|
@@ -92,6 +92,7 @@
|
|
|.macro decode_RB8, dst, ins; and dst, MASKR8, ins, lsr #21; .endmacro
|
|
|.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_RC8, dst, ins; and dst, MASKR8, ins, lsr #13; .endmacro
|
|
|.macro decode_RD, dst, ins; lsr dst, ins, #16; .endmacro
|
|
|.macro decode_RD, dst, ins; lsr dst, ins, #16; .endmacro
|
|
|
|
+|.macro decode_OP, dst, ins; and dst, ins, #255; .endmacro
|
|
|
|
|
|
|
|
|// Instruction fetch.
|
|
|// Instruction fetch.
|
|
|.macro ins_NEXT1
|
|
|.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. */
|
|
/* Generate subroutines used by opcodes and other parts of the VM. */
|
|
/* The .code_sub section should be last to help static branch prediction. */
|
|
/* The .code_sub section should be last to help static branch prediction. */
|
|
static void build_subroutines(BuildCtx *ctx)
|
|
static void build_subroutines(BuildCtx *ctx)
|
|
@@ -417,7 +422,7 @@ static void build_subroutines(BuildCtx *ctx)
|
|
| NYI
|
|
| NYI
|
|
|
|
|
|
|
|
|->cont_nop:
|
|
|->cont_nop:
|
|
- | NYI
|
|
|
|
|
|
+ | ins_next
|
|
|
|
|
|
|
|
|->cont_ra: // RA = resultptr
|
|
|->cont_ra: // RA = resultptr
|
|
| NYI
|
|
| NYI
|
|
@@ -434,18 +439,44 @@ static void build_subroutines(BuildCtx *ctx)
|
|
|//-- Arithmetic metamethods ---------------------------------------------
|
|
|//-- Arithmetic metamethods ---------------------------------------------
|
|
|
|
|
|
|
|
|->vmeta_arith_vn:
|
|
|->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:
|
|
|->vmeta_arith_nv:
|
|
- | NYI
|
|
|
|
|
|
+ | decode_RB8 RB, INS
|
|
|
|
+ | decode_RC8 RC, INS
|
|
|
|
+ | add CARG4, BASE, RB
|
|
|
|
+ | add CARG3, KBASE, RC
|
|
|
|
+ | b >1
|
|
|
|
|
|
|
|
|->vmeta_unm:
|
|
|->vmeta_unm:
|
|
- | NYI
|
|
|
|
|
|
+ | add CARG3, BASE, RC
|
|
|
|
+ | add CARG4, BASE, RC
|
|
|
|
+ | b >1
|
|
|
|
|
|
|
|
|->vmeta_arith_vv:
|
|
|->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:
|
|
|->vmeta_binop:
|
|
|
|
+ | // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2
|
|
| NYI
|
|
| NYI
|
|
|
|
|
|
|
|
|->vmeta_len:
|
|
|->vmeta_len:
|
|
@@ -789,6 +820,9 @@ static void build_subroutines(BuildCtx *ctx)
|
|
#else
|
|
#else
|
|
|->vm_trunc:
|
|
|->vm_trunc:
|
|
#endif
|
|
#endif
|
|
|
|
+ |
|
|
|
|
+ |->vm_mod:
|
|
|
|
+ | NYI
|
|
|
|
|
|
|
|
|->vm_powi:
|
|
|->vm_powi:
|
|
#if LJ_HASJIT
|
|
#if LJ_HASJIT
|
|
@@ -804,7 +838,21 @@ static void build_subroutines(BuildCtx *ctx)
|
|
|// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -)
|
|
|// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -)
|
|
|// and basic math functions. ORDER ARITH
|
|
|// and basic math functions. ORDER ARITH
|
|
|->vm_foldarith:
|
|
|->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 --------------------------------------------
|
|
|//-- Miscellaneous functions --------------------------------------------
|
|
@@ -925,33 +973,125 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
|
|
| ins_next3
|
|
| ins_next3
|
|
|2:
|
|
|2:
|
|
| checktab CARG2, ->vmeta_len
|
|
| 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).
|
|
| // Returns uint32_t (but less than 2^31).
|
|
| b <1
|
|
| b <1
|
|
break;
|
|
break;
|
|
|
|
|
|
/* -- Binary ops -------------------------------------------------------- */
|
|
/* -- 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:
|
|
case BC_ADDVN: case BC_ADDNV: case BC_ADDVV:
|
|
- | NYI
|
|
|
|
|
|
+ | ins_arithdn adds, extern __aeabi_dadd
|
|
break;
|
|
break;
|
|
case BC_SUBVN: case BC_SUBNV: case BC_SUBVV:
|
|
case BC_SUBVN: case BC_SUBNV: case BC_SUBVV:
|
|
- | NYI
|
|
|
|
|
|
+ | ins_arithdn subs, extern __aeabi_dsub
|
|
break;
|
|
break;
|
|
case BC_MULVN: case BC_MULNV: case BC_MULVV:
|
|
case BC_MULVN: case BC_MULNV: case BC_MULVV:
|
|
- | NYI
|
|
|
|
|
|
+ | ins_arithdn smull, extern __aeabi_dmul
|
|
break;
|
|
break;
|
|
case BC_DIVVN: case BC_DIVNV: case BC_DIVVV:
|
|
case BC_DIVVN: case BC_DIVNV: case BC_DIVVV:
|
|
- | NYI
|
|
|
|
|
|
+ | ins_arithfp extern __aeabi_ddiv
|
|
break;
|
|
break;
|
|
case BC_MODVN:
|
|
case BC_MODVN:
|
|
- | NYI
|
|
|
|
|
|
+ | // NYI: integer arithmetic.
|
|
|
|
+ | // Note: __aeabi_idivmod is unsuitable. It uses trunc, not floor.
|
|
|
|
+ | ins_arithfp ->vm_mod
|
|
break;
|
|
break;
|
|
case BC_MODNV: case BC_MODVV:
|
|
case BC_MODNV: case BC_MODVV:
|
|
- | NYI
|
|
|
|
|
|
+ | ins_arithpre
|
|
|
|
+ | b ->BC_MODVN_Z
|
|
break;
|
|
break;
|
|
case BC_POW:
|
|
case BC_POW:
|
|
- | NYI
|
|
|
|
|
|
+ | // NYI: (partial) integer arithmetic.
|
|
|
|
+ | ins_arithfp extern pow
|
|
break;
|
|
break;
|
|
|
|
|
|
case BC_CAT:
|
|
case BC_CAT:
|