Inline-Lua
view release on metacpan or search on metacpan
ffi/target/release/build/mlua-sys-6a99a2ae50f12319/out/luajit-build/build/src/vm_arm.dasc view on Meta::CPAN
/* Generate the code for a single instruction. */
static void build_ins(BuildCtx *ctx, BCOp op, int defop)
{
int vk = 0;
|=>defop:
switch (op) {
/* -- Comparison ops ---------------------------------------------------- */
/* Remember: all ops branch for a true comparison, fall through otherwise. */
case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT:
| // RA = src1*8, RC = src2, JMP with RC = target
| lsl RC, RC, #3
| ldrd CARG12, [RA, BASE]!
| ldrh RB, [PC, #2]
| ldrd CARG34, [RC, BASE]!
| add PC, PC, #4
| add RB, PC, RB, lsl #2
| checktp CARG2, LJ_TISNUM
| bne >3
| checktp CARG4, LJ_TISNUM
| bne >4
| cmp CARG1, CARG3
if (op == BC_ISLT) {
| sublt PC, RB, #0x20000
} else if (op == BC_ISGE) {
| subge PC, RB, #0x20000
} else if (op == BC_ISLE) {
| suble PC, RB, #0x20000
} else {
| subgt PC, RB, #0x20000
}
|1:
| ins_next
|
|3: // CARG12 is not an integer.
|.if FPU
| vldr d0, [RA]
| bhi ->vmeta_comp
| // d0 is a number.
| checktp CARG4, LJ_TISNUM
| vldr d1, [RC]
| blo >5
| bhi ->vmeta_comp
| // d0 is a number, CARG3 is an integer.
| vmov s4, CARG3
| vcvt.f64.s32 d1, s4
| b >5
|4: // CARG1 is an integer, CARG34 is not an integer.
| vldr d1, [RC]
| bhi ->vmeta_comp
| // CARG1 is an integer, d1 is a number.
| vmov s4, CARG1
| vcvt.f64.s32 d0, s4
|5: // d0 and d1 are numbers.
| vcmp.f64 d0, d1
| vmrs
| // To preserve NaN semantics GE/GT branch on unordered, but LT/LE don't.
if (op == BC_ISLT) {
| sublo PC, RB, #0x20000
} else if (op == BC_ISGE) {
| subhs PC, RB, #0x20000
} else if (op == BC_ISLE) {
| subls PC, RB, #0x20000
} else {
| subhi PC, RB, #0x20000
}
| b <1
|.else
| bhi ->vmeta_comp
| // CARG12 is a number.
| checktp CARG4, LJ_TISNUM
| movlo RA, RB // Save RB.
| blo >5
| bhi ->vmeta_comp
| // CARG12 is a number, CARG3 is an integer.
| mov CARG1, CARG3
| mov RC, RA
| mov RA, RB // Save RB.
| bl extern __aeabi_i2d
| mov CARG3, CARG1
| mov CARG4, CARG2
| ldrd CARG12, [RC] // Restore first operand.
| b >5
|4: // CARG1 is an integer, CARG34 is not an integer.
| bhi ->vmeta_comp
| // CARG1 is an integer, CARG34 is a number.
| mov RA, RB // Save RB.
| bl extern __aeabi_i2d
| ldrd CARG34, [RC] // Restore second operand.
|5: // CARG12 and CARG34 are numbers.
| bl extern __aeabi_cdcmple
| // To preserve NaN semantics GE/GT branch on unordered, but LT/LE don't.
if (op == BC_ISLT) {
| sublo PC, RA, #0x20000
} else if (op == BC_ISGE) {
| subhs PC, RA, #0x20000
} else if (op == BC_ISLE) {
| subls PC, RA, #0x20000
} else {
| subhi PC, RA, #0x20000
}
| b <1
|.endif
break;
case BC_ISEQV: case BC_ISNEV:
vk = op == BC_ISEQV;
| // RA = src1*8, RC = src2, JMP with RC = target
| lsl RC, RC, #3
| ldrd CARG12, [RA, BASE]!
| ldrh RB, [PC, #2]
| ldrd CARG34, [RC, BASE]!
| add PC, PC, #4
| add RB, PC, RB, lsl #2
| checktp CARG2, LJ_TISNUM
| cmnls CARG4, #-LJ_TISNUM
if (vk) {
| bls ->BC_ISEQN_Z
} else {
| bls ->BC_ISNEN_Z
}
| // Either or both types are not numbers.
|.if FFI
| checktp CARG2, LJ_TCDATA
| checktpne CARG4, LJ_TCDATA
| beq ->vmeta_equal_cd
|.endif
| cmp CARG2, CARG4 // Compare types.
| bne >2 // Not the same type?
| checktp CARG2, LJ_TISPRI
| bhs >1 // Same type and primitive type?
|
| // Same types and not a primitive type. Compare GCobj or pvalue.
| cmp CARG1, CARG3
if (vk) {
| bne >3 // Different GCobjs or pvalues?
|1: // Branch if same.
| sub PC, RB, #0x20000
|2: // Different.
| ins_next
|3:
| checktp CARG2, LJ_TISTABUD
| bhi <2 // Different objects and not table/ud?
} else {
| beq >1 // Same GCobjs or pvalues?
| checktp CARG2, LJ_TISTABUD
| bhi >2 // Different objects and not table/ud?
}
| // Different tables or userdatas. Need to check __eq metamethod.
| // Field metatable must be at same offset for GCtab and GCudata!
| ldr TAB:RA, TAB:CARG1->metatable
| cmp TAB:RA, #0
( run in 1.485 second using v1.01-cache-2.11-cpan-39bf76dae61 )