/[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 38 - (hide annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 118482 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 0.4.5  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26