1 // SPDX-License-Identifier: LGPL-2.1-or-later
3 * Copyright (C) 2014-2021 Paul Cercueil <paul@crapouillou.net>
6 #include "blockcache.h"
8 #include "disassembler.h"
10 #include "lightning-wrapper.h"
11 #include "optimizer.h"
17 typedef void (*lightrec_rec_func_t)(struct lightrec_cstate *, const struct block *, u16);
19 /* Forward declarations */
20 static void rec_SPECIAL(struct lightrec_cstate *state, const struct block *block, u16 offset);
21 static void rec_REGIMM(struct lightrec_cstate *state, const struct block *block, u16 offset);
22 static void rec_CP0(struct lightrec_cstate *state, const struct block *block, u16 offset);
23 static void rec_CP2(struct lightrec_cstate *state, const struct block *block, u16 offset);
25 static void unknown_opcode(struct lightrec_cstate *state, const struct block *block, u16 offset)
27 pr_warn("Unknown opcode: 0x%08x at PC 0x%08x\n",
28 block->opcode_list[offset].c.opcode,
29 block->pc + (offset << 2));
32 static void lightrec_emit_end_of_block(struct lightrec_cstate *state,
33 const struct block *block, u16 offset,
34 s8 reg_new_pc, u32 imm, u8 ra_reg,
35 u32 link, bool update_cycles)
37 struct regcache *reg_cache = state->reg_cache;
38 u32 cycles = state->cycles;
39 jit_state_t *_jit = block->_jit;
40 const struct opcode *op = &block->opcode_list[offset],
41 *next = &block->opcode_list[offset + 1];
43 jit_note(__FILE__, __LINE__);
46 /* Update the $ra register */
47 u8 link_reg = lightrec_alloc_reg_out(reg_cache, _jit, ra_reg, 0);
48 jit_movi(link_reg, link);
49 lightrec_free_reg(reg_cache, link_reg);
53 reg_new_pc = lightrec_alloc_reg(reg_cache, _jit, JIT_V0);
54 lightrec_lock_reg(reg_cache, _jit, reg_new_pc);
56 jit_movi(reg_new_pc, imm);
59 if (has_delay_slot(op->c) &&
60 !(op->flags & (LIGHTREC_NO_DS | LIGHTREC_LOCAL_BRANCH))) {
61 cycles += lightrec_cycles_of_opcode(next->c);
63 /* Recompile the delay slot */
65 lightrec_rec_opcode(state, block, offset + 1);
68 /* Store back remaining registers */
69 lightrec_storeback_regs(reg_cache, _jit);
71 jit_movr(JIT_V0, reg_new_pc);
73 if (cycles && update_cycles) {
74 jit_subi(LIGHTREC_REG_CYCLE, LIGHTREC_REG_CYCLE, cycles);
75 pr_debug("EOB: %u cycles\n", cycles);
78 if (offset + !!(op->flags & LIGHTREC_NO_DS) < block->nb_ops - 1)
79 state->branches[state->nb_branches++] = jit_jmpi();
82 void lightrec_emit_eob(struct lightrec_cstate *state, const struct block *block,
83 u16 offset, bool after_op)
85 struct regcache *reg_cache = state->reg_cache;
86 jit_state_t *_jit = block->_jit;
87 union code c = block->opcode_list[offset].c;
88 u32 cycles = state->cycles;
91 cycles -= lightrec_cycles_of_opcode(c);
93 lightrec_storeback_regs(reg_cache, _jit);
95 jit_movi(JIT_V0, block->pc + (offset << 2));
96 jit_subi(LIGHTREC_REG_CYCLE, LIGHTREC_REG_CYCLE, cycles);
98 state->branches[state->nb_branches++] = jit_jmpi();
101 static u8 get_jr_jalr_reg(struct lightrec_cstate *state, const struct block *block, u16 offset)
103 struct regcache *reg_cache = state->reg_cache;
104 jit_state_t *_jit = block->_jit;
105 const struct opcode *op = &block->opcode_list[offset],
106 *next = &block->opcode_list[offset + 1];
107 u8 rs = lightrec_request_reg_in(reg_cache, _jit, op->r.rs, JIT_V0);
109 /* If the source register is already mapped to JIT_R0 or JIT_R1, and the
110 * delay slot is a I/O operation, unload the register, since JIT_R0 and
111 * JIT_R1 are explicitely used by the I/O opcode generators. */
112 if ((rs == JIT_R0 || rs == JIT_R1) &&
113 !(op->flags & LIGHTREC_NO_DS) &&
114 opcode_is_io(next->c) &&
115 !(next->flags & (LIGHTREC_NO_INVALIDATE | LIGHTREC_DIRECT_IO))) {
116 lightrec_unload_reg(reg_cache, _jit, rs);
117 lightrec_free_reg(reg_cache, rs);
119 rs = lightrec_request_reg_in(reg_cache, _jit, op->r.rs, JIT_V0);
122 lightrec_lock_reg(reg_cache, _jit, rs);
127 static void rec_special_JR(struct lightrec_cstate *state, const struct block *block, u16 offset)
129 u8 rs = get_jr_jalr_reg(state, block, offset);
131 _jit_name(block->_jit, __func__);
132 lightrec_emit_end_of_block(state, block, offset, rs, 0, 31, 0, true);
135 static void rec_special_JALR(struct lightrec_cstate *state, const struct block *block, u16 offset)
137 u8 rs = get_jr_jalr_reg(state, block, offset);
138 union code c = block->opcode_list[offset].c;
140 _jit_name(block->_jit, __func__);
141 lightrec_emit_end_of_block(state, block, offset, rs, 0, c.r.rd,
142 get_branch_pc(block, offset, 2), true);
145 static void rec_J(struct lightrec_cstate *state, const struct block *block, u16 offset)
147 union code c = block->opcode_list[offset].c;
149 _jit_name(block->_jit, __func__);
150 lightrec_emit_end_of_block(state, block, offset, -1,
151 (block->pc & 0xf0000000) | (c.j.imm << 2),
155 static void rec_JAL(struct lightrec_cstate *state, const struct block *block, u16 offset)
157 union code c = block->opcode_list[offset].c;
159 _jit_name(block->_jit, __func__);
160 lightrec_emit_end_of_block(state, block, offset, -1,
161 (block->pc & 0xf0000000) | (c.j.imm << 2),
162 31, get_branch_pc(block, offset, 2), true);
165 static void rec_b(struct lightrec_cstate *state, const struct block *block, u16 offset,
166 jit_code_t code, u32 link, bool unconditional, bool bz)
168 struct regcache *reg_cache = state->reg_cache;
169 struct native_register *regs_backup;
170 jit_state_t *_jit = block->_jit;
171 struct lightrec_branch *branch;
172 const struct opcode *op = &block->opcode_list[offset],
173 *next = &block->opcode_list[offset + 1];
176 u32 target_offset, cycles = state->cycles;
177 bool is_forward = (s16)op->i.imm >= -1;
180 jit_note(__FILE__, __LINE__);
182 if (!(op->flags & LIGHTREC_NO_DS))
183 cycles += lightrec_cycles_of_opcode(next->c);
188 jit_subi(LIGHTREC_REG_CYCLE, LIGHTREC_REG_CYCLE, cycles);
190 if (!unconditional) {
191 u8 rs = lightrec_alloc_reg_in(reg_cache, _jit, op->i.rs, REG_EXT),
192 rt = bz ? 0 : lightrec_alloc_reg_in(reg_cache,
193 _jit, op->i.rt, REG_EXT);
195 /* Generate the branch opcode */
196 addr = jit_new_node_pww(code, NULL, rs, rt);
198 lightrec_free_regs(reg_cache);
199 regs_backup = lightrec_regcache_enter_branch(reg_cache);
202 if (op->flags & LIGHTREC_LOCAL_BRANCH) {
203 if (next && !(op->flags & LIGHTREC_NO_DS)) {
204 /* Recompile the delay slot */
206 lightrec_rec_opcode(state, block, offset + 1);
210 /* Update the $ra register */
211 link_reg = lightrec_alloc_reg_out(reg_cache, _jit, 31, 0);
212 jit_movi(link_reg, link);
213 lightrec_free_reg(reg_cache, link_reg);
216 /* Store back remaining registers */
217 lightrec_storeback_regs(reg_cache, _jit);
219 target_offset = offset + 1 + (s16)op->i.imm
220 - !!(OPT_SWITCH_DELAY_SLOTS && (op->flags & LIGHTREC_NO_DS));
221 pr_debug("Adding local branch to offset 0x%x\n",
223 branch = &state->local_branches[
224 state->nb_local_branches++];
226 branch->target = target_offset;
228 branch->branch = jit_jmpi();
230 branch->branch = jit_bgti(LIGHTREC_REG_CYCLE, 0);
233 if (!(op->flags & LIGHTREC_LOCAL_BRANCH) || !is_forward) {
234 next_pc = get_branch_pc(block, offset, 1 + (s16)op->i.imm);
235 lightrec_emit_end_of_block(state, block, offset, -1, next_pc,
239 if (!unconditional) {
241 lightrec_regcache_leave_branch(reg_cache, regs_backup);
244 /* Update the $ra register */
245 link_reg = lightrec_alloc_reg_out(reg_cache, _jit,
247 jit_movi(link_reg, (s32)link);
248 lightrec_free_reg(reg_cache, link_reg);
251 if (!(op->flags & LIGHTREC_NO_DS) && next->opcode)
252 lightrec_rec_opcode(state, block, offset + 1);
256 static void rec_BNE(struct lightrec_cstate *state,
257 const struct block *block, u16 offset)
259 union code c = block->opcode_list[offset].c;
261 _jit_name(block->_jit, __func__);
264 rec_b(state, block, offset, jit_code_beqi, 0, false, true);
266 rec_b(state, block, offset, jit_code_beqr, 0, false, false);
269 static void rec_BEQ(struct lightrec_cstate *state,
270 const struct block *block, u16 offset)
272 union code c = block->opcode_list[offset].c;
274 _jit_name(block->_jit, __func__);
277 rec_b(state, block, offset, jit_code_bnei, 0, c.i.rs == 0, true);
279 rec_b(state, block, offset, jit_code_bner, 0, c.i.rs == c.i.rt, false);
282 static void rec_BLEZ(struct lightrec_cstate *state,
283 const struct block *block, u16 offset)
285 union code c = block->opcode_list[offset].c;
287 _jit_name(block->_jit, __func__);
288 rec_b(state, block, offset, jit_code_bgti, 0, c.i.rs == 0, true);
291 static void rec_BGTZ(struct lightrec_cstate *state,
292 const struct block *block, u16 offset)
294 _jit_name(block->_jit, __func__);
295 rec_b(state, block, offset, jit_code_blei, 0, false, true);
298 static void rec_regimm_BLTZ(struct lightrec_cstate *state,
299 const struct block *block, u16 offset)
301 _jit_name(block->_jit, __func__);
302 rec_b(state, block, offset, jit_code_bgei, 0, false, true);
305 static void rec_regimm_BLTZAL(struct lightrec_cstate *state,
306 const struct block *block, u16 offset)
308 _jit_name(block->_jit, __func__);
309 rec_b(state, block, offset, jit_code_bgei,
310 get_branch_pc(block, offset, 2), false, true);
313 static void rec_regimm_BGEZ(struct lightrec_cstate *state,
314 const struct block *block, u16 offset)
316 union code c = block->opcode_list[offset].c;
318 _jit_name(block->_jit, __func__);
319 rec_b(state, block, offset, jit_code_blti, 0, !c.i.rs, true);
322 static void rec_regimm_BGEZAL(struct lightrec_cstate *state,
323 const struct block *block, u16 offset)
325 const struct opcode *op = &block->opcode_list[offset];
326 _jit_name(block->_jit, __func__);
327 rec_b(state, block, offset, jit_code_blti,
328 get_branch_pc(block, offset, 2),
332 static void rec_alu_imm(struct lightrec_cstate *state, const struct block *block,
333 u16 offset, jit_code_t code, bool slti)
335 struct regcache *reg_cache = state->reg_cache;
336 union code c = block->opcode_list[offset].c;
337 jit_state_t *_jit = block->_jit;
338 u8 rs, rt, out_flags = REG_EXT;
341 out_flags |= REG_ZEXT;
343 jit_note(__FILE__, __LINE__);
344 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.i.rs, REG_EXT);
345 rt = lightrec_alloc_reg_out(reg_cache, _jit, c.i.rt, out_flags);
347 jit_new_node_www(code, rt, rs, (s32)(s16) c.i.imm);
349 lightrec_free_reg(reg_cache, rs);
350 lightrec_free_reg(reg_cache, rt);
353 static void rec_alu_special(struct lightrec_cstate *state, const struct block *block,
354 u16 offset, jit_code_t code, bool out_ext)
356 struct regcache *reg_cache = state->reg_cache;
357 union code c = block->opcode_list[offset].c;
358 jit_state_t *_jit = block->_jit;
361 jit_note(__FILE__, __LINE__);
362 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rs, REG_EXT);
363 rt = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rt, REG_EXT);
364 rd = lightrec_alloc_reg_out(reg_cache, _jit, c.r.rd,
365 out_ext ? REG_EXT | REG_ZEXT : 0);
367 jit_new_node_www(code, rd, rs, rt);
369 lightrec_free_reg(reg_cache, rs);
370 lightrec_free_reg(reg_cache, rt);
371 lightrec_free_reg(reg_cache, rd);
374 static void rec_alu_shiftv(struct lightrec_cstate *state, const struct block *block,
375 u16 offset, jit_code_t code)
377 struct regcache *reg_cache = state->reg_cache;
378 union code c = block->opcode_list[offset].c;
379 jit_state_t *_jit = block->_jit;
380 u8 rd, rt, rs, temp, flags = 0;
382 jit_note(__FILE__, __LINE__);
383 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rs, 0);
385 if (code == jit_code_rshr)
387 else if (code == jit_code_rshr_u)
390 rt = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rt, flags);
391 rd = lightrec_alloc_reg_out(reg_cache, _jit, c.r.rd, flags);
393 if (rs != rd && rt != rd) {
394 jit_andi(rd, rs, 0x1f);
395 jit_new_node_www(code, rd, rt, rd);
397 temp = lightrec_alloc_reg_temp(reg_cache, _jit);
398 jit_andi(temp, rs, 0x1f);
399 jit_new_node_www(code, rd, rt, temp);
400 lightrec_free_reg(reg_cache, temp);
403 lightrec_free_reg(reg_cache, rs);
404 lightrec_free_reg(reg_cache, rt);
405 lightrec_free_reg(reg_cache, rd);
408 static void rec_ADDIU(struct lightrec_cstate *state,
409 const struct block *block, u16 offset)
411 _jit_name(block->_jit, __func__);
412 rec_alu_imm(state, block, offset, jit_code_addi, false);
415 static void rec_ADDI(struct lightrec_cstate *state,
416 const struct block *block, u16 offset)
418 /* TODO: Handle the exception? */
419 _jit_name(block->_jit, __func__);
420 rec_alu_imm(state, block, offset, jit_code_addi, false);
423 static void rec_SLTIU(struct lightrec_cstate *state,
424 const struct block *block, u16 offset)
426 _jit_name(block->_jit, __func__);
427 rec_alu_imm(state, block, offset, jit_code_lti_u, true);
430 static void rec_SLTI(struct lightrec_cstate *state,
431 const struct block *block, u16 offset)
433 _jit_name(block->_jit, __func__);
434 rec_alu_imm(state, block, offset, jit_code_lti, true);
437 static void rec_ANDI(struct lightrec_cstate *state,
438 const struct block *block, u16 offset)
440 struct regcache *reg_cache = state->reg_cache;
441 union code c = block->opcode_list[offset].c;
442 jit_state_t *_jit = block->_jit;
445 _jit_name(block->_jit, __func__);
446 jit_note(__FILE__, __LINE__);
447 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.i.rs, 0);
448 rt = lightrec_alloc_reg_out(reg_cache, _jit, c.i.rt,
451 /* PSX code uses ANDI 0xff / ANDI 0xffff a lot, which are basically
452 * casts to uint8_t / uint16_t. */
455 else if (c.i.imm == 0xffff)
458 jit_andi(rt, rs, (u32)(u16) c.i.imm);
460 lightrec_free_reg(reg_cache, rs);
461 lightrec_free_reg(reg_cache, rt);
464 static void rec_alu_or_xor(struct lightrec_cstate *state, const struct block *block,
465 u16 offset, jit_code_t code)
467 struct regcache *reg_cache = state->reg_cache;
468 union code c = block->opcode_list[offset].c;
469 jit_state_t *_jit = block->_jit;
472 jit_note(__FILE__, __LINE__);
473 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.i.rs, 0);
474 rt = lightrec_alloc_reg_out(reg_cache, _jit, c.i.rt, 0);
476 flags = lightrec_get_reg_in_flags(reg_cache, rs);
477 lightrec_set_reg_out_flags(reg_cache, rt, flags);
479 jit_new_node_www(code, rt, rs, (u32)(u16) c.i.imm);
481 lightrec_free_reg(reg_cache, rs);
482 lightrec_free_reg(reg_cache, rt);
486 static void rec_ORI(struct lightrec_cstate *state,
487 const struct block *block, u16 offset)
489 _jit_name(block->_jit, __func__);
490 rec_alu_or_xor(state, block, offset, jit_code_ori);
493 static void rec_XORI(struct lightrec_cstate *state,
494 const struct block *block, u16 offset)
496 _jit_name(block->_jit, __func__);
497 rec_alu_or_xor(state, block, offset, jit_code_xori);
500 static void rec_LUI(struct lightrec_cstate *state,
501 const struct block *block, u16 offset)
503 struct regcache *reg_cache = state->reg_cache;
504 union code c = block->opcode_list[offset].c;
505 jit_state_t *_jit = block->_jit;
506 u8 rt, flags = REG_EXT;
509 jit_note(__FILE__, __LINE__);
511 if (!(c.i.imm & BIT(15)))
514 rt = lightrec_alloc_reg_out(reg_cache, _jit, c.i.rt, flags);
516 jit_movi(rt, (s32)(c.i.imm << 16));
518 lightrec_free_reg(reg_cache, rt);
521 static void rec_special_ADDU(struct lightrec_cstate *state,
522 const struct block *block, u16 offset)
524 _jit_name(block->_jit, __func__);
525 rec_alu_special(state, block, offset, jit_code_addr, false);
528 static void rec_special_ADD(struct lightrec_cstate *state,
529 const struct block *block, u16 offset)
531 /* TODO: Handle the exception? */
532 _jit_name(block->_jit, __func__);
533 rec_alu_special(state, block, offset, jit_code_addr, false);
536 static void rec_special_SUBU(struct lightrec_cstate *state,
537 const struct block *block, u16 offset)
539 _jit_name(block->_jit, __func__);
540 rec_alu_special(state, block, offset, jit_code_subr, false);
543 static void rec_special_SUB(struct lightrec_cstate *state,
544 const struct block *block, u16 offset)
546 /* TODO: Handle the exception? */
547 _jit_name(block->_jit, __func__);
548 rec_alu_special(state, block, offset, jit_code_subr, false);
551 static void rec_special_AND(struct lightrec_cstate *state,
552 const struct block *block, u16 offset)
554 struct regcache *reg_cache = state->reg_cache;
555 union code c = block->opcode_list[offset].c;
556 jit_state_t *_jit = block->_jit;
557 u8 rd, rt, rs, flags_rs, flags_rt, flags_rd;
559 _jit_name(block->_jit, __func__);
560 jit_note(__FILE__, __LINE__);
561 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rs, 0);
562 rt = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rt, 0);
563 rd = lightrec_alloc_reg_out(reg_cache, _jit, c.r.rd, 0);
565 flags_rs = lightrec_get_reg_in_flags(reg_cache, rs);
566 flags_rt = lightrec_get_reg_in_flags(reg_cache, rt);
568 /* Z(rd) = Z(rs) | Z(rt) */
569 flags_rd = REG_ZEXT & (flags_rs | flags_rt);
571 /* E(rd) = (E(rt) & Z(rt)) | (E(rs) & Z(rs)) | (E(rs) & E(rt)) */
572 if (((flags_rs & REG_EXT) && (flags_rt & REG_ZEXT)) ||
573 ((flags_rt & REG_EXT) && (flags_rs & REG_ZEXT)) ||
574 (REG_EXT & flags_rs & flags_rt))
577 lightrec_set_reg_out_flags(reg_cache, rd, flags_rd);
579 jit_andr(rd, rs, rt);
581 lightrec_free_reg(reg_cache, rs);
582 lightrec_free_reg(reg_cache, rt);
583 lightrec_free_reg(reg_cache, rd);
586 static void rec_special_or_nor(struct lightrec_cstate *state,
587 const struct block *block, u16 offset, bool nor)
589 struct regcache *reg_cache = state->reg_cache;
590 union code c = block->opcode_list[offset].c;
591 jit_state_t *_jit = block->_jit;
592 u8 rd, rt, rs, flags_rs, flags_rt, flags_rd = 0;
594 jit_note(__FILE__, __LINE__);
595 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rs, 0);
596 rt = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rt, 0);
597 rd = lightrec_alloc_reg_out(reg_cache, _jit, c.r.rd, 0);
599 flags_rs = lightrec_get_reg_in_flags(reg_cache, rs);
600 flags_rt = lightrec_get_reg_in_flags(reg_cache, rt);
602 /* or: Z(rd) = Z(rs) & Z(rt)
605 flags_rd = REG_ZEXT & flags_rs & flags_rt;
607 /* E(rd) = (E(rs) & E(rt)) | (E(rt) & !Z(rt)) | (E(rs) & !Z(rs)) */
608 if ((REG_EXT & flags_rs & flags_rt) ||
609 (flags_rt & (REG_EXT | REG_ZEXT) == REG_EXT) ||
610 (flags_rs & (REG_EXT | REG_ZEXT) == REG_EXT))
613 lightrec_set_reg_out_flags(reg_cache, rd, flags_rd);
620 lightrec_free_reg(reg_cache, rs);
621 lightrec_free_reg(reg_cache, rt);
622 lightrec_free_reg(reg_cache, rd);
625 static void rec_special_OR(struct lightrec_cstate *state,
626 const struct block *block, u16 offset)
628 _jit_name(block->_jit, __func__);
629 rec_special_or_nor(state, block, offset, false);
632 static void rec_special_NOR(struct lightrec_cstate *state,
633 const struct block *block, u16 offset)
635 _jit_name(block->_jit, __func__);
636 rec_special_or_nor(state, block, offset, true);
639 static void rec_special_XOR(struct lightrec_cstate *state,
640 const struct block *block, u16 offset)
642 struct regcache *reg_cache = state->reg_cache;
643 union code c = block->opcode_list[offset].c;
644 jit_state_t *_jit = block->_jit;
645 u8 rd, rt, rs, flags_rs, flags_rt, flags_rd;
647 _jit_name(block->_jit, __func__);
649 jit_note(__FILE__, __LINE__);
650 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rs, 0);
651 rt = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rt, 0);
652 rd = lightrec_alloc_reg_out(reg_cache, _jit, c.r.rd, 0);
654 flags_rs = lightrec_get_reg_in_flags(reg_cache, rs);
655 flags_rt = lightrec_get_reg_in_flags(reg_cache, rt);
657 /* Z(rd) = Z(rs) & Z(rt) */
658 flags_rd = REG_ZEXT & flags_rs & flags_rt;
660 /* E(rd) = E(rs) & E(rt) */
661 flags_rd |= REG_EXT & flags_rs & flags_rt;
663 lightrec_set_reg_out_flags(reg_cache, rd, flags_rd);
665 jit_xorr(rd, rs, rt);
667 lightrec_free_reg(reg_cache, rs);
668 lightrec_free_reg(reg_cache, rt);
669 lightrec_free_reg(reg_cache, rd);
672 static void rec_special_SLTU(struct lightrec_cstate *state,
673 const struct block *block, u16 offset)
675 _jit_name(block->_jit, __func__);
676 rec_alu_special(state, block, offset, jit_code_ltr_u, true);
679 static void rec_special_SLT(struct lightrec_cstate *state,
680 const struct block *block, u16 offset)
682 _jit_name(block->_jit, __func__);
683 rec_alu_special(state, block, offset, jit_code_ltr, true);
686 static void rec_special_SLLV(struct lightrec_cstate *state,
687 const struct block *block, u16 offset)
689 _jit_name(block->_jit, __func__);
690 rec_alu_shiftv(state, block, offset, jit_code_lshr);
693 static void rec_special_SRLV(struct lightrec_cstate *state,
694 const struct block *block, u16 offset)
696 _jit_name(block->_jit, __func__);
697 rec_alu_shiftv(state, block, offset, jit_code_rshr_u);
700 static void rec_special_SRAV(struct lightrec_cstate *state,
701 const struct block *block, u16 offset)
703 _jit_name(block->_jit, __func__);
704 rec_alu_shiftv(state, block, offset, jit_code_rshr);
707 static void rec_alu_shift(struct lightrec_cstate *state, const struct block *block,
708 u16 offset, jit_code_t code)
710 struct regcache *reg_cache = state->reg_cache;
711 union code c = block->opcode_list[offset].c;
712 jit_state_t *_jit = block->_jit;
713 u8 rd, rt, flags = 0;
715 jit_note(__FILE__, __LINE__);
717 if (code == jit_code_rshi)
719 else if (code == jit_code_rshi_u)
722 rt = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rt, flags);
724 /* Input reg is zero-extended, if we SRL at least by one bit, we know
725 * the output reg will be both zero-extended and sign-extended. */
726 if (code == jit_code_rshi_u && c.r.imm)
728 rd = lightrec_alloc_reg_out(reg_cache, _jit, c.r.rd, flags);
730 jit_new_node_www(code, rd, rt, c.r.imm);
732 lightrec_free_reg(reg_cache, rt);
733 lightrec_free_reg(reg_cache, rd);
736 static void rec_special_SLL(struct lightrec_cstate *state,
737 const struct block *block, u16 offset)
739 _jit_name(block->_jit, __func__);
740 rec_alu_shift(state, block, offset, jit_code_lshi);
743 static void rec_special_SRL(struct lightrec_cstate *state,
744 const struct block *block, u16 offset)
746 _jit_name(block->_jit, __func__);
747 rec_alu_shift(state, block, offset, jit_code_rshi_u);
750 static void rec_special_SRA(struct lightrec_cstate *state,
751 const struct block *block, u16 offset)
753 _jit_name(block->_jit, __func__);
754 rec_alu_shift(state, block, offset, jit_code_rshi);
757 static void rec_alu_mult(struct lightrec_cstate *state,
758 const struct block *block, u16 offset, bool is_signed)
760 struct regcache *reg_cache = state->reg_cache;
761 union code c = block->opcode_list[offset].c;
762 u16 flags = block->opcode_list[offset].flags;
763 u8 reg_lo = get_mult_div_lo(c);
764 u8 reg_hi = get_mult_div_hi(c);
765 jit_state_t *_jit = block->_jit;
766 u8 lo, hi, rs, rt, rflags = 0;
768 jit_note(__FILE__, __LINE__);
775 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rs, rflags);
776 rt = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rt, rflags);
778 if (!(flags & LIGHTREC_NO_LO))
779 lo = lightrec_alloc_reg_out(reg_cache, _jit, reg_lo, 0);
780 else if (__WORDSIZE == 32)
781 lo = lightrec_alloc_reg_temp(reg_cache, _jit);
783 if (!(flags & LIGHTREC_NO_HI))
784 hi = lightrec_alloc_reg_out(reg_cache, _jit, reg_hi, REG_EXT);
786 if (__WORDSIZE == 32) {
787 /* On 32-bit systems, do a 32*32->64 bit operation, or a 32*32->32 bit
788 * operation if the MULT was detected a 32-bit only. */
789 if (!(flags & LIGHTREC_NO_HI)) {
791 jit_qmulr(lo, hi, rs, rt);
793 jit_qmulr_u(lo, hi, rs, rt);
795 jit_mulr(lo, rs, rt);
798 /* On 64-bit systems, do a 64*64->64 bit operation. */
799 if (flags & LIGHTREC_NO_LO) {
800 jit_mulr(hi, rs, rt);
801 jit_rshi(hi, hi, 32);
803 jit_mulr(lo, rs, rt);
805 /* The 64-bit output value is in $lo, store the upper 32 bits in $hi */
806 if (!(flags & LIGHTREC_NO_HI))
807 jit_rshi(hi, lo, 32);
811 lightrec_free_reg(reg_cache, rs);
812 lightrec_free_reg(reg_cache, rt);
813 if (!(flags & LIGHTREC_NO_LO) || __WORDSIZE == 32)
814 lightrec_free_reg(reg_cache, lo);
815 if (!(flags & LIGHTREC_NO_HI))
816 lightrec_free_reg(reg_cache, hi);
819 static void rec_alu_div(struct lightrec_cstate *state,
820 const struct block *block, u16 offset, bool is_signed)
822 struct regcache *reg_cache = state->reg_cache;
823 union code c = block->opcode_list[offset].c;
824 u16 flags = block->opcode_list[offset].flags;
825 bool no_check = flags & LIGHTREC_NO_DIV_CHECK;
826 u8 reg_lo = get_mult_div_lo(c);
827 u8 reg_hi = get_mult_div_hi(c);
828 jit_state_t *_jit = block->_jit;
829 jit_node_t *branch, *to_end;
830 u8 lo = 0, hi = 0, rs, rt, rflags = 0;
832 jit_note(__FILE__, __LINE__);
839 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rs, rflags);
840 rt = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rt, rflags);
842 if (!(flags & LIGHTREC_NO_LO))
843 lo = lightrec_alloc_reg_out(reg_cache, _jit, reg_lo, 0);
845 if (!(flags & LIGHTREC_NO_HI))
846 hi = lightrec_alloc_reg_out(reg_cache, _jit, reg_hi, 0);
848 /* Jump to special handler if dividing by zero */
850 branch = jit_beqi(rt, 0);
852 if (flags & LIGHTREC_NO_LO) {
854 jit_remr(hi, rs, rt);
856 jit_remr_u(hi, rs, rt);
857 } else if (flags & LIGHTREC_NO_HI) {
859 jit_divr(lo, rs, rt);
861 jit_divr_u(lo, rs, rt);
864 jit_qdivr(lo, hi, rs, rt);
866 jit_qdivr_u(lo, hi, rs, rt);
870 lightrec_regcache_mark_live(reg_cache, _jit);
872 /* Jump above the div-by-zero handler */
877 if (!(flags & LIGHTREC_NO_LO)) {
883 jit_movi(lo, 0xffffffff);
887 if (!(flags & LIGHTREC_NO_HI))
893 lightrec_free_reg(reg_cache, rs);
894 lightrec_free_reg(reg_cache, rt);
896 if (!(flags & LIGHTREC_NO_LO))
897 lightrec_free_reg(reg_cache, lo);
899 if (!(flags & LIGHTREC_NO_HI))
900 lightrec_free_reg(reg_cache, hi);
903 static void rec_special_MULT(struct lightrec_cstate *state,
904 const struct block *block, u16 offset)
906 _jit_name(block->_jit, __func__);
907 rec_alu_mult(state, block, offset, true);
910 static void rec_special_MULTU(struct lightrec_cstate *state,
911 const struct block *block, u16 offset)
913 _jit_name(block->_jit, __func__);
914 rec_alu_mult(state, block, offset, false);
917 static void rec_special_DIV(struct lightrec_cstate *state,
918 const struct block *block, u16 offset)
920 _jit_name(block->_jit, __func__);
921 rec_alu_div(state, block, offset, true);
924 static void rec_special_DIVU(struct lightrec_cstate *state,
925 const struct block *block, u16 offset)
927 _jit_name(block->_jit, __func__);
928 rec_alu_div(state, block, offset, false);
931 static void rec_alu_mv_lo_hi(struct lightrec_cstate *state,
932 const struct block *block, u8 dst, u8 src)
934 struct regcache *reg_cache = state->reg_cache;
935 jit_state_t *_jit = block->_jit;
937 jit_note(__FILE__, __LINE__);
938 src = lightrec_alloc_reg_in(reg_cache, _jit, src, 0);
939 dst = lightrec_alloc_reg_out(reg_cache, _jit, dst, REG_EXT);
941 jit_extr_i(dst, src);
943 lightrec_free_reg(reg_cache, src);
944 lightrec_free_reg(reg_cache, dst);
947 static void rec_special_MFHI(struct lightrec_cstate *state,
948 const struct block *block, u16 offset)
950 union code c = block->opcode_list[offset].c;
952 _jit_name(block->_jit, __func__);
953 rec_alu_mv_lo_hi(state, block, c.r.rd, REG_HI);
956 static void rec_special_MTHI(struct lightrec_cstate *state,
957 const struct block *block, u16 offset)
959 union code c = block->opcode_list[offset].c;
961 _jit_name(block->_jit, __func__);
962 rec_alu_mv_lo_hi(state, block, REG_HI, c.r.rs);
965 static void rec_special_MFLO(struct lightrec_cstate *state,
966 const struct block *block, u16 offset)
968 union code c = block->opcode_list[offset].c;
970 _jit_name(block->_jit, __func__);
971 rec_alu_mv_lo_hi(state, block, c.r.rd, REG_LO);
974 static void rec_special_MTLO(struct lightrec_cstate *state,
975 const struct block *block, u16 offset)
977 union code c = block->opcode_list[offset].c;
979 _jit_name(block->_jit, __func__);
980 rec_alu_mv_lo_hi(state, block, REG_LO, c.r.rs);
983 static void call_to_c_wrapper(struct lightrec_cstate *state, const struct block *block,
984 u32 arg, bool with_arg, enum c_wrappers wrapper)
986 struct regcache *reg_cache = state->reg_cache;
987 jit_state_t *_jit = block->_jit;
991 tmp3 = lightrec_alloc_reg(reg_cache, _jit, JIT_R1);
992 tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
994 jit_ldxi(tmp, LIGHTREC_REG_STATE,
995 offsetof(struct lightrec_state, wrappers_eps[wrapper]));
1001 lightrec_free_reg(reg_cache, tmp);
1003 lightrec_free_reg(reg_cache, tmp3);
1004 lightrec_regcache_mark_live(reg_cache, _jit);
1007 static void rec_io(struct lightrec_cstate *state,
1008 const struct block *block, u16 offset,
1009 bool load_rt, bool read_rt)
1011 struct regcache *reg_cache = state->reg_cache;
1012 jit_state_t *_jit = block->_jit;
1013 union code c = block->opcode_list[offset].c;
1014 u16 flags = block->opcode_list[offset].flags;
1015 bool is_tagged = flags & (LIGHTREC_HW_IO | LIGHTREC_DIRECT_IO);
1018 jit_note(__FILE__, __LINE__);
1020 lightrec_clean_reg_if_loaded(reg_cache, _jit, c.i.rs, false);
1022 if (read_rt && likely(c.i.rt))
1023 lightrec_clean_reg_if_loaded(reg_cache, _jit, c.i.rt, true);
1025 lightrec_clean_reg_if_loaded(reg_cache, _jit, c.i.rt, false);
1028 call_to_c_wrapper(state, block, c.opcode, true, C_WRAPPER_RW);
1030 lut_entry = lightrec_get_lut_entry(block);
1031 call_to_c_wrapper(state, block, (lut_entry << 16) | offset,
1032 true, C_WRAPPER_RW_GENERIC);
1036 static void rec_store_direct_no_invalidate(struct lightrec_cstate *cstate,
1037 const struct block *block,
1038 u16 offset, jit_code_t code)
1040 struct lightrec_state *state = cstate->state;
1041 struct regcache *reg_cache = cstate->reg_cache;
1042 union code c = block->opcode_list[offset].c;
1043 jit_state_t *_jit = block->_jit;
1044 jit_node_t *to_not_ram, *to_end;
1045 u8 tmp, tmp2, rs, rt;
1048 jit_note(__FILE__, __LINE__);
1049 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.i.rs, 0);
1050 tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
1052 if (state->offset_ram || state->offset_scratch)
1053 tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit);
1055 /* Convert to KUNSEG and avoid RAM mirrors */
1056 if (state->mirrors_mapped) {
1058 jit_andi(tmp, rs, 0x1f800000 | (4 * RAM_SIZE - 1));
1059 } else if (c.i.imm) {
1061 jit_addi(tmp, rs, (s16)c.i.imm);
1062 jit_andi(tmp, tmp, 0x1f800000 | (RAM_SIZE - 1));
1065 jit_andi(tmp, rs, 0x1f800000 | (RAM_SIZE - 1));
1068 lightrec_free_reg(reg_cache, rs);
1070 if (state->offset_ram != state->offset_scratch) {
1071 to_not_ram = jit_bmsi(tmp, BIT(28));
1073 lightrec_regcache_mark_live(reg_cache, _jit);
1075 jit_movi(tmp2, state->offset_ram);
1077 to_end = jit_jmpi();
1078 jit_patch(to_not_ram);
1080 jit_movi(tmp2, state->offset_scratch);
1082 } else if (state->offset_ram) {
1083 jit_movi(tmp2, state->offset_ram);
1086 if (state->offset_ram || state->offset_scratch) {
1087 jit_addr(tmp, tmp, tmp2);
1088 lightrec_free_reg(reg_cache, tmp2);
1091 rt = lightrec_alloc_reg_in(reg_cache, _jit, c.i.rt, 0);
1092 jit_new_node_www(code, imm, tmp, rt);
1094 lightrec_free_reg(reg_cache, rt);
1095 lightrec_free_reg(reg_cache, tmp);
1098 static void rec_store_direct(struct lightrec_cstate *cstate, const struct block *block,
1099 u16 offset, jit_code_t code)
1101 struct lightrec_state *state = cstate->state;
1102 u32 ram_size = state->mirrors_mapped ? RAM_SIZE * 4 : RAM_SIZE;
1103 struct regcache *reg_cache = cstate->reg_cache;
1104 union code c = block->opcode_list[offset].c;
1105 jit_state_t *_jit = block->_jit;
1106 jit_node_t *to_not_ram, *to_end;
1107 u8 tmp, tmp2, tmp3, rs, rt;
1109 jit_note(__FILE__, __LINE__);
1111 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.i.rs, 0);
1112 tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit);
1113 tmp3 = lightrec_alloc_reg_in(reg_cache, _jit, 0, 0);
1115 /* Convert to KUNSEG and avoid RAM mirrors */
1117 jit_addi(tmp2, rs, (s16)c.i.imm);
1118 jit_andi(tmp2, tmp2, 0x1f800000 | (ram_size - 1));
1120 jit_andi(tmp2, rs, 0x1f800000 | (ram_size - 1));
1123 lightrec_free_reg(reg_cache, rs);
1124 tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
1126 to_not_ram = jit_bgti(tmp2, ram_size);
1128 lightrec_regcache_mark_live(reg_cache, _jit);
1130 /* Compute the offset to the code LUT */
1131 jit_andi(tmp, tmp2, (RAM_SIZE - 1) & ~3);
1132 if (__WORDSIZE == 64)
1133 jit_lshi(tmp, tmp, 1);
1134 jit_addr(tmp, LIGHTREC_REG_STATE, tmp);
1136 /* Write NULL to the code LUT to invalidate any block that's there */
1137 jit_stxi(offsetof(struct lightrec_state, code_lut), tmp, tmp3);
1139 if (state->offset_ram != state->offset_scratch) {
1140 jit_movi(tmp, state->offset_ram);
1142 to_end = jit_jmpi();
1145 jit_patch(to_not_ram);
1147 if (state->offset_ram || state->offset_scratch)
1148 jit_movi(tmp, state->offset_scratch);
1150 if (state->offset_ram != state->offset_scratch)
1153 if (state->offset_ram || state->offset_scratch)
1154 jit_addr(tmp2, tmp2, tmp);
1156 lightrec_free_reg(reg_cache, tmp);
1157 lightrec_free_reg(reg_cache, tmp3);
1159 rt = lightrec_alloc_reg_in(reg_cache, _jit, c.i.rt, 0);
1160 jit_new_node_www(code, 0, tmp2, rt);
1162 lightrec_free_reg(reg_cache, rt);
1163 lightrec_free_reg(reg_cache, tmp2);
1166 static void rec_store(struct lightrec_cstate *state,
1167 const struct block *block, u16 offset, jit_code_t code)
1169 u16 flags = block->opcode_list[offset].flags;
1171 if (flags & LIGHTREC_NO_INVALIDATE) {
1172 rec_store_direct_no_invalidate(state, block, offset, code);
1173 } else if (flags & LIGHTREC_DIRECT_IO) {
1174 if (state->state->invalidate_from_dma_only)
1175 rec_store_direct_no_invalidate(state, block, offset, code);
1177 rec_store_direct(state, block, offset, code);
1179 rec_io(state, block, offset, true, false);
1183 static void rec_SB(struct lightrec_cstate *state,
1184 const struct block *block, u16 offset)
1186 _jit_name(block->_jit, __func__);
1187 rec_store(state, block, offset, jit_code_stxi_c);
1190 static void rec_SH(struct lightrec_cstate *state,
1191 const struct block *block, u16 offset)
1193 _jit_name(block->_jit, __func__);
1194 rec_store(state, block, offset, jit_code_stxi_s);
1197 static void rec_SW(struct lightrec_cstate *state,
1198 const struct block *block, u16 offset)
1201 _jit_name(block->_jit, __func__);
1202 rec_store(state, block, offset, jit_code_stxi_i);
1205 static void rec_SWL(struct lightrec_cstate *state,
1206 const struct block *block, u16 offset)
1208 _jit_name(block->_jit, __func__);
1209 rec_io(state, block, offset, true, false);
1212 static void rec_SWR(struct lightrec_cstate *state,
1213 const struct block *block, u16 offset)
1215 _jit_name(block->_jit, __func__);
1216 rec_io(state, block, offset, true, false);
1219 static void rec_SWC2(struct lightrec_cstate *state,
1220 const struct block *block, u16 offset)
1222 _jit_name(block->_jit, __func__);
1223 rec_io(state, block, offset, false, false);
1226 static void rec_load_direct(struct lightrec_cstate *cstate, const struct block *block,
1227 u16 offset, jit_code_t code, bool is_unsigned)
1229 struct lightrec_state *state = cstate->state;
1230 struct regcache *reg_cache = cstate->reg_cache;
1231 union code c = block->opcode_list[offset].c;
1232 jit_state_t *_jit = block->_jit;
1233 jit_node_t *to_not_ram, *to_not_bios, *to_end, *to_end2;
1234 u8 tmp, rs, rt, addr_reg, flags = REG_EXT;
1243 jit_note(__FILE__, __LINE__);
1244 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.i.rs, 0);
1245 rt = lightrec_alloc_reg_out(reg_cache, _jit, c.i.rt, flags);
1247 if ((state->offset_ram == state->offset_bios &&
1248 state->offset_ram == state->offset_scratch &&
1249 state->mirrors_mapped) || !c.i.imm) {
1253 jit_addi(rt, rs, (s16)c.i.imm);
1257 if (c.i.rs != c.i.rt)
1258 lightrec_free_reg(reg_cache, rs);
1261 tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
1263 if (state->offset_ram == state->offset_bios &&
1264 state->offset_ram == state->offset_scratch) {
1265 if (!state->mirrors_mapped) {
1266 jit_andi(tmp, addr_reg, BIT(28));
1267 jit_rshi_u(tmp, tmp, 28 - 22);
1268 jit_ori(tmp, tmp, 0x1f800000 | (RAM_SIZE - 1));
1269 jit_andr(rt, addr_reg, tmp);
1271 jit_andi(rt, addr_reg, 0x1fffffff);
1274 if (state->offset_ram)
1275 jit_movi(tmp, state->offset_ram);
1277 to_not_ram = jit_bmsi(addr_reg, BIT(28));
1279 lightrec_regcache_mark_live(reg_cache, _jit);
1281 /* Convert to KUNSEG and avoid RAM mirrors */
1282 jit_andi(rt, addr_reg, RAM_SIZE - 1);
1284 if (state->offset_ram)
1285 jit_movi(tmp, state->offset_ram);
1287 to_end = jit_jmpi();
1289 jit_patch(to_not_ram);
1291 if (state->offset_bios != state->offset_scratch)
1292 to_not_bios = jit_bmci(addr_reg, BIT(22));
1294 /* Convert to KUNSEG */
1295 jit_andi(rt, addr_reg, 0x1fc00000 | (BIOS_SIZE - 1));
1297 jit_movi(tmp, state->offset_bios);
1299 if (state->offset_bios != state->offset_scratch) {
1300 to_end2 = jit_jmpi();
1302 jit_patch(to_not_bios);
1304 /* Convert to KUNSEG */
1305 jit_andi(rt, addr_reg, 0x1f800fff);
1307 if (state->offset_scratch)
1308 jit_movi(tmp, state->offset_scratch);
1316 if (state->offset_ram || state->offset_bios || state->offset_scratch)
1317 jit_addr(rt, rt, tmp);
1319 jit_new_node_www(code, rt, rt, imm);
1321 lightrec_free_reg(reg_cache, addr_reg);
1322 lightrec_free_reg(reg_cache, rt);
1323 lightrec_free_reg(reg_cache, tmp);
1326 static void rec_load(struct lightrec_cstate *state, const struct block *block,
1327 u16 offset, jit_code_t code, bool is_unsigned)
1329 u16 flags = block->opcode_list[offset].flags;
1331 if (flags & LIGHTREC_DIRECT_IO)
1332 rec_load_direct(state, block, offset, code, is_unsigned);
1334 rec_io(state, block, offset, false, true);
1337 static void rec_LB(struct lightrec_cstate *state, const struct block *block, u16 offset)
1339 _jit_name(block->_jit, __func__);
1340 rec_load(state, block, offset, jit_code_ldxi_c, false);
1343 static void rec_LBU(struct lightrec_cstate *state, const struct block *block, u16 offset)
1345 _jit_name(block->_jit, __func__);
1346 rec_load(state, block, offset, jit_code_ldxi_uc, true);
1349 static void rec_LH(struct lightrec_cstate *state, const struct block *block, u16 offset)
1351 _jit_name(block->_jit, __func__);
1352 rec_load(state, block, offset, jit_code_ldxi_s, false);
1355 static void rec_LHU(struct lightrec_cstate *state, const struct block *block, u16 offset)
1357 _jit_name(block->_jit, __func__);
1358 rec_load(state, block, offset, jit_code_ldxi_us, true);
1361 static void rec_LWL(struct lightrec_cstate *state, const struct block *block, u16 offset)
1363 _jit_name(block->_jit, __func__);
1364 rec_io(state, block, offset, true, true);
1367 static void rec_LWR(struct lightrec_cstate *state, const struct block *block, u16 offset)
1369 _jit_name(block->_jit, __func__);
1370 rec_io(state, block, offset, true, true);
1373 static void rec_LW(struct lightrec_cstate *state, const struct block *block, u16 offset)
1375 _jit_name(block->_jit, __func__);
1376 rec_load(state, block, offset, jit_code_ldxi_i, false);
1379 static void rec_LWC2(struct lightrec_cstate *state, const struct block *block, u16 offset)
1381 _jit_name(block->_jit, __func__);
1382 rec_io(state, block, offset, false, false);
1385 static void rec_break_syscall(struct lightrec_cstate *state,
1386 const struct block *block, u16 offset, bool is_break)
1388 _jit_note(block->_jit, __FILE__, __LINE__);
1391 call_to_c_wrapper(state, block, 0, false, C_WRAPPER_BREAK);
1393 call_to_c_wrapper(state, block, 0, false, C_WRAPPER_SYSCALL);
1395 /* TODO: the return address should be "pc - 4" if we're a delay slot */
1396 lightrec_emit_end_of_block(state, block, offset, -1,
1397 get_ds_pc(block, offset, 0),
1401 static void rec_special_SYSCALL(struct lightrec_cstate *state,
1402 const struct block *block, u16 offset)
1404 _jit_name(block->_jit, __func__);
1405 rec_break_syscall(state, block, offset, false);
1408 static void rec_special_BREAK(struct lightrec_cstate *state,
1409 const struct block *block, u16 offset)
1411 _jit_name(block->_jit, __func__);
1412 rec_break_syscall(state, block, offset, true);
1415 static void rec_mtc(struct lightrec_cstate *state, const struct block *block, u16 offset)
1417 struct regcache *reg_cache = state->reg_cache;
1418 union code c = block->opcode_list[offset].c;
1419 jit_state_t *_jit = block->_jit;
1421 jit_note(__FILE__, __LINE__);
1422 lightrec_clean_reg_if_loaded(reg_cache, _jit, c.i.rs, false);
1423 lightrec_clean_reg_if_loaded(reg_cache, _jit, c.i.rt, false);
1425 call_to_c_wrapper(state, block, c.opcode, true, C_WRAPPER_MTC);
1427 if (c.i.op == OP_CP0 &&
1428 !(block->opcode_list[offset].flags & LIGHTREC_NO_DS) &&
1429 (c.r.rd == 12 || c.r.rd == 13))
1430 lightrec_emit_end_of_block(state, block, offset, -1,
1431 get_ds_pc(block, offset, 1),
1436 rec_mfc0(struct lightrec_cstate *state, const struct block *block, u16 offset)
1438 struct regcache *reg_cache = state->reg_cache;
1439 union code c = block->opcode_list[offset].c;
1440 jit_state_t *_jit = block->_jit;
1443 jit_note(__FILE__, __LINE__);
1445 rt = lightrec_alloc_reg_out(reg_cache, _jit, c.i.rt, REG_EXT);
1447 jit_ldxi_i(rt, LIGHTREC_REG_STATE,
1448 offsetof(struct lightrec_state, regs.cp0[c.r.rd]));
1450 lightrec_free_reg(reg_cache, rt);
1453 static bool block_in_bios(const struct lightrec_cstate *state,
1454 const struct block *block)
1456 const struct lightrec_mem_map *bios = &state->state->maps[PSX_MAP_BIOS];
1457 u32 pc = kunseg(block->pc);
1459 return pc >= bios->pc && pc < bios->pc + bios->length;
1463 rec_mtc0(struct lightrec_cstate *state, const struct block *block, u16 offset)
1465 struct regcache *reg_cache = state->reg_cache;
1466 const union code c = block->opcode_list[offset].c;
1467 jit_state_t *_jit = block->_jit;
1468 u8 rt, tmp = 0, tmp2, status;
1470 jit_note(__FILE__, __LINE__);
1478 /* Those registers are read-only */
1484 if (block_in_bios(state, block) && c.r.rd == 12) {
1485 /* If we are running code from the BIOS, handle writes to the
1486 * Status register in C. BIOS code may toggle bit 16 which will
1487 * map/unmap the RAM, while game code cannot do that. */
1488 rec_mtc(state, block, offset);
1492 rt = lightrec_alloc_reg_in(reg_cache, _jit, c.i.rt, 0);
1495 jit_stxi_i(offsetof(struct lightrec_state, regs.cp0[c.r.rd]),
1496 LIGHTREC_REG_STATE, rt);
1499 if (c.r.rd == 12 || c.r.rd == 13) {
1500 tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
1501 jit_ldxi_i(tmp, LIGHTREC_REG_STATE,
1502 offsetof(struct lightrec_state, regs.cp0[13]));
1504 tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit);
1509 } else if (c.r.rd == 13) {
1510 /* Cause = (Cause & ~0x0300) | (value & 0x0300) */
1511 jit_andi(tmp2, rt, 0x0300);
1512 jit_ori(tmp, tmp, 0x0300);
1513 jit_xori(tmp, tmp, 0x0300);
1514 jit_orr(tmp, tmp, tmp2);
1515 jit_ldxi_i(tmp2, LIGHTREC_REG_STATE,
1516 offsetof(struct lightrec_state, regs.cp0[12]));
1517 jit_stxi_i(offsetof(struct lightrec_state, regs.cp0[13]),
1518 LIGHTREC_REG_STATE, tmp);
1522 if (c.r.rd == 12 || c.r.rd == 13) {
1523 /* Exit dynarec in case there's a software interrupt.
1524 * exit_flags = !!(status & tmp & 0x0300) & status; */
1525 jit_andr(tmp, tmp, status);
1526 jit_andi(tmp, tmp, 0x0300);
1527 jit_nei(tmp, tmp, 0);
1528 jit_andr(tmp, tmp, status);
1532 /* Exit dynarec in case we unmask a hardware interrupt.
1533 * exit_flags = !(~status & 0x401) */
1535 jit_comr(tmp2, status);
1536 jit_andi(tmp2, tmp2, 0x401);
1537 jit_eqi(tmp2, tmp2, 0);
1538 jit_orr(tmp, tmp, tmp2);
1541 if (c.r.rd == 12 || c.r.rd == 13) {
1542 jit_stxi_i(offsetof(struct lightrec_state, exit_flags),
1543 LIGHTREC_REG_STATE, tmp);
1545 lightrec_free_reg(reg_cache, tmp);
1546 lightrec_free_reg(reg_cache, tmp2);
1549 lightrec_free_reg(reg_cache, rt);
1551 if (!(block->opcode_list[offset].flags & LIGHTREC_NO_DS) &&
1552 (c.r.rd == 12 || c.r.rd == 13))
1553 lightrec_emit_eob(state, block, offset + 1, true);
1556 static void rec_cp0_MFC0(struct lightrec_cstate *state,
1557 const struct block *block, u16 offset)
1559 _jit_name(block->_jit, __func__);
1560 rec_mfc0(state, block, offset);
1563 static void rec_cp0_CFC0(struct lightrec_cstate *state,
1564 const struct block *block, u16 offset)
1566 _jit_name(block->_jit, __func__);
1567 rec_mfc0(state, block, offset);
1570 static void rec_cp0_MTC0(struct lightrec_cstate *state,
1571 const struct block *block, u16 offset)
1573 _jit_name(block->_jit, __func__);
1574 rec_mtc0(state, block, offset);
1577 static void rec_cp0_CTC0(struct lightrec_cstate *state,
1578 const struct block *block, u16 offset)
1580 _jit_name(block->_jit, __func__);
1581 rec_mtc0(state, block, offset);
1584 static void rec_cp2_basic_MFC2(struct lightrec_cstate *state,
1585 const struct block *block, u16 offset)
1587 struct regcache *reg_cache = state->reg_cache;
1588 const union code c = block->opcode_list[offset].c;
1589 jit_state_t *_jit = block->_jit;
1590 const u32 zext_regs = 0x300f0080;
1591 u8 rt, tmp, tmp2, tmp3, out, flags;
1592 u8 reg = c.r.rd == 15 ? 14 : c.r.rd;
1595 _jit_name(block->_jit, __func__);
1597 flags = (zext_regs & BIT(reg)) ? REG_ZEXT : REG_EXT;
1598 rt = lightrec_alloc_reg_out(reg_cache, _jit, c.r.rt, flags);
1608 jit_ldxi_s(rt, LIGHTREC_REG_STATE,
1609 offsetof(struct lightrec_state, regs.cp2d[reg]));
1616 jit_ldxi_us(rt, LIGHTREC_REG_STATE,
1617 offsetof(struct lightrec_state, regs.cp2d[reg]));
1621 tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
1622 tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit);
1623 tmp3 = lightrec_alloc_reg_temp(reg_cache, _jit);
1625 for (i = 0; i < 3; i++) {
1626 out = i == 0 ? rt : tmp;
1628 jit_ldxi_s(tmp, LIGHTREC_REG_STATE,
1629 offsetof(struct lightrec_state, regs.cp2d[9 + i]));
1630 jit_movi(tmp2, 0x1f);
1631 jit_rshi(out, tmp, 7);
1633 jit_ltr(tmp3, tmp2, out);
1634 jit_movnr(out, tmp2, tmp3);
1636 jit_gei(tmp2, out, 0);
1637 jit_movzr(out, tmp2, tmp2);
1640 jit_lshi(tmp, tmp, 5 * i);
1641 jit_orr(rt, rt, tmp);
1646 lightrec_free_reg(reg_cache, tmp);
1647 lightrec_free_reg(reg_cache, tmp2);
1648 lightrec_free_reg(reg_cache, tmp3);
1651 jit_ldxi_i(rt, LIGHTREC_REG_STATE,
1652 offsetof(struct lightrec_state, regs.cp2d[reg]));
1656 lightrec_free_reg(reg_cache, rt);
1659 static void rec_cp2_basic_CFC2(struct lightrec_cstate *state,
1660 const struct block *block, u16 offset)
1662 struct regcache *reg_cache = state->reg_cache;
1663 const union code c = block->opcode_list[offset].c;
1664 jit_state_t *_jit = block->_jit;
1667 _jit_name(block->_jit, __func__);
1677 rt = lightrec_alloc_reg_out(reg_cache, _jit, c.r.rt, REG_EXT);
1678 jit_ldxi_s(rt, LIGHTREC_REG_STATE,
1679 offsetof(struct lightrec_state, regs.cp2c[c.r.rd]));
1682 rt = lightrec_alloc_reg_out(reg_cache, _jit, c.r.rt, REG_ZEXT);
1683 jit_ldxi_i(rt, LIGHTREC_REG_STATE,
1684 offsetof(struct lightrec_state, regs.cp2c[c.r.rd]));
1688 lightrec_free_reg(reg_cache, rt);
1691 static void rec_cp2_basic_MTC2(struct lightrec_cstate *state,
1692 const struct block *block, u16 offset)
1694 struct regcache *reg_cache = state->reg_cache;
1695 const union code c = block->opcode_list[offset].c;
1696 jit_state_t *_jit = block->_jit;
1697 jit_node_t *loop, *to_loop;
1698 u8 rt, tmp, tmp2, flags = 0;
1700 _jit_name(block->_jit, __func__);
1708 rt = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rt, flags);
1712 tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
1713 jit_ldxi_i(tmp, LIGHTREC_REG_STATE,
1714 offsetof(struct lightrec_state, regs.cp2d[13]));
1716 tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit);
1717 jit_ldxi_i(tmp2, LIGHTREC_REG_STATE,
1718 offsetof(struct lightrec_state, regs.cp2d[14]));
1720 jit_stxi_i(offsetof(struct lightrec_state, regs.cp2d[12]),
1721 LIGHTREC_REG_STATE, tmp);
1722 jit_stxi_i(offsetof(struct lightrec_state, regs.cp2d[13]),
1723 LIGHTREC_REG_STATE, tmp2);
1724 jit_stxi_i(offsetof(struct lightrec_state, regs.cp2d[14]),
1725 LIGHTREC_REG_STATE, rt);
1727 lightrec_free_reg(reg_cache, tmp);
1728 lightrec_free_reg(reg_cache, tmp2);
1731 tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
1733 jit_lshi(tmp, rt, 7);
1734 jit_andi(tmp, tmp, 0xf80);
1735 jit_stxi_s(offsetof(struct lightrec_state, regs.cp2d[9]),
1736 LIGHTREC_REG_STATE, tmp);
1738 jit_lshi(tmp, rt, 2);
1739 jit_andi(tmp, tmp, 0xf80);
1740 jit_stxi_s(offsetof(struct lightrec_state, regs.cp2d[10]),
1741 LIGHTREC_REG_STATE, tmp);
1743 jit_rshi(tmp, rt, 3);
1744 jit_andi(tmp, tmp, 0xf80);
1745 jit_stxi_s(offsetof(struct lightrec_state, regs.cp2d[11]),
1746 LIGHTREC_REG_STATE, tmp);
1748 lightrec_free_reg(reg_cache, tmp);
1751 tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
1752 tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit);
1754 /* if (rt < 0) rt = ~rt; */
1755 jit_rshi(tmp, rt, 31);
1756 jit_xorr(tmp, rt, tmp);
1758 /* We know the sign bit is 0. Left-shift by 1 to start the algorithm */
1759 jit_lshi(tmp, tmp, 1);
1762 /* Decrement tmp2 and right-shift the value by 1 until it equals zero */
1764 jit_subi(tmp2, tmp2, 1);
1765 jit_rshi_u(tmp, tmp, 1);
1766 to_loop = jit_bnei(tmp, 0);
1768 jit_patch_at(to_loop, loop);
1770 jit_stxi_i(offsetof(struct lightrec_state, regs.cp2d[31]),
1771 LIGHTREC_REG_STATE, tmp2);
1772 jit_stxi_i(offsetof(struct lightrec_state, regs.cp2d[30]),
1773 LIGHTREC_REG_STATE, rt);
1775 lightrec_free_reg(reg_cache, tmp);
1776 lightrec_free_reg(reg_cache, tmp2);
1779 jit_stxi_i(offsetof(struct lightrec_state, regs.cp2d[c.r.rd]),
1780 LIGHTREC_REG_STATE, rt);
1784 lightrec_free_reg(reg_cache, rt);
1787 static void rec_cp2_basic_CTC2(struct lightrec_cstate *state,
1788 const struct block *block, u16 offset)
1790 struct regcache *reg_cache = state->reg_cache;
1791 const union code c = block->opcode_list[offset].c;
1792 jit_state_t *_jit = block->_jit;
1795 _jit_name(block->_jit, __func__);
1797 rt = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rt, 0);
1807 jit_stxi_s(offsetof(struct lightrec_state, regs.cp2c[c.r.rd]),
1808 LIGHTREC_REG_STATE, rt);
1811 tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
1812 tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit);
1814 jit_andi(tmp, rt, 0x7f87e000);
1815 jit_nei(tmp, tmp, 0);
1816 jit_lshi(tmp, tmp, 31);
1818 jit_andi(tmp2, rt, 0x7ffff000);
1819 jit_orr(tmp, tmp2, tmp);
1821 jit_stxi_i(offsetof(struct lightrec_state, regs.cp2c[31]),
1822 LIGHTREC_REG_STATE, tmp);
1824 lightrec_free_reg(reg_cache, tmp);
1825 lightrec_free_reg(reg_cache, tmp2);
1829 jit_stxi_i(offsetof(struct lightrec_state, regs.cp2c[c.r.rd]),
1830 LIGHTREC_REG_STATE, rt);
1833 lightrec_free_reg(reg_cache, rt);
1836 static void rec_cp0_RFE(struct lightrec_cstate *state,
1837 const struct block *block, u16 offset)
1839 struct regcache *reg_cache = state->reg_cache;
1840 jit_state_t *_jit = block->_jit;
1844 jit_note(__FILE__, __LINE__);
1846 status = lightrec_alloc_reg_temp(reg_cache, _jit);
1847 jit_ldxi_i(status, LIGHTREC_REG_STATE,
1848 offsetof(struct lightrec_state, regs.cp0[12]));
1850 tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
1852 /* status = ((status >> 2) & 0xf) | status & ~0xf; */
1853 jit_rshi(tmp, status, 2);
1854 jit_andi(tmp, tmp, 0xf);
1855 jit_andi(status, status, ~0xful);
1856 jit_orr(status, status, tmp);
1858 jit_ldxi_i(tmp, LIGHTREC_REG_STATE,
1859 offsetof(struct lightrec_state, regs.cp0[13]));
1860 jit_stxi_i(offsetof(struct lightrec_state, regs.cp0[12]),
1861 LIGHTREC_REG_STATE, status);
1863 /* Exit dynarec in case there's a software interrupt.
1864 * exit_flags = !!(status & cause & 0x0300) & status; */
1865 jit_andr(tmp, tmp, status);
1866 jit_andi(tmp, tmp, 0x0300);
1867 jit_nei(tmp, tmp, 0);
1868 jit_andr(tmp, tmp, status);
1869 jit_stxi_i(offsetof(struct lightrec_state, exit_flags),
1870 LIGHTREC_REG_STATE, tmp);
1872 lightrec_free_reg(reg_cache, status);
1873 lightrec_free_reg(reg_cache, tmp);
1876 static void rec_CP(struct lightrec_cstate *state,
1877 const struct block *block, u16 offset)
1879 union code c = block->opcode_list[offset].c;
1880 jit_state_t *_jit = block->_jit;
1883 jit_note(__FILE__, __LINE__);
1885 call_to_c_wrapper(state, block, c.opcode, true, C_WRAPPER_CP);
1888 static void rec_meta_MOV(struct lightrec_cstate *state,
1889 const struct block *block, u16 offset)
1891 struct regcache *reg_cache = state->reg_cache;
1892 union code c = block->opcode_list[offset].c;
1893 jit_state_t *_jit = block->_jit;
1896 _jit_name(block->_jit, __func__);
1897 jit_note(__FILE__, __LINE__);
1899 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rs, 0);
1900 rd = lightrec_alloc_reg_out(reg_cache, _jit, c.r.rd, REG_EXT);
1908 lightrec_free_reg(reg_cache, rs);
1909 lightrec_free_reg(reg_cache, rd);
1912 static void rec_meta_EXTC_EXTS(struct lightrec_cstate *state,
1913 const struct block *block,
1916 struct regcache *reg_cache = state->reg_cache;
1917 union code c = block->opcode_list[offset].c;
1918 jit_state_t *_jit = block->_jit;
1921 _jit_name(block->_jit, __func__);
1922 jit_note(__FILE__, __LINE__);
1924 rs = lightrec_alloc_reg_in(reg_cache, _jit, c.i.rs, 0);
1925 rt = lightrec_alloc_reg_out(reg_cache, _jit, c.i.rt, REG_EXT);
1927 if (c.i.op == OP_META_EXTC)
1932 lightrec_free_reg(reg_cache, rs);
1933 lightrec_free_reg(reg_cache, rt);
1936 static const lightrec_rec_func_t rec_standard[64] = {
1937 SET_DEFAULT_ELM(rec_standard, unknown_opcode),
1938 [OP_SPECIAL] = rec_SPECIAL,
1939 [OP_REGIMM] = rec_REGIMM,
1944 [OP_BLEZ] = rec_BLEZ,
1945 [OP_BGTZ] = rec_BGTZ,
1946 [OP_ADDI] = rec_ADDI,
1947 [OP_ADDIU] = rec_ADDIU,
1948 [OP_SLTI] = rec_SLTI,
1949 [OP_SLTIU] = rec_SLTIU,
1950 [OP_ANDI] = rec_ANDI,
1952 [OP_XORI] = rec_XORI,
1968 [OP_LWC2] = rec_LWC2,
1969 [OP_SWC2] = rec_SWC2,
1971 [OP_META_MOV] = rec_meta_MOV,
1972 [OP_META_EXTC] = rec_meta_EXTC_EXTS,
1973 [OP_META_EXTS] = rec_meta_EXTC_EXTS,
1976 static const lightrec_rec_func_t rec_special[64] = {
1977 SET_DEFAULT_ELM(rec_special, unknown_opcode),
1978 [OP_SPECIAL_SLL] = rec_special_SLL,
1979 [OP_SPECIAL_SRL] = rec_special_SRL,
1980 [OP_SPECIAL_SRA] = rec_special_SRA,
1981 [OP_SPECIAL_SLLV] = rec_special_SLLV,
1982 [OP_SPECIAL_SRLV] = rec_special_SRLV,
1983 [OP_SPECIAL_SRAV] = rec_special_SRAV,
1984 [OP_SPECIAL_JR] = rec_special_JR,
1985 [OP_SPECIAL_JALR] = rec_special_JALR,
1986 [OP_SPECIAL_SYSCALL] = rec_special_SYSCALL,
1987 [OP_SPECIAL_BREAK] = rec_special_BREAK,
1988 [OP_SPECIAL_MFHI] = rec_special_MFHI,
1989 [OP_SPECIAL_MTHI] = rec_special_MTHI,
1990 [OP_SPECIAL_MFLO] = rec_special_MFLO,
1991 [OP_SPECIAL_MTLO] = rec_special_MTLO,
1992 [OP_SPECIAL_MULT] = rec_special_MULT,
1993 [OP_SPECIAL_MULTU] = rec_special_MULTU,
1994 [OP_SPECIAL_DIV] = rec_special_DIV,
1995 [OP_SPECIAL_DIVU] = rec_special_DIVU,
1996 [OP_SPECIAL_ADD] = rec_special_ADD,
1997 [OP_SPECIAL_ADDU] = rec_special_ADDU,
1998 [OP_SPECIAL_SUB] = rec_special_SUB,
1999 [OP_SPECIAL_SUBU] = rec_special_SUBU,
2000 [OP_SPECIAL_AND] = rec_special_AND,
2001 [OP_SPECIAL_OR] = rec_special_OR,
2002 [OP_SPECIAL_XOR] = rec_special_XOR,
2003 [OP_SPECIAL_NOR] = rec_special_NOR,
2004 [OP_SPECIAL_SLT] = rec_special_SLT,
2005 [OP_SPECIAL_SLTU] = rec_special_SLTU,
2008 static const lightrec_rec_func_t rec_regimm[64] = {
2009 SET_DEFAULT_ELM(rec_regimm, unknown_opcode),
2010 [OP_REGIMM_BLTZ] = rec_regimm_BLTZ,
2011 [OP_REGIMM_BGEZ] = rec_regimm_BGEZ,
2012 [OP_REGIMM_BLTZAL] = rec_regimm_BLTZAL,
2013 [OP_REGIMM_BGEZAL] = rec_regimm_BGEZAL,
2016 static const lightrec_rec_func_t rec_cp0[64] = {
2017 SET_DEFAULT_ELM(rec_cp0, rec_CP),
2018 [OP_CP0_MFC0] = rec_cp0_MFC0,
2019 [OP_CP0_CFC0] = rec_cp0_CFC0,
2020 [OP_CP0_MTC0] = rec_cp0_MTC0,
2021 [OP_CP0_CTC0] = rec_cp0_CTC0,
2022 [OP_CP0_RFE] = rec_cp0_RFE,
2025 static const lightrec_rec_func_t rec_cp2_basic[64] = {
2026 SET_DEFAULT_ELM(rec_cp2_basic, rec_CP),
2027 [OP_CP2_BASIC_MFC2] = rec_cp2_basic_MFC2,
2028 [OP_CP2_BASIC_CFC2] = rec_cp2_basic_CFC2,
2029 [OP_CP2_BASIC_MTC2] = rec_cp2_basic_MTC2,
2030 [OP_CP2_BASIC_CTC2] = rec_cp2_basic_CTC2,
2033 static void rec_SPECIAL(struct lightrec_cstate *state,
2034 const struct block *block, u16 offset)
2036 union code c = block->opcode_list[offset].c;
2037 lightrec_rec_func_t f = rec_special[c.r.op];
2039 if (!HAS_DEFAULT_ELM && unlikely(!f))
2040 unknown_opcode(state, block, offset);
2042 (*f)(state, block, offset);
2045 static void rec_REGIMM(struct lightrec_cstate *state,
2046 const struct block *block, u16 offset)
2048 union code c = block->opcode_list[offset].c;
2049 lightrec_rec_func_t f = rec_regimm[c.r.rt];
2051 if (!HAS_DEFAULT_ELM && unlikely(!f))
2052 unknown_opcode(state, block, offset);
2054 (*f)(state, block, offset);
2057 static void rec_CP0(struct lightrec_cstate *state,
2058 const struct block *block, u16 offset)
2060 union code c = block->opcode_list[offset].c;
2061 lightrec_rec_func_t f = rec_cp0[c.r.rs];
2063 if (!HAS_DEFAULT_ELM && unlikely(!f))
2064 rec_CP(state, block, offset);
2066 (*f)(state, block, offset);
2069 static void rec_CP2(struct lightrec_cstate *state,
2070 const struct block *block, u16 offset)
2072 union code c = block->opcode_list[offset].c;
2074 if (c.r.op == OP_CP2_BASIC) {
2075 lightrec_rec_func_t f = rec_cp2_basic[c.r.rs];
2077 if (HAS_DEFAULT_ELM || likely(f)) {
2078 (*f)(state, block, offset);
2083 rec_CP(state, block, offset);
2086 void lightrec_rec_opcode(struct lightrec_cstate *state,
2087 const struct block *block, u16 offset)
2089 struct regcache *reg_cache = state->reg_cache;
2090 struct lightrec_branch_target *target;
2091 const struct opcode *op = &block->opcode_list[offset];
2092 jit_state_t *_jit = block->_jit;
2093 lightrec_rec_func_t f;
2095 if (op->flags & LIGHTREC_SYNC) {
2096 jit_subi(LIGHTREC_REG_CYCLE, LIGHTREC_REG_CYCLE, state->cycles);
2099 lightrec_storeback_regs(reg_cache, _jit);
2100 lightrec_regcache_reset(reg_cache);
2102 pr_debug("Adding branch target at offset 0x%x\n", offset << 2);
2103 target = &state->targets[state->nb_targets++];
2104 target->offset = offset;
2105 target->label = jit_indirect();
2108 if (likely(op->opcode)) {
2109 f = rec_standard[op->i.op];
2111 if (!HAS_DEFAULT_ELM && unlikely(!f))
2112 unknown_opcode(state, block, offset);
2114 (*f)(state, block, offset);
2117 if (unlikely(op->flags & LIGHTREC_UNLOAD_RD)) {
2118 lightrec_clean_reg_if_loaded(reg_cache, _jit, op->r.rd, true);
2119 pr_debug("Cleaning RD reg %s\n", lightrec_reg_name(op->r.rd));
2121 if (unlikely(op->flags & LIGHTREC_UNLOAD_RS)) {
2122 lightrec_clean_reg_if_loaded(reg_cache, _jit, op->i.rs, true);
2123 pr_debug("Cleaning RS reg %s\n", lightrec_reg_name(op->i.rt));
2125 if (unlikely(op->flags & LIGHTREC_UNLOAD_RT)) {
2126 lightrec_clean_reg_if_loaded(reg_cache, _jit, op->i.rt, true);
2127 pr_debug("Cleaning RT reg %s\n", lightrec_reg_name(op->i.rt));