mips: Fill delay slots of JR opcodes in jit_jmpr - lightning.git - Portable just-in-time compiler library

index : lightning.git
Portable just-in-time compiler library
summary refs log tree commit diff
path: root/lib/jit_mips-cpu.c
diff options
context:
space:
mode:
authorPaul Cercueil <paul@crapouillou.net>2023年01月14日 15:10:50 +0000
committerpcpa <paulo.cesar.pereira.de.andrade@gmail.com>2023年01月14日 21:37:25 -0300
commite789a06724d994bd27d53723a9c714b49f222149 (patch)
tree89c8ea55da37ec8b8af4ae69710004fff6bf2150 /lib/jit_mips-cpu.c
parentfc5a26edddfe51b3834236e8f4e8a03f4df7a4ae (diff)
downloadlightning-e789a06724d994bd27d53723a9c714b49f222149.tar.gz
mips: Fill delay slots of JR opcodes in jit_jmpr
When we know that the last generated opcode is not the target of a jump, and that it does not write the register used by the JR opcode, we can swap it with the JR opcode, so that it now becomes the delay slot of the JR opcode. Signed-off-by: Paul Cercueil <paul@crapouillou.net>
Diffstat (limited to 'lib/jit_mips-cpu.c')
-rw-r--r--lib/jit_mips-cpu.c 208
1 files changed, 203 insertions, 5 deletions
diff --git a/lib/jit_mips-cpu.c b/lib/jit_mips-cpu.c
index d73535a..033315e 100644
--- a/lib/jit_mips-cpu.c
+++ b/lib/jit_mips-cpu.c
@@ -52,6 +52,7 @@ typedef union {
struct { jit_uint32_t _:16; jit_uint32_t b : 16; } is;
struct { jit_uint32_t _: 6; jit_uint32_t b : 26; } ii;
#endif
+ jit_uint32_t op_u32;
int op;
} jit_instr_t;
#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
@@ -712,8 +713,8 @@ static jit_word_t _bgti_u(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
static jit_word_t _bner(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
#define bnei(i0,r0,i1) _bnei(_jit,i0,r0,i1)
static jit_word_t _bnei(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
-# define jmpr(r0) _jmpr(_jit,r0)
-static void _jmpr(jit_state_t*,jit_int32_t);
+# define jmpr(r0,prev) _jmpr(_jit,r0,prev)
+static void _jmpr(jit_state_t*,jit_int32_t,jit_node_t*);
# define jmpi(i0) _jmpi(_jit,i0)
static jit_word_t _jmpi(jit_state_t*,jit_word_t);
# define boaddr(i0,r0,r1) _boaddr(_jit,i0,r0,r1)
@@ -774,9 +775,114 @@ static void _vaarg(jit_state_t*, jit_int32_t, jit_int32_t);
static void _patch_abs(jit_state_t*,jit_word_t,jit_word_t);
#define patch_at(jump,label) _patch_at(_jit,jump,label)
static void _patch_at(jit_state_t*,jit_word_t,jit_word_t);
+# define can_swap_ds(node,r0,r1) _can_swap_ds(_jit,node,r0,r1)
+static jit_bool_t _can_swap_ds(jit_state_t *_jit, jit_node_t *prev,
+ jit_uint32_t r0, jit_uint32_t r1);
#endif
#if CODE
+static jit_bool_t has_delay_slot(jit_instr_t instr)
+{
+ switch (instr.hc.b) {
+ case MIPS_SPECIAL:
+ switch (instr.tc.b) {
+ case MIPS_JR:
+ case MIPS_JALR:
+ return 1;
+ default:
+ return 0;
+ }
+ case MIPS_J: case MIPS_JAL:
+ case MIPS_BLEZ: case MIPS_BLEZL:
+ case MIPS_BEQ: case MIPS_BEQL:
+ case MIPS_BGTZ: case MIPS_BGTZL:
+ case MIPS_BNE: case MIPS_BNEL:
+ case MIPS_REGIMM:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static jit_bool_t op_writes_register(jit_instr_t instr, jit_int32_t r0)
+{
+ if (r0 == _ZERO_REGNO)
+ return 0;
+
+ switch (instr.hc.b) {
+ case MIPS_SPECIAL:
+ switch (instr.tc.b) {
+ case MIPS_JR:
+ case MIPS_SYSCALL:
+ case MIPS_BREAK:
+ case MIPS_MULT:
+ case MIPS_MULTU:
+ case MIPS_DIV:
+ case MIPS_DIVU:
+ case MIPS_MTHI:
+ case MIPS_MTLO:
+ return 0;
+ default:
+ return r0 == instr.rd.b;
+ }
+ case MIPS_SPECIAL2:
+ return r0 == instr.rd.b;
+ case MIPS_SPECIAL3:
+ switch(instr.tc.b) {
+ case MIPS_BSHFL:
+ return r0 == instr.rd.b;
+ default:
+ return r0 == instr.rt.b;
+ }
+ case MIPS_COP1:
+ if (instr.tc.b)
+ return 0;
+
+ switch (instr.rs.b) {
+ case MIPS_MF:
+ case MIPS_DMF:
+ return r0 == instr.rt.b;
+ default:
+ return 0;
+ }
+ case MIPS_ADDI:
+ case MIPS_ADDIU:
+ case MIPS_DADDI:
+ case MIPS_DADDIU:
+ case MIPS_SLTI:
+ case MIPS_SLTIU:
+ case MIPS_ANDI:
+ case MIPS_ORI:
+ case MIPS_XORI:
+ case MIPS_LUI:
+ case MIPS_LB:
+ case MIPS_LH:
+ case MIPS_LWL:
+ case MIPS_LW:
+ case MIPS_LWU:
+ case MIPS_LBU:
+ case MIPS_LHU:
+ case MIPS_LWR:
+ case MIPS_LL:
+ case MIPS_LLD:
+ case MIPS_LD:
+ case MIPS_LDC1:
+ return r0 == instr.rt.b;
+ case MIPS_JAL:
+ return r0 == 31;
+ case MIPS_REGIMM:
+ switch (instr.rt.b) {
+ case MIPS_BLTZAL: case MIPS_BLTZALL:
+ case MIPS_BGEZAL: case MIPS_BGEZALL:
+ return r0 == 31;
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
+
static void
_hrrrit(jit_state_t *_jit,jit_int32_t hc,
jit_int32_t rs, jit_int32_t rt, jit_int32_t rd,
@@ -2056,6 +2162,88 @@ _nei(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
SLTU(r0, _ZERO_REGNO, r1);
}
+static jit_bool_t _can_swap_ds(jit_state_t *_jit, jit_node_t *prev,
+ jit_uint32_t r0, jit_uint32_t r1)
+{
+ jit_int32_t offset;
+
+ if (!prev)
+ return 0;
+
+ switch (prev->code) {
+ case jit_code_ltr_f:
+ case jit_code_ler_f:
+ case jit_code_eqr_f:
+ case jit_code_ger_f:
+ case jit_code_gtr_f:
+ case jit_code_ner_f:
+ case jit_code_unltr_f:
+ case jit_code_unler_f:
+ case jit_code_uneqr_f:
+ case jit_code_unger_f:
+ case jit_code_ungtr_f:
+ case jit_code_ltgtr_f:
+ case jit_code_ordr_f:
+ case jit_code_unordr_f:
+ case jit_code_lti_f:
+ case jit_code_lei_f:
+ case jit_code_eqi_f:
+ case jit_code_gei_f:
+ case jit_code_gti_f:
+ case jit_code_nei_f:
+ case jit_code_unlti_f:
+ case jit_code_unlei_f:
+ case jit_code_uneqi_f:
+ case jit_code_ungei_f:
+ case jit_code_ungti_f:
+ case jit_code_ltgti_f:
+ case jit_code_ordi_f:
+ case jit_code_unordi_f:
+ case jit_code_ltr_d:
+ case jit_code_ler_d:
+ case jit_code_eqr_d:
+ case jit_code_ger_d:
+ case jit_code_gtr_d:
+ case jit_code_ner_d:
+ case jit_code_unltr_d:
+ case jit_code_unler_d:
+ case jit_code_uneqr_d:
+ case jit_code_unger_d:
+ case jit_code_ungtr_d:
+ case jit_code_ltgtr_d:
+ case jit_code_ordr_d:
+ case jit_code_unordr_d:
+ case jit_code_lti_d:
+ case jit_code_lei_d:
+ case jit_code_eqi_d:
+ case jit_code_gei_d:
+ case jit_code_gti_d:
+ case jit_code_nei_d:
+ case jit_code_unlti_d:
+ case jit_code_unlei_d:
+ case jit_code_uneqi_d:
+ case jit_code_ungei_d:
+ case jit_code_ungti_d:
+ case jit_code_ltgti_d:
+ case jit_code_ordi_d:
+ case jit_code_unordi_d:
+ case jit_code_casr:
+ case jit_code_casi:
+ /* These instructions will generate a branch to the next opcode.
+ * Therefore, we cannot swap the last opcode to the delay slot. */
+ return 0;
+ default:
+ break;
+ }
+
+ offset = ((jit_word_t)_jit->pc.ui - (jit_word_t)_jit->code.ptr) / sizeof(jit_instr_t);
+
+ return prev && !(prev->flag & jit_flag_patch)
+ && (offset < 2 || !has_delay_slot((jit_instr_t)*(_jit->pc.ui - 2)))
+ && (!r0 || !op_writes_register((jit_instr_t)*(_jit->pc.ui - 1), r0))
+ && (!r1 || !op_writes_register((jit_instr_t)*(_jit->pc.ui - 1), r1));
+}
+
static jit_word_t
_bltr(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
{
@@ -2441,10 +2629,20 @@ _bnei(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
}
static void
-_jmpr(jit_state_t *_jit, jit_int32_t r0)
+_jmpr(jit_state_t *_jit, jit_int32_t r0, jit_node_t *prev)
{
+ jit_int32_t op, offset;
+ jit_bool_t swap_ds;
+
+ swap_ds = can_swap_ds(prev, r0, 0);
+ if (swap_ds)
+ op = *--_jit->pc.ui;
+
JR(r0);
- NOP(1);
+ if (swap_ds)
+ ii(op);
+ else
+ NOP(1);
}
static jit_word_t
@@ -2461,7 +2659,7 @@ _jmpi(jit_state_t *_jit, jit_word_t i0)
else {
reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
movi_p(rn(reg), i0);
- jmpr(rn(reg));
+ jmpr(rn(reg), NULL);
jit_unget_reg(reg);
}
generated by cgit v1.2.3 (git 2.39.1) at 2025年09月14日 04:47:52 +0000

AltStyle によって変換されたページ (->オリジナル) /