ARM: Add binary arithmetic instructions.

This commit is contained in:
Mike Pall 2011-03-30 21:56:05 +02:00
parent a0e4711055
commit 5b06b298a2

View File

@ -92,6 +92,7 @@
|.macro decode_RB8, dst, ins; and dst, MASKR8, ins, lsr #21; .endmacro
|.macro decode_RC8, dst, ins; and dst, MASKR8, ins, lsr #13; .endmacro
|.macro decode_RD, dst, ins; lsr dst, ins, #16; .endmacro
|.macro decode_OP, dst, ins; and dst, ins, #255; .endmacro
|
|// Instruction fetch.
|.macro ins_NEXT1
@ -189,6 +190,10 @@
|
|//-----------------------------------------------------------------------
#if !LJ_DUALNUM
#error "Only dual-number mode supported for ARM target"
#endif
/* Generate subroutines used by opcodes and other parts of the VM. */
/* The .code_sub section should be last to help static branch prediction. */
static void build_subroutines(BuildCtx *ctx)
@ -417,7 +422,7 @@ static void build_subroutines(BuildCtx *ctx)
| NYI
|
|->cont_nop:
| NYI
| ins_next
|
|->cont_ra: // RA = resultptr
| NYI
@ -434,18 +439,44 @@ static void build_subroutines(BuildCtx *ctx)
|//-- Arithmetic metamethods ---------------------------------------------
|
|->vmeta_arith_vn:
| NYI
| decode_RB8 RB, INS
| decode_RC8 RC, INS
| add CARG3, BASE, RB
| add CARG4, KBASE, RC
| b >1
|
|->vmeta_arith_nv:
| NYI
| decode_RB8 RB, INS
| decode_RC8 RC, INS
| add CARG4, BASE, RB
| add CARG3, KBASE, RC
| b >1
|
|->vmeta_unm:
| NYI
| add CARG3, BASE, RC
| add CARG4, BASE, RC
| b >1
|
|->vmeta_arith_vv:
| NYI
| decode_RB8 RB, INS
| decode_RC8 RC, INS
| add CARG3, BASE, RB
| add CARG4, BASE, RC
|1:
| decode_OP OP, INS
| add CARG2, BASE, RA
| str BASE, L->base
| mov CARG1, L
| str PC, SAVE_PC
| str OP, ARG5
| bl extern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
| // Returns NULL (finished) or TValue * (metamethod).
| cmp CRET1, #0
| beq ->cont_nop
|
| // Call metamethod for binary op.
|->vmeta_binop:
| // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2
| NYI
|
|->vmeta_len:
@ -789,6 +820,9 @@ static void build_subroutines(BuildCtx *ctx)
#else
|->vm_trunc:
#endif
|
|->vm_mod:
| NYI
|
|->vm_powi:
#if LJ_HASJIT
@ -804,7 +838,21 @@ static void build_subroutines(BuildCtx *ctx)
|// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -)
|// and basic math functions. ORDER ARITH
|->vm_foldarith:
| NYI
| ldr OP, [sp]
| cmp OP, #1
| blo extern __aeabi_dadd
| beq extern __aeabi_dsub
| cmp OP, #3
| blo extern __aeabi_dmul
| beq extern __aeabi_ddiv
| cmp OP, #5
| blo ->vm_mod
| beq extern pow
| cmp OP, #7
| eorlo CARG2, CARG2, #0x80000000
| biceq CARG2, CARG2, #0x80000000
| bxls lr
| NYI // Other operations only needed by JIT compiler.
|
|//-----------------------------------------------------------------------
|//-- Miscellaneous functions --------------------------------------------
@ -925,33 +973,125 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| ins_next3
|2:
| checktab CARG2, ->vmeta_len
| blx extern lj_tab_len // (GCtab *t)
| bl extern lj_tab_len // (GCtab *t)
| // Returns uint32_t (but less than 2^31).
| b <1
break;
/* -- Binary ops -------------------------------------------------------- */
|.macro ins_arithcheck, cond, ncond, target
||if (vk == 1) {
| cmn CARG4, #-LJ_TISNUM
| cmn..cond CARG2, #-LJ_TISNUM
||} else {
| cmn CARG2, #-LJ_TISNUM
| cmn..cond CARG4, #-LJ_TISNUM
||}
| b..ncond target
|.endmacro
|.macro ins_arithcheck_int, target
| ins_arithcheck eq, ne, target
|.endmacro
|.macro ins_arithcheck_num, target
| ins_arithcheck lo, hs, target
|.endmacro
|
|.macro ins_arithpre
| decode_RB8 RB, INS
| decode_RC8 RC, INS
| // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8
||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
||switch (vk) {
||case 0:
| ldrd CARG12, [BASE, RB]
| ldrd CARG34, [KBASE, RC]
|| break;
||case 1:
| ldrd CARG34, [BASE, RB]
| ldrd CARG12, [KBASE, RC]
|| break;
||default:
| ldrd CARG12, [BASE, RB]
| ldrd CARG34, [BASE, RC]
|| break;
||}
|.endmacro
|
|.macro ins_arithfallback, ins
||switch (vk) {
||case 0:
| ins ->vmeta_arith_vn
|| break;
||case 1:
| ins ->vmeta_arith_nv
|| break;
||default:
| ins ->vmeta_arith_vv
|| break;
||}
|.endmacro
|
|.macro ins_arithdn, intins, fpcall
| ins_arithpre
| ins_next1
| ins_arithcheck_int >5
|.if "intins" == "smull"
| smull CARG1, RC, CARG3, CARG1
| cmp RC, CARG1, asr #31
| ins_arithfallback bne
|.else
| intins CARG1, CARG1, CARG3
| ins_arithfallback bvs
|.endif
|4:
| ins_next2
| strd CARG12, [BASE, RA]
| ins_next3
|5: // FP variant.
| ins_arithfallback ins_arithcheck_num
| bl fpcall
| ins_next1
| b <4
|.endmacro
|
|.macro ins_arithfp, fpcall
| ins_arithpre
||if (op == BC_MODVN) {
| ->BC_MODVN_Z:
||}
| ins_arithfallback ins_arithcheck_num
| bl fpcall
| ins_next1
| ins_next2
| strd CARG12, [BASE, RA]
| ins_next3
|.endmacro
case BC_ADDVN: case BC_ADDNV: case BC_ADDVV:
| NYI
| ins_arithdn adds, extern __aeabi_dadd
break;
case BC_SUBVN: case BC_SUBNV: case BC_SUBVV:
| NYI
| ins_arithdn subs, extern __aeabi_dsub
break;
case BC_MULVN: case BC_MULNV: case BC_MULVV:
| NYI
| ins_arithdn smull, extern __aeabi_dmul
break;
case BC_DIVVN: case BC_DIVNV: case BC_DIVVV:
| NYI
| ins_arithfp extern __aeabi_ddiv
break;
case BC_MODVN:
| NYI
| // NYI: integer arithmetic.
| // Note: __aeabi_idivmod is unsuitable. It uses trunc, not floor.
| ins_arithfp ->vm_mod
break;
case BC_MODNV: case BC_MODVV:
| NYI
| ins_arithpre
| b ->BC_MODVN_Z
break;
case BC_POW:
| NYI
| // NYI: (partial) integer arithmetic.
| ins_arithfp extern pow
break;
case BC_CAT: