aboutsummaryrefslogtreecommitdiff
path: root/src/lj_asm.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lj_asm.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c
index 5d48b6be..ce42c437 100644
--- a/src/lj_asm.c
+++ b/src/lj_asm.c
@@ -2482,6 +2482,31 @@ static void asm_intarith(ASMState *as, IRIns *ir, x86Arith xa)
2482 ra_left(as, dest, lref); 2482 ra_left(as, dest, lref);
2483} 2483}
2484 2484
2485static void asm_intmul(ASMState *as, IRIns *ir)
2486{
2487 IRRef lref = ir->op1;
2488 IRRef rref = ir->op2;
2489 int32_t k = 0;
2490 if (asm_isk32(as, rref, &k)) {
2491 /* NYI: use lea/shl/add/sub (FOLD only does 2^k) depending on CPU. */
2492 Reg dest = ra_dest(as, ir, RSET_GPR);
2493 Reg left = asm_fuseload(as, lref, RSET_GPR);
2494 x86Op xo;
2495 if (checki8(k)) {
2496 emit_i8(as, k);
2497 xo = XO_IMULi8;
2498 } else {
2499 emit_i32(as, k);
2500 xo = XO_IMULi;
2501 }
2502 emit_rr(as, xo, REX_64IR(ir, dest), left);
2503 } else {
2504 /* NYI: integer multiply of non-constant operands. */
2505 setintV(&as->J->errinfo, ir->o);
2506 lj_trace_err_info(as->J, LJ_TRERR_NYIIR);
2507 }
2508}
2509
2485/* LEA is really a 4-operand ADD with an independent destination register, 2510/* LEA is really a 4-operand ADD with an independent destination register,
2486** up to two source registers and an immediate. One register can be scaled 2511** up to two source registers and an immediate. One register can be scaled
2487** by 1, 2, 4 or 8. This can be used to avoid moves or to fuse several 2512** by 1, 2, 4 or 8. This can be used to avoid moves or to fuse several
@@ -3445,7 +3470,12 @@ static void asm_ir(ASMState *as, IRIns *ir)
3445 else /* Note: no need for LEA trick here. i-k is encoded as i+(-k). */ 3470 else /* Note: no need for LEA trick here. i-k is encoded as i+(-k). */
3446 asm_intarith(as, ir, XOg_SUB); 3471 asm_intarith(as, ir, XOg_SUB);
3447 break; 3472 break;
3448 case IR_MUL: asm_fparith(as, ir, XO_MULSD); break; 3473 case IR_MUL:
3474 if (irt_isnum(ir->t))
3475 asm_fparith(as, ir, XO_MULSD);
3476 else
3477 asm_intmul(as, ir);
3478 break;
3449 case IR_DIV: asm_fparith(as, ir, XO_DIVSD); break; 3479 case IR_DIV: asm_fparith(as, ir, XO_DIVSD); break;
3450 3480
3451 case IR_NEG: asm_fparith(as, ir, XO_XORPS); break; 3481 case IR_NEG: asm_fparith(as, ir, XO_XORPS); break;