1 /* MIPS R3000 CPU emulation.
2 Copyright 2001, 2002, 2003, 2004 Brian R. Gaeke.
3
4 This file is part of VMIPS.
5
6 VMIPS is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2 of the License, or (at your
9 option) any later version.
10
11 VMIPS is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with VMIPS; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20 #include <string.h>
21 #include "cpu.h"
22 #include "cpzero.h"
23 #include "debug.h"
24 #include "fpu.h"
25 #include "mapper.h"
26 #include "vmips.h"
27 #include "options.h"
28 #include "excnames.h"
29 #include "cpzeroreg.h"
30 #include "error.h"
31 #include "remotegdb.h"
32 #include "fileutils.h"
33 #include "stub-dis.h"
34 #include <cstring>
35
36 /* states of the delay-slot state machine -- see CPU::step() */
37 static const int NORMAL = 0, DELAYING = 1, DELAYSLOT = 2;
38
39 /* certain fixed register numbers which are handy to know */
40 static const int reg_zero = 0; /* always zero */
41 static const int reg_sp = 29; /* stack pointer */
42 static const int reg_ra = 31; /* return address */
43
44 /* pointer to CPU method returning void and taking two uint32's */
45 typedef void (CPU::*emulate_funptr)(uint32, uint32);
46
strdelaystate(const int state)47 static const char *strdelaystate(const int state) {
48 static const char *const statestr[] = {
49 "NORMAL", "DELAYING", "DELAYSLOT"
50 };
51 return statestr[state];
52 }
53
CPU(Mapper & m,IntCtrl & i)54 CPU::CPU (Mapper &m, IntCtrl &i)
55 : tracing (false), last_epc (0), last_prio (0), mem (&m),
56 cpzero (new CPZero (this, &i)), fpu (0), delay_state (NORMAL)
57 {
58 opt_fpu = machine->opt->option("fpu")->flag;
59 if (opt_fpu)
60 fpu = new FPU (this);
61 reg[reg_zero] = 0;
62 opt_excmsg = machine->opt->option("excmsg")->flag;
63 opt_reportirq = machine->opt->option("reportirq")->flag;
64 opt_excpriomsg = machine->opt->option("excpriomsg")->flag;
65 opt_haltbreak = machine->opt->option("haltbreak")->flag,
66 opt_haltibe = machine->opt->option("haltibe")->flag;
67 opt_instdump = machine->opt->option("instdump")->flag;
68 opt_tracing = machine->opt->option("tracing")->flag;
69 opt_tracesize = machine->opt->option("tracesize")->num;
70 opt_tracestartpc = machine->opt->option("tracestartpc")->num;
71 opt_traceendpc = machine->opt->option("traceendpc")->num;
72 opt_bigendian = machine->opt->option("bigendian")->flag;
73 if (opt_tracing)
74 open_trace_file ();
75 }
76
~CPU()77 CPU::~CPU ()
78 {
79 if (opt_tracing)
80 close_trace_file ();
81 }
82
83 void
reset(void)84 CPU::reset(void)
85 {
86 #ifdef INTENTIONAL_CONFUSION
87 int r;
88 for (r = 0; r < 32; r++) {
89 reg[r] = random();
90 }
91 #endif /* INTENTIONAL_CONFUSION */
92 reg[reg_zero] = 0;
93 pc = 0xbfc00000;
94 cpzero->reset();
95 }
96
97 void
dump_regs(FILE * f)98 CPU::dump_regs(FILE *f)
99 {
100 int i;
101
102 fprintf(f,"Reg Dump: [ PC=%08x LastInstr=%08x HI=%08x LO=%08x\n",
103 pc,instr,hi,lo);
104 fprintf(f," DelayState=%s DelayPC=%08x NextEPC=%08x\n",
105 strdelaystate(delay_state), delay_pc, next_epc);
106 for (i = 0; i < 32; i++) {
107 fprintf(f," R%02d=%08x ",i,reg[i]);
108 if (i % 5 == 4) {
109 fputc('\n',f);
110 } else if (i == 31) {
111 fprintf(f, " ]\n");
112 }
113 }
114 }
115
116 void
dump_stack(FILE * f)117 CPU::dump_stack(FILE *f)
118 {
119 uint32 stackphys;
120 if (cpzero->debug_tlb_translate(reg[reg_sp], &stackphys)) {
121 mem->dump_stack(f, stackphys);
122 } else {
123 fprintf(f, "Stack: (not mapped in TLB)\n");
124 }
125 }
126
127 void
dump_mem(FILE * f,uint32 addr)128 CPU::dump_mem(FILE *f, uint32 addr)
129 {
130 uint32 phys;
131 fprintf(f, "0x%08x: ", addr);
132 if (cpzero->debug_tlb_translate(addr, &phys)) {
133 mem->dump_mem(f, phys);
134 } else {
135 fprintf(f, "(not mapped in TLB)");
136 }
137 fprintf(f, "\n");
138 }
139
140 /* Disassemble a word at addr and print the result to f.
141 * FIXME: currently, f must be stderr, for the disassembler.
142 */
143 void
dis_mem(FILE * f,uint32 addr)144 CPU::dis_mem(FILE *f, uint32 addr)
145 {
146 uint32 phys;
147 uint32 instr;
148 if (cpzero->debug_tlb_translate(addr, &phys)) {
149 fprintf(f,"PC=0x%08x [%08x] %s",addr,phys,(addr==pc?"=>":" "));
150 instr = mem->fetch_word(phys,INSTFETCH,false, this);
151 fprintf(f,"%08x ",instr);
152 machine->disasm->disassemble(addr,instr);
153 } else {
154 fprintf(f,"PC=0x%08x [%08x] %s",addr,phys,(addr==pc?"=>":" "));
155 fprintf(f, "(not mapped in TLB)\n");
156 }
157 }
158
159 void
cpzero_dump_regs_and_tlb(FILE * f)160 CPU::cpzero_dump_regs_and_tlb(FILE *f)
161 {
162 cpzero->dump_regs_and_tlb(f);
163 }
164
165 /* exception handling */
strexccode(const uint16 excCode)166 static const char *strexccode(const uint16 excCode) {
167 static const char *const exception_strs[] =
168 {
169 /* 0 */ "Interrupt",
170 /* 1 */ "TLB modification exception",
171 /* 2 */ "TLB exception (load or instr fetch)",
172 /* 3 */ "TLB exception (store)",
173 /* 4 */ "Address error exception (load or instr fetch)",
174 /* 5 */ "Address error exception (store)",
175 /* 6 */ "Instruction bus error",
176 /* 7 */ "Data (load or store) bus error",
177 /* 8 */ "SYSCALL exception",
178 /* 9 */ "Breakpoint32 exception (BREAK instr)",
179 /* 10 */ "Reserved instr exception",
180 /* 11 */ "Coprocessor Unusable",
181 /* 12 */ "Arithmetic Overflow",
182 /* 13 */ "Trap (R4k/R6k only)",
183 /* 14 */ "LDCz or SDCz to uncached address (R6k)",
184 /* 14 */ "Virtual Coherency Exception (instr) (R4k)",
185 /* 15 */ "Machine check exception (R6k)",
186 /* 15 */ "Floating-point32 exception (R4k)",
187 /* 16 */ "Exception 16 (reserved)",
188 /* 17 */ "Exception 17 (reserved)",
189 /* 18 */ "Exception 18 (reserved)",
190 /* 19 */ "Exception 19 (reserved)",
191 /* 20 */ "Exception 20 (reserved)",
192 /* 21 */ "Exception 21 (reserved)",
193 /* 22 */ "Exception 22 (reserved)",
194 /* 23 */ "Reference to WatchHi/WatchLo address detected (R4k)",
195 /* 24 */ "Exception 24 (reserved)",
196 /* 25 */ "Exception 25 (reserved)",
197 /* 26 */ "Exception 26 (reserved)",
198 /* 27 */ "Exception 27 (reserved)",
199 /* 28 */ "Exception 28 (reserved)",
200 /* 29 */ "Exception 29 (reserved)",
201 /* 30 */ "Exception 30 (reserved)",
202 /* 31 */ "Virtual Coherency Exception (data) (R4k)"
203 };
204
205 return exception_strs[excCode];
206 }
207
strmemmode(const int memmode)208 static const char *strmemmode(const int memmode) {
209 static const char *const memmode_strs[] =
210 {
211 "instruction fetch", /* INSTFETCH */
212 "data load", /* DATALOAD */
213 "data store", /* DATASTORE */
214 "not applicable" /* ANY */
215 };
216
217 return memmode_strs[memmode];
218 }
219
220 int
exception_priority(uint16 excCode,int mode) const221 CPU::exception_priority(uint16 excCode, int mode) const
222 {
223 /* See doc/excprio for an explanation of this table. */
224 static const struct excPriority prio[] = {
225 {1, AdEL, INSTFETCH},
226 {2, TLBL, INSTFETCH}, {2, TLBS, INSTFETCH},
227 {3, IBE, ANY},
228 {4, Ov, ANY}, {4, Tr, ANY}, {4, Sys, ANY},
229 {4, Bp, ANY}, {4, RI, ANY}, {4, CpU, ANY},
230 {5, AdEL, DATALOAD}, {5, AdES, ANY},
231 {6, TLBL, DATALOAD}, {6, TLBS, DATALOAD},
232 {6, TLBL, DATASTORE}, {6, TLBS, DATASTORE},
233 {7, Mod, ANY},
234 {8, DBE, ANY},
235 {9, Int, ANY},
236 {0, ANY, ANY} /* catch-all */
237 };
238 const struct excPriority *p;
239
240 for (p = prio; p->priority != 0; p++) {
241 if (excCode == p->excCode || p->excCode == ANY) {
242 if (mode == p->mode || p->mode == ANY) {
243 return p->priority;
244 } else if (opt_excpriomsg) {
245 fprintf(stderr,
246 "exception code matches but mode %d != table %d\n",
247 mode,p->mode);
248 }
249 } else if (opt_excpriomsg) {
250 fprintf(stderr, "exception code %d != table %d\n", excCode,
251 p->excCode);
252 }
253 }
254 return 0;
255 }
256
257 void
exception(uint16 excCode,int mode,int coprocno)258 CPU::exception(uint16 excCode, int mode /* = ANY */, int coprocno /* = -1 */)
259 {
260 int prio;
261 uint32 base, vector, epc;
262 bool delaying = (delay_state == DELAYSLOT);
263
264 if (opt_haltbreak) {
265 if (excCode == Bp) {
266 fprintf(stderr,"* BREAK instruction reached -- HALTING *\n");
267 machine->halt();
268 }
269 }
270 if (opt_haltibe) {
271 if (excCode == IBE) {
272 fprintf(stderr,"* Instruction bus error occurred -- HALTING *\n");
273 machine->halt();
274 }
275 }
276
277 /* step() ensures that next_epc will always contain the correct
278 * EPC whenever exception() is called.
279 */
280 epc = next_epc;
281
282 /* Prioritize exception -- if the last exception to occur _also_ was
283 * caused by this EPC, only report this exception if it has a higher
284 * priority. Otherwise, exception handling terminates here,
285 * because only one exception will be reported per instruction
286 * (as per MIPS RISC Architecture, p. 6-35). Note that this only
287 * applies IFF the previous exception was caught during the current
288 * _execution_ of the instruction at this EPC, so we check that
289 * EXCEPTION_PENDING is true before aborting exception handling.
290 * (This flag is reset by each call to step().)
291 */
292 prio = exception_priority(excCode, mode);
293 if (epc == last_epc) {
294 if (prio <= last_prio && exception_pending) {
295 if (opt_excpriomsg) {
296 fprintf(stderr,
297 "(Ignoring additional lower priority exception...)\n");
298 }
299 return;
300 } else {
301 last_prio = prio;
302 }
303 }
304 last_epc = epc;
305
306 /* Set processor to Kernel mode, disable interrupts, and save
307 * exception PC.
308 */
309 cpzero->enter_exception(epc,excCode,coprocno,delaying);
310
311 /* Calculate the exception handler address; this is of the form BASE +
312 * VECTOR. The BASE is determined by whether we're using boot-time
313 * exception vectors, according to the BEV bit in the CP0 Status register.
314 */
315 if (cpzero->use_boot_excp_address()) {
316 base = 0xbfc00100;
317 } else {
318 base = 0x80000000;
319 }
320
321 /* Do we have a User TLB Miss exception? If so, jump to the
322 * User TLB Miss exception vector, otherwise jump to the
323 * common exception vector.
324 */
325 if ((excCode == TLBL || excCode == TLBS) && (cpzero->tlb_miss_user)) {
326 vector = 0x000;
327 } else {
328 vector = 0x080;
329 }
330
331 if (opt_excmsg && (excCode != Int || opt_reportirq)) {
332 fprintf(stderr,"Exception %d (%s) triggered, EPC=%08x\n", excCode,
333 strexccode(excCode), epc);
334 fprintf(stderr,
335 " Priority is %d; delay state is %s; mem access mode is %s\n",
336 prio, strdelaystate(delay_state), strmemmode(mode));
337 if (excCode == Int) {
338 uint32 status, bad, cause;
339 cpzero->read_debug_info(&status, &bad, &cause);
340 fprintf (stderr, " Interrupt cause = %x, status = %x\n", cause, status);
341 }
342 }
343 if (opt_tracing) {
344 if (tracing) {
345 current_trace.exception_happened = true;
346 current_trace.last_exception_code = excCode;
347 }
348 }
349 pc = base + vector;
350 exception_pending = true;
351 }
352
353 /* emulation of instructions */
354 void
cpzero_emulate(uint32 instr,uint32 pc)355 CPU::cpzero_emulate(uint32 instr, uint32 pc)
356 {
357 cpzero->cpzero_emulate(instr, pc);
358 mem->cache_set_control_bits(cpzero->caches_isolated(),
359 cpzero->caches_swapped());
360 }
361
362 /* Called when the program wants to use coprocessor COPROCNO, and there
363 * isn't any implementation for that coprocessor.
364 * Results in a Coprocessor Unusable exception, along with an error
365 * message being printed if the coprocessor is marked usable in the
366 * CP0 Status register.
367 */
368 void
cop_unimpl(int coprocno,uint32 instr,uint32 pc)369 CPU::cop_unimpl (int coprocno, uint32 instr, uint32 pc)
370 {
371 if (cpzero->cop_usable (coprocno)) {
372 /* Since they were expecting this to work, the least we
373 * can do is print an error message. */
374 fprintf (stderr, "CP%d instruction %x not implemented at pc=0x%x:\n",
375 coprocno, instr, pc);
376 machine->disasm->disassemble (pc, instr);
377 exception (CpU, ANY, coprocno);
378 } else {
379 /* It's fair game to just throw an exception, if they
380 * haven't even bothered to twiddle the status bits first. */
381 exception (CpU, ANY, coprocno);
382 }
383 }
384
385 void
cpone_emulate(uint32 instr,uint32 pc)386 CPU::cpone_emulate(uint32 instr, uint32 pc)
387 {
388 if (opt_fpu) {
389 // FIXME: check cpzero->cop_usable
390 fpu->cpone_emulate (instr, pc);
391 } else {
392 /* If it's a cfc1 <reg>, $0 then we copy 0 into reg,
393 * which is supposed to mean there is NO cp1...
394 * for now, though, ANYTHING else asked of cp1 results
395 * in the default "unimplemented" behavior. */
396 if (cpzero->cop_usable (1) && rs (instr) == 2
397 && rd (instr) == 0) {
398 reg[rt (instr)] = 0; /* No cp1. */
399 } else {
400 cop_unimpl (1, instr, pc);
401 }
402 }
403 }
404
405 void
cptwo_emulate(uint32 instr,uint32 pc)406 CPU::cptwo_emulate(uint32 instr, uint32 pc)
407 {
408 cop_unimpl (2, instr, pc);
409 }
410
411 void
cpthree_emulate(uint32 instr,uint32 pc)412 CPU::cpthree_emulate(uint32 instr, uint32 pc)
413 {
414 cop_unimpl (3, instr, pc);
415 }
416
417 void
control_transfer(uint32 new_pc)418 CPU::control_transfer (uint32 new_pc)
419 {
420 if (!new_pc) warning ("Jumping to zero (PC = 0x%x)\n", pc);
421 delay_state = DELAYING;
422 delay_pc = new_pc;
423 }
424
425 /// calc_jump_target - Calculate the address to jump to as a result of
426 /// the J-format (jump) instruction INSTR at address PC. (PC is the address
427 /// of the jump instruction, and INSTR is the jump instruction word.)
428 ///
429 uint32
calc_jump_target(uint32 instr,uint32 pc)430 CPU::calc_jump_target (uint32 instr, uint32 pc)
431 {
432 // Must use address of delay slot (pc + 4) to calculate.
433 return ((pc + 4) & 0xf0000000) | (jumptarg(instr) << 2);
434 }
435
436 void
jump(uint32 instr,uint32 pc)437 CPU::jump(uint32 instr, uint32 pc)
438 {
439 control_transfer (calc_jump_target (instr, pc));
440 }
441
442 void
j_emulate(uint32 instr,uint32 pc)443 CPU::j_emulate(uint32 instr, uint32 pc)
444 {
445 jump (instr, pc);
446 }
447
448 void
jal_emulate(uint32 instr,uint32 pc)449 CPU::jal_emulate(uint32 instr, uint32 pc)
450 {
451 jump (instr, pc);
452 // RA gets addr of instr after delay slot (2 words after this one).
453 reg[reg_ra] = pc + 8;
454 }
455
456 /// calc_branch_target - Calculate the address to jump to for the
457 /// PC-relative branch for which the offset is specified by the immediate field
458 /// of the branch instruction word INSTR, with the program counter equal to PC.
459 ///
460 uint32
calc_branch_target(uint32 instr,uint32 pc)461 CPU::calc_branch_target(uint32 instr, uint32 pc)
462 {
463 return (pc + 4) + (s_immed(instr) << 2);
464 }
465
466 void
branch(uint32 instr,uint32 pc)467 CPU::branch(uint32 instr, uint32 pc)
468 {
469 control_transfer (calc_branch_target (instr, pc));
470 }
471
472 void
beq_emulate(uint32 instr,uint32 pc)473 CPU::beq_emulate(uint32 instr, uint32 pc)
474 {
475 if (reg[rs(instr)] == reg[rt(instr)])
476 branch (instr, pc);
477 }
478
479 void
bne_emulate(uint32 instr,uint32 pc)480 CPU::bne_emulate(uint32 instr, uint32 pc)
481 {
482 if (reg[rs(instr)] != reg[rt(instr)])
483 branch (instr, pc);
484 }
485
486 void
blez_emulate(uint32 instr,uint32 pc)487 CPU::blez_emulate(uint32 instr, uint32 pc)
488 {
489 if (rt(instr) != 0) {
490 exception(RI);
491 return;
492 }
493 if (reg[rs(instr)] == 0 || (reg[rs(instr)] & 0x80000000))
494 branch(instr, pc);
495 }
496
497 void
bgtz_emulate(uint32 instr,uint32 pc)498 CPU::bgtz_emulate(uint32 instr, uint32 pc)
499 {
500 if (rt(instr) != 0) {
501 exception(RI);
502 return;
503 }
504 if (reg[rs(instr)] != 0 && (reg[rs(instr)] & 0x80000000) == 0)
505 branch(instr, pc);
506 }
507
508 void
addi_emulate(uint32 instr,uint32 pc)509 CPU::addi_emulate(uint32 instr, uint32 pc)
510 {
511 int32 a, b, sum;
512
513 a = (int32)reg[rs(instr)];
514 b = s_immed(instr);
515 sum = a + b;
516 if ((a < 0 && b < 0 && !(sum < 0)) || (a >= 0 && b >= 0 && !(sum >= 0))) {
517 exception(Ov);
518 return;
519 } else {
520 reg[rt(instr)] = (uint32)sum;
521 }
522 }
523
524 void
addiu_emulate(uint32 instr,uint32 pc)525 CPU::addiu_emulate(uint32 instr, uint32 pc)
526 {
527 int32 a, b, sum;
528
529 a = (int32)reg[rs(instr)];
530 b = s_immed(instr);
531 sum = a + b;
532 reg[rt(instr)] = (uint32)sum;
533 }
534
535 void
slti_emulate(uint32 instr,uint32 pc)536 CPU::slti_emulate(uint32 instr, uint32 pc)
537 {
538 int32 s_rs = reg[rs(instr)];
539
540 if (s_rs < s_immed(instr)) {
541 reg[rt(instr)] = 1;
542 } else {
543 reg[rt(instr)] = 0;
544 }
545 }
546
547 void
sltiu_emulate(uint32 instr,uint32 pc)548 CPU::sltiu_emulate(uint32 instr, uint32 pc)
549 {
550 if (reg[rs(instr)] < (uint32)(int32)s_immed(instr)) {
551 reg[rt(instr)] = 1;
552 } else {
553 reg[rt(instr)] = 0;
554 }
555 }
556
557 void
andi_emulate(uint32 instr,uint32 pc)558 CPU::andi_emulate(uint32 instr, uint32 pc)
559 {
560 reg[rt(instr)] = (reg[rs(instr)] & 0x0ffff) & immed(instr);
561 }
562
563 void
ori_emulate(uint32 instr,uint32 pc)564 CPU::ori_emulate(uint32 instr, uint32 pc)
565 {
566 reg[rt(instr)] = reg[rs(instr)] | immed(instr);
567 }
568
569 void
xori_emulate(uint32 instr,uint32 pc)570 CPU::xori_emulate(uint32 instr, uint32 pc)
571 {
572 reg[rt(instr)] = reg[rs(instr)] ^ immed(instr);
573 }
574
575 void
lui_emulate(uint32 instr,uint32 pc)576 CPU::lui_emulate(uint32 instr, uint32 pc)
577 {
578 reg[rt(instr)] = immed(instr) << 16;
579 }
580
581 void
lb_emulate(uint32 instr,uint32 pc)582 CPU::lb_emulate(uint32 instr, uint32 pc)
583 {
584 uint32 phys, virt, base;
585 int8 byte;
586 int32 offset;
587 bool cacheable;
588
589 /* Calculate virtual address. */
590 base = reg[rs(instr)];
591 offset = s_immed(instr);
592 virt = base + offset;
593
594 /* Translate virtual address to physical address. */
595 phys = cpzero->address_trans(virt, DATALOAD, &cacheable, this);
596 if (exception_pending) return;
597
598 /* Fetch byte.
599 * Because it is assigned to a signed variable (int32 byte)
600 * it will be sign-extended.
601 */
602 byte = mem->fetch_byte(phys, cacheable, this);
603 if (exception_pending) return;
604
605 /* Load target register with data. */
606 reg[rt(instr)] = byte;
607 }
608
609 void
lh_emulate(uint32 instr,uint32 pc)610 CPU::lh_emulate(uint32 instr, uint32 pc)
611 {
612 uint32 phys, virt, base;
613 int16 halfword;
614 int32 offset;
615 bool cacheable;
616
617 /* Calculate virtual address. */
618 base = reg[rs(instr)];
619 offset = s_immed(instr);
620 virt = base + offset;
621
622 /* This virtual address must be halfword-aligned. */
623 if (virt % 2 != 0) {
624 exception(AdEL,DATALOAD);
625 return;
626 }
627
628 /* Translate virtual address to physical address. */
629 phys = cpzero->address_trans(virt, DATALOAD, &cacheable, this);
630 if (exception_pending) return;
631
632 /* Fetch halfword.
633 * Because it is assigned to a signed variable (int32 halfword)
634 * it will be sign-extended.
635 */
636 halfword = mem->fetch_halfword(phys, cacheable, this);
637 if (exception_pending) return;
638
639 /* Load target register with data. */
640 reg[rt(instr)] = halfword;
641 }
642
643 /* The lwr and lwl algorithms here are taken from SPIM 6.0,
644 * since I didn't manage to come up with a better way to write them.
645 * Improvements are welcome.
646 */
647 uint32
lwr(uint32 regval,uint32 memval,uint8 offset)648 CPU::lwr(uint32 regval, uint32 memval, uint8 offset)
649 {
650 if (opt_bigendian) {
651 switch (offset)
652 {
653 case 0: return (regval & 0xffffff00) |
654 ((unsigned)(memval & 0xff000000) >> 24);
655 case 1: return (regval & 0xffff0000) |
656 ((unsigned)(memval & 0xffff0000) >> 16);
657 case 2: return (regval & 0xff000000) |
658 ((unsigned)(memval & 0xffffff00) >> 8);
659 case 3: return memval;
660 }
661 } else /* if MIPS target is little endian */ {
662 switch (offset)
663 {
664 /* The SPIM source claims that "The description of the
665 * little-endian case in Kane is totally wrong." The fact
666 * that I ripped off the LWR algorithm from them could be
667 * viewed as a sort of passive assumption that their claim
668 * is correct.
669 */
670 case 0: /* 3 in book */
671 return memval;
672 case 1: /* 0 in book */
673 return (regval & 0xff000000) | ((memval & 0xffffff00) >> 8);
674 case 2: /* 1 in book */
675 return (regval & 0xffff0000) | ((memval & 0xffff0000) >> 16);
676 case 3: /* 2 in book */
677 return (regval & 0xffffff00) | ((memval & 0xff000000) >> 24);
678 }
679 }
680 fatal_error("Invalid offset %x passed to lwr\n", offset);
681 }
682
683 uint32
lwl(uint32 regval,uint32 memval,uint8 offset)684 CPU::lwl(uint32 regval, uint32 memval, uint8 offset)
685 {
686 if (opt_bigendian) {
687 switch (offset)
688 {
689 case 0: return memval;
690 case 1: return (memval & 0xffffff) << 8 | (regval & 0xff);
691 case 2: return (memval & 0xffff) << 16 | (regval & 0xffff);
692 case 3: return (memval & 0xff) << 24 | (regval & 0xffffff);
693 }
694 } else /* if MIPS target is little endian */ {
695 switch (offset)
696 {
697 case 0: return (memval & 0xff) << 24 | (regval & 0xffffff);
698 case 1: return (memval & 0xffff) << 16 | (regval & 0xffff);
699 case 2: return (memval & 0xffffff) << 8 | (regval & 0xff);
700 case 3: return memval;
701 }
702 }
703 fatal_error("Invalid offset %x passed to lwl\n", offset);
704 }
705
706 void
lwl_emulate(uint32 instr,uint32 pc)707 CPU::lwl_emulate(uint32 instr, uint32 pc)
708 {
709 uint32 phys, virt, wordvirt, base, memword;
710 uint8 which_byte;
711 int32 offset;
712 bool cacheable;
713
714 /* Calculate virtual address. */
715 base = reg[rs(instr)];
716 offset = s_immed(instr);
717 virt = base + offset;
718 /* We request the word containing the byte-address requested. */
719 wordvirt = virt & ~0x03UL;
720
721 /* Translate virtual address to physical address. */
722 phys = cpzero->address_trans(wordvirt, DATALOAD, &cacheable, this);
723 if (exception_pending) return;
724
725 /* Fetch word. */
726 memword = mem->fetch_word(phys, DATALOAD, cacheable, this);
727 if (exception_pending) return;
728
729 /* Insert bytes into the left side of the register. */
730 which_byte = virt & 0x03;
731 reg[rt(instr)] = lwl(reg[rt(instr)], memword, which_byte);
732 }
733
734 void
lw_emulate(uint32 instr,uint32 pc)735 CPU::lw_emulate(uint32 instr, uint32 pc)
736 {
737 uint32 phys, virt, base, word;
738 int32 offset;
739 bool cacheable;
740
741 /* Calculate virtual address. */
742 base = reg[rs(instr)];
743 offset = s_immed(instr);
744 virt = base + offset;
745
746 /* This virtual address must be word-aligned. */
747 if (virt % 4 != 0) {
748 exception(AdEL,DATALOAD);
749 return;
750 }
751
752 /* Translate virtual address to physical address. */
753 phys = cpzero->address_trans(virt, DATALOAD, &cacheable, this);
754 if (exception_pending) return;
755
756 /* Fetch word. */
757 word = mem->fetch_word(phys, DATALOAD, cacheable, this);
758 if (exception_pending) return;
759
760 /* Load target register with data. */
761 reg[rt(instr)] = word;
762 }
763
764 void
lbu_emulate(uint32 instr,uint32 pc)765 CPU::lbu_emulate(uint32 instr, uint32 pc)
766 {
767 uint32 phys, virt, base, byte;
768 int32 offset;
769 bool cacheable;
770
771 /* Calculate virtual address. */
772 base = reg[rs(instr)];
773 offset = s_immed(instr);
774 virt = base + offset;
775
776 /* Translate virtual address to physical address. */
777 phys = cpzero->address_trans(virt, DATALOAD, &cacheable, this);
778 if (exception_pending) return;
779
780 /* Fetch byte. */
781 byte = mem->fetch_byte(phys, cacheable, this) & 0x000000ff;
782 if (exception_pending) return;
783
784 /* Load target register with data. */
785 reg[rt(instr)] = byte;
786 }
787
788 void
lhu_emulate(uint32 instr,uint32 pc)789 CPU::lhu_emulate(uint32 instr, uint32 pc)
790 {
791 uint32 phys, virt, base, halfword;
792 int32 offset;
793 bool cacheable;
794
795 /* Calculate virtual address. */
796 base = reg[rs(instr)];
797 offset = s_immed(instr);
798 virt = base + offset;
799
800 /* This virtual address must be halfword-aligned. */
801 if (virt % 2 != 0) {
802 exception(AdEL,DATALOAD);
803 return;
804 }
805
806 /* Translate virtual address to physical address. */
807 phys = cpzero->address_trans(virt, DATALOAD, &cacheable, this);
808 if (exception_pending) return;
809
810 /* Fetch halfword. */
811 halfword = mem->fetch_halfword(phys, cacheable, this) & 0x0000ffff;
812 if (exception_pending) return;
813
814 /* Load target register with data. */
815 reg[rt(instr)] = halfword;
816 }
817
818 void
lwr_emulate(uint32 instr,uint32 pc)819 CPU::lwr_emulate(uint32 instr, uint32 pc)
820 {
821 uint32 phys, virt, wordvirt, base, memword;
822 uint8 which_byte;
823 int32 offset;
824 bool cacheable;
825
826 /* Calculate virtual address. */
827 base = reg[rs(instr)];
828 offset = s_immed(instr);
829 virt = base + offset;
830 /* We request the word containing the byte-address requested. */
831 wordvirt = virt & ~0x03UL;
832
833 /* Translate virtual address to physical address. */
834 phys = cpzero->address_trans(wordvirt, DATALOAD, &cacheable, this);
835 if (exception_pending) return;
836
837 /* Fetch word. */
838 memword = mem->fetch_word(phys, DATALOAD, cacheable, this);
839 if (exception_pending) return;
840
841 /* Insert bytes into the left side of the register. */
842 which_byte = virt & 0x03;
843 reg[rt(instr)] = lwr(reg[rt(instr)], memword, which_byte);
844 }
845
846 void
sb_emulate(uint32 instr,uint32 pc)847 CPU::sb_emulate(uint32 instr, uint32 pc)
848 {
849 uint32 phys, virt, base;
850 uint8 data;
851 int32 offset;
852 bool cacheable;
853
854 /* Load data from register. */
855 data = reg[rt(instr)] & 0x0ff;
856
857 /* Calculate virtual address. */
858 base = reg[rs(instr)];
859 offset = s_immed(instr);
860 virt = base + offset;
861
862 /* Translate virtual address to physical address. */
863 phys = cpzero->address_trans(virt, DATASTORE, &cacheable, this);
864 if (exception_pending) return;
865
866 /* Store byte. */
867 mem->store_byte(phys, data, cacheable, this);
868 }
869
870 void
sh_emulate(uint32 instr,uint32 pc)871 CPU::sh_emulate(uint32 instr, uint32 pc)
872 {
873 uint32 phys, virt, base;
874 uint16 data;
875 int32 offset;
876 bool cacheable;
877
878 /* Load data from register. */
879 data = reg[rt(instr)] & 0x0ffff;
880
881 /* Calculate virtual address. */
882 base = reg[rs(instr)];
883 offset = s_immed(instr);
884 virt = base + offset;
885
886 /* This virtual address must be halfword-aligned. */
887 if (virt % 2 != 0) {
888 exception(AdES,DATASTORE);
889 return;
890 }
891
892 /* Translate virtual address to physical address. */
893 phys = cpzero->address_trans(virt, DATASTORE, &cacheable, this);
894 if (exception_pending) return;
895
896 /* Store halfword. */
897 mem->store_halfword(phys, data, cacheable, this);
898 }
899
900 uint32
swl(uint32 regval,uint32 memval,uint8 offset)901 CPU::swl(uint32 regval, uint32 memval, uint8 offset)
902 {
903 if (opt_bigendian) {
904 switch (offset) {
905 case 0: return regval;
906 case 1: return (memval & 0xff000000) | (regval >> 8 & 0xffffff);
907 case 2: return (memval & 0xffff0000) | (regval >> 16 & 0xffff);
908 case 3: return (memval & 0xffffff00) | (regval >> 24 & 0xff);
909 }
910 } else /* if MIPS target is little endian */ {
911 switch (offset) {
912 case 0: return (memval & 0xffffff00) | (regval >> 24 & 0xff);
913 case 1: return (memval & 0xffff0000) | (regval >> 16 & 0xffff);
914 case 2: return (memval & 0xff000000) | (regval >> 8 & 0xffffff);
915 case 3: return regval;
916 }
917 }
918 fatal_error("Invalid offset %x passed to swl\n", offset);
919 }
920
921 uint32
swr(uint32 regval,uint32 memval,uint8 offset)922 CPU::swr(uint32 regval, uint32 memval, uint8 offset)
923 {
924 if (opt_bigendian) {
925 switch (offset) {
926 case 0: return ((regval << 24) & 0xff000000) | (memval & 0xffffff);
927 case 1: return ((regval << 16) & 0xffff0000) | (memval & 0xffff);
928 case 2: return ((regval << 8) & 0xffffff00) | (memval & 0xff);
929 case 3: return regval;
930 }
931 } else /* if MIPS target is little endian */ {
932 switch (offset) {
933 case 0: return regval;
934 case 1: return ((regval << 8) & 0xffffff00) | (memval & 0xff);
935 case 2: return ((regval << 16) & 0xffff0000) | (memval & 0xffff);
936 case 3: return ((regval << 24) & 0xff000000) | (memval & 0xffffff);
937 }
938 }
939 fatal_error("Invalid offset %x passed to swr\n", offset);
940 }
941
942 void
swl_emulate(uint32 instr,uint32 pc)943 CPU::swl_emulate(uint32 instr, uint32 pc)
944 {
945 uint32 phys, virt, wordvirt, base, regdata, memdata;
946 int32 offset;
947 uint8 which_byte;
948 bool cacheable;
949
950 /* Load data from register. */
951 regdata = reg[rt(instr)];
952
953 /* Calculate virtual address. */
954 base = reg[rs(instr)];
955 offset = s_immed(instr);
956 virt = base + offset;
957 /* We request the word containing the byte-address requested. */
958 wordvirt = virt & ~0x03UL;
959
960 /* Translate virtual address to physical address. */
961 phys = cpzero->address_trans(wordvirt, DATASTORE, &cacheable, this);
962 if (exception_pending) return;
963
964 /* Read data from memory. */
965 memdata = mem->fetch_word(phys, DATASTORE, cacheable, this);
966 if (exception_pending) return;
967
968 /* Write back the left side of the register. */
969 which_byte = virt & 0x03UL;
970 mem->store_word(phys, swl(regdata, memdata, which_byte), cacheable, this);
971 }
972
973 void
sw_emulate(uint32 instr,uint32 pc)974 CPU::sw_emulate(uint32 instr, uint32 pc)
975 {
976 uint32 phys, virt, base, data;
977 int32 offset;
978 bool cacheable;
979
980 /* Load data from register. */
981 data = reg[rt(instr)];
982
983 /* Calculate virtual address. */
984 base = reg[rs(instr)];
985 offset = s_immed(instr);
986 virt = base + offset;
987
988 /* This virtual address must be word-aligned. */
989 if (virt % 4 != 0) {
990 exception(AdES,DATASTORE);
991 return;
992 }
993
994 /* Translate virtual address to physical address. */
995 phys = cpzero->address_trans(virt, DATASTORE, &cacheable, this);
996 if (exception_pending) return;
997
998 /* Store word. */
999 mem->store_word(phys, data, cacheable, this);
1000 }
1001
1002 void
swr_emulate(uint32 instr,uint32 pc)1003 CPU::swr_emulate(uint32 instr, uint32 pc)
1004 {
1005 uint32 phys, virt, wordvirt, base, regdata, memdata;
1006 int32 offset;
1007 uint8 which_byte;
1008 bool cacheable;
1009
1010 /* Load data from register. */
1011 regdata = reg[rt(instr)];
1012
1013 /* Calculate virtual address. */
1014 base = reg[rs(instr)];
1015 offset = s_immed(instr);
1016 virt = base + offset;
1017 /* We request the word containing the byte-address requested. */
1018 wordvirt = virt & ~0x03UL;
1019
1020 /* Translate virtual address to physical address. */
1021 phys = cpzero->address_trans(wordvirt, DATASTORE, &cacheable, this);
1022 if (exception_pending) return;
1023
1024 /* Read data from memory. */
1025 memdata = mem->fetch_word(phys, DATASTORE, cacheable, this);
1026 if (exception_pending) return;
1027
1028 /* Write back the right side of the register. */
1029 which_byte = virt & 0x03UL;
1030 mem->store_word(phys, swr(regdata, memdata, which_byte), cacheable, this);
1031 }
1032
1033 void
lwc1_emulate(uint32 instr,uint32 pc)1034 CPU::lwc1_emulate(uint32 instr, uint32 pc)
1035 {
1036 if (opt_fpu) {
1037 uint32 phys, virt, base, word;
1038 int32 offset;
1039 bool cacheable;
1040
1041 /* Calculate virtual address. */
1042 base = reg[rs(instr)];
1043 offset = s_immed(instr);
1044 virt = base + offset;
1045
1046 /* This virtual address must be word-aligned. */
1047 if (virt % 4 != 0) {
1048 exception(AdEL,DATALOAD);
1049 return;
1050 }
1051
1052 /* Translate virtual address to physical address. */
1053 phys = cpzero->address_trans(virt, DATALOAD, &cacheable, this);
1054 if (exception_pending) return;
1055
1056 /* Fetch word. */
1057 word = mem->fetch_word(phys, DATALOAD, cacheable, this);
1058 if (exception_pending) return;
1059
1060 /* Load target register with data. */
1061 fpu->write_reg (rt (instr), word);
1062 } else {
1063 cop_unimpl (1, instr, pc);
1064 }
1065 }
1066
1067 void
lwc2_emulate(uint32 instr,uint32 pc)1068 CPU::lwc2_emulate(uint32 instr, uint32 pc)
1069 {
1070 cop_unimpl (2, instr, pc);
1071 }
1072
1073 void
lwc3_emulate(uint32 instr,uint32 pc)1074 CPU::lwc3_emulate(uint32 instr, uint32 pc)
1075 {
1076 cop_unimpl (3, instr, pc);
1077 }
1078
1079 void
swc1_emulate(uint32 instr,uint32 pc)1080 CPU::swc1_emulate(uint32 instr, uint32 pc)
1081 {
1082 if (opt_fpu) {
1083 uint32 phys, virt, base, data;
1084 int32 offset;
1085 bool cacheable;
1086
1087 /* Load data from register. */
1088 data = fpu->read_reg (rt (instr));
1089
1090 /* Calculate virtual address. */
1091 base = reg[rs(instr)];
1092 offset = s_immed(instr);
1093 virt = base + offset;
1094
1095 /* This virtual address must be word-aligned. */
1096 if (virt % 4 != 0) {
1097 exception(AdES,DATASTORE);
1098 return;
1099 }
1100
1101 /* Translate virtual address to physical address. */
1102 phys = cpzero->address_trans(virt, DATASTORE, &cacheable, this);
1103 if (exception_pending) return;
1104
1105 /* Store word. */
1106 mem->store_word(phys, data, cacheable, this);
1107 } else {
1108 cop_unimpl (1, instr, pc);
1109 }
1110 }
1111
1112 void
swc2_emulate(uint32 instr,uint32 pc)1113 CPU::swc2_emulate(uint32 instr, uint32 pc)
1114 {
1115 cop_unimpl (2, instr, pc);
1116 }
1117
1118 void
swc3_emulate(uint32 instr,uint32 pc)1119 CPU::swc3_emulate(uint32 instr, uint32 pc)
1120 {
1121 cop_unimpl (3, instr, pc);
1122 }
1123
1124 void
sll_emulate(uint32 instr,uint32 pc)1125 CPU::sll_emulate(uint32 instr, uint32 pc)
1126 {
1127 reg[rd(instr)] = reg[rt(instr)] << shamt(instr);
1128 }
1129
1130 int32
srl(int32 a,int32 b)1131 srl(int32 a, int32 b)
1132 {
1133 if (b == 0) {
1134 return a;
1135 } else if (b == 32) {
1136 return 0;
1137 } else {
1138 return (a >> b) & ((1 << (32 - b)) - 1);
1139 }
1140 }
1141
1142 int32
sra(int32 a,int32 b)1143 sra(int32 a, int32 b)
1144 {
1145 if (b == 0) {
1146 return a;
1147 } else {
1148 return (a >> b) | (((a >> 31) & 0x01) * (((1 << b) - 1) << (32 - b)));
1149 }
1150 }
1151
1152 void
srl_emulate(uint32 instr,uint32 pc)1153 CPU::srl_emulate(uint32 instr, uint32 pc)
1154 {
1155 reg[rd(instr)] = srl(reg[rt(instr)], shamt(instr));
1156 }
1157
1158 void
sra_emulate(uint32 instr,uint32 pc)1159 CPU::sra_emulate(uint32 instr, uint32 pc)
1160 {
1161 reg[rd(instr)] = sra(reg[rt(instr)], shamt(instr));
1162 }
1163
1164 void
sllv_emulate(uint32 instr,uint32 pc)1165 CPU::sllv_emulate(uint32 instr, uint32 pc)
1166 {
1167 reg[rd(instr)] = reg[rt(instr)] << (reg[rs(instr)] & 0x01f);
1168 }
1169
1170 void
srlv_emulate(uint32 instr,uint32 pc)1171 CPU::srlv_emulate(uint32 instr, uint32 pc)
1172 {
1173 reg[rd(instr)] = srl(reg[rt(instr)], reg[rs(instr)] & 0x01f);
1174 }
1175
1176 void
srav_emulate(uint32 instr,uint32 pc)1177 CPU::srav_emulate(uint32 instr, uint32 pc)
1178 {
1179 reg[rd(instr)] = sra(reg[rt(instr)], reg[rs(instr)] & 0x01f);
1180 }
1181
1182 void
jr_emulate(uint32 instr,uint32 pc)1183 CPU::jr_emulate(uint32 instr, uint32 pc)
1184 {
1185 if (reg[rd(instr)] != 0) {
1186 exception(RI);
1187 return;
1188 }
1189 control_transfer (reg[rs(instr)]);
1190 }
1191
1192 void
jalr_emulate(uint32 instr,uint32 pc)1193 CPU::jalr_emulate(uint32 instr, uint32 pc)
1194 {
1195 control_transfer (reg[rs(instr)]);
1196 /* RA gets addr of instr after delay slot (2 words after this one). */
1197 reg[rd(instr)] = pc + 8;
1198 }
1199
1200 void
syscall_emulate(uint32 instr,uint32 pc)1201 CPU::syscall_emulate(uint32 instr, uint32 pc)
1202 {
1203 exception(Sys);
1204 }
1205
1206 void
break_emulate(uint32 instr,uint32 pc)1207 CPU::break_emulate(uint32 instr, uint32 pc)
1208 {
1209 exception(Bp);
1210 }
1211
1212 void
mfhi_emulate(uint32 instr,uint32 pc)1213 CPU::mfhi_emulate(uint32 instr, uint32 pc)
1214 {
1215 reg[rd(instr)] = hi;
1216 }
1217
1218 void
mthi_emulate(uint32 instr,uint32 pc)1219 CPU::mthi_emulate(uint32 instr, uint32 pc)
1220 {
1221 if (rd(instr) != 0) {
1222 exception(RI);
1223 return;
1224 }
1225 hi = reg[rs(instr)];
1226 }
1227
1228 void
mflo_emulate(uint32 instr,uint32 pc)1229 CPU::mflo_emulate(uint32 instr, uint32 pc)
1230 {
1231 reg[rd(instr)] = lo;
1232 }
1233
1234 void
mtlo_emulate(uint32 instr,uint32 pc)1235 CPU::mtlo_emulate(uint32 instr, uint32 pc)
1236 {
1237 if (rd(instr) != 0) {
1238 exception(RI);
1239 return;
1240 }
1241 lo = reg[rs(instr)];
1242 }
1243
1244 void
mult_emulate(uint32 instr,uint32 pc)1245 CPU::mult_emulate(uint32 instr, uint32 pc)
1246 {
1247 if (rd(instr) != 0) {
1248 exception(RI);
1249 return;
1250 }
1251 mult64s(&hi, &lo, reg[rs(instr)], reg[rt(instr)]);
1252 }
1253
1254 void
mult64(uint32 * hi,uint32 * lo,uint32 n,uint32 m)1255 CPU::mult64(uint32 *hi, uint32 *lo, uint32 n, uint32 m)
1256 {
1257 #ifdef HAVE_LONG_LONG
1258 uint64 result;
1259 result = ((uint64)n) * ((uint64)m);
1260 *hi = (uint32) (result >> 32);
1261 *lo = (uint32) result;
1262 #else /* HAVE_LONG_LONG */
1263 /* n = (w << 16) | x ; m = (y << 16) | z
1264 * w x g = a + e ; h = b + f ; p = 65535
1265 * X y z c = (z * x) mod p
1266 * ----- b = (z * w + ((z * x) div p)) mod p
1267 * a b c a = (z * w + ((z * x) div p)) div p
1268 * d e f f = (y * x) mod p
1269 * ------- e = (y * w + ((y * x) div p)) mod p
1270 * i g h c d = (y * w + ((y * x) div p)) div p
1271 */
1272 uint16 w,x,y,z,a,b,c,d,e,f,g,h,i;
1273 uint32 p;
1274 p = 65536;
1275 w = (n >> 16) & 0x0ffff;
1276 x = n & 0x0ffff;
1277 y = (m >> 16) & 0x0ffff;
1278 z = m & 0x0ffff;
1279 c = (z * x) % p;
1280 b = (z * w + ((z * x) / p)) % p;
1281 a = (z * w + ((z * x) / p)) / p;
1282 f = (y * x) % p;
1283 e = (y * w + ((y * x) / p)) % p;
1284 d = (y * w + ((y * x) / p)) / p;
1285 h = (b + f) % p;
1286 g = ((a + e) + ((b + f) / p)) % p;
1287 i = d + (((a + e) + ((b + f) / p)) / p);
1288 *hi = (i << 16) | g;
1289 *lo = (h << 16) | c;
1290 #endif /* HAVE_LONG_LONG */
1291 }
1292
1293 void
mult64s(uint32 * hi,uint32 * lo,int32 n,int32 m)1294 CPU::mult64s(uint32 *hi, uint32 *lo, int32 n, int32 m)
1295 {
1296 #ifdef HAVE_LONG_LONG
1297 int64 result;
1298 result = ((int64)n) * ((int64)m);
1299 *hi = (uint32) (result >> 32);
1300 *lo = (uint32) result;
1301 #else /* HAVE_LONG_LONG */
1302 int32 result_sign = (n<0)^(m<0);
1303 int32 n_abs = n;
1304 int32 m_abs = m;
1305
1306 if (n_abs < 0) n_abs = -n_abs;
1307 if (m_abs < 0) m_abs = -m_abs;
1308
1309 mult64(hi,lo,n_abs,m_abs);
1310 if (result_sign)
1311 {
1312 *hi = ~*hi;
1313 *lo = ~*lo;
1314 if (*lo & 0x80000000)
1315 {
1316 *lo += 1;
1317 if (!(*lo & 0x80000000))
1318 {
1319 *hi += 1;
1320 }
1321 }
1322 else
1323 {
1324 *lo += 1;
1325 }
1326 }
1327 #endif /* HAVE_LONG_LONG */
1328 }
1329
1330 void
multu_emulate(uint32 instr,uint32 pc)1331 CPU::multu_emulate(uint32 instr, uint32 pc)
1332 {
1333 if (rd(instr) != 0) {
1334 exception(RI);
1335 return;
1336 }
1337 mult64(&hi, &lo, reg[rs(instr)], reg[rt(instr)]);
1338 }
1339
1340 void
div_emulate(uint32 instr,uint32 pc)1341 CPU::div_emulate(uint32 instr, uint32 pc)
1342 {
1343 int32 signed_rs = (int32)reg[rs(instr)];
1344 int32 signed_rt = (int32)reg[rt(instr)];
1345 lo = signed_rs / signed_rt;
1346 hi = signed_rs % signed_rt;
1347 }
1348
1349 void
divu_emulate(uint32 instr,uint32 pc)1350 CPU::divu_emulate(uint32 instr, uint32 pc)
1351 {
1352 lo = reg[rs(instr)] / reg[rt(instr)];
1353 hi = reg[rs(instr)] % reg[rt(instr)];
1354 }
1355
1356 void
add_emulate(uint32 instr,uint32 pc)1357 CPU::add_emulate(uint32 instr, uint32 pc)
1358 {
1359 int32 a, b, sum;
1360 a = (int32)reg[rs(instr)];
1361 b = (int32)reg[rt(instr)];
1362 sum = a + b;
1363 if ((a < 0 && b < 0 && !(sum < 0)) || (a >= 0 && b >= 0 && !(sum >= 0))) {
1364 exception(Ov);
1365 return;
1366 } else {
1367 reg[rd(instr)] = (uint32)sum;
1368 }
1369 }
1370
1371 void
addu_emulate(uint32 instr,uint32 pc)1372 CPU::addu_emulate(uint32 instr, uint32 pc)
1373 {
1374 int32 a, b, sum;
1375 a = (int32)reg[rs(instr)];
1376 b = (int32)reg[rt(instr)];
1377 sum = a + b;
1378 reg[rd(instr)] = (uint32)sum;
1379 }
1380
1381 void
sub_emulate(uint32 instr,uint32 pc)1382 CPU::sub_emulate(uint32 instr, uint32 pc)
1383 {
1384 int32 a, b, diff;
1385 a = (int32)reg[rs(instr)];
1386 b = (int32)reg[rt(instr)];
1387 diff = a - b;
1388 if ((a < 0 && !(b < 0) && !(diff < 0)) || (!(a < 0) && b < 0 && diff < 0)) {
1389 exception(Ov);
1390 return;
1391 } else {
1392 reg[rd(instr)] = (uint32)diff;
1393 }
1394 }
1395
1396 void
subu_emulate(uint32 instr,uint32 pc)1397 CPU::subu_emulate(uint32 instr, uint32 pc)
1398 {
1399 int32 a, b, diff;
1400 a = (int32)reg[rs(instr)];
1401 b = (int32)reg[rt(instr)];
1402 diff = a - b;
1403 reg[rd(instr)] = (uint32)diff;
1404 }
1405
1406 void
and_emulate(uint32 instr,uint32 pc)1407 CPU::and_emulate(uint32 instr, uint32 pc)
1408 {
1409 reg[rd(instr)] = reg[rs(instr)] & reg[rt(instr)];
1410 }
1411
1412 void
or_emulate(uint32 instr,uint32 pc)1413 CPU::or_emulate(uint32 instr, uint32 pc)
1414 {
1415 reg[rd(instr)] = reg[rs(instr)] | reg[rt(instr)];
1416 }
1417
1418 void
xor_emulate(uint32 instr,uint32 pc)1419 CPU::xor_emulate(uint32 instr, uint32 pc)
1420 {
1421 reg[rd(instr)] = reg[rs(instr)] ^ reg[rt(instr)];
1422 }
1423
1424 void
nor_emulate(uint32 instr,uint32 pc)1425 CPU::nor_emulate(uint32 instr, uint32 pc)
1426 {
1427 reg[rd(instr)] = ~(reg[rs(instr)] | reg[rt(instr)]);
1428 }
1429
1430 void
slt_emulate(uint32 instr,uint32 pc)1431 CPU::slt_emulate(uint32 instr, uint32 pc)
1432 {
1433 int32 s_rs = (int32)reg[rs(instr)];
1434 int32 s_rt = (int32)reg[rt(instr)];
1435 if (s_rs < s_rt) {
1436 reg[rd(instr)] = 1;
1437 } else {
1438 reg[rd(instr)] = 0;
1439 }
1440 }
1441
1442 void
sltu_emulate(uint32 instr,uint32 pc)1443 CPU::sltu_emulate(uint32 instr, uint32 pc)
1444 {
1445 if (reg[rs(instr)] < reg[rt(instr)]) {
1446 reg[rd(instr)] = 1;
1447 } else {
1448 reg[rd(instr)] = 0;
1449 }
1450 }
1451
1452 void
bltz_emulate(uint32 instr,uint32 pc)1453 CPU::bltz_emulate(uint32 instr, uint32 pc)
1454 {
1455 if ((int32)reg[rs(instr)] < 0)
1456 branch(instr, pc);
1457 }
1458
1459 void
bgez_emulate(uint32 instr,uint32 pc)1460 CPU::bgez_emulate(uint32 instr, uint32 pc)
1461 {
1462 if ((int32)reg[rs(instr)] >= 0)
1463 branch(instr, pc);
1464 }
1465
1466 /* As with JAL, BLTZAL and BGEZAL cause RA to get the address of the
1467 * instruction two words after the current one (pc + 8).
1468 */
1469 void
bltzal_emulate(uint32 instr,uint32 pc)1470 CPU::bltzal_emulate(uint32 instr, uint32 pc)
1471 {
1472 reg[reg_ra] = pc + 8;
1473 if ((int32)reg[rs(instr)] < 0)
1474 branch(instr, pc);
1475 }
1476
1477 void
bgezal_emulate(uint32 instr,uint32 pc)1478 CPU::bgezal_emulate(uint32 instr, uint32 pc)
1479 {
1480 reg[reg_ra] = pc + 8;
1481 if ((int32)reg[rs(instr)] >= 0)
1482 branch(instr, pc);
1483 }
1484
1485 /* reserved instruction */
1486 void
RI_emulate(uint32 instr,uint32 pc)1487 CPU::RI_emulate(uint32 instr, uint32 pc)
1488 {
1489 exception(RI);
1490 }
1491
1492 void
open_trace_file()1493 CPU::open_trace_file ()
1494 {
1495 char tracefilename[80];
1496 for (unsigned i = 0; ; ++i) {
1497 sprintf (tracefilename, "traceout%d.txt", i);
1498 if (!can_read_file (tracefilename))
1499 break;
1500 }
1501 traceout = fopen (tracefilename, "w");
1502 }
1503
1504 void
close_trace_file()1505 CPU::close_trace_file ()
1506 {
1507 fclose (traceout);
1508 }
1509
1510 void
write_trace_to_file()1511 CPU::write_trace_to_file ()
1512 {
1513 for (Trace::record_iterator ri = current_trace.rbegin (), re =
1514 current_trace.rend (); ri != re; ++ri) {
1515 Trace::Record &tr = *ri;
1516 fprintf (traceout, "(TraceRec (PC #x%08x) (Insn #x%08x) ", tr.pc, tr.instr);
1517
1518 if (! tr.inputs.empty ()) {
1519
1520 fprintf (traceout, "(Inputs (");
1521 for (std::vector<Trace::Operand>::iterator oi = tr.inputs.begin (),
1522 oe = tr.inputs.end (); oi != oe; ++oi) {
1523 Trace::Operand &op = *oi;
1524 if (op.regno != -1) {
1525 fprintf (traceout, "(%s %d #x%08x) ", op.tag, op.regno, op.val);
1526 } else {
1527 fprintf (traceout, "(%s #x%08x) ", op.tag, op.val);
1528 }
1529 }
1530 fprintf (traceout, "))");
1531
1532 }
1533
1534 if (!tr.outputs.empty ()) {
1535
1536 fprintf (traceout, "(Outputs (");
1537 for (std::vector<Trace::Operand>::iterator oi = tr.outputs.begin (),
1538 oe = tr.outputs.end (); oi != oe; ++oi) {
1539 Trace::Operand &op = *oi;
1540 if (op.regno != -1) {
1541 fprintf (traceout, "(%s %d #x%08x) ", op.tag, op.regno, op.val);
1542 } else {
1543 fprintf (traceout, "(%s #x%08x) ", op.tag, op.val);
1544 }
1545 }
1546 fprintf (traceout, "))");
1547
1548 }
1549 fprintf (traceout, ")\n");
1550 }
1551 // print lastchanges
1552 fprintf (traceout, "(LastChanges (");
1553 for (unsigned i = 0; i < 32; ++i) {
1554 if (current_trace.last_change_for_reg.find (i) !=
1555 current_trace.last_change_for_reg.end ()) {
1556 last_change &lc = current_trace.last_change_for_reg[i];
1557 fprintf (traceout,
1558 "(Reg %d PC %x Instr %x OldValue %x CurValue %x) ",
1559 i, lc.pc, lc.instr, lc.old_value, reg[i]);
1560 }
1561 }
1562 fprintf (traceout, "))\n");
1563 }
1564
1565 void
flush_trace()1566 CPU::flush_trace()
1567 {
1568 if (!opt_tracing) return;
1569 write_trace_to_file ();
1570 current_trace.clear ();
1571 }
1572
1573 void
start_tracing()1574 CPU::start_tracing()
1575 {
1576 if (!opt_tracing) return;
1577 tracing = true;
1578 current_trace.clear ();
1579 }
1580
1581 void
write_trace_instr_inputs(uint32 instr)1582 CPU::write_trace_instr_inputs (uint32 instr)
1583 {
1584 // rs,rt: add,addu,and,beq,bne,div,divu,mult,multu,nor,or,sb,sh,sllv,slt,
1585 // sltu,srav,srlv,sub,subu,sw,swl,swr,xor
1586 // rs: addi,addiu,andi,bgez,bgezal,bgtz,blez,bltz,bltzal,jal,jr,lb,lbu,
1587 // lh,lhu,lw,lwl,lwr,mthi,mtlo,ori,slti,sltiu,xori
1588 // hi: mfhi
1589 // lo: mflo
1590 // rt: mtc0
1591 // rt,shamt: sll,sra,srl
1592 // NOT HANDLED: syscall,break,jalr,cpone,cpthree,cptwo,cpzero,
1593 // j,lui,lwc1,lwc2,lwc3,mtc0,swc1,swc2,swc3
1594 switch(opcode(instr))
1595 {
1596 case 0:
1597 switch(funct(instr))
1598 {
1599 case 4: //sllv
1600 case 6: //srlv
1601 case 7: //srav
1602 case 24: //mult
1603 case 25: //multu
1604 case 26: //div
1605 case 27: //divu
1606 case 32: //add
1607 case 33: //addu
1608 case 34: //sub
1609 case 35: //subu
1610 case 36: //and
1611 case 37: //or
1612 case 38: //xor
1613 case 39: //nor
1614 case 42: //slt
1615 case 43: //sltu
1616 current_trace_record.inputs_push_back_op("rs",
1617 rs(instr), reg[rs(instr)]);
1618 current_trace_record.inputs_push_back_op("rt",
1619 rt(instr), reg[rt(instr)]);
1620 break;
1621 case 0: //sll
1622 case 2: //srl
1623 case 3: //sra
1624 current_trace_record.inputs_push_back_op("rt",
1625 rt(instr), reg[rt(instr)]);
1626 break;
1627 case 8: //jr
1628 case 17: //mthi
1629 case 19: //mtlo
1630 current_trace_record.inputs_push_back_op("rs",
1631 rs(instr), reg[rs(instr)]);
1632 break;
1633 case 16: //mfhi
1634 current_trace_record.inputs_push_back_op("hi",
1635 hi);
1636 break;
1637 case 18: //mflo
1638 current_trace_record.inputs_push_back_op("lo",
1639 lo);
1640 break;
1641 }
1642 break;
1643 case 1:
1644 switch(rt(instr)) {
1645 case 0: //bltz
1646 case 1: //bgez
1647 case 16: //bltzal
1648 case 17: //bgezal
1649 current_trace_record.inputs_push_back_op("rs",
1650 rs(instr), reg[rs(instr)]);
1651 break;
1652 }
1653 break;
1654 case 3: //jal
1655 case 6: //blez
1656 case 7: //bgtz
1657 case 8: //addi
1658 case 9: //addiu
1659 case 12: //andi
1660 case 32: //lb
1661 case 33: //lh
1662 case 35: //lw
1663 case 36: //lbu
1664 case 37: //lhu
1665 case 40: //sb
1666 case 41: //sh
1667 case 42: //swl
1668 case 43: //sw
1669 case 46: //swr
1670 current_trace_record.inputs_push_back_op("rs",
1671 rs(instr), reg[rs(instr)]);
1672 current_trace_record.inputs_push_back_op("rt",
1673 rt(instr), reg[rt(instr)]);
1674 break;
1675 case 4: //beq
1676 case 5: //bne
1677 case 10: //slti
1678 case 11: //sltiu
1679 case 13: //ori
1680 case 14: //xori
1681 case 34: //lwl
1682 case 38: //lwr
1683 current_trace_record.inputs_push_back_op("rs",
1684 rs(instr), reg[rs(instr)]);
1685 break;
1686 }
1687 }
1688
1689
1690 void
write_trace_instr_outputs(uint32 instr)1691 CPU::write_trace_instr_outputs (uint32 instr)
1692 {
1693 // hi,lo: div,divu,mult,multu
1694 // hi: mthi
1695 // lo: mtlo
1696 // rt: addi,addiu,andi,lb,lbu,lh,lhu,lui,lw,lwl,lwr,mfc0,ori,slti,sltiu,
1697 // xori
1698 // rd: add,addu,and,jalr,mfhi,mflo,nor,or,sllv,slt,sltu,sll,sra,srav,srl,
1699 // srlv,sub,subu,xor
1700 // r31: jal
1701 // NOT HANDLED: syscall,break,jalr,cpone,cpthree,cptwo,cpzero,j,lwc1,lwc2,
1702 // lwc3,mtc0,swc1,swc2,swc3,jr,jalr,mfc0,bgtz,blez,sb,sh,sw,
1703 // swl,swr,beq,bne
1704 switch(opcode(instr))
1705 {
1706 case 0:
1707 switch(funct(instr))
1708 {
1709 case 26: //div
1710 case 27: //divu
1711 case 24: //mult
1712 case 25: //multu
1713 current_trace_record.outputs_push_back_op("lo",
1714 lo);
1715 current_trace_record.outputs_push_back_op("hi",
1716 hi);
1717 break;
1718 case 17: //mthi
1719 current_trace_record.outputs_push_back_op("hi",
1720 hi);
1721 break;
1722 case 19: //mtlo
1723 current_trace_record.outputs_push_back_op("lo",
1724 lo);
1725 break;
1726 case 32: //add
1727 case 33: //addu
1728 case 36: //and
1729 case 39: //nor
1730 case 37: //or
1731 case 4: //sllv
1732 case 42: //slt
1733 case 43: //sltu
1734 case 7: //srav
1735 case 6: //srlv
1736 case 34: //sub
1737 case 35: //subu
1738 case 38: //xor
1739 case 0: //sll
1740 case 3: //sra
1741 case 2: //srl
1742 case 16: //mfhi
1743 case 18: //mflo
1744 current_trace_record.outputs_push_back_op("rd",
1745 rd(instr),reg[rd(instr)]);
1746 break;
1747 }
1748 break;
1749 case 8: //addi
1750 case 9: //addiu
1751 case 12: //andi
1752 case 32: //lb
1753 case 36: //lbu
1754 case 33: //lh
1755 case 37: //lhu
1756 case 35: //lw
1757 case 34: //lwl
1758 case 38: //lwr
1759 case 13: //ori
1760 case 10: //slti
1761 case 11: //sltiu
1762 case 14: //xori
1763 case 15: //lui
1764 current_trace_record.outputs_push_back_op("rt",rt(instr),
1765 reg[rt(instr)]);
1766 break;
1767 case 3: //jal
1768 current_trace_record.outputs_push_back_op("ra",
1769 reg[reg_ra]);
1770 break;
1771 }
1772 }
1773
1774 void
write_trace_record_1(uint32 pc,uint32 instr)1775 CPU::write_trace_record_1(uint32 pc, uint32 instr)
1776 {
1777 current_trace_record.clear ();
1778 current_trace_record.pc = pc;
1779 current_trace_record.instr = instr;
1780 write_trace_instr_inputs (instr);
1781 std::copy (®[0], ®[32], ¤t_trace_record.saved_reg[0]);
1782 }
1783
1784 void
write_trace_record_2(uint32 pc,uint32 instr)1785 CPU::write_trace_record_2 (uint32 pc, uint32 instr)
1786 {
1787 write_trace_instr_outputs (instr);
1788 // which insn was the last to change each reg?
1789 for (unsigned i = 0; i < 32; ++i) {
1790 if (current_trace_record.saved_reg[i] != reg[i]) {
1791 current_trace.last_change_for_reg[i] = last_change::make (pc, instr,
1792 current_trace_record.saved_reg[i]);
1793 }
1794 }
1795 current_trace.push_back_record (current_trace_record);
1796 if (current_trace.record_size () > opt_tracesize)
1797 flush_trace ();
1798 }
1799
1800 void
stop_tracing()1801 CPU::stop_tracing()
1802 {
1803 tracing = false;
1804 }
1805
1806 /* dispatching */
1807 void
step()1808 CPU::step()
1809 {
1810 // Table of emulation functions.
1811 static const emulate_funptr opcodeJumpTable[] = {
1812 &CPU::funct_emulate, &CPU::regimm_emulate, &CPU::j_emulate,
1813 &CPU::jal_emulate, &CPU::beq_emulate, &CPU::bne_emulate,
1814 &CPU::blez_emulate, &CPU::bgtz_emulate, &CPU::addi_emulate,
1815 &CPU::addiu_emulate, &CPU::slti_emulate, &CPU::sltiu_emulate,
1816 &CPU::andi_emulate, &CPU::ori_emulate, &CPU::xori_emulate,
1817 &CPU::lui_emulate, &CPU::cpzero_emulate, &CPU::cpone_emulate,
1818 &CPU::cptwo_emulate, &CPU::cpthree_emulate, &CPU::RI_emulate,
1819 &CPU::RI_emulate, &CPU::RI_emulate, &CPU::RI_emulate,
1820 &CPU::RI_emulate, &CPU::RI_emulate, &CPU::RI_emulate,
1821 &CPU::RI_emulate, &CPU::RI_emulate, &CPU::RI_emulate,
1822 &CPU::RI_emulate, &CPU::RI_emulate, &CPU::lb_emulate,
1823 &CPU::lh_emulate, &CPU::lwl_emulate, &CPU::lw_emulate,
1824 &CPU::lbu_emulate, &CPU::lhu_emulate, &CPU::lwr_emulate,
1825 &CPU::RI_emulate, &CPU::sb_emulate, &CPU::sh_emulate,
1826 &CPU::swl_emulate, &CPU::sw_emulate, &CPU::RI_emulate,
1827 &CPU::RI_emulate, &CPU::swr_emulate, &CPU::RI_emulate,
1828 &CPU::RI_emulate, &CPU::lwc1_emulate, &CPU::lwc2_emulate,
1829 &CPU::lwc3_emulate, &CPU::RI_emulate, &CPU::RI_emulate,
1830 &CPU::RI_emulate, &CPU::RI_emulate, &CPU::RI_emulate,
1831 &CPU::swc1_emulate, &CPU::swc2_emulate, &CPU::swc3_emulate,
1832 &CPU::RI_emulate, &CPU::RI_emulate, &CPU::RI_emulate,
1833 &CPU::RI_emulate
1834 };
1835
1836 // Clear exception_pending flag if it was set by a prior instruction.
1837 exception_pending = false;
1838
1839 // Decrement Random register every clock cycle.
1840 cpzero->adjust_random();
1841
1842 // Check whether we should start tracing with this instruction.
1843 if (opt_tracing && !tracing && pc == opt_tracestartpc)
1844 start_tracing();
1845
1846 // Save address of instruction responsible for exceptions which may occur.
1847 if (delay_state != DELAYSLOT)
1848 next_epc = pc;
1849
1850 // Get physical address of next instruction.
1851 bool cacheable;
1852 uint32 real_pc = cpzero->address_trans(pc,INSTFETCH,&cacheable, this);
1853 if (exception_pending) {
1854 if (opt_excmsg)
1855 fprintf(stderr,
1856 "** PC address translation caused the exception! **\n");
1857 goto out;
1858 }
1859
1860 // Fetch next instruction.
1861 instr = mem->fetch_word(real_pc,INSTFETCH,cacheable, this);
1862 if (exception_pending) {
1863 if (opt_excmsg)
1864 fprintf(stderr, "** Instruction fetch caused the exception! **\n");
1865 goto out;
1866 }
1867
1868 // Disassemble the instruction, if the user requested it.
1869 if (opt_instdump) {
1870 fprintf(stderr,"PC=0x%08x [%08x]\t%08x ",pc,real_pc,instr);
1871 machine->disasm->disassemble(pc,instr);
1872 }
1873
1874 // Perform first half of trace recording for this instruction.
1875 if (tracing)
1876 write_trace_record_1 (pc, instr);
1877
1878 // Check for a (hardware or software) interrupt.
1879 if (cpzero->interrupt_pending()) {
1880 exception(Int);
1881 goto out;
1882 }
1883
1884 // Emulate the instruction by jumping to the appropriate emulation method.
1885 (this->*opcodeJumpTable[opcode(instr)])(instr, pc);
1886
1887 out:
1888 // Force register zero to contain zero.
1889 reg[reg_zero] = 0;
1890
1891 // Perform second half of trace recording for this instruction.
1892 if (tracing) {
1893 write_trace_record_2 (pc, instr);
1894 if (pc == opt_traceendpc)
1895 stop_tracing();
1896 }
1897
1898 // If an exception is pending, then the PC has already been changed to
1899 // contain the exception vector. Return now, so that we don't clobber it.
1900 if (exception_pending) {
1901 // Instruction at beginning of exception handler is NOT in delay slot,
1902 // no matter what the last instruction was.
1903 delay_state = NORMAL;
1904 return;
1905 }
1906
1907 // Recall the delay_state values: 0=NORMAL, 1=DELAYING, 2=DELAYSLOT.
1908 // This is what the delay_state values mean (at this point in the code):
1909 // DELAYING: The last instruction caused a branch to be taken.
1910 // The next instruction is in the delay slot.
1911 // The next instruction EPC will be PC - 4.
1912 // DELAYSLOT: The last instruction was executed in a delay slot.
1913 // The next instruction is on the other end of the branch.
1914 // The next instruction EPC will be PC.
1915 // NORMAL: No branch was executed; next instruction is at PC + 4.
1916 // Next instruction EPC is PC.
1917
1918 // Update the pc and delay_state values.
1919 pc += 4;
1920 if (delay_state == DELAYSLOT)
1921 pc = delay_pc;
1922 delay_state = (delay_state << 1) & 0x03; // 0->0, 1->2, 2->0
1923 }
1924
1925 void
funct_emulate(uint32 instr,uint32 pc)1926 CPU::funct_emulate(uint32 instr, uint32 pc)
1927 {
1928 static const emulate_funptr functJumpTable[] = {
1929 &CPU::sll_emulate, &CPU::RI_emulate,
1930 &CPU::srl_emulate, &CPU::sra_emulate,
1931 &CPU::sllv_emulate, &CPU::RI_emulate,
1932 &CPU::srlv_emulate, &CPU::srav_emulate,
1933 &CPU::jr_emulate, &CPU::jalr_emulate,
1934 &CPU::RI_emulate, &CPU::RI_emulate,
1935 &CPU::syscall_emulate, &CPU::break_emulate,
1936 &CPU::RI_emulate, &CPU::RI_emulate,
1937 &CPU::mfhi_emulate, &CPU::mthi_emulate,
1938 &CPU::mflo_emulate, &CPU::mtlo_emulate,
1939 &CPU::RI_emulate, &CPU::RI_emulate,
1940 &CPU::RI_emulate, &CPU::RI_emulate,
1941 &CPU::mult_emulate, &CPU::multu_emulate,
1942 &CPU::div_emulate, &CPU::divu_emulate,
1943 &CPU::RI_emulate, &CPU::RI_emulate,
1944 &CPU::RI_emulate, &CPU::RI_emulate,
1945 &CPU::add_emulate, &CPU::addu_emulate,
1946 &CPU::sub_emulate, &CPU::subu_emulate,
1947 &CPU::and_emulate, &CPU::or_emulate,
1948 &CPU::xor_emulate, &CPU::nor_emulate,
1949 &CPU::RI_emulate, &CPU::RI_emulate,
1950 &CPU::slt_emulate, &CPU::sltu_emulate,
1951 &CPU::RI_emulate, &CPU::RI_emulate,
1952 &CPU::RI_emulate, &CPU::RI_emulate,
1953 &CPU::RI_emulate, &CPU::RI_emulate,
1954 &CPU::RI_emulate, &CPU::RI_emulate,
1955 &CPU::RI_emulate, &CPU::RI_emulate,
1956 &CPU::RI_emulate, &CPU::RI_emulate,
1957 &CPU::RI_emulate, &CPU::RI_emulate,
1958 &CPU::RI_emulate, &CPU::RI_emulate,
1959 &CPU::RI_emulate, &CPU::RI_emulate,
1960 &CPU::RI_emulate, &CPU::RI_emulate
1961 };
1962 (this->*functJumpTable[funct(instr)])(instr, pc);
1963 }
1964
1965 void
regimm_emulate(uint32 instr,uint32 pc)1966 CPU::regimm_emulate(uint32 instr, uint32 pc)
1967 {
1968 switch(rt(instr))
1969 {
1970 case 0: bltz_emulate(instr, pc); break;
1971 case 1: bgez_emulate(instr, pc); break;
1972 case 16: bltzal_emulate(instr, pc); break;
1973 case 17: bgezal_emulate(instr, pc); break;
1974 default: exception(RI); break; /* reserved instruction */
1975 }
1976 }
1977
1978 /* Debug functions.
1979 *
1980 * These functions are primarily intended to support the Debug class,
1981 * which interfaces with GDB's remote serial protocol.
1982 */
1983
1984 /* Copy registers into an ASCII-encoded packet of hex numbers to send
1985 * to the remote GDB, and return the packet (allocated with malloc).
1986 */
1987 char *
debug_registers_to_packet(void)1988 CPU::debug_registers_to_packet(void)
1989 {
1990 char *packet = new char [PBUFSIZ];
1991 int i, r;
1992
1993 /* order of regs: (gleaned from gdb/gdb/config/mips/tm-mips.h)
1994 *
1995 * cpu->reg[0]...cpu->reg[31]
1996 * cpzero->reg[Status]
1997 * cpu->lo
1998 * cpu->hi
1999 * cpzero->reg[BadVAddr]
2000 * cpzero->reg[Cause]
2001 * cpu->pc
2002 * fpu stuff: 35 zeroes (Unimplemented registers read as
2003 * all bits zero.)
2004 */
2005 packet[0] = '\0';
2006 r = 0;
2007 for (i = 0; i < 32; i++) {
2008 debug_packet_push_word(packet, reg[i]); r++;
2009 }
2010 uint32 sr, bad, cause;
2011 cpzero->read_debug_info(&sr, &bad, &cause);
2012 debug_packet_push_word(packet, sr); r++;
2013 debug_packet_push_word(packet, lo); r++;
2014 debug_packet_push_word(packet, hi); r++;
2015 debug_packet_push_word(packet, bad); r++;
2016 debug_packet_push_word(packet, cause); r++;
2017 debug_packet_push_word(packet, pc); r++;
2018 for (; r < 90; r++) { /* unimplemented regs at end */
2019 debug_packet_push_word(packet, 0);
2020 }
2021 return packet;
2022 }
2023
2024 /* Copy the register values in the ASCII-encoded hex PACKET received from
2025 * the remote GDB and store them in the appropriate registers.
2026 */
2027 void
debug_packet_to_registers(char * packet)2028 CPU::debug_packet_to_registers(char *packet)
2029 {
2030 int i;
2031
2032 for (i = 0; i < 32; i++)
2033 reg[i] = machine->dbgr->packet_pop_word(&packet);
2034 uint32 sr, bad, cause;
2035 sr = machine->dbgr->packet_pop_word(&packet);
2036 lo = machine->dbgr->packet_pop_word(&packet);
2037 hi = machine->dbgr->packet_pop_word(&packet);
2038 bad = machine->dbgr->packet_pop_word(&packet);
2039 cause = machine->dbgr->packet_pop_word(&packet);
2040 pc = machine->dbgr->packet_pop_word(&packet);
2041 cpzero->write_debug_info(sr, bad, cause);
2042 }
2043
2044 /* Returns the exception code of any pending exception, or 0 if no
2045 * exception is pending.
2046 */
2047 uint8
pending_exception(void)2048 CPU::pending_exception(void)
2049 {
2050 uint32 sr, bad, cause;
2051
2052 if (! exception_pending) return 0;
2053 cpzero->read_debug_info(&sr, &bad, &cause);
2054 return ((cause & Cause_ExcCode_MASK) >> 2);
2055 }
2056
2057 /* Sets the program counter register to the value given in NEWPC. */
2058 void
debug_set_pc(uint32 newpc)2059 CPU::debug_set_pc(uint32 newpc)
2060 {
2061 pc = newpc;
2062 }
2063
2064 /* Returns the current program counter register. */
2065 uint32
debug_get_pc(void)2066 CPU::debug_get_pc(void)
2067 {
2068 return pc;
2069 }
2070
2071 void
debug_packet_push_word(char * packet,uint32 n)2072 CPU::debug_packet_push_word(char *packet, uint32 n)
2073 {
2074 if (!opt_bigendian) {
2075 n = Mapper::swap_word(n);
2076 }
2077 char packetpiece[10];
2078 sprintf(packetpiece, "%08x", n);
2079 strcat(packet, packetpiece);
2080 }
2081
2082 void
debug_packet_push_byte(char * packet,uint8 n)2083 CPU::debug_packet_push_byte(char *packet, uint8 n)
2084 {
2085 char packetpiece[4];
2086 sprintf(packetpiece, "%02x", n);
2087 strcat(packet, packetpiece);
2088 }
2089
2090 /* Fetch LEN bytes starting from virtual address ADDR into the packet
2091 * PACKET, sending exceptions (if any) to CLIENT. Returns -1 if an exception
2092 * was encountered, 0 otherwise. If an exception was encountered, the
2093 * contents of PACKET are undefined, and CLIENT->exception() will have
2094 * been called.
2095 */
2096 int
debug_fetch_region(uint32 addr,uint32 len,char * packet,DeviceExc * client)2097 CPU::debug_fetch_region(uint32 addr, uint32 len, char *packet,
2098 DeviceExc *client)
2099 {
2100 uint8 byte;
2101 uint32 real_addr;
2102 bool cacheable = false;
2103
2104 for (; len; addr++, len--) {
2105 real_addr = cpzero->address_trans(addr, DATALOAD, &cacheable, client);
2106 /* Stop now and return an error code if translation
2107 * caused an exception.
2108 */
2109 if (client->exception_pending) {
2110 return -1;
2111 }
2112 byte = mem->fetch_byte(real_addr, true, client);
2113 /* Stop now and return an error code if the fetch
2114 * caused an exception.
2115 */
2116 if (client->exception_pending) {
2117 return -1;
2118 }
2119 debug_packet_push_byte(packet, byte);
2120 }
2121 return 0;
2122 }
2123
2124 /* Store LEN bytes starting from virtual address ADDR from data in the packet
2125 * PACKET, sending exceptions (if any) to CLIENT. Returns -1 if an exception
2126 * was encountered, 0 otherwise. If an exception was encountered, the
2127 * contents of the region of virtual memory from ADDR to ADDR+LEN are undefined,
2128 * and CLIENT->exception() will have been called.
2129 */
2130 int
debug_store_region(uint32 addr,uint32 len,char * packet,DeviceExc * client)2131 CPU::debug_store_region(uint32 addr, uint32 len, char *packet,
2132 DeviceExc *client)
2133 {
2134 uint8 byte;
2135 uint32 real_addr;
2136 bool cacheable = false;
2137
2138 for (; len; addr++, len--) {
2139 byte = machine->dbgr->packet_pop_byte(&packet);
2140 real_addr = cpzero->address_trans(addr, DATALOAD, &cacheable, client);
2141 if (client->exception_pending) {
2142 return -1;
2143 }
2144 mem->store_byte(real_addr, byte, true, client);
2145 if (client->exception_pending) {
2146 return -1;
2147 }
2148 }
2149 return 0;
2150 }
2151