Handle DIV overflow in lightrec and the interpreter
[pcsx_rearmed.git] / deps / lightrec / interpreter.c
CommitLineData
d16005f8
PC
1/*
2 * Copyright (C) 2019-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 "disassembler.h"
16#include "interpreter.h"
17#include "lightrec-private.h"
18#include "optimizer.h"
19#include "regcache.h"
20
21#include <stdbool.h>
22
23struct interpreter;
24
25static u32 int_CP0(struct interpreter *inter);
26static u32 int_CP2(struct interpreter *inter);
27static u32 int_SPECIAL(struct interpreter *inter);
28static u32 int_REGIMM(struct interpreter *inter);
29static u32 int_branch(struct interpreter *inter, u32 pc,
30 union code code, bool branch);
31
32typedef u32 (*lightrec_int_func_t)(struct interpreter *inter);
33
34static const lightrec_int_func_t int_standard[64];
35
36struct interpreter {
37 struct lightrec_state *state;
38 struct block *block;
39 struct opcode *op;
40 u32 cycles;
41 bool delay_slot;
42};
43
44static inline u32 execute(lightrec_int_func_t func, struct interpreter *inter)
45{
46 return (*func)(inter);
47}
48
49static inline u32 jump_skip(struct interpreter *inter)
50{
51 inter->op = inter->op->next;
52
53 return execute(int_standard[inter->op->i.op], inter);
54}
55
56static inline u32 jump_next(struct interpreter *inter)
57{
58 inter->cycles += lightrec_cycles_of_opcode(inter->op->c);
59
60 if (unlikely(inter->delay_slot))
61 return 0;
62
63 return jump_skip(inter);
64}
65
66static inline u32 jump_after_branch(struct interpreter *inter)
67{
68 inter->cycles += lightrec_cycles_of_opcode(inter->op->c);
69
70 if (unlikely(inter->delay_slot))
71 return 0;
72
73 inter->op = inter->op->next;
74
75 return jump_skip(inter);
76}
77
78static void update_cycles_before_branch(struct interpreter *inter)
79{
80 u32 cycles;
81
82 if (!inter->delay_slot) {
83 cycles = lightrec_cycles_of_opcode(inter->op->c);
84
85 if (has_delay_slot(inter->op->c) &&
86 !(inter->op->flags & LIGHTREC_NO_DS))
87 cycles += lightrec_cycles_of_opcode(inter->op->next->c);
88
89 inter->cycles += cycles;
90 inter->state->current_cycle += inter->cycles;
91 inter->cycles = -cycles;
92 }
93}
94
95static bool is_branch_taken(const u32 *reg_cache, union code op)
96{
97 switch (op.i.op) {
98 case OP_SPECIAL:
99 return op.r.op == OP_SPECIAL_JR || op.r.op == OP_SPECIAL_JALR;
100 case OP_J:
101 case OP_JAL:
102 return true;
103 case OP_BEQ:
104 case OP_META_BEQZ:
105 return reg_cache[op.r.rs] == reg_cache[op.r.rt];
106 case OP_BNE:
107 case OP_META_BNEZ:
108 return reg_cache[op.r.rs] != reg_cache[op.r.rt];
109 case OP_REGIMM:
110 switch (op.r.rt) {
111 case OP_REGIMM_BLTZ:
112 case OP_REGIMM_BLTZAL:
113 return (s32)reg_cache[op.r.rs] < 0;
114 case OP_REGIMM_BGEZ:
115 case OP_REGIMM_BGEZAL:
116 return (s32)reg_cache[op.r.rs] >= 0;
117 }
118 default:
119 break;
120 }
121
122 return false;
123}
124
125static u32 int_delay_slot(struct interpreter *inter, u32 pc, bool branch)
126{
127 struct lightrec_state *state = inter->state;
128 u32 *reg_cache = state->native_reg_cache;
129 struct opcode new_op, *op = inter->op->next;
130 union code op_next;
131 struct interpreter inter2 = {
132 .state = state,
133 .cycles = inter->cycles,
134 .delay_slot = true,
135 .block = NULL,
136 };
137 bool run_first_op = false, dummy_ld = false, save_rs = false,
138 load_in_ds, branch_in_ds = false, branch_at_addr = false,
139 branch_taken;
140 u32 old_rs, new_rs, new_rt;
141 u32 next_pc, ds_next_pc;
142 u32 cause, epc;
143
144 if (op->i.op == OP_CP0 && op->r.rs == OP_CP0_RFE) {
145 /* When an IRQ happens, the PSX exception handlers (when done)
146 * will jump back to the instruction that was executed right
147 * before the IRQ, unless it was a GTE opcode; in that case, it
148 * jumps to the instruction right after.
149 * Since we will never handle the IRQ right after a GTE opcode,
150 * but on branch boundaries, we need to adjust the return
151 * address so that the GTE opcode is effectively executed.
152 */
a59e5536 153 cause = (*state->ops.cop0_ops.cfc)(state, op->c.opcode, 13);
154 epc = (*state->ops.cop0_ops.cfc)(state, op->c.opcode, 14);
d16005f8
PC
155
156 if (!(cause & 0x7c) && epc == pc - 4)
157 pc -= 4;
158 }
159
160 if (inter->delay_slot) {
161 /* The branch opcode was in a delay slot of another branch
162 * opcode. Just return the target address of the second
163 * branch. */
164 return pc;
165 }
166
167 /* An opcode located in the delay slot performing a delayed read
168 * requires special handling; we will always resort to using the
169 * interpreter in that case.
170 * Same goes for when we have a branch in a delay slot of another
171 * branch. */
172 load_in_ds = load_in_delay_slot(op->c);
173 branch_in_ds = has_delay_slot(op->c);
174
175 if (branch) {
176 if (load_in_ds || branch_in_ds)
177 op_next = lightrec_read_opcode(state, pc);
178
179 if (load_in_ds) {
180 /* Verify that the next block actually reads the
181 * destination register of the delay slot opcode. */
182 run_first_op = opcode_reads_register(op_next, op->r.rt);
183 }
184
185 if (branch_in_ds) {
186 run_first_op = true;
187 next_pc = pc + 4;
188 }
189
190 if (load_in_ds && run_first_op) {
191 next_pc = pc + 4;
192
193 /* If the first opcode of the next block writes the
194 * regiser used as the address for the load, we need to
195 * reset to the old value after it has been executed,
196 * then restore the new value after the delay slot
197 * opcode has been executed. */
198 save_rs = opcode_reads_register(op->c, op->r.rs) &&
199 opcode_writes_register(op_next, op->r.rs);
200 if (save_rs)
201 old_rs = reg_cache[op->r.rs];
202
203 /* If both the first opcode of the next block and the
204 * delay slot opcode write to the same register, the
205 * value written by the delay slot opcode is
206 * discarded. */
207 dummy_ld = opcode_writes_register(op_next, op->r.rt);
208 }
209
210 if (!run_first_op) {
211 next_pc = pc;
212 } else if (has_delay_slot(op_next)) {
213 /* The first opcode of the next block is a branch, so we
214 * cannot execute it here, because of the load delay.
215 * Just check whether or not the branch would be taken,
216 * and save that info into the interpreter struct. */
217 branch_at_addr = true;
218 branch_taken = is_branch_taken(reg_cache, op_next);
219 pr_debug("Target of impossible branch is a branch, "
220 "%staken.\n", branch_taken ? "" : "not ");
a59e5536 221 inter->cycles += lightrec_cycles_of_opcode(op_next);
222 old_rs = reg_cache[op_next.r.rs];
d16005f8
PC
223 } else {
224 new_op.c = op_next;
225 new_op.flags = 0;
226 new_op.offset = 0;
227 new_op.next = NULL;
228 inter2.op = &new_op;
229
230 /* Execute the first opcode of the next block */
231 (*int_standard[inter2.op->i.op])(&inter2);
232
233 if (save_rs) {
234 new_rs = reg_cache[op->r.rs];
235 reg_cache[op->r.rs] = old_rs;
236 }
237
238 inter->cycles += lightrec_cycles_of_opcode(op_next);
239 }
240 } else {
241 next_pc = inter->block->pc
242 + (inter->op->offset + 2) * sizeof(u32);
243 }
244
245 inter2.block = inter->block;
246 inter2.op = op;
247 inter2.cycles = inter->cycles;
248
249 if (dummy_ld)
250 new_rt = reg_cache[op->r.rt];
251
252 /* Execute delay slot opcode */
a59e5536 253 ds_next_pc = (*int_standard[inter2.op->i.op])(&inter2);
254
255 if (branch_at_addr) {
256 if (op_next.i.op == OP_SPECIAL)
257 /* TODO: Handle JALR setting $ra */
258 ds_next_pc = old_rs;
259 else if (op_next.i.op == OP_J || op_next.i.op == OP_JAL)
260 /* TODO: Handle JAL setting $ra */
261 ds_next_pc = (pc & 0xf0000000) | (op_next.j.imm << 2);
262 else
263 ds_next_pc = pc + 4 + ((s16)op_next.i.imm << 2);
264 }
d16005f8
PC
265
266 if (branch_at_addr && !branch_taken) {
267 /* If the branch at the target of the branch opcode is not
268 * taken, we jump to its delay slot */
269 next_pc = pc + sizeof(u32);
a59e5536 270 } else if (branch_at_addr || (!branch && branch_in_ds)) {
d16005f8
PC
271 next_pc = ds_next_pc;
272 }
273
274 if (save_rs)
275 reg_cache[op->r.rs] = new_rs;
276 if (dummy_ld)
277 reg_cache[op->r.rt] = new_rt;
278
279 inter->cycles += lightrec_cycles_of_opcode(op->c);
280
281 if (branch_at_addr && branch_taken) {
282 /* If the branch at the target of the branch opcode is taken,
283 * we execute its delay slot here, and jump to its target
284 * address. */
285 op_next = lightrec_read_opcode(state, pc + 4);
286
287 new_op.c = op_next;
288 new_op.flags = 0;
289 new_op.offset = sizeof(u32);
290 new_op.next = NULL;
291 inter2.op = &new_op;
292 inter2.block = NULL;
293
294 inter->cycles += lightrec_cycles_of_opcode(op_next);
295
296 pr_debug("Running delay slot of branch at target of impossible "
297 "branch\n");
298 (*int_standard[inter2.op->i.op])(&inter2);
299 }
300
301 return next_pc;
302}
303
304static u32 int_unimplemented(struct interpreter *inter)
305{
306 pr_warn("Unimplemented opcode 0x%08x\n", inter->op->opcode);
307
308 return jump_next(inter);
309}
310
311static u32 int_jump(struct interpreter *inter, bool link)
312{
313 struct lightrec_state *state = inter->state;
314 u32 old_pc = inter->block->pc + inter->op->offset * sizeof(u32);
315 u32 pc = (old_pc & 0xf0000000) | (inter->op->j.imm << 2);
316
317 if (link)
318 state->native_reg_cache[31] = old_pc + 8;
319
320 if (inter->op->flags & LIGHTREC_NO_DS)
321 return pc;
322
323 return int_delay_slot(inter, pc, true);
324}
325
326static u32 int_J(struct interpreter *inter)
327{
328 return int_jump(inter, false);
329}
330
331static u32 int_JAL(struct interpreter *inter)
332{
333 return int_jump(inter, true);
334}
335
336static u32 int_jumpr(struct interpreter *inter, u8 link_reg)
337{
338 struct lightrec_state *state = inter->state;
339 u32 old_pc, next_pc = state->native_reg_cache[inter->op->r.rs];
340
341 if (link_reg) {
342 old_pc = inter->block->pc + inter->op->offset * sizeof(u32);
343 state->native_reg_cache[link_reg] = old_pc + 8;
344 }
345
346 if (inter->op->flags & LIGHTREC_NO_DS)
347 return next_pc;
348
349 return int_delay_slot(inter, next_pc, true);
350}
351
352static u32 int_special_JR(struct interpreter *inter)
353{
354 return int_jumpr(inter, 0);
355}
356
357static u32 int_special_JALR(struct interpreter *inter)
358{
359 return int_jumpr(inter, inter->op->r.rd);
360}
361
362static u32 int_do_branch(struct interpreter *inter, u32 old_pc, u32 next_pc)
363{
364 if (!inter->delay_slot &&
365 (inter->op->flags & LIGHTREC_LOCAL_BRANCH) &&
366 (s16)inter->op->c.i.imm >= 0) {
367 next_pc = old_pc + ((1 + (s16)inter->op->c.i.imm) << 2);
368 next_pc = lightrec_emulate_block(inter->block, next_pc);
369 }
370
371 return next_pc;
372}
373
374static u32 int_branch(struct interpreter *inter, u32 pc,
375 union code code, bool branch)
376{
377 u32 next_pc = pc + 4 + ((s16)code.i.imm << 2);
378
379 update_cycles_before_branch(inter);
380
381 if (inter->op->flags & LIGHTREC_NO_DS) {
382 if (branch)
383 return int_do_branch(inter, pc, next_pc);
384 else
385 return jump_next(inter);
386 }
387
388 if (!inter->delay_slot)
389 next_pc = int_delay_slot(inter, next_pc, branch);
390
391 if (branch)
392 return int_do_branch(inter, pc, next_pc);
393
394 if (inter->op->flags & LIGHTREC_EMULATE_BRANCH)
395 return pc + 8;
396 else
397 return jump_after_branch(inter);
398}
399
400static u32 int_beq(struct interpreter *inter, bool bne)
401{
402 u32 rs, rt, old_pc = inter->block->pc + inter->op->offset * sizeof(u32);
403
404 rs = inter->state->native_reg_cache[inter->op->i.rs];
405 rt = inter->state->native_reg_cache[inter->op->i.rt];
406
407 return int_branch(inter, old_pc, inter->op->c, (rs == rt) ^ bne);
408}
409
410static u32 int_BEQ(struct interpreter *inter)
411{
412 return int_beq(inter, false);
413}
414
415static u32 int_BNE(struct interpreter *inter)
416{
417 return int_beq(inter, true);
418}
419
420static u32 int_bgez(struct interpreter *inter, bool link, bool lt, bool regimm)
421{
422 u32 old_pc = inter->block->pc + inter->op->offset * sizeof(u32);
423 s32 rs;
424
425 if (link)
426 inter->state->native_reg_cache[31] = old_pc + 8;
427
428 rs = (s32)inter->state->native_reg_cache[inter->op->i.rs];
429
430 return int_branch(inter, old_pc, inter->op->c,
431 ((regimm && !rs) || rs > 0) ^ lt);
432}
433
434static u32 int_regimm_BLTZ(struct interpreter *inter)
435{
436 return int_bgez(inter, false, true, true);
437}
438
439static u32 int_regimm_BGEZ(struct interpreter *inter)
440{
441 return int_bgez(inter, false, false, true);
442}
443
444static u32 int_regimm_BLTZAL(struct interpreter *inter)
445{
446 return int_bgez(inter, true, true, true);
447}
448
449static u32 int_regimm_BGEZAL(struct interpreter *inter)
450{
451 return int_bgez(inter, true, false, true);
452}
453
454static u32 int_BLEZ(struct interpreter *inter)
455{
456 return int_bgez(inter, false, true, false);
457}
458
459static u32 int_BGTZ(struct interpreter *inter)
460{
461 return int_bgez(inter, false, false, false);
462}
463
464static u32 int_cfc(struct interpreter *inter)
465{
466 struct lightrec_state *state = inter->state;
467 const struct opcode *op = inter->op;
468 u32 val;
469
470 val = lightrec_mfc(state, op->c);
471
472 if (likely(op->r.rt))
473 state->native_reg_cache[op->r.rt] = val;
474
475 return jump_next(inter);
476}
477
478static u32 int_ctc(struct interpreter *inter)
479{
480 struct lightrec_state *state = inter->state;
481 const struct opcode *op = inter->op;
482
483 lightrec_mtc(state, op->c, state->native_reg_cache[op->r.rt]);
484
485 /* If we have a MTC0 or CTC0 to CP0 register 12 (Status) or 13 (Cause),
486 * return early so that the emulator will be able to check software
487 * interrupt status. */
a59e5536 488 if (!(inter->op->flags & LIGHTREC_NO_DS) &&
489 op->i.op == OP_CP0 && (op->r.rd == 12 || op->r.rd == 13))
d16005f8
PC
490 return inter->block->pc + (op->offset + 1) * sizeof(u32);
491 else
492 return jump_next(inter);
493}
494
495static u32 int_cp0_RFE(struct interpreter *inter)
496{
497 struct lightrec_state *state = inter->state;
498 u32 status;
499
500 /* Read CP0 Status register (r12) */
a59e5536 501 status = state->ops.cop0_ops.mfc(state, inter->op->c.opcode, 12);
d16005f8
PC
502
503 /* Switch the bits */
504 status = ((status & 0x3c) >> 2) | (status & ~0xf);
505
506 /* Write it back */
a59e5536 507 state->ops.cop0_ops.ctc(state, inter->op->c.opcode, 12, status);
d16005f8
PC
508
509 return jump_next(inter);
510}
511
512static u32 int_CP(struct interpreter *inter)
513{
514 struct lightrec_state *state = inter->state;
515 const struct lightrec_cop_ops *ops;
516 const struct opcode *op = inter->op;
517
518 if ((op->j.imm >> 25) & 1)
519 ops = &state->ops.cop2_ops;
520 else
521 ops = &state->ops.cop0_ops;
522
523 (*ops->op)(state, (op->j.imm) & ~(1 << 25));
524
525 return jump_next(inter);
526}
527
528static u32 int_ADDI(struct interpreter *inter)
529{
530 u32 *reg_cache = inter->state->native_reg_cache;
531 struct opcode_i *op = &inter->op->i;
532
533 if (likely(op->rt))
534 reg_cache[op->rt] = reg_cache[op->rs] + (s32)(s16)op->imm;
535
536 return jump_next(inter);
537}
538
539static u32 int_SLTI(struct interpreter *inter)
540{
541 u32 *reg_cache = inter->state->native_reg_cache;
542 struct opcode_i *op = &inter->op->i;
543
544 if (likely(op->rt))
545 reg_cache[op->rt] = (s32)reg_cache[op->rs] < (s32)(s16)op->imm;
546
547 return jump_next(inter);
548}
549
550static u32 int_SLTIU(struct interpreter *inter)
551{
552 u32 *reg_cache = inter->state->native_reg_cache;
553 struct opcode_i *op = &inter->op->i;
554
555 if (likely(op->rt))
556 reg_cache[op->rt] = reg_cache[op->rs] < (u32)(s32)(s16)op->imm;
557
558 return jump_next(inter);
559}
560
561static u32 int_ANDI(struct interpreter *inter)
562{
563 u32 *reg_cache = inter->state->native_reg_cache;
564 struct opcode_i *op = &inter->op->i;
565
566 if (likely(op->rt))
567 reg_cache[op->rt] = reg_cache[op->rs] & op->imm;
568
569 return jump_next(inter);
570}
571
572static u32 int_ORI(struct interpreter *inter)
573{
574 u32 *reg_cache = inter->state->native_reg_cache;
575 struct opcode_i *op = &inter->op->i;
576
577 if (likely(op->rt))
578 reg_cache[op->rt] = reg_cache[op->rs] | op->imm;
579
580 return jump_next(inter);
581}
582
583static u32 int_XORI(struct interpreter *inter)
584{
585 u32 *reg_cache = inter->state->native_reg_cache;
586 struct opcode_i *op = &inter->op->i;
587
588 if (likely(op->rt))
589 reg_cache[op->rt] = reg_cache[op->rs] ^ op->imm;
590
591 return jump_next(inter);
592}
593
594static u32 int_LUI(struct interpreter *inter)
595{
596 struct opcode_i *op = &inter->op->i;
597
598 inter->state->native_reg_cache[op->rt] = op->imm << 16;
599
600 return jump_next(inter);
601}
602
603static u32 int_io(struct interpreter *inter, bool is_load)
604{
605 struct opcode_i *op = &inter->op->i;
606 u32 *reg_cache = inter->state->native_reg_cache;
607 u32 val;
608
609 val = lightrec_rw(inter->state, inter->op->c,
610 reg_cache[op->rs], reg_cache[op->rt],
611 &inter->op->flags);
612
613 if (is_load && op->rt)
614 reg_cache[op->rt] = val;
615
616 return jump_next(inter);
617}
618
619static u32 int_load(struct interpreter *inter)
620{
621 return int_io(inter, true);
622}
623
624static u32 int_store(struct interpreter *inter)
625{
626 u32 next_pc;
627
628 if (likely(!(inter->op->flags & LIGHTREC_SMC)))
629 return int_io(inter, false);
630
631 lightrec_rw(inter->state, inter->op->c,
632 inter->state->native_reg_cache[inter->op->i.rs],
633 inter->state->native_reg_cache[inter->op->i.rt],
634 &inter->op->flags);
635
636 next_pc = inter->block->pc + (inter->op->offset + 1) * 4;
637
638 /* Invalidate next PC, to force the rest of the block to be rebuilt */
639 lightrec_invalidate(inter->state, next_pc, 4);
640
641 return next_pc;
642}
643
644static u32 int_LWC2(struct interpreter *inter)
645{
646 return int_io(inter, false);
647}
648
649static u32 int_special_SLL(struct interpreter *inter)
650{
651 struct opcode *op = inter->op;
652 u32 rt;
653
654 if (op->opcode) { /* Handle NOPs */
655 rt = inter->state->native_reg_cache[op->r.rt];
656 inter->state->native_reg_cache[op->r.rd] = rt << op->r.imm;
657 }
658
659 return jump_next(inter);
660}
661
662static u32 int_special_SRL(struct interpreter *inter)
663{
664 struct opcode *op = inter->op;
665 u32 rt = inter->state->native_reg_cache[op->r.rt];
666
667 inter->state->native_reg_cache[op->r.rd] = rt >> op->r.imm;
668
669 return jump_next(inter);
670}
671
672static u32 int_special_SRA(struct interpreter *inter)
673{
674 struct opcode *op = inter->op;
675 s32 rt = inter->state->native_reg_cache[op->r.rt];
676
677 inter->state->native_reg_cache[op->r.rd] = rt >> op->r.imm;
678
679 return jump_next(inter);
680}
681
682static u32 int_special_SLLV(struct interpreter *inter)
683{
684 struct opcode *op = inter->op;
685 u32 rs = inter->state->native_reg_cache[op->r.rs];
686 u32 rt = inter->state->native_reg_cache[op->r.rt];
687
688 inter->state->native_reg_cache[op->r.rd] = rt << (rs & 0x1f);
689
690 return jump_next(inter);
691}
692
693static u32 int_special_SRLV(struct interpreter *inter)
694{
695 struct opcode *op = inter->op;
696 u32 rs = inter->state->native_reg_cache[op->r.rs];
697 u32 rt = inter->state->native_reg_cache[op->r.rt];
698
699 inter->state->native_reg_cache[op->r.rd] = rt >> (rs & 0x1f);
700
701 return jump_next(inter);
702}
703
704static u32 int_special_SRAV(struct interpreter *inter)
705{
706 struct opcode *op = inter->op;
707 u32 rs = inter->state->native_reg_cache[op->r.rs];
708 s32 rt = inter->state->native_reg_cache[op->r.rt];
709
710 inter->state->native_reg_cache[op->r.rd] = rt >> (rs & 0x1f);
711
712 return jump_next(inter);
713}
714
715static u32 int_syscall_break(struct interpreter *inter)
716{
717
718 if (inter->op->r.op == OP_SPECIAL_BREAK)
719 inter->state->exit_flags |= LIGHTREC_EXIT_BREAK;
720 else
721 inter->state->exit_flags |= LIGHTREC_EXIT_SYSCALL;
722
723 return inter->block->pc + inter->op->offset * sizeof(u32);
724}
725
726static u32 int_special_MFHI(struct interpreter *inter)
727{
728 u32 *reg_cache = inter->state->native_reg_cache;
729 struct opcode_r *op = &inter->op->r;
730
731 if (likely(op->rd))
732 reg_cache[op->rd] = reg_cache[REG_HI];
733
734 return jump_next(inter);
735}
736
737static u32 int_special_MTHI(struct interpreter *inter)
738{
739 u32 *reg_cache = inter->state->native_reg_cache;
740
741 reg_cache[REG_HI] = reg_cache[inter->op->r.rs];
742
743 return jump_next(inter);
744}
745
746static u32 int_special_MFLO(struct interpreter *inter)
747{
748 u32 *reg_cache = inter->state->native_reg_cache;
749 struct opcode_r *op = &inter->op->r;
750
751 if (likely(op->rd))
752 reg_cache[op->rd] = reg_cache[REG_LO];
753
754 return jump_next(inter);
755}
756
757static u32 int_special_MTLO(struct interpreter *inter)
758{
759 u32 *reg_cache = inter->state->native_reg_cache;
760
761 reg_cache[REG_LO] = reg_cache[inter->op->r.rs];
762
763 return jump_next(inter);
764}
765
766static u32 int_special_MULT(struct interpreter *inter)
767{
768 u32 *reg_cache = inter->state->native_reg_cache;
769 s32 rs = reg_cache[inter->op->r.rs];
770 s32 rt = reg_cache[inter->op->r.rt];
771 u64 res = (s64)rs * (s64)rt;
772
773 if (!(inter->op->flags & LIGHTREC_MULT32))
774 reg_cache[REG_HI] = res >> 32;
775 reg_cache[REG_LO] = res;
776
777 return jump_next(inter);
778}
779
780static u32 int_special_MULTU(struct interpreter *inter)
781{
782 u32 *reg_cache = inter->state->native_reg_cache;
783 u32 rs = reg_cache[inter->op->r.rs];
784 u32 rt = reg_cache[inter->op->r.rt];
785 u64 res = (u64)rs * (u64)rt;
786
787 if (!(inter->op->flags & LIGHTREC_MULT32))
788 reg_cache[REG_HI] = res >> 32;
789 reg_cache[REG_LO] = res;
790
791 return jump_next(inter);
792}
793
794static u32 int_special_DIV(struct interpreter *inter)
795{
796 u32 *reg_cache = inter->state->native_reg_cache;
797 s32 rs = reg_cache[inter->op->r.rs];
798 s32 rt = reg_cache[inter->op->r.rt];
799 u32 lo, hi;
800
801 if (rt == 0) {
802 hi = rs;
803 lo = (rs < 0) * 2 - 1;
f533290e
EC
804 } else if ((rs == 0x80000000) && (rt == 0xFFFFFFFF)) {
805 lo = rs;
806 hi = 0;
d16005f8
PC
807 } else {
808 lo = rs / rt;
809 hi = rs % rt;
810 }
811
812 reg_cache[REG_HI] = hi;
813 reg_cache[REG_LO] = lo;
814
815 return jump_next(inter);
816}
817
818static u32 int_special_DIVU(struct interpreter *inter)
819{
820 u32 *reg_cache = inter->state->native_reg_cache;
821 u32 rs = reg_cache[inter->op->r.rs];
822 u32 rt = reg_cache[inter->op->r.rt];
823 u32 lo, hi;
824
825 if (rt == 0) {
826 hi = rs;
827 lo = (u32)-1;
828 } else {
829 lo = rs / rt;
830 hi = rs % rt;
831 }
832
833 reg_cache[REG_HI] = hi;
834 reg_cache[REG_LO] = lo;
835
836 return jump_next(inter);
837}
838
839static u32 int_special_ADD(struct interpreter *inter)
840{
841 u32 *reg_cache = inter->state->native_reg_cache;
842 struct opcode_r *op = &inter->op->r;
843 s32 rs = reg_cache[op->rs];
844 s32 rt = reg_cache[op->rt];
845
846 if (likely(op->rd))
847 reg_cache[op->rd] = rs + rt;
848
849 return jump_next(inter);
850}
851
852static u32 int_special_SUB(struct interpreter *inter)
853{
854 u32 *reg_cache = inter->state->native_reg_cache;
855 struct opcode_r *op = &inter->op->r;
856 u32 rs = reg_cache[op->rs];
857 u32 rt = reg_cache[op->rt];
858
859 if (likely(op->rd))
860 reg_cache[op->rd] = rs - rt;
861
862 return jump_next(inter);
863}
864
865static u32 int_special_AND(struct interpreter *inter)
866{
867 u32 *reg_cache = inter->state->native_reg_cache;
868 struct opcode_r *op = &inter->op->r;
869 u32 rs = reg_cache[op->rs];
870 u32 rt = reg_cache[op->rt];
871
872 if (likely(op->rd))
873 reg_cache[op->rd] = rs & rt;
874
875 return jump_next(inter);
876}
877
878static u32 int_special_OR(struct interpreter *inter)
879{
880 u32 *reg_cache = inter->state->native_reg_cache;
881 struct opcode_r *op = &inter->op->r;
882 u32 rs = reg_cache[op->rs];
883 u32 rt = reg_cache[op->rt];
884
885 if (likely(op->rd))
886 reg_cache[op->rd] = rs | rt;
887
888 return jump_next(inter);
889}
890
891static u32 int_special_XOR(struct interpreter *inter)
892{
893 u32 *reg_cache = inter->state->native_reg_cache;
894 struct opcode_r *op = &inter->op->r;
895 u32 rs = reg_cache[op->rs];
896 u32 rt = reg_cache[op->rt];
897
898 if (likely(op->rd))
899 reg_cache[op->rd] = rs ^ rt;
900
901 return jump_next(inter);
902}
903
904static u32 int_special_NOR(struct interpreter *inter)
905{
906 u32 *reg_cache = inter->state->native_reg_cache;
907 struct opcode_r *op = &inter->op->r;
908 u32 rs = reg_cache[op->rs];
909 u32 rt = reg_cache[op->rt];
910
911 if (likely(op->rd))
912 reg_cache[op->rd] = ~(rs | rt);
913
914 return jump_next(inter);
915}
916
917static u32 int_special_SLT(struct interpreter *inter)
918{
919 u32 *reg_cache = inter->state->native_reg_cache;
920 struct opcode_r *op = &inter->op->r;
921 s32 rs = reg_cache[op->rs];
922 s32 rt = reg_cache[op->rt];
923
924 if (likely(op->rd))
925 reg_cache[op->rd] = rs < rt;
926
927 return jump_next(inter);
928}
929
930static u32 int_special_SLTU(struct interpreter *inter)
931{
932 u32 *reg_cache = inter->state->native_reg_cache;
933 struct opcode_r *op = &inter->op->r;
934 u32 rs = reg_cache[op->rs];
935 u32 rt = reg_cache[op->rt];
936
937 if (likely(op->rd))
938 reg_cache[op->rd] = rs < rt;
939
940 return jump_next(inter);
941}
942
943static u32 int_META_SKIP(struct interpreter *inter)
944{
945 return jump_skip(inter);
946}
947
948static u32 int_META_MOV(struct interpreter *inter)
949{
950 u32 *reg_cache = inter->state->native_reg_cache;
951 struct opcode_r *op = &inter->op->r;
952
953 if (likely(op->rd))
954 reg_cache[op->rd] = reg_cache[op->rs];
955
956 return jump_next(inter);
957}
958
959static u32 int_META_SYNC(struct interpreter *inter)
960{
961 inter->state->current_cycle += inter->cycles;
962 inter->cycles = 0;
963
964 return jump_skip(inter);
965}
966
967static const lightrec_int_func_t int_standard[64] = {
968 [OP_SPECIAL] = int_SPECIAL,
969 [OP_REGIMM] = int_REGIMM,
970 [OP_J] = int_J,
971 [OP_JAL] = int_JAL,
972 [OP_BEQ] = int_BEQ,
973 [OP_BNE] = int_BNE,
974 [OP_BLEZ] = int_BLEZ,
975 [OP_BGTZ] = int_BGTZ,
976 [OP_ADDI] = int_ADDI,
977 [OP_ADDIU] = int_ADDI,
978 [OP_SLTI] = int_SLTI,
979 [OP_SLTIU] = int_SLTIU,
980 [OP_ANDI] = int_ANDI,
981 [OP_ORI] = int_ORI,
982 [OP_XORI] = int_XORI,
983 [OP_LUI] = int_LUI,
984 [OP_CP0] = int_CP0,
985 [OP_CP2] = int_CP2,
986 [OP_LB] = int_load,
987 [OP_LH] = int_load,
988 [OP_LWL] = int_load,
989 [OP_LW] = int_load,
990 [OP_LBU] = int_load,
991 [OP_LHU] = int_load,
992 [OP_LWR] = int_load,
993 [OP_SB] = int_store,
994 [OP_SH] = int_store,
995 [OP_SWL] = int_store,
996 [OP_SW] = int_store,
997 [OP_SWR] = int_store,
998 [OP_LWC2] = int_LWC2,
999 [OP_SWC2] = int_store,
1000
1001 [OP_META_REG_UNLOAD] = int_META_SKIP,
1002 [OP_META_BEQZ] = int_BEQ,
1003 [OP_META_BNEZ] = int_BNE,
1004 [OP_META_MOV] = int_META_MOV,
1005 [OP_META_SYNC] = int_META_SYNC,
1006};
1007
1008static const lightrec_int_func_t int_special[64] = {
1009 [OP_SPECIAL_SLL] = int_special_SLL,
1010 [OP_SPECIAL_SRL] = int_special_SRL,
1011 [OP_SPECIAL_SRA] = int_special_SRA,
1012 [OP_SPECIAL_SLLV] = int_special_SLLV,
1013 [OP_SPECIAL_SRLV] = int_special_SRLV,
1014 [OP_SPECIAL_SRAV] = int_special_SRAV,
1015 [OP_SPECIAL_JR] = int_special_JR,
1016 [OP_SPECIAL_JALR] = int_special_JALR,
1017 [OP_SPECIAL_SYSCALL] = int_syscall_break,
1018 [OP_SPECIAL_BREAK] = int_syscall_break,
1019 [OP_SPECIAL_MFHI] = int_special_MFHI,
1020 [OP_SPECIAL_MTHI] = int_special_MTHI,
1021 [OP_SPECIAL_MFLO] = int_special_MFLO,
1022 [OP_SPECIAL_MTLO] = int_special_MTLO,
1023 [OP_SPECIAL_MULT] = int_special_MULT,
1024 [OP_SPECIAL_MULTU] = int_special_MULTU,
1025 [OP_SPECIAL_DIV] = int_special_DIV,
1026 [OP_SPECIAL_DIVU] = int_special_DIVU,
1027 [OP_SPECIAL_ADD] = int_special_ADD,
1028 [OP_SPECIAL_ADDU] = int_special_ADD,
1029 [OP_SPECIAL_SUB] = int_special_SUB,
1030 [OP_SPECIAL_SUBU] = int_special_SUB,
1031 [OP_SPECIAL_AND] = int_special_AND,
1032 [OP_SPECIAL_OR] = int_special_OR,
1033 [OP_SPECIAL_XOR] = int_special_XOR,
1034 [OP_SPECIAL_NOR] = int_special_NOR,
1035 [OP_SPECIAL_SLT] = int_special_SLT,
1036 [OP_SPECIAL_SLTU] = int_special_SLTU,
1037};
1038
1039static const lightrec_int_func_t int_regimm[64] = {
1040 [OP_REGIMM_BLTZ] = int_regimm_BLTZ,
1041 [OP_REGIMM_BGEZ] = int_regimm_BGEZ,
1042 [OP_REGIMM_BLTZAL] = int_regimm_BLTZAL,
1043 [OP_REGIMM_BGEZAL] = int_regimm_BGEZAL,
1044};
1045
1046static const lightrec_int_func_t int_cp0[64] = {
1047 [OP_CP0_MFC0] = int_cfc,
1048 [OP_CP0_CFC0] = int_cfc,
1049 [OP_CP0_MTC0] = int_ctc,
1050 [OP_CP0_CTC0] = int_ctc,
1051 [OP_CP0_RFE] = int_cp0_RFE,
1052};
1053
1054static const lightrec_int_func_t int_cp2_basic[64] = {
1055 [OP_CP2_BASIC_MFC2] = int_cfc,
1056 [OP_CP2_BASIC_CFC2] = int_cfc,
1057 [OP_CP2_BASIC_MTC2] = int_ctc,
1058 [OP_CP2_BASIC_CTC2] = int_ctc,
1059};
1060
1061static u32 int_SPECIAL(struct interpreter *inter)
1062{
1063 lightrec_int_func_t f = int_special[inter->op->r.op];
1064 if (likely(f))
1065 return execute(f, inter);
1066 else
1067 return int_unimplemented(inter);
1068}
1069
1070static u32 int_REGIMM(struct interpreter *inter)
1071{
1072 lightrec_int_func_t f = int_regimm[inter->op->r.rt];
1073 if (likely(f))
1074 return execute(f, inter);
1075 else
1076 return int_unimplemented(inter);
1077}
1078
1079static u32 int_CP0(struct interpreter *inter)
1080{
1081 lightrec_int_func_t f = int_cp0[inter->op->r.rs];
1082 if (likely(f))
1083 return execute(f, inter);
1084 else
1085 return int_CP(inter);
1086}
1087
1088static u32 int_CP2(struct interpreter *inter)
1089{
1090 if (inter->op->r.op == OP_CP2_BASIC) {
1091 lightrec_int_func_t f = int_cp2_basic[inter->op->r.rs];
1092 if (likely(f))
1093 return execute(f, inter);
1094 }
1095
1096 return int_CP(inter);
1097}
1098
1099static u32 lightrec_int_op(struct interpreter *inter)
1100{
1101 return execute(int_standard[inter->op->i.op], inter);
1102}
1103
1104static u32 lightrec_emulate_block_list(struct block *block, struct opcode *op)
1105{
1106 struct interpreter inter;
1107 u32 pc;
1108
1109 inter.block = block;
1110 inter.state = block->state;
1111 inter.op = op;
1112 inter.cycles = 0;
1113 inter.delay_slot = false;
1114
1115 pc = lightrec_int_op(&inter);
1116
1117 /* Add the cycles of the last branch */
1118 inter.cycles += lightrec_cycles_of_opcode(inter.op->c);
1119
1120 block->state->current_cycle += inter.cycles;
1121
1122 return pc;
1123}
1124
1125u32 lightrec_emulate_block(struct block *block, u32 pc)
1126{
1127 u32 offset = (kunseg(pc) - kunseg(block->pc)) >> 2;
1128 struct opcode *op;
1129
1130 for (op = block->opcode_list;
1131 op && (op->offset < offset); op = op->next);
1132 if (op)
1133 return lightrec_emulate_block_list(block, op);
1134
1135 pr_err("PC 0x%x is outside block at PC 0x%x\n", pc, block->pc);
1136
1137 return 0;
1138}