summaryrefslogtreecommitdiff
path: root/src/runtime/c/pgf/lightning/arm/funcs.h
diff options
context:
space:
mode:
authorkr.angelov <kr.angelov@gmail.com>2013-09-11 20:17:50 +0000
committerkr.angelov <kr.angelov@gmail.com>2013-09-11 20:17:50 +0000
commitbfafdbfec33e0dc1d1bda0d0cfe2fd0555c45acc (patch)
treeebfa64730dd9cbd28c6ecbd07fcd748c85fb6fe8 /src/runtime/c/pgf/lightning/arm/funcs.h
parent8a3b97e6a504cb37f07013378e687eb103b0e50d (diff)
rewrite the ARM port of GNU lightning to a form compatible with the versions for the other CPUs
Diffstat (limited to 'src/runtime/c/pgf/lightning/arm/funcs.h')
-rw-r--r--src/runtime/c/pgf/lightning/arm/funcs.h278
1 files changed, 276 insertions, 2 deletions
diff --git a/src/runtime/c/pgf/lightning/arm/funcs.h b/src/runtime/c/pgf/lightning/arm/funcs.h
index ec19e52a3..79d63df40 100644
--- a/src/runtime/c/pgf/lightning/arm/funcs.h
+++ b/src/runtime/c/pgf/lightning/arm/funcs.h
@@ -51,8 +51,7 @@ jit_flush_code(void *start, void *end)
__clear_cache(start, end);
}
-#define jit_get_cpu jit_get_cpu
-__jit_constructor static void
+__attribute__((constructor)) static void
jit_get_cpu(void)
{
#if defined(__linux__)
@@ -106,4 +105,279 @@ jit_get_cpu(void)
jit_cpu.thumb = 0;
}
+static void
+arm_patch_arguments(struct jit_local_state* jitl)
+{
+ int reg;
+ int ioff;
+ int foff;
+ int size;
+ int index;
+ jit_thumb_t thumb;
+ int offset;
+ union {
+ _ui *i;
+ _us *s;
+ } u;
+
+ ioff = foff = 0;
+ for (index = jitl->nextarg_put - 1, offset = 0; index >= 0; index--) {
+ if (jitl->types[index >> 5] & (1 << (index & 31)))
+ size = sizeof(double);
+ else
+ size = sizeof(int);
+ u.i = jitl->arguments[index];
+ if (jit_thumb_p()) {
+ code2thumb(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ switch (thumb.i & 0xfff00f00) {
+ case ARM_CC_AL|ARM_VSTR|ARM_P:
+ if (jit_hardfp_p()) {
+ if (foff < 16) {
+ reg = (thumb.i >> 12) & 0xf;
+ thumb.i = (ARM_CC_AL|ARM_VMOV_F |
+ ((foff >> 1) << 12) | reg);
+ if (foff & 1)
+ thumb.i |= ARM_V_D;
+ thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ ++foff;
+ continue;
+ }
+ }
+ else {
+ if (ioff < 4) {
+ thumb.i = ((thumb.i & 0xfff0ff00) |
+ (JIT_FP << 16) | ioff);
+ thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ ++ioff;
+ continue;
+ }
+ }
+ thumb.i = (thumb.i & 0xffffff00) | (offset >> 2);
+ thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ break;
+ case ARM_CC_AL|ARM_VSTR|ARM_V_F64|ARM_P:
+ if (jit_hardfp_p()) {
+ if (foff & 1)
+ ++foff;
+ if (foff < 16) {
+ reg = (thumb.i >> 12) & 0xf;
+ thumb.i = (ARM_CC_AL|ARM_VMOV_F|ARM_V_F64 |
+ ((foff >> 1) << 12) | reg);
+ thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ foff += 2;
+ continue;
+ }
+ }
+ else {
+ if (ioff & 1)
+ ++ioff;
+ if (ioff < 4) {
+ thumb.i = ((thumb.i & 0xfff0ff00) |
+ (JIT_FP << 16) | ioff);
+ thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ ioff += 2;
+ continue;
+ }
+ }
+ if (offset & 7)
+ offset += sizeof(int);
+ thumb.i = (thumb.i & 0xffffff00) | (offset >> 2);
+ thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ break;
+ case THUMB2_STRWI:
+ thumb_stri:
+ if (size == 8 && (ioff & 1))
+ ++ioff;
+ if (ioff < 4) {
+ thumb.i = ((thumb.i & 0xfff0f000) |
+ (JIT_FP << 16) | (ioff << 2));
+ thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ ++ioff;
+ if (size == 8) {
+ code2thumb(thumb.s[0], thumb.s[1], u.s[2], u.s[3]);
+ thumb.i = ((thumb.i & 0xfff0f000) |
+ (JIT_FP << 16) | (ioff << 2));
+ thumb2code(thumb.s[0], thumb.s[1], u.s[2], u.s[3]);
+ ++ioff;
+ }
+ continue;
+ }
+ if (size == 8 && (offset & 7))
+ offset += sizeof(int);
+ thumb.i = (thumb.i & 0xfffff000) | offset;
+ thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
+ if (size == 8) {
+ code2thumb(thumb.s[0], thumb.s[1], u.s[2], u.s[3]);
+ thumb.i = (thumb.i & 0xfffff000) | (offset + 4);
+ thumb2code(thumb.s[0], thumb.s[1], u.s[2], u.s[3]);
+ }
+ break;
+ default:
+ /* offset too large */
+ if ((thumb.i & 0xfff00000) == THUMB2_STRWI)
+ goto thumb_stri;
+ abort();
+ }
+ }
+ else {
+ switch (u.i[0] & 0xfff00f00) {
+ case ARM_CC_AL|ARM_VSTR|ARM_P:
+ if (jit_hardfp_p()) {
+ if (foff < 16) {
+ reg = (u.i[0] >> 12) & 0xf;
+ u.i[0] = (ARM_CC_AL|ARM_VMOV_F |
+ ((foff >> 1) << 12) | reg);
+ if (foff & 1)
+ u.i[0] |= ARM_V_D;
+ ++foff;
+ continue;
+ }
+ }
+ else {
+ if (ioff < 4) {
+ u.i[0] = ((u.i[0] & 0xfff0ff00) |
+ (JIT_FP << 16) | ioff);
+ ++ioff;
+ continue;
+ }
+ }
+ u.i[0] = (u.i[0] & 0xffffff00) | (offset >> 2);
+ break;
+ case ARM_CC_AL|ARM_VSTR|ARM_V_F64|ARM_P:
+ if (jit_hardfp_p()) {
+ if (foff & 1)
+ ++foff;
+ if (foff < 16) {
+ reg = (u.i[0] >> 12) & 0xf;
+ u.i[0] = (ARM_CC_AL|ARM_VMOV_F|ARM_V_F64 |
+ ((foff >> 1) << 12) | reg);
+ foff += 2;
+ continue;
+ }
+ }
+ else {
+ if (ioff & 1)
+ ++ioff;
+ if (ioff < 4) {
+ u.i[0] = ((u.i[0] & 0xfff0ff00) |
+ (JIT_FP << 16) | ioff);
+ ioff += 2;
+ continue;
+ }
+ }
+ if (offset & 7)
+ offset += sizeof(int);
+ u.i[0] = (u.i[0] & 0xffffff00) | (offset >> 2);
+ break;
+ case ARM_CC_AL|ARM_STRI|ARM_P:
+ arm_stri:
+ if (size == 8 && (ioff & 1))
+ ++ioff;
+ if (ioff < 4) {
+ u.i[0] = ((u.i[0] & 0xfff0f000) |
+ (JIT_FP << 16) | (ioff << 2));
+ ++ioff;
+ if (size == 8) {
+ u.i[1] = ((u.i[1] & 0xfff0f000) |
+ (JIT_FP << 16) | (ioff << 2));
+ ++ioff;
+ }
+ continue;
+ }
+ if (size == 8 && (offset & 7))
+ offset += sizeof(int);
+ u.i[0] = (u.i[0] & 0xfffff000) | offset;
+ if (size == 8)
+ u.i[1] = (u.i[1] & 0xfffff000) | (offset + 4);
+ break;
+ default:
+ /* offset too large */
+ if ((u.i[0] & 0xfff00000) == (ARM_CC_AL|ARM_STRI|ARM_P))
+ goto arm_stri;
+ abort();
+ }
+ }
+ offset += size;
+ }
+ jitl->reglist = ((1 << ioff) - 1) & 0xf;
+ if (jitl->stack_length < offset) {
+ jitl->stack_length = offset;
+ jit_patch_movi(jitl->stack, (void *)
+ ((jitl->alloca_offset + jitl->stack_length + 7) & -8));
+ }
+}
+
+extern int __aeabi_idivmod(int, int);
+extern unsigned __aeabi_uidivmod(unsigned, unsigned);
+
+#pragma push_macro("_jit")
+#ifdef _jit
+#undef _jit
+#endif
+#define _jit (*jit)
+static void
+arm_divmod(jit_state* jit, int div, int sign,
+ jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
+{
+ int d;
+ int l;
+ void *p;
+ l = 0xf;
+ if ((int)r0 < 4)
+ /* bogus extra push to align at 8 bytes */
+ l = (l & ~(1 << r0)) | 0x10;
+#ifdef USE_THUMB_CODE
+ T1_PUSH(l);
+#else
+ _PUSH(l);
+#endif
+ if (r1 == _R1 && r2 == _R0) {
+ jit_movr_i(JIT_FTMP, _R0);
+ jit_movr_i(_R0, _R1);
+ jit_movr_i(_R1, JIT_FTMP);
+ } else if (r2 == _R0) {
+ jit_movr_i(_R1, r2);
+ jit_movr_i(_R0, r1);
+ } else {
+ jit_movr_i(_R0, r1);
+ jit_movr_i(_R1, r2);
+ }
+ p = (sign) ? (void*) __aeabi_idivmod : (void*) __aeabi_uidivmod;
+ if (!jit_exchange_p()) {
+#ifdef USE_THUMB_CODE
+ d = (((int)p - (int)_jit.x.pc) >> 1) - 2;
+#else
+ d = (((int)p - (int)_jit.x.pc) >> 2) - 2;
+#endif
+ if (_s24P(d)) {
+#ifdef USE_THUMB_CODE
+ T2_BLI(encode_thumb_jump(d));
+#else
+ _BLI(d & 0x00ffffff);
+#endif
+ }
+ else
+ goto fallback;
+ } else {
+fallback:
+ jit_movi_i(JIT_FTMP, (int)p);
+#ifdef USE_THUMB_CODE
+ T1_BLX(JIT_FTMP);
+#else
+ _BLX(JIT_FTMP);
+#endif
+ }
+ if (div) {
+ jit_movr_i(r0, _R0);
+ } else {
+ jit_movr_i(r0, _R1);
+ }
+#ifdef USE_THUMB_CODE
+ T1_POP(l);
+#else
+ _POP(l);
+#endif
+}
+#pragma pop_macro("_jit")
+
#endif /* __lightning_funcs_h */