/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (hide annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 123928 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


1 dpavlin 22 /*
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 dpavlin 30 * $Id: cpu_mips_instr.c,v 1.104 2006/08/14 17:45:47 debug Exp $
29 dpavlin 22 *
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 dpavlin 24 * invalid: For catching bugs.
41 dpavlin 22 */
42 dpavlin 24 X(invalid)
43 dpavlin 22 {
44 dpavlin 24 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 dpavlin 22 }
49    
50    
51     /*
52 dpavlin 24 * reserved: Attempt to execute a reserved instruction (e.g. a 64-bit
53     * instruction on an emulated 32-bit processor).
54 dpavlin 22 */
55 dpavlin 24 X(reserved)
56 dpavlin 22 {
57 dpavlin 24 /* 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 dpavlin 22 }
65    
66    
67     /*
68 dpavlin 24 * 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 dpavlin 22 * 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 dpavlin 24 MODE_int_t old_pc = cpu->pc;
104 dpavlin 22 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
105     int x = rs == rt;
106 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
107 dpavlin 22 ic[1].f(cpu, ic+1);
108     cpu->n_translated_instrs ++;
109 dpavlin 24 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 dpavlin 22 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 dpavlin 24 } else
120     cpu->delay_slot = NOT_DELAYED;
121 dpavlin 22 }
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 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
127 dpavlin 22 ic[1].f(cpu, ic+1);
128     cpu->n_translated_instrs ++;
129 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
130 dpavlin 22 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 dpavlin 24 cpu->delay_slot = NOT_DELAYED;
137 dpavlin 22 }
138 dpavlin 28 X(beq_samepage_addiu)
139     {
140     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
141     cpu->n_translated_instrs ++;
142     reg(ic[1].arg[1]) = (int32_t)
143     ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
144     if (rs == rt)
145     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
146     else
147     cpu->cd.mips.next_ic ++;
148     }
149     X(beq_samepage_nop)
150     {
151     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
152     cpu->n_translated_instrs ++;
153     if (rs == rt)
154     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
155     else
156     cpu->cd.mips.next_ic ++;
157     }
158 dpavlin 22 X(bne)
159     {
160 dpavlin 24 MODE_int_t old_pc = cpu->pc;
161 dpavlin 22 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
162     int x = rs != rt;
163 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
164 dpavlin 22 ic[1].f(cpu, ic+1);
165     cpu->n_translated_instrs ++;
166 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
167     /* Note: Must be non-delayed when jumping to the new pc: */
168     cpu->delay_slot = NOT_DELAYED;
169 dpavlin 22 if (x) {
170     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
171     MIPS_INSTR_ALIGNMENT_SHIFT);
172     cpu->pc = old_pc + (int32_t)ic->arg[2];
173     quick_pc_to_pointers(cpu);
174     } else
175     cpu->cd.mips.next_ic ++;
176 dpavlin 24 } else
177     cpu->delay_slot = NOT_DELAYED;
178 dpavlin 22 }
179     X(bne_samepage)
180     {
181     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
182     int x = rs != rt;
183 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
184 dpavlin 22 ic[1].f(cpu, ic+1);
185     cpu->n_translated_instrs ++;
186 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
187 dpavlin 22 if (x)
188     cpu->cd.mips.next_ic = (struct mips_instr_call *)
189     ic->arg[2];
190     else
191     cpu->cd.mips.next_ic ++;
192     }
193 dpavlin 24 cpu->delay_slot = NOT_DELAYED;
194 dpavlin 22 }
195 dpavlin 28 X(bne_samepage_addiu)
196     {
197     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
198     cpu->n_translated_instrs ++;
199     reg(ic[1].arg[1]) = (int32_t)
200     ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
201     if (rs != rt)
202     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
203     else
204     cpu->cd.mips.next_ic ++;
205     }
206     X(bne_samepage_nop)
207     {
208     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
209     cpu->n_translated_instrs ++;
210     if (rs != rt)
211     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
212     else
213     cpu->cd.mips.next_ic ++;
214     }
215 dpavlin 22 X(b)
216     {
217 dpavlin 24 MODE_int_t old_pc = cpu->pc;
218     cpu->delay_slot = TO_BE_DELAYED;
219 dpavlin 22 ic[1].f(cpu, ic+1);
220     cpu->n_translated_instrs ++;
221 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
222     /* Note: Must be non-delayed when jumping to the new pc: */
223     cpu->delay_slot = NOT_DELAYED;
224 dpavlin 22 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
225     MIPS_INSTR_ALIGNMENT_SHIFT);
226     cpu->pc = old_pc + (int32_t)ic->arg[2];
227     quick_pc_to_pointers(cpu);
228 dpavlin 24 } else
229     cpu->delay_slot = NOT_DELAYED;
230 dpavlin 22 }
231     X(b_samepage)
232     {
233 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
234 dpavlin 22 ic[1].f(cpu, ic+1);
235     cpu->n_translated_instrs ++;
236 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT))
237 dpavlin 22 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
238 dpavlin 24 cpu->delay_slot = NOT_DELAYED;
239 dpavlin 22 }
240    
241    
242     /*
243 dpavlin 24 * beql: Branch if equal likely
244     * bnel: Branch if not equal likely
245     *
246     * arg[0] = pointer to rs
247     * arg[1] = pointer to rt
248     * arg[2] = (int32_t) relative offset from the next instruction
249     */
250     X(beql)
251     {
252     MODE_int_t old_pc = cpu->pc;
253     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
254     int x = rs == rt;
255     cpu->delay_slot = TO_BE_DELAYED;
256     if (x)
257     ic[1].f(cpu, ic+1);
258     cpu->n_translated_instrs ++;
259     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
260     /* Note: Must be non-delayed when jumping to the new pc: */
261     cpu->delay_slot = NOT_DELAYED;
262     if (x) {
263     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
264     MIPS_INSTR_ALIGNMENT_SHIFT);
265     cpu->pc = old_pc + (int32_t)ic->arg[2];
266     quick_pc_to_pointers(cpu);
267     } else
268     cpu->cd.mips.next_ic ++;
269     } else
270     cpu->delay_slot = NOT_DELAYED;
271     }
272     X(beql_samepage)
273     {
274     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
275     int x = rs == rt;
276     cpu->delay_slot = TO_BE_DELAYED;
277     if (x)
278     ic[1].f(cpu, ic+1);
279     cpu->n_translated_instrs ++;
280     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
281     if (x)
282     cpu->cd.mips.next_ic = (struct mips_instr_call *)
283     ic->arg[2];
284     else
285     cpu->cd.mips.next_ic ++;
286     }
287     cpu->delay_slot = NOT_DELAYED;
288     }
289     X(bnel)
290     {
291     MODE_int_t old_pc = cpu->pc;
292     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
293     int x = rs != rt;
294     cpu->delay_slot = TO_BE_DELAYED;
295     if (x)
296     ic[1].f(cpu, ic+1);
297     cpu->n_translated_instrs ++;
298     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
299     /* Note: Must be non-delayed when jumping to the new pc: */
300     cpu->delay_slot = NOT_DELAYED;
301     if (x) {
302     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
303     MIPS_INSTR_ALIGNMENT_SHIFT);
304     cpu->pc = old_pc + (int32_t)ic->arg[2];
305     quick_pc_to_pointers(cpu);
306     } else
307     cpu->cd.mips.next_ic ++;
308     } else
309     cpu->delay_slot = NOT_DELAYED;
310     }
311     X(bnel_samepage)
312     {
313     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
314     int x = rs != rt;
315     cpu->delay_slot = TO_BE_DELAYED;
316     if (x)
317     ic[1].f(cpu, ic+1);
318     cpu->n_translated_instrs ++;
319     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
320     if (x)
321     cpu->cd.mips.next_ic = (struct mips_instr_call *)
322     ic->arg[2];
323     else
324     cpu->cd.mips.next_ic ++;
325     }
326     cpu->delay_slot = NOT_DELAYED;
327     }
328    
329    
330     /*
331     * blez: Branch if less than or equal
332     * blezl: Branch if less than or equal likely
333     *
334     * arg[0] = pointer to rs
335     * arg[2] = (int32_t) relative offset from the next instruction
336     */
337     X(blez)
338     {
339     MODE_int_t old_pc = cpu->pc;
340     MODE_int_t rs = reg(ic->arg[0]);
341     int x = (rs <= 0);
342     cpu->delay_slot = TO_BE_DELAYED;
343     ic[1].f(cpu, ic+1);
344     cpu->n_translated_instrs ++;
345     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
346     /* Note: Must be non-delayed when jumping to the new pc: */
347     cpu->delay_slot = NOT_DELAYED;
348     if (x) {
349     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
350     MIPS_INSTR_ALIGNMENT_SHIFT);
351     cpu->pc = old_pc + (int32_t)ic->arg[2];
352     quick_pc_to_pointers(cpu);
353     } else
354     cpu->cd.mips.next_ic ++;
355     } else
356     cpu->delay_slot = NOT_DELAYED;
357     }
358     X(blez_samepage)
359     {
360     MODE_int_t rs = reg(ic->arg[0]);
361     int x = (rs <= 0);
362     cpu->delay_slot = TO_BE_DELAYED;
363     ic[1].f(cpu, ic+1);
364     cpu->n_translated_instrs ++;
365     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
366     if (x)
367     cpu->cd.mips.next_ic = (struct mips_instr_call *)
368     ic->arg[2];
369     else
370     cpu->cd.mips.next_ic ++;
371     }
372     cpu->delay_slot = NOT_DELAYED;
373     }
374     X(blezl)
375     {
376     MODE_int_t old_pc = cpu->pc;
377     MODE_int_t rs = reg(ic->arg[0]);
378     int x = (rs <= 0);
379     cpu->delay_slot = TO_BE_DELAYED;
380     if (x)
381     ic[1].f(cpu, ic+1);
382     cpu->n_translated_instrs ++;
383     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
384     /* Note: Must be non-delayed when jumping to the new pc: */
385     cpu->delay_slot = NOT_DELAYED;
386     if (x) {
387     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
388     MIPS_INSTR_ALIGNMENT_SHIFT);
389     cpu->pc = old_pc + (int32_t)ic->arg[2];
390     quick_pc_to_pointers(cpu);
391     } else
392     cpu->cd.mips.next_ic ++;
393     } else
394     cpu->delay_slot = NOT_DELAYED;
395     }
396     X(blezl_samepage)
397     {
398     MODE_int_t rs = reg(ic->arg[0]);
399     int x = (rs <= 0);
400     cpu->delay_slot = TO_BE_DELAYED;
401     if (x)
402     ic[1].f(cpu, ic+1);
403     cpu->n_translated_instrs ++;
404     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
405     if (x)
406     cpu->cd.mips.next_ic = (struct mips_instr_call *)
407     ic->arg[2];
408     else
409     cpu->cd.mips.next_ic ++;
410     }
411     cpu->delay_slot = NOT_DELAYED;
412     }
413    
414    
415     /*
416     * bltz: Branch if less than
417     * bltzl: Branch if less than likely
418     *
419     * arg[0] = pointer to rs
420     * arg[2] = (int32_t) relative offset from the next instruction
421     */
422     X(bltz)
423     {
424     MODE_int_t old_pc = cpu->pc;
425     MODE_int_t rs = reg(ic->arg[0]);
426     int x = (rs < 0);
427     cpu->delay_slot = TO_BE_DELAYED;
428     ic[1].f(cpu, ic+1);
429     cpu->n_translated_instrs ++;
430     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
431     /* Note: Must be non-delayed when jumping to the new pc: */
432     cpu->delay_slot = NOT_DELAYED;
433     if (x) {
434     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
435     MIPS_INSTR_ALIGNMENT_SHIFT);
436     cpu->pc = old_pc + (int32_t)ic->arg[2];
437     quick_pc_to_pointers(cpu);
438     } else
439     cpu->cd.mips.next_ic ++;
440     } else
441     cpu->delay_slot = NOT_DELAYED;
442     }
443     X(bltz_samepage)
444     {
445     MODE_int_t rs = reg(ic->arg[0]);
446     int x = (rs < 0);
447     cpu->delay_slot = TO_BE_DELAYED;
448     ic[1].f(cpu, ic+1);
449     cpu->n_translated_instrs ++;
450     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
451     if (x)
452     cpu->cd.mips.next_ic = (struct mips_instr_call *)
453     ic->arg[2];
454     else
455     cpu->cd.mips.next_ic ++;
456     }
457     cpu->delay_slot = NOT_DELAYED;
458     }
459     X(bltzl)
460     {
461     MODE_int_t old_pc = cpu->pc;
462     MODE_int_t rs = reg(ic->arg[0]);
463     int x = (rs < 0);
464     cpu->delay_slot = TO_BE_DELAYED;
465     if (x)
466     ic[1].f(cpu, ic+1);
467     cpu->n_translated_instrs ++;
468     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
469     /* Note: Must be non-delayed when jumping to the new pc: */
470     cpu->delay_slot = NOT_DELAYED;
471     if (x) {
472     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
473     MIPS_INSTR_ALIGNMENT_SHIFT);
474     cpu->pc = old_pc + (int32_t)ic->arg[2];
475     quick_pc_to_pointers(cpu);
476     } else
477     cpu->cd.mips.next_ic ++;
478     } else
479     cpu->delay_slot = NOT_DELAYED;
480     }
481     X(bltzl_samepage)
482     {
483     MODE_int_t rs = reg(ic->arg[0]);
484     int x = (rs < 0);
485     cpu->delay_slot = TO_BE_DELAYED;
486     if (x)
487     ic[1].f(cpu, ic+1);
488     cpu->n_translated_instrs ++;
489     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
490     if (x)
491     cpu->cd.mips.next_ic = (struct mips_instr_call *)
492     ic->arg[2];
493     else
494     cpu->cd.mips.next_ic ++;
495     }
496     cpu->delay_slot = NOT_DELAYED;
497     }
498    
499    
500     /*
501     * bgez: Branch if greater than or equal
502     * bgezl: Branch if greater than or equal likely
503     *
504     * arg[0] = pointer to rs
505     * arg[2] = (int32_t) relative offset from the next instruction
506     */
507     X(bgez)
508     {
509     MODE_int_t old_pc = cpu->pc;
510     MODE_int_t rs = reg(ic->arg[0]);
511     int x = (rs >= 0);
512     cpu->delay_slot = TO_BE_DELAYED;
513     ic[1].f(cpu, ic+1);
514     cpu->n_translated_instrs ++;
515     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
516     /* Note: Must be non-delayed when jumping to the new pc: */
517     cpu->delay_slot = NOT_DELAYED;
518     if (x) {
519     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
520     MIPS_INSTR_ALIGNMENT_SHIFT);
521     cpu->pc = old_pc + (int32_t)ic->arg[2];
522     quick_pc_to_pointers(cpu);
523     } else
524     cpu->cd.mips.next_ic ++;
525     } else
526     cpu->delay_slot = NOT_DELAYED;
527     }
528     X(bgez_samepage)
529     {
530     MODE_int_t rs = reg(ic->arg[0]);
531     int x = (rs >= 0);
532     cpu->delay_slot = TO_BE_DELAYED;
533     ic[1].f(cpu, ic+1);
534     cpu->n_translated_instrs ++;
535     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
536     if (x)
537     cpu->cd.mips.next_ic = (struct mips_instr_call *)
538     ic->arg[2];
539     else
540     cpu->cd.mips.next_ic ++;
541     }
542     cpu->delay_slot = NOT_DELAYED;
543     }
544     X(bgezl)
545     {
546     MODE_int_t old_pc = cpu->pc;
547     MODE_int_t rs = reg(ic->arg[0]);
548     int x = (rs >= 0);
549     cpu->delay_slot = TO_BE_DELAYED;
550     if (x)
551     ic[1].f(cpu, ic+1);
552     cpu->n_translated_instrs ++;
553     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
554     /* Note: Must be non-delayed when jumping to the new pc: */
555     cpu->delay_slot = NOT_DELAYED;
556     if (x) {
557     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
558     MIPS_INSTR_ALIGNMENT_SHIFT);
559     cpu->pc = old_pc + (int32_t)ic->arg[2];
560     quick_pc_to_pointers(cpu);
561     } else
562     cpu->cd.mips.next_ic ++;
563     } else
564     cpu->delay_slot = NOT_DELAYED;
565     }
566     X(bgezl_samepage)
567     {
568     MODE_int_t rs = reg(ic->arg[0]);
569     int x = (rs >= 0);
570     cpu->delay_slot = TO_BE_DELAYED;
571     if (x)
572     ic[1].f(cpu, ic+1);
573     cpu->n_translated_instrs ++;
574     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
575     if (x)
576     cpu->cd.mips.next_ic = (struct mips_instr_call *)
577     ic->arg[2];
578     else
579     cpu->cd.mips.next_ic ++;
580     }
581     cpu->delay_slot = NOT_DELAYED;
582     }
583    
584    
585     /*
586     * bgezal: Branch if greater than or equal (and link)
587     * bgezall: Branch if greater than or equal (and link) likely
588     *
589     * arg[0] = pointer to rs
590     * arg[2] = (int32_t) relative offset from the next instruction
591     */
592     X(bgezal)
593     {
594     MODE_int_t old_pc = cpu->pc;
595     MODE_int_t rs = reg(ic->arg[0]);
596     int x = (rs >= 0), low_pc;
597    
598     cpu->delay_slot = TO_BE_DELAYED;
599     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
600     / sizeof(struct mips_instr_call);
601     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
602     << MIPS_INSTR_ALIGNMENT_SHIFT);
603     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
604     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
605    
606     ic[1].f(cpu, ic+1);
607     cpu->n_translated_instrs ++;
608     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
609     /* Note: Must be non-delayed when jumping to the new pc: */
610     cpu->delay_slot = NOT_DELAYED;
611     if (x) {
612     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
613     MIPS_INSTR_ALIGNMENT_SHIFT);
614     cpu->pc = old_pc + (int32_t)ic->arg[2];
615     quick_pc_to_pointers(cpu);
616     } else
617     cpu->cd.mips.next_ic ++;
618     } else
619     cpu->delay_slot = NOT_DELAYED;
620     }
621     X(bgezal_samepage)
622     {
623     MODE_int_t rs = reg(ic->arg[0]);
624     int x = (rs >= 0), low_pc;
625    
626     cpu->delay_slot = TO_BE_DELAYED;
627     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
628     / sizeof(struct mips_instr_call);
629     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
630     << MIPS_INSTR_ALIGNMENT_SHIFT);
631     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
632     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
633    
634     ic[1].f(cpu, ic+1);
635     cpu->n_translated_instrs ++;
636     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
637     if (x)
638     cpu->cd.mips.next_ic = (struct mips_instr_call *)
639     ic->arg[2];
640     else
641     cpu->cd.mips.next_ic ++;
642     }
643     cpu->delay_slot = NOT_DELAYED;
644     }
645     X(bgezall)
646     {
647     MODE_int_t old_pc = cpu->pc;
648     MODE_int_t rs = reg(ic->arg[0]);
649     int x = (rs >= 0), low_pc;
650    
651     cpu->delay_slot = TO_BE_DELAYED;
652     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
653     / sizeof(struct mips_instr_call);
654     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
655     << MIPS_INSTR_ALIGNMENT_SHIFT);
656     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
657     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
658    
659     if (x)
660     ic[1].f(cpu, ic+1);
661     cpu->n_translated_instrs ++;
662     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
663     /* Note: Must be non-delayed when jumping to the new pc: */
664     cpu->delay_slot = NOT_DELAYED;
665     if (x) {
666     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
667     MIPS_INSTR_ALIGNMENT_SHIFT);
668     cpu->pc = old_pc + (int32_t)ic->arg[2];
669     quick_pc_to_pointers(cpu);
670     } else
671     cpu->cd.mips.next_ic ++;
672     } else
673     cpu->delay_slot = NOT_DELAYED;
674     }
675     X(bgezall_samepage)
676     {
677     MODE_int_t rs = reg(ic->arg[0]);
678     int x = (rs >= 0), low_pc;
679    
680     cpu->delay_slot = TO_BE_DELAYED;
681     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
682     / sizeof(struct mips_instr_call);
683     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
684     << MIPS_INSTR_ALIGNMENT_SHIFT);
685     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
686     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
687    
688     if (x)
689     ic[1].f(cpu, ic+1);
690     cpu->n_translated_instrs ++;
691     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
692     if (x)
693     cpu->cd.mips.next_ic = (struct mips_instr_call *)
694     ic->arg[2];
695     else
696     cpu->cd.mips.next_ic ++;
697     }
698     cpu->delay_slot = NOT_DELAYED;
699     }
700    
701    
702     /*
703     * bltzal: Branch if less than zero (and link)
704     * bltzall: Branch if less than zero (and link) likely
705     *
706     * arg[0] = pointer to rs
707     * arg[2] = (int32_t) relative offset from the next instruction
708     */
709     X(bltzal)
710     {
711     MODE_int_t old_pc = cpu->pc;
712     MODE_int_t rs = reg(ic->arg[0]);
713     int x = (rs < 0), low_pc;
714    
715     cpu->delay_slot = TO_BE_DELAYED;
716     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
717     / sizeof(struct mips_instr_call);
718     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
719     << MIPS_INSTR_ALIGNMENT_SHIFT);
720     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
721     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
722    
723     ic[1].f(cpu, ic+1);
724     cpu->n_translated_instrs ++;
725     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
726     /* Note: Must be non-delayed when jumping to the new pc: */
727     cpu->delay_slot = NOT_DELAYED;
728     if (x) {
729     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
730     MIPS_INSTR_ALIGNMENT_SHIFT);
731     cpu->pc = old_pc + (int32_t)ic->arg[2];
732     quick_pc_to_pointers(cpu);
733     } else
734     cpu->cd.mips.next_ic ++;
735     } else
736     cpu->delay_slot = NOT_DELAYED;
737     }
738     X(bltzal_samepage)
739     {
740     MODE_int_t rs = reg(ic->arg[0]);
741     int x = (rs < 0), low_pc;
742    
743     cpu->delay_slot = TO_BE_DELAYED;
744     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
745     / sizeof(struct mips_instr_call);
746     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
747     << MIPS_INSTR_ALIGNMENT_SHIFT);
748     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
749     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
750    
751     ic[1].f(cpu, ic+1);
752     cpu->n_translated_instrs ++;
753     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
754     if (x)
755     cpu->cd.mips.next_ic = (struct mips_instr_call *)
756     ic->arg[2];
757     else
758     cpu->cd.mips.next_ic ++;
759     }
760     cpu->delay_slot = NOT_DELAYED;
761     }
762     X(bltzall)
763     {
764     MODE_int_t old_pc = cpu->pc;
765     MODE_int_t rs = reg(ic->arg[0]);
766     int x = (rs < 0), low_pc;
767    
768     cpu->delay_slot = TO_BE_DELAYED;
769     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
770     / sizeof(struct mips_instr_call);
771     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
772     << MIPS_INSTR_ALIGNMENT_SHIFT);
773     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
774     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
775    
776     if (x)
777     ic[1].f(cpu, ic+1);
778     cpu->n_translated_instrs ++;
779     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
780     /* Note: Must be non-delayed when jumping to the new pc: */
781     cpu->delay_slot = NOT_DELAYED;
782     if (x) {
783     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
784     MIPS_INSTR_ALIGNMENT_SHIFT);
785     cpu->pc = old_pc + (int32_t)ic->arg[2];
786     quick_pc_to_pointers(cpu);
787     } else
788     cpu->cd.mips.next_ic ++;
789     } else
790     cpu->delay_slot = NOT_DELAYED;
791     }
792     X(bltzall_samepage)
793     {
794     MODE_int_t rs = reg(ic->arg[0]);
795     int x = (rs < 0), low_pc;
796    
797     cpu->delay_slot = TO_BE_DELAYED;
798     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
799     / sizeof(struct mips_instr_call);
800     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
801     << MIPS_INSTR_ALIGNMENT_SHIFT);
802     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
803     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
804    
805     if (x)
806     ic[1].f(cpu, ic+1);
807     cpu->n_translated_instrs ++;
808     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
809     if (x)
810     cpu->cd.mips.next_ic = (struct mips_instr_call *)
811     ic->arg[2];
812     else
813     cpu->cd.mips.next_ic ++;
814     }
815     cpu->delay_slot = NOT_DELAYED;
816     }
817    
818    
819     /*
820     * bgtz: Branch if greater than zero
821     * bgtzl: Branch if greater than zero likely
822     *
823     * arg[0] = pointer to rs
824     * arg[2] = (int32_t) relative offset from the next instruction
825     */
826     X(bgtz)
827     {
828     MODE_int_t old_pc = cpu->pc;
829     MODE_int_t rs = reg(ic->arg[0]);
830     int x = (rs > 0);
831     cpu->delay_slot = TO_BE_DELAYED;
832     ic[1].f(cpu, ic+1);
833     cpu->n_translated_instrs ++;
834     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
835     /* Note: Must be non-delayed when jumping to the new pc: */
836     cpu->delay_slot = NOT_DELAYED;
837     if (x) {
838     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
839     MIPS_INSTR_ALIGNMENT_SHIFT);
840     cpu->pc = old_pc + (int32_t)ic->arg[2];
841     quick_pc_to_pointers(cpu);
842     } else
843     cpu->cd.mips.next_ic ++;
844     } else
845     cpu->delay_slot = NOT_DELAYED;
846     }
847     X(bgtz_samepage)
848     {
849     MODE_int_t rs = reg(ic->arg[0]);
850     int x = (rs > 0);
851     cpu->delay_slot = TO_BE_DELAYED;
852     ic[1].f(cpu, ic+1);
853     cpu->n_translated_instrs ++;
854     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
855     if (x)
856     cpu->cd.mips.next_ic = (struct mips_instr_call *)
857     ic->arg[2];
858     else
859     cpu->cd.mips.next_ic ++;
860     }
861     cpu->delay_slot = NOT_DELAYED;
862     }
863     X(bgtzl)
864     {
865     MODE_int_t old_pc = cpu->pc;
866     MODE_int_t rs = reg(ic->arg[0]);
867     int x = (rs > 0);
868     cpu->delay_slot = TO_BE_DELAYED;
869     if (x)
870     ic[1].f(cpu, ic+1);
871     cpu->n_translated_instrs ++;
872     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
873     /* Note: Must be non-delayed when jumping to the new pc: */
874     cpu->delay_slot = NOT_DELAYED;
875     if (x) {
876     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
877     MIPS_INSTR_ALIGNMENT_SHIFT);
878     cpu->pc = old_pc + (int32_t)ic->arg[2];
879     quick_pc_to_pointers(cpu);
880     } else
881     cpu->cd.mips.next_ic ++;
882     } else
883     cpu->delay_slot = NOT_DELAYED;
884     }
885     X(bgtzl_samepage)
886     {
887     MODE_int_t rs = reg(ic->arg[0]);
888     int x = (rs > 0);
889     cpu->delay_slot = TO_BE_DELAYED;
890     if (x)
891     ic[1].f(cpu, ic+1);
892     cpu->n_translated_instrs ++;
893     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
894     if (x)
895     cpu->cd.mips.next_ic = (struct mips_instr_call *)
896     ic->arg[2];
897     else
898     cpu->cd.mips.next_ic ++;
899     }
900     cpu->delay_slot = NOT_DELAYED;
901     }
902    
903    
904     /*
905 dpavlin 22 * jr, jalr: Jump to a register [and link].
906     *
907     * arg[0] = ptr to rs
908     * arg[1] = ptr to rd (for jalr)
909     * arg[2] = (int32_t) relative offset of the next instruction
910     */
911     X(jr)
912     {
913 dpavlin 24 MODE_int_t rs = reg(ic->arg[0]);
914     cpu->delay_slot = TO_BE_DELAYED;
915 dpavlin 22 ic[1].f(cpu, ic+1);
916     cpu->n_translated_instrs ++;
917 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
918 dpavlin 22 cpu->pc = rs;
919 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
920     cpu->delay_slot = NOT_DELAYED;
921 dpavlin 22 quick_pc_to_pointers(cpu);
922 dpavlin 24 } else
923     cpu->delay_slot = NOT_DELAYED;
924 dpavlin 22 }
925     X(jr_ra)
926     {
927 dpavlin 24 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
928     cpu->delay_slot = TO_BE_DELAYED;
929 dpavlin 22 ic[1].f(cpu, ic+1);
930     cpu->n_translated_instrs ++;
931 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
932 dpavlin 22 cpu->pc = rs;
933 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
934     cpu->delay_slot = NOT_DELAYED;
935 dpavlin 22 quick_pc_to_pointers(cpu);
936 dpavlin 24 } else
937     cpu->delay_slot = NOT_DELAYED;
938 dpavlin 22 }
939 dpavlin 28 X(jr_ra_addiu)
940     {
941     /* jr ra, followed by an addiu */
942     MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
943     reg(ic[1].arg[1]) = (int32_t)
944     ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
945     cpu->pc = rs;
946     quick_pc_to_pointers(cpu);
947     cpu->n_translated_instrs ++;
948     }
949 dpavlin 22 X(jr_ra_trace)
950     {
951 dpavlin 24 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
952     cpu->delay_slot = TO_BE_DELAYED;
953 dpavlin 22 ic[1].f(cpu, ic+1);
954     cpu->n_translated_instrs ++;
955 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
956 dpavlin 22 cpu->pc = rs;
957     cpu_functioncall_trace_return(cpu);
958 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
959     cpu->delay_slot = NOT_DELAYED;
960 dpavlin 22 quick_pc_to_pointers(cpu);
961 dpavlin 24 } else
962     cpu->delay_slot = NOT_DELAYED;
963 dpavlin 22 }
964     X(jalr)
965     {
966 dpavlin 24 MODE_int_t rs = reg(ic->arg[0]), rd;
967     cpu->delay_slot = TO_BE_DELAYED;
968 dpavlin 22 rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
969     MIPS_INSTR_ALIGNMENT_SHIFT);
970     rd += (int32_t)ic->arg[2];
971     reg(ic->arg[1]) = rd;
972     ic[1].f(cpu, ic+1);
973     cpu->n_translated_instrs ++;
974 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
975 dpavlin 22 cpu->pc = rs;
976 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
977     cpu->delay_slot = NOT_DELAYED;
978 dpavlin 22 quick_pc_to_pointers(cpu);
979 dpavlin 24 } else
980     cpu->delay_slot = NOT_DELAYED;
981 dpavlin 22 }
982     X(jalr_trace)
983     {
984 dpavlin 24 MODE_int_t rs = reg(ic->arg[0]), rd;
985     cpu->delay_slot = TO_BE_DELAYED;
986 dpavlin 22 rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
987     MIPS_INSTR_ALIGNMENT_SHIFT);
988     rd += (int32_t)ic->arg[2];
989     reg(ic->arg[1]) = rd;
990     ic[1].f(cpu, ic+1);
991     cpu->n_translated_instrs ++;
992 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
993 dpavlin 22 cpu->pc = rs;
994     cpu_functioncall_trace(cpu, cpu->pc);
995 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
996     cpu->delay_slot = NOT_DELAYED;
997 dpavlin 22 quick_pc_to_pointers(cpu);
998 dpavlin 24 } else
999     cpu->delay_slot = NOT_DELAYED;
1000 dpavlin 22 }
1001    
1002    
1003     /*
1004 dpavlin 24 * j, jal: Jump [and link].
1005     *
1006     * arg[0] = lowest 28 bits of new pc.
1007     * arg[1] = offset from start of page to the jal instruction + 8
1008     */
1009     X(j)
1010     {
1011     MODE_int_t old_pc = cpu->pc;
1012     cpu->delay_slot = TO_BE_DELAYED;
1013     ic[1].f(cpu, ic+1);
1014     cpu->n_translated_instrs ++;
1015     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1016     /* Note: Must be non-delayed when jumping to the new pc: */
1017     cpu->delay_slot = NOT_DELAYED;
1018     old_pc &= ~0x03ffffff;
1019     cpu->pc = old_pc | (uint32_t)ic->arg[0];
1020     quick_pc_to_pointers(cpu);
1021     } else
1022     cpu->delay_slot = NOT_DELAYED;
1023     }
1024     X(jal)
1025     {
1026     MODE_int_t old_pc = cpu->pc;
1027     cpu->delay_slot = TO_BE_DELAYED;
1028     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1029     cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
1030     ic[1].f(cpu, ic+1);
1031     cpu->n_translated_instrs ++;
1032     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1033     /* Note: Must be non-delayed when jumping to the new pc: */
1034     cpu->delay_slot = NOT_DELAYED;
1035     old_pc &= ~0x03ffffff;
1036     cpu->pc = old_pc | (int32_t)ic->arg[0];
1037     quick_pc_to_pointers(cpu);
1038     } else
1039     cpu->delay_slot = NOT_DELAYED;
1040     }
1041     X(jal_trace)
1042     {
1043     MODE_int_t old_pc = cpu->pc;
1044     cpu->delay_slot = TO_BE_DELAYED;
1045     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1046     cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
1047     ic[1].f(cpu, ic+1);
1048     cpu->n_translated_instrs ++;
1049     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1050     /* Note: Must be non-delayed when jumping to the new pc: */
1051     cpu->delay_slot = NOT_DELAYED;
1052     old_pc &= ~0x03ffffff;
1053     cpu->pc = old_pc | (int32_t)ic->arg[0];
1054     cpu_functioncall_trace(cpu, cpu->pc);
1055     quick_pc_to_pointers(cpu);
1056     } else
1057     cpu->delay_slot = NOT_DELAYED;
1058     }
1059    
1060    
1061     /*
1062     * cache: Cache operation.
1063     */
1064     X(cache)
1065     {
1066 dpavlin 28 /* TODO: Implement cache operations. */
1067    
1068     /* Make sure the rmw bit is cleared: */
1069 dpavlin 24 cpu->cd.mips.rmw = 0;
1070     }
1071    
1072    
1073     /*
1074 dpavlin 22 * 2-register + immediate:
1075     *
1076     * arg[0] = pointer to rs
1077     * arg[1] = pointer to rt
1078     * arg[2] = uint32_t immediate value
1079     */
1080 dpavlin 24 X(andi) { reg(ic->arg[1]) = reg(ic->arg[0]) & (uint32_t)ic->arg[2]; }
1081     X(ori) { reg(ic->arg[1]) = reg(ic->arg[0]) | (uint32_t)ic->arg[2]; }
1082     X(xori) { reg(ic->arg[1]) = reg(ic->arg[0]) ^ (uint32_t)ic->arg[2]; }
1083 dpavlin 22
1084    
1085     /*
1086     * 2-register:
1087 dpavlin 24 *
1088     * arg[0] = ptr to rs
1089     * arg[1] = ptr to rt
1090 dpavlin 22 */
1091 dpavlin 24 X(div)
1092     {
1093     int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1094     int32_t res, rem;
1095     if (b == 0)
1096     res = 0, rem = a;
1097     else
1098     res = a / b, rem = a - b*res;
1099     reg(&cpu->cd.mips.lo) = (int32_t)res;
1100     reg(&cpu->cd.mips.hi) = (int32_t)rem;
1101     }
1102     X(divu)
1103     {
1104     uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1105     uint32_t res, rem;
1106     if (b == 0)
1107     res = 0, rem = a;
1108     else
1109     res = a / b, rem = a - b*res;
1110     reg(&cpu->cd.mips.lo) = (int32_t)res;
1111     reg(&cpu->cd.mips.hi) = (int32_t)rem;
1112     }
1113     X(ddiv)
1114     {
1115     int64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1116     int64_t res, rem;
1117     if (b == 0)
1118     res = 0;
1119     else
1120     res = a / b;
1121     rem = a - b*res;
1122     reg(&cpu->cd.mips.lo) = res;
1123     reg(&cpu->cd.mips.hi) = rem;
1124     }
1125     X(ddivu)
1126     {
1127     uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1128     uint64_t res, rem;
1129     if (b == 0)
1130     res = 0;
1131     else
1132     res = a / b;
1133     rem = a - b*res;
1134     reg(&cpu->cd.mips.lo) = res;
1135     reg(&cpu->cd.mips.hi) = rem;
1136     }
1137 dpavlin 22 X(mult)
1138     {
1139     int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1140     int64_t res = (int64_t)a * (int64_t)b;
1141     reg(&cpu->cd.mips.lo) = (int32_t)res;
1142     reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1143     }
1144 dpavlin 24 X(mult_r5900)
1145     {
1146     /* C790/TX79/R5900 multiplication, stores result in
1147     hi, lo, and a third register */
1148     int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1149     int64_t res = (int64_t)a * (int64_t)b;
1150     reg(&cpu->cd.mips.lo) = (int32_t)res;
1151     reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1152     reg(ic->arg[2]) = (int32_t)res;
1153     }
1154 dpavlin 22 X(multu)
1155     {
1156     uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1157     uint64_t res = (uint64_t)a * (uint64_t)b;
1158     reg(&cpu->cd.mips.lo) = (int32_t)res;
1159     reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1160     }
1161 dpavlin 24 X(multu_r5900)
1162     {
1163     /* C790/TX79/R5900 multiplication, stores result in
1164     hi, lo, and a third register */
1165     uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1166     uint64_t res = (uint64_t)a * (uint64_t)b;
1167     reg(&cpu->cd.mips.lo) = (int32_t)res;
1168     reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1169     reg(ic->arg[2]) = (int32_t)res;
1170     }
1171     X(dmult)
1172     {
1173     uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1174     uint64_t hi = 0, lo = 0;
1175     int neg = 0;
1176     if (a >> 63)
1177     neg = !neg, a = -a;
1178     if (b >> 63)
1179     neg = !neg, b = -b;
1180     for (; a; a >>= 1) {
1181     if (a & 1) {
1182     uint64_t old_lo = lo;
1183     hi += c;
1184     lo += b;
1185     if (lo < old_lo)
1186     hi ++;
1187     }
1188     c = (c << 1) | (b >> 63); b <<= 1;
1189     }
1190     if (neg) {
1191     if (lo == 0)
1192     hi --;
1193     lo --;
1194     hi ^= (int64_t) -1;
1195     lo ^= (int64_t) -1;
1196     }
1197     reg(&cpu->cd.mips.lo) = lo;
1198     reg(&cpu->cd.mips.hi) = hi;
1199     }
1200     X(dmultu)
1201     {
1202     uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1203     uint64_t hi = 0, lo = 0;
1204     for (; a; a >>= 1) {
1205     if (a & 1) {
1206     uint64_t old_lo = lo;
1207     hi += c;
1208     lo += b;
1209     if (lo < old_lo)
1210     hi ++;
1211     }
1212     c = (c << 1) | (b >> 63); b <<= 1;
1213     }
1214     reg(&cpu->cd.mips.lo) = lo;
1215     reg(&cpu->cd.mips.hi) = hi;
1216     }
1217     X(tge)
1218     {
1219     MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1220     if (a >= b) {
1221     /* Synch. PC and cause an exception: */
1222     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1223     / sizeof(struct mips_instr_call);
1224     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1225     << MIPS_INSTR_ALIGNMENT_SHIFT);
1226     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1227     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1228     }
1229     }
1230     X(tgeu)
1231     {
1232     MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1233     if (a >= b) {
1234     /* Synch. PC and cause an exception: */
1235     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1236     / sizeof(struct mips_instr_call);
1237     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1238     << MIPS_INSTR_ALIGNMENT_SHIFT);
1239     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1240     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1241     }
1242     }
1243     X(tlt)
1244     {
1245     MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1246     if (a < b) {
1247     /* Synch. PC and cause an exception: */
1248     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1249     / sizeof(struct mips_instr_call);
1250     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1251     << MIPS_INSTR_ALIGNMENT_SHIFT);
1252     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1253     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1254     }
1255     }
1256     X(tltu)
1257     {
1258     MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1259     if (a < b) {
1260     /* Synch. PC and cause an exception: */
1261     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1262     / sizeof(struct mips_instr_call);
1263     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1264     << MIPS_INSTR_ALIGNMENT_SHIFT);
1265     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1266     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1267     }
1268     }
1269     X(teq)
1270     {
1271     MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1272     if (a == b) {
1273     /* Synch. PC and cause an exception: */
1274     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1275     / sizeof(struct mips_instr_call);
1276     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1277     << MIPS_INSTR_ALIGNMENT_SHIFT);
1278     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1279     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1280     }
1281     }
1282     X(tne)
1283     {
1284     MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1285     if (a != b) {
1286     /* Synch. PC and cause an exception: */
1287     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1288     / sizeof(struct mips_instr_call);
1289     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1290     << MIPS_INSTR_ALIGNMENT_SHIFT);
1291     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1292     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1293     }
1294     }
1295 dpavlin 22
1296    
1297     /*
1298 dpavlin 24 * 3-register arithmetic instructions:
1299     *
1300     * arg[0] = ptr to rs
1301     * arg[1] = ptr to rt
1302     * arg[2] = ptr to rd
1303 dpavlin 22 */
1304     X(addu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) + reg(ic->arg[1])); }
1305 dpavlin 24 X(add)
1306     {
1307     int32_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1308     int32_t rd = rs + rt;
1309    
1310     if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1311     /* Synch. PC and cause an exception: */
1312     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1313     / sizeof(struct mips_instr_call);
1314     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1315     << MIPS_INSTR_ALIGNMENT_SHIFT);
1316     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1317     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1318     } else
1319     reg(ic->arg[2]) = rd;
1320     }
1321     X(daddu){ reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }
1322     X(dadd)
1323     {
1324     int64_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1325     int64_t rd = rs + rt;
1326    
1327     if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1328     /* Synch. PC and cause an exception: */
1329     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1330     / sizeof(struct mips_instr_call);
1331     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1332     << MIPS_INSTR_ALIGNMENT_SHIFT);
1333     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1334     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1335     } else
1336     reg(ic->arg[2]) = rd;
1337     }
1338 dpavlin 22 X(subu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) - reg(ic->arg[1])); }
1339 dpavlin 24 X(sub)
1340     {
1341     /* NOTE: Negating rt and using addition. TODO: Is this correct? */
1342     int32_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1343     int32_t rd = rs + rt;
1344    
1345     if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1346     /* Synch. PC and cause an exception: */
1347     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1348     / sizeof(struct mips_instr_call);
1349     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1350     << MIPS_INSTR_ALIGNMENT_SHIFT);
1351     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1352     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1353     } else
1354     reg(ic->arg[2]) = rd;
1355     }
1356     X(dsubu){ reg(ic->arg[2]) = reg(ic->arg[0]) - reg(ic->arg[1]); }
1357     X(dsub)
1358     {
1359     /* NOTE: Negating rt and using addition. TODO: Is this correct? */
1360     int64_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1361     int64_t rd = rs + rt;
1362    
1363     if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1364     /* Synch. PC and cause an exception: */
1365     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1366     / sizeof(struct mips_instr_call);
1367     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1368     << MIPS_INSTR_ALIGNMENT_SHIFT);
1369     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1370     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1371     } else
1372     reg(ic->arg[2]) = rd;
1373     }
1374 dpavlin 22 X(slt) {
1375 dpavlin 24 reg(ic->arg[2]) =
1376     (MODE_int_t)reg(ic->arg[0]) < (MODE_int_t)reg(ic->arg[1]);
1377 dpavlin 22 }
1378     X(sltu) {
1379 dpavlin 24 reg(ic->arg[2]) =
1380     (MODE_uint_t)reg(ic->arg[0]) < (MODE_uint_t)reg(ic->arg[1]);
1381 dpavlin 22 }
1382 dpavlin 24 X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
1383     X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
1384 dpavlin 22 X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
1385     X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }
1386 dpavlin 24 X(sll) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << (int32_t)ic->arg[1]); }
1387     X(sllv){ int32_t sa = reg(ic->arg[1]) & 31;
1388     reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << sa); }
1389 dpavlin 22 X(srl) { reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1390 dpavlin 24 X(srlv){ int32_t sa = reg(ic->arg[1]) & 31;
1391     reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> sa); }
1392 dpavlin 22 X(sra) { reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1393 dpavlin 24 X(srav){ int32_t sa = reg(ic->arg[1]) & 31;
1394     reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> sa); }
1395     X(dsll) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) << (int64_t)ic->arg[1]; }
1396     X(dsllv){ int64_t sa = reg(ic->arg[1]) & 63;
1397     reg(ic->arg[2]) = reg(ic->arg[0]) << sa; }
1398     X(dsrl) { reg(ic->arg[2]) = (int64_t)((uint64_t)reg(ic->arg[0]) >>
1399     (uint64_t) ic->arg[1]);}
1400     X(dsrlv){ int64_t sa = reg(ic->arg[1]) & 63;
1401     reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) >> sa; }
1402     X(dsra) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> (int64_t)ic->arg[1]; }
1403     X(dsrav){ int64_t sa = reg(ic->arg[1]) & 63;
1404     reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> sa; }
1405 dpavlin 22 X(mul) { reg(ic->arg[2]) = (int32_t)
1406     ( (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]) ); }
1407 dpavlin 24 X(movn) { if (reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1408     X(movz) { if (!reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1409 dpavlin 22
1410    
1411     /*
1412 dpavlin 24 * p*: 128-bit C790/TX79/R5900 stuff
1413     *
1414     * arg[0] = rs (note: not a pointer)
1415     * arg[1] = rt (note: not a pointer)
1416     * arg[2] = rd (note: not a pointer)
1417     */
1418     X(por)
1419     {
1420     cpu->cd.mips.gpr[ic->arg[2]] = cpu->cd.mips.gpr[ic->arg[0]] |
1421     cpu->cd.mips.gpr[ic->arg[1]];
1422     cpu->cd.mips.gpr_quadhi[ic->arg[2]] =
1423     cpu->cd.mips.gpr_quadhi[ic->arg[0]] |
1424     cpu->cd.mips.gpr_quadhi[ic->arg[1]];
1425     }
1426     X(pextlw)
1427     {
1428     uint64_t lo, hi;
1429    
1430     lo = (uint32_t)cpu->cd.mips.gpr[ic->arg[1]] |
1431     (uint64_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[0]] << 32);
1432     hi = (cpu->cd.mips.gpr[ic->arg[0]] & 0xffffffff00000000ULL) |
1433     (uint32_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[1]] >> 32);
1434    
1435     cpu->cd.mips.gpr[ic->arg[2]] = lo;
1436     cpu->cd.mips.gpr_quadhi[ic->arg[2]] = hi;
1437     }
1438    
1439    
1440     /*
1441     * madd, maddu, msub, msubu: Multiply-and-add/subtract
1442     *
1443     * arg[0] = ptr to rs
1444     * arg[1] = ptr to rt
1445     * arg[2] = ptr to rd (only used on R5900/TX79)
1446     */
1447     X(madd)
1448     {
1449     int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1450     int64_t sum = rs * rt,
1451     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1452     hilo += sum;
1453     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1454     }
1455     X(madd_rd)
1456     {
1457     int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1458     int64_t sum = rs * rt,
1459     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1460     hilo += sum;
1461     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1462     reg(ic->arg[2]) = (int32_t)hilo;
1463     }
1464     X(msub)
1465     {
1466     int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1467     int64_t sum = rs * rt,
1468     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1469     hilo -= sum;
1470     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1471     }
1472     X(maddu)
1473     {
1474     int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1475     int64_t sum = rs * rt,
1476     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1477     hilo += sum;
1478     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1479     }
1480     X(maddu_rd)
1481     {
1482     int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1483     int64_t sum = rs * rt,
1484     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1485     hilo += sum;
1486     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1487     reg(ic->arg[2]) = (int32_t)hilo;
1488     }
1489     X(msubu)
1490     {
1491     int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1492     int64_t sum = rs * rt,
1493     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1494     hilo -= sum;
1495     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1496     }
1497    
1498    
1499     /*
1500 dpavlin 22 * mov: Move one register into another.
1501     *
1502     * arg[0] = pointer to source
1503     * arg[2] = pointer to destination
1504     */
1505     X(mov) { reg(ic->arg[2]) = reg(ic->arg[0]); }
1506    
1507    
1508     /*
1509     * clz, clo, dclz, dclo: Count leading zeroes/ones.
1510     *
1511     * arg[0] = pointer to rs
1512     * arg[1] = pointer to rd
1513     */
1514     X(clz)
1515     {
1516     uint32_t x = reg(ic->arg[0]);
1517     int count;
1518     for (count=0; count<32; count++) {
1519     if (x & 0x80000000UL)
1520     break;
1521     x <<= 1;
1522     }
1523     reg(ic->arg[1]) = count;
1524     }
1525     X(clo)
1526     {
1527     uint32_t x = reg(ic->arg[0]);
1528     int count;
1529     for (count=0; count<32; count++) {
1530     if (!(x & 0x80000000UL))
1531     break;
1532     x <<= 1;
1533     }
1534     reg(ic->arg[1]) = count;
1535     }
1536     X(dclz)
1537     {
1538     uint64_t x = reg(ic->arg[0]);
1539     int count;
1540     for (count=0; count<64; count++) {
1541     if (x & 0x8000000000000000ULL)
1542     break;
1543     x <<= 1;
1544     }
1545     reg(ic->arg[1]) = count;
1546     }
1547     X(dclo)
1548     {
1549     uint64_t x = reg(ic->arg[0]);
1550     int count;
1551     for (count=0; count<64; count++) {
1552     if (!(x & 0x8000000000000000ULL))
1553     break;
1554     x <<= 1;
1555     }
1556     reg(ic->arg[1]) = count;
1557     }
1558    
1559    
1560     /*
1561 dpavlin 24 * addi, daddi: Add immediate, overflow detection.
1562     * addiu, daddiu: Add immediate.
1563     * slti: Set if less than immediate (signed 32-bit)
1564     * sltiu: Set if less than immediate (signed 32-bit, but unsigned compare)
1565 dpavlin 22 *
1566     * arg[0] = pointer to rs
1567     * arg[1] = pointer to rt
1568     * arg[2] = (int32_t) immediate value
1569     */
1570 dpavlin 24 X(addi)
1571     {
1572     int32_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1573     int32_t rt = rs + imm;
1574    
1575     if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1576     /* Synch. PC and cause an exception: */
1577     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1578     / sizeof(struct mips_instr_call);
1579     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1580     << MIPS_INSTR_ALIGNMENT_SHIFT);
1581     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1582     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1583     } else
1584     reg(ic->arg[1]) = rt;
1585     }
1586 dpavlin 22 X(addiu)
1587     {
1588     reg(ic->arg[1]) = (int32_t)
1589     ((int32_t)reg(ic->arg[0]) + (int32_t)ic->arg[2]);
1590     }
1591 dpavlin 24 X(daddi)
1592     {
1593     int64_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1594     int64_t rt = rs + imm;
1595 dpavlin 22
1596 dpavlin 24 if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1597     /* Synch. PC and cause an exception: */
1598     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1599     / sizeof(struct mips_instr_call);
1600     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1601     << MIPS_INSTR_ALIGNMENT_SHIFT);
1602     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1603     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1604     } else
1605     reg(ic->arg[1]) = rt;
1606     }
1607 dpavlin 22 X(daddiu)
1608     {
1609     reg(ic->arg[1]) = reg(ic->arg[0]) + (int32_t)ic->arg[2];
1610     }
1611 dpavlin 24 X(slti)
1612     {
1613     reg(ic->arg[1]) = (MODE_int_t)reg(ic->arg[0]) < (int32_t)ic->arg[2];
1614     }
1615     X(sltiu)
1616     {
1617     reg(ic->arg[1]) = (MODE_uint_t)reg(ic->arg[0]) <
1618     ((MODE_uint_t)(int32_t)ic->arg[2]);
1619     }
1620 dpavlin 22
1621    
1622     /*
1623     * set: Set a register to an immediate (signed) 32-bit value.
1624     *
1625     * arg[0] = pointer to the register
1626     * arg[1] = (int32_t) immediate value
1627     */
1628     X(set)
1629     {
1630     reg(ic->arg[0]) = (int32_t)ic->arg[1];
1631     }
1632    
1633    
1634     /*
1635 dpavlin 24 * cfc0: Copy from Coprocessor 0.
1636 dpavlin 22 * mfc0, dmfc0: Move from Coprocessor 0.
1637     * mtc0, dmtc0: Move to Coprocessor 0.
1638     *
1639     * arg[0] = pointer to GPR (rt)
1640 dpavlin 24 * arg[1] = coprocessor 0 register number | (select << 5) (or for the
1641     * cfc0 instruction, the coprocessor control register number)
1642 dpavlin 22 * arg[2] = relative addr of this instruction within the page
1643     */
1644 dpavlin 24 X(cfc0)
1645     {
1646     int fs = ic->arg[1] & 31;
1647     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1648     cpu->pc |= ic->arg[2];
1649     /* TODO: cause exception if necessary */
1650     reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->fcr[fs];
1651     }
1652 dpavlin 22 X(mfc0)
1653     {
1654     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1655     uint64_t tmp;
1656     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1657     cpu->pc |= ic->arg[2];
1658     /* TODO: cause exception if necessary */
1659     coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select);
1660     reg(ic->arg[0]) = (int32_t)tmp;
1661     }
1662     X(mtc0)
1663     {
1664     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1665 dpavlin 24 uint64_t tmp = (int32_t) reg(ic->arg[0]);
1666 dpavlin 26
1667 dpavlin 22 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1668     cpu->pc |= ic->arg[2];
1669 dpavlin 24
1670 dpavlin 22 /* TODO: cause exception if necessary */
1671 dpavlin 24 coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd, &tmp, 0, select);
1672    
1673 dpavlin 26 /*
1674     * Interrupts enabled, and any interrupt pending? (Note/TODO: This
1675     * code is duplicated in cpu_dyntrans.c. Fix this?)
1676     */
1677     if (rd == COP0_STATUS && !cpu->delay_slot) {
1678 dpavlin 24 uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1679     uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1680     /* NOTE: STATUS_IE happens to match the enable bit also
1681     on R2000/R3000, so this is ok. */
1682 dpavlin 30 if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1683     if (status & (STATUS_EXL | STATUS_ERL))
1684     status &= ~STATUS_IE;
1685     }
1686 dpavlin 26 /* Ugly R5900 special case: (TODO: move this?) */
1687     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1688     !(status & R5900_STATUS_EIE))
1689     status &= ~STATUS_IE;
1690     if (status & STATUS_IE && (status & cause & STATUS_IM_MASK)) {
1691     cpu->pc += sizeof(uint32_t);
1692     mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0,0,0,0,0);
1693     }
1694 dpavlin 24 }
1695 dpavlin 22 }
1696     X(dmfc0)
1697     {
1698     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1699     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1700     cpu->pc |= ic->arg[2];
1701     /* TODO: cause exception if necessary */
1702     coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,
1703     (uint64_t *)ic->arg[0], select);
1704     }
1705     X(dmtc0)
1706     {
1707     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1708     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1709     cpu->pc |= ic->arg[2];
1710     /* TODO: cause exception if necessary */
1711     coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,
1712     (uint64_t *)ic->arg[0], 1, select);
1713     }
1714 dpavlin 24
1715    
1716     /*
1717     * cop1_bc: Floating point conditional branch.
1718     *
1719     * arg[0] = cc
1720     * arg[1] = nd (=2) and tf (=1) bits
1721     * arg[2] = offset (relative to start of this page)
1722     */
1723     X(cop1_bc)
1724 dpavlin 22 {
1725 dpavlin 24 MODE_int_t old_pc = cpu->pc;
1726     const int cpnr = 1;
1727     int x, low_pc, cc = ic->arg[0];
1728    
1729     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     if (!(cpu->cd.mips.coproc[0]->
1734     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1735     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1736     return;
1737     }
1738    
1739     /* Get the correct condition code bit: */
1740     if (cc == 0)
1741     x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1742     >> MIPS_FCSR_FCC0_SHIFT) & 1;
1743     else
1744     x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1745     >> (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;
1746    
1747     /* Branch on false? Then invert the truth value. */
1748     if (!(ic->arg[1] & 1))
1749     x ^= 1;
1750    
1751     /* Execute the delay slot (except if it is nullified): */
1752     cpu->delay_slot = TO_BE_DELAYED;
1753     if (x || !(ic->arg[1] & 2))
1754     ic[1].f(cpu, ic+1);
1755     cpu->n_translated_instrs ++;
1756    
1757     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1758     /* Note: Must be non-delayed when jumping to the new pc: */
1759     cpu->delay_slot = NOT_DELAYED;
1760     if (x) {
1761     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1762     MIPS_INSTR_ALIGNMENT_SHIFT);
1763     cpu->pc = old_pc + (int32_t)ic->arg[2];
1764     quick_pc_to_pointers(cpu);
1765     } else
1766     cpu->cd.mips.next_ic ++;
1767     } else
1768     cpu->delay_slot = NOT_DELAYED;
1769     }
1770    
1771    
1772     /*
1773     * cop1_slow: Fallback to legacy cop1 code. (Slow, but it should work.)
1774     */
1775     X(cop1_slow)
1776     {
1777     const int cpnr = 1;
1778     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1779     / sizeof(struct mips_instr_call);
1780     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1781     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1782    
1783     if (!(cpu->cd.mips.coproc[0]->
1784     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1785     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1786     return;
1787     }
1788    
1789     coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1790     }
1791    
1792    
1793     /*
1794     * syscall, break: Synchronize the PC and cause an exception.
1795     */
1796     X(syscall)
1797     {
1798     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1799     / sizeof(struct mips_instr_call);
1800     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1801     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1802     mips_cpu_exception(cpu, EXCEPTION_SYS, 0, 0, 0, 0, 0, 0);
1803     }
1804     X(break)
1805     {
1806     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1807     / sizeof(struct mips_instr_call);
1808     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1809     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1810     mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1811     }
1812 dpavlin 30 X(reboot)
1813     {
1814     cpu->running = 0;
1815     debugger_n_steps_left_before_interaction = 0;
1816     cpu->cd.mips.next_ic = &nothing_call;
1817     }
1818 dpavlin 24
1819    
1820     /*
1821     * promemul: PROM software emulation.
1822     */
1823     X(promemul)
1824     {
1825     /* Synchronize the PC and call the correct emulation layer: */
1826     MODE_int_t old_pc;
1827     int res, low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1828     / sizeof(struct mips_instr_call);
1829     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1830     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1831     old_pc = cpu->pc;
1832    
1833     switch (cpu->machine->machine_type) {
1834     case MACHINE_PMAX:
1835     res = decstation_prom_emul(cpu);
1836     break;
1837     case MACHINE_PS2:
1838     res = playstation2_sifbios_emul(cpu);
1839     break;
1840     case MACHINE_ARC:
1841     case MACHINE_SGI:
1842     res = arcbios_emul(cpu);
1843     break;
1844     case MACHINE_EVBMIPS:
1845     res = yamon_emul(cpu);
1846     break;
1847     default:fatal("TODO: Unimplemented machine type for PROM magic trap\n");
1848     exit(1);
1849     }
1850    
1851     if (res) {
1852     /* Return from the PROM call: */
1853     cpu->pc = (MODE_int_t)cpu->cd.mips.gpr[MIPS_GPR_RA];
1854     cpu->delay_slot = NOT_DELAYED;
1855    
1856     if (cpu->machine->show_trace_tree)
1857     cpu_functioncall_trace_return(cpu);
1858     } else {
1859     /* The PROM call blocks. */
1860     cpu->n_translated_instrs += 10;
1861     cpu->pc = old_pc;
1862     }
1863    
1864     quick_pc_to_pointers(cpu);
1865     }
1866    
1867    
1868     /*
1869     * tlbw: TLB write indexed and random
1870     *
1871     * arg[0] = 1 for random, 0 for indexed
1872     * arg[2] = relative addr of this instruction within the page
1873     */
1874     X(tlbw)
1875     {
1876 dpavlin 22 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1877     cpu->pc |= ic->arg[2];
1878 dpavlin 24 coproc_tlbwri(cpu, ic->arg[0]);
1879 dpavlin 22 }
1880    
1881    
1882 dpavlin 24 /*
1883     * tlbp: TLB probe
1884     * tlbr: TLB read
1885     *
1886     * arg[2] = relative addr of this instruction within the page
1887     */
1888     X(tlbp)
1889     {
1890     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1891     cpu->pc |= ic->arg[2];
1892     coproc_tlbpr(cpu, 0);
1893     }
1894     X(tlbr)
1895     {
1896     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1897     cpu->pc |= ic->arg[2];
1898     coproc_tlbpr(cpu, 1);
1899     }
1900    
1901    
1902     /*
1903     * rfe: Return from exception handler (R2000/R3000)
1904     */
1905     X(rfe)
1906     {
1907 dpavlin 28 /* Just rotate the interrupt/user bits: */
1908     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
1909     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
1910     ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
1911 dpavlin 24
1912 dpavlin 28 /*
1913     * Note: no pc to pointers conversion is necessary here. Usually the
1914     * rfe instruction resides in the delay slot of a jr k0/k1, and
1915     * it is up to that instruction to do the pointer conversion.
1916     */
1917 dpavlin 24 }
1918    
1919    
1920     /*
1921 dpavlin 28 * eret: Return from exception handler (non-R3000 style)
1922 dpavlin 24 */
1923     X(eret)
1924     {
1925 dpavlin 28 if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
1926     cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
1927     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
1928     } else {
1929     cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
1930     cpu->delay_slot = 0;
1931     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1932     }
1933    
1934 dpavlin 24 quick_pc_to_pointers(cpu);
1935 dpavlin 28
1936     cpu->cd.mips.rmw = 0; /* the "LL bit" */
1937 dpavlin 24 }
1938    
1939    
1940     /*
1941     * deret: Return from debug (EJTAG) handler
1942     */
1943     X(deret)
1944     {
1945     /*
1946     * According to the MIPS64 manual, deret loads PC from the DEPC cop0
1947     * register, and jumps there immediately. No delay slot.
1948     *
1949     * TODO: This instruction is only available if the processor is in
1950     * debug mode. (What does that mean?)
1951     *
1952     * TODO: This instruction is undefined in a delay slot.
1953     */
1954    
1955     cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_DEPC];
1956     cpu->delay_slot = 0;
1957     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1958     quick_pc_to_pointers(cpu);
1959     }
1960    
1961    
1962     /*
1963 dpavlin 30 * wait: Wait for external interrupt.
1964     */
1965     X(wait)
1966     {
1967     /*
1968     * If there is an interrupt, then just return. Otherwise
1969     * re-run the wait instruction (after a delay).
1970     */
1971     uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1972     uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1973    
1974     /* NOTE: STATUS_IE happens to match the enable bit also
1975     on R2000/R3000, so this is ok. */
1976     if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1977     if (status & (STATUS_EXL | STATUS_ERL))
1978     status &= ~STATUS_IE;
1979     }
1980     /* Ugly R5900 special case: (TODO: move this?) */
1981     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1982     !(status & R5900_STATUS_EIE))
1983     status &= ~STATUS_IE;
1984     if (status & STATUS_IE && (status & cause & STATUS_IM_MASK))
1985     return;
1986    
1987     cpu->cd.mips.next_ic = ic;
1988     cpu->is_halted = 1;
1989    
1990     /*
1991     * There was no interrupt. Go to sleep.
1992     *
1993     * TODO:
1994     *
1995     * Think about how to actually implement this usleep stuff,
1996     * in an SMP and/or timing accurate environment.
1997     */
1998    
1999     if (cpu->machine->ncpus == 1) {
2000     static int x = 0;
2001     if ((++x) == 600) {
2002     usleep(1);
2003     x = 0;
2004     }
2005     cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
2006     }
2007     }
2008    
2009    
2010     /*
2011 dpavlin 24 * rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
2012     *
2013     * arg[0] = ptr to rt (destination register)
2014     */
2015     X(rdhwr_cpunum)
2016     {
2017     reg(ic->arg[0]) = cpu->cpu_id;
2018     }
2019    
2020    
2021     #include "tmp_mips_loadstore.c"
2022    
2023    
2024     /*
2025     * Load linked / store conditional:
2026     *
2027     * A Load-linked instruction initiates a RMW (read-modify-write) sequence.
2028     * COP0_LLADDR is updated for diagnostic purposes, except for CPUs in the
2029     * R10000 family.
2030     *
2031     * A Store-conditional instruction ends the sequence.
2032     *
2033     * arg[0] = ptr to rt
2034     * arg[1] = ptr to rs
2035     * arg[2] = int32_t imm
2036     */
2037     X(ll)
2038     {
2039     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2040     int low_pc;
2041     uint8_t word[sizeof(uint32_t)];
2042    
2043     /* Synch. PC and load using slow memory_rw(): */
2044     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2045     / sizeof(struct mips_instr_call);
2046     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2047     << MIPS_INSTR_ALIGNMENT_SHIFT);
2048     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2049    
2050     if (addr & (sizeof(word)-1)) {
2051     fatal("TODO: load linked unaligned access: exception\n");
2052     exit(1);
2053     }
2054    
2055     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2056     sizeof(word), MEM_READ, CACHE_DATA)) {
2057     /* An exception occurred. */
2058     return;
2059     }
2060    
2061     cpu->cd.mips.rmw = 1;
2062     cpu->cd.mips.rmw_addr = addr;
2063     cpu->cd.mips.rmw_len = sizeof(word);
2064     if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2065     cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2066     (addr >> 4) & 0xffffffffULL;
2067    
2068     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2069     reg(ic->arg[0]) = (int32_t) (word[0] + (word[1] << 8)
2070     + (word[2] << 16) + (word[3] << 24));
2071     else
2072     reg(ic->arg[0]) = (int32_t) (word[3] + (word[2] << 8)
2073     + (word[1] << 16) + (word[0] << 24));
2074     }
2075     X(lld)
2076     {
2077     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2078     int low_pc;
2079     uint8_t word[sizeof(uint64_t)];
2080    
2081     /* Synch. PC and load using slow memory_rw(): */
2082     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2083     / sizeof(struct mips_instr_call);
2084     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2085     << MIPS_INSTR_ALIGNMENT_SHIFT);
2086     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2087    
2088     if (addr & (sizeof(word)-1)) {
2089     fatal("TODO: load linked unaligned access: exception\n");
2090     exit(1);
2091     }
2092    
2093     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2094     sizeof(word), MEM_READ, CACHE_DATA)) {
2095     /* An exception occurred. */
2096     return;
2097     }
2098    
2099     cpu->cd.mips.rmw = 1;
2100     cpu->cd.mips.rmw_addr = addr;
2101     cpu->cd.mips.rmw_len = sizeof(word);
2102     if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2103     cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2104     (addr >> 4) & 0xffffffffULL;
2105    
2106     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2107     reg(ic->arg[0]) = word[0] + (word[1] << 8)
2108     + (word[2] << 16) + ((uint64_t)word[3] << 24) +
2109     + ((uint64_t)word[4] << 32) + ((uint64_t)word[5] << 40)
2110     + ((uint64_t)word[6] << 48) + ((uint64_t)word[7] << 56);
2111     else
2112     reg(ic->arg[0]) = word[7] + (word[6] << 8)
2113     + (word[5] << 16) + ((uint64_t)word[4] << 24) +
2114     + ((uint64_t)word[3] << 32) + ((uint64_t)word[2] << 40)
2115     + ((uint64_t)word[1] << 48) + ((uint64_t)word[0] << 56);
2116     }
2117     X(sc)
2118     {
2119     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2120     uint64_t r = reg(ic->arg[0]);
2121     int low_pc, i;
2122     uint8_t word[sizeof(uint32_t)];
2123    
2124     /* Synch. PC and store using slow memory_rw(): */
2125     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2126     / sizeof(struct mips_instr_call);
2127     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2128     << MIPS_INSTR_ALIGNMENT_SHIFT);
2129     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2130    
2131     if (addr & (sizeof(word)-1)) {
2132     fatal("TODO: sc unaligned access: exception\n");
2133     exit(1);
2134     }
2135    
2136     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2137     word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2138     } else {
2139     word[3]=r; word[2]=r>>8; word[1]=r>>16; word[0]=r>>24;
2140     }
2141    
2142     /* If rmw is 0, then the store failed. (This cache-line was written
2143     to by someone else.) */
2144     if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2145     || cpu->cd.mips.rmw_len != sizeof(word)) {
2146     reg(ic->arg[0]) = 0;
2147     cpu->cd.mips.rmw = 0;
2148     return;
2149     }
2150    
2151     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2152     sizeof(word), MEM_WRITE, CACHE_DATA)) {
2153     /* An exception occurred. */
2154     return;
2155     }
2156    
2157     /* We succeeded. Let's invalidate everybody else's store to this
2158     cache line: */
2159     for (i=0; i<cpu->machine->ncpus; i++) {
2160     if (cpu->machine->cpus[i]->cd.mips.rmw) {
2161     uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2162     cd.mips.rmw_addr;
2163     uint64_t mask = ~(cpu->machine->cpus[i]->
2164     cd.mips.cache_linesize[CACHE_DATA] - 1);
2165     xaddr &= mask;
2166     yaddr &= mask;
2167     if (xaddr == yaddr)
2168     cpu->machine->cpus[i]->cd.mips.rmw = 0;
2169     }
2170     }
2171    
2172     reg(ic->arg[0]) = 1;
2173     cpu->cd.mips.rmw = 0;
2174     }
2175     X(scd)
2176     {
2177     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2178     uint64_t r = reg(ic->arg[0]);
2179     int low_pc, i;
2180     uint8_t word[sizeof(uint64_t)];
2181    
2182     /* Synch. PC and store using slow memory_rw(): */
2183     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2184     / sizeof(struct mips_instr_call);
2185     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2186     << MIPS_INSTR_ALIGNMENT_SHIFT);
2187     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2188    
2189     if (addr & (sizeof(word)-1)) {
2190     fatal("TODO: sc unaligned access: exception\n");
2191     exit(1);
2192     }
2193    
2194     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2195     word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2196     word[4]=r>>32; word[5]=r>>40; word[6]=r>>48; word[7]=r>>56;
2197     } else {
2198     word[7]=r; word[6]=r>>8; word[5]=r>>16; word[4]=r>>24;
2199     word[3]=r>>32; word[2]=r>>40; word[1]=r>>48; word[0]=r>>56;
2200     }
2201    
2202     /* If rmw is 0, then the store failed. (This cache-line was written
2203     to by someone else.) */
2204     if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2205     || cpu->cd.mips.rmw_len != sizeof(word)) {
2206     reg(ic->arg[0]) = 0;
2207     cpu->cd.mips.rmw = 0;
2208     return;
2209     }
2210    
2211     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2212     sizeof(word), MEM_WRITE, CACHE_DATA)) {
2213     /* An exception occurred. */
2214     return;
2215     }
2216    
2217     /* We succeeded. Let's invalidate everybody else's store to this
2218     cache line: */
2219     for (i=0; i<cpu->machine->ncpus; i++) {
2220     if (cpu->machine->cpus[i]->cd.mips.rmw) {
2221     uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2222     cd.mips.rmw_addr;
2223     uint64_t mask = ~(cpu->machine->cpus[i]->
2224     cd.mips.cache_linesize[CACHE_DATA] - 1);
2225     xaddr &= mask;
2226     yaddr &= mask;
2227     if (xaddr == yaddr)
2228     cpu->machine->cpus[i]->cd.mips.rmw = 0;
2229     }
2230     }
2231    
2232     reg(ic->arg[0]) = 1;
2233     cpu->cd.mips.rmw = 0;
2234     }
2235    
2236    
2237     /*
2238     * lwc1, swc1: Coprocessor 1 load/store (32-bit)
2239     * ldc1, sdc1: Coprocessor 1 load/store (64-bit)
2240     *
2241     * arg[0] = ptr to coprocessor register
2242     * arg[1] = ptr to rs (base pointer register)
2243     * arg[2] = int32_t imm
2244     */
2245     X(lwc1)
2246     {
2247     const int cpnr = 1;
2248    
2249     /* Synch. PC and call the generic load/store function: */
2250     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2251     / sizeof(struct mips_instr_call);
2252     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2253     << MIPS_INSTR_ALIGNMENT_SHIFT);
2254     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2255    
2256     /* ... but first, let's see if the coprocessor is available: */
2257     if (!(cpu->cd.mips.coproc[0]->
2258     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2259     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2260     return;
2261     }
2262    
2263     #ifdef MODE32
2264     mips32_loadstore
2265     #else
2266     mips_loadstore
2267     #endif
2268     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 2 * 2 + 1]
2269     (cpu, ic);
2270     }
2271     X(swc1)
2272     {
2273     const int cpnr = 1;
2274    
2275     /* Synch. PC and call the generic load/store function: */
2276     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2277     / sizeof(struct mips_instr_call);
2278     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2279     << MIPS_INSTR_ALIGNMENT_SHIFT);
2280     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2281    
2282     /* ... but first, let's see if the coprocessor is available: */
2283     if (!(cpu->cd.mips.coproc[0]->
2284     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2285     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2286     return;
2287     }
2288    
2289     #ifdef MODE32
2290     mips32_loadstore
2291     #else
2292     mips_loadstore
2293     #endif
2294     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 2 * 2]
2295     (cpu, ic);
2296     }
2297     X(ldc1)
2298     {
2299     const int cpnr = 1;
2300     int use_fp_pairs =
2301     !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2302     uint64_t fpr, *backup_ptr;
2303    
2304     /* Synch. PC and call the generic load/store function: */
2305     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2306     / sizeof(struct mips_instr_call);
2307     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2308     << MIPS_INSTR_ALIGNMENT_SHIFT);
2309     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2310    
2311     /* ... but first, let's see if the coprocessor is available: */
2312     if (!(cpu->cd.mips.coproc[0]->
2313     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2314     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2315     return;
2316     }
2317    
2318     backup_ptr = (uint64_t *) ic->arg[0];
2319     ic->arg[0] = (size_t) &fpr;
2320    
2321     #ifdef MODE32
2322     mips32_loadstore
2323     #else
2324     mips_loadstore
2325     #endif
2326     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 3 * 2 + 1]
2327     (cpu, ic);
2328    
2329     if (use_fp_pairs) {
2330     backup_ptr[0] = (int64_t)(int32_t) fpr;
2331     backup_ptr[1] = (int64_t)(int32_t) (fpr >> 32);
2332     } else {
2333     *backup_ptr = fpr;
2334     }
2335    
2336     ic->arg[0] = (size_t) backup_ptr;
2337     }
2338     X(sdc1)
2339     {
2340     const int cpnr = 1;
2341     int use_fp_pairs =
2342     !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2343     uint64_t fpr, *backup_ptr;
2344    
2345     /* Synch. PC and call the generic load/store function: */
2346     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2347     / sizeof(struct mips_instr_call);
2348     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2349     << MIPS_INSTR_ALIGNMENT_SHIFT);
2350     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2351    
2352     /* ... but first, let's see if the coprocessor is available: */
2353     if (!(cpu->cd.mips.coproc[0]->
2354     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2355     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2356     return;
2357     }
2358    
2359     backup_ptr = (uint64_t *) ic->arg[0];
2360     ic->arg[0] = (size_t) &fpr;
2361    
2362     if (use_fp_pairs) {
2363     uint32_t lo = backup_ptr[0];
2364     uint32_t hi = backup_ptr[1];
2365     fpr = (((uint64_t)hi) << 32) | lo;
2366     } else {
2367     fpr = *backup_ptr;
2368     }
2369    
2370     #ifdef MODE32
2371     mips32_loadstore
2372     #else
2373     mips_loadstore
2374     #endif
2375     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 3 * 2]
2376     (cpu, ic);
2377    
2378     ic->arg[0] = (size_t) backup_ptr;
2379     }
2380    
2381    
2382     /*
2383     * Unaligned loads/stores:
2384     *
2385     * arg[0] = ptr to rt
2386     * arg[1] = ptr to rs
2387     * arg[2] = int32_t imm
2388     */
2389     X(lwl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 0); }
2390     X(lwr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 0); }
2391     X(ldl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 0); }
2392     X(ldr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 0); }
2393     X(swl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 1); }
2394     X(swr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 1); }
2395     X(sdl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 1); }
2396     X(sdr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 1); }
2397    
2398    
2399     /*
2400     * di, ei: R5900 interrupt enable/disable.
2401     *
2402     * TODO: check the R5900_STATUS_EDI bit in the status register. If it is
2403     * cleared, and we are not running in kernel mode, then both the EI and DI
2404     * instructions should be treated as NOPs!
2405     */
2406     X(di_r5900)
2407     {
2408     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2409     }
2410     X(ei_r5900)
2411     {
2412     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2413     }
2414    
2415    
2416 dpavlin 22 /*****************************************************************************/
2417    
2418    
2419     /*
2420 dpavlin 28 * sw_loop:
2421     *
2422     * s: addiu rX,rX,4 rX = arg[0] and arg[1]
2423     * bne rY,rX,s (or rX,rY,s) rt=arg[1], rs=arg[0]
2424     * sw rZ,-4(rX) rt=arg[0], rs=arg[1]
2425     */
2426     X(sw_loop)
2427     {
2428     MODE_uint_t rX = reg(ic->arg[0]), rZ = reg(ic[2].arg[0]);
2429     uint64_t *rYp = (uint64_t *) ic[1].arg[0];
2430     MODE_uint_t rY, bytes_to_write;
2431     unsigned char *page;
2432     int partial = 0;
2433    
2434     page = cpu->cd.mips.host_store[rX >> 12];
2435    
2436     /* Fallback: */
2437     if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2438     instr(addiu)(cpu, ic);
2439     return;
2440 dpavlin 30 }
2441 dpavlin 28
2442     if (rYp == (uint64_t *) ic->arg[0])
2443     rYp = (uint64_t *) ic[1].arg[1];
2444    
2445     rY = reg(rYp);
2446    
2447     bytes_to_write = rY - rX;
2448     if ((rX & 0xfff) + bytes_to_write > 0x1000) {
2449     bytes_to_write = 0x1000 - (rX & 0xfff);
2450     partial = 1;
2451     }
2452    
2453     /* printf("rX = %08x\n", (int)rX);
2454     printf("rY = %08x\n", (int)rY);
2455     printf("rZ = %08x\n", (int)rZ);
2456     printf("%i bytes\n", (int)bytes_to_write); */
2457    
2458     memset(page + (rX & 0xfff), 0, bytes_to_write);
2459    
2460     reg(ic->arg[0]) = rX + bytes_to_write;
2461    
2462     cpu->n_translated_instrs += bytes_to_write / 4 * 3 - 1;
2463     cpu->cd.mips.next_ic = partial?
2464     (struct mips_instr_call *) &ic[0] :
2465     (struct mips_instr_call *) &ic[3];
2466     }
2467    
2468    
2469 dpavlin 30 #ifdef MODE32
2470 dpavlin 28 /*
2471 dpavlin 30 * multi_sw_2, _3, _4:
2472 dpavlin 28 *
2473     * sw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2]
2474     */
2475 dpavlin 30 X(multi_sw_2_le)
2476     {
2477     uint32_t *page;
2478     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2479     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2480     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2481     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2482    
2483     page = (uint32_t *) cpu->cd.mips.host_store[index0];
2484    
2485     /* Fallback: */
2486     if (cpu->delay_slot ||
2487     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2488     index0 != index1) {
2489     /* Normal safe sw: */
2490     mips32_loadstore[8 + 2 * 2](cpu, ic);
2491     return;
2492     }
2493    
2494     addr0 = (addr0 >> 2) & 0x3ff;
2495     addr1 = (addr1 >> 2) & 0x3ff;
2496    
2497     r1 = reg(ic[0].arg[0]);
2498     r2 = reg(ic[1].arg[0]);
2499    
2500     r1 = LE32_TO_HOST(r1);
2501     r2 = LE32_TO_HOST(r2);
2502    
2503     page[addr0] = r1;
2504     page[addr1] = r2;
2505    
2506     cpu->n_translated_instrs ++;
2507     cpu->cd.mips.next_ic ++;
2508     }
2509     X(multi_sw_2_be)
2510     {
2511     uint32_t *page;
2512     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2513     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2514     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2515     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2516    
2517     page = (uint32_t *) cpu->cd.mips.host_store[index0];
2518    
2519     /* Fallback: */
2520     if (cpu->delay_slot ||
2521     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2522     index0 != index1) {
2523     /* Normal safe sw: */
2524     mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2525     return;
2526     }
2527    
2528     addr0 = (addr0 >> 2) & 0x3ff;
2529     addr1 = (addr1 >> 2) & 0x3ff;
2530    
2531     r1 = reg(ic[0].arg[0]);
2532     r2 = reg(ic[1].arg[0]);
2533    
2534     r1 = BE32_TO_HOST(r1);
2535     r2 = BE32_TO_HOST(r2);
2536    
2537     page[addr0] = r1;
2538     page[addr1] = r2;
2539    
2540     cpu->n_translated_instrs ++;
2541     cpu->cd.mips.next_ic ++;
2542     }
2543 dpavlin 28 X(multi_sw_3_le)
2544     {
2545     uint32_t *page;
2546     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2547     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2548     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2549     MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2550     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2551     index2 = addr2 >> 12;
2552    
2553     page = (uint32_t *) cpu->cd.mips.host_store[index0];
2554    
2555     /* Fallback: */
2556     if (cpu->delay_slot ||
2557     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2558     (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2559     /* Normal safe sw: */
2560 dpavlin 30 mips32_loadstore[8 + 2 * 2](cpu, ic);
2561 dpavlin 28 return;
2562     }
2563    
2564     addr0 = (addr0 >> 2) & 0x3ff;
2565     addr1 = (addr1 >> 2) & 0x3ff;
2566     addr2 = (addr2 >> 2) & 0x3ff;
2567    
2568     /* printf("addr0=%x 1=%x 2=%x\n",
2569     (int)addr0, (int)addr1, (int)addr2); */
2570    
2571     r1 = reg(ic[0].arg[0]);
2572     r2 = reg(ic[1].arg[0]);
2573     r3 = reg(ic[2].arg[0]);
2574    
2575     r1 = LE32_TO_HOST(r1);
2576     r2 = LE32_TO_HOST(r2);
2577     r3 = LE32_TO_HOST(r3);
2578    
2579     page[addr0] = r1;
2580     page[addr1] = r2;
2581     page[addr2] = r3;
2582    
2583     cpu->n_translated_instrs += 2;
2584 dpavlin 30 cpu->cd.mips.next_ic += 2;
2585 dpavlin 28 }
2586     X(multi_sw_3_be)
2587     {
2588     uint32_t *page;
2589     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2590     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2591     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2592     MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2593     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2594     index2 = addr2 >> 12;
2595    
2596     page = (uint32_t *) cpu->cd.mips.host_store[index0];
2597    
2598     /* Fallback: */
2599     if (cpu->delay_slot ||
2600     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2601     (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2602     /* Normal safe sw: */
2603 dpavlin 30 mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2604 dpavlin 28 return;
2605     }
2606    
2607     addr0 = (addr0 >> 2) & 0x3ff;
2608     addr1 = (addr1 >> 2) & 0x3ff;
2609     addr2 = (addr2 >> 2) & 0x3ff;
2610    
2611     /* printf("addr0=%x 1=%x 2=%x\n",
2612     (int)addr0, (int)addr1, (int)addr2); */
2613    
2614     r1 = reg(ic[0].arg[0]);
2615     r2 = reg(ic[1].arg[0]);
2616     r3 = reg(ic[2].arg[0]);
2617    
2618     r1 = BE32_TO_HOST(r1);
2619     r2 = BE32_TO_HOST(r2);
2620     r3 = BE32_TO_HOST(r3);
2621    
2622     page[addr0] = r1;
2623     page[addr1] = r2;
2624     page[addr2] = r3;
2625    
2626     cpu->n_translated_instrs += 2;
2627 dpavlin 30 cpu->cd.mips.next_ic += 2;
2628 dpavlin 28 }
2629 dpavlin 30 X(multi_sw_4_le)
2630     {
2631     uint32_t *page;
2632     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2633     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2634     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2635     MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2636     MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2637     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2638     index2 = addr2 >> 12, index3 = addr3 >> 12;
2639 dpavlin 28
2640 dpavlin 30 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2641 dpavlin 28
2642 dpavlin 30 /* Fallback: */
2643     if (cpu->delay_slot ||
2644     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2645     (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||
2646     index0 != index2 || index0 != index3) {
2647     /* Normal safe sw: */
2648     mips32_loadstore[8 + 2 * 2](cpu, ic);
2649     return;
2650     }
2651    
2652     addr0 = (addr0 >> 2) & 0x3ff;
2653     addr1 = (addr1 >> 2) & 0x3ff;
2654     addr2 = (addr2 >> 2) & 0x3ff;
2655     addr3 = (addr3 >> 2) & 0x3ff;
2656    
2657     r1 = reg(ic[0].arg[0]);
2658     r2 = reg(ic[1].arg[0]);
2659     r3 = reg(ic[2].arg[0]);
2660     r4 = reg(ic[3].arg[0]);
2661    
2662     r1 = LE32_TO_HOST(r1);
2663     r2 = LE32_TO_HOST(r2);
2664     r3 = LE32_TO_HOST(r3);
2665     r4 = LE32_TO_HOST(r4);
2666    
2667     page[addr0] = r1;
2668     page[addr1] = r2;
2669     page[addr2] = r3;
2670     page[addr3] = r4;
2671    
2672     cpu->n_translated_instrs += 3;
2673     cpu->cd.mips.next_ic += 3;
2674     }
2675     X(multi_sw_4_be)
2676     {
2677     uint32_t *page;
2678     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2679     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2680     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2681     MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2682     MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2683     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2684     index2 = addr2 >> 12, index3 = addr3 >> 12;
2685    
2686     page = (uint32_t *) cpu->cd.mips.host_store[index0];
2687    
2688     /* Fallback: */
2689     if (cpu->delay_slot ||
2690     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2691     (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||
2692     index0 != index2 || index0 != index3) {
2693     /* Normal safe sw: */
2694     mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2695     return;
2696     }
2697    
2698     addr0 = (addr0 >> 2) & 0x3ff;
2699     addr1 = (addr1 >> 2) & 0x3ff;
2700     addr2 = (addr2 >> 2) & 0x3ff;
2701     addr3 = (addr3 >> 2) & 0x3ff;
2702    
2703     r1 = reg(ic[0].arg[0]);
2704     r2 = reg(ic[1].arg[0]);
2705     r3 = reg(ic[2].arg[0]);
2706     r4 = reg(ic[3].arg[0]);
2707    
2708     r1 = BE32_TO_HOST(r1);
2709     r2 = BE32_TO_HOST(r2);
2710     r3 = BE32_TO_HOST(r3);
2711     r4 = BE32_TO_HOST(r4);
2712    
2713     page[addr0] = r1;
2714     page[addr1] = r2;
2715     page[addr2] = r3;
2716     page[addr3] = r4;
2717    
2718     cpu->n_translated_instrs += 3;
2719     cpu->cd.mips.next_ic += 3;
2720     }
2721     #endif
2722    
2723    
2724     #ifdef MODE32
2725 dpavlin 28 /*
2726 dpavlin 30 * multi_lw_2, _3, _4:
2727     *
2728     * lw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2]
2729     */
2730     X(multi_lw_2_le)
2731     {
2732     uint32_t *page;
2733     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2734     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2735     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2736     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2737    
2738     page = (uint32_t *) cpu->cd.mips.host_load[index0];
2739    
2740     /* Fallback: */
2741     if (cpu->delay_slot ||
2742     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2743     index0 != index1) {
2744     /* Normal safe lw: */
2745     mips32_loadstore[2 * 2 + 1](cpu, ic);
2746     return;
2747     }
2748    
2749     addr0 = (addr0 >> 2) & 0x3ff;
2750     addr1 = (addr1 >> 2) & 0x3ff;
2751    
2752     r1 = page[addr0];
2753     r2 = page[addr1];
2754    
2755     r1 = LE32_TO_HOST(r1);
2756     r2 = LE32_TO_HOST(r2);
2757    
2758     reg(ic[0].arg[0]) = r1;
2759     reg(ic[1].arg[0]) = r2;
2760    
2761     cpu->n_translated_instrs ++;
2762     cpu->cd.mips.next_ic ++;
2763     }
2764     X(multi_lw_2_be)
2765     {
2766     uint32_t *page;
2767     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2768     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2769     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2770     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2771    
2772     page = (uint32_t *) cpu->cd.mips.host_load[index0];
2773    
2774     /* Fallback: */
2775     if (cpu->delay_slot ||
2776     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2777     index0 != index1) {
2778     /* Normal safe lw: */
2779     mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2780     return;
2781     }
2782    
2783     addr0 = (addr0 >> 2) & 0x3ff;
2784     addr1 = (addr1 >> 2) & 0x3ff;
2785    
2786     r1 = page[addr0];
2787     r2 = page[addr1];
2788    
2789     r1 = BE32_TO_HOST(r1);
2790     r2 = BE32_TO_HOST(r2);
2791    
2792     reg(ic[0].arg[0]) = r1;
2793     reg(ic[1].arg[0]) = r2;
2794    
2795     cpu->n_translated_instrs ++;
2796     cpu->cd.mips.next_ic ++;
2797     }
2798     X(multi_lw_3_le)
2799     {
2800     uint32_t *page;
2801     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2802     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2803     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2804     MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2805     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2806     index2 = addr2 >> 12;
2807    
2808     page = (uint32_t *) cpu->cd.mips.host_load[index0];
2809    
2810     /* Fallback: */
2811     if (cpu->delay_slot ||
2812     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2813     (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2814     /* Normal safe lw: */
2815     mips32_loadstore[2 * 2 + 1](cpu, ic);
2816     return;
2817     }
2818    
2819     addr0 = (addr0 >> 2) & 0x3ff;
2820     addr1 = (addr1 >> 2) & 0x3ff;
2821     addr2 = (addr2 >> 2) & 0x3ff;
2822    
2823     /* printf("addr0=%x 1=%x 2=%x\n",
2824     (int)addr0, (int)addr1, (int)addr2); */
2825    
2826     r1 = page[addr0];
2827     r2 = page[addr1];
2828     r3 = page[addr2];
2829    
2830     r1 = LE32_TO_HOST(r1);
2831     r2 = LE32_TO_HOST(r2);
2832     r3 = LE32_TO_HOST(r3);
2833    
2834     reg(ic[0].arg[0]) = r1;
2835     reg(ic[1].arg[0]) = r2;
2836     reg(ic[2].arg[0]) = r3;
2837    
2838     cpu->n_translated_instrs += 2;
2839     cpu->cd.mips.next_ic += 2;
2840     }
2841     X(multi_lw_3_be)
2842     {
2843     uint32_t *page;
2844     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2845     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2846     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2847     MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2848     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2849     index2 = addr2 >> 12;
2850    
2851     page = (uint32_t *) cpu->cd.mips.host_load[index0];
2852    
2853     /* Fallback: */
2854     if (cpu->delay_slot ||
2855     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2856     (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2857     /* Normal safe lw: */
2858     mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2859     return;
2860     }
2861    
2862     addr0 = (addr0 >> 2) & 0x3ff;
2863     addr1 = (addr1 >> 2) & 0x3ff;
2864     addr2 = (addr2 >> 2) & 0x3ff;
2865    
2866     /* printf("addr0=%x 1=%x 2=%x\n",
2867     (int)addr0, (int)addr1, (int)addr2); */
2868    
2869     r1 = page[addr0];
2870     r2 = page[addr1];
2871     r3 = page[addr2];
2872    
2873     r1 = BE32_TO_HOST(r1);
2874     r2 = BE32_TO_HOST(r2);
2875     r3 = BE32_TO_HOST(r3);
2876    
2877     reg(ic[0].arg[0]) = r1;
2878     reg(ic[1].arg[0]) = r2;
2879     reg(ic[2].arg[0]) = r3;
2880    
2881     cpu->n_translated_instrs += 2;
2882     cpu->cd.mips.next_ic += 2;
2883     }
2884     X(multi_lw_4_le)
2885     {
2886     uint32_t *page;
2887     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2888     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2889     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2890     MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2891     MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2892     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2893     index2 = addr2 >> 12, index3 = addr3 >> 12;
2894    
2895     page = (uint32_t *) cpu->cd.mips.host_load[index0];
2896    
2897     /* Fallback: */
2898     if (cpu->delay_slot ||
2899     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2900     (addr2 & 3) != 0 || (addr3 & 3) != 0 ||
2901     index0 != index1 || index0 != index2 || index0 != index3) {
2902     /* Normal safe lw: */
2903     mips32_loadstore[2 * 2 + 1](cpu, ic);
2904     return;
2905     }
2906    
2907     addr0 = (addr0 >> 2) & 0x3ff;
2908     addr1 = (addr1 >> 2) & 0x3ff;
2909     addr2 = (addr2 >> 2) & 0x3ff;
2910     addr3 = (addr3 >> 2) & 0x3ff;
2911    
2912     r1 = page[addr0];
2913     r2 = page[addr1];
2914     r3 = page[addr2];
2915     r4 = page[addr3];
2916    
2917     r1 = LE32_TO_HOST(r1);
2918     r2 = LE32_TO_HOST(r2);
2919     r3 = LE32_TO_HOST(r3);
2920     r4 = LE32_TO_HOST(r4);
2921    
2922     reg(ic[0].arg[0]) = r1;
2923     reg(ic[1].arg[0]) = r2;
2924     reg(ic[2].arg[0]) = r3;
2925     reg(ic[3].arg[0]) = r4;
2926    
2927     cpu->n_translated_instrs += 3;
2928     cpu->cd.mips.next_ic += 3;
2929     }
2930     X(multi_lw_4_be)
2931     {
2932     uint32_t *page;
2933     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2934     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2935     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2936     MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2937     MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2938     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2939     index2 = addr2 >> 12, index3 = addr3 >> 12;
2940    
2941     page = (uint32_t *) cpu->cd.mips.host_load[index0];
2942    
2943     /* Fallback: */
2944     if (cpu->delay_slot ||
2945     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2946     (addr2 & 3) != 0 || (addr3 & 3) != 0 ||
2947     index0 != index1 || index0 != index2 || index0 != index3) {
2948     /* Normal safe lw: */
2949     mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2950     return;
2951     }
2952    
2953     addr0 = (addr0 >> 2) & 0x3ff;
2954     addr1 = (addr1 >> 2) & 0x3ff;
2955     addr2 = (addr2 >> 2) & 0x3ff;
2956     addr3 = (addr3 >> 2) & 0x3ff;
2957    
2958     r1 = page[addr0];
2959     r2 = page[addr1];
2960     r3 = page[addr2];
2961     r4 = page[addr3];
2962    
2963     r1 = BE32_TO_HOST(r1);
2964     r2 = BE32_TO_HOST(r2);
2965     r3 = BE32_TO_HOST(r3);
2966     r4 = BE32_TO_HOST(r4);
2967    
2968     reg(ic[0].arg[0]) = r1;
2969     reg(ic[1].arg[0]) = r2;
2970     reg(ic[2].arg[0]) = r3;
2971     reg(ic[3].arg[0]) = r4;
2972    
2973     cpu->n_translated_instrs += 3;
2974     cpu->cd.mips.next_ic += 3;
2975     }
2976     #endif
2977    
2978    
2979     /*
2980     * multi_addu_3:
2981     */
2982     X(multi_addu_3)
2983     {
2984     /* Fallback: */
2985     if (cpu->delay_slot) {
2986     instr(addu)(cpu, ic);
2987     return;
2988     }
2989    
2990     reg(ic[0].arg[2]) = (int32_t)(reg(ic[0].arg[0]) + reg(ic[0].arg[1]));
2991     reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0]) + reg(ic[1].arg[1]));
2992     reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0]) + reg(ic[2].arg[1]));
2993     cpu->n_translated_instrs += 2;
2994     cpu->cd.mips.next_ic += 2;
2995     }
2996    
2997    
2998     /*
2999 dpavlin 28 * netbsd_r3k_picache_do_inv:
3000     *
3001     * ic[0] mtc0 rV,status
3002     * 1 nop
3003     * 2 nop
3004     * 3 s: addiu rX,rX,4
3005     * 4 bne rY,rX,s
3006     * 5 sb zr,-4(rX)
3007     * 6 nop
3008     * 7 nop
3009     * 8 mtc0 rT,status
3010     */
3011     X(netbsd_r3k_picache_do_inv)
3012     {
3013     MODE_uint_t rx = reg(ic[3].arg[0]), ry = reg(ic[4].arg[1]);
3014    
3015     /* Fallback if the environment isn't exactly right: */
3016     if (!(reg(ic[0].arg[0]) & MIPS1_ISOL_CACHES) ||
3017     (rx & 3) || (ry & 3) || cpu->delay_slot) {
3018     instr(mtc0)(cpu, ic);
3019     return;
3020     }
3021    
3022     reg(ic[3].arg[0]) = ry;
3023     cpu->n_translated_instrs += (ry - rx + 4) / 4 * 3 + 4;
3024    
3025     /* Run the last mtc0 instruction: */
3026     cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[8];
3027     }
3028    
3029    
3030     #ifdef MODE32
3031     /*
3032     * netbsd_strlen():
3033     *
3034     * lb rV,0(rX)
3035     * s: addiu rX,rX,1
3036     * bne zr,rV,s
3037     * nop
3038     */
3039     X(netbsd_strlen)
3040     {
3041     MODE_uint_t rx = reg(ic[0].arg[1]);
3042     MODE_int_t rv;
3043     signed char *page;
3044     uint32_t pageindex = rx >> 12;
3045     int i;
3046    
3047     page = (signed char *) cpu->cd.mips.host_load[pageindex];
3048    
3049     /* Fallback: */
3050     if (cpu->delay_slot || page == NULL) {
3051     /*
3052     * Normal lb: NOTE: It doesn't matter whether [1] or
3053     * [16+1] is called here, because endianness for 8-bit
3054     * loads is irrelevant. :-)
3055     */
3056     mips32_loadstore[1](cpu, ic);
3057     return;
3058     }
3059    
3060     i = rx & 0xfff;
3061    
3062     /*
3063     * TODO: This loop can be optimized further for optimal
3064     * performance on the host, e.g. by reading full words...
3065     */
3066     do {
3067     rv = page[i ++];
3068     } while (i < 0x1000 && rv != 0);
3069    
3070     cpu->n_translated_instrs += (i - (rx & 0xfff)) * 4 - 1;
3071    
3072     reg(ic[0].arg[1]) = (rx & ~0xfff) + i;
3073     reg(ic[2].arg[0]) = rv;
3074    
3075     /* Done with the loop? Or continue on the next rx page? */
3076     if (rv == 0)
3077     cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[4];
3078     else
3079     cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[0];
3080     }
3081     #endif
3082    
3083    
3084     /*
3085 dpavlin 30 * addiu_bne_samepage_addiu:
3086 dpavlin 28 */
3087 dpavlin 30 X(addiu_bne_samepage_addiu)
3088 dpavlin 28 {
3089 dpavlin 30 MODE_uint_t rs, rt;
3090    
3091     if (cpu->delay_slot) {
3092     instr(addiu)(cpu, ic);
3093     return;
3094     }
3095    
3096     cpu->n_translated_instrs += 2;
3097     reg(ic[0].arg[1]) = (int32_t)
3098     ((int32_t)reg(ic[0].arg[0]) + (int32_t)ic[0].arg[2]);
3099     rs = reg(ic[1].arg[0]);
3100     rt = reg(ic[1].arg[1]);
3101     reg(ic[2].arg[1]) = (int32_t)
3102     ((int32_t)reg(ic[2].arg[0]) + (int32_t)ic[2].arg[2]);
3103     if (rs != rt)
3104     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic[1].arg[2];
3105     else
3106     cpu->cd.mips.next_ic += 2;
3107     }
3108    
3109    
3110     /*
3111     * xor_andi_sll:
3112     */
3113     X(xor_andi_sll)
3114     {
3115     /* Fallback: */
3116     if (cpu->delay_slot) {
3117     instr(xor)(cpu, ic);
3118     return;
3119     }
3120    
3121     reg(ic[0].arg[2]) = reg(ic[0].arg[0]) ^ reg(ic[0].arg[1]);
3122     reg(ic[1].arg[1]) = reg(ic[1].arg[0]) & (uint32_t)ic[1].arg[2];
3123     reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0])<<(int32_t)ic[2].arg[1]);
3124    
3125     cpu->n_translated_instrs += 2;
3126     cpu->cd.mips.next_ic += 2;
3127     }
3128    
3129    
3130     /*
3131     * andi_sll:
3132     */
3133     X(andi_sll)
3134     {
3135     /* Fallback: */
3136     if (cpu->delay_slot) {
3137     instr(andi)(cpu, ic);
3138     return;
3139     }
3140    
3141     reg(ic[0].arg[1]) = reg(ic[0].arg[0]) & (uint32_t)ic[0].arg[2];
3142     reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0])<<(int32_t)ic[1].arg[1]);
3143    
3144 dpavlin 28 cpu->n_translated_instrs ++;
3145     cpu->cd.mips.next_ic ++;
3146     }
3147    
3148    
3149     /*
3150 dpavlin 30 * lui_ori:
3151     */
3152     X(lui_ori)
3153     {
3154     /* Fallback: */
3155     if (cpu->delay_slot) {
3156     instr(set)(cpu, ic);
3157     return;
3158     }
3159    
3160     reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3161     reg(ic[1].arg[1]) = reg(ic[1].arg[0]) | (uint32_t)ic[1].arg[2];
3162    
3163     cpu->n_translated_instrs ++;
3164     cpu->cd.mips.next_ic ++;
3165     }
3166    
3167    
3168     /*
3169     * lui_addiu:
3170     */
3171     X(lui_addiu)
3172     {
3173     /* Fallback: */
3174     if (cpu->delay_slot) {
3175     instr(set)(cpu, ic);
3176     return;
3177     }
3178    
3179     reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3180     reg(ic[1].arg[1]) = (int32_t)
3181     ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
3182    
3183     cpu->n_translated_instrs ++;
3184     cpu->cd.mips.next_ic ++;
3185     }
3186    
3187    
3188     /*
3189 dpavlin 22 * b_samepage_addiu:
3190     *
3191     * Combination of branch within the same page, followed by addiu.
3192     */
3193     X(b_samepage_addiu)
3194     {
3195 dpavlin 24 reg(ic[1].arg[1]) = (int32_t)
3196     ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
3197 dpavlin 22 cpu->n_translated_instrs ++;
3198     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
3199     }
3200    
3201    
3202 dpavlin 24 /*
3203     * b_samepage_daddiu:
3204     *
3205     * Combination of branch within the same page, followed by daddiu.
3206     */
3207     X(b_samepage_daddiu)
3208     {
3209     *(uint64_t *)ic[1].arg[1] = *(uint64_t *)ic[1].arg[0] +
3210     (int32_t)ic[1].arg[2];
3211     cpu->n_translated_instrs ++;
3212     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
3213     }
3214    
3215    
3216 dpavlin 22 /*****************************************************************************/
3217    
3218    
3219     X(end_of_page)
3220     {
3221     /* Update the PC: (offset 0, but on the next page) */
3222     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
3223     MIPS_INSTR_ALIGNMENT_SHIFT);
3224     cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);
3225    
3226 dpavlin 24 /* end_of_page doesn't count as an executed instruction: */
3227     cpu->n_translated_instrs --;
3228 dpavlin 22
3229 dpavlin 24 /*
3230     * Find the new physpage and update translation pointers.
3231     *
3232     * Note: This may cause an exception, if e.g. the new page is
3233     * not accessible.
3234     */
3235     quick_pc_to_pointers(cpu);
3236 dpavlin 22
3237 dpavlin 24 /* Simple jump to the next page (if we are lucky): */
3238     if (cpu->delay_slot == NOT_DELAYED)
3239     return;
3240 dpavlin 22
3241 dpavlin 24 /*
3242     * If we were in a delay slot, and we got an exception while doing
3243     * quick_pc_to_pointers, then return. The function which called
3244     * end_of_page should handle this case.
3245     */
3246     if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
3247 dpavlin 22 return;
3248    
3249 dpavlin 24 /*
3250     * Tricky situation; the delay slot is on the next virtual page.
3251     * Calling to_be_translated will translate one instruction manually,
3252     * execute it, and then discard it.
3253     */
3254 dpavlin 22 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
3255    
3256 dpavlin 24 instr(to_be_translated)(cpu, cpu->cd.mips.next_ic);
3257 dpavlin 22
3258     /* The instruction in the delay slot has now executed. */
3259 dpavlin 24 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
3260     cpu->delay_slot); */
3261 dpavlin 22
3262     /* Find the physpage etc of the instruction in the delay slot
3263     (or, if there was an exception, the exception handler): */
3264     quick_pc_to_pointers(cpu);
3265     }
3266    
3267    
3268     X(end_of_page2)
3269     {
3270 dpavlin 24 /* Synchronize PC on the _second_ instruction on the next page: */
3271     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
3272     / sizeof(struct mips_instr_call);
3273     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
3274     << MIPS_INSTR_ALIGNMENT_SHIFT);
3275     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
3276 dpavlin 22
3277 dpavlin 24 /* This doesn't count as an executed instruction. */
3278     cpu->n_translated_instrs --;
3279 dpavlin 22
3280 dpavlin 24 quick_pc_to_pointers(cpu);
3281 dpavlin 22
3282 dpavlin 24 if (cpu->delay_slot == NOT_DELAYED)
3283 dpavlin 22 return;
3284    
3285 dpavlin 24 fatal("end_of_page2: fatal error, we're in a delay slot\n");
3286 dpavlin 22 exit(1);
3287     }
3288    
3289    
3290     /*****************************************************************************/
3291    
3292    
3293     /*
3294 dpavlin 28 * Combine: Memory fill loop (addiu, bne, sw)
3295     *
3296     * s: addiu rX,rX,4
3297     * bne rY,rX,s
3298     * sw rZ,-4(rX)
3299 dpavlin 22 */
3300 dpavlin 28 void COMBINE(sw_loop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3301     {
3302     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3303     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3304    
3305     /* Only for 32-bit virtual address translation so far. */
3306     if (!cpu->is_32bit)
3307     return;
3308    
3309     if (n_back < 2)
3310     return;
3311    
3312     if (ic[-2].f == instr(addiu) && ic[-2].arg[0] == ic[-2].arg[1] &&
3313     (int32_t)ic[-2].arg[2] == 4 &&
3314     ic[-1].f == instr(bne_samepage) &&
3315     (ic[-1].arg[0] == ic[-2].arg[0] ||
3316     ic[-1].arg[1] == ic[-2].arg[0]) &&
3317     ic[-1].arg[0] != ic[-1].arg[1] &&
3318     ic[-1].arg[2] == (size_t) &ic[-2] &&
3319     ic[0].arg[0] != ic[0].arg[1] &&
3320     ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {
3321     ic[-2].f = instr(sw_loop);
3322     }
3323     }
3324    
3325    
3326 dpavlin 30 /* Only for 32-bit virtual address translation so far. */
3327     #ifdef MODE32
3328 dpavlin 28 /*
3329     * Combine: Multiple SW in a row using the same base register
3330     *
3331     * sw r?,???(rX)
3332     * sw r?,???(rX)
3333     * sw r?,???(rX)
3334     * ...
3335     */
3336     void COMBINE(multi_sw)(struct cpu *cpu, struct mips_instr_call *ic,
3337 dpavlin 22 int low_addr)
3338     {
3339     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3340     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3341    
3342 dpavlin 30 if (n_back < 3)
3343 dpavlin 28 return;
3344    
3345 dpavlin 30 /* Convert a multi_sw_3 to a multi_sw_4: */
3346     if ((ic[-3].f == instr(multi_sw_3_be) ||
3347     ic[-3].f == instr(multi_sw_3_le)) &&
3348     ic[-3].arg[1] == ic[0].arg[1]) {
3349     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3350     ic[-3].f = instr(multi_sw_4_le);
3351     else
3352     ic[-3].f = instr(multi_sw_4_be);
3353     }
3354 dpavlin 28
3355 dpavlin 30 /* Convert a multi_sw_2 to a multi_sw_3: */
3356     if ((ic[-2].f == instr(multi_sw_2_be) ||
3357     ic[-2].f == instr(multi_sw_2_le)) &&
3358     ic[-2].arg[1] == ic[0].arg[1]) {
3359     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3360     ic[-2].f = instr(multi_sw_3_le);
3361     else
3362     ic[-2].f = instr(multi_sw_3_be);
3363     }
3364    
3365     if (ic[-1].f == ic[0].f && ic[-1].arg[1] == ic[0].arg[1]) {
3366     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3367     ic[-1].f = instr(multi_sw_2_le);
3368     else
3369     ic[-1].f = instr(multi_sw_2_be);
3370     }
3371     }
3372     #endif
3373    
3374    
3375     /* Only for 32-bit virtual address translation so far. */
3376     #ifdef MODE32
3377     /*
3378     * Combine: Multiple LW in a row using the same base register
3379     *
3380     * lw r?,???(rX)
3381     * lw r?,???(rX)
3382     * lw r?,???(rX)
3383     * ...
3384     */
3385     void COMBINE(multi_lw)(struct cpu *cpu, struct mips_instr_call *ic,
3386     int low_addr)
3387     {
3388     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3389     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3390    
3391     if (n_back < 3)
3392 dpavlin 28 return;
3393    
3394 dpavlin 30 /* Convert a multi_lw_3 to a multi_lw_4: */
3395     if ((ic[-3].f == instr(multi_lw_3_be) ||
3396     ic[-3].f == instr(multi_lw_3_le)) &&
3397     ic[-3].arg[1] == ic[0].arg[1] &&
3398     ic[-1].arg[0] != ic[0].arg[1]) {
3399     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3400     ic[-3].f = instr(multi_lw_4_le);
3401     else
3402     ic[-3].f = instr(multi_lw_4_be);
3403     }
3404    
3405     /* Convert a multi_lw_2 to a multi_lw_3: */
3406     if ((ic[-2].f == instr(multi_lw_2_be) ||
3407     ic[-2].f == instr(multi_lw_2_le)) &&
3408 dpavlin 28 ic[-2].arg[1] == ic[0].arg[1] &&
3409 dpavlin 30 ic[-1].arg[0] != ic[0].arg[1]) {
3410 dpavlin 28 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3411 dpavlin 30 ic[-2].f = instr(multi_lw_3_le);
3412 dpavlin 28 else
3413 dpavlin 30 ic[-2].f = instr(multi_lw_3_be);
3414 dpavlin 28 }
3415 dpavlin 30
3416     /* Note: Loads to the base register are not allowed in slot -1. */
3417     if (ic[-1].f == ic[0].f &&
3418     ic[-1].arg[1] == ic[0].arg[1] &&
3419     ic[-1].arg[0] != ic[0].arg[1]) {
3420     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3421     ic[-1].f = instr(multi_lw_2_le);
3422     else
3423     ic[-1].f = instr(multi_lw_2_be);
3424     }
3425 dpavlin 28 }
3426 dpavlin 30 #endif
3427 dpavlin 28
3428    
3429     /*
3430     * Combine: NetBSD/pmax 3.0 R2000/R3000 physical cache invalidation loop
3431     *
3432     * Instruction cache loop:
3433     *
3434     * ic[-8] mtc0 rV,status
3435     * -7 nop
3436     * -6 nop
3437     * -5 s: addiu rX,rX,4
3438     * -4 bne rY,rX,s
3439     * -3 sb zr,-4(rX)
3440     * -2 nop
3441     * -1 nop
3442     * 0 mtc0 rT,status
3443     */
3444     void COMBINE(netbsd_r3k_cache_inv)(struct cpu *cpu,
3445     struct mips_instr_call *ic, int low_addr)
3446     {
3447     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3448     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3449    
3450     if (n_back < 8)
3451     return;
3452    
3453     if (ic[-8].f == instr(mtc0) && ic[-8].arg[1] == COP0_STATUS &&
3454     ic[-7].f == instr(nop) && ic[-6].f == instr(nop) &&
3455     ic[-5].f == instr(addiu) && ic[-5].arg[0] == ic[-5].arg[1] &&
3456     (int32_t)ic[-5].arg[2] == 4 && ic[-4].f == instr(bne_samepage) &&
3457     ic[-4].arg[0] == ic[-5].arg[0] && ic[-4].arg[0] != ic[-4].arg[1] &&
3458     ic[-4].arg[2] == (size_t) &ic[-5] &&
3459     ic[-3].arg[1] == ic[-5].arg[0] &&
3460     ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
3461     ic[-8].f = instr(netbsd_r3k_picache_do_inv);
3462     }
3463     }
3464    
3465    
3466     /*
3467     * Combine: something ending with a nop.
3468     *
3469     * NetBSD's strlen core.
3470     * [Conditional] branch, followed by nop.
3471     */
3472     void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3473     {
3474     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3475     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3476    
3477     #ifdef MODE32
3478     if (n_back < 3)
3479     return;
3480    
3481     if ((ic[-3].f == mips32_loadstore[1] ||
3482     ic[-3].f == mips32_loadstore[16 + 1]) &&
3483     ic[-3].arg[2] == 0 &&
3484     ic[-3].arg[0] == ic[-1].arg[0] && ic[-3].arg[1] == ic[-2].arg[0] &&
3485     ic[-2].arg[0] == ic[-2].arg[1] && ic[-2].arg[2] == 1 &&
3486     ic[-2].f == instr(addiu) && ic[-1].arg[2] == (size_t) &ic[-3] &&
3487     ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3488     ic[-1].f == instr(bne_samepage)) {
3489     ic[-3].f = instr(netbsd_strlen);
3490     return;
3491     }
3492     #endif
3493    
3494 dpavlin 22 if (n_back < 1)
3495     return;
3496    
3497 dpavlin 28 if (ic[-1].f == instr(bne_samepage)) {
3498     ic[-1].f = instr(bne_samepage_nop);
3499     return;
3500     }
3501    
3502     if (ic[-1].f == instr(beq_samepage)) {
3503     ic[-1].f = instr(beq_samepage_nop);
3504     return;
3505     }
3506    
3507     /* TODO: other branches that are followed by nop should be here */
3508     }
3509    
3510    
3511     /*
3512     * Combine:
3513     *
3514 dpavlin 30 * xor + andi + sll
3515     * andi + sll
3516     */
3517     void COMBINE(sll)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3518     {
3519     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3520     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3521    
3522     if (n_back < 2)
3523     return;
3524    
3525     if (ic[-2].f == instr(xor) && ic[-1].f == instr(andi)) {
3526     ic[-2].f = instr(xor_andi_sll);
3527     return;
3528     }
3529    
3530     if (ic[-1].f == instr(andi)) {
3531     ic[-1].f = instr(andi_sll);
3532     return;
3533     }
3534     }
3535    
3536    
3537     /*
3538     * lui + ori
3539     */
3540     void COMBINE(ori)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3541     {
3542     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3543     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3544    
3545     if (n_back < 1)
3546     return;
3547    
3548     if (ic[-1].f == instr(set)) {
3549     ic[-1].f = instr(lui_ori);
3550     return;
3551     }
3552     }
3553    
3554    
3555     /*
3556     * addu + addu + addu
3557     */
3558     void COMBINE(addu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3559     {
3560     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3561     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3562    
3563     if (n_back < 4)
3564     return;
3565    
3566     /* Avoid "overlapping" instruction combinations: */
3567     if (ic[-4].f == instr(multi_addu_3) ||
3568     ic[-3].f == instr(multi_addu_3))
3569     return;
3570    
3571     if (ic[-2].f == instr(addu) && ic[-1].f == instr(addu)) {
3572     ic[-2].f = instr(multi_addu_3);
3573     return;
3574     }
3575     }
3576    
3577    
3578     /*
3579     * Combine:
3580     *
3581 dpavlin 28 * [Conditional] branch, followed by addiu.
3582     */
3583     void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3584     {
3585     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3586     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3587    
3588 dpavlin 30 if (n_back < 2)
3589 dpavlin 28 return;
3590    
3591 dpavlin 30 if (ic[-2].f == instr(addiu) &&
3592     ic[-1].f == instr(bne_samepage)) {
3593     ic[-2].f = instr(addiu_bne_samepage_addiu);
3594 dpavlin 28 return;
3595     }
3596    
3597 dpavlin 30 if (ic[-1].f == instr(set)) {
3598     ic[-1].f = instr(lui_addiu);
3599     return;
3600     }
3601    
3602 dpavlin 22 if (ic[-1].f == instr(b_samepage)) {
3603     ic[-1].f = instr(b_samepage_addiu);
3604 dpavlin 28 return;
3605 dpavlin 22 }
3606    
3607 dpavlin 28 if (ic[-1].f == instr(beq_samepage)) {
3608     ic[-1].f = instr(beq_samepage_addiu);
3609     return;
3610     }
3611    
3612     if (ic[-1].f == instr(bne_samepage)) {
3613     ic[-1].f = instr(bne_samepage_addiu);
3614     return;
3615     }
3616    
3617     if (ic[-1].f == instr(jr_ra)) {
3618     ic[-1].f = instr(jr_ra_addiu);
3619     return;
3620     }
3621    
3622 dpavlin 22 /* TODO: other branches that are followed by addiu should be here */
3623     }
3624    
3625    
3626 dpavlin 24 /*
3627     * Combine: [Conditional] branch, followed by daddiu.
3628     */
3629     void COMBINE(b_daddiu)(struct cpu *cpu, struct mips_instr_call *ic,
3630     int low_addr)
3631     {
3632     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3633     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3634    
3635     if (n_back < 1)
3636     return;
3637    
3638     if (ic[-1].f == instr(b_samepage)) {
3639     ic[-1].f = instr(b_samepage_daddiu);
3640     }
3641    
3642     /* TODO: other branches that are followed by daddiu should be here */
3643     }
3644    
3645    
3646 dpavlin 22 /*****************************************************************************/
3647    
3648    
3649     /*
3650     * mips_instr_to_be_translated():
3651     *
3652 dpavlin 24 * Translate an instruction word into a mips_instr_call. ic is filled in with
3653 dpavlin 22 * valid data for the translated instruction, or a "nothing" instruction if
3654     * there was a translation failure. The newly translated instruction is then
3655     * executed.
3656     */
3657     X(to_be_translated)
3658     {
3659     uint64_t addr, low_pc;
3660     uint32_t iword, imm;
3661     unsigned char *page;
3662     unsigned char ib[4];
3663     int main_opcode, rt, rs, rd, sa, s6, x64 = 0;
3664     int in_crosspage_delayslot = 0;
3665     void (*samepage_function)(struct cpu *, struct mips_instr_call *);
3666 dpavlin 24 int store, signedness, size;
3667 dpavlin 22
3668     /* Figure out the (virtual) address of the instruction: */
3669     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
3670     / sizeof(struct mips_instr_call);
3671    
3672     /* Special case for branch with delayslot on the next page: */
3673 dpavlin 24 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
3674     /* fatal("[ delay-slot translation across page "
3675     "boundary ]\n"); */
3676 dpavlin 22 in_crosspage_delayslot = 1;
3677     }
3678    
3679     addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)
3680     << MIPS_INSTR_ALIGNMENT_SHIFT);
3681     addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
3682 dpavlin 24 cpu->pc = (MODE_int_t)addr;
3683 dpavlin 22 addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
3684    
3685     /* Read the instruction word from memory: */
3686 dpavlin 24 #ifdef MODE32
3687 dpavlin 22 page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
3688 dpavlin 24 #else
3689     {
3690     const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
3691     const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
3692     const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
3693     uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
3694     uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
3695     uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
3696     DYNTRANS_L3N)) & mask3;
3697     struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.mips.l1_64[x1];
3698     struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
3699     page = l3->host_load[x3];
3700     }
3701     #endif
3702 dpavlin 22
3703     if (page != NULL) {
3704     /* fatal("TRANSLATION HIT!\n"); */
3705 dpavlin 24 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
3706 dpavlin 22 } else {
3707     /* fatal("TRANSLATION MISS!\n"); */
3708     if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
3709     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
3710 dpavlin 24 fatal("to_be_translated(): read failed: TODO\n");
3711 dpavlin 22 goto bad;
3712     }
3713     }
3714    
3715     iword = *((uint32_t *)&ib[0]);
3716    
3717     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3718     iword = LE32_TO_HOST(iword);
3719     else
3720     iword = BE32_TO_HOST(iword);
3721    
3722    
3723     #define DYNTRANS_TO_BE_TRANSLATED_HEAD
3724     #include "cpu_dyntrans.c"
3725     #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
3726    
3727    
3728     /*
3729     * Translate the instruction:
3730     *
3731 dpavlin 24 * NOTE: _NEVER_ allow writes to the zero register; all instructions
3732     * that use the zero register as their destination should be treated
3733     * as NOPs, except those that access memory (they should use the
3734     * scratch register instead).
3735 dpavlin 22 */
3736    
3737     main_opcode = iword >> 26;
3738     rs = (iword >> 21) & 31;
3739     rt = (iword >> 16) & 31;
3740     rd = (iword >> 11) & 31;
3741     sa = (iword >> 6) & 31;
3742     imm = (int16_t)iword;
3743     s6 = iword & 63;
3744    
3745     switch (main_opcode) {
3746    
3747     case HI6_SPECIAL:
3748     switch (s6) {
3749    
3750     case SPECIAL_SLL:
3751 dpavlin 24 case SPECIAL_SLLV:
3752 dpavlin 22 case SPECIAL_SRL:
3753 dpavlin 24 case SPECIAL_SRLV:
3754 dpavlin 22 case SPECIAL_SRA:
3755 dpavlin 24 case SPECIAL_SRAV:
3756     case SPECIAL_DSRL:
3757     case SPECIAL_DSRLV:
3758     case SPECIAL_DSRL32:
3759     case SPECIAL_DSLL:
3760     case SPECIAL_DSLLV:
3761     case SPECIAL_DSLL32:
3762     case SPECIAL_DSRA:
3763     case SPECIAL_DSRAV:
3764     case SPECIAL_DSRA32:
3765 dpavlin 22 switch (s6) {
3766     case SPECIAL_SLL: ic->f = instr(sll); break;
3767 dpavlin 24 case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
3768 dpavlin 22 case SPECIAL_SRL: ic->f = instr(srl); break;
3769 dpavlin 24 case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
3770 dpavlin 22 case SPECIAL_SRA: ic->f = instr(sra); break;
3771 dpavlin 24 case SPECIAL_SRAV: ic->f = instr(srav); sa = -1; break;
3772     case SPECIAL_DSRL: ic->f = instr(dsrl); x64=1; break;
3773     case SPECIAL_DSRLV:ic->f = instr(dsrlv);
3774     x64 = 1; sa = -1; break;
3775     case SPECIAL_DSRL32:ic->f= instr(dsrl); x64=1;
3776     sa += 32; break;
3777     case SPECIAL_DSLL: ic->f = instr(dsll); x64=1; break;
3778     case SPECIAL_DSLLV:ic->f = instr(dsllv);
3779     x64 = 1; sa = -1; break;
3780     case SPECIAL_DSLL32:ic->f= instr(dsll); x64=1;
3781     sa += 32; break;
3782     case SPECIAL_DSRA: ic->f = instr(dsra); x64=1; break;
3783     case SPECIAL_DSRAV:ic->f = instr(dsrav);
3784     x64 = 1; sa = -1; break;
3785     case SPECIAL_DSRA32:ic->f = instr(dsra); x64=1;
3786     sa += 32; break;
3787 dpavlin 22 }
3788     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3789 dpavlin 24 if (sa >= 0)
3790     ic->arg[1] = sa;
3791     else
3792     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3793 dpavlin 22 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3794     if (rd == MIPS_GPR_ZERO)
3795     ic->f = instr(nop);
3796 dpavlin 30 if (ic->f == instr(sll))
3797     cpu->cd.mips.combination_check = COMBINE(sll);
3798 dpavlin 22 break;
3799    
3800 dpavlin 24 case SPECIAL_ADD:
3801 dpavlin 22 case SPECIAL_ADDU:
3802 dpavlin 24 case SPECIAL_SUB:
3803 dpavlin 22 case SPECIAL_SUBU:
3804 dpavlin 24 case SPECIAL_DADD:
3805 dpavlin 22 case SPECIAL_DADDU:
3806 dpavlin 24 case SPECIAL_DSUB:
3807 dpavlin 22 case SPECIAL_DSUBU:
3808     case SPECIAL_SLT:
3809     case SPECIAL_SLTU:
3810 dpavlin 24 case SPECIAL_AND:
3811 dpavlin 22 case SPECIAL_OR:
3812     case SPECIAL_XOR:
3813     case SPECIAL_NOR:
3814 dpavlin 24 case SPECIAL_MOVN:
3815     case SPECIAL_MOVZ:
3816 dpavlin 22 case SPECIAL_MFHI:
3817     case SPECIAL_MFLO:
3818     case SPECIAL_MTHI:
3819     case SPECIAL_MTLO:
3820 dpavlin 24 case SPECIAL_DIV:
3821     case SPECIAL_DIVU:
3822     case SPECIAL_DDIV:
3823     case SPECIAL_DDIVU:
3824     case SPECIAL_MULT:
3825     case SPECIAL_MULTU:
3826     case SPECIAL_DMULT:
3827     case SPECIAL_DMULTU:
3828     case SPECIAL_TGE:
3829     case SPECIAL_TGEU:
3830     case SPECIAL_TLT:
3831     case SPECIAL_TLTU:
3832     case SPECIAL_TEQ:
3833     case SPECIAL_TNE:
3834 dpavlin 22 switch (s6) {
3835 dpavlin 24 case SPECIAL_ADD: ic->f = instr(add); break;
3836 dpavlin 22 case SPECIAL_ADDU: ic->f = instr(addu); break;
3837 dpavlin 24 case SPECIAL_SUB: ic->f = instr(sub); break;
3838 dpavlin 22 case SPECIAL_SUBU: ic->f = instr(subu); break;
3839 dpavlin 24 case SPECIAL_DADD: ic->f = instr(dadd); x64=1; break;
3840 dpavlin 22 case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
3841 dpavlin 24 case SPECIAL_DSUB: ic->f = instr(dsub); x64=1; break;
3842 dpavlin 22 case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;
3843     case SPECIAL_SLT: ic->f = instr(slt); break;
3844     case SPECIAL_SLTU: ic->f = instr(sltu); break;
3845 dpavlin 24 case SPECIAL_AND: ic->f = instr(and); break;
3846 dpavlin 22 case SPECIAL_OR: ic->f = instr(or); break;
3847     case SPECIAL_XOR: ic->f = instr(xor); break;
3848     case SPECIAL_NOR: ic->f = instr(nor); break;
3849     case SPECIAL_MFHI: ic->f = instr(mov); break;
3850     case SPECIAL_MFLO: ic->f = instr(mov); break;
3851     case SPECIAL_MTHI: ic->f = instr(mov); break;
3852     case SPECIAL_MTLO: ic->f = instr(mov); break;
3853 dpavlin 24 case SPECIAL_DIV: ic->f = instr(div); break;
3854     case SPECIAL_DIVU: ic->f = instr(divu); break;
3855     case SPECIAL_DDIV: ic->f = instr(ddiv); x64=1; break;
3856     case SPECIAL_DDIVU: ic->f = instr(ddivu); x64=1; break;
3857     case SPECIAL_MULT : ic->f = instr(mult); break;
3858     case SPECIAL_MULTU: ic->f = instr(multu); break;
3859     case SPECIAL_DMULT: ic->f = instr(dmult); x64=1; break;
3860     case SPECIAL_DMULTU:ic->f = instr(dmultu); x64=1; break;
3861     case SPECIAL_TGE: ic->f = instr(tge); break;
3862     case SPECIAL_TGEU: ic->f = instr(tgeu); break;
3863     case SPECIAL_TLT: ic->f = instr(tlt); break;
3864     case SPECIAL_TLTU: ic->f = instr(tltu); break;
3865     case SPECIAL_TEQ: ic->f = instr(teq); break;
3866     case SPECIAL_TNE: ic->f = instr(tne); break;
3867     case SPECIAL_MOVN: ic->f = instr(movn); break;
3868     case SPECIAL_MOVZ: ic->f = instr(movz); break;
3869 dpavlin 22 }
3870     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3871     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3872     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3873     switch (s6) {
3874     case SPECIAL_MFHI:
3875     ic->arg[0] = (size_t)&cpu->cd.mips.hi;
3876     break;
3877     case SPECIAL_MFLO:
3878     ic->arg[0] = (size_t)&cpu->cd.mips.lo;
3879     break;
3880     case SPECIAL_MTHI:
3881     ic->arg[2] = (size_t)&cpu->cd.mips.hi;
3882     break;
3883     case SPECIAL_MTLO:
3884     ic->arg[2] = (size_t)&cpu->cd.mips.lo;
3885     break;
3886     }
3887 dpavlin 24 /* Special cases for rd: */
3888 dpavlin 22 switch (s6) {
3889     case SPECIAL_MTHI:
3890     case SPECIAL_MTLO:
3891 dpavlin 24 case SPECIAL_DIV:
3892     case SPECIAL_DIVU:
3893     case SPECIAL_DDIV:
3894     case SPECIAL_DDIVU:
3895 dpavlin 22 case SPECIAL_MULT:
3896     case SPECIAL_MULTU:
3897     case SPECIAL_DMULT:
3898     case SPECIAL_DMULTU:
3899 dpavlin 24 case SPECIAL_TGE:
3900     case SPECIAL_TGEU:
3901     case SPECIAL_TLT:
3902     case SPECIAL_TLTU:
3903     case SPECIAL_TEQ:
3904     case SPECIAL_TNE:
3905     if (s6 == SPECIAL_MULT && rd != MIPS_GPR_ZERO) {
3906     if (cpu->cd.mips.cpu_type.rev ==
3907     MIPS_R5900) {
3908     ic->f = instr(mult_r5900);
3909     break;
3910     }
3911     break;
3912     }
3913     if (s6 == SPECIAL_MULTU && rd!=MIPS_GPR_ZERO) {
3914     if (cpu->cd.mips.cpu_type.rev ==
3915     MIPS_R5900) {
3916     ic->f = instr(multu_r5900);
3917     break;
3918     }
3919     }
3920 dpavlin 22 if (rd != MIPS_GPR_ZERO) {
3921 dpavlin 24 fatal("TODO: rd NON-zero\n");
3922 dpavlin 22 goto bad;
3923     }
3924 dpavlin 24 /* These instructions don't use rd. */
3925 dpavlin 22 break;
3926 dpavlin 24 default:if (rd == MIPS_GPR_ZERO)
3927     ic->f = instr(nop);
3928 dpavlin 22 }
3929 dpavlin 30
3930     if (ic->f == instr(addu))
3931     cpu->cd.mips.combination_check = COMBINE(addu);
3932 dpavlin 22 break;
3933    
3934     case SPECIAL_JR:
3935     case SPECIAL_JALR:
3936     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3937     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
3938 dpavlin 24 if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
3939     s6 = SPECIAL_JR;
3940     ic->arg[2] = (addr & 0xffc) + 8;
3941     switch (s6) {
3942 dpavlin 22 case SPECIAL_JR:
3943     if (rs == MIPS_GPR_RA) {
3944     if (cpu->machine->show_trace_tree)
3945     ic->f = instr(jr_ra_trace);
3946     else
3947     ic->f = instr(jr_ra);
3948     } else {
3949     ic->f = instr(jr);
3950     }
3951     break;
3952     case SPECIAL_JALR:
3953     if (cpu->machine->show_trace_tree)
3954     ic->f = instr(jalr_trace);
3955     else
3956     ic->f = instr(jalr);
3957     break;
3958     }
3959 dpavlin 24 if (cpu->delay_slot) {
3960     fatal("TODO: branch in delay slot? (1)\n");
3961     goto bad;
3962 dpavlin 22 }
3963     break;
3964    
3965 dpavlin 24 case SPECIAL_SYSCALL:
3966     if (((iword >> 6) & 0xfffff) == 0x30378) {
3967     /* "Magic trap" for PROM emulation: */
3968     ic->f = instr(promemul);
3969     } else {
3970     ic->f = instr(syscall);
3971     }
3972     break;
3973    
3974     case SPECIAL_BREAK:
3975 dpavlin 30 if (((iword >> 6) & 0xfffff) == 0x30378) {
3976     /* "Magic trap" for REBOOT: */
3977     ic->f = instr(reboot);
3978     } else {
3979     ic->f = instr(break);
3980     }
3981 dpavlin 24 break;
3982    
3983 dpavlin 22 case SPECIAL_SYNC:
3984     ic->f = instr(nop);
3985     break;
3986    
3987     default:goto bad;
3988     }
3989     break;
3990    
3991     case HI6_BEQ:
3992     case HI6_BNE:
3993 dpavlin 24 case HI6_BEQL:
3994     case HI6_BNEL:
3995     case HI6_BLEZ:
3996     case HI6_BLEZL:
3997     case HI6_BGTZ:
3998     case HI6_BGTZL:
3999 dpavlin 22 samepage_function = NULL; /* get rid of a compiler warning */
4000     switch (main_opcode) {
4001     case HI6_BEQ:
4002     ic->f = instr(beq);
4003     samepage_function = instr(beq_samepage);
4004     /* Special case: comparing a register with itself: */
4005     if (rs == rt) {
4006     ic->f = instr(b);
4007     samepage_function = instr(b_samepage);
4008     }
4009     break;
4010     case HI6_BNE:
4011     ic->f = instr(bne);
4012     samepage_function = instr(bne_samepage);
4013 dpavlin 24 break;
4014     case HI6_BEQL:
4015     ic->f = instr(beql);
4016     samepage_function = instr(beql_samepage);
4017     /* Special case: comparing a register with itself: */
4018     if (rs == rt) {
4019     ic->f = instr(b);
4020     samepage_function = instr(b_samepage);
4021     }
4022     break;
4023     case HI6_BNEL:
4024     ic->f = instr(bnel);
4025     samepage_function = instr(bnel_samepage);
4026     break;
4027     case HI6_BLEZ:
4028     ic->f = instr(blez);
4029     samepage_function = instr(blez_samepage);
4030     break;
4031     case HI6_BLEZL:
4032     ic->f = instr(blezl);
4033     samepage_function = instr(blezl_samepage);
4034     break;
4035     case HI6_BGTZ:
4036     ic->f = instr(bgtz);
4037     samepage_function = instr(bgtz_samepage);
4038     break;
4039     case HI6_BGTZL:
4040     ic->f = instr(bgtzl);
4041     samepage_function = instr(bgtzl_samepage);
4042     break;
4043 dpavlin 22 }
4044     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4045     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4046 dpavlin 24 ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
4047     + (addr & 0xffc) + 4 );
4048 dpavlin 22 /* Is the offset from the start of the current page still
4049     within the same page? Then use the samepage_function: */
4050     if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE - 1)
4051     << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc) < 0xffc) {
4052     ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page +
4053     ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
4054     & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
4055     ic->f = samepage_function;
4056     }
4057 dpavlin 24 if (cpu->delay_slot) {
4058     fatal("TODO: branch in delay slot? (2)\n");
4059     goto bad;
4060 dpavlin 22 }
4061     break;
4062    
4063 dpavlin 24 case HI6_ADDI:
4064 dpavlin 22 case HI6_ADDIU:
4065 dpavlin 24 case HI6_SLTI:
4066     case HI6_SLTIU:
4067     case HI6_DADDI:
4068 dpavlin 22 case HI6_DADDIU:
4069     case HI6_ANDI:
4070     case HI6_ORI:
4071     case HI6_XORI:
4072     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4073     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4074     if (main_opcode == HI6_ADDI ||
4075     main_opcode == HI6_ADDIU ||
4076 dpavlin 24 main_opcode == HI6_SLTI ||
4077     main_opcode == HI6_SLTIU ||
4078 dpavlin 22 main_opcode == HI6_DADDI ||
4079     main_opcode == HI6_DADDIU)
4080     ic->arg[2] = (int16_t)iword;
4081     else
4082     ic->arg[2] = (uint16_t)iword;
4083 dpavlin 24
4084 dpavlin 22 switch (main_opcode) {
4085 dpavlin 24 case HI6_ADDI: ic->f = instr(addi); break;
4086 dpavlin 22 case HI6_ADDIU: ic->f = instr(addiu); break;
4087 dpavlin 24 case HI6_SLTI: ic->f = instr(slti); break;
4088     case HI6_SLTIU: ic->f = instr(sltiu); break;
4089     case HI6_DADDI: ic->f = instr(daddi); x64 = 1; break;
4090 dpavlin 22 case HI6_DADDIU: ic->f = instr(daddiu); x64 = 1; break;
4091     case HI6_ANDI: ic->f = instr(andi); break;
4092     case HI6_ORI: ic->f = instr(ori); break;
4093     case HI6_XORI: ic->f = instr(xori); break;
4094     }
4095 dpavlin 24
4096 dpavlin 28 if (ic->arg[2] == 0) {
4097     if ((cpu->is_32bit && ic->f == instr(addiu)) ||
4098     (!cpu->is_32bit && ic->f == instr(daddiu))) {
4099     ic->f = instr(mov);
4100     ic->arg[2] = ic->arg[1];
4101     }
4102     }
4103    
4104 dpavlin 22 if (rt == MIPS_GPR_ZERO)
4105     ic->f = instr(nop);
4106    
4107 dpavlin 30 if (ic->f == instr(ori))
4108     cpu->cd.mips.combination_check = COMBINE(ori);
4109 dpavlin 22 if (ic->f == instr(addiu))
4110 dpavlin 28 cpu->cd.mips.combination_check = COMBINE(addiu);
4111 dpavlin 24 if (ic->f == instr(daddiu))
4112     cpu->cd.mips.combination_check = COMBINE(b_daddiu);
4113 dpavlin 22 break;
4114    
4115     case HI6_LUI:
4116     ic->f = instr(set);
4117     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4118 dpavlin 24 ic->arg[1] = (int32_t) (imm << 16);
4119 dpavlin 28 /* NOTE: Don't use arg[2] here. It can be used with
4120     instruction combinations, to do lui + addiu, etc. */
4121 dpavlin 22 if (rt == MIPS_GPR_ZERO)
4122     ic->f = instr(nop);
4123     break;
4124    
4125 dpavlin 24 case HI6_J:
4126     case HI6_JAL:
4127     switch (main_opcode) {
4128     case HI6_J:
4129     ic->f = instr(j);
4130     break;
4131     case HI6_JAL:
4132     if (cpu->machine->show_trace_tree)
4133     ic->f = instr(jal_trace);
4134     else
4135     ic->f = instr(jal);
4136     break;
4137     }
4138     ic->arg[0] = (iword & 0x03ffffff) << 2;
4139     ic->arg[1] = (addr & 0xffc) + 8;
4140     if (cpu->delay_slot) {
4141     fatal("TODO: branch in delay slot (=%i)? (3); addr=%016"
4142     PRIx64" iword=%08"PRIx32"\n", cpu->delay_slot,
4143     (uint64_t)addr, iword);
4144     goto bad;
4145     }
4146     break;
4147    
4148 dpavlin 22 case HI6_COP0:
4149 dpavlin 24 /* TODO: Is checking bit 25 enough, or perhaps all bits
4150     25..21 must be checked? */
4151     if ((iword >> 25) & 1) {
4152     ic->arg[2] = addr & 0xffc;
4153     switch (iword & 0xff) {
4154     case COP0_TLBR:
4155     ic->f = instr(tlbr);
4156     break;
4157     case COP0_TLBWI:
4158     case COP0_TLBWR:
4159     ic->f = instr(tlbw);
4160     ic->arg[0] = (iword & 0xff) == COP0_TLBWR;
4161     break;
4162     case COP0_TLBP:
4163     ic->f = instr(tlbp);
4164     break;
4165     case COP0_RFE:
4166     ic->f = instr(rfe);
4167     break;
4168     case COP0_ERET:
4169     ic->f = instr(eret);
4170     break;
4171     case COP0_DERET:
4172     ic->f = instr(deret);
4173     break;
4174 dpavlin 30 case COP0_WAIT:
4175     ic->f = instr(wait);
4176     if (cpu->cd.mips.cpu_type.rev != MIPS_RM5200 &&
4177     cpu->cd.mips.cpu_type.isa_level < 32) {
4178     static int warned = 0;
4179     ic->f = instr(reserved);
4180     if (!warned) {
4181     fatal("{ WARNING: Attempt to "
4182     "execute the WAIT instruct"
4183     "ion, but the emulated CPU "
4184     "is neither RM52xx, nor "
4185     "MIPS32/64! }\n");
4186     warned = 1;
4187     }
4188     }
4189     break;
4190 dpavlin 24 case COP0_STANDBY:
4191     case COP0_SUSPEND:
4192     case COP0_HIBERNATE:
4193     /* TODO */
4194     ic->f = instr(nop);
4195     break;
4196     case COP0_EI:
4197     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4198     ic->f = instr(ei_r5900);
4199     } else
4200     goto bad;
4201     break;
4202     case COP0_DI:
4203     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4204     ic->f = instr(di_r5900);
4205     } else
4206     goto bad;
4207     break;
4208     default:fatal("UNIMPLEMENTED cop0 (func 0x%02x)\n",
4209     iword & 0xff);
4210     goto bad;
4211     }
4212     break;
4213     }
4214    
4215 dpavlin 22 /* rs contains the coprocessor opcode! */
4216     switch (rs) {
4217 dpavlin 24 case COPz_CFCz:
4218     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4219     ic->arg[1] = rd + ((iword & 7) << 5);
4220     ic->arg[2] = addr & 0xffc;
4221     ic->f = instr(cfc0);
4222     if (rt == MIPS_GPR_ZERO)
4223     ic->f = instr(nop);
4224     break;
4225 dpavlin 22 case COPz_MFCz:
4226     case COPz_DMFCz:
4227     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4228     ic->arg[1] = rd + ((iword & 7) << 5);
4229     ic->arg[2] = addr & 0xffc;
4230     ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);
4231     if (rt == MIPS_GPR_ZERO)
4232     ic->f = instr(nop);
4233     break;
4234     case COPz_MTCz:
4235     case COPz_DMTCz:
4236     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4237     ic->arg[1] = rd + ((iword & 7) << 5);
4238     ic->arg[2] = addr & 0xffc;
4239     ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
4240 dpavlin 28
4241     if (cpu->cd.mips.cpu_type.exc_model == EXC3K &&
4242     rs == COPz_MTCz && rd == COP0_STATUS)
4243     cpu->cd.mips.combination_check =
4244     COMBINE(netbsd_r3k_cache_inv);
4245    
4246 dpavlin 22 break;
4247 dpavlin 24 case 8: if (iword == 0x4100ffff) {
4248     /* R2020 DECstation write-loop thingy. */
4249     ic->f = instr(nop);
4250     } else {
4251     fatal("Unimplemented blah blah zzzz...\n");
4252     goto bad;
4253     }
4254     break;
4255    
4256 dpavlin 22 default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
4257     goto bad;
4258     }
4259     break;
4260    
4261     case HI6_COP1:
4262 dpavlin 24 /* Always cause a coprocessor unusable exception if
4263     there is no floating point coprocessor: */
4264     if (cpu->cd.mips.cpu_type.flags & NOFPU ||
4265     cpu->cd.mips.coproc[1] == NULL) {
4266     ic->f = instr(cpu);
4267     ic->arg[0] = 1;
4268     break;
4269     }
4270    
4271     /* Bits 25..21 are floating point main opcode: */
4272 dpavlin 22 switch (rs) {
4273 dpavlin 24
4274     case COPz_BCzc:
4275     /* Conditional branch: */
4276     /* TODO: Reimplement this in a faster way. */
4277     ic->f = instr(cop1_bc);
4278     ic->arg[0] = (iword >> 18) & 7; /* cc */
4279     ic->arg[1] = (iword >> 16) & 3; /* nd, tf bits */
4280     ic->arg[2] = (int32_t) ((imm <<
4281     MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);
4282     if (cpu->delay_slot) {
4283     fatal("TODO: branch in delay slot? (4)\n");
4284     goto bad;
4285     }
4286     if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
4287     ic->arg[0] != 0) {
4288     fatal("Attempt to execute a non-cc-0 BC*"
4289     " instruction on an isa level %i cpu. "
4290     "TODO: How should this be handled?\n",
4291     cpu->cd.mips.cpu_type.isa_level);
4292     goto bad;
4293     }
4294    
4295     break;
4296    
4297     case COPz_DMFCz:
4298     case COPz_DMTCz:
4299     x64 = 1;
4300     /* FALL-THROUGH */
4301     case COP1_FMT_S:
4302     case COP1_FMT_D:
4303     case COP1_FMT_W:
4304     case COP1_FMT_L:
4305     case COP1_FMT_PS:
4306 dpavlin 22 case COPz_CFCz:
4307 dpavlin 24 case COPz_CTCz:
4308     case COPz_MFCz:
4309     case COPz_MTCz:
4310     /* Fallback to slow pre-dyntrans code, for now. */
4311     /* TODO: Fix/optimize/rewrite. */
4312     ic->f = instr(cop1_slow);
4313     ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);
4314 dpavlin 22 break;
4315 dpavlin 24
4316     default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
4317 dpavlin 22 goto bad;
4318     }
4319     break;
4320    
4321 dpavlin 24 case HI6_COP2:
4322     /* Always cause a coprocessor unusable exception if
4323     there is no coprocessor 2: */
4324     if (cpu->cd.mips.coproc[2] == NULL) {
4325     ic->f = instr(cpu);
4326     ic->arg[0] = 2;
4327     break;
4328     }
4329     fatal("COP2 functionality not yet implemented\n");
4330     goto bad;
4331     break;
4332    
4333 dpavlin 22 case HI6_SPECIAL2:
4334 dpavlin 24 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4335     /* R5900, TX79/C790, have MMI instead of SPECIAL2: */
4336     int mmi_subopcode = (iword >> 6) & 0x1f;
4337    
4338     switch (s6) {
4339    
4340     case MMI_MADD:
4341     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4342     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4343     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4344     if (rd == MIPS_GPR_ZERO)
4345     ic->f = instr(madd);
4346     else
4347     ic->f = instr(madd_rd);
4348     break;
4349    
4350     case MMI_MADDU:
4351     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4352     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4353     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4354     if (rd == MIPS_GPR_ZERO)
4355     ic->f = instr(maddu);
4356     else
4357     ic->f = instr(maddu_rd);
4358     break;
4359    
4360     case MMI_MMI0:
4361     switch (mmi_subopcode) {
4362    
4363     case MMI0_PEXTLW:
4364     ic->arg[0] = rs;
4365     ic->arg[1] = rt;
4366     ic->arg[2] = rd;
4367     if (rd == MIPS_GPR_ZERO)
4368     ic->f = instr(nop);
4369     else
4370     ic->f = instr(pextlw);
4371     break;
4372    
4373     default:goto bad;
4374     }
4375     break;
4376    
4377     case MMI_MMI3:
4378     switch (mmi_subopcode) {
4379    
4380     case MMI3_POR:
4381     ic->arg[0] = rs;
4382     ic->arg[1] = rt;
4383     ic->arg[2] = rd;
4384     if (rd == MIPS_GPR_ZERO)
4385     ic->f = instr(nop);
4386     else
4387     ic->f = instr(por);
4388     break;
4389    
4390     default:goto bad;
4391     }
4392     break;
4393    
4394     default:goto bad;
4395     }
4396     break;
4397     }
4398    
4399     /* TODO: is this correct? Or are there other non-MIPS32/64
4400     MIPS processors that have support for SPECIAL2 opcodes? */
4401     if (cpu->cd.mips.cpu_type.isa_level < 32) {
4402     ic->f = instr(reserved);
4403     break;
4404     }
4405    
4406     /* SPECIAL2: */
4407 dpavlin 22 switch (s6) {
4408    
4409 dpavlin 24 case SPECIAL2_MADD:
4410     case SPECIAL2_MADDU:
4411     case SPECIAL2_MSUB:
4412     case SPECIAL2_MSUBU:
4413     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4414     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4415     switch (s6) {
4416     case SPECIAL2_MADD: ic->f = instr(madd); break;
4417     case SPECIAL2_MADDU:ic->f = instr(maddu); break;
4418     case SPECIAL2_MSUB: ic->f = instr(msub); break;
4419     case SPECIAL2_MSUBU:ic->f = instr(msubu); break;
4420     }
4421     break;
4422    
4423 dpavlin 22 case SPECIAL2_MUL:
4424     ic->f = instr(mul);
4425     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4426     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4427     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4428     if (rd == MIPS_GPR_ZERO)
4429     ic->f = instr(nop);
4430     break;
4431    
4432     case SPECIAL2_CLZ:
4433     case SPECIAL2_CLO:
4434     case SPECIAL2_DCLZ:
4435     case SPECIAL2_DCLO:
4436     switch (s6) {
4437     case SPECIAL2_CLZ: ic->f = instr(clz); break;
4438     case SPECIAL2_CLO: ic->f = instr(clo); break;
4439     case SPECIAL2_DCLZ: ic->f = instr(dclz); break;
4440     case SPECIAL2_DCLO: ic->f = instr(dclo); break;
4441     }
4442     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4443     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4444     if (rd == MIPS_GPR_ZERO)
4445     ic->f = instr(nop);
4446     break;
4447    
4448     default:goto bad;
4449     }
4450     break;
4451    
4452 dpavlin 24 case HI6_REGIMM:
4453     switch (rt) {
4454     case REGIMM_BGEZ:
4455     case REGIMM_BGEZL:
4456     case REGIMM_BLTZ:
4457     case REGIMM_BLTZL:
4458     case REGIMM_BGEZAL:
4459     case REGIMM_BGEZALL:
4460     case REGIMM_BLTZAL:
4461     case REGIMM_BLTZALL:
4462     samepage_function = NULL;
4463     switch (rt) {
4464     case REGIMM_BGEZ:
4465     ic->f = instr(bgez);
4466     samepage_function = instr(bgez_samepage);
4467     break;
4468     case REGIMM_BGEZL:
4469     ic->f = instr(bgezl);
4470     samepage_function = instr(bgezl_samepage);
4471     break;
4472     case REGIMM_BLTZ:
4473     ic->f = instr(bltz);
4474     samepage_function = instr(bltz_samepage);
4475     break;
4476     case REGIMM_BLTZL:
4477     ic->f = instr(bltzl);
4478     samepage_function = instr(bltzl_samepage);
4479     break;
4480     case REGIMM_BGEZAL:
4481     ic->f = instr(bgezal);
4482     samepage_function = instr(bgezal_samepage);
4483     break;
4484     case REGIMM_BGEZALL:
4485     ic->f = instr(bgezall);
4486     samepage_function = instr(bgezall_samepage);
4487     break;
4488     case REGIMM_BLTZAL:
4489     ic->f = instr(bltzal);
4490     samepage_function = instr(bltzal_samepage);
4491     break;
4492     case REGIMM_BLTZALL:
4493     ic->f = instr(bltzall);
4494     samepage_function = instr(bltzall_samepage);
4495     break;
4496     }
4497     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4498     ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
4499     + (addr & 0xffc) + 4;
4500     /* Is the offset from the start of the current page
4501     still within the same page? Then use the
4502     samepage_function: */
4503     if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE-1)
4504     << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc)
4505     < 0xffc) {
4506     ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page+
4507     ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
4508     & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
4509     ic->f = samepage_function;
4510     }
4511     if (cpu->delay_slot) {
4512     fatal("TODO: branch in delay slot? (5)\n");
4513     goto bad;
4514     }
4515     break;
4516     default:fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
4517     goto bad;
4518     }
4519     break;
4520    
4521     case HI6_LB:
4522     case HI6_LBU:
4523     case HI6_SB:
4524     case HI6_LH:
4525     case HI6_LHU:
4526     case HI6_SH:
4527     case HI6_LW:
4528     case HI6_LWU:
4529     case HI6_SW:
4530     case HI6_LD:
4531     case HI6_SD:
4532     /* TODO: LWU should probably also be x64=1? */
4533     size = 2; signedness = 0; store = 0;
4534     switch (main_opcode) {
4535     case HI6_LB: size = 0; signedness = 1; break;
4536     case HI6_LBU: size = 0; break;
4537     case HI6_LH: size = 1; signedness = 1; break;
4538     case HI6_LHU: size = 1; break;
4539     case HI6_LW: signedness = 1; break;
4540     case HI6_LWU: break;
4541     case HI6_LD: size = 3; x64 = 1; break;
4542     case HI6_SB: store = 1; size = 0; break;
4543     case HI6_SH: store = 1; size = 1; break;
4544     case HI6_SW: store = 1; break;
4545     case HI6_SD: store = 1; size = 3; x64 = 1; break;
4546     }
4547    
4548     ic->f =
4549     #ifdef MODE32
4550     mips32_loadstore
4551     #else
4552     mips_loadstore
4553     #endif
4554     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16)
4555     + store * 8 + size * 2 + signedness];
4556     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4557     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4558     ic->arg[2] = (int32_t)imm;
4559    
4560     /* Load into the dummy scratch register, if rt = zero */
4561     if (!store && rt == MIPS_GPR_ZERO)
4562     ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4563 dpavlin 28
4564 dpavlin 30 /* Check for multiple loads or stores in a row using the same
4565 dpavlin 28 base register: */
4566 dpavlin 30 #ifdef MODE32
4567     if (main_opcode == HI6_LW)
4568     cpu->cd.mips.combination_check = COMBINE(multi_lw);
4569     if (main_opcode == HI6_SW)
4570 dpavlin 28 cpu->cd.mips.combination_check = COMBINE(multi_sw);
4571 dpavlin 30 #endif
4572 dpavlin 24 break;
4573    
4574     case HI6_LL:
4575     case HI6_LLD:
4576     case HI6_SC:
4577     case HI6_SCD:
4578     /* 32-bit load-linked/store-condition for ISA II and up: */
4579     /* (64-bit load-linked/store-condition for ISA III...) */
4580     if (cpu->cd.mips.cpu_type.isa_level < 2) {
4581     ic->f = instr(reserved);
4582     break;
4583     }
4584    
4585     store = 0;
4586     switch (main_opcode) {
4587     case HI6_LL: ic->f = instr(ll); break;
4588     case HI6_LLD: ic->f = instr(lld); x64 = 1; break;
4589     case HI6_SC: ic->f = instr(sc); store = 1; break;
4590     case HI6_SCD: ic->f = instr(scd); store = 1; x64 = 1; break;
4591     }
4592     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4593     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4594     ic->arg[2] = (int32_t)imm;
4595     if (!store && rt == MIPS_GPR_ZERO) {
4596     fatal("HM... unusual load linked\n");
4597     goto bad;
4598     }
4599     break;
4600    
4601     case HI6_LWL:
4602     case HI6_LWR:
4603     case HI6_LDL:
4604     case HI6_LDR:
4605     case HI6_SWL:
4606     case HI6_SWR:
4607     case HI6_SDL:
4608     case HI6_SDR:
4609     /* TODO: replace these with faster versions... */
4610     store = 0;
4611     switch (main_opcode) {
4612     case HI6_LWL: ic->f = instr(lwl); break;
4613     case HI6_LWR: ic->f = instr(lwr); break;
4614     case HI6_LDL: ic->f = instr(ldl); x64 = 1; break;
4615     case HI6_LDR: ic->f = instr(ldr); x64 = 1; break;
4616     case HI6_SWL: ic->f = instr(swl); store = 1; break;
4617     case HI6_SWR: ic->f = instr(swr); store = 1; break;
4618     case HI6_SDL: ic->f = instr(sdl); store = 1; x64 = 1; break;
4619     case HI6_SDR: ic->f = instr(sdr); store = 1; x64 = 1; break;
4620     }
4621     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4622     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4623     ic->arg[2] = (int32_t)imm;
4624    
4625     /* Load into the dummy scratch register, if rt = zero */
4626     if (!store && rt == MIPS_GPR_ZERO)
4627     ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4628     break;
4629    
4630     case HI6_LWC1:
4631     case HI6_SWC1:
4632     case HI6_LDC1:
4633     case HI6_SDC1:
4634     /* 64-bit floating-point load/store for ISA II and up... */
4635     if ((main_opcode == HI6_LDC1 || main_opcode == HI6_SDC1)
4636     && cpu->cd.mips.cpu_type.isa_level < 2) {
4637     ic->f = instr(reserved);
4638     break;
4639     }
4640    
4641     ic->arg[0] = (size_t)&cpu->cd.mips.coproc[1]->reg[rt];
4642     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4643     ic->arg[2] = (int32_t)imm;
4644     switch (main_opcode) {
4645     case HI6_LWC1: ic->f = instr(lwc1); break;
4646     case HI6_LDC1: ic->f = instr(ldc1); break;
4647     case HI6_SWC1: ic->f = instr(swc1); break;
4648     case HI6_SDC1: ic->f = instr(sdc1); break;
4649     }
4650    
4651     /* Cause a coprocessor unusable exception if
4652     there is no floating point coprocessor: */
4653     if (cpu->cd.mips.cpu_type.flags & NOFPU ||
4654     cpu->cd.mips.coproc[1] == NULL) {
4655     ic->f = instr(cpu);
4656     ic->arg[0] = 1;
4657     }
4658     break;
4659    
4660     case HI6_LWC3:
4661     /* PREF (prefetch) on ISA IV and MIPS32/64: */
4662     if (cpu->cd.mips.cpu_type.isa_level >= 4) {
4663     /* Treat as nop for now: */
4664     ic->f = instr(nop);
4665     } else {
4666     fatal("TODO: lwc3 not implemented yet\n");
4667     goto bad;
4668     }
4669     break;
4670    
4671     case HI6_LQ_MDMX:
4672     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4673     fatal("TODO: R5900 128-bit loads\n");
4674     goto bad;
4675     }
4676    
4677     fatal("TODO: MDMX\n");
4678     goto bad;
4679     /* break */
4680    
4681     case HI6_SQ_SPECIAL3:
4682     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4683     fatal("TODO: R5900 128-bit stores\n");
4684     goto bad;
4685     }
4686    
4687     if (cpu->cd.mips.cpu_type.isa_level < 32 ||
4688     cpu->cd.mips.cpu_type.isa_revision < 2) {
4689     static int warning = 0;
4690     if (!warning) {
4691 dpavlin 28 fatal("[ WARNING! SPECIAL3 opcode used, but"
4692     " the %s processor does not implement "
4693     "such instructions. Only printing this "
4694     "warning once. ]\n",
4695     cpu->cd.mips.cpu_type.name);
4696 dpavlin 24 warning = 1;
4697     }
4698     ic->f = instr(reserved);
4699     break;
4700     }
4701    
4702     switch (s6) {
4703    
4704     case SPECIAL3_RDHWR:
4705     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4706    
4707     switch (rd) {
4708    
4709     case 0: ic->f = instr(rdhwr_cpunum);
4710     if (rt == MIPS_GPR_ZERO)
4711     ic->f = instr(nop);
4712     break;
4713    
4714     default:fatal("unimplemented rdhwr register rd=%i\n",
4715     rd);
4716     goto bad;
4717     }
4718     break;
4719    
4720     default:goto bad;
4721     }
4722     break;
4723    
4724     case HI6_CACHE:
4725     /* TODO: rt and op etc... */
4726     ic->f = instr(cache);
4727     break;
4728    
4729 dpavlin 22 default:goto bad;
4730     }
4731    
4732 dpavlin 24 #ifdef MODE32
4733     if (x64) {
4734     static int has_warned = 0;
4735     if (!has_warned)
4736     fatal("[ WARNING/NOTE: attempt to execute a 64-bit"
4737     " instruction on an emulated 32-bit processor; "
4738     "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);
4739     has_warned = 1;
4740     ic->f = instr(reserved);
4741     }
4742     #endif
4743 dpavlin 22
4744 dpavlin 28 if (ic->f == instr(nop) && cpu->cd.mips.combination_check == NULL)
4745     cpu->cd.mips.combination_check = COMBINE(nop);
4746 dpavlin 22
4747 dpavlin 28
4748 dpavlin 22 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
4749     #include "cpu_dyntrans.c"
4750     #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
4751     }
4752    

  ViewVC Help
Powered by ViewVC 1.1.26