b[pos++] = n;
switch (action) {
case DASM_DISP:
- if (n == 0) { if ((mrm&7) == 4) mrm = p[-2]; if ((mrm&7) != 5) break; }
+ if (n == 0) { if (mrm < 0) mrm = p[-2]; if ((mrm&7) != 5) break; }
- case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob;
+ /* fallthrough */
+ case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob; /* fallthrough */
case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */
case DASM_IMM_D: ofs += 4; break;
case DASM_IMM_S: CK(((n+128)&-256) == 0, RANGE_I); goto ob;
case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break;
case DASM_SPACE: p++; ofs += n; break;
case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */
- case DASM_VREG: CK((n&-8) == 0 && (n != 4 || (*p&1) == 0), RANGE_VREG);
- if (*p++ == 1 && *p == DASM_DISP) mrm = n;
+ case DASM_VREG: CK((n&-16) == 0 && (n != 4 || (*p>>5) != 2), RANGE_VREG);
+ if (*p < 0x40 && p[1] == DASM_DISP) mrm = n;
+ if (*p < 0x20 && (n&7) == 4) ofs++;
+ switch ((*p++ >> 3) & 3) {
- case 3: n |= b[pos-3];
- case 2: n |= b[pos-2];
++ case 3: n |= b[pos-3]; /* fallthrough */
++ case 2: n |= b[pos-2]; /* fallthrough */
+ case 1: if (n <= 7) { b[pos-1] |= 0x10; ofs--; }
+ }
continue;
}
- mrm = 4;
+ mrm = -1;
} else {
int *pl, n;
switch (action) {
case DASM_IMM_DB: if (((n+128)&-256) == 0) {
db: if (!mark) mark = cp; mark[-2] += 2; mark = NULL; goto wb;
} else mark = NULL;
+ /* fallthrough */
case DASM_IMM_D: wd: dasmd(n); break;
case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL;
+ /* fallthrough */
case DASM_IMM_W: dasmw(n); break;
- case DASM_VREG: { int t = *p++; if (t >= 2) n<<=3; cp[-1] |= n; break; }
+ case DASM_VREG: {
+ int t = *p++;
+ unsigned char *ex = cp - (t&7);
+ if ((n & 8) && t < 0xa0) {
+ if (*ex & 0x80) ex[1] ^= 0x20 << (t>>6); else *ex ^= 1 << (t>>6);
+ n &= 7;
+ } else if (n & 0x10) {
+ if (*ex & 0x80) {
+ *ex = 0xc5; ex[1] = (ex[1] & 0x80) | ex[2]; ex += 2;
+ }
+ while (++ex < cp) ex[-1] = *ex;
+ if (mark) mark--;
+ cp--;
+ n &= 7;
+ }
+ if (t >= 0xc0) n <<= 4;
+ else if (t >= 0x40) n <<= 3;
+ else if (n == 4 && t < 0x20) { cp[-1] ^= n; *cp++ = 0x20; }
+ cp[-1] ^= n;
+ break;
+ }
case DASM_REL_LG: p++; if (n >= 0) goto rel_pc;
b++; n = (int)(ptrdiff_t)D->globals[-n];
+ /* fallthrough */
case DASM_REL_A: rel_a:
n -= (unsigned int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */
case DASM_REL_PC: rel_pc: {
/* fallthrough */
#endif
/* C calls evict all scratch regs and return results in RID_RET. */
- case IR_SNEW: case IR_XSNEW: case IR_NEWREF:
+ case IR_SNEW: case IR_XSNEW: case IR_NEWREF: case IR_BUFPUT:
if (REGARG_NUMGPR < 3 && as->evenspill < 3)
as->evenspill = 3; /* lj_str_new and lj_tab_newkey need 3 args. */
- case IR_TNEW: case IR_TDUP: case IR_CNEW: case IR_CNEWI: case IR_TOSTR:
+#if LJ_TARGET_X86 && LJ_HASFFI
+ if (0) {
+ case IR_CNEW:
+ if (ir->op2 != REF_NIL && as->evenspill < 4)
+ as->evenspill = 4; /* lj_cdata_newv needs 4 args. */
+ }
++ /* fallthrough */
+#else
++ /* fallthrough */
+ case IR_CNEW:
+#endif
+ /* fallthrough */
+ case IR_TNEW: case IR_TDUP: case IR_CNEWI: case IR_TOSTR:
+ case IR_BUFSTR:
ir->prev = REGSP_HINT(RID_RET);
if (inloop)
as->modset = RSET_SCRATCH;
if (inloop)
as->modset = RSET_SCRATCH;
break;
-#if !LJ_TARGET_X86ORX64 && !LJ_SOFTFP
- case IR_ATAN2: case IR_LDEXP:
+#if !LJ_SOFTFP
+ case IR_ATAN2:
+#if LJ_TARGET_X86
+ if (as->evenspill < 4) /* Leave room to call atan2(). */
+ as->evenspill = 4;
+#endif
+#if !LJ_TARGET_X86ORX64
+ case IR_LDEXP:
+#endif
#endif
++ /* fallthrough */
case IR_POW:
if (!LJ_SOFTFP && irt_isnum(ir->t)) {
-#if LJ_TARGET_X86ORX64
- ir->prev = REGSP_HINT(RID_XMM0);
if (inloop)
- as->modset |= RSET_RANGE(RID_XMM0, RID_XMM1+1)|RID2RSET(RID_EAX);
+ as->modset |= RSET_SCRATCH;
+#if LJ_TARGET_X86
+ break;
#else
ir->prev = REGSP_HINT(RID_FPRET);
- if (inloop)
- as->modset |= RSET_SCRATCH;
-#endif
continue;
+#endif
}
- /* fallthrough for integer POW */
+ /* fallthrough */ /* for integer POW */
case IR_DIV: case IR_MOD:
if (!irt_isnum(ir->t)) {
ir->prev = REGSP_HINT(RID_RET);
#endif
#if LJ_TARGET_X86ORX64
/* Non-constant shift counts need to be in RID_ECX on x86/x64. */
- case IR_BSHL: case IR_BSHR: case IR_BSAR: case IR_BROL: case IR_BROR:
+ case IR_BSHL: case IR_BSHR: case IR_BSAR:
+ if ((as->flags & JIT_F_BMI2)) /* Except if BMI2 is available. */
+ break;
++ /* fallthrough */
+ case IR_BROL: case IR_BROR:
if (!irref_isk(ir->op2) && !ra_hashint(IR(ir->op2)->r)) {
IR(ir->op2)->r = REGSP_HINT(RID_ECX);
if (inloop)