summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@igalia.com>2019-04-26 12:40:44 +0200
committerAndy Wingo <wingo@igalia.com>2019-04-26 12:40:44 +0200
commit04d89a7ce27ba60bc2735e2f563d88c28fff2208 (patch)
treee7e4003e9c5af3ee1b86a8367cecce2aab535c40
parent796f263ed8b81c785daeafd03caea8cfd8d55f78 (diff)
downloadguile-04d89a7ce27ba60bc2735e2f563d88c28fff2208.tar.gz
Implement reloc shortening, and remove unused functionality
-rw-r--r--lightening.h1
-rw-r--r--lightening/lightening.c29
-rw-r--r--lightening/x86-cpu.c114
-rw-r--r--lightening/x86.c38
4 files changed, 79 insertions, 103 deletions
diff --git a/lightening.h b/lightening.h
index 43ef7b82b..437ba1872 100644
--- a/lightening.h
+++ b/lightening.h
@@ -78,7 +78,6 @@ typedef struct jit_reloc
{
uint8_t kind;
uint8_t inst_start_offset;
- uint16_t flags;
uint32_t offset;
} jit_reloc_t;
diff --git a/lightening/lightening.c b/lightening/lightening.c
index 1a135590d..faba86bdb 100644
--- a/lightening/lightening.c
+++ b/lightening/lightening.c
@@ -124,11 +124,6 @@ struct jit_state
void (*free)(void*);
};
-enum jit_reloc_flags
-{
- JIT_RELOC_CAN_SHORTEN = 1<<0
-};
-
#define ASSERT(x) do { if (!(x)) abort(); } while (0)
#if defined(__GNUC__)
# define UNLIKELY(exprn) __builtin_expect(exprn, 0)
@@ -139,7 +134,8 @@ enum jit_reloc_flags
static jit_bool_t jit_get_cpu(void);
static jit_bool_t jit_init(jit_state_t *);
static void jit_flush(void *fptr, void *tptr);
-static void jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc);
+static void jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc,
+ jit_pointer_t addr);
jit_bool_t
init_jit(void)
@@ -283,13 +279,12 @@ static inline void emit_u64(jit_state_t *_jit, uint64_t u64) {
static inline jit_reloc_t
jit_reloc (jit_state_t *_jit, enum jit_reloc_kind kind,
- uint8_t inst_start_offset, uint16_t flags)
+ uint8_t inst_start_offset)
{
jit_reloc_t ret;
ret.kind = kind;
ret.inst_start_offset = inst_start_offset;
- ret.flags = 0;
ret.offset = _jit->pc.uc - _jit->start;
switch (kind)
@@ -331,6 +326,7 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr)
if (_jit->overflow)
return;
union jit_pc loc;
+ uint8_t *end;
loc.uc = _jit->start + reloc.offset;
ptrdiff_t diff;
@@ -341,38 +337,37 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr)
*loc.ui = (uintptr_t)addr;
else
*loc.ul = (uintptr_t)addr;
- if (loc.uc + sizeof(diff) == _jit->pc.uc &&
- (reloc.flags & JIT_RELOC_CAN_SHORTEN))
- jit_try_shorten (_jit, reloc);
+ end = loc.uc + sizeof(diff);
break;
case JIT_RELOC_REL8:
diff = ((uint8_t*)addr) - (loc.uc + 1);
ASSERT (INT8_MIN <= diff && diff <= INT8_MAX);
*loc.uc = diff;
+ end = loc.uc + 1;
break;
case JIT_RELOC_REL16:
diff = ((uint8_t*)addr) - (loc.uc + 2);
ASSERT (INT16_MIN <= diff && diff <= INT16_MAX);
*loc.us = diff;
- if ((loc.uc + 1) == _jit->pc.uc && (reloc.flags & JIT_RELOC_CAN_SHORTEN))
- jit_try_shorten (_jit, reloc);
+ end = loc.uc + 2;
break;
case JIT_RELOC_REL32:
diff = ((uint8_t*)addr) - (loc.uc + 4);
ASSERT (INT32_MIN <= diff && diff <= INT32_MAX);
*loc.ui = diff;
- if ((loc.ui + 1) == _jit->pc.ui && (reloc.flags & JIT_RELOC_CAN_SHORTEN))
- jit_try_shorten (_jit, reloc);
+ end = loc.uc + 4;
break;
case JIT_RELOC_REL64:
diff = ((uint8_t*)addr) - (loc.uc + 8);
*loc.ul = diff;
- if ((loc.ul + 1) == _jit->pc.ul && (reloc.flags & JIT_RELOC_CAN_SHORTEN))
- jit_try_shorten (_jit, reloc);
+ end = loc.uc + 8;
break;
default:
abort ();
}
+
+ if (end == _jit->pc.uc)
+ jit_try_shorten (_jit, reloc, addr);
}
#if defined(__i386__) || defined(__x86_64__)
diff --git a/lightening/x86-cpu.c b/lightening/x86-cpu.c
index 7b1639335..aa9d68a68 100644
--- a/lightening/x86-cpu.c
+++ b/lightening/x86-cpu.c
@@ -403,7 +403,7 @@ mov_addr(jit_state_t *_jit, int32_t r0)
rex(_jit, 0, WIDE, _NOREG, _NOREG, r0);
ic(_jit, 0xb8 | r7(r0));
ptrdiff_t inst_start = _jit->pc.uc - pc_start;
- return jit_reloc(_jit, JIT_RELOC_ABSOLUTE, inst_start, 0);
+ return jit_reloc(_jit, JIT_RELOC_ABSOLUTE, inst_start);
}
static void
@@ -660,15 +660,6 @@ testi(jit_state_t *_jit, int32_t r0, jit_word_t i0)
}
static void
-cc(jit_state_t *_jit, int32_t code, int32_t r0)
-{
- rex(_jit, 0, 0, _NOREG, _NOREG, r0);
- ic(_jit, 0x0f);
- ic(_jit, 0x90 | code);
- mrm(_jit, 0x03, 0x00, r7(r0));
-}
-
-static void
negr(jit_state_t *_jit, int32_t r0, int32_t r1)
{
if (r0 == r1) {
@@ -1466,69 +1457,6 @@ xori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
}
static void
-cr(jit_state_t *_jit, int32_t code, int32_t r0, int32_t r1, int32_t r2)
-{
- if (reg8_p(r0)) {
- jit_bool_t same = r0 == r1 || r0 == r2;
- if (!same)
- ixorr(_jit, r0, r0);
- icmpr(_jit, r1, r2);
- if (same)
- imovi(_jit, r0, 0);
- cc(_jit, code, r0);
- } else {
- jit_gpr_t reg = get_temp_gpr(_jit);
- ixorr(_jit, jit_gpr_regno(reg), jit_gpr_regno(reg));
- icmpr(_jit, r1, r2);
- cc(_jit, code, jit_gpr_regno(reg));
- movr(_jit, r0, jit_gpr_regno(reg));
- unget_temp_gpr(_jit);
- }
-}
-
-static void
-ci(jit_state_t *_jit, int32_t code, int32_t r0, int32_t r1, jit_word_t i0)
-{
- if (reg8_p(r0)) {
- jit_bool_t same = r0 == r1;
- if (!same)
- ixorr(_jit, r0, r0);
- icmpi(_jit, r1, i0);
- if (same)
- imovi(_jit, r0, 0);
- cc(_jit, code, r0);
- } else {
- jit_gpr_t reg = get_temp_gpr(_jit);
- ixorr(_jit, jit_gpr_regno(reg), jit_gpr_regno(reg));
- icmpi(_jit, r1, i0);
- cc(_jit, code, jit_gpr_regno(reg));
- movr(_jit, r0, jit_gpr_regno(reg));
- unget_temp_gpr(_jit);
- }
-}
-
-static void
-ci0(jit_state_t *_jit, int32_t code, int32_t r0, int32_t r1)
-{
- if (reg8_p(r0)) {
- jit_bool_t same = r0 == r1;
- if (!same)
- ixorr(_jit, r0, r0);
- testr(_jit, r1, r1);
- if (same)
- imovi(_jit, r0, 0);
- cc(_jit, code, r0);
- } else {
- jit_gpr_t reg = get_temp_gpr(_jit);
- ixorr(_jit, jit_gpr_regno(reg), jit_gpr_regno(reg));
- testr(_jit, r1, r1);
- cc(_jit, code, jit_gpr_regno(reg));
- movr(_jit, r0, jit_gpr_regno(reg));
- unget_temp_gpr(_jit);
- }
-}
-
-static void
extr_c(jit_state_t *_jit, int32_t r0, int32_t r1)
{
if (reg8_p(r1)) {
@@ -2255,7 +2183,7 @@ static jit_reloc_t
jccs(jit_state_t *_jit, int32_t code)
{
ic(_jit, 0x70 | code);
- return jit_reloc(_jit, JIT_RELOC_REL8, 1, 0);
+ return jit_reloc(_jit, JIT_RELOC_REL8, 1);
}
static jit_reloc_t
@@ -2263,7 +2191,26 @@ jcc(jit_state_t *_jit, int32_t code)
{
ic(_jit, 0x0f);
ic(_jit, 0x80 | code);
- return jit_reloc(_jit, JIT_RELOC_REL32, 2, 0);
+ return jit_reloc(_jit, JIT_RELOC_REL32, 2);
+}
+
+static void
+jcci(jit_state_t *_jit, int32_t code, jit_word_t i0)
+{
+ ptrdiff_t rel8 = i0 - (_jit->pc.w + 1 + 1);
+ ptrdiff_t rel32 = i0 - (_jit->pc.w + 2 + 4);
+ if (INT8_MIN <= rel8 && rel8 <= INT8_MAX)
+ {
+ ic(_jit, 0x70 | code);
+ ic(_jit, rel8);
+ }
+ else
+ {
+ ASSERT(INT32_MIN <= rel32 && rel32 <= INT32_MAX);
+ ic(_jit, 0x0f);
+ ic(_jit, 0x80 | code);
+ ii(_jit, rel32);
+ }
}
#define DEFINE_JUMPS(cc, CC, code) \
@@ -2666,8 +2613,14 @@ jmpr(jit_state_t *_jit, int32_t r0)
static void
jmpi(jit_state_t *_jit, jit_word_t i0)
{
+ ptrdiff_t rel8 = i0 - (_jit->pc.w + 1 + 1);
ptrdiff_t rel32 = i0 - (_jit->pc.w + 1 + 4);
- if (INT32_MIN <= rel32 && rel32 <= INT32_MAX)
+ if (INT8_MIN <= rel8 && rel8 <= INT8_MAX)
+ {
+ ic(_jit, 0xeb);
+ ic(_jit, rel8);
+ }
+ else if (INT32_MIN <= rel32 && rel32 <= INT32_MAX)
{
ic(_jit, 0xe9);
ii(_jit, rel32);
@@ -2685,14 +2638,7 @@ static jit_reloc_t
jmp(jit_state_t *_jit)
{
ic(_jit, 0xe9);
- return jit_reloc(_jit, JIT_RELOC_REL32, 1, 0);
-}
-
-static jit_reloc_t
-jmpsi(jit_state_t *_jit)
-{
- ic(_jit, 0xeb);
- return jit_reloc(_jit, JIT_RELOC_REL8, 1, 0);
+ return jit_reloc(_jit, JIT_RELOC_REL32, 1);
}
static void
diff --git a/lightening/x86.c b/lightening/x86.c
index a0afd02aa..4031bb1ca 100644
--- a/lightening/x86.c
+++ b/lightening/x86.c
@@ -351,6 +351,42 @@ jit_flush(void *fptr, void *tptr)
}
static void
-jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc)
+jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, jit_pointer_t addr)
{
+ uint8_t *loc = _jit->start + reloc.offset;
+ uint8_t *start = loc - reloc.inst_start_offset;
+ jit_imm_t i0 = (jit_imm_t)addr;
+
+ switch (reloc.kind)
+ {
+ case JIT_RELOC_ABSOLUTE: {
+ _jit->pc.uc = start;
+ ASSERT((loc[-1] & ~7) == 0xb8); // MOVI
+ int32_t r0 = loc[-1] & 7;
+ if (start != loc - 1) {
+ ASSERT(start == loc - 2);
+ r0 |= (loc[-2] & 1) << 3;
+ }
+ return movi(_jit, r0, i0);
+ }
+ case JIT_RELOC_REL8:
+ ASSERT((loc[-1] & ~0xf) == 0x70 || loc[-1] == 0xeb); // JCCSI or JMPSI
+ /* Nothing useful to do. */
+ return;
+ case JIT_RELOC_REL16:
+ /* We don't emit these. */
+ abort ();
+ case JIT_RELOC_REL32:
+ _jit->pc.uc = start;
+ if (start[0] == 0xe9) { // JMP
+ return jmpi(_jit, i0);
+ }
+ ASSERT(start[0] == 0x0f); // JCC
+ return jcci(_jit, start[1] & ~0x80, i0);
+ case JIT_RELOC_REL64:
+ /* We don't emit these. */
+ abort ();
+ default:
+ abort ();
+ }
}