/[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 28 - (hide annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 106893 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


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 28 * $Id: cpu_mips_instr.c,v 1.97 2006/07/20 03:20:03 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 26 if (status & (STATUS_EXL | STATUS_ERL))
1683     status &= ~STATUS_IE;
1684     /* Ugly R5900 special case: (TODO: move this?) */
1685     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1686     !(status & R5900_STATUS_EIE))
1687     status &= ~STATUS_IE;
1688     if (status & STATUS_IE && (status & cause & STATUS_IM_MASK)) {
1689     cpu->pc += sizeof(uint32_t);
1690     mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0,0,0,0,0);
1691     }
1692 dpavlin 24 }
1693 dpavlin 22 }
1694     X(dmfc0)
1695     {
1696     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1697     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1698     cpu->pc |= ic->arg[2];
1699     /* TODO: cause exception if necessary */
1700     coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,
1701     (uint64_t *)ic->arg[0], select);
1702     }
1703     X(dmtc0)
1704     {
1705     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1706     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1707     cpu->pc |= ic->arg[2];
1708     /* TODO: cause exception if necessary */
1709     coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,
1710     (uint64_t *)ic->arg[0], 1, select);
1711     }
1712 dpavlin 24
1713    
1714     /*
1715     * cop1_bc: Floating point conditional branch.
1716     *
1717     * arg[0] = cc
1718     * arg[1] = nd (=2) and tf (=1) bits
1719     * arg[2] = offset (relative to start of this page)
1720     */
1721     X(cop1_bc)
1722 dpavlin 22 {
1723 dpavlin 24 MODE_int_t old_pc = cpu->pc;
1724     const int cpnr = 1;
1725     int x, low_pc, cc = ic->arg[0];
1726    
1727     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1728     / sizeof(struct mips_instr_call);
1729     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1730     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1731     if (!(cpu->cd.mips.coproc[0]->
1732     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1733     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1734     return;
1735     }
1736    
1737     /* Get the correct condition code bit: */
1738     if (cc == 0)
1739     x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1740     >> MIPS_FCSR_FCC0_SHIFT) & 1;
1741     else
1742     x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1743     >> (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;
1744    
1745     /* Branch on false? Then invert the truth value. */
1746     if (!(ic->arg[1] & 1))
1747     x ^= 1;
1748    
1749     /* Execute the delay slot (except if it is nullified): */
1750     cpu->delay_slot = TO_BE_DELAYED;
1751     if (x || !(ic->arg[1] & 2))
1752     ic[1].f(cpu, ic+1);
1753     cpu->n_translated_instrs ++;
1754    
1755     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1756     /* Note: Must be non-delayed when jumping to the new pc: */
1757     cpu->delay_slot = NOT_DELAYED;
1758     if (x) {
1759     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1760     MIPS_INSTR_ALIGNMENT_SHIFT);
1761     cpu->pc = old_pc + (int32_t)ic->arg[2];
1762     quick_pc_to_pointers(cpu);
1763     } else
1764     cpu->cd.mips.next_ic ++;
1765     } else
1766     cpu->delay_slot = NOT_DELAYED;
1767     }
1768    
1769    
1770     /*
1771     * cop1_slow: Fallback to legacy cop1 code. (Slow, but it should work.)
1772     */
1773     X(cop1_slow)
1774     {
1775     const int cpnr = 1;
1776     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1777     / sizeof(struct mips_instr_call);
1778     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1779     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1780    
1781     if (!(cpu->cd.mips.coproc[0]->
1782     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1783     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1784     return;
1785     }
1786    
1787     coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1788     }
1789    
1790    
1791     /*
1792     * syscall, break: Synchronize the PC and cause an exception.
1793     */
1794     X(syscall)
1795     {
1796     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1797     / sizeof(struct mips_instr_call);
1798     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1799     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1800     mips_cpu_exception(cpu, EXCEPTION_SYS, 0, 0, 0, 0, 0, 0);
1801     }
1802     X(break)
1803     {
1804     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1805     / sizeof(struct mips_instr_call);
1806     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1807     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1808     mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1809     }
1810    
1811    
1812     /*
1813     * promemul: PROM software emulation.
1814     */
1815     X(promemul)
1816     {
1817     /* Synchronize the PC and call the correct emulation layer: */
1818     MODE_int_t old_pc;
1819     int res, low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1820     / sizeof(struct mips_instr_call);
1821     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1822     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1823     old_pc = cpu->pc;
1824    
1825     switch (cpu->machine->machine_type) {
1826     case MACHINE_PMAX:
1827     res = decstation_prom_emul(cpu);
1828     break;
1829     case MACHINE_PS2:
1830     res = playstation2_sifbios_emul(cpu);
1831     break;
1832     case MACHINE_ARC:
1833     case MACHINE_SGI:
1834     res = arcbios_emul(cpu);
1835     break;
1836     case MACHINE_EVBMIPS:
1837     res = yamon_emul(cpu);
1838     break;
1839     default:fatal("TODO: Unimplemented machine type for PROM magic trap\n");
1840     exit(1);
1841     }
1842    
1843     if (res) {
1844     /* Return from the PROM call: */
1845     cpu->pc = (MODE_int_t)cpu->cd.mips.gpr[MIPS_GPR_RA];
1846     cpu->delay_slot = NOT_DELAYED;
1847    
1848     if (cpu->machine->show_trace_tree)
1849     cpu_functioncall_trace_return(cpu);
1850     } else {
1851     /* The PROM call blocks. */
1852     cpu->n_translated_instrs += 10;
1853     cpu->pc = old_pc;
1854     }
1855    
1856     quick_pc_to_pointers(cpu);
1857     }
1858    
1859    
1860     /*
1861     * tlbw: TLB write indexed and random
1862     *
1863     * arg[0] = 1 for random, 0 for indexed
1864     * arg[2] = relative addr of this instruction within the page
1865     */
1866     X(tlbw)
1867     {
1868 dpavlin 22 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1869     cpu->pc |= ic->arg[2];
1870 dpavlin 24 coproc_tlbwri(cpu, ic->arg[0]);
1871 dpavlin 22 }
1872    
1873    
1874 dpavlin 24 /*
1875     * tlbp: TLB probe
1876     * tlbr: TLB read
1877     *
1878     * arg[2] = relative addr of this instruction within the page
1879     */
1880     X(tlbp)
1881     {
1882     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1883     cpu->pc |= ic->arg[2];
1884     coproc_tlbpr(cpu, 0);
1885     }
1886     X(tlbr)
1887     {
1888     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1889     cpu->pc |= ic->arg[2];
1890     coproc_tlbpr(cpu, 1);
1891     }
1892    
1893    
1894     /*
1895     * rfe: Return from exception handler (R2000/R3000)
1896     */
1897     X(rfe)
1898     {
1899 dpavlin 28 /* Just rotate the interrupt/user bits: */
1900     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
1901     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
1902     ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
1903 dpavlin 24
1904 dpavlin 28 /*
1905     * Note: no pc to pointers conversion is necessary here. Usually the
1906     * rfe instruction resides in the delay slot of a jr k0/k1, and
1907     * it is up to that instruction to do the pointer conversion.
1908     */
1909 dpavlin 24 }
1910    
1911    
1912     /*
1913 dpavlin 28 * eret: Return from exception handler (non-R3000 style)
1914 dpavlin 24 */
1915     X(eret)
1916     {
1917 dpavlin 28 if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
1918     cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
1919     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
1920     } else {
1921     cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
1922     cpu->delay_slot = 0;
1923     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1924     }
1925    
1926 dpavlin 24 quick_pc_to_pointers(cpu);
1927 dpavlin 28
1928     cpu->cd.mips.rmw = 0; /* the "LL bit" */
1929 dpavlin 24 }
1930    
1931    
1932     /*
1933     * deret: Return from debug (EJTAG) handler
1934     */
1935     X(deret)
1936     {
1937     /*
1938     * According to the MIPS64 manual, deret loads PC from the DEPC cop0
1939     * register, and jumps there immediately. No delay slot.
1940     *
1941     * TODO: This instruction is only available if the processor is in
1942     * debug mode. (What does that mean?)
1943     *
1944     * TODO: This instruction is undefined in a delay slot.
1945     */
1946    
1947     cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_DEPC];
1948     cpu->delay_slot = 0;
1949     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1950     quick_pc_to_pointers(cpu);
1951     }
1952    
1953    
1954     /*
1955     * rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
1956     *
1957     * arg[0] = ptr to rt (destination register)
1958     */
1959     X(rdhwr_cpunum)
1960     {
1961     reg(ic->arg[0]) = cpu->cpu_id;
1962     }
1963    
1964    
1965     #include "tmp_mips_loadstore.c"
1966    
1967    
1968     /*
1969     * Load linked / store conditional:
1970     *
1971     * A Load-linked instruction initiates a RMW (read-modify-write) sequence.
1972     * COP0_LLADDR is updated for diagnostic purposes, except for CPUs in the
1973     * R10000 family.
1974     *
1975     * A Store-conditional instruction ends the sequence.
1976     *
1977     * arg[0] = ptr to rt
1978     * arg[1] = ptr to rs
1979     * arg[2] = int32_t imm
1980     */
1981     X(ll)
1982     {
1983     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1984     int low_pc;
1985     uint8_t word[sizeof(uint32_t)];
1986    
1987     /* Synch. PC and load using slow memory_rw(): */
1988     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1989     / sizeof(struct mips_instr_call);
1990     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1991     << MIPS_INSTR_ALIGNMENT_SHIFT);
1992     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1993    
1994     if (addr & (sizeof(word)-1)) {
1995     fatal("TODO: load linked unaligned access: exception\n");
1996     exit(1);
1997     }
1998    
1999     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2000     sizeof(word), MEM_READ, CACHE_DATA)) {
2001     /* An exception occurred. */
2002     return;
2003     }
2004    
2005     cpu->cd.mips.rmw = 1;
2006     cpu->cd.mips.rmw_addr = addr;
2007     cpu->cd.mips.rmw_len = sizeof(word);
2008     if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2009     cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2010     (addr >> 4) & 0xffffffffULL;
2011    
2012     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2013     reg(ic->arg[0]) = (int32_t) (word[0] + (word[1] << 8)
2014     + (word[2] << 16) + (word[3] << 24));
2015     else
2016     reg(ic->arg[0]) = (int32_t) (word[3] + (word[2] << 8)
2017     + (word[1] << 16) + (word[0] << 24));
2018     }
2019     X(lld)
2020     {
2021     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2022     int low_pc;
2023     uint8_t word[sizeof(uint64_t)];
2024    
2025     /* Synch. PC and load using slow memory_rw(): */
2026     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2027     / sizeof(struct mips_instr_call);
2028     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2029     << MIPS_INSTR_ALIGNMENT_SHIFT);
2030     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2031    
2032     if (addr & (sizeof(word)-1)) {
2033     fatal("TODO: load linked unaligned access: exception\n");
2034     exit(1);
2035     }
2036    
2037     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2038     sizeof(word), MEM_READ, CACHE_DATA)) {
2039     /* An exception occurred. */
2040     return;
2041     }
2042    
2043     cpu->cd.mips.rmw = 1;
2044     cpu->cd.mips.rmw_addr = addr;
2045     cpu->cd.mips.rmw_len = sizeof(word);
2046     if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2047     cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2048     (addr >> 4) & 0xffffffffULL;
2049    
2050     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2051     reg(ic->arg[0]) = word[0] + (word[1] << 8)
2052     + (word[2] << 16) + ((uint64_t)word[3] << 24) +
2053     + ((uint64_t)word[4] << 32) + ((uint64_t)word[5] << 40)
2054     + ((uint64_t)word[6] << 48) + ((uint64_t)word[7] << 56);
2055     else
2056     reg(ic->arg[0]) = word[7] + (word[6] << 8)
2057     + (word[5] << 16) + ((uint64_t)word[4] << 24) +
2058     + ((uint64_t)word[3] << 32) + ((uint64_t)word[2] << 40)
2059     + ((uint64_t)word[1] << 48) + ((uint64_t)word[0] << 56);
2060     }
2061     X(sc)
2062     {
2063     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2064     uint64_t r = reg(ic->arg[0]);
2065     int low_pc, i;
2066     uint8_t word[sizeof(uint32_t)];
2067    
2068     /* Synch. PC and store using slow memory_rw(): */
2069     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2070     / sizeof(struct mips_instr_call);
2071     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2072     << MIPS_INSTR_ALIGNMENT_SHIFT);
2073     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2074    
2075     if (addr & (sizeof(word)-1)) {
2076     fatal("TODO: sc unaligned access: exception\n");
2077     exit(1);
2078     }
2079    
2080     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2081     word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2082     } else {
2083     word[3]=r; word[2]=r>>8; word[1]=r>>16; word[0]=r>>24;
2084     }
2085    
2086     /* If rmw is 0, then the store failed. (This cache-line was written
2087     to by someone else.) */
2088     if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2089     || cpu->cd.mips.rmw_len != sizeof(word)) {
2090     reg(ic->arg[0]) = 0;
2091     cpu->cd.mips.rmw = 0;
2092     return;
2093     }
2094    
2095     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2096     sizeof(word), MEM_WRITE, CACHE_DATA)) {
2097     /* An exception occurred. */
2098     return;
2099     }
2100    
2101     /* We succeeded. Let's invalidate everybody else's store to this
2102     cache line: */
2103     for (i=0; i<cpu->machine->ncpus; i++) {
2104     if (cpu->machine->cpus[i]->cd.mips.rmw) {
2105     uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2106     cd.mips.rmw_addr;
2107     uint64_t mask = ~(cpu->machine->cpus[i]->
2108     cd.mips.cache_linesize[CACHE_DATA] - 1);
2109     xaddr &= mask;
2110     yaddr &= mask;
2111     if (xaddr == yaddr)
2112     cpu->machine->cpus[i]->cd.mips.rmw = 0;
2113     }
2114     }
2115    
2116     reg(ic->arg[0]) = 1;
2117     cpu->cd.mips.rmw = 0;
2118     }
2119     X(scd)
2120     {
2121     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2122     uint64_t r = reg(ic->arg[0]);
2123     int low_pc, i;
2124     uint8_t word[sizeof(uint64_t)];
2125    
2126     /* Synch. PC and store using slow memory_rw(): */
2127     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2128     / sizeof(struct mips_instr_call);
2129     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2130     << MIPS_INSTR_ALIGNMENT_SHIFT);
2131     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2132    
2133     if (addr & (sizeof(word)-1)) {
2134     fatal("TODO: sc unaligned access: exception\n");
2135     exit(1);
2136     }
2137    
2138     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2139     word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2140     word[4]=r>>32; word[5]=r>>40; word[6]=r>>48; word[7]=r>>56;
2141     } else {
2142     word[7]=r; word[6]=r>>8; word[5]=r>>16; word[4]=r>>24;
2143     word[3]=r>>32; word[2]=r>>40; word[1]=r>>48; word[0]=r>>56;
2144     }
2145    
2146     /* If rmw is 0, then the store failed. (This cache-line was written
2147     to by someone else.) */
2148     if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2149     || cpu->cd.mips.rmw_len != sizeof(word)) {
2150     reg(ic->arg[0]) = 0;
2151     cpu->cd.mips.rmw = 0;
2152     return;
2153     }
2154    
2155     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2156     sizeof(word), MEM_WRITE, CACHE_DATA)) {
2157     /* An exception occurred. */
2158     return;
2159     }
2160    
2161     /* We succeeded. Let's invalidate everybody else's store to this
2162     cache line: */
2163     for (i=0; i<cpu->machine->ncpus; i++) {
2164     if (cpu->machine->cpus[i]->cd.mips.rmw) {
2165     uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2166     cd.mips.rmw_addr;
2167     uint64_t mask = ~(cpu->machine->cpus[i]->
2168     cd.mips.cache_linesize[CACHE_DATA] - 1);
2169     xaddr &= mask;
2170     yaddr &= mask;
2171     if (xaddr == yaddr)
2172     cpu->machine->cpus[i]->cd.mips.rmw = 0;
2173     }
2174     }
2175    
2176     reg(ic->arg[0]) = 1;
2177     cpu->cd.mips.rmw = 0;
2178     }
2179    
2180    
2181     /*
2182     * lwc1, swc1: Coprocessor 1 load/store (32-bit)
2183     * ldc1, sdc1: Coprocessor 1 load/store (64-bit)
2184     *
2185     * arg[0] = ptr to coprocessor register
2186     * arg[1] = ptr to rs (base pointer register)
2187     * arg[2] = int32_t imm
2188     */
2189     X(lwc1)
2190     {
2191     const int cpnr = 1;
2192    
2193     /* Synch. PC and call the generic load/store function: */
2194     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2195     / sizeof(struct mips_instr_call);
2196     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2197     << MIPS_INSTR_ALIGNMENT_SHIFT);
2198     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2199    
2200     /* ... but first, let's see if the coprocessor is available: */
2201     if (!(cpu->cd.mips.coproc[0]->
2202     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2203     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2204     return;
2205     }
2206    
2207     #ifdef MODE32
2208     mips32_loadstore
2209     #else
2210     mips_loadstore
2211     #endif
2212     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 2 * 2 + 1]
2213     (cpu, ic);
2214     }
2215     X(swc1)
2216     {
2217     const int cpnr = 1;
2218    
2219     /* Synch. PC and call the generic load/store function: */
2220     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2221     / sizeof(struct mips_instr_call);
2222     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2223     << MIPS_INSTR_ALIGNMENT_SHIFT);
2224     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2225    
2226     /* ... but first, let's see if the coprocessor is available: */
2227     if (!(cpu->cd.mips.coproc[0]->
2228     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2229     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2230     return;
2231     }
2232    
2233     #ifdef MODE32
2234     mips32_loadstore
2235     #else
2236     mips_loadstore
2237     #endif
2238     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 2 * 2]
2239     (cpu, ic);
2240     }
2241     X(ldc1)
2242     {
2243     const int cpnr = 1;
2244     int use_fp_pairs =
2245     !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2246     uint64_t fpr, *backup_ptr;
2247    
2248     /* Synch. PC and call the generic load/store function: */
2249     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2250     / sizeof(struct mips_instr_call);
2251     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2252     << MIPS_INSTR_ALIGNMENT_SHIFT);
2253     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2254    
2255     /* ... but first, let's see if the coprocessor is available: */
2256     if (!(cpu->cd.mips.coproc[0]->
2257     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2258     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2259     return;
2260     }
2261    
2262     backup_ptr = (uint64_t *) ic->arg[0];
2263     ic->arg[0] = (size_t) &fpr;
2264    
2265     #ifdef MODE32
2266     mips32_loadstore
2267     #else
2268     mips_loadstore
2269     #endif
2270     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 3 * 2 + 1]
2271     (cpu, ic);
2272    
2273     if (use_fp_pairs) {
2274     backup_ptr[0] = (int64_t)(int32_t) fpr;
2275     backup_ptr[1] = (int64_t)(int32_t) (fpr >> 32);
2276     } else {
2277     *backup_ptr = fpr;
2278     }
2279    
2280     ic->arg[0] = (size_t) backup_ptr;
2281     }
2282     X(sdc1)
2283     {
2284     const int cpnr = 1;
2285     int use_fp_pairs =
2286     !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2287     uint64_t fpr, *backup_ptr;
2288    
2289     /* Synch. PC and call the generic load/store function: */
2290     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2291     / sizeof(struct mips_instr_call);
2292     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2293     << MIPS_INSTR_ALIGNMENT_SHIFT);
2294     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2295    
2296     /* ... but first, let's see if the coprocessor is available: */
2297     if (!(cpu->cd.mips.coproc[0]->
2298     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2299     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2300     return;
2301     }
2302    
2303     backup_ptr = (uint64_t *) ic->arg[0];
2304     ic->arg[0] = (size_t) &fpr;
2305    
2306     if (use_fp_pairs) {
2307     uint32_t lo = backup_ptr[0];
2308     uint32_t hi = backup_ptr[1];
2309     fpr = (((uint64_t)hi) << 32) | lo;
2310     } else {
2311     fpr = *backup_ptr;
2312     }
2313    
2314     #ifdef MODE32
2315     mips32_loadstore
2316     #else
2317     mips_loadstore
2318     #endif
2319     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 3 * 2]
2320     (cpu, ic);
2321    
2322     ic->arg[0] = (size_t) backup_ptr;
2323     }
2324    
2325    
2326     /*
2327     * Unaligned loads/stores:
2328     *
2329     * arg[0] = ptr to rt
2330     * arg[1] = ptr to rs
2331     * arg[2] = int32_t imm
2332     */
2333     X(lwl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 0); }
2334     X(lwr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 0); }
2335     X(ldl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 0); }
2336     X(ldr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 0); }
2337     X(swl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 1); }
2338     X(swr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 1); }
2339     X(sdl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 1); }
2340     X(sdr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 1); }
2341    
2342    
2343     /*
2344     * di, ei: R5900 interrupt enable/disable.
2345     *
2346     * TODO: check the R5900_STATUS_EDI bit in the status register. If it is
2347     * cleared, and we are not running in kernel mode, then both the EI and DI
2348     * instructions should be treated as NOPs!
2349     */
2350     X(di_r5900)
2351     {
2352     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2353     }
2354     X(ei_r5900)
2355     {
2356     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2357     }
2358    
2359    
2360 dpavlin 22 /*****************************************************************************/
2361    
2362    
2363     /*
2364 dpavlin 28 * sw_loop:
2365     *
2366     * s: addiu rX,rX,4 rX = arg[0] and arg[1]
2367     * bne rY,rX,s (or rX,rY,s) rt=arg[1], rs=arg[0]
2368     * sw rZ,-4(rX) rt=arg[0], rs=arg[1]
2369     */
2370     X(sw_loop)
2371     {
2372     MODE_uint_t rX = reg(ic->arg[0]), rZ = reg(ic[2].arg[0]);
2373     uint64_t *rYp = (uint64_t *) ic[1].arg[0];
2374     MODE_uint_t rY, bytes_to_write;
2375     unsigned char *page;
2376     int partial = 0;
2377    
2378     page = cpu->cd.mips.host_store[rX >> 12];
2379    
2380     /* Fallback: */
2381     if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2382     instr(addiu)(cpu, ic);
2383     return;
2384     }
2385    
2386     if (rYp == (uint64_t *) ic->arg[0])
2387     rYp = (uint64_t *) ic[1].arg[1];
2388    
2389     rY = reg(rYp);
2390    
2391     bytes_to_write = rY - rX;
2392     if ((rX & 0xfff) + bytes_to_write > 0x1000) {
2393     bytes_to_write = 0x1000 - (rX & 0xfff);
2394     partial = 1;
2395     }
2396    
2397     /* printf("rX = %08x\n", (int)rX);
2398     printf("rY = %08x\n", (int)rY);
2399     printf("rZ = %08x\n", (int)rZ);
2400     printf("%i bytes\n", (int)bytes_to_write); */
2401    
2402     memset(page + (rX & 0xfff), 0, bytes_to_write);
2403    
2404     reg(ic->arg[0]) = rX + bytes_to_write;
2405    
2406     cpu->n_translated_instrs += bytes_to_write / 4 * 3 - 1;
2407     cpu->cd.mips.next_ic = partial?
2408     (struct mips_instr_call *) &ic[0] :
2409     (struct mips_instr_call *) &ic[3];
2410     }
2411    
2412    
2413     /*
2414     * multi_sw_3:
2415     *
2416     * sw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2]
2417     * sw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2]
2418     * sw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2]
2419     */
2420     X(multi_sw_3_le)
2421     {
2422     uint32_t *page;
2423     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2424     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2425     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2426     MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2427     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2428     index2 = addr2 >> 12;
2429    
2430     page = (uint32_t *) cpu->cd.mips.host_store[index0];
2431    
2432     /* Fallback: */
2433     if (cpu->delay_slot ||
2434     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2435     (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2436     /* Normal safe sw: */
2437     ic[1].f(cpu, ic);
2438     return;
2439     }
2440    
2441     addr0 = (addr0 >> 2) & 0x3ff;
2442     addr1 = (addr1 >> 2) & 0x3ff;
2443     addr2 = (addr2 >> 2) & 0x3ff;
2444    
2445     /* printf("addr0=%x 1=%x 2=%x\n",
2446     (int)addr0, (int)addr1, (int)addr2); */
2447    
2448     r1 = reg(ic[0].arg[0]);
2449     r2 = reg(ic[1].arg[0]);
2450     r3 = reg(ic[2].arg[0]);
2451    
2452     r1 = LE32_TO_HOST(r1);
2453     r2 = LE32_TO_HOST(r2);
2454     r3 = LE32_TO_HOST(r3);
2455    
2456     page[addr0] = r1;
2457     page[addr1] = r2;
2458     page[addr2] = r3;
2459    
2460     cpu->n_translated_instrs += 2;
2461     cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3];
2462     }
2463     X(multi_sw_3_be)
2464     {
2465     uint32_t *page;
2466     MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2467     MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2468     MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2469     MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2470     uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2471     index2 = addr2 >> 12;
2472    
2473     page = (uint32_t *) cpu->cd.mips.host_store[index0];
2474    
2475     /* Fallback: */
2476     if (cpu->delay_slot ||
2477     page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2478     (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2479     /* Normal safe sw: */
2480     ic[1].f(cpu, ic);
2481     return;
2482     }
2483    
2484     addr0 = (addr0 >> 2) & 0x3ff;
2485     addr1 = (addr1 >> 2) & 0x3ff;
2486     addr2 = (addr2 >> 2) & 0x3ff;
2487    
2488     /* printf("addr0=%x 1=%x 2=%x\n",
2489     (int)addr0, (int)addr1, (int)addr2); */
2490    
2491     r1 = reg(ic[0].arg[0]);
2492     r2 = reg(ic[1].arg[0]);
2493     r3 = reg(ic[2].arg[0]);
2494    
2495     r1 = BE32_TO_HOST(r1);
2496     r2 = BE32_TO_HOST(r2);
2497     r3 = BE32_TO_HOST(r3);
2498    
2499     page[addr0] = r1;
2500     page[addr1] = r2;
2501     page[addr2] = r3;
2502    
2503     cpu->n_translated_instrs += 2;
2504     cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3];
2505     }
2506    
2507    
2508     /*
2509     * netbsd_r3k_picache_do_inv:
2510     *
2511     * ic[0] mtc0 rV,status
2512     * 1 nop
2513     * 2 nop
2514     * 3 s: addiu rX,rX,4
2515     * 4 bne rY,rX,s
2516     * 5 sb zr,-4(rX)
2517     * 6 nop
2518     * 7 nop
2519     * 8 mtc0 rT,status
2520     */
2521     X(netbsd_r3k_picache_do_inv)
2522     {
2523     MODE_uint_t rx = reg(ic[3].arg[0]), ry = reg(ic[4].arg[1]);
2524    
2525     /* Fallback if the environment isn't exactly right: */
2526     if (!(reg(ic[0].arg[0]) & MIPS1_ISOL_CACHES) ||
2527     (rx & 3) || (ry & 3) || cpu->delay_slot) {
2528     instr(mtc0)(cpu, ic);
2529     return;
2530     }
2531    
2532     reg(ic[3].arg[0]) = ry;
2533     cpu->n_translated_instrs += (ry - rx + 4) / 4 * 3 + 4;
2534    
2535     /* Run the last mtc0 instruction: */
2536     cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[8];
2537     }
2538    
2539    
2540     #ifdef MODE32
2541     /*
2542     * netbsd_strlen():
2543     *
2544     * lb rV,0(rX)
2545     * s: addiu rX,rX,1
2546     * bne zr,rV,s
2547     * nop
2548     */
2549     X(netbsd_strlen)
2550     {
2551     MODE_uint_t rx = reg(ic[0].arg[1]);
2552     MODE_int_t rv;
2553     signed char *page;
2554     uint32_t pageindex = rx >> 12;
2555     int i;
2556    
2557     page = (signed char *) cpu->cd.mips.host_load[pageindex];
2558    
2559     /* Fallback: */
2560     if (cpu->delay_slot || page == NULL) {
2561     /*
2562     * Normal lb: NOTE: It doesn't matter whether [1] or
2563     * [16+1] is called here, because endianness for 8-bit
2564     * loads is irrelevant. :-)
2565     */
2566     mips32_loadstore[1](cpu, ic);
2567     return;
2568     }
2569    
2570     i = rx & 0xfff;
2571    
2572     /*
2573     * TODO: This loop can be optimized further for optimal
2574     * performance on the host, e.g. by reading full words...
2575     */
2576     do {
2577     rv = page[i ++];
2578     } while (i < 0x1000 && rv != 0);
2579    
2580     cpu->n_translated_instrs += (i - (rx & 0xfff)) * 4 - 1;
2581    
2582     reg(ic[0].arg[1]) = (rx & ~0xfff) + i;
2583     reg(ic[2].arg[0]) = rv;
2584    
2585     /* Done with the loop? Or continue on the next rx page? */
2586     if (rv == 0)
2587     cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[4];
2588     else
2589     cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[0];
2590     }
2591     #endif
2592    
2593    
2594     /*
2595     * lui_32bit:
2596     *
2597     * Combination of lui and addiu.
2598     * Note: All 32 bits of arg[2] of the lui instr_call are used.
2599     */
2600     X(lui_32bit)
2601     {
2602     reg(ic[0].arg[0]) = (int32_t) ic[0].arg[2];
2603     cpu->n_translated_instrs ++;
2604     cpu->cd.mips.next_ic ++;
2605     }
2606    
2607    
2608     /*
2609 dpavlin 22 * b_samepage_addiu:
2610     *
2611     * Combination of branch within the same page, followed by addiu.
2612     */
2613     X(b_samepage_addiu)
2614     {
2615 dpavlin 24 reg(ic[1].arg[1]) = (int32_t)
2616     ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
2617 dpavlin 22 cpu->n_translated_instrs ++;
2618     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2619     }
2620    
2621    
2622 dpavlin 24 /*
2623     * b_samepage_daddiu:
2624     *
2625     * Combination of branch within the same page, followed by daddiu.
2626     */
2627     X(b_samepage_daddiu)
2628     {
2629     *(uint64_t *)ic[1].arg[1] = *(uint64_t *)ic[1].arg[0] +
2630     (int32_t)ic[1].arg[2];
2631     cpu->n_translated_instrs ++;
2632     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2633     }
2634    
2635    
2636 dpavlin 22 /*****************************************************************************/
2637    
2638    
2639     X(end_of_page)
2640     {
2641     /* Update the PC: (offset 0, but on the next page) */
2642     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
2643     MIPS_INSTR_ALIGNMENT_SHIFT);
2644     cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);
2645    
2646 dpavlin 24 /* end_of_page doesn't count as an executed instruction: */
2647     cpu->n_translated_instrs --;
2648 dpavlin 22
2649 dpavlin 24 /*
2650     * Find the new physpage and update translation pointers.
2651     *
2652     * Note: This may cause an exception, if e.g. the new page is
2653     * not accessible.
2654     */
2655     quick_pc_to_pointers(cpu);
2656 dpavlin 22
2657 dpavlin 24 /* Simple jump to the next page (if we are lucky): */
2658     if (cpu->delay_slot == NOT_DELAYED)
2659     return;
2660 dpavlin 22
2661 dpavlin 24 /*
2662     * If we were in a delay slot, and we got an exception while doing
2663     * quick_pc_to_pointers, then return. The function which called
2664     * end_of_page should handle this case.
2665     */
2666     if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
2667 dpavlin 22 return;
2668    
2669 dpavlin 24 /*
2670     * Tricky situation; the delay slot is on the next virtual page.
2671     * Calling to_be_translated will translate one instruction manually,
2672     * execute it, and then discard it.
2673     */
2674 dpavlin 22 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
2675    
2676 dpavlin 24 instr(to_be_translated)(cpu, cpu->cd.mips.next_ic);
2677 dpavlin 22
2678     /* The instruction in the delay slot has now executed. */
2679 dpavlin 24 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
2680     cpu->delay_slot); */
2681 dpavlin 22
2682     /* Find the physpage etc of the instruction in the delay slot
2683     (or, if there was an exception, the exception handler): */
2684     quick_pc_to_pointers(cpu);
2685     }
2686    
2687    
2688     X(end_of_page2)
2689     {
2690 dpavlin 24 /* Synchronize PC on the _second_ instruction on the next page: */
2691     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2692     / sizeof(struct mips_instr_call);
2693     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2694     << MIPS_INSTR_ALIGNMENT_SHIFT);
2695     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2696 dpavlin 22
2697 dpavlin 24 /* This doesn't count as an executed instruction. */
2698     cpu->n_translated_instrs --;
2699 dpavlin 22
2700 dpavlin 24 quick_pc_to_pointers(cpu);
2701 dpavlin 22
2702 dpavlin 24 if (cpu->delay_slot == NOT_DELAYED)
2703 dpavlin 22 return;
2704    
2705 dpavlin 24 fatal("end_of_page2: fatal error, we're in a delay slot\n");
2706 dpavlin 22 exit(1);
2707     }
2708    
2709    
2710     /*****************************************************************************/
2711    
2712    
2713     /*
2714 dpavlin 28 * Combine: Memory fill loop (addiu, bne, sw)
2715     *
2716     * s: addiu rX,rX,4
2717     * bne rY,rX,s
2718     * sw rZ,-4(rX)
2719 dpavlin 22 */
2720 dpavlin 28 void COMBINE(sw_loop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
2721     {
2722     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2723     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2724    
2725     /* Only for 32-bit virtual address translation so far. */
2726     if (!cpu->is_32bit)
2727     return;
2728    
2729     if (n_back < 2)
2730     return;
2731    
2732     if (ic[-2].f == instr(addiu) && ic[-2].arg[0] == ic[-2].arg[1] &&
2733     (int32_t)ic[-2].arg[2] == 4 &&
2734     ic[-1].f == instr(bne_samepage) &&
2735     (ic[-1].arg[0] == ic[-2].arg[0] ||
2736     ic[-1].arg[1] == ic[-2].arg[0]) &&
2737     ic[-1].arg[0] != ic[-1].arg[1] &&
2738     ic[-1].arg[2] == (size_t) &ic[-2] &&
2739     ic[0].arg[0] != ic[0].arg[1] &&
2740     ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {
2741     ic[-2].f = instr(sw_loop);
2742     combined;
2743     }
2744     }
2745    
2746    
2747     /*
2748     * Combine: Multiple SW in a row using the same base register
2749     *
2750     * sw r?,???(rX)
2751     * sw r?,???(rX)
2752     * sw r?,???(rX)
2753     * ...
2754     */
2755     void COMBINE(multi_sw)(struct cpu *cpu, struct mips_instr_call *ic,
2756 dpavlin 22 int low_addr)
2757     {
2758     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2759     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2760    
2761 dpavlin 28 /* Only for 32-bit virtual address translation so far. */
2762     if (!cpu->is_32bit)
2763     return;
2764    
2765     if (n_back < 4)
2766     return;
2767    
2768     /* Avoid "overlapping" instruction combinations: */
2769     if (ic[-4].f == instr(multi_sw_3_be)||ic[-3].f == instr(multi_sw_3_be)||
2770     ic[-4].f == instr(multi_sw_3_le)||ic[-3].f == instr(multi_sw_3_le))
2771     return;
2772    
2773     if (ic[-2].f == ic[0].f && ic[-1].f == ic[0].f &&
2774     ic[-2].arg[1] == ic[0].arg[1] &&
2775     ic[-1].arg[1] == ic[0].arg[1]) {
2776     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2777     ic[-2].f = instr(multi_sw_3_le);
2778     else
2779     ic[-2].f = instr(multi_sw_3_be);
2780     combined;
2781     }
2782     }
2783    
2784    
2785     /*
2786     * Combine: NetBSD/pmax 3.0 R2000/R3000 physical cache invalidation loop
2787     *
2788     * Instruction cache loop:
2789     *
2790     * ic[-8] mtc0 rV,status
2791     * -7 nop
2792     * -6 nop
2793     * -5 s: addiu rX,rX,4
2794     * -4 bne rY,rX,s
2795     * -3 sb zr,-4(rX)
2796     * -2 nop
2797     * -1 nop
2798     * 0 mtc0 rT,status
2799     */
2800     void COMBINE(netbsd_r3k_cache_inv)(struct cpu *cpu,
2801     struct mips_instr_call *ic, int low_addr)
2802     {
2803     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2804     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2805    
2806     if (n_back < 8)
2807     return;
2808    
2809     if (ic[-8].f == instr(mtc0) && ic[-8].arg[1] == COP0_STATUS &&
2810     ic[-7].f == instr(nop) && ic[-6].f == instr(nop) &&
2811     ic[-5].f == instr(addiu) && ic[-5].arg[0] == ic[-5].arg[1] &&
2812     (int32_t)ic[-5].arg[2] == 4 && ic[-4].f == instr(bne_samepage) &&
2813     ic[-4].arg[0] == ic[-5].arg[0] && ic[-4].arg[0] != ic[-4].arg[1] &&
2814     ic[-4].arg[2] == (size_t) &ic[-5] &&
2815     ic[-3].arg[1] == ic[-5].arg[0] &&
2816     ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
2817     ic[-8].f = instr(netbsd_r3k_picache_do_inv);
2818     combined;
2819     }
2820     }
2821    
2822    
2823     /*
2824     * Combine: something ending with a nop.
2825     *
2826     * NetBSD's strlen core.
2827     * [Conditional] branch, followed by nop.
2828     */
2829     void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
2830     {
2831     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2832     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2833    
2834     #ifdef MODE32
2835     if (n_back < 3)
2836     return;
2837    
2838     if ((ic[-3].f == mips32_loadstore[1] ||
2839     ic[-3].f == mips32_loadstore[16 + 1]) &&
2840     ic[-3].arg[2] == 0 &&
2841     ic[-3].arg[0] == ic[-1].arg[0] && ic[-3].arg[1] == ic[-2].arg[0] &&
2842     ic[-2].arg[0] == ic[-2].arg[1] && ic[-2].arg[2] == 1 &&
2843     ic[-2].f == instr(addiu) && ic[-1].arg[2] == (size_t) &ic[-3] &&
2844     ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
2845     ic[-1].f == instr(bne_samepage)) {
2846     ic[-3].f = instr(netbsd_strlen);
2847     combined;
2848     return;
2849     }
2850     #endif
2851    
2852 dpavlin 22 if (n_back < 1)
2853     return;
2854    
2855 dpavlin 28 if (ic[-1].f == instr(bne_samepage)) {
2856     ic[-1].f = instr(bne_samepage_nop);
2857     combined;
2858     return;
2859     }
2860    
2861     if (ic[-1].f == instr(beq_samepage)) {
2862     ic[-1].f = instr(beq_samepage_nop);
2863     combined;
2864     return;
2865     }
2866    
2867     /* TODO: other branches that are followed by nop should be here */
2868     }
2869    
2870    
2871     /*
2872     * Combine:
2873     *
2874     * [Conditional] branch, followed by addiu.
2875     * lui + addiu.
2876     */
2877     void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
2878     {
2879     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2880     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2881    
2882     if (n_back < 1)
2883     return;
2884    
2885     if (ic[-1].f == instr(set) && ic[-1].arg[0] == ic[0].arg[0] &&
2886     ic[0].arg[0] == ic[0].arg[1]) {
2887     ic[-1].f = instr(lui_32bit);
2888     ic[-1].arg[2] = (int32_t) (ic[-1].arg[1] + ic[0].arg[2]);
2889     combined;
2890     return;
2891     }
2892    
2893 dpavlin 22 if (ic[-1].f == instr(b_samepage)) {
2894     ic[-1].f = instr(b_samepage_addiu);
2895     combined;
2896 dpavlin 28 return;
2897 dpavlin 22 }
2898    
2899 dpavlin 28 if (ic[-1].f == instr(beq_samepage)) {
2900     ic[-1].f = instr(beq_samepage_addiu);
2901     combined;
2902     return;
2903     }
2904    
2905     if (ic[-1].f == instr(bne_samepage)) {
2906     ic[-1].f = instr(bne_samepage_addiu);
2907     combined;
2908     return;
2909     }
2910    
2911     if (ic[-1].f == instr(jr_ra)) {
2912     ic[-1].f = instr(jr_ra_addiu);
2913     combined;
2914     return;
2915     }
2916    
2917 dpavlin 22 /* TODO: other branches that are followed by addiu should be here */
2918     }
2919    
2920    
2921 dpavlin 24 /*
2922     * Combine: [Conditional] branch, followed by daddiu.
2923     */
2924     void COMBINE(b_daddiu)(struct cpu *cpu, struct mips_instr_call *ic,
2925     int low_addr)
2926     {
2927     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2928     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2929    
2930     if (n_back < 1)
2931     return;
2932    
2933     if (ic[-1].f == instr(b_samepage)) {
2934     ic[-1].f = instr(b_samepage_daddiu);
2935     combined;
2936     }
2937    
2938     /* TODO: other branches that are followed by daddiu should be here */
2939     }
2940    
2941    
2942 dpavlin 22 /*****************************************************************************/
2943    
2944    
2945     /*
2946     * mips_instr_to_be_translated():
2947     *
2948 dpavlin 24 * Translate an instruction word into a mips_instr_call. ic is filled in with
2949 dpavlin 22 * valid data for the translated instruction, or a "nothing" instruction if
2950     * there was a translation failure. The newly translated instruction is then
2951     * executed.
2952     */
2953     X(to_be_translated)
2954     {
2955     uint64_t addr, low_pc;
2956     uint32_t iword, imm;
2957     unsigned char *page;
2958     unsigned char ib[4];
2959     int main_opcode, rt, rs, rd, sa, s6, x64 = 0;
2960     int in_crosspage_delayslot = 0;
2961     void (*samepage_function)(struct cpu *, struct mips_instr_call *);
2962 dpavlin 24 int store, signedness, size;
2963 dpavlin 22
2964     /* Figure out the (virtual) address of the instruction: */
2965     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2966     / sizeof(struct mips_instr_call);
2967    
2968     /* Special case for branch with delayslot on the next page: */
2969 dpavlin 24 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
2970     /* fatal("[ delay-slot translation across page "
2971     "boundary ]\n"); */
2972 dpavlin 22 in_crosspage_delayslot = 1;
2973     }
2974    
2975     addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2976     << MIPS_INSTR_ALIGNMENT_SHIFT);
2977     addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2978 dpavlin 24 cpu->pc = (MODE_int_t)addr;
2979 dpavlin 22 addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
2980    
2981     /* Read the instruction word from memory: */
2982 dpavlin 24 #ifdef MODE32
2983 dpavlin 22 page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
2984 dpavlin 24 #else
2985     {
2986     const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2987     const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2988     const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2989     uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2990     uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2991     uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2992     DYNTRANS_L3N)) & mask3;
2993     struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.mips.l1_64[x1];
2994     struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2995     page = l3->host_load[x3];
2996     }
2997     #endif
2998 dpavlin 22
2999     if (page != NULL) {
3000     /* fatal("TRANSLATION HIT!\n"); */
3001 dpavlin 24 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
3002 dpavlin 22 } else {
3003     /* fatal("TRANSLATION MISS!\n"); */
3004     if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
3005     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
3006 dpavlin 24 fatal("to_be_translated(): read failed: TODO\n");
3007 dpavlin 22 goto bad;
3008     }
3009     }
3010    
3011     iword = *((uint32_t *)&ib[0]);
3012    
3013     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3014     iword = LE32_TO_HOST(iword);
3015     else
3016     iword = BE32_TO_HOST(iword);
3017    
3018    
3019     #define DYNTRANS_TO_BE_TRANSLATED_HEAD
3020     #include "cpu_dyntrans.c"
3021     #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
3022    
3023    
3024     /*
3025     * Translate the instruction:
3026     *
3027 dpavlin 24 * NOTE: _NEVER_ allow writes to the zero register; all instructions
3028     * that use the zero register as their destination should be treated
3029     * as NOPs, except those that access memory (they should use the
3030     * scratch register instead).
3031 dpavlin 22 */
3032    
3033     main_opcode = iword >> 26;
3034     rs = (iword >> 21) & 31;
3035     rt = (iword >> 16) & 31;
3036     rd = (iword >> 11) & 31;
3037     sa = (iword >> 6) & 31;
3038     imm = (int16_t)iword;
3039     s6 = iword & 63;
3040    
3041     switch (main_opcode) {
3042    
3043     case HI6_SPECIAL:
3044     switch (s6) {
3045    
3046     case SPECIAL_SLL:
3047 dpavlin 24 case SPECIAL_SLLV:
3048 dpavlin 22 case SPECIAL_SRL:
3049 dpavlin 24 case SPECIAL_SRLV:
3050 dpavlin 22 case SPECIAL_SRA:
3051 dpavlin 24 case SPECIAL_SRAV:
3052     case SPECIAL_DSRL:
3053     case SPECIAL_DSRLV:
3054     case SPECIAL_DSRL32:
3055     case SPECIAL_DSLL:
3056     case SPECIAL_DSLLV:
3057     case SPECIAL_DSLL32:
3058     case SPECIAL_DSRA:
3059     case SPECIAL_DSRAV:
3060     case SPECIAL_DSRA32:
3061 dpavlin 22 switch (s6) {
3062     case SPECIAL_SLL: ic->f = instr(sll); break;
3063 dpavlin 24 case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
3064 dpavlin 22 case SPECIAL_SRL: ic->f = instr(srl); break;
3065 dpavlin 24 case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
3066 dpavlin 22 case SPECIAL_SRA: ic->f = instr(sra); break;
3067 dpavlin 24 case SPECIAL_SRAV: ic->f = instr(srav); sa = -1; break;
3068     case SPECIAL_DSRL: ic->f = instr(dsrl); x64=1; break;
3069     case SPECIAL_DSRLV:ic->f = instr(dsrlv);
3070     x64 = 1; sa = -1; break;
3071     case SPECIAL_DSRL32:ic->f= instr(dsrl); x64=1;
3072     sa += 32; break;
3073     case SPECIAL_DSLL: ic->f = instr(dsll); x64=1; break;
3074     case SPECIAL_DSLLV:ic->f = instr(dsllv);
3075     x64 = 1; sa = -1; break;
3076     case SPECIAL_DSLL32:ic->f= instr(dsll); x64=1;
3077     sa += 32; break;
3078     case SPECIAL_DSRA: ic->f = instr(dsra); x64=1; break;
3079     case SPECIAL_DSRAV:ic->f = instr(dsrav);
3080     x64 = 1; sa = -1; break;
3081     case SPECIAL_DSRA32:ic->f = instr(dsra); x64=1;
3082     sa += 32; break;
3083 dpavlin 22 }
3084     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3085 dpavlin 24 if (sa >= 0)
3086     ic->arg[1] = sa;
3087     else
3088     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3089 dpavlin 22 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3090     if (rd == MIPS_GPR_ZERO)
3091     ic->f = instr(nop);
3092     break;
3093    
3094 dpavlin 24 case SPECIAL_ADD:
3095 dpavlin 22 case SPECIAL_ADDU:
3096 dpavlin 24 case SPECIAL_SUB:
3097 dpavlin 22 case SPECIAL_SUBU:
3098 dpavlin 24 case SPECIAL_DADD:
3099 dpavlin 22 case SPECIAL_DADDU:
3100 dpavlin 24 case SPECIAL_DSUB:
3101 dpavlin 22 case SPECIAL_DSUBU:
3102     case SPECIAL_SLT:
3103     case SPECIAL_SLTU:
3104 dpavlin 24 case SPECIAL_AND:
3105 dpavlin 22 case SPECIAL_OR:
3106     case SPECIAL_XOR:
3107     case SPECIAL_NOR:
3108 dpavlin 24 case SPECIAL_MOVN:
3109     case SPECIAL_MOVZ:
3110 dpavlin 22 case SPECIAL_MFHI:
3111     case SPECIAL_MFLO:
3112     case SPECIAL_MTHI:
3113     case SPECIAL_MTLO:
3114 dpavlin 24 case SPECIAL_DIV:
3115     case SPECIAL_DIVU:
3116     case SPECIAL_DDIV:
3117     case SPECIAL_DDIVU:
3118     case SPECIAL_MULT:
3119     case SPECIAL_MULTU:
3120     case SPECIAL_DMULT:
3121     case SPECIAL_DMULTU:
3122     case SPECIAL_TGE:
3123     case SPECIAL_TGEU:
3124     case SPECIAL_TLT:
3125     case SPECIAL_TLTU:
3126     case SPECIAL_TEQ:
3127     case SPECIAL_TNE:
3128 dpavlin 22 switch (s6) {
3129 dpavlin 24 case SPECIAL_ADD: ic->f = instr(add); break;
3130 dpavlin 22 case SPECIAL_ADDU: ic->f = instr(addu); break;
3131 dpavlin 24 case SPECIAL_SUB: ic->f = instr(sub); break;
3132 dpavlin 22 case SPECIAL_SUBU: ic->f = instr(subu); break;
3133 dpavlin 24 case SPECIAL_DADD: ic->f = instr(dadd); x64=1; break;
3134 dpavlin 22 case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
3135 dpavlin 24 case SPECIAL_DSUB: ic->f = instr(dsub); x64=1; break;
3136 dpavlin 22 case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;
3137     case SPECIAL_SLT: ic->f = instr(slt); break;
3138     case SPECIAL_SLTU: ic->f = instr(sltu); break;
3139 dpavlin 24 case SPECIAL_AND: ic->f = instr(and); break;
3140 dpavlin 22 case SPECIAL_OR: ic->f = instr(or); break;
3141     case SPECIAL_XOR: ic->f = instr(xor); break;
3142     case SPECIAL_NOR: ic->f = instr(nor); break;
3143     case SPECIAL_MFHI: ic->f = instr(mov); break;
3144     case SPECIAL_MFLO: ic->f = instr(mov); break;
3145     case SPECIAL_MTHI: ic->f = instr(mov); break;
3146     case SPECIAL_MTLO: ic->f = instr(mov); break;
3147 dpavlin 24 case SPECIAL_DIV: ic->f = instr(div); break;
3148     case SPECIAL_DIVU: ic->f = instr(divu); break;
3149     case SPECIAL_DDIV: ic->f = instr(ddiv); x64=1; break;
3150     case SPECIAL_DDIVU: ic->f = instr(ddivu); x64=1; break;
3151     case SPECIAL_MULT : ic->f = instr(mult); break;
3152     case SPECIAL_MULTU: ic->f = instr(multu); break;
3153     case SPECIAL_DMULT: ic->f = instr(dmult); x64=1; break;
3154     case SPECIAL_DMULTU:ic->f = instr(dmultu); x64=1; break;
3155     case SPECIAL_TGE: ic->f = instr(tge); break;
3156     case SPECIAL_TGEU: ic->f = instr(tgeu); break;
3157     case SPECIAL_TLT: ic->f = instr(tlt); break;
3158     case SPECIAL_TLTU: ic->f = instr(tltu); break;
3159     case SPECIAL_TEQ: ic->f = instr(teq); break;
3160     case SPECIAL_TNE: ic->f = instr(tne); break;
3161     case SPECIAL_MOVN: ic->f = instr(movn); break;
3162     case SPECIAL_MOVZ: ic->f = instr(movz); break;
3163 dpavlin 22 }
3164     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3165     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3166     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3167     switch (s6) {
3168     case SPECIAL_MFHI:
3169     ic->arg[0] = (size_t)&cpu->cd.mips.hi;
3170     break;
3171     case SPECIAL_MFLO:
3172     ic->arg[0] = (size_t)&cpu->cd.mips.lo;
3173     break;
3174     case SPECIAL_MTHI:
3175     ic->arg[2] = (size_t)&cpu->cd.mips.hi;
3176     break;
3177     case SPECIAL_MTLO:
3178     ic->arg[2] = (size_t)&cpu->cd.mips.lo;
3179     break;
3180     }
3181 dpavlin 24 /* Special cases for rd: */
3182 dpavlin 22 switch (s6) {
3183     case SPECIAL_MTHI:
3184     case SPECIAL_MTLO:
3185 dpavlin 24 case SPECIAL_DIV:
3186     case SPECIAL_DIVU:
3187     case SPECIAL_DDIV:
3188     case SPECIAL_DDIVU:
3189 dpavlin 22 case SPECIAL_MULT:
3190     case SPECIAL_MULTU:
3191     case SPECIAL_DMULT:
3192     case SPECIAL_DMULTU:
3193 dpavlin 24 case SPECIAL_TGE:
3194     case SPECIAL_TGEU:
3195     case SPECIAL_TLT:
3196     case SPECIAL_TLTU:
3197     case SPECIAL_TEQ:
3198     case SPECIAL_TNE:
3199     if (s6 == SPECIAL_MULT && rd != MIPS_GPR_ZERO) {
3200     if (cpu->cd.mips.cpu_type.rev ==
3201     MIPS_R5900) {
3202     ic->f = instr(mult_r5900);
3203     break;
3204     }
3205     break;
3206     }
3207     if (s6 == SPECIAL_MULTU && rd!=MIPS_GPR_ZERO) {
3208     if (cpu->cd.mips.cpu_type.rev ==
3209     MIPS_R5900) {
3210     ic->f = instr(multu_r5900);
3211     break;
3212     }
3213     }
3214 dpavlin 22 if (rd != MIPS_GPR_ZERO) {
3215 dpavlin 24 fatal("TODO: rd NON-zero\n");
3216 dpavlin 22 goto bad;
3217     }
3218 dpavlin 24 /* These instructions don't use rd. */
3219 dpavlin 22 break;
3220 dpavlin 24 default:if (rd == MIPS_GPR_ZERO)
3221     ic->f = instr(nop);
3222 dpavlin 22 }
3223     break;
3224    
3225     case SPECIAL_JR:
3226     case SPECIAL_JALR:
3227     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3228     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
3229 dpavlin 24 if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
3230     s6 = SPECIAL_JR;
3231     ic->arg[2] = (addr & 0xffc) + 8;
3232     switch (s6) {
3233 dpavlin 22 case SPECIAL_JR:
3234     if (rs == MIPS_GPR_RA) {
3235     if (cpu->machine->show_trace_tree)
3236     ic->f = instr(jr_ra_trace);
3237     else
3238     ic->f = instr(jr_ra);
3239     } else {
3240     ic->f = instr(jr);
3241     }
3242     break;
3243     case SPECIAL_JALR:
3244     if (cpu->machine->show_trace_tree)
3245     ic->f = instr(jalr_trace);
3246     else
3247     ic->f = instr(jalr);
3248     break;
3249     }
3250 dpavlin 24 if (cpu->delay_slot) {
3251     fatal("TODO: branch in delay slot? (1)\n");
3252     goto bad;
3253 dpavlin 22 }
3254     break;
3255    
3256 dpavlin 24 case SPECIAL_SYSCALL:
3257     if (((iword >> 6) & 0xfffff) == 0x30378) {
3258     /* "Magic trap" for PROM emulation: */
3259     ic->f = instr(promemul);
3260     } else {
3261     ic->f = instr(syscall);
3262     }
3263     break;
3264    
3265     case SPECIAL_BREAK:
3266     ic->f = instr(break);
3267     break;
3268    
3269 dpavlin 22 case SPECIAL_SYNC:
3270     ic->f = instr(nop);
3271     break;
3272    
3273     default:goto bad;
3274     }
3275     break;
3276    
3277     case HI6_BEQ:
3278     case HI6_BNE:
3279 dpavlin 24 case HI6_BEQL:
3280     case HI6_BNEL:
3281     case HI6_BLEZ:
3282     case HI6_BLEZL:
3283     case HI6_BGTZ:
3284     case HI6_BGTZL:
3285 dpavlin 22 samepage_function = NULL; /* get rid of a compiler warning */
3286     switch (main_opcode) {
3287     case HI6_BEQ:
3288     ic->f = instr(beq);
3289     samepage_function = instr(beq_samepage);
3290     /* Special case: comparing a register with itself: */
3291     if (rs == rt) {
3292     ic->f = instr(b);
3293     samepage_function = instr(b_samepage);
3294     }
3295     break;
3296     case HI6_BNE:
3297     ic->f = instr(bne);
3298     samepage_function = instr(bne_samepage);
3299 dpavlin 24 break;
3300     case HI6_BEQL:
3301     ic->f = instr(beql);
3302     samepage_function = instr(beql_samepage);
3303     /* Special case: comparing a register with itself: */
3304     if (rs == rt) {
3305     ic->f = instr(b);
3306     samepage_function = instr(b_samepage);
3307     }
3308     break;
3309     case HI6_BNEL:
3310     ic->f = instr(bnel);
3311     samepage_function = instr(bnel_samepage);
3312     break;
3313     case HI6_BLEZ:
3314     ic->f = instr(blez);
3315     samepage_function = instr(blez_samepage);
3316     break;
3317     case HI6_BLEZL:
3318     ic->f = instr(blezl);
3319     samepage_function = instr(blezl_samepage);
3320     break;
3321     case HI6_BGTZ:
3322     ic->f = instr(bgtz);
3323     samepage_function = instr(bgtz_samepage);
3324     break;
3325     case HI6_BGTZL:
3326     ic->f = instr(bgtzl);
3327     samepage_function = instr(bgtzl_samepage);
3328     break;
3329 dpavlin 22 }
3330     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3331     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3332 dpavlin 24 ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
3333     + (addr & 0xffc) + 4 );
3334 dpavlin 22 /* Is the offset from the start of the current page still
3335     within the same page? Then use the samepage_function: */
3336     if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE - 1)
3337     << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc) < 0xffc) {
3338     ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page +
3339     ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
3340     & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
3341     ic->f = samepage_function;
3342     }
3343 dpavlin 24 if (cpu->delay_slot) {
3344     fatal("TODO: branch in delay slot? (2)\n");
3345     goto bad;
3346 dpavlin 22 }
3347     break;
3348    
3349 dpavlin 24 case HI6_ADDI:
3350 dpavlin 22 case HI6_ADDIU:
3351 dpavlin 24 case HI6_SLTI:
3352     case HI6_SLTIU:
3353     case HI6_DADDI:
3354 dpavlin 22 case HI6_DADDIU:
3355     case HI6_ANDI:
3356     case HI6_ORI:
3357     case HI6_XORI:
3358     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3359     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3360     if (main_opcode == HI6_ADDI ||
3361     main_opcode == HI6_ADDIU ||
3362 dpavlin 24 main_opcode == HI6_SLTI ||
3363     main_opcode == HI6_SLTIU ||
3364 dpavlin 22 main_opcode == HI6_DADDI ||
3365     main_opcode == HI6_DADDIU)
3366     ic->arg[2] = (int16_t)iword;
3367     else
3368     ic->arg[2] = (uint16_t)iword;
3369 dpavlin 24
3370 dpavlin 22 switch (main_opcode) {
3371 dpavlin 24 case HI6_ADDI: ic->f = instr(addi); break;
3372 dpavlin 22 case HI6_ADDIU: ic->f = instr(addiu); break;
3373 dpavlin 24 case HI6_SLTI: ic->f = instr(slti); break;
3374     case HI6_SLTIU: ic->f = instr(sltiu); break;
3375     case HI6_DADDI: ic->f = instr(daddi); x64 = 1; break;
3376 dpavlin 22 case HI6_DADDIU: ic->f = instr(daddiu); x64 = 1; break;
3377     case HI6_ANDI: ic->f = instr(andi); break;
3378     case HI6_ORI: ic->f = instr(ori); break;
3379     case HI6_XORI: ic->f = instr(xori); break;
3380     }
3381 dpavlin 24
3382 dpavlin 28 if (ic->arg[2] == 0) {
3383     if ((cpu->is_32bit && ic->f == instr(addiu)) ||
3384     (!cpu->is_32bit && ic->f == instr(daddiu))) {
3385     ic->f = instr(mov);
3386     ic->arg[2] = ic->arg[1];
3387     }
3388     }
3389    
3390 dpavlin 22 if (rt == MIPS_GPR_ZERO)
3391     ic->f = instr(nop);
3392    
3393     if (ic->f == instr(addiu))
3394 dpavlin 28 cpu->cd.mips.combination_check = COMBINE(addiu);
3395 dpavlin 24 if (ic->f == instr(daddiu))
3396     cpu->cd.mips.combination_check = COMBINE(b_daddiu);
3397 dpavlin 22 break;
3398    
3399     case HI6_LUI:
3400     ic->f = instr(set);
3401     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3402 dpavlin 24 ic->arg[1] = (int32_t) (imm << 16);
3403 dpavlin 28 /* NOTE: Don't use arg[2] here. It can be used with
3404     instruction combinations, to do lui + addiu, etc. */
3405 dpavlin 22 if (rt == MIPS_GPR_ZERO)
3406     ic->f = instr(nop);
3407     break;
3408    
3409 dpavlin 24 case HI6_J:
3410     case HI6_JAL:
3411     switch (main_opcode) {
3412     case HI6_J:
3413     ic->f = instr(j);
3414     break;
3415     case HI6_JAL:
3416     if (cpu->machine->show_trace_tree)
3417     ic->f = instr(jal_trace);
3418     else
3419     ic->f = instr(jal);
3420     break;
3421     }
3422     ic->arg[0] = (iword & 0x03ffffff) << 2;
3423     ic->arg[1] = (addr & 0xffc) + 8;
3424     if (cpu->delay_slot) {
3425     fatal("TODO: branch in delay slot (=%i)? (3); addr=%016"
3426     PRIx64" iword=%08"PRIx32"\n", cpu->delay_slot,
3427     (uint64_t)addr, iword);
3428     goto bad;
3429     }
3430     break;
3431    
3432 dpavlin 22 case HI6_COP0:
3433 dpavlin 24 /* TODO: Is checking bit 25 enough, or perhaps all bits
3434     25..21 must be checked? */
3435     if ((iword >> 25) & 1) {
3436     ic->arg[2] = addr & 0xffc;
3437     switch (iword & 0xff) {
3438     case COP0_TLBR:
3439     ic->f = instr(tlbr);
3440     break;
3441     case COP0_TLBWI:
3442     case COP0_TLBWR:
3443     ic->f = instr(tlbw);
3444     ic->arg[0] = (iword & 0xff) == COP0_TLBWR;
3445     break;
3446     case COP0_TLBP:
3447     ic->f = instr(tlbp);
3448     break;
3449     case COP0_RFE:
3450     ic->f = instr(rfe);
3451     break;
3452     case COP0_ERET:
3453     ic->f = instr(eret);
3454     break;
3455     case COP0_DERET:
3456     ic->f = instr(deret);
3457     break;
3458     case COP0_IDLE:
3459     case COP0_STANDBY:
3460     case COP0_SUSPEND:
3461     case COP0_HIBERNATE:
3462     /* TODO */
3463     ic->f = instr(nop);
3464     break;
3465     case COP0_EI:
3466     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3467     ic->f = instr(ei_r5900);
3468     } else
3469     goto bad;
3470     break;
3471     case COP0_DI:
3472     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3473     ic->f = instr(di_r5900);
3474     } else
3475     goto bad;
3476     break;
3477     default:fatal("UNIMPLEMENTED cop0 (func 0x%02x)\n",
3478     iword & 0xff);
3479     goto bad;
3480     }
3481     break;
3482     }
3483    
3484 dpavlin 22 /* rs contains the coprocessor opcode! */
3485     switch (rs) {
3486 dpavlin 24 case COPz_CFCz:
3487     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3488     ic->arg[1] = rd + ((iword & 7) << 5);
3489     ic->arg[2] = addr & 0xffc;
3490     ic->f = instr(cfc0);
3491     if (rt == MIPS_GPR_ZERO)
3492     ic->f = instr(nop);
3493     break;
3494 dpavlin 22 case COPz_MFCz:
3495     case COPz_DMFCz:
3496     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3497     ic->arg[1] = rd + ((iword & 7) << 5);
3498     ic->arg[2] = addr & 0xffc;
3499     ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);
3500     if (rt == MIPS_GPR_ZERO)
3501     ic->f = instr(nop);
3502     break;
3503     case COPz_MTCz:
3504     case COPz_DMTCz:
3505     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3506     ic->arg[1] = rd + ((iword & 7) << 5);
3507     ic->arg[2] = addr & 0xffc;
3508     ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
3509 dpavlin 28
3510     if (cpu->cd.mips.cpu_type.exc_model == EXC3K &&
3511     rs == COPz_MTCz && rd == COP0_STATUS)
3512     cpu->cd.mips.combination_check =
3513     COMBINE(netbsd_r3k_cache_inv);
3514    
3515 dpavlin 22 break;
3516 dpavlin 24 case 8: if (iword == 0x4100ffff) {
3517     /* R2020 DECstation write-loop thingy. */
3518     ic->f = instr(nop);
3519     } else {
3520     fatal("Unimplemented blah blah zzzz...\n");
3521     goto bad;
3522     }
3523     break;
3524    
3525 dpavlin 22 default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
3526     goto bad;
3527     }
3528     break;
3529    
3530     case HI6_COP1:
3531 dpavlin 24 /* Always cause a coprocessor unusable exception if
3532     there is no floating point coprocessor: */
3533     if (cpu->cd.mips.cpu_type.flags & NOFPU ||
3534     cpu->cd.mips.coproc[1] == NULL) {
3535     ic->f = instr(cpu);
3536     ic->arg[0] = 1;
3537     break;
3538     }
3539    
3540     /* Bits 25..21 are floating point main opcode: */
3541 dpavlin 22 switch (rs) {
3542 dpavlin 24
3543     case COPz_BCzc:
3544     /* Conditional branch: */
3545     /* TODO: Reimplement this in a faster way. */
3546     ic->f = instr(cop1_bc);
3547     ic->arg[0] = (iword >> 18) & 7; /* cc */
3548     ic->arg[1] = (iword >> 16) & 3; /* nd, tf bits */
3549     ic->arg[2] = (int32_t) ((imm <<
3550     MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);
3551     if (cpu->delay_slot) {
3552     fatal("TODO: branch in delay slot? (4)\n");
3553     goto bad;
3554     }
3555     if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
3556     ic->arg[0] != 0) {
3557     fatal("Attempt to execute a non-cc-0 BC*"
3558     " instruction on an isa level %i cpu. "
3559     "TODO: How should this be handled?\n",
3560     cpu->cd.mips.cpu_type.isa_level);
3561     goto bad;
3562     }
3563    
3564     break;
3565    
3566     case COPz_DMFCz:
3567     case COPz_DMTCz:
3568     x64 = 1;
3569     /* FALL-THROUGH */
3570     case COP1_FMT_S:
3571     case COP1_FMT_D:
3572     case COP1_FMT_W:
3573     case COP1_FMT_L:
3574     case COP1_FMT_PS:
3575 dpavlin 22 case COPz_CFCz:
3576 dpavlin 24 case COPz_CTCz:
3577     case COPz_MFCz:
3578     case COPz_MTCz:
3579     /* Fallback to slow pre-dyntrans code, for now. */
3580     /* TODO: Fix/optimize/rewrite. */
3581     ic->f = instr(cop1_slow);
3582     ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);
3583 dpavlin 22 break;
3584 dpavlin 24
3585     default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
3586 dpavlin 22 goto bad;
3587     }
3588     break;
3589    
3590 dpavlin 24 case HI6_COP2:
3591     /* Always cause a coprocessor unusable exception if
3592     there is no coprocessor 2: */
3593     if (cpu->cd.mips.coproc[2] == NULL) {
3594     ic->f = instr(cpu);
3595     ic->arg[0] = 2;
3596     break;
3597     }
3598     fatal("COP2 functionality not yet implemented\n");
3599     goto bad;
3600     break;
3601    
3602 dpavlin 22 case HI6_SPECIAL2:
3603 dpavlin 24 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3604     /* R5900, TX79/C790, have MMI instead of SPECIAL2: */
3605     int mmi_subopcode = (iword >> 6) & 0x1f;
3606    
3607     switch (s6) {
3608    
3609     case MMI_MADD:
3610     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3611     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3612     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3613     if (rd == MIPS_GPR_ZERO)
3614     ic->f = instr(madd);
3615     else
3616     ic->f = instr(madd_rd);
3617     break;
3618    
3619     case MMI_MADDU:
3620     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3621     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3622     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3623     if (rd == MIPS_GPR_ZERO)
3624     ic->f = instr(maddu);
3625     else
3626     ic->f = instr(maddu_rd);
3627     break;
3628    
3629     case MMI_MMI0:
3630     switch (mmi_subopcode) {
3631    
3632     case MMI0_PEXTLW:
3633     ic->arg[0] = rs;
3634     ic->arg[1] = rt;
3635     ic->arg[2] = rd;
3636     if (rd == MIPS_GPR_ZERO)
3637     ic->f = instr(nop);
3638     else
3639     ic->f = instr(pextlw);
3640     break;
3641    
3642     default:goto bad;
3643     }
3644     break;
3645    
3646     case MMI_MMI3:
3647     switch (mmi_subopcode) {
3648    
3649     case MMI3_POR:
3650     ic->arg[0] = rs;
3651     ic->arg[1] = rt;
3652     ic->arg[2] = rd;
3653     if (rd == MIPS_GPR_ZERO)
3654     ic->f = instr(nop);
3655     else
3656     ic->f = instr(por);
3657     break;
3658    
3659     default:goto bad;
3660     }
3661     break;
3662    
3663     default:goto bad;
3664     }
3665     break;
3666     }
3667    
3668     /* TODO: is this correct? Or are there other non-MIPS32/64
3669     MIPS processors that have support for SPECIAL2 opcodes? */
3670     if (cpu->cd.mips.cpu_type.isa_level < 32) {
3671     ic->f = instr(reserved);
3672     break;
3673     }
3674    
3675     /* SPECIAL2: */
3676 dpavlin 22 switch (s6) {
3677    
3678 dpavlin 24 case SPECIAL2_MADD:
3679     case SPECIAL2_MADDU:
3680     case SPECIAL2_MSUB:
3681     case SPECIAL2_MSUBU:
3682     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3683     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3684     switch (s6) {
3685     case SPECIAL2_MADD: ic->f = instr(madd); break;
3686     case SPECIAL2_MADDU:ic->f = instr(maddu); break;
3687     case SPECIAL2_MSUB: ic->f = instr(msub); break;
3688     case SPECIAL2_MSUBU:ic->f = instr(msubu); break;
3689     }
3690     break;
3691    
3692 dpavlin 22 case SPECIAL2_MUL:
3693     ic->f = instr(mul);
3694     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3695     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3696     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3697     if (rd == MIPS_GPR_ZERO)
3698     ic->f = instr(nop);
3699     break;
3700    
3701     case SPECIAL2_CLZ:
3702     case SPECIAL2_CLO:
3703     case SPECIAL2_DCLZ:
3704     case SPECIAL2_DCLO:
3705     switch (s6) {
3706     case SPECIAL2_CLZ: ic->f = instr(clz); break;
3707     case SPECIAL2_CLO: ic->f = instr(clo); break;
3708     case SPECIAL2_DCLZ: ic->f = instr(dclz); break;
3709     case SPECIAL2_DCLO: ic->f = instr(dclo); break;
3710     }
3711     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3712     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
3713     if (rd == MIPS_GPR_ZERO)
3714     ic->f = instr(nop);
3715     break;
3716    
3717     default:goto bad;
3718     }
3719     break;
3720    
3721 dpavlin 24 case HI6_REGIMM:
3722     switch (rt) {
3723     case REGIMM_BGEZ:
3724     case REGIMM_BGEZL:
3725     case REGIMM_BLTZ:
3726     case REGIMM_BLTZL:
3727     case REGIMM_BGEZAL:
3728     case REGIMM_BGEZALL:
3729     case REGIMM_BLTZAL:
3730     case REGIMM_BLTZALL:
3731     samepage_function = NULL;
3732     switch (rt) {
3733     case REGIMM_BGEZ:
3734     ic->f = instr(bgez);
3735     samepage_function = instr(bgez_samepage);
3736     break;
3737     case REGIMM_BGEZL:
3738     ic->f = instr(bgezl);
3739     samepage_function = instr(bgezl_samepage);
3740     break;
3741     case REGIMM_BLTZ:
3742     ic->f = instr(bltz);
3743     samepage_function = instr(bltz_samepage);
3744     break;
3745     case REGIMM_BLTZL:
3746     ic->f = instr(bltzl);
3747     samepage_function = instr(bltzl_samepage);
3748     break;
3749     case REGIMM_BGEZAL:
3750     ic->f = instr(bgezal);
3751     samepage_function = instr(bgezal_samepage);
3752     break;
3753     case REGIMM_BGEZALL:
3754     ic->f = instr(bgezall);
3755     samepage_function = instr(bgezall_samepage);
3756     break;
3757     case REGIMM_BLTZAL:
3758     ic->f = instr(bltzal);
3759     samepage_function = instr(bltzal_samepage);
3760     break;
3761     case REGIMM_BLTZALL:
3762     ic->f = instr(bltzall);
3763     samepage_function = instr(bltzall_samepage);
3764     break;
3765     }
3766     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3767     ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
3768     + (addr & 0xffc) + 4;
3769     /* Is the offset from the start of the current page
3770     still within the same page? Then use the
3771     samepage_function: */
3772     if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE-1)
3773     << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc)
3774     < 0xffc) {
3775     ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page+
3776     ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
3777     & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
3778     ic->f = samepage_function;
3779     }
3780     if (cpu->delay_slot) {
3781     fatal("TODO: branch in delay slot? (5)\n");
3782     goto bad;
3783     }
3784     break;
3785     default:fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
3786     goto bad;
3787     }
3788     break;
3789    
3790     case HI6_LB:
3791     case HI6_LBU:
3792     case HI6_SB:
3793     case HI6_LH:
3794     case HI6_LHU:
3795     case HI6_SH:
3796     case HI6_LW:
3797     case HI6_LWU:
3798     case HI6_SW:
3799     case HI6_LD:
3800     case HI6_SD:
3801     /* TODO: LWU should probably also be x64=1? */
3802     size = 2; signedness = 0; store = 0;
3803     switch (main_opcode) {
3804     case HI6_LB: size = 0; signedness = 1; break;
3805     case HI6_LBU: size = 0; break;
3806     case HI6_LH: size = 1; signedness = 1; break;
3807     case HI6_LHU: size = 1; break;
3808     case HI6_LW: signedness = 1; break;
3809     case HI6_LWU: break;
3810     case HI6_LD: size = 3; x64 = 1; break;
3811     case HI6_SB: store = 1; size = 0; break;
3812     case HI6_SH: store = 1; size = 1; break;
3813     case HI6_SW: store = 1; break;
3814     case HI6_SD: store = 1; size = 3; x64 = 1; break;
3815     }
3816    
3817     ic->f =
3818     #ifdef MODE32
3819     mips32_loadstore
3820     #else
3821     mips_loadstore
3822     #endif
3823     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16)
3824     + store * 8 + size * 2 + signedness];
3825     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3826     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3827     ic->arg[2] = (int32_t)imm;
3828    
3829     /* Load into the dummy scratch register, if rt = zero */
3830     if (!store && rt == MIPS_GPR_ZERO)
3831     ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
3832 dpavlin 28
3833     /* Check for multiple stores in a row using the same
3834     base register: */
3835     if (main_opcode == HI6_SW && rs == MIPS_GPR_SP)
3836     cpu->cd.mips.combination_check = COMBINE(multi_sw);
3837    
3838 dpavlin 24 break;
3839    
3840     case HI6_LL:
3841     case HI6_LLD:
3842     case HI6_SC:
3843     case HI6_SCD:
3844     /* 32-bit load-linked/store-condition for ISA II and up: */
3845     /* (64-bit load-linked/store-condition for ISA III...) */
3846     if (cpu->cd.mips.cpu_type.isa_level < 2) {
3847     ic->f = instr(reserved);
3848     break;
3849     }
3850    
3851     store = 0;
3852     switch (main_opcode) {
3853     case HI6_LL: ic->f = instr(ll); break;
3854     case HI6_LLD: ic->f = instr(lld); x64 = 1; break;
3855     case HI6_SC: ic->f = instr(sc); store = 1; break;
3856     case HI6_SCD: ic->f = instr(scd); store = 1; x64 = 1; break;
3857     }
3858     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3859     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3860     ic->arg[2] = (int32_t)imm;
3861     if (!store && rt == MIPS_GPR_ZERO) {
3862     fatal("HM... unusual load linked\n");
3863     goto bad;
3864     }
3865     break;
3866    
3867     case HI6_LWL:
3868     case HI6_LWR:
3869     case HI6_LDL:
3870     case HI6_LDR:
3871     case HI6_SWL:
3872     case HI6_SWR:
3873     case HI6_SDL:
3874     case HI6_SDR:
3875     /* TODO: replace these with faster versions... */
3876     store = 0;
3877     switch (main_opcode) {
3878     case HI6_LWL: ic->f = instr(lwl); break;
3879     case HI6_LWR: ic->f = instr(lwr); break;
3880     case HI6_LDL: ic->f = instr(ldl); x64 = 1; break;
3881     case HI6_LDR: ic->f = instr(ldr); x64 = 1; break;
3882     case HI6_SWL: ic->f = instr(swl); store = 1; break;
3883     case HI6_SWR: ic->f = instr(swr); store = 1; break;
3884     case HI6_SDL: ic->f = instr(sdl); store = 1; x64 = 1; break;
3885     case HI6_SDR: ic->f = instr(sdr); store = 1; x64 = 1; break;
3886     }
3887     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3888     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3889     ic->arg[2] = (int32_t)imm;
3890    
3891     /* Load into the dummy scratch register, if rt = zero */
3892     if (!store && rt == MIPS_GPR_ZERO)
3893     ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
3894     break;
3895    
3896     case HI6_LWC1:
3897     case HI6_SWC1:
3898     case HI6_LDC1:
3899     case HI6_SDC1:
3900     /* 64-bit floating-point load/store for ISA II and up... */
3901     if ((main_opcode == HI6_LDC1 || main_opcode == HI6_SDC1)
3902     && cpu->cd.mips.cpu_type.isa_level < 2) {
3903     ic->f = instr(reserved);
3904     break;
3905     }
3906    
3907     ic->arg[0] = (size_t)&cpu->cd.mips.coproc[1]->reg[rt];
3908     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3909     ic->arg[2] = (int32_t)imm;
3910     switch (main_opcode) {
3911     case HI6_LWC1: ic->f = instr(lwc1); break;
3912     case HI6_LDC1: ic->f = instr(ldc1); break;
3913     case HI6_SWC1: ic->f = instr(swc1); break;
3914     case HI6_SDC1: ic->f = instr(sdc1); break;
3915     }
3916    
3917     /* Cause a coprocessor unusable exception if
3918     there is no floating point coprocessor: */
3919     if (cpu->cd.mips.cpu_type.flags & NOFPU ||
3920     cpu->cd.mips.coproc[1] == NULL) {
3921     ic->f = instr(cpu);
3922     ic->arg[0] = 1;
3923     }
3924     break;
3925    
3926     case HI6_LWC3:
3927     /* PREF (prefetch) on ISA IV and MIPS32/64: */
3928     if (cpu->cd.mips.cpu_type.isa_level >= 4) {
3929     /* Treat as nop for now: */
3930     ic->f = instr(nop);
3931     } else {
3932     fatal("TODO: lwc3 not implemented yet\n");
3933     goto bad;
3934     }
3935     break;
3936    
3937     case HI6_LQ_MDMX:
3938     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3939     fatal("TODO: R5900 128-bit loads\n");
3940     goto bad;
3941     }
3942    
3943     fatal("TODO: MDMX\n");
3944     goto bad;
3945     /* break */
3946    
3947     case HI6_SQ_SPECIAL3:
3948     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3949     fatal("TODO: R5900 128-bit stores\n");
3950     goto bad;
3951     }
3952    
3953     if (cpu->cd.mips.cpu_type.isa_level < 32 ||
3954     cpu->cd.mips.cpu_type.isa_revision < 2) {
3955     static int warning = 0;
3956     if (!warning) {
3957 dpavlin 28 fatal("[ WARNING! SPECIAL3 opcode used, but"
3958     " the %s processor does not implement "
3959     "such instructions. Only printing this "
3960     "warning once. ]\n",
3961     cpu->cd.mips.cpu_type.name);
3962 dpavlin 24 warning = 1;
3963     }
3964     ic->f = instr(reserved);
3965     break;
3966     }
3967    
3968     switch (s6) {
3969    
3970     case SPECIAL3_RDHWR:
3971     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3972    
3973     switch (rd) {
3974    
3975     case 0: ic->f = instr(rdhwr_cpunum);
3976     if (rt == MIPS_GPR_ZERO)
3977     ic->f = instr(nop);
3978     break;
3979    
3980     default:fatal("unimplemented rdhwr register rd=%i\n",
3981     rd);
3982     goto bad;
3983     }
3984     break;
3985    
3986     default:goto bad;
3987     }
3988     break;
3989    
3990     case HI6_CACHE:
3991     /* TODO: rt and op etc... */
3992     ic->f = instr(cache);
3993     break;
3994    
3995 dpavlin 22 default:goto bad;
3996     }
3997    
3998 dpavlin 24 #ifdef MODE32
3999     if (x64) {
4000     static int has_warned = 0;
4001     if (!has_warned)
4002     fatal("[ WARNING/NOTE: attempt to execute a 64-bit"
4003     " instruction on an emulated 32-bit processor; "
4004     "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);
4005     has_warned = 1;
4006     ic->f = instr(reserved);
4007     }
4008     #endif
4009 dpavlin 22
4010 dpavlin 28 if (ic->f == instr(nop) && cpu->cd.mips.combination_check == NULL)
4011     cpu->cd.mips.combination_check = COMBINE(nop);
4012 dpavlin 22
4013 dpavlin 28
4014 dpavlin 22 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
4015     #include "cpu_dyntrans.c"
4016     #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
4017     }
4018    

  ViewVC Help
Powered by ViewVC 1.1.26