/[gxemul]/trunk/src/cpus/cpu_mips_instr.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/cpus/cpu_mips_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (show annotations)
Mon Oct 8 16:20:10 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 93974 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1264 2006/06/25 11:08:04 debug Exp $
20060624	Replacing the error-prone machine type initialization stuff
		with something more reasonable.
		Finally removing the old "cpu_run" kludge; moving around stuff
		in machine.c and emul.c to better suit the dyntrans system.
		Various minor dyntrans cleanups (renaming translate_address to
		translate_v2p, and experimenting with template physpages).
20060625	Removing the speed hack which separated the vph entries into
		two halves (code vs data); things seem a lot more stable now.
		Minor performance hack: R2000/R3000 cache isolation now only
		clears address translations when going into isolation, not
		when going out of it.
		Fixing the MIPS interrupt problems by letting mtc0 immediately
		cause interrupts.

==============  RELEASE 0.4.0.1  ==============


1 /*
2 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_mips_instr.c,v 1.87 2006/06/25 02:46:08 debug Exp $
29 *
30 * MIPS instructions.
31 *
32 * Individual functions should keep track of cpu->n_translated_instrs.
33 * (If no instruction was executed, then it should be decreased. If, say, 4
34 * instructions were combined into one function and executed, then it should
35 * be increased by 3.)
36 */
37
38
39 /*
40 * invalid: For catching bugs.
41 */
42 X(invalid)
43 {
44 fatal("FATAL ERROR: An internal error occured in the MIPS"
45 " dyntrans code. Please contact the author with detailed"
46 " repro steps on how to trigger this bug.\n");
47 exit(1);
48 }
49
50
51 /*
52 * reserved: Attempt to execute a reserved instruction (e.g. a 64-bit
53 * instruction on an emulated 32-bit processor).
54 */
55 X(reserved)
56 {
57 /* Synchronize the PC and cause an exception: */
58 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
59 / sizeof(struct mips_instr_call);
60 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
61 << MIPS_INSTR_ALIGNMENT_SHIFT);
62 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
63 mips_cpu_exception(cpu, EXCEPTION_RI, 0, 0, 0, 0, 0, 0);
64 }
65
66
67 /*
68 * cpu: Cause a CoProcessor Unusable exception.
69 *
70 * arg[0] = the number of the coprocessor
71 */
72 X(cpu)
73 {
74 /* Synchronize the PC and cause an exception: */
75 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
76 / sizeof(struct mips_instr_call);
77 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
78 << MIPS_INSTR_ALIGNMENT_SHIFT);
79 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
80 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, ic->arg[0], 0, 0, 0);
81 }
82
83
84 /*
85 * nop: Do nothing.
86 */
87 X(nop)
88 {
89 }
90
91
92 /*
93 * beq: Branch if equal
94 * bne: Branch if not equal
95 * b: Branch (comparing a register to itself, always true)
96 *
97 * arg[0] = pointer to rs
98 * arg[1] = pointer to rt
99 * arg[2] = (int32_t) relative offset from the next instruction
100 */
101 X(beq)
102 {
103 MODE_int_t old_pc = cpu->pc;
104 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
105 int x = rs == rt;
106 cpu->delay_slot = TO_BE_DELAYED;
107 ic[1].f(cpu, ic+1);
108 cpu->n_translated_instrs ++;
109 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
110 /* Note: Must be non-delayed when jumping to the new pc: */
111 cpu->delay_slot = NOT_DELAYED;
112 if (x) {
113 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
114 MIPS_INSTR_ALIGNMENT_SHIFT);
115 cpu->pc = old_pc + (int32_t)ic->arg[2];
116 quick_pc_to_pointers(cpu);
117 } else
118 cpu->cd.mips.next_ic ++;
119 } else
120 cpu->delay_slot = NOT_DELAYED;
121 }
122 X(beq_samepage)
123 {
124 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
125 int x = rs == rt;
126 cpu->delay_slot = TO_BE_DELAYED;
127 ic[1].f(cpu, ic+1);
128 cpu->n_translated_instrs ++;
129 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
130 if (x)
131 cpu->cd.mips.next_ic = (struct mips_instr_call *)
132 ic->arg[2];
133 else
134 cpu->cd.mips.next_ic ++;
135 }
136 cpu->delay_slot = NOT_DELAYED;
137 }
138 X(bne)
139 {
140 MODE_int_t old_pc = cpu->pc;
141 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
142 int x = rs != rt;
143 cpu->delay_slot = TO_BE_DELAYED;
144 ic[1].f(cpu, ic+1);
145 cpu->n_translated_instrs ++;
146 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
147 /* Note: Must be non-delayed when jumping to the new pc: */
148 cpu->delay_slot = NOT_DELAYED;
149 if (x) {
150 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
151 MIPS_INSTR_ALIGNMENT_SHIFT);
152 cpu->pc = old_pc + (int32_t)ic->arg[2];
153 quick_pc_to_pointers(cpu);
154 } else
155 cpu->cd.mips.next_ic ++;
156 } else
157 cpu->delay_slot = NOT_DELAYED;
158 }
159 X(bne_samepage)
160 {
161 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
162 int x = rs != rt;
163 cpu->delay_slot = TO_BE_DELAYED;
164 ic[1].f(cpu, ic+1);
165 cpu->n_translated_instrs ++;
166 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
167 if (x)
168 cpu->cd.mips.next_ic = (struct mips_instr_call *)
169 ic->arg[2];
170 else
171 cpu->cd.mips.next_ic ++;
172 }
173 cpu->delay_slot = NOT_DELAYED;
174 }
175 X(b)
176 {
177 MODE_int_t old_pc = cpu->pc;
178 cpu->delay_slot = TO_BE_DELAYED;
179 ic[1].f(cpu, ic+1);
180 cpu->n_translated_instrs ++;
181 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
182 /* Note: Must be non-delayed when jumping to the new pc: */
183 cpu->delay_slot = NOT_DELAYED;
184 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
185 MIPS_INSTR_ALIGNMENT_SHIFT);
186 cpu->pc = old_pc + (int32_t)ic->arg[2];
187 quick_pc_to_pointers(cpu);
188 } else
189 cpu->delay_slot = NOT_DELAYED;
190 }
191 X(b_samepage)
192 {
193 cpu->delay_slot = TO_BE_DELAYED;
194 ic[1].f(cpu, ic+1);
195 cpu->n_translated_instrs ++;
196 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT))
197 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
198 cpu->delay_slot = NOT_DELAYED;
199 }
200
201
202 /*
203 * beql: Branch if equal likely
204 * bnel: Branch if not equal likely
205 *
206 * arg[0] = pointer to rs
207 * arg[1] = pointer to rt
208 * arg[2] = (int32_t) relative offset from the next instruction
209 */
210 X(beql)
211 {
212 MODE_int_t old_pc = cpu->pc;
213 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
214 int x = rs == rt;
215 cpu->delay_slot = TO_BE_DELAYED;
216 if (x)
217 ic[1].f(cpu, ic+1);
218 cpu->n_translated_instrs ++;
219 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
220 /* Note: Must be non-delayed when jumping to the new pc: */
221 cpu->delay_slot = NOT_DELAYED;
222 if (x) {
223 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
224 MIPS_INSTR_ALIGNMENT_SHIFT);
225 cpu->pc = old_pc + (int32_t)ic->arg[2];
226 quick_pc_to_pointers(cpu);
227 } else
228 cpu->cd.mips.next_ic ++;
229 } else
230 cpu->delay_slot = NOT_DELAYED;
231 }
232 X(beql_samepage)
233 {
234 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
235 int x = rs == rt;
236 cpu->delay_slot = TO_BE_DELAYED;
237 if (x)
238 ic[1].f(cpu, ic+1);
239 cpu->n_translated_instrs ++;
240 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
241 if (x)
242 cpu->cd.mips.next_ic = (struct mips_instr_call *)
243 ic->arg[2];
244 else
245 cpu->cd.mips.next_ic ++;
246 }
247 cpu->delay_slot = NOT_DELAYED;
248 }
249 X(bnel)
250 {
251 MODE_int_t old_pc = cpu->pc;
252 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
253 int x = rs != rt;
254 cpu->delay_slot = TO_BE_DELAYED;
255 if (x)
256 ic[1].f(cpu, ic+1);
257 cpu->n_translated_instrs ++;
258 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
259 /* Note: Must be non-delayed when jumping to the new pc: */
260 cpu->delay_slot = NOT_DELAYED;
261 if (x) {
262 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
263 MIPS_INSTR_ALIGNMENT_SHIFT);
264 cpu->pc = old_pc + (int32_t)ic->arg[2];
265 quick_pc_to_pointers(cpu);
266 } else
267 cpu->cd.mips.next_ic ++;
268 } else
269 cpu->delay_slot = NOT_DELAYED;
270 }
271 X(bnel_samepage)
272 {
273 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
274 int x = rs != rt;
275 cpu->delay_slot = TO_BE_DELAYED;
276 if (x)
277 ic[1].f(cpu, ic+1);
278 cpu->n_translated_instrs ++;
279 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
280 if (x)
281 cpu->cd.mips.next_ic = (struct mips_instr_call *)
282 ic->arg[2];
283 else
284 cpu->cd.mips.next_ic ++;
285 }
286 cpu->delay_slot = NOT_DELAYED;
287 }
288
289
290 /*
291 * blez: Branch if less than or equal
292 * blezl: Branch if less than or equal likely
293 *
294 * arg[0] = pointer to rs
295 * arg[2] = (int32_t) relative offset from the next instruction
296 */
297 X(blez)
298 {
299 MODE_int_t old_pc = cpu->pc;
300 MODE_int_t rs = reg(ic->arg[0]);
301 int x = (rs <= 0);
302 cpu->delay_slot = TO_BE_DELAYED;
303 ic[1].f(cpu, ic+1);
304 cpu->n_translated_instrs ++;
305 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
306 /* Note: Must be non-delayed when jumping to the new pc: */
307 cpu->delay_slot = NOT_DELAYED;
308 if (x) {
309 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
310 MIPS_INSTR_ALIGNMENT_SHIFT);
311 cpu->pc = old_pc + (int32_t)ic->arg[2];
312 quick_pc_to_pointers(cpu);
313 } else
314 cpu->cd.mips.next_ic ++;
315 } else
316 cpu->delay_slot = NOT_DELAYED;
317 }
318 X(blez_samepage)
319 {
320 MODE_int_t rs = reg(ic->arg[0]);
321 int x = (rs <= 0);
322 cpu->delay_slot = TO_BE_DELAYED;
323 ic[1].f(cpu, ic+1);
324 cpu->n_translated_instrs ++;
325 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
326 if (x)
327 cpu->cd.mips.next_ic = (struct mips_instr_call *)
328 ic->arg[2];
329 else
330 cpu->cd.mips.next_ic ++;
331 }
332 cpu->delay_slot = NOT_DELAYED;
333 }
334 X(blezl)
335 {
336 MODE_int_t old_pc = cpu->pc;
337 MODE_int_t rs = reg(ic->arg[0]);
338 int x = (rs <= 0);
339 cpu->delay_slot = TO_BE_DELAYED;
340 if (x)
341 ic[1].f(cpu, ic+1);
342 cpu->n_translated_instrs ++;
343 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
344 /* Note: Must be non-delayed when jumping to the new pc: */
345 cpu->delay_slot = NOT_DELAYED;
346 if (x) {
347 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
348 MIPS_INSTR_ALIGNMENT_SHIFT);
349 cpu->pc = old_pc + (int32_t)ic->arg[2];
350 quick_pc_to_pointers(cpu);
351 } else
352 cpu->cd.mips.next_ic ++;
353 } else
354 cpu->delay_slot = NOT_DELAYED;
355 }
356 X(blezl_samepage)
357 {
358 MODE_int_t rs = reg(ic->arg[0]);
359 int x = (rs <= 0);
360 cpu->delay_slot = TO_BE_DELAYED;
361 if (x)
362 ic[1].f(cpu, ic+1);
363 cpu->n_translated_instrs ++;
364 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
365 if (x)
366 cpu->cd.mips.next_ic = (struct mips_instr_call *)
367 ic->arg[2];
368 else
369 cpu->cd.mips.next_ic ++;
370 }
371 cpu->delay_slot = NOT_DELAYED;
372 }
373
374
375 /*
376 * bltz: Branch if less than
377 * bltzl: Branch if less than likely
378 *
379 * arg[0] = pointer to rs
380 * arg[2] = (int32_t) relative offset from the next instruction
381 */
382 X(bltz)
383 {
384 MODE_int_t old_pc = cpu->pc;
385 MODE_int_t rs = reg(ic->arg[0]);
386 int x = (rs < 0);
387 cpu->delay_slot = TO_BE_DELAYED;
388 ic[1].f(cpu, ic+1);
389 cpu->n_translated_instrs ++;
390 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
391 /* Note: Must be non-delayed when jumping to the new pc: */
392 cpu->delay_slot = NOT_DELAYED;
393 if (x) {
394 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
395 MIPS_INSTR_ALIGNMENT_SHIFT);
396 cpu->pc = old_pc + (int32_t)ic->arg[2];
397 quick_pc_to_pointers(cpu);
398 } else
399 cpu->cd.mips.next_ic ++;
400 } else
401 cpu->delay_slot = NOT_DELAYED;
402 }
403 X(bltz_samepage)
404 {
405 MODE_int_t rs = reg(ic->arg[0]);
406 int x = (rs < 0);
407 cpu->delay_slot = TO_BE_DELAYED;
408 ic[1].f(cpu, ic+1);
409 cpu->n_translated_instrs ++;
410 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
411 if (x)
412 cpu->cd.mips.next_ic = (struct mips_instr_call *)
413 ic->arg[2];
414 else
415 cpu->cd.mips.next_ic ++;
416 }
417 cpu->delay_slot = NOT_DELAYED;
418 }
419 X(bltzl)
420 {
421 MODE_int_t old_pc = cpu->pc;
422 MODE_int_t rs = reg(ic->arg[0]);
423 int x = (rs < 0);
424 cpu->delay_slot = TO_BE_DELAYED;
425 if (x)
426 ic[1].f(cpu, ic+1);
427 cpu->n_translated_instrs ++;
428 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
429 /* Note: Must be non-delayed when jumping to the new pc: */
430 cpu->delay_slot = NOT_DELAYED;
431 if (x) {
432 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
433 MIPS_INSTR_ALIGNMENT_SHIFT);
434 cpu->pc = old_pc + (int32_t)ic->arg[2];
435 quick_pc_to_pointers(cpu);
436 } else
437 cpu->cd.mips.next_ic ++;
438 } else
439 cpu->delay_slot = NOT_DELAYED;
440 }
441 X(bltzl_samepage)
442 {
443 MODE_int_t rs = reg(ic->arg[0]);
444 int x = (rs < 0);
445 cpu->delay_slot = TO_BE_DELAYED;
446 if (x)
447 ic[1].f(cpu, ic+1);
448 cpu->n_translated_instrs ++;
449 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
450 if (x)
451 cpu->cd.mips.next_ic = (struct mips_instr_call *)
452 ic->arg[2];
453 else
454 cpu->cd.mips.next_ic ++;
455 }
456 cpu->delay_slot = NOT_DELAYED;
457 }
458
459
460 /*
461 * bgez: Branch if greater than or equal
462 * bgezl: Branch if greater than or equal likely
463 *
464 * arg[0] = pointer to rs
465 * arg[2] = (int32_t) relative offset from the next instruction
466 */
467 X(bgez)
468 {
469 MODE_int_t old_pc = cpu->pc;
470 MODE_int_t rs = reg(ic->arg[0]);
471 int x = (rs >= 0);
472 cpu->delay_slot = TO_BE_DELAYED;
473 ic[1].f(cpu, ic+1);
474 cpu->n_translated_instrs ++;
475 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
476 /* Note: Must be non-delayed when jumping to the new pc: */
477 cpu->delay_slot = NOT_DELAYED;
478 if (x) {
479 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
480 MIPS_INSTR_ALIGNMENT_SHIFT);
481 cpu->pc = old_pc + (int32_t)ic->arg[2];
482 quick_pc_to_pointers(cpu);
483 } else
484 cpu->cd.mips.next_ic ++;
485 } else
486 cpu->delay_slot = NOT_DELAYED;
487 }
488 X(bgez_samepage)
489 {
490 MODE_int_t rs = reg(ic->arg[0]);
491 int x = (rs >= 0);
492 cpu->delay_slot = TO_BE_DELAYED;
493 ic[1].f(cpu, ic+1);
494 cpu->n_translated_instrs ++;
495 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
496 if (x)
497 cpu->cd.mips.next_ic = (struct mips_instr_call *)
498 ic->arg[2];
499 else
500 cpu->cd.mips.next_ic ++;
501 }
502 cpu->delay_slot = NOT_DELAYED;
503 }
504 X(bgezl)
505 {
506 MODE_int_t old_pc = cpu->pc;
507 MODE_int_t rs = reg(ic->arg[0]);
508 int x = (rs >= 0);
509 cpu->delay_slot = TO_BE_DELAYED;
510 if (x)
511 ic[1].f(cpu, ic+1);
512 cpu->n_translated_instrs ++;
513 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
514 /* Note: Must be non-delayed when jumping to the new pc: */
515 cpu->delay_slot = NOT_DELAYED;
516 if (x) {
517 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
518 MIPS_INSTR_ALIGNMENT_SHIFT);
519 cpu->pc = old_pc + (int32_t)ic->arg[2];
520 quick_pc_to_pointers(cpu);
521 } else
522 cpu->cd.mips.next_ic ++;
523 } else
524 cpu->delay_slot = NOT_DELAYED;
525 }
526 X(bgezl_samepage)
527 {
528 MODE_int_t rs = reg(ic->arg[0]);
529 int x = (rs >= 0);
530 cpu->delay_slot = TO_BE_DELAYED;
531 if (x)
532 ic[1].f(cpu, ic+1);
533 cpu->n_translated_instrs ++;
534 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
535 if (x)
536 cpu->cd.mips.next_ic = (struct mips_instr_call *)
537 ic->arg[2];
538 else
539 cpu->cd.mips.next_ic ++;
540 }
541 cpu->delay_slot = NOT_DELAYED;
542 }
543
544
545 /*
546 * bgezal: Branch if greater than or equal (and link)
547 * bgezall: Branch if greater than or equal (and link) likely
548 *
549 * arg[0] = pointer to rs
550 * arg[2] = (int32_t) relative offset from the next instruction
551 */
552 X(bgezal)
553 {
554 MODE_int_t old_pc = cpu->pc;
555 MODE_int_t rs = reg(ic->arg[0]);
556 int x = (rs >= 0), low_pc;
557
558 cpu->delay_slot = TO_BE_DELAYED;
559 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
560 / sizeof(struct mips_instr_call);
561 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
562 << MIPS_INSTR_ALIGNMENT_SHIFT);
563 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
564 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
565
566 ic[1].f(cpu, ic+1);
567 cpu->n_translated_instrs ++;
568 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
569 /* Note: Must be non-delayed when jumping to the new pc: */
570 cpu->delay_slot = NOT_DELAYED;
571 if (x) {
572 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
573 MIPS_INSTR_ALIGNMENT_SHIFT);
574 cpu->pc = old_pc + (int32_t)ic->arg[2];
575 quick_pc_to_pointers(cpu);
576 } else
577 cpu->cd.mips.next_ic ++;
578 } else
579 cpu->delay_slot = NOT_DELAYED;
580 }
581 X(bgezal_samepage)
582 {
583 MODE_int_t rs = reg(ic->arg[0]);
584 int x = (rs >= 0), low_pc;
585
586 cpu->delay_slot = TO_BE_DELAYED;
587 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
588 / sizeof(struct mips_instr_call);
589 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
590 << MIPS_INSTR_ALIGNMENT_SHIFT);
591 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
592 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
593
594 ic[1].f(cpu, ic+1);
595 cpu->n_translated_instrs ++;
596 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
597 if (x)
598 cpu->cd.mips.next_ic = (struct mips_instr_call *)
599 ic->arg[2];
600 else
601 cpu->cd.mips.next_ic ++;
602 }
603 cpu->delay_slot = NOT_DELAYED;
604 }
605 X(bgezall)
606 {
607 MODE_int_t old_pc = cpu->pc;
608 MODE_int_t rs = reg(ic->arg[0]);
609 int x = (rs >= 0), low_pc;
610
611 cpu->delay_slot = TO_BE_DELAYED;
612 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
613 / sizeof(struct mips_instr_call);
614 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
615 << MIPS_INSTR_ALIGNMENT_SHIFT);
616 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
617 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
618
619 if (x)
620 ic[1].f(cpu, ic+1);
621 cpu->n_translated_instrs ++;
622 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
623 /* Note: Must be non-delayed when jumping to the new pc: */
624 cpu->delay_slot = NOT_DELAYED;
625 if (x) {
626 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
627 MIPS_INSTR_ALIGNMENT_SHIFT);
628 cpu->pc = old_pc + (int32_t)ic->arg[2];
629 quick_pc_to_pointers(cpu);
630 } else
631 cpu->cd.mips.next_ic ++;
632 } else
633 cpu->delay_slot = NOT_DELAYED;
634 }
635 X(bgezall_samepage)
636 {
637 MODE_int_t rs = reg(ic->arg[0]);
638 int x = (rs >= 0), low_pc;
639
640 cpu->delay_slot = TO_BE_DELAYED;
641 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
642 / sizeof(struct mips_instr_call);
643 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
644 << MIPS_INSTR_ALIGNMENT_SHIFT);
645 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
646 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
647
648 if (x)
649 ic[1].f(cpu, ic+1);
650 cpu->n_translated_instrs ++;
651 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
652 if (x)
653 cpu->cd.mips.next_ic = (struct mips_instr_call *)
654 ic->arg[2];
655 else
656 cpu->cd.mips.next_ic ++;
657 }
658 cpu->delay_slot = NOT_DELAYED;
659 }
660
661
662 /*
663 * bltzal: Branch if less than zero (and link)
664 * bltzall: Branch if less than zero (and link) likely
665 *
666 * arg[0] = pointer to rs
667 * arg[2] = (int32_t) relative offset from the next instruction
668 */
669 X(bltzal)
670 {
671 MODE_int_t old_pc = cpu->pc;
672 MODE_int_t rs = reg(ic->arg[0]);
673 int x = (rs < 0), low_pc;
674
675 cpu->delay_slot = TO_BE_DELAYED;
676 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
677 / sizeof(struct mips_instr_call);
678 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
679 << MIPS_INSTR_ALIGNMENT_SHIFT);
680 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
681 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
682
683 ic[1].f(cpu, ic+1);
684 cpu->n_translated_instrs ++;
685 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
686 /* Note: Must be non-delayed when jumping to the new pc: */
687 cpu->delay_slot = NOT_DELAYED;
688 if (x) {
689 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
690 MIPS_INSTR_ALIGNMENT_SHIFT);
691 cpu->pc = old_pc + (int32_t)ic->arg[2];
692 quick_pc_to_pointers(cpu);
693 } else
694 cpu->cd.mips.next_ic ++;
695 } else
696 cpu->delay_slot = NOT_DELAYED;
697 }
698 X(bltzal_samepage)
699 {
700 MODE_int_t rs = reg(ic->arg[0]);
701 int x = (rs < 0), low_pc;
702
703 cpu->delay_slot = TO_BE_DELAYED;
704 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
705 / sizeof(struct mips_instr_call);
706 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
707 << MIPS_INSTR_ALIGNMENT_SHIFT);
708 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
709 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
710
711 ic[1].f(cpu, ic+1);
712 cpu->n_translated_instrs ++;
713 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
714 if (x)
715 cpu->cd.mips.next_ic = (struct mips_instr_call *)
716 ic->arg[2];
717 else
718 cpu->cd.mips.next_ic ++;
719 }
720 cpu->delay_slot = NOT_DELAYED;
721 }
722 X(bltzall)
723 {
724 MODE_int_t old_pc = cpu->pc;
725 MODE_int_t rs = reg(ic->arg[0]);
726 int x = (rs < 0), low_pc;
727
728 cpu->delay_slot = TO_BE_DELAYED;
729 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
730 / sizeof(struct mips_instr_call);
731 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
732 << MIPS_INSTR_ALIGNMENT_SHIFT);
733 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
734 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
735
736 if (x)
737 ic[1].f(cpu, ic+1);
738 cpu->n_translated_instrs ++;
739 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
740 /* Note: Must be non-delayed when jumping to the new pc: */
741 cpu->delay_slot = NOT_DELAYED;
742 if (x) {
743 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
744 MIPS_INSTR_ALIGNMENT_SHIFT);
745 cpu->pc = old_pc + (int32_t)ic->arg[2];
746 quick_pc_to_pointers(cpu);
747 } else
748 cpu->cd.mips.next_ic ++;
749 } else
750 cpu->delay_slot = NOT_DELAYED;
751 }
752 X(bltzall_samepage)
753 {
754 MODE_int_t rs = reg(ic->arg[0]);
755 int x = (rs < 0), low_pc;
756
757 cpu->delay_slot = TO_BE_DELAYED;
758 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
759 / sizeof(struct mips_instr_call);
760 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
761 << MIPS_INSTR_ALIGNMENT_SHIFT);
762 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
763 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
764
765 if (x)
766 ic[1].f(cpu, ic+1);
767 cpu->n_translated_instrs ++;
768 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
769 if (x)
770 cpu->cd.mips.next_ic = (struct mips_instr_call *)
771 ic->arg[2];
772 else
773 cpu->cd.mips.next_ic ++;
774 }
775 cpu->delay_slot = NOT_DELAYED;
776 }
777
778
779 /*
780 * bgtz: Branch if greater than zero
781 * bgtzl: Branch if greater than zero likely
782 *
783 * arg[0] = pointer to rs
784 * arg[2] = (int32_t) relative offset from the next instruction
785 */
786 X(bgtz)
787 {
788 MODE_int_t old_pc = cpu->pc;
789 MODE_int_t rs = reg(ic->arg[0]);
790 int x = (rs > 0);
791 cpu->delay_slot = TO_BE_DELAYED;
792 ic[1].f(cpu, ic+1);
793 cpu->n_translated_instrs ++;
794 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
795 /* Note: Must be non-delayed when jumping to the new pc: */
796 cpu->delay_slot = NOT_DELAYED;
797 if (x) {
798 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
799 MIPS_INSTR_ALIGNMENT_SHIFT);
800 cpu->pc = old_pc + (int32_t)ic->arg[2];
801 quick_pc_to_pointers(cpu);
802 } else
803 cpu->cd.mips.next_ic ++;
804 } else
805 cpu->delay_slot = NOT_DELAYED;
806 }
807 X(bgtz_samepage)
808 {
809 MODE_int_t rs = reg(ic->arg[0]);
810 int x = (rs > 0);
811 cpu->delay_slot = TO_BE_DELAYED;
812 ic[1].f(cpu, ic+1);
813 cpu->n_translated_instrs ++;
814 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
815 if (x)
816 cpu->cd.mips.next_ic = (struct mips_instr_call *)
817 ic->arg[2];
818 else
819 cpu->cd.mips.next_ic ++;
820 }
821 cpu->delay_slot = NOT_DELAYED;
822 }
823 X(bgtzl)
824 {
825 MODE_int_t old_pc = cpu->pc;
826 MODE_int_t rs = reg(ic->arg[0]);
827 int x = (rs > 0);
828 cpu->delay_slot = TO_BE_DELAYED;
829 if (x)
830 ic[1].f(cpu, ic+1);
831 cpu->n_translated_instrs ++;
832 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
833 /* Note: Must be non-delayed when jumping to the new pc: */
834 cpu->delay_slot = NOT_DELAYED;
835 if (x) {
836 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
837 MIPS_INSTR_ALIGNMENT_SHIFT);
838 cpu->pc = old_pc + (int32_t)ic->arg[2];
839 quick_pc_to_pointers(cpu);
840 } else
841 cpu->cd.mips.next_ic ++;
842 } else
843 cpu->delay_slot = NOT_DELAYED;
844 }
845 X(bgtzl_samepage)
846 {
847 MODE_int_t rs = reg(ic->arg[0]);
848 int x = (rs > 0);
849 cpu->delay_slot = TO_BE_DELAYED;
850 if (x)
851 ic[1].f(cpu, ic+1);
852 cpu->n_translated_instrs ++;
853 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
854 if (x)
855 cpu->cd.mips.next_ic = (struct mips_instr_call *)
856 ic->arg[2];
857 else
858 cpu->cd.mips.next_ic ++;
859 }
860 cpu->delay_slot = NOT_DELAYED;
861 }
862
863
864 /*
865 * jr, jalr: Jump to a register [and link].
866 *
867 * arg[0] = ptr to rs
868 * arg[1] = ptr to rd (for jalr)
869 * arg[2] = (int32_t) relative offset of the next instruction
870 */
871 X(jr)
872 {
873 MODE_int_t rs = reg(ic->arg[0]);
874 cpu->delay_slot = TO_BE_DELAYED;
875 ic[1].f(cpu, ic+1);
876 cpu->n_translated_instrs ++;
877 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
878 cpu->pc = rs;
879 /* Note: Must be non-delayed when jumping to the new pc: */
880 cpu->delay_slot = NOT_DELAYED;
881 quick_pc_to_pointers(cpu);
882 } else
883 cpu->delay_slot = NOT_DELAYED;
884 }
885 X(jr_ra)
886 {
887 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
888 cpu->delay_slot = TO_BE_DELAYED;
889 ic[1].f(cpu, ic+1);
890 cpu->n_translated_instrs ++;
891 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
892 cpu->pc = rs;
893 /* Note: Must be non-delayed when jumping to the new pc: */
894 cpu->delay_slot = NOT_DELAYED;
895 quick_pc_to_pointers(cpu);
896 } else
897 cpu->delay_slot = NOT_DELAYED;
898 }
899 X(jr_ra_trace)
900 {
901 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
902 cpu->delay_slot = TO_BE_DELAYED;
903 ic[1].f(cpu, ic+1);
904 cpu->n_translated_instrs ++;
905 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
906 cpu->pc = rs;
907 cpu_functioncall_trace_return(cpu);
908 /* Note: Must be non-delayed when jumping to the new pc: */
909 cpu->delay_slot = NOT_DELAYED;
910 quick_pc_to_pointers(cpu);
911 } else
912 cpu->delay_slot = NOT_DELAYED;
913 }
914 X(jalr)
915 {
916 MODE_int_t rs = reg(ic->arg[0]), rd;
917 cpu->delay_slot = TO_BE_DELAYED;
918 rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
919 MIPS_INSTR_ALIGNMENT_SHIFT);
920 rd += (int32_t)ic->arg[2];
921 reg(ic->arg[1]) = rd;
922 ic[1].f(cpu, ic+1);
923 cpu->n_translated_instrs ++;
924 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
925 cpu->pc = rs;
926 /* Note: Must be non-delayed when jumping to the new pc: */
927 cpu->delay_slot = NOT_DELAYED;
928 quick_pc_to_pointers(cpu);
929 } else
930 cpu->delay_slot = NOT_DELAYED;
931 }
932 X(jalr_trace)
933 {
934 MODE_int_t rs = reg(ic->arg[0]), rd;
935 cpu->delay_slot = TO_BE_DELAYED;
936 rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
937 MIPS_INSTR_ALIGNMENT_SHIFT);
938 rd += (int32_t)ic->arg[2];
939 reg(ic->arg[1]) = rd;
940 ic[1].f(cpu, ic+1);
941 cpu->n_translated_instrs ++;
942 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
943 cpu->pc = rs;
944 cpu_functioncall_trace(cpu, cpu->pc);
945 /* Note: Must be non-delayed when jumping to the new pc: */
946 cpu->delay_slot = NOT_DELAYED;
947 quick_pc_to_pointers(cpu);
948 } else
949 cpu->delay_slot = NOT_DELAYED;
950 }
951
952
953 /*
954 * j, jal: Jump [and link].
955 *
956 * arg[0] = lowest 28 bits of new pc.
957 * arg[1] = offset from start of page to the jal instruction + 8
958 */
959 X(j)
960 {
961 MODE_int_t old_pc = cpu->pc;
962 cpu->delay_slot = TO_BE_DELAYED;
963 ic[1].f(cpu, ic+1);
964 cpu->n_translated_instrs ++;
965 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
966 /* Note: Must be non-delayed when jumping to the new pc: */
967 cpu->delay_slot = NOT_DELAYED;
968 old_pc &= ~0x03ffffff;
969 cpu->pc = old_pc | (uint32_t)ic->arg[0];
970 quick_pc_to_pointers(cpu);
971 } else
972 cpu->delay_slot = NOT_DELAYED;
973 }
974 X(jal)
975 {
976 MODE_int_t old_pc = cpu->pc;
977 cpu->delay_slot = TO_BE_DELAYED;
978 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
979 cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
980 ic[1].f(cpu, ic+1);
981 cpu->n_translated_instrs ++;
982 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
983 /* Note: Must be non-delayed when jumping to the new pc: */
984 cpu->delay_slot = NOT_DELAYED;
985 old_pc &= ~0x03ffffff;
986 cpu->pc = old_pc | (int32_t)ic->arg[0];
987 quick_pc_to_pointers(cpu);
988 } else
989 cpu->delay_slot = NOT_DELAYED;
990 }
991 X(jal_trace)
992 {
993 MODE_int_t old_pc = cpu->pc;
994 cpu->delay_slot = TO_BE_DELAYED;
995 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
996 cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
997 ic[1].f(cpu, ic+1);
998 cpu->n_translated_instrs ++;
999 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1000 /* Note: Must be non-delayed when jumping to the new pc: */
1001 cpu->delay_slot = NOT_DELAYED;
1002 old_pc &= ~0x03ffffff;
1003 cpu->pc = old_pc | (int32_t)ic->arg[0];
1004 cpu_functioncall_trace(cpu, cpu->pc);
1005 quick_pc_to_pointers(cpu);
1006 } else
1007 cpu->delay_slot = NOT_DELAYED;
1008 }
1009
1010
1011 /*
1012 * cache: Cache operation.
1013 */
1014 X(cache)
1015 {
1016 /* TODO. For now, just clear the rmw bit: */
1017 cpu->cd.mips.rmw = 0;
1018
1019 /* TODO: fix */
1020 cpu->invalidate_code_translation(cpu, 0, INVALIDATE_ALL);
1021 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
1022 /* cpu_create_or_reset_tc(cpu); */
1023 }
1024
1025
1026 /*
1027 * 2-register + immediate:
1028 *
1029 * arg[0] = pointer to rs
1030 * arg[1] = pointer to rt
1031 * arg[2] = uint32_t immediate value
1032 */
1033 X(andi) { reg(ic->arg[1]) = reg(ic->arg[0]) & (uint32_t)ic->arg[2]; }
1034 X(ori) { reg(ic->arg[1]) = reg(ic->arg[0]) | (uint32_t)ic->arg[2]; }
1035 X(xori) { reg(ic->arg[1]) = reg(ic->arg[0]) ^ (uint32_t)ic->arg[2]; }
1036
1037
1038 /*
1039 * 2-register:
1040 *
1041 * arg[0] = ptr to rs
1042 * arg[1] = ptr to rt
1043 */
1044 X(div)
1045 {
1046 int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1047 int32_t res, rem;
1048 if (b == 0)
1049 res = 0, rem = a;
1050 else
1051 res = a / b, rem = a - b*res;
1052 reg(&cpu->cd.mips.lo) = (int32_t)res;
1053 reg(&cpu->cd.mips.hi) = (int32_t)rem;
1054 }
1055 X(divu)
1056 {
1057 uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1058 uint32_t res, rem;
1059 if (b == 0)
1060 res = 0, rem = a;
1061 else
1062 res = a / b, rem = a - b*res;
1063 reg(&cpu->cd.mips.lo) = (int32_t)res;
1064 reg(&cpu->cd.mips.hi) = (int32_t)rem;
1065 }
1066 X(ddiv)
1067 {
1068 int64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1069 int64_t res, rem;
1070 if (b == 0)
1071 res = 0;
1072 else
1073 res = a / b;
1074 rem = a - b*res;
1075 reg(&cpu->cd.mips.lo) = res;
1076 reg(&cpu->cd.mips.hi) = rem;
1077 }
1078 X(ddivu)
1079 {
1080 uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1081 uint64_t res, rem;
1082 if (b == 0)
1083 res = 0;
1084 else
1085 res = a / b;
1086 rem = a - b*res;
1087 reg(&cpu->cd.mips.lo) = res;
1088 reg(&cpu->cd.mips.hi) = rem;
1089 }
1090 X(mult)
1091 {
1092 int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1093 int64_t res = (int64_t)a * (int64_t)b;
1094 reg(&cpu->cd.mips.lo) = (int32_t)res;
1095 reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1096 }
1097 X(mult_r5900)
1098 {
1099 /* C790/TX79/R5900 multiplication, stores result in
1100 hi, lo, and a third register */
1101 int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1102 int64_t res = (int64_t)a * (int64_t)b;
1103 reg(&cpu->cd.mips.lo) = (int32_t)res;
1104 reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1105 reg(ic->arg[2]) = (int32_t)res;
1106 }
1107 X(multu)
1108 {
1109 uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1110 uint64_t res = (uint64_t)a * (uint64_t)b;
1111 reg(&cpu->cd.mips.lo) = (int32_t)res;
1112 reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1113 }
1114 X(multu_r5900)
1115 {
1116 /* C790/TX79/R5900 multiplication, stores result in
1117 hi, lo, and a third register */
1118 uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1119 uint64_t res = (uint64_t)a * (uint64_t)b;
1120 reg(&cpu->cd.mips.lo) = (int32_t)res;
1121 reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1122 reg(ic->arg[2]) = (int32_t)res;
1123 }
1124 X(dmult)
1125 {
1126 uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1127 uint64_t hi = 0, lo = 0;
1128 int neg = 0;
1129 if (a >> 63)
1130 neg = !neg, a = -a;
1131 if (b >> 63)
1132 neg = !neg, b = -b;
1133 for (; a; a >>= 1) {
1134 if (a & 1) {
1135 uint64_t old_lo = lo;
1136 hi += c;
1137 lo += b;
1138 if (lo < old_lo)
1139 hi ++;
1140 }
1141 c = (c << 1) | (b >> 63); b <<= 1;
1142 }
1143 if (neg) {
1144 if (lo == 0)
1145 hi --;
1146 lo --;
1147 hi ^= (int64_t) -1;
1148 lo ^= (int64_t) -1;
1149 }
1150 reg(&cpu->cd.mips.lo) = lo;
1151 reg(&cpu->cd.mips.hi) = hi;
1152 }
1153 X(dmultu)
1154 {
1155 uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1156 uint64_t hi = 0, lo = 0;
1157 for (; a; a >>= 1) {
1158 if (a & 1) {
1159 uint64_t old_lo = lo;
1160 hi += c;
1161 lo += b;
1162 if (lo < old_lo)
1163 hi ++;
1164 }
1165 c = (c << 1) | (b >> 63); b <<= 1;
1166 }
1167 reg(&cpu->cd.mips.lo) = lo;
1168 reg(&cpu->cd.mips.hi) = hi;
1169 }
1170 X(tge)
1171 {
1172 MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1173 if (a >= b) {
1174 /* Synch. PC and cause an exception: */
1175 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1176 / sizeof(struct mips_instr_call);
1177 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1178 << MIPS_INSTR_ALIGNMENT_SHIFT);
1179 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1180 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1181 }
1182 }
1183 X(tgeu)
1184 {
1185 MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1186 if (a >= b) {
1187 /* Synch. PC and cause an exception: */
1188 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1189 / sizeof(struct mips_instr_call);
1190 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1191 << MIPS_INSTR_ALIGNMENT_SHIFT);
1192 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1193 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1194 }
1195 }
1196 X(tlt)
1197 {
1198 MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1199 if (a < b) {
1200 /* Synch. PC and cause an exception: */
1201 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1202 / sizeof(struct mips_instr_call);
1203 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1204 << MIPS_INSTR_ALIGNMENT_SHIFT);
1205 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1206 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1207 }
1208 }
1209 X(tltu)
1210 {
1211 MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1212 if (a < b) {
1213 /* Synch. PC and cause an exception: */
1214 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1215 / sizeof(struct mips_instr_call);
1216 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1217 << MIPS_INSTR_ALIGNMENT_SHIFT);
1218 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1219 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1220 }
1221 }
1222 X(teq)
1223 {
1224 MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1225 if (a == b) {
1226 /* Synch. PC and cause an exception: */
1227 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1228 / sizeof(struct mips_instr_call);
1229 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1230 << MIPS_INSTR_ALIGNMENT_SHIFT);
1231 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1232 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1233 }
1234 }
1235 X(tne)
1236 {
1237 MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1238 if (a != b) {
1239 /* Synch. PC and cause an exception: */
1240 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1241 / sizeof(struct mips_instr_call);
1242 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1243 << MIPS_INSTR_ALIGNMENT_SHIFT);
1244 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1245 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1246 }
1247 }
1248
1249
1250 /*
1251 * 3-register arithmetic instructions:
1252 *
1253 * arg[0] = ptr to rs
1254 * arg[1] = ptr to rt
1255 * arg[2] = ptr to rd
1256 */
1257 X(addu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) + reg(ic->arg[1])); }
1258 X(add)
1259 {
1260 int32_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1261 int32_t rd = rs + rt;
1262
1263 if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1264 /* Synch. PC and cause an exception: */
1265 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1266 / sizeof(struct mips_instr_call);
1267 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1268 << MIPS_INSTR_ALIGNMENT_SHIFT);
1269 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1270 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1271 } else
1272 reg(ic->arg[2]) = rd;
1273 }
1274 X(daddu){ reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }
1275 X(dadd)
1276 {
1277 int64_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1278 int64_t rd = rs + rt;
1279
1280 if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1281 /* Synch. PC and cause an exception: */
1282 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1283 / sizeof(struct mips_instr_call);
1284 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1285 << MIPS_INSTR_ALIGNMENT_SHIFT);
1286 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1287 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1288 } else
1289 reg(ic->arg[2]) = rd;
1290 }
1291 X(subu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) - reg(ic->arg[1])); }
1292 X(sub)
1293 {
1294 /* NOTE: Negating rt and using addition. TODO: Is this correct? */
1295 int32_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1296 int32_t rd = rs + rt;
1297
1298 if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1299 /* Synch. PC and cause an exception: */
1300 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1301 / sizeof(struct mips_instr_call);
1302 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1303 << MIPS_INSTR_ALIGNMENT_SHIFT);
1304 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1305 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1306 } else
1307 reg(ic->arg[2]) = rd;
1308 }
1309 X(dsubu){ reg(ic->arg[2]) = reg(ic->arg[0]) - reg(ic->arg[1]); }
1310 X(dsub)
1311 {
1312 /* NOTE: Negating rt and using addition. TODO: Is this correct? */
1313 int64_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1314 int64_t rd = rs + rt;
1315
1316 if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1317 /* Synch. PC and cause an exception: */
1318 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1319 / sizeof(struct mips_instr_call);
1320 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1321 << MIPS_INSTR_ALIGNMENT_SHIFT);
1322 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1323 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1324 } else
1325 reg(ic->arg[2]) = rd;
1326 }
1327 X(slt) {
1328 reg(ic->arg[2]) =
1329 (MODE_int_t)reg(ic->arg[0]) < (MODE_int_t)reg(ic->arg[1]);
1330 }
1331 X(sltu) {
1332 reg(ic->arg[2]) =
1333 (MODE_uint_t)reg(ic->arg[0]) < (MODE_uint_t)reg(ic->arg[1]);
1334 }
1335 X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
1336 X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
1337 X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
1338 X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }
1339 X(sll) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << (int32_t)ic->arg[1]); }
1340 X(sllv){ int32_t sa = reg(ic->arg[1]) & 31;
1341 reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << sa); }
1342 X(srl) { reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1343 X(srlv){ int32_t sa = reg(ic->arg[1]) & 31;
1344 reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> sa); }
1345 X(sra) { reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1346 X(srav){ int32_t sa = reg(ic->arg[1]) & 31;
1347 reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> sa); }
1348 X(dsll) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) << (int64_t)ic->arg[1]; }
1349 X(dsllv){ int64_t sa = reg(ic->arg[1]) & 63;
1350 reg(ic->arg[2]) = reg(ic->arg[0]) << sa; }
1351 X(dsrl) { reg(ic->arg[2]) = (int64_t)((uint64_t)reg(ic->arg[0]) >>
1352 (uint64_t) ic->arg[1]);}
1353 X(dsrlv){ int64_t sa = reg(ic->arg[1]) & 63;
1354 reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) >> sa; }
1355 X(dsra) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> (int64_t)ic->arg[1]; }
1356 X(dsrav){ int64_t sa = reg(ic->arg[1]) & 63;
1357 reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> sa; }
1358 X(mul) { reg(ic->arg[2]) = (int32_t)
1359 ( (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]) ); }
1360 X(movn) { if (reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1361 X(movz) { if (!reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1362
1363
1364 /*
1365 * p*: 128-bit C790/TX79/R5900 stuff
1366 *
1367 * arg[0] = rs (note: not a pointer)
1368 * arg[1] = rt (note: not a pointer)
1369 * arg[2] = rd (note: not a pointer)
1370 */
1371 X(por)
1372 {
1373 cpu->cd.mips.gpr[ic->arg[2]] = cpu->cd.mips.gpr[ic->arg[0]] |
1374 cpu->cd.mips.gpr[ic->arg[1]];
1375 cpu->cd.mips.gpr_quadhi[ic->arg[2]] =
1376 cpu->cd.mips.gpr_quadhi[ic->arg[0]] |
1377 cpu->cd.mips.gpr_quadhi[ic->arg[1]];
1378 }
1379 X(pextlw)
1380 {
1381 uint64_t lo, hi;
1382
1383 lo = (uint32_t)cpu->cd.mips.gpr[ic->arg[1]] |
1384 (uint64_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[0]] << 32);
1385 hi = (cpu->cd.mips.gpr[ic->arg[0]] & 0xffffffff00000000ULL) |
1386 (uint32_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[1]] >> 32);
1387
1388 cpu->cd.mips.gpr[ic->arg[2]] = lo;
1389 cpu->cd.mips.gpr_quadhi[ic->arg[2]] = hi;
1390 }
1391
1392
1393 /*
1394 * madd, maddu, msub, msubu: Multiply-and-add/subtract
1395 *
1396 * arg[0] = ptr to rs
1397 * arg[1] = ptr to rt
1398 * arg[2] = ptr to rd (only used on R5900/TX79)
1399 */
1400 X(madd)
1401 {
1402 int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1403 int64_t sum = rs * rt,
1404 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1405 hilo += sum;
1406 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1407 }
1408 X(madd_rd)
1409 {
1410 int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1411 int64_t sum = rs * rt,
1412 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1413 hilo += sum;
1414 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1415 reg(ic->arg[2]) = (int32_t)hilo;
1416 }
1417 X(msub)
1418 {
1419 int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1420 int64_t sum = rs * rt,
1421 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1422 hilo -= sum;
1423 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1424 }
1425 X(maddu)
1426 {
1427 int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1428 int64_t sum = rs * rt,
1429 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1430 hilo += sum;
1431 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1432 }
1433 X(maddu_rd)
1434 {
1435 int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1436 int64_t sum = rs * rt,
1437 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1438 hilo += sum;
1439 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1440 reg(ic->arg[2]) = (int32_t)hilo;
1441 }
1442 X(msubu)
1443 {
1444 int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1445 int64_t sum = rs * rt,
1446 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1447 hilo -= sum;
1448 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1449 }
1450
1451
1452 /*
1453 * mov: Move one register into another.
1454 *
1455 * arg[0] = pointer to source
1456 * arg[2] = pointer to destination
1457 */
1458 X(mov) { reg(ic->arg[2]) = reg(ic->arg[0]); }
1459
1460
1461 /*
1462 * clz, clo, dclz, dclo: Count leading zeroes/ones.
1463 *
1464 * arg[0] = pointer to rs
1465 * arg[1] = pointer to rd
1466 */
1467 X(clz)
1468 {
1469 uint32_t x = reg(ic->arg[0]);
1470 int count;
1471 for (count=0; count<32; count++) {
1472 if (x & 0x80000000UL)
1473 break;
1474 x <<= 1;
1475 }
1476 reg(ic->arg[1]) = count;
1477 }
1478 X(clo)
1479 {
1480 uint32_t x = reg(ic->arg[0]);
1481 int count;
1482 for (count=0; count<32; count++) {
1483 if (!(x & 0x80000000UL))
1484 break;
1485 x <<= 1;
1486 }
1487 reg(ic->arg[1]) = count;
1488 }
1489 X(dclz)
1490 {
1491 uint64_t x = reg(ic->arg[0]);
1492 int count;
1493 for (count=0; count<64; count++) {
1494 if (x & 0x8000000000000000ULL)
1495 break;
1496 x <<= 1;
1497 }
1498 reg(ic->arg[1]) = count;
1499 }
1500 X(dclo)
1501 {
1502 uint64_t x = reg(ic->arg[0]);
1503 int count;
1504 for (count=0; count<64; count++) {
1505 if (!(x & 0x8000000000000000ULL))
1506 break;
1507 x <<= 1;
1508 }
1509 reg(ic->arg[1]) = count;
1510 }
1511
1512
1513 /*
1514 * addi, daddi: Add immediate, overflow detection.
1515 * addiu, daddiu: Add immediate.
1516 * slti: Set if less than immediate (signed 32-bit)
1517 * sltiu: Set if less than immediate (signed 32-bit, but unsigned compare)
1518 *
1519 * arg[0] = pointer to rs
1520 * arg[1] = pointer to rt
1521 * arg[2] = (int32_t) immediate value
1522 */
1523 X(addi)
1524 {
1525 int32_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1526 int32_t rt = rs + imm;
1527
1528 if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1529 /* Synch. PC and cause an exception: */
1530 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1531 / sizeof(struct mips_instr_call);
1532 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1533 << MIPS_INSTR_ALIGNMENT_SHIFT);
1534 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1535 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1536 } else
1537 reg(ic->arg[1]) = rt;
1538 }
1539 X(addiu)
1540 {
1541 reg(ic->arg[1]) = (int32_t)
1542 ((int32_t)reg(ic->arg[0]) + (int32_t)ic->arg[2]);
1543 }
1544 X(daddi)
1545 {
1546 int64_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1547 int64_t rt = rs + imm;
1548
1549 if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1550 /* Synch. PC and cause an exception: */
1551 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1552 / sizeof(struct mips_instr_call);
1553 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1554 << MIPS_INSTR_ALIGNMENT_SHIFT);
1555 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1556 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1557 } else
1558 reg(ic->arg[1]) = rt;
1559 }
1560 X(daddiu)
1561 {
1562 reg(ic->arg[1]) = reg(ic->arg[0]) + (int32_t)ic->arg[2];
1563 }
1564 X(slti)
1565 {
1566 reg(ic->arg[1]) = (MODE_int_t)reg(ic->arg[0]) < (int32_t)ic->arg[2];
1567 }
1568 X(sltiu)
1569 {
1570 reg(ic->arg[1]) = (MODE_uint_t)reg(ic->arg[0]) <
1571 ((MODE_uint_t)(int32_t)ic->arg[2]);
1572 }
1573
1574
1575 /*
1576 * set: Set a register to an immediate (signed) 32-bit value.
1577 *
1578 * arg[0] = pointer to the register
1579 * arg[1] = (int32_t) immediate value
1580 */
1581 X(set)
1582 {
1583 reg(ic->arg[0]) = (int32_t)ic->arg[1];
1584 }
1585
1586
1587 /*
1588 * cfc0: Copy from Coprocessor 0.
1589 * mfc0, dmfc0: Move from Coprocessor 0.
1590 * mtc0, dmtc0: Move to Coprocessor 0.
1591 *
1592 * arg[0] = pointer to GPR (rt)
1593 * arg[1] = coprocessor 0 register number | (select << 5) (or for the
1594 * cfc0 instruction, the coprocessor control register number)
1595 * arg[2] = relative addr of this instruction within the page
1596 */
1597 X(cfc0)
1598 {
1599 int fs = ic->arg[1] & 31;
1600 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1601 cpu->pc |= ic->arg[2];
1602 /* TODO: cause exception if necessary */
1603 reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->fcr[fs];
1604 }
1605 X(mfc0)
1606 {
1607 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1608 uint64_t tmp;
1609 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1610 cpu->pc |= ic->arg[2];
1611 /* TODO: cause exception if necessary */
1612 coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select);
1613 reg(ic->arg[0]) = (int32_t)tmp;
1614 }
1615 X(mtc0)
1616 {
1617 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1618 uint64_t tmp = (int32_t) reg(ic->arg[0]);
1619
1620 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1621 cpu->pc |= ic->arg[2];
1622
1623 /* TODO: cause exception if necessary */
1624 coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd, &tmp, 0, select);
1625
1626 /*
1627 * Interrupts enabled, and any interrupt pending? (Note/TODO: This
1628 * code is duplicated in cpu_dyntrans.c. Fix this?)
1629 */
1630 if (rd == COP0_STATUS && !cpu->delay_slot) {
1631 uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1632 uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1633 /* NOTE: STATUS_IE happens to match the enable bit also
1634 on R2000/R3000, so this is ok. */
1635 if (status & (STATUS_EXL | STATUS_ERL))
1636 status &= ~STATUS_IE;
1637 /* Ugly R5900 special case: (TODO: move this?) */
1638 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1639 !(status & R5900_STATUS_EIE))
1640 status &= ~STATUS_IE;
1641 if (status & STATUS_IE && (status & cause & STATUS_IM_MASK)) {
1642 cpu->pc += sizeof(uint32_t);
1643 mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0,0,0,0,0);
1644 }
1645 }
1646 }
1647 X(dmfc0)
1648 {
1649 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1650 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1651 cpu->pc |= ic->arg[2];
1652 /* TODO: cause exception if necessary */
1653 coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,
1654 (uint64_t *)ic->arg[0], select);
1655 }
1656 X(dmtc0)
1657 {
1658 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1659 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1660 cpu->pc |= ic->arg[2];
1661 /* TODO: cause exception if necessary */
1662 coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,
1663 (uint64_t *)ic->arg[0], 1, select);
1664 }
1665
1666
1667 /*
1668 * cop1_bc: Floating point conditional branch.
1669 *
1670 * arg[0] = cc
1671 * arg[1] = nd (=2) and tf (=1) bits
1672 * arg[2] = offset (relative to start of this page)
1673 */
1674 X(cop1_bc)
1675 {
1676 MODE_int_t old_pc = cpu->pc;
1677 const int cpnr = 1;
1678 int x, low_pc, cc = ic->arg[0];
1679
1680 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1681 / sizeof(struct mips_instr_call);
1682 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1683 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1684 if (!(cpu->cd.mips.coproc[0]->
1685 reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1686 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1687 return;
1688 }
1689
1690 /* Get the correct condition code bit: */
1691 if (cc == 0)
1692 x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1693 >> MIPS_FCSR_FCC0_SHIFT) & 1;
1694 else
1695 x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1696 >> (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;
1697
1698 /* Branch on false? Then invert the truth value. */
1699 if (!(ic->arg[1] & 1))
1700 x ^= 1;
1701
1702 /* Execute the delay slot (except if it is nullified): */
1703 cpu->delay_slot = TO_BE_DELAYED;
1704 if (x || !(ic->arg[1] & 2))
1705 ic[1].f(cpu, ic+1);
1706 cpu->n_translated_instrs ++;
1707
1708 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1709 /* Note: Must be non-delayed when jumping to the new pc: */
1710 cpu->delay_slot = NOT_DELAYED;
1711 if (x) {
1712 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1713 MIPS_INSTR_ALIGNMENT_SHIFT);
1714 cpu->pc = old_pc + (int32_t)ic->arg[2];
1715 quick_pc_to_pointers(cpu);
1716 } else
1717 cpu->cd.mips.next_ic ++;
1718 } else
1719 cpu->delay_slot = NOT_DELAYED;
1720 }
1721
1722
1723 /*
1724 * cop1_slow: Fallback to legacy cop1 code. (Slow, but it should work.)
1725 */
1726 X(cop1_slow)
1727 {
1728 const int cpnr = 1;
1729 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1730 / sizeof(struct mips_instr_call);
1731 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1732 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1733
1734 if (!(cpu->cd.mips.coproc[0]->
1735 reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1736 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1737 return;
1738 }
1739
1740 coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1741 }
1742
1743
1744 /*
1745 * syscall, break: Synchronize the PC and cause an exception.
1746 */
1747 X(syscall)
1748 {
1749 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1750 / sizeof(struct mips_instr_call);
1751 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1752 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1753 mips_cpu_exception(cpu, EXCEPTION_SYS, 0, 0, 0, 0, 0, 0);
1754 }
1755 X(break)
1756 {
1757 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1758 / sizeof(struct mips_instr_call);
1759 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1760 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1761 mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1762 }
1763
1764
1765 /*
1766 * promemul: PROM software emulation.
1767 */
1768 X(promemul)
1769 {
1770 /* Synchronize the PC and call the correct emulation layer: */
1771 MODE_int_t old_pc;
1772 int res, low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1773 / sizeof(struct mips_instr_call);
1774 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1775 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1776 old_pc = cpu->pc;
1777
1778 switch (cpu->machine->machine_type) {
1779 case MACHINE_PMAX:
1780 res = decstation_prom_emul(cpu);
1781 break;
1782 case MACHINE_PS2:
1783 res = playstation2_sifbios_emul(cpu);
1784 break;
1785 case MACHINE_ARC:
1786 case MACHINE_SGI:
1787 res = arcbios_emul(cpu);
1788 break;
1789 case MACHINE_EVBMIPS:
1790 res = yamon_emul(cpu);
1791 break;
1792 default:fatal("TODO: Unimplemented machine type for PROM magic trap\n");
1793 exit(1);
1794 }
1795
1796 if (res) {
1797 /* Return from the PROM call: */
1798 cpu->pc = (MODE_int_t)cpu->cd.mips.gpr[MIPS_GPR_RA];
1799 cpu->delay_slot = NOT_DELAYED;
1800
1801 if (cpu->machine->show_trace_tree)
1802 cpu_functioncall_trace_return(cpu);
1803 } else {
1804 /* The PROM call blocks. */
1805 cpu->n_translated_instrs += 10;
1806 cpu->pc = old_pc;
1807 }
1808
1809 quick_pc_to_pointers(cpu);
1810 }
1811
1812
1813 /*
1814 * tlbw: TLB write indexed and random
1815 *
1816 * arg[0] = 1 for random, 0 for indexed
1817 * arg[2] = relative addr of this instruction within the page
1818 */
1819 X(tlbw)
1820 {
1821 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1822 cpu->pc |= ic->arg[2];
1823 coproc_tlbwri(cpu, ic->arg[0]);
1824 }
1825
1826
1827 /*
1828 * tlbp: TLB probe
1829 * tlbr: TLB read
1830 *
1831 * arg[2] = relative addr of this instruction within the page
1832 */
1833 X(tlbp)
1834 {
1835 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1836 cpu->pc |= ic->arg[2];
1837 coproc_tlbpr(cpu, 0);
1838 }
1839 X(tlbr)
1840 {
1841 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1842 cpu->pc |= ic->arg[2];
1843 coproc_tlbpr(cpu, 1);
1844 }
1845
1846
1847 /*
1848 * rfe: Return from exception handler (R2000/R3000)
1849 */
1850 X(rfe)
1851 {
1852 coproc_rfe(cpu);
1853
1854 /* Note: no pc to pointers conversion is necessary here. */
1855 }
1856
1857
1858 /*
1859 * eret: Return from exception handler
1860 */
1861 X(eret)
1862 {
1863 coproc_eret(cpu);
1864 quick_pc_to_pointers(cpu);
1865 }
1866
1867
1868 /*
1869 * deret: Return from debug (EJTAG) handler
1870 */
1871 X(deret)
1872 {
1873 /*
1874 * According to the MIPS64 manual, deret loads PC from the DEPC cop0
1875 * register, and jumps there immediately. No delay slot.
1876 *
1877 * TODO: This instruction is only available if the processor is in
1878 * debug mode. (What does that mean?)
1879 *
1880 * TODO: This instruction is undefined in a delay slot.
1881 */
1882
1883 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_DEPC];
1884 cpu->delay_slot = 0;
1885 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1886 quick_pc_to_pointers(cpu);
1887 }
1888
1889
1890 /*
1891 * rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
1892 *
1893 * arg[0] = ptr to rt (destination register)
1894 */
1895 X(rdhwr_cpunum)
1896 {
1897 reg(ic->arg[0]) = cpu->cpu_id;
1898 }
1899
1900
1901 #include "tmp_mips_loadstore.c"
1902
1903
1904 /*
1905 * Load linked / store conditional:
1906 *
1907 * A Load-linked instruction initiates a RMW (read-modify-write) sequence.
1908 * COP0_LLADDR is updated for diagnostic purposes, except for CPUs in the
1909 * R10000 family.
1910 *
1911 * A Store-conditional instruction ends the sequence.
1912 *
1913 * arg[0] = ptr to rt
1914 * arg[1] = ptr to rs
1915 * arg[2] = int32_t imm
1916 */
1917 X(ll)
1918 {
1919 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1920 int low_pc;
1921 uint8_t word[sizeof(uint32_t)];
1922
1923 /* Synch. PC and load using slow memory_rw(): */
1924 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1925 / sizeof(struct mips_instr_call);
1926 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1927 << MIPS_INSTR_ALIGNMENT_SHIFT);
1928 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1929
1930 if (addr & (sizeof(word)-1)) {
1931 fatal("TODO: load linked unaligned access: exception\n");
1932 exit(1);
1933 }
1934
1935 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
1936 sizeof(word), MEM_READ, CACHE_DATA)) {
1937 /* An exception occurred. */
1938 return;
1939 }
1940
1941 cpu->cd.mips.rmw = 1;
1942 cpu->cd.mips.rmw_addr = addr;
1943 cpu->cd.mips.rmw_len = sizeof(word);
1944 if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
1945 cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
1946 (addr >> 4) & 0xffffffffULL;
1947
1948 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1949 reg(ic->arg[0]) = (int32_t) (word[0] + (word[1] << 8)
1950 + (word[2] << 16) + (word[3] << 24));
1951 else
1952 reg(ic->arg[0]) = (int32_t) (word[3] + (word[2] << 8)
1953 + (word[1] << 16) + (word[0] << 24));
1954 }
1955 X(lld)
1956 {
1957 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1958 int low_pc;
1959 uint8_t word[sizeof(uint64_t)];
1960
1961 /* Synch. PC and load using slow memory_rw(): */
1962 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1963 / sizeof(struct mips_instr_call);
1964 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1965 << MIPS_INSTR_ALIGNMENT_SHIFT);
1966 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1967
1968 if (addr & (sizeof(word)-1)) {
1969 fatal("TODO: load linked unaligned access: exception\n");
1970 exit(1);
1971 }
1972
1973 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
1974 sizeof(word), MEM_READ, CACHE_DATA)) {
1975 /* An exception occurred. */
1976 return;
1977 }
1978
1979 cpu->cd.mips.rmw = 1;
1980 cpu->cd.mips.rmw_addr = addr;
1981 cpu->cd.mips.rmw_len = sizeof(word);
1982 if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
1983 cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
1984 (addr >> 4) & 0xffffffffULL;
1985
1986 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1987 reg(ic->arg[0]) = word[0] + (word[1] << 8)
1988 + (word[2] << 16) + ((uint64_t)word[3] << 24) +
1989 + ((uint64_t)word[4] << 32) + ((uint64_t)word[5] << 40)
1990 + ((uint64_t)word[6] << 48) + ((uint64_t)word[7] << 56);
1991 else
1992 reg(ic->arg[0]) = word[7] + (word[6] << 8)
1993 + (word[5] << 16) + ((uint64_t)word[4] << 24) +
1994 + ((uint64_t)word[3] << 32) + ((uint64_t)word[2] << 40)
1995 + ((uint64_t)word[1] << 48) + ((uint64_t)word[0] << 56);
1996 }
1997 X(sc)
1998 {
1999 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2000 uint64_t r = reg(ic->arg[0]);
2001 int low_pc, i;
2002 uint8_t word[sizeof(uint32_t)];
2003
2004 /* Synch. PC and store using slow memory_rw(): */
2005 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2006 / sizeof(struct mips_instr_call);
2007 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2008 << MIPS_INSTR_ALIGNMENT_SHIFT);
2009 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2010
2011 if (addr & (sizeof(word)-1)) {
2012 fatal("TODO: sc unaligned access: exception\n");
2013 exit(1);
2014 }
2015
2016 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2017 word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2018 } else {
2019 word[3]=r; word[2]=r>>8; word[1]=r>>16; word[0]=r>>24;
2020 }
2021
2022 /* If rmw is 0, then the store failed. (This cache-line was written
2023 to by someone else.) */
2024 if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2025 || cpu->cd.mips.rmw_len != sizeof(word)) {
2026 reg(ic->arg[0]) = 0;
2027 cpu->cd.mips.rmw = 0;
2028 return;
2029 }
2030
2031 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2032 sizeof(word), MEM_WRITE, CACHE_DATA)) {
2033 /* An exception occurred. */
2034 return;
2035 }
2036
2037 /* We succeeded. Let's invalidate everybody else's store to this
2038 cache line: */
2039 for (i=0; i<cpu->machine->ncpus; i++) {
2040 if (cpu->machine->cpus[i]->cd.mips.rmw) {
2041 uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2042 cd.mips.rmw_addr;
2043 uint64_t mask = ~(cpu->machine->cpus[i]->
2044 cd.mips.cache_linesize[CACHE_DATA] - 1);
2045 xaddr &= mask;
2046 yaddr &= mask;
2047 if (xaddr == yaddr)
2048 cpu->machine->cpus[i]->cd.mips.rmw = 0;
2049 }
2050 }
2051
2052 reg(ic->arg[0]) = 1;
2053 cpu->cd.mips.rmw = 0;
2054 }
2055 X(scd)
2056 {
2057 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2058 uint64_t r = reg(ic->arg[0]);
2059 int low_pc, i;
2060 uint8_t word[sizeof(uint64_t)];
2061
2062 /* Synch. PC and store using slow memory_rw(): */
2063 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2064 / sizeof(struct mips_instr_call);
2065 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2066 << MIPS_INSTR_ALIGNMENT_SHIFT);
2067 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2068
2069 if (addr & (sizeof(word)-1)) {
2070 fatal("TODO: sc unaligned access: exception\n");
2071 exit(1);
2072 }
2073
2074 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2075 word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2076 word[4]=r>>32; word[5]=r>>40; word[6]=r>>48; word[7]=r>>56;
2077 } else {
2078 word[7]=r; word[6]=r>>8; word[5]=r>>16; word[4]=r>>24;
2079 word[3]=r>>32; word[2]=r>>40; word[1]=r>>48; word[0]=r>>56;
2080 }
2081
2082 /* If rmw is 0, then the store failed. (This cache-line was written
2083 to by someone else.) */
2084 if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2085 || cpu->cd.mips.rmw_len != sizeof(word)) {
2086 reg(ic->arg[0]) = 0;
2087 cpu->cd.mips.rmw = 0;
2088 return;
2089 }
2090
2091 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2092 sizeof(word), MEM_WRITE, CACHE_DATA)) {
2093 /* An exception occurred. */
2094 return;
2095 }
2096
2097 /* We succeeded. Let's invalidate everybody else's store to this
2098 cache line: */
2099 for (i=0; i<cpu->machine->ncpus; i++) {
2100 if (cpu->machine->cpus[i]->cd.mips.rmw) {
2101 uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2102 cd.mips.rmw_addr;
2103 uint64_t mask = ~(cpu->machine->cpus[i]->
2104 cd.mips.cache_linesize[CACHE_DATA] - 1);
2105 xaddr &= mask;
2106 yaddr &= mask;
2107 if (xaddr == yaddr)
2108 cpu->machine->cpus[i]->cd.mips.rmw = 0;
2109 }
2110 }
2111
2112 reg(ic->arg[0]) = 1;
2113 cpu->cd.mips.rmw = 0;
2114 }
2115
2116
2117 /*
2118 * lwc1, swc1: Coprocessor 1 load/store (32-bit)
2119 * ldc1, sdc1: Coprocessor 1 load/store (64-bit)
2120 *
2121 * arg[0] = ptr to coprocessor register
2122 * arg[1] = ptr to rs (base pointer register)
2123 * arg[2] = int32_t imm
2124 */
2125 X(lwc1)
2126 {
2127 const int cpnr = 1;
2128
2129 /* Synch. PC and call the generic load/store function: */
2130 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2131 / sizeof(struct mips_instr_call);
2132 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2133 << MIPS_INSTR_ALIGNMENT_SHIFT);
2134 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2135
2136 /* ... but first, let's see if the coprocessor is available: */
2137 if (!(cpu->cd.mips.coproc[0]->
2138 reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2139 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2140 return;
2141 }
2142
2143 #ifdef MODE32
2144 mips32_loadstore
2145 #else
2146 mips_loadstore
2147 #endif
2148 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 2 * 2 + 1]
2149 (cpu, ic);
2150 }
2151 X(swc1)
2152 {
2153 const int cpnr = 1;
2154
2155 /* Synch. PC and call the generic load/store function: */
2156 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2157 / sizeof(struct mips_instr_call);
2158 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2159 << MIPS_INSTR_ALIGNMENT_SHIFT);
2160 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2161
2162 /* ... but first, let's see if the coprocessor is available: */
2163 if (!(cpu->cd.mips.coproc[0]->
2164 reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2165 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2166 return;
2167 }
2168
2169 #ifdef MODE32
2170 mips32_loadstore
2171 #else
2172 mips_loadstore
2173 #endif
2174 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 2 * 2]
2175 (cpu, ic);
2176 }
2177 X(ldc1)
2178 {
2179 const int cpnr = 1;
2180 int use_fp_pairs =
2181 !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2182 uint64_t fpr, *backup_ptr;
2183
2184 /* Synch. PC and call the generic load/store function: */
2185 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2186 / sizeof(struct mips_instr_call);
2187 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2188 << MIPS_INSTR_ALIGNMENT_SHIFT);
2189 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2190
2191 /* ... but first, let's see if the coprocessor is available: */
2192 if (!(cpu->cd.mips.coproc[0]->
2193 reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2194 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2195 return;
2196 }
2197
2198 backup_ptr = (uint64_t *) ic->arg[0];
2199 ic->arg[0] = (size_t) &fpr;
2200
2201 #ifdef MODE32
2202 mips32_loadstore
2203 #else
2204 mips_loadstore
2205 #endif
2206 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 3 * 2 + 1]
2207 (cpu, ic);
2208
2209 if (use_fp_pairs) {
2210 backup_ptr[0] = (int64_t)(int32_t) fpr;
2211 backup_ptr[1] = (int64_t)(int32_t) (fpr >> 32);
2212 } else {
2213 *backup_ptr = fpr;
2214 }
2215
2216 ic->arg[0] = (size_t) backup_ptr;
2217 }
2218 X(sdc1)
2219 {
2220 const int cpnr = 1;
2221 int use_fp_pairs =
2222 !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2223 uint64_t fpr, *backup_ptr;
2224
2225 /* Synch. PC and call the generic load/store function: */
2226 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2227 / sizeof(struct mips_instr_call);
2228 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2229 << MIPS_INSTR_ALIGNMENT_SHIFT);
2230 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2231
2232 /* ... but first, let's see if the coprocessor is available: */
2233 if (!(cpu->cd.mips.coproc[0]->
2234 reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2235 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2236 return;
2237 }
2238
2239 backup_ptr = (uint64_t *) ic->arg[0];
2240 ic->arg[0] = (size_t) &fpr;
2241
2242 if (use_fp_pairs) {
2243 uint32_t lo = backup_ptr[0];
2244 uint32_t hi = backup_ptr[1];
2245 fpr = (((uint64_t)hi) << 32) | lo;
2246 } else {
2247 fpr = *backup_ptr;
2248 }
2249
2250 #ifdef MODE32
2251 mips32_loadstore
2252 #else
2253 mips_loadstore
2254 #endif
2255 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 3 * 2]
2256 (cpu, ic);
2257
2258 ic->arg[0] = (size_t) backup_ptr;
2259 }
2260
2261
2262 /*
2263 * Unaligned loads/stores:
2264 *
2265 * arg[0] = ptr to rt
2266 * arg[1] = ptr to rs
2267 * arg[2] = int32_t imm
2268 */
2269 X(lwl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 0); }
2270 X(lwr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 0); }
2271 X(ldl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 0); }
2272 X(ldr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 0); }
2273 X(swl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 1); }
2274 X(swr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 1); }
2275 X(sdl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 1); }
2276 X(sdr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 1); }
2277
2278
2279 /*
2280 * di, ei: R5900 interrupt enable/disable.
2281 *
2282 * TODO: check the R5900_STATUS_EDI bit in the status register. If it is
2283 * cleared, and we are not running in kernel mode, then both the EI and DI
2284 * instructions should be treated as NOPs!
2285 */
2286 X(di_r5900)
2287 {
2288 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2289 }
2290 X(ei_r5900)
2291 {
2292 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2293 }
2294
2295
2296 /*****************************************************************************/
2297
2298
2299 /*
2300 * b_samepage_addiu:
2301 *
2302 * Combination of branch within the same page, followed by addiu.
2303 */
2304 X(b_samepage_addiu)
2305 {
2306 reg(ic[1].arg[1]) = (int32_t)
2307 ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
2308 cpu->n_translated_instrs ++;
2309 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2310 }
2311
2312
2313 /*
2314 * b_samepage_daddiu:
2315 *
2316 * Combination of branch within the same page, followed by daddiu.
2317 */
2318 X(b_samepage_daddiu)
2319 {
2320 *(uint64_t *)ic[1].arg[1] = *(uint64_t *)ic[1].arg[0] +
2321 (int32_t)ic[1].arg[2];
2322 cpu->n_translated_instrs ++;
2323 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2324 }
2325
2326
2327 /*****************************************************************************/
2328
2329
2330 X(end_of_page)
2331 {
2332 /* Update the PC: (offset 0, but on the next page) */
2333 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
2334 MIPS_INSTR_ALIGNMENT_SHIFT);
2335 cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);
2336
2337 /* end_of_page doesn't count as an executed instruction: */
2338 cpu->n_translated_instrs --;
2339
2340 /*
2341 * Find the new physpage and update translation pointers.
2342 *
2343 * Note: This may cause an exception, if e.g. the new page is
2344 * not accessible.
2345 */
2346 quick_pc_to_pointers(cpu);
2347
2348 /* Simple jump to the next page (if we are lucky): */
2349 if (cpu->delay_slot == NOT_DELAYED)
2350 return;
2351
2352 /*
2353 * If we were in a delay slot, and we got an exception while doing
2354 * quick_pc_to_pointers, then return. The function which called
2355 * end_of_page should handle this case.
2356 */
2357 if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
2358 return;
2359
2360 /*
2361 * Tricky situation; the delay slot is on the next virtual page.
2362 * Calling to_be_translated will translate one instruction manually,
2363 * execute it, and then discard it.
2364 */
2365 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
2366
2367 instr(to_be_translated)(cpu, cpu->cd.mips.next_ic);
2368
2369 /* The instruction in the delay slot has now executed. */
2370 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
2371 cpu->delay_slot); */
2372
2373 /* Find the physpage etc of the instruction in the delay slot
2374 (or, if there was an exception, the exception handler): */
2375 quick_pc_to_pointers(cpu);
2376 }
2377
2378
2379 X(end_of_page2)
2380 {
2381 /* Synchronize PC on the _second_ instruction on the next page: */
2382 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2383 / sizeof(struct mips_instr_call);
2384 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2385 << MIPS_INSTR_ALIGNMENT_SHIFT);
2386 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2387
2388 /* This doesn't count as an executed instruction. */
2389 cpu->n_translated_instrs --;
2390
2391 quick_pc_to_pointers(cpu);
2392
2393 if (cpu->delay_slot == NOT_DELAYED)
2394 return;
2395
2396 fatal("end_of_page2: fatal error, we're in a delay slot\n");
2397 exit(1);
2398 }
2399
2400
2401 /*****************************************************************************/
2402
2403
2404 /*
2405 * Combine: [Conditional] branch, followed by addiu.
2406 */
2407 void COMBINE(b_addiu)(struct cpu *cpu, struct mips_instr_call *ic,
2408 int low_addr)
2409 {
2410 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2411 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2412
2413 if (n_back < 1)
2414 return;
2415
2416 if (ic[-1].f == instr(b_samepage)) {
2417 ic[-1].f = instr(b_samepage_addiu);
2418 combined;
2419 }
2420
2421 /* TODO: other branches that are followed by addiu should be here */
2422 }
2423
2424
2425 /*
2426 * Combine: [Conditional] branch, followed by daddiu.
2427 */
2428 void COMBINE(b_daddiu)(struct cpu *cpu, struct mips_instr_call *ic,
2429 int low_addr)
2430 {
2431 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2432 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2433
2434 if (n_back < 1)
2435 return;
2436
2437 if (ic[-1].f == instr(b_samepage)) {
2438 ic[-1].f = instr(b_samepage_daddiu);
2439 combined;
2440 }
2441
2442 /* TODO: other branches that are followed by daddiu should be here */
2443 }
2444
2445
2446 /*****************************************************************************/
2447
2448
2449 /*
2450 * mips_instr_to_be_translated():
2451 *
2452 * Translate an instruction word into a mips_instr_call. ic is filled in with
2453 * valid data for the translated instruction, or a "nothing" instruction if
2454 * there was a translation failure. The newly translated instruction is then
2455 * executed.
2456 */
2457 X(to_be_translated)
2458 {
2459 uint64_t addr, low_pc;
2460 uint32_t iword, imm;
2461 unsigned char *page;
2462 unsigned char ib[4];
2463 int main_opcode, rt, rs, rd, sa, s6, x64 = 0;
2464 int in_crosspage_delayslot = 0;
2465 void (*samepage_function)(struct cpu *, struct mips_instr_call *);
2466 int store, signedness, size;
2467
2468 /* Figure out the (virtual) address of the instruction: */
2469 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2470 / sizeof(struct mips_instr_call);
2471
2472 /* Special case for branch with delayslot on the next page: */
2473 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
2474 /* fatal("[ delay-slot translation across page "
2475 "boundary ]\n"); */
2476 in_crosspage_delayslot = 1;
2477 }
2478
2479 addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2480 << MIPS_INSTR_ALIGNMENT_SHIFT);
2481 addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2482 cpu->pc = (MODE_int_t)addr;
2483 addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
2484
2485 /* Read the instruction word from memory: */
2486 #ifdef MODE32
2487 page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
2488 #else
2489 {
2490 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2491 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2492 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2493 uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2494 uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2495 uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2496 DYNTRANS_L3N)) & mask3;
2497 struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.mips.l1_64[x1];
2498 struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2499 page = l3->host_load[x3];
2500 }
2501 #endif
2502
2503 if (page != NULL) {
2504 /* fatal("TRANSLATION HIT!\n"); */
2505 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
2506 } else {
2507 /* fatal("TRANSLATION MISS!\n"); */
2508 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2509 sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2510 fatal("to_be_translated(): read failed: TODO\n");
2511 goto bad;
2512 }
2513 }
2514
2515 iword = *((uint32_t *)&ib[0]);
2516
2517 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2518 iword = LE32_TO_HOST(iword);
2519 else
2520 iword = BE32_TO_HOST(iword);
2521
2522
2523 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
2524 #include "cpu_dyntrans.c"
2525 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
2526
2527
2528 /*
2529 * Translate the instruction:
2530 *
2531 * NOTE: _NEVER_ allow writes to the zero register; all instructions
2532 * that use the zero register as their destination should be treated
2533 * as NOPs, except those that access memory (they should use the
2534 * scratch register instead).
2535 */
2536
2537 main_opcode = iword >> 26;
2538 rs = (iword >> 21) & 31;
2539 rt = (iword >> 16) & 31;
2540 rd = (iword >> 11) & 31;
2541 sa = (iword >> 6) & 31;
2542 imm = (int16_t)iword;
2543 s6 = iword & 63;
2544
2545 switch (main_opcode) {
2546
2547 case HI6_SPECIAL:
2548 switch (s6) {
2549
2550 case SPECIAL_SLL:
2551 case SPECIAL_SLLV:
2552 case SPECIAL_SRL:
2553 case SPECIAL_SRLV:
2554 case SPECIAL_SRA:
2555 case SPECIAL_SRAV:
2556 case SPECIAL_DSRL:
2557 case SPECIAL_DSRLV:
2558 case SPECIAL_DSRL32:
2559 case SPECIAL_DSLL:
2560 case SPECIAL_DSLLV:
2561 case SPECIAL_DSLL32:
2562 case SPECIAL_DSRA:
2563 case SPECIAL_DSRAV:
2564 case SPECIAL_DSRA32:
2565 switch (s6) {
2566 case SPECIAL_SLL: ic->f = instr(sll); break;
2567 case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
2568 case SPECIAL_SRL: ic->f = instr(srl); break;
2569 case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
2570 case SPECIAL_SRA: ic->f = instr(sra); break;
2571 case SPECIAL_SRAV: ic->f = instr(srav); sa = -1; break;
2572 case SPECIAL_DSRL: ic->f = instr(dsrl); x64=1; break;
2573 case SPECIAL_DSRLV:ic->f = instr(dsrlv);
2574 x64 = 1; sa = -1; break;
2575 case SPECIAL_DSRL32:ic->f= instr(dsrl); x64=1;
2576 sa += 32; break;
2577 case SPECIAL_DSLL: ic->f = instr(dsll); x64=1; break;
2578 case SPECIAL_DSLLV:ic->f = instr(dsllv);
2579 x64 = 1; sa = -1; break;
2580 case SPECIAL_DSLL32:ic->f= instr(dsll); x64=1;
2581 sa += 32; break;
2582 case SPECIAL_DSRA: ic->f = instr(dsra); x64=1; break;
2583 case SPECIAL_DSRAV:ic->f = instr(dsrav);
2584 x64 = 1; sa = -1; break;
2585 case SPECIAL_DSRA32:ic->f = instr(dsra); x64=1;
2586 sa += 32; break;
2587 }
2588 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2589 if (sa >= 0)
2590 ic->arg[1] = sa;
2591 else
2592 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
2593 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
2594 if (rd == MIPS_GPR_ZERO)
2595 ic->f = instr(nop);
2596 break;
2597
2598 case SPECIAL_ADD:
2599 case SPECIAL_ADDU:
2600 case SPECIAL_SUB:
2601 case SPECIAL_SUBU:
2602 case SPECIAL_DADD:
2603 case SPECIAL_DADDU:
2604 case SPECIAL_DSUB:
2605 case SPECIAL_DSUBU:
2606 case SPECIAL_SLT:
2607 case SPECIAL_SLTU:
2608 case SPECIAL_AND:
2609 case SPECIAL_OR:
2610 case SPECIAL_XOR:
2611 case SPECIAL_NOR:
2612 case SPECIAL_MOVN:
2613 case SPECIAL_MOVZ:
2614 case SPECIAL_MFHI:
2615 case SPECIAL_MFLO:
2616 case SPECIAL_MTHI:
2617 case SPECIAL_MTLO:
2618 case SPECIAL_DIV:
2619 case SPECIAL_DIVU:
2620 case SPECIAL_DDIV:
2621 case SPECIAL_DDIVU:
2622 case SPECIAL_MULT:
2623 case SPECIAL_MULTU:
2624 case SPECIAL_DMULT:
2625 case SPECIAL_DMULTU:
2626 case SPECIAL_TGE:
2627 case SPECIAL_TGEU:
2628 case SPECIAL_TLT:
2629 case SPECIAL_TLTU:
2630 case SPECIAL_TEQ:
2631 case SPECIAL_TNE:
2632 switch (s6) {
2633 case SPECIAL_ADD: ic->f = instr(add); break;
2634 case SPECIAL_ADDU: ic->f = instr(addu); break;
2635 case SPECIAL_SUB: ic->f = instr(sub); break;
2636 case SPECIAL_SUBU: ic->f = instr(subu); break;
2637 case SPECIAL_DADD: ic->f = instr(dadd); x64=1; break;
2638 case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
2639 case SPECIAL_DSUB: ic->f = instr(dsub); x64=1; break;
2640 case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;
2641 case SPECIAL_SLT: ic->f = instr(slt); break;
2642 case SPECIAL_SLTU: ic->f = instr(sltu); break;
2643 case SPECIAL_AND: ic->f = instr(and); break;
2644 case SPECIAL_OR: ic->f = instr(or); break;
2645 case SPECIAL_XOR: ic->f = instr(xor); break;
2646 case SPECIAL_NOR: ic->f = instr(nor); break;
2647 case SPECIAL_MFHI: ic->f = instr(mov); break;
2648 case SPECIAL_MFLO: ic->f = instr(mov); break;
2649 case SPECIAL_MTHI: ic->f = instr(mov); break;
2650 case SPECIAL_MTLO: ic->f = instr(mov); break;
2651 case SPECIAL_DIV: ic->f = instr(div); break;
2652 case SPECIAL_DIVU: ic->f = instr(divu); break;
2653 case SPECIAL_DDIV: ic->f = instr(ddiv); x64=1; break;
2654 case SPECIAL_DDIVU: ic->f = instr(ddivu); x64=1; break;
2655 case SPECIAL_MULT : ic->f = instr(mult); break;
2656 case SPECIAL_MULTU: ic->f = instr(multu); break;
2657 case SPECIAL_DMULT: ic->f = instr(dmult); x64=1; break;
2658 case SPECIAL_DMULTU:ic->f = instr(dmultu); x64=1; break;
2659 case SPECIAL_TGE: ic->f = instr(tge); break;
2660 case SPECIAL_TGEU: ic->f = instr(tgeu); break;
2661 case SPECIAL_TLT: ic->f = instr(tlt); break;
2662 case SPECIAL_TLTU: ic->f = instr(tltu); break;
2663 case SPECIAL_TEQ: ic->f = instr(teq); break;
2664 case SPECIAL_TNE: ic->f = instr(tne); break;
2665 case SPECIAL_MOVN: ic->f = instr(movn); break;
2666 case SPECIAL_MOVZ: ic->f = instr(movz); break;
2667 }
2668 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2669 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
2670 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
2671 switch (s6) {
2672 case SPECIAL_MFHI:
2673 ic->arg[0] = (size_t)&cpu->cd.mips.hi;
2674 break;
2675 case SPECIAL_MFLO:
2676 ic->arg[0] = (size_t)&cpu->cd.mips.lo;
2677 break;
2678 case SPECIAL_MTHI:
2679 ic->arg[2] = (size_t)&cpu->cd.mips.hi;
2680 break;
2681 case SPECIAL_MTLO:
2682 ic->arg[2] = (size_t)&cpu->cd.mips.lo;
2683 break;
2684 }
2685 /* Special cases for rd: */
2686 switch (s6) {
2687 case SPECIAL_MTHI:
2688 case SPECIAL_MTLO:
2689 case SPECIAL_DIV:
2690 case SPECIAL_DIVU:
2691 case SPECIAL_DDIV:
2692 case SPECIAL_DDIVU:
2693 case SPECIAL_MULT:
2694 case SPECIAL_MULTU:
2695 case SPECIAL_DMULT:
2696 case SPECIAL_DMULTU:
2697 case SPECIAL_TGE:
2698 case SPECIAL_TGEU:
2699 case SPECIAL_TLT:
2700 case SPECIAL_TLTU:
2701 case SPECIAL_TEQ:
2702 case SPECIAL_TNE:
2703 if (s6 == SPECIAL_MULT && rd != MIPS_GPR_ZERO) {
2704 if (cpu->cd.mips.cpu_type.rev ==
2705 MIPS_R5900) {
2706 ic->f = instr(mult_r5900);
2707 break;
2708 }
2709 break;
2710 }
2711 if (s6 == SPECIAL_MULTU && rd!=MIPS_GPR_ZERO) {
2712 if (cpu->cd.mips.cpu_type.rev ==
2713 MIPS_R5900) {
2714 ic->f = instr(multu_r5900);
2715 break;
2716 }
2717 }
2718 if (rd != MIPS_GPR_ZERO) {
2719 fatal("TODO: rd NON-zero\n");
2720 goto bad;
2721 }
2722 /* These instructions don't use rd. */
2723 break;
2724 default:if (rd == MIPS_GPR_ZERO)
2725 ic->f = instr(nop);
2726 }
2727 break;
2728
2729 case SPECIAL_JR:
2730 case SPECIAL_JALR:
2731 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2732 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
2733 if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
2734 s6 = SPECIAL_JR;
2735 ic->arg[2] = (addr & 0xffc) + 8;
2736 switch (s6) {
2737 case SPECIAL_JR:
2738 if (rs == MIPS_GPR_RA) {
2739 if (cpu->machine->show_trace_tree)
2740 ic->f = instr(jr_ra_trace);
2741 else
2742 ic->f = instr(jr_ra);
2743 } else {
2744 ic->f = instr(jr);
2745 }
2746 break;
2747 case SPECIAL_JALR:
2748 if (cpu->machine->show_trace_tree)
2749 ic->f = instr(jalr_trace);
2750 else
2751 ic->f = instr(jalr);
2752 break;
2753 }
2754 if (cpu->delay_slot) {
2755 fatal("TODO: branch in delay slot? (1)\n");
2756 goto bad;
2757 }
2758 break;
2759
2760 case SPECIAL_SYSCALL:
2761 if (((iword >> 6) & 0xfffff) == 0x30378) {
2762 /* "Magic trap" for PROM emulation: */
2763 ic->f = instr(promemul);
2764 } else {
2765 ic->f = instr(syscall);
2766 }
2767 break;
2768
2769 case SPECIAL_BREAK:
2770 ic->f = instr(break);
2771 break;
2772
2773 case SPECIAL_SYNC:
2774 ic->f = instr(nop);
2775 break;
2776
2777 default:goto bad;
2778 }
2779 break;
2780
2781 case HI6_BEQ:
2782 case HI6_BNE:
2783 case HI6_BEQL:
2784 case HI6_BNEL:
2785 case HI6_BLEZ:
2786 case HI6_BLEZL:
2787 case HI6_BGTZ:
2788 case HI6_BGTZL:
2789 samepage_function = NULL; /* get rid of a compiler warning */
2790 switch (main_opcode) {
2791 case HI6_BEQ:
2792 ic->f = instr(beq);
2793 samepage_function = instr(beq_samepage);
2794 /* Special case: comparing a register with itself: */
2795 if (rs == rt) {
2796 ic->f = instr(b);
2797 samepage_function = instr(b_samepage);
2798 }
2799 break;
2800 case HI6_BNE:
2801 ic->f = instr(bne);
2802 samepage_function = instr(bne_samepage);
2803 break;
2804 case HI6_BEQL:
2805 ic->f = instr(beql);
2806 samepage_function = instr(beql_samepage);
2807 /* Special case: comparing a register with itself: */
2808 if (rs == rt) {
2809 ic->f = instr(b);
2810 samepage_function = instr(b_samepage);
2811 }
2812 break;
2813 case HI6_BNEL:
2814 ic->f = instr(bnel);
2815 samepage_function = instr(bnel_samepage);
2816 break;
2817 case HI6_BLEZ:
2818 ic->f = instr(blez);
2819 samepage_function = instr(blez_samepage);
2820 break;
2821 case HI6_BLEZL:
2822 ic->f = instr(blezl);
2823 samepage_function = instr(blezl_samepage);
2824 break;
2825 case HI6_BGTZ:
2826 ic->f = instr(bgtz);
2827 samepage_function = instr(bgtz_samepage);
2828 break;
2829 case HI6_BGTZL:
2830 ic->f = instr(bgtzl);
2831 samepage_function = instr(bgtzl_samepage);
2832 break;
2833 }
2834 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2835 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
2836 ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
2837 + (addr & 0xffc) + 4 );
2838 /* Is the offset from the start of the current page still
2839 within the same page? Then use the samepage_function: */
2840 if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE - 1)
2841 << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc) < 0xffc) {
2842 ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page +
2843 ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
2844 & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
2845 ic->f = samepage_function;
2846 }
2847 if (cpu->delay_slot) {
2848 fatal("TODO: branch in delay slot? (2)\n");
2849 goto bad;
2850 }
2851 break;
2852
2853 case HI6_ADDI:
2854 case HI6_ADDIU:
2855 case HI6_SLTI:
2856 case HI6_SLTIU:
2857 case HI6_DADDI:
2858 case HI6_DADDIU:
2859 case HI6_ANDI:
2860 case HI6_ORI:
2861 case HI6_XORI:
2862 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2863 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
2864 if (main_opcode == HI6_ADDI ||
2865 main_opcode == HI6_ADDIU ||
2866 main_opcode == HI6_SLTI ||
2867 main_opcode == HI6_SLTIU ||
2868 main_opcode == HI6_DADDI ||
2869 main_opcode == HI6_DADDIU)
2870 ic->arg[2] = (int16_t)iword;
2871 else
2872 ic->arg[2] = (uint16_t)iword;
2873
2874 switch (main_opcode) {
2875 case HI6_ADDI: ic->f = instr(addi); break;
2876 case HI6_ADDIU: ic->f = instr(addiu); break;
2877 case HI6_SLTI: ic->f = instr(slti); break;
2878 case HI6_SLTIU: ic->f = instr(sltiu); break;
2879 case HI6_DADDI: ic->f = instr(daddi); x64 = 1; break;
2880 case HI6_DADDIU: ic->f = instr(daddiu); x64 = 1; break;
2881 case HI6_ANDI: ic->f = instr(andi); break;
2882 case HI6_ORI: ic->f = instr(ori); break;
2883 case HI6_XORI: ic->f = instr(xori); break;
2884 }
2885
2886 if (rt == MIPS_GPR_ZERO)
2887 ic->f = instr(nop);
2888
2889 if (ic->f == instr(addiu))
2890 cpu->cd.mips.combination_check = COMBINE(b_addiu);
2891 if (ic->f == instr(daddiu))
2892 cpu->cd.mips.combination_check = COMBINE(b_daddiu);
2893 break;
2894
2895 case HI6_LUI:
2896 ic->f = instr(set);
2897 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2898 ic->arg[1] = (int32_t) (imm << 16);
2899 if (rt == MIPS_GPR_ZERO)
2900 ic->f = instr(nop);
2901 break;
2902
2903 case HI6_J:
2904 case HI6_JAL:
2905 switch (main_opcode) {
2906 case HI6_J:
2907 ic->f = instr(j);
2908 break;
2909 case HI6_JAL:
2910 if (cpu->machine->show_trace_tree)
2911 ic->f = instr(jal_trace);
2912 else
2913 ic->f = instr(jal);
2914 break;
2915 }
2916 ic->arg[0] = (iword & 0x03ffffff) << 2;
2917 ic->arg[1] = (addr & 0xffc) + 8;
2918 if (cpu->delay_slot) {
2919 fatal("TODO: branch in delay slot (=%i)? (3); addr=%016"
2920 PRIx64" iword=%08"PRIx32"\n", cpu->delay_slot,
2921 (uint64_t)addr, iword);
2922 goto bad;
2923 }
2924 break;
2925
2926 case HI6_COP0:
2927 /* TODO: Is checking bit 25 enough, or perhaps all bits
2928 25..21 must be checked? */
2929 if ((iword >> 25) & 1) {
2930 ic->arg[2] = addr & 0xffc;
2931 switch (iword & 0xff) {
2932 case COP0_TLBR:
2933 ic->f = instr(tlbr);
2934 break;
2935 case COP0_TLBWI:
2936 case COP0_TLBWR:
2937 ic->f = instr(tlbw);
2938 ic->arg[0] = (iword & 0xff) == COP0_TLBWR;
2939 break;
2940 case COP0_TLBP:
2941 ic->f = instr(tlbp);
2942 break;
2943 case COP0_RFE:
2944 ic->f = instr(rfe);
2945 break;
2946 case COP0_ERET:
2947 ic->f = instr(eret);
2948 break;
2949 case COP0_DERET:
2950 ic->f = instr(deret);
2951 break;
2952 case COP0_IDLE:
2953 case COP0_STANDBY:
2954 case COP0_SUSPEND:
2955 case COP0_HIBERNATE:
2956 /* TODO */
2957 ic->f = instr(nop);
2958 break;
2959 case COP0_EI:
2960 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
2961 ic->f = instr(ei_r5900);
2962 } else
2963 goto bad;
2964 break;
2965 case COP0_DI:
2966 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
2967 ic->f = instr(di_r5900);
2968 } else
2969 goto bad;
2970 break;
2971 default:fatal("UNIMPLEMENTED cop0 (func 0x%02x)\n",
2972 iword & 0xff);
2973 goto bad;
2974 }
2975 break;
2976 }
2977
2978 /* rs contains the coprocessor opcode! */
2979 switch (rs) {
2980 case COPz_CFCz:
2981 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2982 ic->arg[1] = rd + ((iword & 7) << 5);
2983 ic->arg[2] = addr & 0xffc;
2984 ic->f = instr(cfc0);
2985 if (rt == MIPS_GPR_ZERO)
2986 ic->f = instr(nop);
2987 break;
2988 case COPz_MFCz:
2989 case COPz_DMFCz:
2990 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2991 ic->arg[1] = rd + ((iword & 7) << 5);
2992 ic->arg[2] = addr & 0xffc;
2993 ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);
2994 if (rt == MIPS_GPR_ZERO)
2995 ic->f = instr(nop);
2996 break;
2997 case COPz_MTCz:
2998 case COPz_DMTCz:
2999 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3000 ic->arg[1] = rd + ((iword & 7) << 5);
3001 ic->arg[2] = addr & 0xffc;
3002 ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
3003 break;
3004 case 8: if (iword == 0x4100ffff) {
3005 /* R2020 DECstation write-loop thingy. */
3006 ic->f = instr(nop);
3007 } else {
3008 fatal("Unimplemented blah blah zzzz...\n");
3009 goto bad;
3010 }
3011 break;
3012
3013 default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
3014 goto bad;
3015 }
3016 break;
3017
3018 case HI6_COP1:
3019 /* Always cause a coprocessor unusable exception if
3020 there is no floating point coprocessor: */
3021 if (cpu->cd.mips.cpu_type.flags & NOFPU ||
3022 cpu->cd.mips.coproc[1] == NULL) {
3023 ic->f = instr(cpu);
3024 ic->arg[0] = 1;
3025 break;
3026 }
3027
3028 /* Bits 25..21 are floating point main opcode: */
3029 switch (rs) {
3030
3031 case COPz_BCzc:
3032 /* Conditional branch: */
3033 /* TODO: Reimplement this in a faster way. */
3034 ic->f = instr(cop1_bc);
3035 ic->arg[0] = (iword >> 18) & 7; /* cc */
3036 ic->arg[1] = (iword >> 16) & 3; /* nd, tf bits */
3037 ic->arg[2] = (int32_t) ((imm <<
3038 MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);
3039 if (cpu->delay_slot) {
3040 fatal("TODO: branch in delay slot? (4)\n");
3041 goto bad;
3042 }
3043 if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
3044 ic->arg[0] != 0) {
3045 fatal("Attempt to execute a non-cc-0 BC*"
3046 " instruction on an isa level %i cpu. "
3047 "TODO: How should this be handled?\n",
3048 cpu->cd.mips.cpu_type.isa_level);
3049 goto bad;
3050 }
3051
3052 break;
3053
3054 case COPz_DMFCz:
3055 case COPz_DMTCz:
3056 x64 = 1;
3057 /* FALL-THROUGH */
3058 case COP1_FMT_S:
3059 case COP1_FMT_D:
3060 case COP1_FMT_W:
3061 case COP1_FMT_L:
3062 case COP1_FMT_PS:
3063 case COPz_CFCz:
3064 case COPz_CTCz:
3065 case COPz_MFCz:
3066 case COPz_MTCz:
3067 /* Fallback to slow pre-dyntrans code, for now. */
3068 /* TODO: Fix/optimize/rewrite. */
3069 ic->f = instr(cop1_slow);
3070 ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);
3071 break;
3072
3073 default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
3074 goto bad;
3075 }
3076 break;
3077
3078 case HI6_COP2:
3079 /* Always cause a coprocessor unusable exception if
3080 there is no coprocessor 2: */
3081 if (cpu->cd.mips.coproc[2] == NULL) {
3082 ic->f = instr(cpu);
3083 ic->arg[0] = 2;
3084 break;
3085 }
3086 fatal("COP2 functionality not yet implemented\n");
3087 goto bad;
3088 break;
3089
3090 case HI6_SPECIAL2:
3091 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3092 /* R5900, TX79/C790, have MMI instead of SPECIAL2: */
3093 int mmi_subopcode = (iword >> 6) & 0x1f;
3094
3095 switch (s6) {
3096
3097 case MMI_MADD:
3098 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3099 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3100 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3101 if (rd == MIPS_GPR_ZERO)
3102 ic->f = instr(madd);
3103 else
3104 ic->f = instr(madd_rd);
3105 break;
3106
3107 case MMI_MADDU:
3108 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3109 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3110 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3111 if (rd == MIPS_GPR_ZERO)
3112 ic->f = instr(maddu);
3113 else
3114 ic->f = instr(maddu_rd);
3115 break;
3116
3117 case MMI_MMI0:
3118 switch (mmi_subopcode) {
3119
3120 case MMI0_PEXTLW:
3121 ic->arg[0] = rs;
3122 ic->arg[1] = rt;
3123 ic->arg[2] = rd;
3124 if (rd == MIPS_GPR_ZERO)
3125 ic->f = instr(nop);
3126 else
3127 ic->f = instr(pextlw);
3128 break;
3129
3130 default:goto bad;
3131 }
3132 break;
3133
3134 case MMI_MMI3:
3135 switch (mmi_subopcode) {
3136
3137 case MMI3_POR:
3138 ic->arg[0] = rs;
3139 ic->arg[1] = rt;
3140 ic->arg[2] = rd;
3141 if (rd == MIPS_GPR_ZERO)
3142 ic->f = instr(nop);
3143 else
3144 ic->f = instr(por);
3145 break;
3146
3147 default:goto bad;
3148 }
3149 break;
3150
3151 default:goto bad;
3152 }
3153 break;
3154 }
3155
3156 /* TODO: is this correct? Or are there other non-MIPS32/64
3157 MIPS processors that have support for SPECIAL2 opcodes? */
3158 if (cpu->cd.mips.cpu_type.isa_level < 32) {
3159 ic->f = instr(reserved);
3160 break;
3161 }
3162
3163 /* SPECIAL2: */
3164 switch (s6) {
3165
3166 case SPECIAL2_MADD:
3167 case SPECIAL2_MADDU:
3168 case SPECIAL2_MSUB:
3169 case SPECIAL2_MSUBU:
3170 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3171 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3172 switch (s6) {
3173 case SPECIAL2_MADD: ic->f = instr(madd); break;
3174 case SPECIAL2_MADDU:ic->f = instr(maddu); break;
3175 case SPECIAL2_MSUB: ic->f = instr(msub); break;
3176 case SPECIAL2_MSUBU:ic->f = instr(msubu); break;
3177 }
3178 break;
3179
3180 case SPECIAL2_MUL:
3181 ic->f = instr(mul);
3182 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3183 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3184 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3185 if (rd == MIPS_GPR_ZERO)
3186 ic->f = instr(nop);
3187 break;
3188
3189 case SPECIAL2_CLZ:
3190 case SPECIAL2_CLO:
3191 case SPECIAL2_DCLZ:
3192 case SPECIAL2_DCLO:
3193 switch (s6) {
3194 case SPECIAL2_CLZ: ic->f = instr(clz); break;
3195 case SPECIAL2_CLO: ic->f = instr(clo); break;
3196 case SPECIAL2_DCLZ: ic->f = instr(dclz); break;
3197 case SPECIAL2_DCLO: ic->f = instr(dclo); break;
3198 }
3199 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3200 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
3201 if (rd == MIPS_GPR_ZERO)
3202 ic->f = instr(nop);
3203 break;
3204
3205 default:goto bad;
3206 }
3207 break;
3208
3209 case HI6_REGIMM:
3210 switch (rt) {
3211 case REGIMM_BGEZ:
3212 case REGIMM_BGEZL:
3213 case REGIMM_BLTZ:
3214 case REGIMM_BLTZL:
3215 case REGIMM_BGEZAL:
3216 case REGIMM_BGEZALL:
3217 case REGIMM_BLTZAL:
3218 case REGIMM_BLTZALL:
3219 samepage_function = NULL;
3220 switch (rt) {
3221 case REGIMM_BGEZ:
3222 ic->f = instr(bgez);
3223 samepage_function = instr(bgez_samepage);
3224 break;
3225 case REGIMM_BGEZL:
3226 ic->f = instr(bgezl);
3227 samepage_function = instr(bgezl_samepage);
3228 break;
3229 case REGIMM_BLTZ:
3230 ic->f = instr(bltz);
3231 samepage_function = instr(bltz_samepage);
3232 break;
3233 case REGIMM_BLTZL:
3234 ic->f = instr(bltzl);
3235 samepage_function = instr(bltzl_samepage);
3236 break;
3237 case REGIMM_BGEZAL:
3238 ic->f = instr(bgezal);
3239 samepage_function = instr(bgezal_samepage);
3240 break;
3241 case REGIMM_BGEZALL:
3242 ic->f = instr(bgezall);
3243 samepage_function = instr(bgezall_samepage);
3244 break;
3245 case REGIMM_BLTZAL:
3246 ic->f = instr(bltzal);
3247 samepage_function = instr(bltzal_samepage);
3248 break;
3249 case REGIMM_BLTZALL:
3250 ic->f = instr(bltzall);
3251 samepage_function = instr(bltzall_samepage);
3252 break;
3253 }
3254 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3255 ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
3256 + (addr & 0xffc) + 4;
3257 /* Is the offset from the start of the current page
3258 still within the same page? Then use the
3259 samepage_function: */
3260 if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE-1)
3261 << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc)
3262 < 0xffc) {
3263 ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page+
3264 ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
3265 & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
3266 ic->f = samepage_function;
3267 }
3268 if (cpu->delay_slot) {
3269 fatal("TODO: branch in delay slot? (5)\n");
3270 goto bad;
3271 }
3272 break;
3273 default:fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
3274 goto bad;
3275 }
3276 break;
3277
3278 case HI6_LB:
3279 case HI6_LBU:
3280 case HI6_SB:
3281 case HI6_LH:
3282 case HI6_LHU:
3283 case HI6_SH:
3284 case HI6_LW:
3285 case HI6_LWU:
3286 case HI6_SW:
3287 case HI6_LD:
3288 case HI6_SD:
3289 /* TODO: LWU should probably also be x64=1? */
3290 size = 2; signedness = 0; store = 0;
3291 switch (main_opcode) {
3292 case HI6_LB: size = 0; signedness = 1; break;
3293 case HI6_LBU: size = 0; break;
3294 case HI6_LH: size = 1; signedness = 1; break;
3295 case HI6_LHU: size = 1; break;
3296 case HI6_LW: signedness = 1; break;
3297 case HI6_LWU: break;
3298 case HI6_LD: size = 3; x64 = 1; break;
3299 case HI6_SB: store = 1; size = 0; break;
3300 case HI6_SH: store = 1; size = 1; break;
3301 case HI6_SW: store = 1; break;
3302 case HI6_SD: store = 1; size = 3; x64 = 1; break;
3303 }
3304
3305 ic->f =
3306 #ifdef MODE32
3307 mips32_loadstore
3308 #else
3309 mips_loadstore
3310 #endif
3311 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16)
3312 + store * 8 + size * 2 + signedness];
3313 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3314 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3315 ic->arg[2] = (int32_t)imm;
3316
3317 /* Load into the dummy scratch register, if rt = zero */
3318 if (!store && rt == MIPS_GPR_ZERO)
3319 ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
3320 break;
3321
3322 case HI6_LL:
3323 case HI6_LLD:
3324 case HI6_SC:
3325 case HI6_SCD:
3326 /* 32-bit load-linked/store-condition for ISA II and up: */
3327 /* (64-bit load-linked/store-condition for ISA III...) */
3328 if (cpu->cd.mips.cpu_type.isa_level < 2) {
3329 ic->f = instr(reserved);
3330 break;
3331 }
3332
3333 store = 0;
3334 switch (main_opcode) {
3335 case HI6_LL: ic->f = instr(ll); break;
3336 case HI6_LLD: ic->f = instr(lld); x64 = 1; break;
3337 case HI6_SC: ic->f = instr(sc); store = 1; break;
3338 case HI6_SCD: ic->f = instr(scd); store = 1; x64 = 1; break;
3339 }
3340 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3341 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3342 ic->arg[2] = (int32_t)imm;
3343 if (!store && rt == MIPS_GPR_ZERO) {
3344 fatal("HM... unusual load linked\n");
3345 goto bad;
3346 }
3347 break;
3348
3349 case HI6_LWL:
3350 case HI6_LWR:
3351 case HI6_LDL:
3352 case HI6_LDR:
3353 case HI6_SWL:
3354 case HI6_SWR:
3355 case HI6_SDL:
3356 case HI6_SDR:
3357 /* TODO: replace these with faster versions... */
3358 store = 0;
3359 switch (main_opcode) {
3360 case HI6_LWL: ic->f = instr(lwl); break;
3361 case HI6_LWR: ic->f = instr(lwr); break;
3362 case HI6_LDL: ic->f = instr(ldl); x64 = 1; break;
3363 case HI6_LDR: ic->f = instr(ldr); x64 = 1; break;
3364 case HI6_SWL: ic->f = instr(swl); store = 1; break;
3365 case HI6_SWR: ic->f = instr(swr); store = 1; break;
3366 case HI6_SDL: ic->f = instr(sdl); store = 1; x64 = 1; break;
3367 case HI6_SDR: ic->f = instr(sdr); store = 1; x64 = 1; break;
3368 }
3369 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3370 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3371 ic->arg[2] = (int32_t)imm;
3372
3373 /* Load into the dummy scratch register, if rt = zero */
3374 if (!store && rt == MIPS_GPR_ZERO)
3375 ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
3376 break;
3377
3378 case HI6_LWC1:
3379 case HI6_SWC1:
3380 case HI6_LDC1:
3381 case HI6_SDC1:
3382 /* 64-bit floating-point load/store for ISA II and up... */
3383 if ((main_opcode == HI6_LDC1 || main_opcode == HI6_SDC1)
3384 && cpu->cd.mips.cpu_type.isa_level < 2) {
3385 ic->f = instr(reserved);
3386 break;
3387 }
3388
3389 ic->arg[0] = (size_t)&cpu->cd.mips.coproc[1]->reg[rt];
3390 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3391 ic->arg[2] = (int32_t)imm;
3392 switch (main_opcode) {
3393 case HI6_LWC1: ic->f = instr(lwc1); break;
3394 case HI6_LDC1: ic->f = instr(ldc1); break;
3395 case HI6_SWC1: ic->f = instr(swc1); break;
3396 case HI6_SDC1: ic->f = instr(sdc1); break;
3397 }
3398
3399 /* Cause a coprocessor unusable exception if
3400 there is no floating point coprocessor: */
3401 if (cpu->cd.mips.cpu_type.flags & NOFPU ||
3402 cpu->cd.mips.coproc[1] == NULL) {
3403 ic->f = instr(cpu);
3404 ic->arg[0] = 1;
3405 }
3406 break;
3407
3408 case HI6_LWC3:
3409 /* PREF (prefetch) on ISA IV and MIPS32/64: */
3410 if (cpu->cd.mips.cpu_type.isa_level >= 4) {
3411 /* Treat as nop for now: */
3412 ic->f = instr(nop);
3413 } else {
3414 fatal("TODO: lwc3 not implemented yet\n");
3415 goto bad;
3416 }
3417 break;
3418
3419 case HI6_LQ_MDMX:
3420 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3421 fatal("TODO: R5900 128-bit loads\n");
3422 goto bad;
3423 }
3424
3425 fatal("TODO: MDMX\n");
3426 goto bad;
3427 /* break */
3428
3429 case HI6_SQ_SPECIAL3:
3430 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3431 fatal("TODO: R5900 128-bit stores\n");
3432 goto bad;
3433 }
3434
3435 if (cpu->cd.mips.cpu_type.isa_level < 32 ||
3436 cpu->cd.mips.cpu_type.isa_revision < 2) {
3437 static int warning = 0;
3438 if (!warning) {
3439 fatal("[ WARNING! SPECIAL3 opcode used on a"
3440 " cpu which doesn't implement it ]\n");
3441 warning = 1;
3442 }
3443 ic->f = instr(reserved);
3444 break;
3445 }
3446
3447 switch (s6) {
3448
3449 case SPECIAL3_RDHWR:
3450 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3451
3452 switch (rd) {
3453
3454 case 0: ic->f = instr(rdhwr_cpunum);
3455 if (rt == MIPS_GPR_ZERO)
3456 ic->f = instr(nop);
3457 break;
3458
3459 default:fatal("unimplemented rdhwr register rd=%i\n",
3460 rd);
3461 goto bad;
3462 }
3463 break;
3464
3465 default:goto bad;
3466 }
3467 break;
3468
3469 case HI6_CACHE:
3470 /* TODO: rt and op etc... */
3471 ic->f = instr(cache);
3472 break;
3473
3474 default:goto bad;
3475 }
3476
3477 #ifdef MODE32
3478 if (x64) {
3479 static int has_warned = 0;
3480 if (!has_warned)
3481 fatal("[ WARNING/NOTE: attempt to execute a 64-bit"
3482 " instruction on an emulated 32-bit processor; "
3483 "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);
3484 has_warned = 1;
3485 ic->f = instr(reserved);
3486 }
3487 #endif
3488
3489
3490 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
3491 #include "cpu_dyntrans.c"
3492 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
3493 }
3494

  ViewVC Help
Powered by ViewVC 1.1.26