diff options
Diffstat (limited to '')
-rw-r--r-- | src/lj_asm.c | 32 |
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 | ||
2485 | static 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; |