diff options
Diffstat (limited to 'src/lj_emit_arm.h')
-rw-r--r-- | src/lj_emit_arm.h | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/src/lj_emit_arm.h b/src/lj_emit_arm.h index 27de6852..79ca2db7 100644 --- a/src/lj_emit_arm.h +++ b/src/lj_emit_arm.h | |||
@@ -103,6 +103,15 @@ static void emit_lso(ASMState *as, ARMIns ai, Reg rd, Reg rn, int32_t ofs) | |||
103 | *--as->mcp = ai | ARMI_LS_P | ARMF_D(rd) | ARMF_N(rn) | ofs; | 103 | *--as->mcp = ai | ARMI_LS_P | ARMF_D(rd) | ARMF_N(rn) | ofs; |
104 | } | 104 | } |
105 | 105 | ||
106 | #if !LJ_SOFTFP | ||
107 | static void emit_vlso(ASMState *as, ARMIns ai, Reg rd, Reg rn, int32_t ofs) | ||
108 | { | ||
109 | lua_assert(ofs >= -1020 && ofs <= 1020 && (ofs&3) == 0); | ||
110 | if (ofs < 0) ofs = -ofs; else ai |= ARMI_LS_U; | ||
111 | *--as->mcp = ai | ARMI_LS_P | ARMF_D(rd & 15) | ARMF_N(rn) | (ofs >> 2); | ||
112 | } | ||
113 | #endif | ||
114 | |||
106 | /* -- Emit loads/stores --------------------------------------------------- */ | 115 | /* -- Emit loads/stores --------------------------------------------------- */ |
107 | 116 | ||
108 | /* Prefer spills of BASE/L. */ | 117 | /* Prefer spills of BASE/L. */ |
@@ -208,6 +217,28 @@ static void emit_lsptr(ASMState *as, ARMIns ai, Reg r, void *p) | |||
208 | (i & 4095)); | 217 | (i & 4095)); |
209 | } | 218 | } |
210 | 219 | ||
220 | #if !LJ_SOFTFP | ||
221 | /* Load a number constant into an FPR. */ | ||
222 | static void emit_loadn(ASMState *as, Reg r, cTValue *tv) | ||
223 | { | ||
224 | int32_t i; | ||
225 | if ((as->flags & JIT_F_VFPV3) && !tv->u32.lo) { | ||
226 | uint32_t hi = tv->u32.hi; | ||
227 | uint32_t b = ((hi >> 22) & 0x1ff); | ||
228 | if (!(hi & 0xffff) && (b == 0x100 || b == 0x0ff)) { | ||
229 | *--as->mcp = ARMI_VMOVI_D | ARMF_D(r & 15) | | ||
230 | ((tv->u32.hi >> 12) & 0x00080000) | | ||
231 | ((tv->u32.hi >> 4) & 0x00070000) | | ||
232 | ((tv->u32.hi >> 16) & 0x0000000f); | ||
233 | return; | ||
234 | } | ||
235 | } | ||
236 | i = i32ptr(tv); | ||
237 | emit_vlso(as, ARMI_VLDR_D, r, | ||
238 | ra_allock(as, (i & ~1020), RSET_GPR), (i & 1020)); | ||
239 | } | ||
240 | #endif | ||
241 | |||
211 | /* Get/set global_State fields. */ | 242 | /* Get/set global_State fields. */ |
212 | #define emit_getgl(as, r, field) \ | 243 | #define emit_getgl(as, r, field) \ |
213 | emit_lsptr(as, ARMI_LDR, (r), (void *)&J2G(as->J)->field) | 244 | emit_lsptr(as, ARMI_LDR, (r), (void *)&J2G(as->J)->field) |
@@ -256,7 +287,15 @@ static void emit_call(ASMState *as, void *target) | |||
256 | /* Generic move between two regs. */ | 287 | /* Generic move between two regs. */ |
257 | static void emit_movrr(ASMState *as, IRIns *ir, Reg dst, Reg src) | 288 | static void emit_movrr(ASMState *as, IRIns *ir, Reg dst, Reg src) |
258 | { | 289 | { |
290 | #if LJ_SOFTFP | ||
259 | lua_assert(!irt_isnum(ir->t)); UNUSED(ir); | 291 | lua_assert(!irt_isnum(ir->t)); UNUSED(ir); |
292 | #else | ||
293 | if (dst >= RID_MAX_GPR) { | ||
294 | emit_dm(as, irt_isnum(ir->t) ? ARMI_VMOV_D : ARMI_VMOV_S, | ||
295 | (dst & 15), (src & 15)); | ||
296 | return; | ||
297 | } | ||
298 | #endif | ||
260 | if (as->mcp != as->mcloop) { /* Swap early registers for loads/stores. */ | 299 | if (as->mcp != as->mcloop) { /* Swap early registers for loads/stores. */ |
261 | MCode ins = *as->mcp, swp = (src^dst); | 300 | MCode ins = *as->mcp, swp = (src^dst); |
262 | if ((ins & 0x0c000000) == 0x04000000 && (ins & 0x02000010) != 0x02000010) { | 301 | if ((ins & 0x0c000000) == 0x04000000 && (ins & 0x02000010) != 0x02000010) { |
@@ -272,15 +311,27 @@ static void emit_movrr(ASMState *as, IRIns *ir, Reg dst, Reg src) | |||
272 | /* Generic load of register from stack slot. */ | 311 | /* Generic load of register from stack slot. */ |
273 | static void emit_spload(ASMState *as, IRIns *ir, Reg r, int32_t ofs) | 312 | static void emit_spload(ASMState *as, IRIns *ir, Reg r, int32_t ofs) |
274 | { | 313 | { |
314 | #if LJ_SOFTFP | ||
275 | lua_assert(!irt_isnum(ir->t)); UNUSED(ir); | 315 | lua_assert(!irt_isnum(ir->t)); UNUSED(ir); |
276 | emit_lso(as, ARMI_LDR, r, RID_SP, ofs); | 316 | #else |
317 | if (r >= RID_MAX_GPR) | ||
318 | emit_vlso(as, irt_isnum(ir->t) ? ARMI_VLDR_D : ARMI_VLDR_S, r, RID_SP, ofs); | ||
319 | else | ||
320 | #endif | ||
321 | emit_lso(as, ARMI_LDR, r, RID_SP, ofs); | ||
277 | } | 322 | } |
278 | 323 | ||
279 | /* Generic store of register to stack slot. */ | 324 | /* Generic store of register to stack slot. */ |
280 | static void emit_spstore(ASMState *as, IRIns *ir, Reg r, int32_t ofs) | 325 | static void emit_spstore(ASMState *as, IRIns *ir, Reg r, int32_t ofs) |
281 | { | 326 | { |
327 | #if LJ_SOFTFP | ||
282 | lua_assert(!irt_isnum(ir->t)); UNUSED(ir); | 328 | lua_assert(!irt_isnum(ir->t)); UNUSED(ir); |
283 | emit_lso(as, ARMI_STR, r, RID_SP, ofs); | 329 | #else |
330 | if (r >= RID_MAX_GPR) | ||
331 | emit_vlso(as, irt_isnum(ir->t) ? ARMI_VSTR_D : ARMI_VSTR_S, r, RID_SP, ofs); | ||
332 | else | ||
333 | #endif | ||
334 | emit_lso(as, ARMI_STR, r, RID_SP, ofs); | ||
284 | } | 335 | } |
285 | 336 | ||
286 | /* Emit an arithmetic/logic operation with a constant operand. */ | 337 | /* Emit an arithmetic/logic operation with a constant operand. */ |