From 297ae99c3f1959f387f59da535eb68f34ae523fe Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Mon, 6 Apr 2020 16:04:57 +1200 Subject: [PATCH 01/11] Add flag bits to the jit_reloc_kind enum --- lightening.h | 2 ++ lightening/lightening.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lightening.h b/lightening.h index bcf2032fa..4749723bf 100644 --- a/lightening.h +++ b/lightening.h @@ -91,6 +91,8 @@ enum jit_reloc_kind JIT_RELOC_JCC_WITH_VENEER, JIT_RELOC_LOAD_FROM_POOL, #endif + JIT_RELOC_MASK = 15, + JIT_RELOC_FLAG_0 = 16, }; typedef struct jit_reloc diff --git a/lightening/lightening.c b/lightening/lightening.c index ca5708f0a..8d4c3d7cd 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -379,7 +379,7 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) ASSERT((diff & ((1 << reloc.rsh) - 1)) == 0); diff >>= reloc.rsh; - switch (reloc.kind) + switch (reloc.kind & JIT_RELOC_MASK) { case JIT_RELOC_ABSOLUTE: if (sizeof(diff) == 4) @@ -1365,7 +1365,7 @@ emit_literal_pool(jit_state_t *_jit, enum guard_pool guard) if (_jit->overflow) return; - switch (entry->reloc.kind) { + switch (entry->reloc.kind & JIT_RELOC_MASK) { case JIT_RELOC_JMP_WITH_VENEER: patch_jmp_offset((uint32_t*) loc, diff); emit_veneer(_jit, (void*) (uintptr_t) entry->value); From aacaa6e38cda6154c5ab5d8d6bb2fe1b84feb256 Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Mon, 6 Apr 2020 19:44:03 +1200 Subject: [PATCH 02/11] Add separate functions for veneer patching --- lightening/aarch64.c | 8 ++++++-- lightening/arm-cpu.c | 12 ++++++++++++ lightening/lightening.c | 6 ++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lightening/aarch64.c b/lightening/aarch64.c index 2e525166c..b605cc53a 100644 --- a/lightening/aarch64.c +++ b/lightening/aarch64.c @@ -114,8 +114,12 @@ DEFINE_ENCODER(size, 2, 22, unsigned, uint32_t) } \ } -DEFINE_PATCHABLE_INSTRUCTION(jmp, simm26, JMP_WITH_VENEER, 2); -DEFINE_PATCHABLE_INSTRUCTION(jcc, simm19, JCC_WITH_VENEER, 2); +#define DEFINE_PATCHABLE_INSTRUCTIONS(name, kind, RELOC, rsh) \ + DEFINE_PATCHABLE_INSTRUCTION(name, kind, RELOC, rsh); \ + DEFINE_PATCHABLE_INSTRUCTION(veneer_##name, kind, RELOC, rsh); + +DEFINE_PATCHABLE_INSTRUCTIONS(jmp, simm26, JMP_WITH_VENEER, 2); +DEFINE_PATCHABLE_INSTRUCTIONS(jcc, simm19, JCC_WITH_VENEER, 2); DEFINE_PATCHABLE_INSTRUCTION(load_from_pool, simm19, LOAD_FROM_POOL, 2); struct veneer diff --git a/lightening/arm-cpu.c b/lightening/arm-cpu.c index d96d57b2d..8e3b12196 100644 --- a/lightening/arm-cpu.c +++ b/lightening/arm-cpu.c @@ -325,6 +325,12 @@ patch_jmp_offset(uint32_t *loc, int32_t v) write_wide_thumb(loc, patch_thumb_jump(read_wide_thumb(loc), v)); } +static void +patch_veneer_jmp_offset(uint32_t *loc, int32_t v) +{ + patch_jmp_offset(loc, v); +} + static jit_reloc_t emit_thumb_jump(jit_state_t *_jit, uint32_t inst) { @@ -401,6 +407,12 @@ patch_jcc_offset(uint32_t *loc, int32_t v) write_wide_thumb(loc, patch_thumb_cc_jump(read_wide_thumb(loc), v)); } +static void +patch_veneer_jcc_offset(uint32_t *loc, int32_t v) +{ + patch_jcc_offset(loc, v); +} + static jit_reloc_t emit_thumb_cc_jump(jit_state_t *_jit, uint32_t inst) { diff --git a/lightening/lightening.c b/lightening/lightening.c index 8d4c3d7cd..09402634b 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -107,9 +107,11 @@ static void emit_literal_pool(jit_state_t *_jit, enum guard_pool guard); static int32_t read_jmp_offset(uint32_t *loc); static int offset_in_jmp_range(ptrdiff_t offset); static void patch_jmp_offset(uint32_t *loc, ptrdiff_t offset); +static void patch_veneer_jmp_offset(uint32_t *loc, ptrdiff_t offset); static int32_t read_jcc_offset(uint32_t *loc); static int offset_in_jcc_range(ptrdiff_t offset); static void patch_jcc_offset(uint32_t *loc, ptrdiff_t offset); +static void patch_veneer_jcc_offset(uint32_t *loc, ptrdiff_t offset); static void patch_veneer(uint32_t *loc, jit_pointer_t addr); static int32_t read_load_from_pool_offset(uint32_t *loc); #endif @@ -1367,11 +1369,11 @@ emit_literal_pool(jit_state_t *_jit, enum guard_pool guard) switch (entry->reloc.kind & JIT_RELOC_MASK) { case JIT_RELOC_JMP_WITH_VENEER: - patch_jmp_offset((uint32_t*) loc, diff); + patch_veneer_jmp_offset((uint32_t*) loc, diff); emit_veneer(_jit, (void*) (uintptr_t) entry->value); break; case JIT_RELOC_JCC_WITH_VENEER: - patch_jcc_offset((uint32_t*) loc, diff); + patch_veneer_jcc_offset((uint32_t*) loc, diff); emit_veneer(_jit, (void*) (uintptr_t) entry->value); break; case JIT_RELOC_LOAD_FROM_POOL: From 1656fc1d81e7e2978edd3438c4390de6f95c471b Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Thu, 9 Apr 2020 17:31:25 +1200 Subject: [PATCH 03/11] Add a test for local forward and backward jumps --- tests/jmpi_local.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/jmpi_local.c diff --git a/tests/jmpi_local.c b/tests/jmpi_local.c new file mode 100644 index 000000000..49e450732 --- /dev/null +++ b/tests/jmpi_local.c @@ -0,0 +1,25 @@ +#include "test.h" + +static void +run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size) +{ + jit_begin(j, arena_base, arena_size); + + jit_reloc_t r = jit_jmp (j); + jit_reti (j, 0); + jit_pointer_t addr = jit_address (j); + jit_reti (j, 1); + jit_patch_here (j, r); + jit_jmpi (j, addr); + jit_reti (j, 2); + + int (*f)(void) = jit_end(j, NULL); + + ASSERT(f() == 1); +} + +int +main (int argc, char *argv[]) +{ + return main_helper(argc, argv, run_test); +} From ba24ce465f3d0b8a3888e4a668f7410b49415c12 Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Thu, 9 Apr 2020 19:36:13 +1200 Subject: [PATCH 04/11] Use an rsh of 0 for jumps on ARM This will allow supporting jumping to ARM (as opposed to Thumb) code. --- lightening/arm-cpu.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/lightening/arm-cpu.c b/lightening/arm-cpu.c index 8e3b12196..9f7876ee3 100644 --- a/lightening/arm-cpu.c +++ b/lightening/arm-cpu.c @@ -267,7 +267,7 @@ write_wide_thumb(uint32_t *loc, uint32_t v) static int offset_in_jmp_range(int32_t offset) { - return -0x800000 <= offset && offset <= 0x7fffff; + return -0x1000000 <= offset && offset <= 0xffffff; } static int32_t @@ -287,7 +287,7 @@ decode_thumb_jump(uint32_t v) ret |= i2 << 21; ret |= hi << 11; ret |= lo; - return ret; + return ret << 1; } static const uint32_t thumb_jump_mask = 0xf800d000; @@ -296,13 +296,14 @@ static uint32_t encode_thumb_jump(int32_t v) { ASSERT(offset_in_jmp_range(v)); + v >>= 1; uint32_t s = !!(v & 0x800000); uint32_t i1 = !!(v & 0x400000); uint32_t i2 = !!(v & 0x200000); uint32_t j1 = s ? i1 : !i1; uint32_t j2 = s ? i2 : !i2; uint32_t ret = (s<<26)|((v&0x1ff800)<<5)|(j1<<13)|(j2<<11)|(v&0x7ff); - ASSERT(decode_thumb_jump(ret) == v); + ASSERT(decode_thumb_jump(ret) == v << 1); ASSERT((ret & thumb_jump_mask) == 0); return ret; } @@ -322,13 +323,14 @@ read_jmp_offset(uint32_t *loc) static void patch_jmp_offset(uint32_t *loc, int32_t v) { - write_wide_thumb(loc, patch_thumb_jump(read_wide_thumb(loc), v)); + write_wide_thumb(loc, patch_thumb_jump(read_wide_thumb(loc), v | 1)); } static void patch_veneer_jmp_offset(uint32_t *loc, int32_t v) { - patch_jmp_offset(loc, v); + ASSERT(!(v & 1)); + patch_jmp_offset(loc, v | 1); } static jit_reloc_t @@ -336,10 +338,9 @@ emit_thumb_jump(jit_state_t *_jit, uint32_t inst) { while (1) { uint8_t *pc_base = _jit->pc.uc + 4; - uint8_t rsh = 1; - int32_t off = (_jit->pc.uc - pc_base) >> rsh; + int32_t off = (uint8_t*)jit_address(_jit) - pc_base; jit_reloc_t ret = - jit_reloc (_jit, JIT_RELOC_JMP_WITH_VENEER, 0, _jit->pc.uc, pc_base, rsh); + jit_reloc (_jit, JIT_RELOC_JMP_WITH_VENEER, 0, _jit->pc.uc, pc_base, 0); uint8_t thumb_jump_width = 24; if (add_pending_literal(_jit, ret, thumb_jump_width - 1)) { emit_wide_thumb(_jit, patch_thumb_jump(inst, off)); @@ -351,7 +352,7 @@ emit_thumb_jump(jit_state_t *_jit, uint32_t inst) static int offset_in_jcc_range(int32_t v) { - return -0x80000 <= v && v <= 0x7ffff; + return -0x100000 <= v && v <= 0xfffff; } static int32_t @@ -369,7 +370,7 @@ decode_thumb_cc_jump(uint32_t v) ret |= j1 << 17; ret |= hi << 11; ret |= lo; - return ret; + return ret << 1; } static const uint32_t thumb_cc_jump_mask = 0xfbc0d000; @@ -378,13 +379,14 @@ static uint32_t encode_thumb_cc_jump(int32_t v) { ASSERT(offset_in_jcc_range(v)); + v >>= 1; uint32_t s = !!(v & 0x80000); uint32_t j2 = !!(v & 0x40000); uint32_t j1 = !!(v & 0x20000); uint32_t hi = (v >> 11) & 0x3f; uint32_t lo = v & 0x7ff; uint32_t ret = (s<<26)|(hi << 16)|(j1<<13)|(j2<<11)|lo; - ASSERT(decode_thumb_cc_jump(ret) == v); + ASSERT(decode_thumb_cc_jump(ret) == v << 1); ASSERT((ret & thumb_cc_jump_mask) == 0); return ret; } @@ -404,13 +406,14 @@ read_jcc_offset(uint32_t *loc) static void patch_jcc_offset(uint32_t *loc, int32_t v) { - write_wide_thumb(loc, patch_thumb_cc_jump(read_wide_thumb(loc), v)); + write_wide_thumb(loc, patch_thumb_cc_jump(read_wide_thumb(loc), v | 1)); } static void patch_veneer_jcc_offset(uint32_t *loc, int32_t v) { - patch_jcc_offset(loc, v); + ASSERT(!(v & 1)); + patch_jcc_offset(loc, v | 1); } static jit_reloc_t @@ -418,10 +421,9 @@ emit_thumb_cc_jump(jit_state_t *_jit, uint32_t inst) { while (1) { uint8_t *pc_base = _jit->pc.uc + 4; - uint8_t rsh = 1; - int32_t off = (_jit->pc.uc - pc_base) >> rsh; + int32_t off = (uint8_t*)jit_address(_jit) - pc_base; jit_reloc_t ret = - jit_reloc (_jit, JIT_RELOC_JCC_WITH_VENEER, 0, _jit->pc.uc, pc_base, rsh); + jit_reloc (_jit, JIT_RELOC_JCC_WITH_VENEER, 0, _jit->pc.uc, pc_base, 0); uint8_t thumb_cc_jump_width = 20; if (add_pending_literal(_jit, ret, thumb_cc_jump_width - 1)) { emit_wide_thumb(_jit, patch_thumb_cc_jump(inst, off)); @@ -2076,8 +2078,6 @@ jmp(jit_state_t *_jit) static void jmpi(jit_state_t *_jit, jit_word_t i0) { - /* Strip thumb bit, if any. */ - i0 &= ~1; return jit_patch_there(_jit, jmp(_jit), (void*)i0); } @@ -2917,10 +2917,7 @@ callr(jit_state_t *_jit, int32_t r0) static void calli(jit_state_t *_jit, jit_word_t i0) { - if (i0 & 1) - jit_patch_there(_jit, T2_BLI(_jit), (void*)(i0 & ~1)); - else - jit_patch_there(_jit, T2_BLXI(_jit), (void*)i0); + jit_patch_there(_jit, T2_BLI(_jit), (void*)i0); } static void @@ -3002,8 +2999,7 @@ static void patch_jmp_without_veneer(jit_state_t *_jit, uint32_t *loc) { uint8_t *pc_base = ((uint8_t *)loc) + 4; - uint8_t rsh = 1; - int32_t off = (_jit->pc.uc - pc_base) >> rsh; + int32_t off = (uint8_t*)jit_address(_jit) - pc_base; write_wide_thumb(loc, THUMB2_B | encode_thumb_jump(off)); } From 8045386a4597454507b31139ad87e5ea6fe5164a Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Thu, 9 Apr 2020 19:30:18 +1200 Subject: [PATCH 05/11] Return a function pointer from jit_address This will allow supporting ARM code on armv7 without having to change any users of Lightening. --- lightening/lightening.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lightening/lightening.c b/lightening/lightening.c index 09402634b..92e40c4bf 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -171,7 +171,7 @@ jit_pointer_t jit_address(jit_state_t *_jit) { ASSERT (_jit->start); - return _jit->pc.uc; + return jit_address_to_function_pointer (_jit->pc.uc); } void From 7f5f26269f7f70dfa78f032b42448b4fbd4ab501 Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Thu, 9 Apr 2020 20:37:12 +1200 Subject: [PATCH 06/11] Stop setting the thumb bit except on jumps to veneers Thanks to the previous commit, the jump targets should all be correct. --- lightening/arm-cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lightening/arm-cpu.c b/lightening/arm-cpu.c index 9f7876ee3..9b328adc5 100644 --- a/lightening/arm-cpu.c +++ b/lightening/arm-cpu.c @@ -323,7 +323,7 @@ read_jmp_offset(uint32_t *loc) static void patch_jmp_offset(uint32_t *loc, int32_t v) { - write_wide_thumb(loc, patch_thumb_jump(read_wide_thumb(loc), v | 1)); + write_wide_thumb(loc, patch_thumb_jump(read_wide_thumb(loc), v)); } static void @@ -406,7 +406,7 @@ read_jcc_offset(uint32_t *loc) static void patch_jcc_offset(uint32_t *loc, int32_t v) { - write_wide_thumb(loc, patch_thumb_cc_jump(read_wide_thumb(loc), v | 1)); + write_wide_thumb(loc, patch_thumb_cc_jump(read_wide_thumb(loc), v)); } static void From a6fee1add8043f54b3adfe9e539b25c69456d2d6 Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Thu, 9 Apr 2020 21:24:51 +1200 Subject: [PATCH 07/11] Use bx instead of mov for jumps on ARM --- lightening/arm-cpu.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lightening/arm-cpu.c b/lightening/arm-cpu.c index 9b328adc5..3cea9f878 100644 --- a/lightening/arm-cpu.c +++ b/lightening/arm-cpu.c @@ -2066,7 +2066,7 @@ rshi_u(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0) static void jmpr(jit_state_t *_jit, int32_t r0) { - T1_MOV(_jit, jit_gpr_regno(_PC), r0); + T1_BX(_jit, r0); } static jit_reloc_t @@ -3022,11 +3022,10 @@ emit_veneer(jit_state_t *_jit, jit_pointer_t target) { uint16_t thumb1_ldr = 0x4800; int32_t tmp = jit_gpr_regno(JIT_TMP1); - int32_t rd = jit_gpr_regno(_PC); ASSERT(tmp < 8); // Loaded addr is 4 bytes after the LDR, which is aligned, so offset is 0. emit_u16(_jit, thumb1_ldr | (tmp << 8)); - emit_u16(_jit, THUMB_MOV|((_u4(rd)&8)<<4)|(_u4(tmp)<<3)|(rd&7)); + emit_u16(_jit, THUMB_BX|(_u4(tmp)<<3)); emit_u32(_jit, (uint32_t) target); } From 52ec8aefa0c6a4926c61b9e027fce7256034ad6e Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Thu, 9 Apr 2020 21:26:57 +1200 Subject: [PATCH 08/11] Remove T2_BLXI --- lightening/arm-cpu.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lightening/arm-cpu.c b/lightening/arm-cpu.c index 3cea9f878..192c70583 100644 --- a/lightening/arm-cpu.c +++ b/lightening/arm-cpu.c @@ -1042,12 +1042,6 @@ T2_BLI(jit_state_t *_jit) return tb(_jit, THUMB2_BLI); } -static jit_reloc_t -T2_BLXI(jit_state_t *_jit) -{ - return tb(_jit, THUMB2_BLXI); -} - enum dmb_option { DMB_ISH = 0xb }; static void T1_DMB(jit_state_t *_jit, enum dmb_option option) From 11b9d3744e963a121270712199bbfa7edb70d245 Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Thu, 9 Apr 2020 22:10:15 +1200 Subject: [PATCH 09/11] Always emit veneers for non-bl jumps to ARM code It is unlikely for any ARM code to be close enough to not have needed a veneer, but it is possible, especially if running in a program with another JIT library. --- lightening/aarch64.c | 4 ++-- lightening/arm-cpu.c | 26 ++++++++++++++++++-------- lightening/lightening.c | 9 +++++---- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/lightening/aarch64.c b/lightening/aarch64.c index b605cc53a..2b3ed4d60 100644 --- a/lightening/aarch64.c +++ b/lightening/aarch64.c @@ -90,9 +90,9 @@ DEFINE_ENCODER(size, 2, 22, unsigned, uint32_t) { \ return read_signed_bitfield(*loc, kind##_width, kind##_shift); \ } \ - static int offset_in_##name##_range(ptrdiff_t diff) maybe_unused; \ + static int offset_in_##name##_range(ptrdiff_t diff, int flags) maybe_unused; \ static int \ - offset_in_##name##_range(ptrdiff_t diff) \ + offset_in_##name##_range(ptrdiff_t diff, int flags) \ { \ return in_signed_range(diff, kind##_width); \ } \ diff --git a/lightening/arm-cpu.c b/lightening/arm-cpu.c index 192c70583..1bb739467 100644 --- a/lightening/arm-cpu.c +++ b/lightening/arm-cpu.c @@ -186,6 +186,8 @@ #define _NOREG (jit_gpr_regno(_PC)) +#define JIT_RELOC_B JIT_RELOC_FLAG_0 + static void emit_wide_thumb(jit_state_t *_jit, uint32_t inst) { @@ -265,9 +267,12 @@ write_wide_thumb(uint32_t *loc, uint32_t v) } static int -offset_in_jmp_range(int32_t offset) +offset_in_jmp_range(int32_t offset, int flags) { - return -0x1000000 <= offset && offset <= 0xffffff; + if (!(offset & 1) && flags | JIT_RELOC_B) + return 0; + else + return -0x1000000 <= offset && offset <= 0xffffff; } static int32_t @@ -295,7 +300,7 @@ static const uint32_t thumb_jump_mask = 0xf800d000; static uint32_t encode_thumb_jump(int32_t v) { - ASSERT(offset_in_jmp_range(v)); + ASSERT(offset_in_jmp_range(v, 0)); v >>= 1; uint32_t s = !!(v & 0x800000); uint32_t i1 = !!(v & 0x400000); @@ -339,8 +344,10 @@ emit_thumb_jump(jit_state_t *_jit, uint32_t inst) while (1) { uint8_t *pc_base = _jit->pc.uc + 4; int32_t off = (uint8_t*)jit_address(_jit) - pc_base; - jit_reloc_t ret = - jit_reloc (_jit, JIT_RELOC_JMP_WITH_VENEER, 0, _jit->pc.uc, pc_base, 0); + enum jit_reloc_kind kind = JIT_RELOC_JMP_WITH_VENEER; + if (inst == THUMB2_B) + kind |= JIT_RELOC_B; + jit_reloc_t ret = jit_reloc (_jit, kind, 0, _jit->pc.uc, pc_base, 0); uint8_t thumb_jump_width = 24; if (add_pending_literal(_jit, ret, thumb_jump_width - 1)) { emit_wide_thumb(_jit, patch_thumb_jump(inst, off)); @@ -350,9 +357,12 @@ emit_thumb_jump(jit_state_t *_jit, uint32_t inst) } static int -offset_in_jcc_range(int32_t v) +offset_in_jcc_range(int32_t v, int flags) { - return -0x100000 <= v && v <= 0xfffff; + if (!(v & 1)) + return 0; + else + return -0x100000 <= v && v <= 0xfffff; } static int32_t @@ -378,7 +388,7 @@ static const uint32_t thumb_cc_jump_mask = 0xfbc0d000; static uint32_t encode_thumb_cc_jump(int32_t v) { - ASSERT(offset_in_jcc_range(v)); + ASSERT(offset_in_jcc_range(v, 0)); v >>= 1; uint32_t s = !!(v & 0x80000); uint32_t j2 = !!(v & 0x40000); diff --git a/lightening/lightening.c b/lightening/lightening.c index 92e40c4bf..66207885f 100644 --- a/lightening/lightening.c +++ b/lightening/lightening.c @@ -105,11 +105,11 @@ enum guard_pool { GUARD_NEEDED, NO_GUARD_NEEDED }; static void emit_literal_pool(jit_state_t *_jit, enum guard_pool guard); static int32_t read_jmp_offset(uint32_t *loc); -static int offset_in_jmp_range(ptrdiff_t offset); +static int offset_in_jmp_range(ptrdiff_t offset, int flags); static void patch_jmp_offset(uint32_t *loc, ptrdiff_t offset); static void patch_veneer_jmp_offset(uint32_t *loc, ptrdiff_t offset); static int32_t read_jcc_offset(uint32_t *loc); -static int offset_in_jcc_range(ptrdiff_t offset); +static int offset_in_jcc_range(ptrdiff_t offset, int flags); static void patch_jcc_offset(uint32_t *loc, ptrdiff_t offset); static void patch_veneer_jcc_offset(uint32_t *loc, ptrdiff_t offset); static void patch_veneer(uint32_t *loc, jit_pointer_t addr); @@ -380,6 +380,7 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) ptrdiff_t diff = (uint8_t*)addr - pc_base; ASSERT((diff & ((1 << reloc.rsh) - 1)) == 0); diff >>= reloc.rsh; + int flags = reloc.kind & ~JIT_RELOC_MASK; switch (reloc.kind & JIT_RELOC_MASK) { @@ -406,7 +407,7 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) uint8_t *target = pc_base + (voff << reloc.rsh); if (target == loc.uc) { // PC still in range to reify direct branch. - if (offset_in_jmp_range(diff)) { + if (offset_in_jmp_range(diff, flags)) { // Target also in range: reify direct branch. patch_jmp_offset(loc.ui, diff); remove_pending_literal(_jit, reloc); @@ -425,7 +426,7 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr) int32_t voff = read_jcc_offset(loc.ui); uint8_t *target = pc_base + (voff << reloc.rsh); if (target == loc.uc) { - if (offset_in_jcc_range(diff)) { + if (offset_in_jcc_range(diff, flags)) { patch_jcc_offset(loc.ui, diff); remove_pending_literal(_jit, reloc); } else { From 0ff3b3163c3bf7bc9b498403428999deb771d2cd Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Thu, 9 Apr 2020 21:32:55 +1200 Subject: [PATCH 10/11] Convert BLI to BLXI for jumps to ARM code With this, Guile builds and runs in both ARM and Thumb mode. Closes: #12 --- lightening/arm-cpu.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lightening/arm-cpu.c b/lightening/arm-cpu.c index 1bb739467..0e38883ef 100644 --- a/lightening/arm-cpu.c +++ b/lightening/arm-cpu.c @@ -316,7 +316,13 @@ encode_thumb_jump(int32_t v) static uint32_t patch_thumb_jump(uint32_t inst, int32_t v) { - return (inst & thumb_jump_mask) | encode_thumb_jump(v); + inst &= thumb_jump_mask; + if (!(v & 1)) { + ASSERT(inst == THUMB2_BLI || inst == THUMB2_BLXI); + v = (v + 2) & ~2; + inst = THUMB2_BLXI; + } + return inst | encode_thumb_jump(v); } static int32_t From 2a4ed4b77648fc6cc640c1b6bd9a4019cd6a1974 Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Thu, 9 Apr 2020 22:34:21 +1200 Subject: [PATCH 11/11] Add CI jobs for ARM in both instruction sets --- .gitlab-ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ff2bf03b8..0360cf0c7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -30,4 +30,9 @@ aarch64: armhf: stage: test script: - - make -C tests test-armv7 CC_ARMv7=arm-linux-gnueabihf-gcc + - make -C tests test-armv7 CC_ARMv7="arm-linux-gnueabihf-gcc -marm" + +armhf-thumb: + stage: test + script: + - make -C tests test-armv7 CC_ARMv7="arm-linux-gnueabihf-gcc -mthumb"