206a45ca6fbd62d03d6747e7a49c27d3433ca2ff
[pcsx_rearmed.git] / deps / lightrec / emitter.c
1 /*
2  * Copyright (C) 2014-2020 Paul Cercueil <paul@crapouillou.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  */
14
15 #include "blockcache.h"
16 #include "debug.h"
17 #include "disassembler.h"
18 #include "emitter.h"
19 #include "optimizer.h"
20 #include "regcache.h"
21
22 #include <lightning.h>
23 #include <stdbool.h>
24 #include <stddef.h>
25
26 typedef void (*lightrec_rec_func_t)(const struct block *,
27                                     const struct opcode *, u32);
28
29 /* Forward declarations */
30 static void rec_SPECIAL(const struct block *block,
31                        const struct opcode *op, u32 pc);
32 static void rec_REGIMM(const struct block *block,
33                       const struct opcode *op, u32 pc);
34 static void rec_CP0(const struct block *block, const struct opcode *op, u32 pc);
35 static void rec_CP2(const struct block *block, const struct opcode *op, u32 pc);
36
37
38 static void unknown_opcode(const struct block *block,
39                            const struct opcode *op, u32 pc)
40 {
41         pr_warn("Unknown opcode: 0x%08x at PC 0x%08x\n", op->opcode, pc);
42 }
43
44 static void lightrec_emit_end_of_block(const struct block *block,
45                                        const struct opcode *op, u32 pc,
46                                        s8 reg_new_pc, u32 imm, u8 ra_reg,
47                                        u32 link, bool update_cycles)
48 {
49         struct lightrec_state *state = block->state;
50         struct regcache *reg_cache = state->reg_cache;
51         u32 cycles = state->cycles;
52         jit_state_t *_jit = block->_jit;
53
54         jit_note(__FILE__, __LINE__);
55
56         if (link) {
57                 /* Update the $ra register */
58                 u8 link_reg = lightrec_alloc_reg_out(reg_cache, _jit, ra_reg);
59                 jit_movi(link_reg, link);
60                 lightrec_free_reg(reg_cache, link_reg);
61         }
62
63         if (reg_new_pc < 0) {
64                 reg_new_pc = lightrec_alloc_reg(reg_cache, _jit, JIT_V0);
65                 lightrec_lock_reg(reg_cache, _jit, reg_new_pc);
66
67                 jit_movi(reg_new_pc, imm);
68         }
69
70         if (has_delay_slot(op->c) &&
71             !(op->flags & (LIGHTREC_NO_DS | LIGHTREC_LOCAL_BRANCH))) {
72                 cycles += lightrec_cycles_of_opcode(op->next->c);
73
74                 /* Recompile the delay slot */
75                 if (op->next->c.opcode)
76                         lightrec_rec_opcode(block, op->next, pc + 4);
77         }
78
79         /* Store back remaining registers */
80         lightrec_storeback_regs(reg_cache, _jit);
81
82         jit_movr(JIT_V0, reg_new_pc);
83
84         if (cycles && update_cycles) {
85                 jit_subi(LIGHTREC_REG_CYCLE, LIGHTREC_REG_CYCLE, cycles);
86                 pr_debug("EOB: %u cycles\n", cycles);
87         }
88
89         if (op->next && ((op->flags & LIGHTREC_NO_DS) || op->next->next))
90                 state->branches[state->nb_branches++] = jit_jmpi();
91 }
92
93 void lightrec_emit_eob(const struct block *block,
94                        const struct opcode *op, u32 pc)
95 {
96         struct lightrec_state *state = block->state;
97         struct regcache *reg_cache = state->reg_cache;
98         jit_state_t *_jit = block->_jit;
99
100         lightrec_storeback_regs(reg_cache, _jit);
101
102         jit_movi(JIT_V0, pc);
103         jit_subi(LIGHTREC_REG_CYCLE, LIGHTREC_REG_CYCLE,
104                  state->cycles - lightrec_cycles_of_opcode(op->c));
105
106         state->branches[state->nb_branches++] = jit_jmpi();
107 }
108
109 static void rec_special_JR(const struct block *block,
110                            const struct opcode *op, u32 pc)
111 {
112         struct regcache *reg_cache = block->state->reg_cache;
113         jit_state_t *_jit = block->_jit;
114         u8 rs = lightrec_request_reg_in(reg_cache, _jit, op->r.rs, JIT_V0);
115
116         _jit_name(block->_jit, __func__);
117         lightrec_lock_reg(reg_cache, _jit, rs);
118         lightrec_emit_end_of_block(block, op, pc, rs, 0, 31, 0, true);
119 }
120
121 static void rec_special_JALR(const struct block *block,
122                              const struct opcode *op, u32 pc)
123 {
124         struct regcache *reg_cache = block->state->reg_cache;
125         jit_state_t *_jit = block->_jit;
126         u8 rs = lightrec_request_reg_in(reg_cache, _jit, op->r.rs, JIT_V0);
127
128         _jit_name(block->_jit, __func__);
129         lightrec_lock_reg(reg_cache, _jit, rs);
130         lightrec_emit_end_of_block(block, op, pc, rs, 0, op->r.rd, pc + 8, true);
131 }
132
133 static void rec_J(const struct block *block, const struct opcode *op, u32 pc)
134 {
135         _jit_name(block->_jit, __func__);
136         lightrec_emit_end_of_block(block, op, pc, -1,
137                                    (pc & 0xf0000000) | (op->j.imm << 2), 31, 0, true);
138 }
139
140 static void rec_JAL(const struct block *block, const struct opcode *op, u32 pc)
141 {
142         _jit_name(block->_jit, __func__);
143         lightrec_emit_end_of_block(block, op, pc, -1,
144                                    (pc & 0xf0000000) | (op->j.imm << 2),
145                                    31, pc + 8, true);
146 }
147
148 static void rec_b(const struct block *block, const struct opcode *op, u32 pc,
149                   jit_code_t code, u32 link, bool unconditional, bool bz)
150 {
151         struct regcache *reg_cache = block->state->reg_cache;
152         struct native_register *regs_backup;
153         jit_state_t *_jit = block->_jit;
154         struct lightrec_branch *branch;
155         jit_node_t *addr;
156         u8 link_reg;
157         u32 offset, cycles = block->state->cycles;
158         bool is_forward = (s16)op->i.imm >= -1;
159
160         jit_note(__FILE__, __LINE__);
161
162         if (!(op->flags & LIGHTREC_NO_DS))
163                 cycles += lightrec_cycles_of_opcode(op->next->c);
164
165         block->state->cycles = 0;
166
167         if (cycles)
168                 jit_subi(LIGHTREC_REG_CYCLE, LIGHTREC_REG_CYCLE, cycles);
169
170         if (!unconditional) {
171                 u8 rs = lightrec_alloc_reg_in_ext(reg_cache, _jit, op->i.rs),
172                    rt = bz ? 0 : lightrec_alloc_reg_in_ext(reg_cache,
173                                                            _jit, op->i.rt);
174
175                 /* Generate the branch opcode */
176                 addr = jit_new_node_pww(code, NULL, rs, rt);
177
178                 lightrec_free_regs(reg_cache);
179                 regs_backup = lightrec_regcache_enter_branch(reg_cache);
180         }
181
182         if (op->flags & LIGHTREC_LOCAL_BRANCH) {
183                 if (op->next && !(op->flags & LIGHTREC_NO_DS)) {
184                         /* Recompile the delay slot */
185                         if (op->next->opcode)
186                                 lightrec_rec_opcode(block, op->next, pc + 4);
187                 }
188
189                 if (link) {
190                         /* Update the $ra register */
191                         link_reg = lightrec_alloc_reg_out(reg_cache, _jit, 31);
192                         jit_movi(link_reg, link);
193                         lightrec_free_reg(reg_cache, link_reg);
194                 }
195
196                 /* Store back remaining registers */
197                 lightrec_storeback_regs(reg_cache, _jit);
198
199                 offset = op->offset + 1 + (s16)op->i.imm;
200                 pr_debug("Adding local branch to offset 0x%x\n", offset << 2);
201                 branch = &block->state->local_branches[
202                         block->state->nb_local_branches++];
203
204                 branch->target = offset;
205                 if (is_forward)
206                         branch->branch = jit_jmpi();
207                 else
208                         branch->branch = jit_bgti(LIGHTREC_REG_CYCLE, 0);
209         }
210
211         if (!(op->flags & LIGHTREC_LOCAL_BRANCH) || !is_forward) {
212                 lightrec_emit_end_of_block(block, op, pc, -1,
213                                            pc + 4 + ((s16)op->i.imm << 2),
214                                            31, link, false);
215         }
216
217         if (!unconditional) {
218                 jit_patch(addr);
219                 lightrec_regcache_leave_branch(reg_cache, regs_backup);
220
221                 if (bz && link) {
222                         /* Update the $ra register */
223                         link_reg = lightrec_alloc_reg_out_ext(reg_cache,
224                                                               _jit, 31);
225                         jit_movi(link_reg, (s32)link);
226                         lightrec_free_reg(reg_cache, link_reg);
227                 }
228
229                 if (!(op->flags & LIGHTREC_NO_DS) && op->next->opcode)
230                         lightrec_rec_opcode(block, op->next, pc + 4);
231         }
232 }
233
234 static void rec_BNE(const struct block *block, const struct opcode *op, u32 pc)
235 {
236         _jit_name(block->_jit, __func__);
237         rec_b(block, op, pc, jit_code_beqr, 0, false, false);
238 }
239
240 static void rec_BEQ(const struct block *block, const struct opcode *op, u32 pc)
241 {
242         _jit_name(block->_jit, __func__);
243         rec_b(block, op, pc, jit_code_bner, 0,
244                         op->i.rs == op->i.rt, false);
245 }
246
247 static void rec_BLEZ(const struct block *block, const struct opcode *op, u32 pc)
248 {
249         _jit_name(block->_jit, __func__);
250         rec_b(block, op, pc, jit_code_bgti, 0, op->i.rs == 0, true);
251 }
252
253 static void rec_BGTZ(const struct block *block, const struct opcode *op, u32 pc)
254 {
255         _jit_name(block->_jit, __func__);
256         rec_b(block, op, pc, jit_code_blei, 0, false, true);
257 }
258
259 static void rec_regimm_BLTZ(const struct block *block,
260                             const struct opcode *op, u32 pc)
261 {
262         _jit_name(block->_jit, __func__);
263         rec_b(block, op, pc, jit_code_bgei, 0, false, true);
264 }
265
266 static void rec_regimm_BLTZAL(const struct block *block,
267                               const struct opcode *op, u32 pc)
268 {
269         _jit_name(block->_jit, __func__);
270         rec_b(block, op, pc, jit_code_bgei, pc + 8, false, true);
271 }
272
273 static void rec_regimm_BGEZ(const struct block *block,
274                             const struct opcode *op, u32 pc)
275 {
276         _jit_name(block->_jit, __func__);
277         rec_b(block, op, pc, jit_code_blti, 0, !op->i.rs, true);
278 }
279
280 static void rec_regimm_BGEZAL(const struct block *block,
281                               const struct opcode *op, u32 pc)
282 {
283         _jit_name(block->_jit, __func__);
284         rec_b(block, op, pc, jit_code_blti, pc + 8, !op->i.rs, true);
285 }
286
287 static void rec_alu_imm(const struct block *block, const struct opcode *op,
288                         jit_code_t code, bool sign_extend)
289 {
290         struct regcache *reg_cache = block->state->reg_cache;
291         jit_state_t *_jit = block->_jit;
292         u8 rs, rt;
293
294         jit_note(__FILE__, __LINE__);
295         rs = lightrec_alloc_reg_in_ext(reg_cache, _jit, op->i.rs);
296         rt = lightrec_alloc_reg_out_ext(reg_cache, _jit, op->i.rt);
297
298         if (sign_extend)
299                 jit_new_node_www(code, rt, rs, (s32)(s16) op->i.imm);
300         else
301                 jit_new_node_www(code, rt, rs, (u32)(u16) op->i.imm);
302
303         lightrec_free_reg(reg_cache, rs);
304         lightrec_free_reg(reg_cache, rt);
305 }
306
307 static void rec_alu_special(const struct block *block, const struct opcode *op,
308                             jit_code_t code, bool out_ext)
309 {
310         struct regcache *reg_cache = block->state->reg_cache;
311         jit_state_t *_jit = block->_jit;
312         u8 rd, rt, rs;
313
314         jit_note(__FILE__, __LINE__);
315         rs = lightrec_alloc_reg_in_ext(reg_cache, _jit, op->r.rs);
316         rt = lightrec_alloc_reg_in_ext(reg_cache, _jit, op->r.rt);
317
318         if (out_ext)
319            rd = lightrec_alloc_reg_out_ext(reg_cache, _jit, op->r.rd);
320         else
321            rd = lightrec_alloc_reg_out(reg_cache, _jit, op->r.rd);
322
323         jit_new_node_www(code, rd, rs, rt);
324
325         lightrec_free_reg(reg_cache, rs);
326         lightrec_free_reg(reg_cache, rt);
327         lightrec_free_reg(reg_cache, rd);
328 }
329
330 static void rec_alu_shiftv(const struct block *block,
331                            const struct opcode *op, jit_code_t code)
332 {
333         struct regcache *reg_cache = block->state->reg_cache;
334         jit_state_t *_jit = block->_jit;
335         u8 rd, rt, rs, temp;
336
337         jit_note(__FILE__, __LINE__);
338         rs = lightrec_alloc_reg_in(reg_cache, _jit, op->r.rs);
339         temp = lightrec_alloc_reg_temp(reg_cache, _jit);
340
341         if (code == jit_code_rshr) {
342                 rt = lightrec_alloc_reg_in_ext(reg_cache, _jit, op->r.rt);
343                 rd = lightrec_alloc_reg_out_ext(reg_cache, _jit, op->r.rd);
344         } else {
345                 rt = lightrec_alloc_reg_in(reg_cache, _jit, op->r.rt);
346                 rd = lightrec_alloc_reg_out(reg_cache, _jit, op->r.rd);
347         }
348
349         jit_andi(temp, rs, 0x1f);
350
351 #if __WORDSIZE == 64
352         if (code == jit_code_rshr_u) {
353                 jit_extr_ui(rd, rt);
354                 jit_new_node_www(code, rd, rd, temp);
355         }
356 #endif
357
358         if (__WORDSIZE == 32 || code != jit_code_rshr_u)
359                 jit_new_node_www(code, rd, rt, temp);
360
361         lightrec_free_reg(reg_cache, rs);
362         lightrec_free_reg(reg_cache, temp);
363         lightrec_free_reg(reg_cache, rt);
364         lightrec_free_reg(reg_cache, rd);
365 }
366
367 static void rec_ADDIU(const struct block *block,
368                       const struct opcode *op, u32 pc)
369 {
370         _jit_name(block->_jit, __func__);
371         rec_alu_imm(block, op, jit_code_addi, true);
372 }
373
374 static void rec_ADDI(const struct block *block, const struct opcode *op, u32 pc)
375 {
376         /* TODO: Handle the exception? */
377         _jit_name(block->_jit, __func__);
378         rec_alu_imm(block, op, jit_code_addi, true);
379 }
380
381 static void rec_SLTIU(const struct block *block,
382                       const struct opcode *op, u32 pc)
383 {
384         _jit_name(block->_jit, __func__);
385         rec_alu_imm(block, op, jit_code_lti_u, true);
386 }
387
388 static void rec_SLTI(const struct block *block, const struct opcode *op, u32 pc)
389 {
390         _jit_name(block->_jit, __func__);
391         rec_alu_imm(block, op, jit_code_lti, true);
392 }
393
394 static void rec_ANDI(const struct block *block, const struct opcode *op, u32 pc)
395 {
396         struct regcache *reg_cache = block->state->reg_cache;
397         jit_state_t *_jit = block->_jit;
398         u8 rs, rt;
399
400         _jit_name(block->_jit, __func__);
401         jit_note(__FILE__, __LINE__);
402         rs = lightrec_alloc_reg_in(reg_cache, _jit, op->i.rs);
403         rt = lightrec_alloc_reg_out_ext(reg_cache, _jit, op->i.rt);
404
405         /* PSX code uses ANDI 0xff / ANDI 0xffff a lot, which are basically
406          * casts to uint8_t / uint16_t. */
407         if (op->i.imm == 0xff)
408                 jit_extr_uc(rt, rs);
409         else if (op->i.imm == 0xffff)
410                 jit_extr_us(rt, rs);
411         else
412                 jit_andi(rt, rs, (u32)(u16) op->i.imm);
413
414         lightrec_free_reg(reg_cache, rs);
415         lightrec_free_reg(reg_cache, rt);
416 }
417
418 static void rec_ORI(const struct block *block, const struct opcode *op, u32 pc)
419 {
420         _jit_name(block->_jit, __func__);
421         rec_alu_imm(block, op, jit_code_ori, false);
422 }
423
424 static void rec_XORI(const struct block *block, const struct opcode *op, u32 pc)
425 {
426         _jit_name(block->_jit, __func__);
427         rec_alu_imm(block, op, jit_code_xori, false);
428 }
429
430 static void rec_LUI(const struct block *block, const struct opcode *op, u32 pc)
431 {
432         struct regcache *reg_cache = block->state->reg_cache;
433         jit_state_t *_jit = block->_jit;
434         u8 rt;
435
436         jit_name(__func__);
437         jit_note(__FILE__, __LINE__);
438         rt = lightrec_alloc_reg_out_ext(reg_cache, _jit, op->i.rt);
439
440         jit_movi(rt, (s32)(op->i.imm << 16));
441
442         lightrec_free_reg(reg_cache, rt);
443 }
444
445 static void rec_special_ADDU(const struct block *block,
446                              const struct opcode *op, u32 pc)
447 {
448         _jit_name(block->_jit, __func__);
449         rec_alu_special(block, op, jit_code_addr, false);
450 }
451
452 static void rec_special_ADD(const struct block *block,
453                             const struct opcode *op, u32 pc)
454 {
455         /* TODO: Handle the exception? */
456         _jit_name(block->_jit, __func__);
457         rec_alu_special(block, op, jit_code_addr, false);
458 }
459
460 static void rec_special_SUBU(const struct block *block,
461                              const struct opcode *op, u32 pc)
462 {
463         _jit_name(block->_jit, __func__);
464         rec_alu_special(block, op, jit_code_subr, false);
465 }
466
467 static void rec_special_SUB(const struct block *block,
468                             const struct opcode *op, u32 pc)
469 {
470         /* TODO: Handle the exception? */
471         _jit_name(block->_jit, __func__);
472         rec_alu_special(block, op, jit_code_subr, false);
473 }
474
475 static void rec_special_AND(const struct block *block,
476                             const struct opcode *op, u32 pc)
477 {
478         _jit_name(block->_jit, __func__);
479         rec_alu_special(block, op, jit_code_andr, false);
480 }
481
482 static void rec_special_OR(const struct block *block,
483                            const struct opcode *op, u32 pc)
484 {
485         _jit_name(block->_jit, __func__);
486         rec_alu_special(block, op, jit_code_orr, false);
487 }
488
489 static void rec_special_XOR(const struct block *block,
490                             const struct opcode *op, u32 pc)
491 {
492         _jit_name(block->_jit, __func__);
493         rec_alu_special(block, op, jit_code_xorr, false);
494 }
495
496 static void rec_special_NOR(const struct block *block,
497                             const struct opcode *op, u32 pc)
498 {
499         struct regcache *reg_cache = block->state->reg_cache;
500         jit_state_t *_jit = block->_jit;
501         u8 rd;
502
503         jit_name(__func__);
504         rec_alu_special(block, op, jit_code_orr, false);
505         rd = lightrec_alloc_reg_out(reg_cache, _jit, op->r.rd);
506
507         jit_comr(rd, rd);
508
509         lightrec_free_reg(reg_cache, rd);
510 }
511
512 static void rec_special_SLTU(const struct block *block,
513                              const struct opcode *op, u32 pc)
514 {
515         _jit_name(block->_jit, __func__);
516         rec_alu_special(block, op, jit_code_ltr_u, true);
517 }
518
519 static void rec_special_SLT(const struct block *block,
520                             const struct opcode *op, u32 pc)
521 {
522         _jit_name(block->_jit, __func__);
523         rec_alu_special(block, op, jit_code_ltr, true);
524 }
525
526 static void rec_special_SLLV(const struct block *block,
527                              const struct opcode *op, u32 pc)
528 {
529         _jit_name(block->_jit, __func__);
530         rec_alu_shiftv(block, op, jit_code_lshr);
531 }
532
533 static void rec_special_SRLV(const struct block *block,
534                              const struct opcode *op, u32 pc)
535 {
536         _jit_name(block->_jit, __func__);
537         rec_alu_shiftv(block, op, jit_code_rshr_u);
538 }
539
540 static void rec_special_SRAV(const struct block *block,
541                              const struct opcode *op, u32 pc)
542 {
543         _jit_name(block->_jit, __func__);
544         rec_alu_shiftv(block, op, jit_code_rshr);
545 }
546
547 static void rec_alu_shift(const struct block *block,
548                           const struct opcode *op, jit_code_t code)
549 {
550         struct regcache *reg_cache = block->state->reg_cache;
551         jit_state_t *_jit = block->_jit;
552         u8 rd, rt;
553
554         jit_note(__FILE__, __LINE__);
555
556         if (code == jit_code_rshi) {
557                 rt = lightrec_alloc_reg_in_ext(reg_cache, _jit, op->r.rt);
558                 rd = lightrec_alloc_reg_out_ext(reg_cache, _jit, op->r.rd);
559         } else {
560                 rt = lightrec_alloc_reg_in(reg_cache, _jit, op->r.rt);
561                 rd = lightrec_alloc_reg_out(reg_cache, _jit, op->r.rd);
562         }
563
564 #if __WORDSIZE == 64
565         if (code == jit_code_rshi_u) {
566                 jit_extr_ui(rd, rt);
567                 jit_new_node_www(code, rd, rd, op->r.imm);
568         }
569 #endif
570         if (__WORDSIZE == 32 || code != jit_code_rshi_u)
571                 jit_new_node_www(code, rd, rt, op->r.imm);
572
573         lightrec_free_reg(reg_cache, rt);
574         lightrec_free_reg(reg_cache, rd);
575 }
576
577 static void rec_special_SLL(const struct block *block,
578                             const struct opcode *op, u32 pc)
579 {
580         _jit_name(block->_jit, __func__);
581         rec_alu_shift(block, op, jit_code_lshi);
582 }
583
584 static void rec_special_SRL(const struct block *block,
585                             const struct opcode *op, u32 pc)
586 {
587         _jit_name(block->_jit, __func__);
588         rec_alu_shift(block, op, jit_code_rshi_u);
589 }
590
591 static void rec_special_SRA(const struct block *block,
592                             const struct opcode *op, u32 pc)
593 {
594         _jit_name(block->_jit, __func__);
595         rec_alu_shift(block, op, jit_code_rshi);
596 }
597
598 static void rec_alu_mult(const struct block *block,
599                          const struct opcode *op, bool is_signed)
600 {
601         struct regcache *reg_cache = block->state->reg_cache;
602         jit_state_t *_jit = block->_jit;
603         u8 lo, hi, rs, rt;
604
605         jit_note(__FILE__, __LINE__);
606
607         lo = lightrec_alloc_reg_out(reg_cache, _jit, REG_LO);
608         if (!(op->flags & LIGHTREC_MULT32))
609                 hi = lightrec_alloc_reg_out_ext(reg_cache, _jit, REG_HI);
610         else if (__WORDSIZE == 64)
611                 hi = lightrec_alloc_reg_temp(reg_cache, _jit);
612
613         if (__WORDSIZE == 32 || !is_signed) {
614                 rs = lightrec_alloc_reg_in(reg_cache, _jit, op->r.rs);
615                 rt = lightrec_alloc_reg_in(reg_cache, _jit, op->r.rt);
616         } else {
617                 rs = lightrec_alloc_reg_in_ext(reg_cache, _jit, op->r.rs);
618                 rt = lightrec_alloc_reg_in_ext(reg_cache, _jit, op->r.rt);
619         }
620
621 #if __WORDSIZE == 32
622         /* On 32-bit systems, do a 32*32->64 bit operation, or a 32*32->32 bit
623          * operation if the MULT was detected a 32-bit only. */
624         if (!(op->flags & LIGHTREC_MULT32)) {
625                 if (is_signed)
626                         jit_qmulr(lo, hi, rs, rt);
627                 else
628                         jit_qmulr_u(lo, hi, rs, rt);
629         } else {
630                 jit_mulr(lo, rs, rt);
631         }
632 #else
633         /* On 64-bit systems, do a 64*64->64 bit operation.
634          * The input registers must be 32 bits, so we first sign-extend (if
635          * mult) or clear (if multu) the input registers. */
636         if (is_signed) {
637                 jit_mulr(lo, rs, rt);
638         } else {
639                 jit_extr_ui(lo, rt);
640                 jit_extr_ui(hi, rs);
641                 jit_mulr(lo, hi, lo);
642         }
643
644         /* The 64-bit output value is in $lo, store the upper 32 bits in $hi */
645         if (!(op->flags & LIGHTREC_MULT32))
646                 jit_rshi(hi, lo, 32);
647 #endif
648
649         lightrec_free_reg(reg_cache, rs);
650         lightrec_free_reg(reg_cache, rt);
651         lightrec_free_reg(reg_cache, lo);
652         if (__WORDSIZE == 64 || !(op->flags & LIGHTREC_MULT32))
653                 lightrec_free_reg(reg_cache, hi);
654 }
655
656 static void rec_alu_div(const struct block *block,
657                         const struct opcode *op, bool is_signed)
658 {
659         struct regcache *reg_cache = block->state->reg_cache;
660         jit_state_t *_jit = block->_jit;
661         jit_node_t *branch, *to_end;
662         u8 lo, hi, rs, rt;
663
664         jit_note(__FILE__, __LINE__);
665         lo = lightrec_alloc_reg_out(reg_cache, _jit, REG_LO);
666         hi = lightrec_alloc_reg_out(reg_cache, _jit, REG_HI);
667
668         if (__WORDSIZE == 32 || !is_signed) {
669                 rs = lightrec_alloc_reg_in(reg_cache, _jit, op->r.rs);
670                 rt = lightrec_alloc_reg_in(reg_cache, _jit, op->r.rt);
671         } else {
672                 rs = lightrec_alloc_reg_in_ext(reg_cache, _jit, op->r.rs);
673                 rt = lightrec_alloc_reg_in_ext(reg_cache, _jit, op->r.rt);
674         }
675
676         /* Jump to special handler if dividing by zero  */
677         branch = jit_beqi(rt, 0);
678
679 #if __WORDSIZE == 32
680         if (is_signed)
681                 jit_qdivr(lo, hi, rs, rt);
682         else
683                 jit_qdivr_u(lo, hi, rs, rt);
684 #else
685         /* On 64-bit systems, the input registers must be 32 bits, so we first sign-extend
686          * (if div) or clear (if divu) the input registers. */
687         if (is_signed) {
688                 jit_qdivr(lo, hi, rs, rt);
689         } else {
690                 jit_extr_ui(lo, rt);
691                 jit_extr_ui(hi, rs);
692                 jit_qdivr_u(lo, hi, hi, lo);
693         }
694 #endif
695
696         /* Jump above the div-by-zero handler */
697         to_end = jit_jmpi();
698
699         jit_patch(branch);
700
701         if (is_signed) {
702                 jit_lti(lo, rs, 0);
703                 jit_lshi(lo, lo, 1);
704                 jit_subi(lo, lo, 1);
705         } else {
706                 jit_movi(lo, 0xffffffff);
707         }
708
709         jit_movr(hi, rs);
710
711         jit_patch(to_end);
712
713         lightrec_free_reg(reg_cache, rs);
714         lightrec_free_reg(reg_cache, rt);
715         lightrec_free_reg(reg_cache, lo);
716         lightrec_free_reg(reg_cache, hi);
717 }
718
719 static void rec_special_MULT(const struct block *block,
720                              const struct opcode *op, u32 pc)
721 {
722         _jit_name(block->_jit, __func__);
723         rec_alu_mult(block, op, true);
724 }
725
726 static void rec_special_MULTU(const struct block *block,
727                               const struct opcode *op, u32 pc)
728 {
729         _jit_name(block->_jit, __func__);
730         rec_alu_mult(block, op, false);
731 }
732
733 static void rec_special_DIV(const struct block *block,
734                             const struct opcode *op, u32 pc)
735 {
736         _jit_name(block->_jit, __func__);
737         rec_alu_div(block, op, true);
738 }
739
740 static void rec_special_DIVU(const struct block *block,
741                              const struct opcode *op, u32 pc)
742 {
743         _jit_name(block->_jit, __func__);
744         rec_alu_div(block, op, false);
745 }
746
747 static void rec_alu_mv_lo_hi(const struct block *block, u8 dst, u8 src)
748 {
749         struct regcache *reg_cache = block->state->reg_cache;
750         jit_state_t *_jit = block->_jit;
751
752         jit_note(__FILE__, __LINE__);
753         src = lightrec_alloc_reg_in(reg_cache, _jit, src);
754         dst = lightrec_alloc_reg_out_ext(reg_cache, _jit, dst);
755
756 #if __WORDSIZE == 32
757         jit_movr(dst, src);
758 #else
759         jit_extr_i(dst, src);
760 #endif
761
762         lightrec_free_reg(reg_cache, src);
763         lightrec_free_reg(reg_cache, dst);
764 }
765
766 static void rec_special_MFHI(const struct block *block,
767                              const struct opcode *op, u32 pc)
768 {
769         _jit_name(block->_jit, __func__);
770         rec_alu_mv_lo_hi(block, op->r.rd, REG_HI);
771 }
772
773 static void rec_special_MTHI(const struct block *block,
774                              const struct opcode *op, u32 pc)
775 {
776         _jit_name(block->_jit, __func__);
777         rec_alu_mv_lo_hi(block, REG_HI, op->r.rs);
778 }
779
780 static void rec_special_MFLO(const struct block *block,
781                              const struct opcode *op, u32 pc)
782 {
783         _jit_name(block->_jit, __func__);
784         rec_alu_mv_lo_hi(block, op->r.rd, REG_LO);
785 }
786
787 static void rec_special_MTLO(const struct block *block,
788                              const struct opcode *op, u32 pc)
789 {
790         _jit_name(block->_jit, __func__);
791         rec_alu_mv_lo_hi(block, REG_LO, op->r.rs);
792 }
793
794 static void rec_io(const struct block *block, const struct opcode *op,
795                    bool load_rt, bool read_rt)
796 {
797         struct regcache *reg_cache = block->state->reg_cache;
798         jit_state_t *_jit = block->_jit;
799         bool is_tagged = op->flags & (LIGHTREC_HW_IO | LIGHTREC_DIRECT_IO);
800         u32 offset;
801         u8 tmp, tmp2, tmp3;
802
803         jit_note(__FILE__, __LINE__);
804
805         tmp = lightrec_alloc_reg(reg_cache, _jit, JIT_R0);
806
807         if (is_tagged) {
808                 offset = offsetof(struct lightrec_state, rw_func);
809         } else {
810                 tmp3 = lightrec_alloc_reg(reg_cache, _jit, JIT_R1);
811                 offset = offsetof(struct lightrec_state, rw_generic_func);
812         }
813
814         tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit);
815         jit_ldxi(tmp2, LIGHTREC_REG_STATE, offset);
816
817         lightrec_clean_reg_if_loaded(reg_cache, _jit, op->i.rs, false);
818
819         if (read_rt && likely(op->i.rt))
820                 lightrec_clean_reg_if_loaded(reg_cache, _jit, op->i.rt, true);
821         else if (load_rt)
822                 lightrec_clean_reg_if_loaded(reg_cache, _jit, op->i.rt, false);
823
824         if (is_tagged) {
825                 jit_movi(tmp, op->opcode);
826         } else {
827                 jit_movi(tmp, (uintptr_t)op);
828                 jit_movi(tmp3, (uintptr_t)block);
829         }
830
831         jit_callr(tmp2);
832
833         lightrec_free_reg(reg_cache, tmp);
834         lightrec_free_reg(reg_cache, tmp2);
835         if (!is_tagged)
836                 lightrec_free_reg(reg_cache, tmp3);
837         lightrec_regcache_mark_live(reg_cache, _jit);
838 }
839
840 static void rec_store_direct_no_invalidate(const struct block *block,
841                                            const struct opcode *op,
842                                            jit_code_t code)
843 {
844         struct lightrec_state *state = block->state;
845         struct regcache *reg_cache = state->reg_cache;
846         jit_state_t *_jit = block->_jit;
847         jit_node_t *to_not_ram, *to_end;
848         u8 tmp, tmp2, rs, rt;
849         s16 imm;
850
851         jit_note(__FILE__, __LINE__);
852         rs = lightrec_alloc_reg_in(reg_cache, _jit, op->i.rs);
853         tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
854         tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit);
855
856         /* Convert to KUNSEG and avoid RAM mirrors */
857         if (state->mirrors_mapped) {
858                 imm = (s16)op->i.imm;
859                 jit_andi(tmp, rs, 0x1f800000 | (4 * RAM_SIZE - 1));
860         } else if (op->i.imm) {
861                 imm = 0;
862                 jit_addi(tmp, rs, (s16)op->i.imm);
863                 jit_andi(tmp, tmp, 0x1f800000 | (RAM_SIZE - 1));
864         } else {
865                 imm = 0;
866                 jit_andi(tmp, rs, 0x1f800000 | (RAM_SIZE - 1));
867         }
868
869         lightrec_free_reg(reg_cache, rs);
870
871         if (state->offset_ram != state->offset_scratch) {
872                 to_not_ram = jit_bmsi(tmp, BIT(28));
873
874                 jit_movi(tmp2, state->offset_ram);
875
876                 to_end = jit_jmpi();
877                 jit_patch(to_not_ram);
878
879                 jit_movi(tmp2, state->offset_scratch);
880                 jit_patch(to_end);
881         } else if (state->offset_ram) {
882                 jit_movi(tmp2, state->offset_ram);
883         }
884
885         if (state->offset_ram || state->offset_scratch)
886                 jit_addr(tmp, tmp, tmp2);
887
888         lightrec_free_reg(reg_cache, tmp2);
889
890         rt = lightrec_alloc_reg_in(reg_cache, _jit, op->i.rt);
891         jit_new_node_www(code, imm, tmp, rt);
892
893         lightrec_free_reg(reg_cache, rt);
894         lightrec_free_reg(reg_cache, tmp);
895 }
896
897 static void rec_store_direct(const struct block *block, const struct opcode *op,
898                              jit_code_t code)
899 {
900         struct lightrec_state *state = block->state;
901         struct regcache *reg_cache = state->reg_cache;
902         jit_state_t *_jit = block->_jit;
903         jit_node_t *to_not_ram, *to_end;
904         u8 tmp, tmp2, tmp3, rs, rt;
905
906         jit_note(__FILE__, __LINE__);
907
908         rs = lightrec_alloc_reg_in(reg_cache, _jit, op->i.rs);
909         tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit);
910         tmp3 = lightrec_alloc_reg_in(reg_cache, _jit, 0);
911
912         /* Convert to KUNSEG and avoid RAM mirrors */
913         if (op->i.imm) {
914                 jit_addi(tmp2, rs, (s16)op->i.imm);
915                 jit_andi(tmp2, tmp2, 0x1f800000 | (RAM_SIZE - 1));
916         } else {
917                 jit_andi(tmp2, rs, 0x1f800000 | (RAM_SIZE - 1));
918         }
919
920         lightrec_free_reg(reg_cache, rs);
921         tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
922
923         to_not_ram = jit_bgti(tmp2, RAM_SIZE);
924
925         /* Compute the offset to the code LUT */
926         jit_andi(tmp, tmp2, (RAM_SIZE - 1) & ~3);
927 #if __WORDSIZE == 64
928         jit_lshi(tmp, tmp, 1);
929 #endif
930         jit_addr(tmp, LIGHTREC_REG_STATE, tmp);
931
932         /* Write NULL to the code LUT to invalidate any block that's there */
933         jit_stxi(offsetof(struct lightrec_state, code_lut), tmp, tmp3);
934
935         if (state->offset_ram != state->offset_scratch) {
936                 jit_movi(tmp, state->offset_ram);
937
938                 to_end = jit_jmpi();
939         }
940
941         jit_patch(to_not_ram);
942
943         if (state->offset_ram || state->offset_scratch)
944                 jit_movi(tmp, state->offset_scratch);
945
946         if (state->offset_ram != state->offset_scratch)
947                 jit_patch(to_end);
948
949         if (state->offset_ram || state->offset_scratch)
950                 jit_addr(tmp2, tmp2, tmp);
951
952         lightrec_free_reg(reg_cache, tmp);
953         lightrec_free_reg(reg_cache, tmp3);
954
955         rt = lightrec_alloc_reg_in(reg_cache, _jit, op->i.rt);
956         jit_new_node_www(code, 0, tmp2, rt);
957
958         lightrec_free_reg(reg_cache, rt);
959         lightrec_free_reg(reg_cache, tmp2);
960 }
961
962 static void rec_store(const struct block *block, const struct opcode *op,
963                      jit_code_t code)
964 {
965         if (op->flags & LIGHTREC_NO_INVALIDATE) {
966                 rec_store_direct_no_invalidate(block, op, code);
967         } else if (op->flags & LIGHTREC_DIRECT_IO) {
968                 if (block->state->invalidate_from_dma_only)
969                         rec_store_direct_no_invalidate(block, op, code);
970                 else
971                         rec_store_direct(block, op, code);
972         } else {
973                 rec_io(block, op, true, false);
974         }
975 }
976
977 static void rec_SB(const struct block *block, const struct opcode *op, u32 pc)
978 {
979         _jit_name(block->_jit, __func__);
980         rec_store(block, op, jit_code_stxi_c);
981 }
982
983 static void rec_SH(const struct block *block, const struct opcode *op, u32 pc)
984 {
985         _jit_name(block->_jit, __func__);
986         rec_store(block, op, jit_code_stxi_s);
987 }
988
989 static void rec_SW(const struct block *block, const struct opcode *op, u32 pc)
990 {
991         _jit_name(block->_jit, __func__);
992         rec_store(block, op, jit_code_stxi_i);
993 }
994
995 static void rec_SWL(const struct block *block, const struct opcode *op, u32 pc)
996 {
997         _jit_name(block->_jit, __func__);
998         rec_io(block, op, true, false);
999 }
1000
1001 static void rec_SWR(const struct block *block, const struct opcode *op, u32 pc)
1002 {
1003         _jit_name(block->_jit, __func__);
1004         rec_io(block, op, true, false);
1005 }
1006
1007 static void rec_SWC2(const struct block *block, const struct opcode *op, u32 pc)
1008 {
1009         _jit_name(block->_jit, __func__);
1010         rec_io(block, op, false, false);
1011 }
1012
1013 static void rec_load_direct(const struct block *block, const struct opcode *op,
1014                             jit_code_t code)
1015 {
1016         struct lightrec_state *state = block->state;
1017         struct regcache *reg_cache = state->reg_cache;
1018         jit_state_t *_jit = block->_jit;
1019         jit_node_t *to_not_ram, *to_not_bios, *to_end, *to_end2;
1020         u8 tmp, rs, rt, addr_reg;
1021         s16 imm;
1022
1023         if (!op->i.rt)
1024                 return;
1025
1026         jit_note(__FILE__, __LINE__);
1027         rs = lightrec_alloc_reg_in(reg_cache, _jit, op->i.rs);
1028         rt = lightrec_alloc_reg_out_ext(reg_cache, _jit, op->i.rt);
1029
1030         if ((state->offset_ram == state->offset_bios &&
1031             state->offset_ram == state->offset_scratch &&
1032             state->mirrors_mapped) || !op->i.imm) {
1033                 addr_reg = rs;
1034                 imm = (s16)op->i.imm;
1035         } else {
1036                 jit_addi(rt, rs, (s16)op->i.imm);
1037                 addr_reg = rt;
1038                 imm = 0;
1039
1040                 if (op->i.rs != op->i.rt)
1041                         lightrec_free_reg(reg_cache, rs);
1042         }
1043
1044         tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
1045
1046         if (state->offset_ram == state->offset_bios &&
1047             state->offset_ram == state->offset_scratch) {
1048                 if (!state->mirrors_mapped) {
1049                         jit_andi(tmp, addr_reg, BIT(28));
1050                         jit_rshi_u(tmp, tmp, 28 - 22);
1051                         jit_ori(tmp, tmp, 0x1f800000 | (RAM_SIZE - 1));
1052                         jit_andr(rt, addr_reg, tmp);
1053                 } else {
1054                         jit_andi(rt, addr_reg, 0x1fffffff);
1055                 }
1056
1057                 if (state->offset_ram)
1058                         jit_movi(tmp, state->offset_ram);
1059         } else {
1060                 to_not_ram = jit_bmsi(addr_reg, BIT(28));
1061
1062                 /* Convert to KUNSEG and avoid RAM mirrors */
1063                 jit_andi(rt, addr_reg, RAM_SIZE - 1);
1064
1065                 if (state->offset_ram)
1066                         jit_movi(tmp, state->offset_ram);
1067
1068                 to_end = jit_jmpi();
1069
1070                 jit_patch(to_not_ram);
1071
1072                 if (state->offset_bios != state->offset_scratch)
1073                         to_not_bios = jit_bmci(addr_reg, BIT(22));
1074
1075                 /* Convert to KUNSEG */
1076                 jit_andi(rt, addr_reg, 0x1fc00000 | (BIOS_SIZE - 1));
1077
1078                 jit_movi(tmp, state->offset_bios);
1079
1080                 if (state->offset_bios != state->offset_scratch) {
1081                         to_end2 = jit_jmpi();
1082
1083                         jit_patch(to_not_bios);
1084
1085                         /* Convert to KUNSEG */
1086                         jit_andi(rt, addr_reg, 0x1f800fff);
1087
1088                         if (state->offset_scratch)
1089                                 jit_movi(tmp, state->offset_scratch);
1090
1091                         jit_patch(to_end2);
1092                 }
1093
1094                 jit_patch(to_end);
1095         }
1096
1097         if (state->offset_ram || state->offset_bios || state->offset_scratch)
1098                 jit_addr(rt, rt, tmp);
1099
1100         jit_new_node_www(code, rt, rt, imm);
1101
1102         lightrec_free_reg(reg_cache, addr_reg);
1103         lightrec_free_reg(reg_cache, rt);
1104         lightrec_free_reg(reg_cache, tmp);
1105 }
1106
1107 static void rec_load(const struct block *block, const struct opcode *op,
1108                     jit_code_t code)
1109 {
1110         if (op->flags & LIGHTREC_DIRECT_IO)
1111                 rec_load_direct(block, op, code);
1112         else
1113                 rec_io(block, op, false, true);
1114 }
1115
1116 static void rec_LB(const struct block *block, const struct opcode *op, u32 pc)
1117 {
1118         _jit_name(block->_jit, __func__);
1119         rec_load(block, op, jit_code_ldxi_c);
1120 }
1121
1122 static void rec_LBU(const struct block *block, const struct opcode *op, u32 pc)
1123 {
1124         _jit_name(block->_jit, __func__);
1125         rec_load(block, op, jit_code_ldxi_uc);
1126 }
1127
1128 static void rec_LH(const struct block *block, const struct opcode *op, u32 pc)
1129 {
1130         _jit_name(block->_jit, __func__);
1131         rec_load(block, op, jit_code_ldxi_s);
1132 }
1133
1134 static void rec_LHU(const struct block *block, const struct opcode *op, u32 pc)
1135 {
1136         _jit_name(block->_jit, __func__);
1137         rec_load(block, op, jit_code_ldxi_us);
1138 }
1139
1140 static void rec_LWL(const struct block *block, const struct opcode *op, u32 pc)
1141 {
1142         _jit_name(block->_jit, __func__);
1143         rec_io(block, op, true, true);
1144 }
1145
1146 static void rec_LWR(const struct block *block, const struct opcode *op, u32 pc)
1147 {
1148         _jit_name(block->_jit, __func__);
1149         rec_io(block, op, true, true);
1150 }
1151
1152 static void rec_LW(const struct block *block, const struct opcode *op, u32 pc)
1153 {
1154         _jit_name(block->_jit, __func__);
1155         rec_load(block, op, jit_code_ldxi_i);
1156 }
1157
1158 static void rec_LWC2(const struct block *block, const struct opcode *op, u32 pc)
1159 {
1160         _jit_name(block->_jit, __func__);
1161         rec_io(block, op, false, false);
1162 }
1163
1164 static void rec_break_syscall(const struct block *block,
1165                               const struct opcode *op, u32 pc, bool is_break)
1166 {
1167         struct regcache *reg_cache = block->state->reg_cache;
1168         jit_state_t *_jit = block->_jit;
1169         u32 offset;
1170         u8 tmp;
1171
1172         jit_note(__FILE__, __LINE__);
1173
1174         if (is_break)
1175                 offset = offsetof(struct lightrec_state, break_func);
1176         else
1177                 offset = offsetof(struct lightrec_state, syscall_func);
1178
1179         tmp = lightrec_alloc_reg_temp(reg_cache, _jit);
1180         jit_ldxi(tmp, LIGHTREC_REG_STATE, offset);
1181         jit_callr(tmp);
1182         lightrec_free_reg(reg_cache, tmp);
1183
1184         lightrec_regcache_mark_live(reg_cache, _jit);
1185
1186         /* TODO: the return address should be "pc - 4" if we're a delay slot */
1187         lightrec_emit_end_of_block(block, op, pc, -1, pc, 31, 0, true);
1188 }
1189
1190 static void rec_special_SYSCALL(const struct block *block,
1191                                 const struct opcode *op, u32 pc)
1192 {
1193         _jit_name(block->_jit, __func__);
1194         rec_break_syscall(block, op, pc, false);
1195 }
1196
1197 static void rec_special_BREAK(const struct block *block,
1198                               const struct opcode *op, u32 pc)
1199 {
1200         _jit_name(block->_jit, __func__);
1201         rec_break_syscall(block, op, pc, true);
1202 }
1203
1204 static void rec_mfc(const struct block *block, const struct opcode *op)
1205 {
1206         u8 tmp, tmp2;
1207         struct lightrec_state *state = block->state;
1208         struct regcache *reg_cache = state->reg_cache;
1209         jit_state_t *_jit = block->_jit;
1210
1211         jit_note(__FILE__, __LINE__);
1212
1213         tmp = lightrec_alloc_reg(reg_cache, _jit, JIT_R0);
1214         tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit);
1215
1216         jit_ldxi(tmp2, LIGHTREC_REG_STATE,
1217                  offsetof(struct lightrec_state, mfc_func));
1218
1219         lightrec_clean_reg_if_loaded(reg_cache, _jit, op->i.rt, true);
1220
1221         jit_movi(tmp, op->opcode);
1222         jit_callr(tmp2);
1223         lightrec_free_reg(reg_cache, tmp);
1224         lightrec_free_reg(reg_cache, tmp2);
1225
1226         lightrec_regcache_mark_live(reg_cache, _jit);
1227 }
1228
1229 static void rec_mtc(const struct block *block, const struct opcode *op, u32 pc)
1230 {
1231         struct lightrec_state *state = block->state;
1232         struct regcache *reg_cache = state->reg_cache;
1233         jit_state_t *_jit = block->_jit;
1234         u8 tmp, tmp2;
1235
1236         jit_note(__FILE__, __LINE__);
1237
1238         tmp = lightrec_alloc_reg(reg_cache, _jit, JIT_R0);
1239         tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit);
1240         jit_ldxi(tmp2, LIGHTREC_REG_STATE,
1241                  offsetof(struct lightrec_state, mtc_func));
1242
1243         lightrec_clean_reg_if_loaded(reg_cache, _jit, op->i.rs, false);
1244         lightrec_clean_reg_if_loaded(reg_cache, _jit, op->i.rt, false);
1245
1246         jit_movi(tmp, op->opcode);
1247         jit_callr(tmp2);
1248         lightrec_free_reg(reg_cache, tmp);
1249         lightrec_free_reg(reg_cache, tmp2);
1250
1251         lightrec_regcache_mark_live(reg_cache, _jit);
1252
1253         if (op->i.op == OP_CP0 && !(op->flags & LIGHTREC_NO_DS) &&
1254             (op->r.rd == 12 || op->r.rd == 13))
1255                 lightrec_emit_end_of_block(block, op, pc, -1, pc + 4, 0, 0, true);
1256 }
1257
1258 static void rec_cp0_MFC0(const struct block *block,
1259                          const struct opcode *op, u32 pc)
1260 {
1261         _jit_name(block->_jit, __func__);
1262         rec_mfc(block, op);
1263 }
1264
1265 static void rec_cp0_CFC0(const struct block *block,
1266                          const struct opcode *op, u32 pc)
1267 {
1268         _jit_name(block->_jit, __func__);
1269         rec_mfc(block, op);
1270 }
1271
1272 static void rec_cp0_MTC0(const struct block *block,
1273                          const struct opcode *op, u32 pc)
1274 {
1275         _jit_name(block->_jit, __func__);
1276         rec_mtc(block, op, pc);
1277 }
1278
1279 static void rec_cp0_CTC0(const struct block *block,
1280                          const struct opcode *op, u32 pc)
1281 {
1282         _jit_name(block->_jit, __func__);
1283         rec_mtc(block, op, pc);
1284 }
1285
1286 static void rec_cp2_basic_MFC2(const struct block *block,
1287                                const struct opcode *op, u32 pc)
1288 {
1289         _jit_name(block->_jit, __func__);
1290         rec_mfc(block, op);
1291 }
1292
1293 static void rec_cp2_basic_CFC2(const struct block *block,
1294                                const struct opcode *op, u32 pc)
1295 {
1296         _jit_name(block->_jit, __func__);
1297         rec_mfc(block, op);
1298 }
1299
1300 static void rec_cp2_basic_MTC2(const struct block *block,
1301                                const struct opcode *op, u32 pc)
1302 {
1303         _jit_name(block->_jit, __func__);
1304         rec_mtc(block, op, pc);
1305 }
1306
1307 static void rec_cp2_basic_CTC2(const struct block *block,
1308                                const struct opcode *op, u32 pc)
1309 {
1310         _jit_name(block->_jit, __func__);
1311         rec_mtc(block, op, pc);
1312 }
1313
1314 static void rec_cp0_RFE(const struct block *block,
1315                         const struct opcode *op, u32 pc)
1316 {
1317         struct lightrec_state *state = block->state;
1318         jit_state_t *_jit = block->_jit;
1319         u8 tmp;
1320
1321         jit_name(__func__);
1322         jit_note(__FILE__, __LINE__);
1323
1324         tmp = lightrec_alloc_reg_temp(state->reg_cache, _jit);
1325         jit_ldxi(tmp, LIGHTREC_REG_STATE,
1326                  offsetof(struct lightrec_state, rfe_func));
1327         jit_callr(tmp);
1328         lightrec_free_reg(state->reg_cache, tmp);
1329
1330         lightrec_regcache_mark_live(state->reg_cache, _jit);
1331 }
1332
1333 static void rec_CP(const struct block *block, const struct opcode *op, u32 pc)
1334 {
1335         struct regcache *reg_cache = block->state->reg_cache;
1336         jit_state_t *_jit = block->_jit;
1337         u8 tmp, tmp2;
1338
1339         jit_name(__func__);
1340         jit_note(__FILE__, __LINE__);
1341
1342         tmp = lightrec_alloc_reg(reg_cache, _jit, JIT_R0);
1343         tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit);
1344
1345         jit_ldxi(tmp2, LIGHTREC_REG_STATE,
1346                  offsetof(struct lightrec_state, cp_func));
1347
1348         jit_movi(tmp, op->opcode);
1349         jit_callr(tmp2);
1350         lightrec_free_reg(reg_cache, tmp);
1351         lightrec_free_reg(reg_cache, tmp2);
1352
1353         lightrec_regcache_mark_live(reg_cache, _jit);
1354 }
1355
1356 static void rec_meta_unload(const struct block *block,
1357                             const struct opcode *op, u32 pc)
1358 {
1359         struct lightrec_state *state = block->state;
1360         struct regcache *reg_cache = state->reg_cache;
1361         jit_state_t *_jit = block->_jit;
1362
1363         jit_name(__func__);
1364         jit_note(__FILE__, __LINE__);
1365
1366         pr_debug("Unloading reg %s\n", lightrec_reg_name(op->i.rs));
1367         lightrec_clean_reg_if_loaded(reg_cache, _jit, op->i.rs, true);
1368 }
1369
1370 static void rec_meta_BEQZ(const struct block *block,
1371                           const struct opcode *op, u32 pc)
1372 {
1373         _jit_name(block->_jit, __func__);
1374         rec_b(block, op, pc, jit_code_bnei, 0, false, true);
1375 }
1376
1377 static void rec_meta_BNEZ(const struct block *block,
1378                           const struct opcode *op, u32 pc)
1379 {
1380         _jit_name(block->_jit, __func__);
1381         rec_b(block, op, pc, jit_code_beqi, 0, false, true);
1382 }
1383
1384 static void rec_meta_MOV(const struct block *block,
1385                          const struct opcode *op, u32 pc)
1386 {
1387         struct lightrec_state *state = block->state;
1388         struct regcache *reg_cache = state->reg_cache;
1389         jit_state_t *_jit = block->_jit;
1390         u8 rs, rd;
1391
1392         _jit_name(block->_jit, __func__);
1393         jit_note(__FILE__, __LINE__);
1394         rs = op->r.rs ? lightrec_alloc_reg_in(reg_cache, _jit, op->r.rs) : 0;
1395         rd = lightrec_alloc_reg_out_ext(reg_cache, _jit, op->r.rd);
1396
1397         if (op->r.rs == 0) {
1398                 jit_movi(rd, 0);
1399         } else {
1400 #if __WORDSIZE == 32
1401                 jit_movr(rd, rs);
1402 #else
1403                 jit_extr_i(rd, rs);
1404 #endif
1405         }
1406
1407         lightrec_free_reg(state->reg_cache, rs);
1408         lightrec_free_reg(state->reg_cache, rd);
1409 }
1410
1411 static void rec_meta_sync(const struct block *block,
1412                           const struct opcode *op, u32 pc)
1413 {
1414         struct lightrec_state *state = block->state;
1415         struct lightrec_branch_target *target;
1416         jit_state_t *_jit = block->_jit;
1417
1418         jit_name(__func__);
1419         jit_note(__FILE__, __LINE__);
1420
1421         jit_subi(LIGHTREC_REG_CYCLE, LIGHTREC_REG_CYCLE, state->cycles);
1422         state->cycles = 0;
1423
1424         lightrec_storeback_regs(state->reg_cache, _jit);
1425         lightrec_regcache_reset(state->reg_cache);
1426
1427         pr_debug("Adding branch target at offset 0x%x\n",
1428                  op->offset << 2);
1429         target = &state->targets[state->nb_targets++];
1430         target->offset = op->offset;
1431         target->label = jit_indirect();
1432 }
1433
1434 static const lightrec_rec_func_t rec_standard[64] = {
1435         [OP_SPECIAL]            = rec_SPECIAL,
1436         [OP_REGIMM]             = rec_REGIMM,
1437         [OP_J]                  = rec_J,
1438         [OP_JAL]                = rec_JAL,
1439         [OP_BEQ]                = rec_BEQ,
1440         [OP_BNE]                = rec_BNE,
1441         [OP_BLEZ]               = rec_BLEZ,
1442         [OP_BGTZ]               = rec_BGTZ,
1443         [OP_ADDI]               = rec_ADDI,
1444         [OP_ADDIU]              = rec_ADDIU,
1445         [OP_SLTI]               = rec_SLTI,
1446         [OP_SLTIU]              = rec_SLTIU,
1447         [OP_ANDI]               = rec_ANDI,
1448         [OP_ORI]                = rec_ORI,
1449         [OP_XORI]               = rec_XORI,
1450         [OP_LUI]                = rec_LUI,
1451         [OP_CP0]                = rec_CP0,
1452         [OP_CP2]                = rec_CP2,
1453         [OP_LB]                 = rec_LB,
1454         [OP_LH]                 = rec_LH,
1455         [OP_LWL]                = rec_LWL,
1456         [OP_LW]                 = rec_LW,
1457         [OP_LBU]                = rec_LBU,
1458         [OP_LHU]                = rec_LHU,
1459         [OP_LWR]                = rec_LWR,
1460         [OP_SB]                 = rec_SB,
1461         [OP_SH]                 = rec_SH,
1462         [OP_SWL]                = rec_SWL,
1463         [OP_SW]                 = rec_SW,
1464         [OP_SWR]                = rec_SWR,
1465         [OP_LWC2]               = rec_LWC2,
1466         [OP_SWC2]               = rec_SWC2,
1467
1468         [OP_META_REG_UNLOAD]    = rec_meta_unload,
1469         [OP_META_BEQZ]          = rec_meta_BEQZ,
1470         [OP_META_BNEZ]          = rec_meta_BNEZ,
1471         [OP_META_MOV]           = rec_meta_MOV,
1472         [OP_META_SYNC]          = rec_meta_sync,
1473 };
1474
1475 static const lightrec_rec_func_t rec_special[64] = {
1476         [OP_SPECIAL_SLL]        = rec_special_SLL,
1477         [OP_SPECIAL_SRL]        = rec_special_SRL,
1478         [OP_SPECIAL_SRA]        = rec_special_SRA,
1479         [OP_SPECIAL_SLLV]       = rec_special_SLLV,
1480         [OP_SPECIAL_SRLV]       = rec_special_SRLV,
1481         [OP_SPECIAL_SRAV]       = rec_special_SRAV,
1482         [OP_SPECIAL_JR]         = rec_special_JR,
1483         [OP_SPECIAL_JALR]       = rec_special_JALR,
1484         [OP_SPECIAL_SYSCALL]    = rec_special_SYSCALL,
1485         [OP_SPECIAL_BREAK]      = rec_special_BREAK,
1486         [OP_SPECIAL_MFHI]       = rec_special_MFHI,
1487         [OP_SPECIAL_MTHI]       = rec_special_MTHI,
1488         [OP_SPECIAL_MFLO]       = rec_special_MFLO,
1489         [OP_SPECIAL_MTLO]       = rec_special_MTLO,
1490         [OP_SPECIAL_MULT]       = rec_special_MULT,
1491         [OP_SPECIAL_MULTU]      = rec_special_MULTU,
1492         [OP_SPECIAL_DIV]        = rec_special_DIV,
1493         [OP_SPECIAL_DIVU]       = rec_special_DIVU,
1494         [OP_SPECIAL_ADD]        = rec_special_ADD,
1495         [OP_SPECIAL_ADDU]       = rec_special_ADDU,
1496         [OP_SPECIAL_SUB]        = rec_special_SUB,
1497         [OP_SPECIAL_SUBU]       = rec_special_SUBU,
1498         [OP_SPECIAL_AND]        = rec_special_AND,
1499         [OP_SPECIAL_OR]         = rec_special_OR,
1500         [OP_SPECIAL_XOR]        = rec_special_XOR,
1501         [OP_SPECIAL_NOR]        = rec_special_NOR,
1502         [OP_SPECIAL_SLT]        = rec_special_SLT,
1503         [OP_SPECIAL_SLTU]       = rec_special_SLTU,
1504 };
1505
1506 static const lightrec_rec_func_t rec_regimm[64] = {
1507         [OP_REGIMM_BLTZ]        = rec_regimm_BLTZ,
1508         [OP_REGIMM_BGEZ]        = rec_regimm_BGEZ,
1509         [OP_REGIMM_BLTZAL]      = rec_regimm_BLTZAL,
1510         [OP_REGIMM_BGEZAL]      = rec_regimm_BGEZAL,
1511 };
1512
1513 static const lightrec_rec_func_t rec_cp0[64] = {
1514         [OP_CP0_MFC0]           = rec_cp0_MFC0,
1515         [OP_CP0_CFC0]           = rec_cp0_CFC0,
1516         [OP_CP0_MTC0]           = rec_cp0_MTC0,
1517         [OP_CP0_CTC0]           = rec_cp0_CTC0,
1518         [OP_CP0_RFE]            = rec_cp0_RFE,
1519 };
1520
1521 static const lightrec_rec_func_t rec_cp2_basic[64] = {
1522         [OP_CP2_BASIC_MFC2]     = rec_cp2_basic_MFC2,
1523         [OP_CP2_BASIC_CFC2]     = rec_cp2_basic_CFC2,
1524         [OP_CP2_BASIC_MTC2]     = rec_cp2_basic_MTC2,
1525         [OP_CP2_BASIC_CTC2]     = rec_cp2_basic_CTC2,
1526 };
1527
1528 static void rec_SPECIAL(const struct block *block,
1529                         const struct opcode *op, u32 pc)
1530 {
1531         lightrec_rec_func_t f = rec_special[op->r.op];
1532         if (likely(f))
1533                 (*f)(block, op, pc);
1534         else
1535                 unknown_opcode(block, op, pc);
1536 }
1537
1538 static void rec_REGIMM(const struct block *block,
1539                        const struct opcode *op, u32 pc)
1540 {
1541         lightrec_rec_func_t f = rec_regimm[op->r.rt];
1542         if (likely(f))
1543                 (*f)(block, op, pc);
1544         else
1545                 unknown_opcode(block, op, pc);
1546 }
1547
1548 static void rec_CP0(const struct block *block, const struct opcode *op, u32 pc)
1549 {
1550         lightrec_rec_func_t f = rec_cp0[op->r.rs];
1551         if (likely(f))
1552                 (*f)(block, op, pc);
1553         else
1554                 rec_CP(block, op, pc);
1555 }
1556
1557 static void rec_CP2(const struct block *block, const struct opcode *op, u32 pc)
1558 {
1559         if (op->r.op == OP_CP2_BASIC) {
1560                 lightrec_rec_func_t f = rec_cp2_basic[op->r.rs];
1561                 if (likely(f)) {
1562                         (*f)(block, op, pc);
1563                         return;
1564                 }
1565         }
1566
1567         rec_CP(block, op, pc);
1568 }
1569
1570 void lightrec_rec_opcode(const struct block *block,
1571                          const struct opcode *op, u32 pc)
1572 {
1573         lightrec_rec_func_t f = rec_standard[op->i.op];
1574         if (likely(f))
1575                 (*f)(block, op, pc);
1576         else
1577                 unknown_opcode(block, op, pc);
1578 }