aboutsummaryrefslogtreecommitdiff
path: root/src/lj_ccallback.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lj_ccallback.c70
1 files changed, 60 insertions, 10 deletions
diff --git a/src/lj_ccallback.c b/src/lj_ccallback.c
index 43c29e41..2ca6406c 100644
--- a/src/lj_ccallback.c
+++ b/src/lj_ccallback.c
@@ -63,9 +63,13 @@ static MSize CALLBACK_OFS2SLOT(MSize ofs)
63 63
64#define CALLBACK_MCODE_HEAD 24 64#define CALLBACK_MCODE_HEAD 24
65 65
66#elif LJ_TARGET_MIPS 66#elif LJ_TARGET_MIPS32
67 67
68#define CALLBACK_MCODE_HEAD 24 68#define CALLBACK_MCODE_HEAD 20
69
70#elif LJ_TARGET_MIPS64
71
72#define CALLBACK_MCODE_HEAD 52
69 73
70#else 74#else
71 75
@@ -206,14 +210,27 @@ static void callback_mcode_init(global_State *g, uint32_t *page)
206static void callback_mcode_init(global_State *g, uint32_t *page) 210static void callback_mcode_init(global_State *g, uint32_t *page)
207{ 211{
208 uint32_t *p = page; 212 uint32_t *p = page;
209 void *target = (void *)lj_vm_ffi_callback; 213 uintptr_t target = (uintptr_t)(void *)lj_vm_ffi_callback;
214 uintptr_t ug = (uintptr_t)(void *)g;
210 MSize slot; 215 MSize slot;
211 *p++ = MIPSI_SW | MIPSF_T(RID_R1)|MIPSF_S(RID_SP) | 0; 216#if LJ_TARGET_MIPS32
212 *p++ = MIPSI_LUI | MIPSF_T(RID_R3) | (u32ptr(target) >> 16); 217 *p++ = MIPSI_LUI | MIPSF_T(RID_R3) | (target >> 16);
213 *p++ = MIPSI_LUI | MIPSF_T(RID_R2) | (u32ptr(g) >> 16); 218 *p++ = MIPSI_LUI | MIPSF_T(RID_R2) | (ug >> 16);
214 *p++ = MIPSI_ORI | MIPSF_T(RID_R3)|MIPSF_S(RID_R3) |(u32ptr(target)&0xffff); 219#else
220 *p++ = MIPSI_LUI | MIPSF_T(RID_R3) | (target >> 48);
221 *p++ = MIPSI_LUI | MIPSF_T(RID_R2) | (ug >> 48);
222 *p++ = MIPSI_ORI | MIPSF_T(RID_R3)|MIPSF_S(RID_R3) | ((target >> 32) & 0xffff);
223 *p++ = MIPSI_ORI | MIPSF_T(RID_R2)|MIPSF_S(RID_R2) | ((ug >> 32) & 0xffff);
224 *p++ = MIPSI_DSLL | MIPSF_D(RID_R3)|MIPSF_T(RID_R3) | MIPSF_A(16);
225 *p++ = MIPSI_DSLL | MIPSF_D(RID_R2)|MIPSF_T(RID_R2) | MIPSF_A(16);
226 *p++ = MIPSI_ORI | MIPSF_T(RID_R3)|MIPSF_S(RID_R3) | ((target >> 16) & 0xffff);
227 *p++ = MIPSI_ORI | MIPSF_T(RID_R2)|MIPSF_S(RID_R2) | ((ug >> 16) & 0xffff);
228 *p++ = MIPSI_DSLL | MIPSF_D(RID_R3)|MIPSF_T(RID_R3) | MIPSF_A(16);
229 *p++ = MIPSI_DSLL | MIPSF_D(RID_R2)|MIPSF_T(RID_R2) | MIPSF_A(16);
230#endif
231 *p++ = MIPSI_ORI | MIPSF_T(RID_R3)|MIPSF_S(RID_R3) | (target & 0xffff);
215 *p++ = MIPSI_JR | MIPSF_S(RID_R3); 232 *p++ = MIPSI_JR | MIPSF_S(RID_R3);
216 *p++ = MIPSI_ORI | MIPSF_T(RID_R2)|MIPSF_S(RID_R2) | (u32ptr(g)&0xffff); 233 *p++ = MIPSI_ORI | MIPSF_T(RID_R2)|MIPSF_S(RID_R2) | (ug & 0xffff);
217 for (slot = 0; slot < CALLBACK_MAX_SLOT; slot++) { 234 for (slot = 0; slot < CALLBACK_MAX_SLOT; slot++) {
218 *p = MIPSI_B | ((page-p-1) & 0x0000ffffu); 235 *p = MIPSI_B | ((page-p-1) & 0x0000ffffu);
219 p++; 236 p++;
@@ -425,7 +442,7 @@ void lj_ccallback_mcode_free(CTState *cts)
425 if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \ 442 if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
426 *(double *)dp = *(float *)dp; /* FPRs always hold doubles. */ 443 *(double *)dp = *(float *)dp; /* FPRs always hold doubles. */
427 444
428#elif LJ_TARGET_MIPS 445#elif LJ_TARGET_MIPS32
429 446
430#define CALLBACK_HANDLE_GPR \ 447#define CALLBACK_HANDLE_GPR \
431 if (n > 1) ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \ 448 if (n > 1) ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \
@@ -455,6 +472,29 @@ void lj_ccallback_mcode_free(CTState *cts)
455 if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \ 472 if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
456 ((float *)dp)[1] = *(float *)dp; 473 ((float *)dp)[1] = *(float *)dp;
457 474
475#elif LJ_TARGET_MIPS64
476
477#if !LJ_ABI_SOFTFP /* MIPS64 hard-float */
478#define CALLBACK_HANDLE_REGARG \
479 if (ngpr + n <= maxgpr) { \
480 sp = isfp ? (void*) &cts->cb.fpr[ngpr] : (void*) &cts->cb.gpr[ngpr]; \
481 ngpr += n; \
482 goto done; \
483 }
484#else /* MIPS64 soft-float */
485#define CALLBACK_HANDLE_REGARG \
486 if (ngpr + n <= maxgpr) { \
487 UNUSED(isfp); \
488 sp = (void*) &cts->cb.gpr[ngpr]; \
489 ngpr += n; \
490 goto done; \
491 }
492#endif
493
494#define CALLBACK_HANDLE_RET \
495 if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
496 ((float *)dp)[1] = *(float *)dp;
497
458#else 498#else
459#error "Missing calling convention definitions for this architecture" 499#error "Missing calling convention definitions for this architecture"
460#endif 500#endif
@@ -542,7 +582,11 @@ static void callback_conv_args(CTState *cts, lua_State *L)
542 nsp += n; 582 nsp += n;
543 583
544 done: 584 done:
545 if (LJ_BE && cta->size < CTSIZE_PTR) 585 if (LJ_BE && cta->size < CTSIZE_PTR
586#if LJ_TARGET_MIPS64
587 && !(isfp && nsp)
588#endif
589 )
546 sp = (void *)((uint8_t *)sp + CTSIZE_PTR-cta->size); 590 sp = (void *)((uint8_t *)sp + CTSIZE_PTR-cta->size);
547 gcsteps += lj_cconv_tv_ct(cts, cta, 0, o++, sp); 591 gcsteps += lj_cconv_tv_ct(cts, cta, 0, o++, sp);
548 } 592 }
@@ -593,6 +637,12 @@ static void callback_conv_result(CTState *cts, lua_State *L, TValue *o)
593 *(int32_t *)dp = ctr->size == 1 ? (int32_t)*(int8_t *)dp : 637 *(int32_t *)dp = ctr->size == 1 ? (int32_t)*(int8_t *)dp :
594 (int32_t)*(int16_t *)dp; 638 (int32_t)*(int16_t *)dp;
595 } 639 }
640#if LJ_TARGET_MIPS64
641 /* Always sign-extend results to 64 bits. Even a soft-fp 'float'. */
642 if (ctr->size <= 4 &&
643 (LJ_ABI_SOFTFP || ctype_isinteger_or_bool(ctr->info)))
644 *(int64_t *)dp = (int64_t)*(int32_t *)dp;
645#endif
596#if LJ_TARGET_X86 646#if LJ_TARGET_X86
597 if (ctype_isfp(ctr->info)) 647 if (ctype_isfp(ctr->info))
598 cts->cb.gpr[2] = ctr->size == sizeof(float) ? 1 : 2; 648 cts->cb.gpr[2] = ctr->size == sizeof(float) ? 1 : 2;