/[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 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 123195 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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 44 * $Id: cpu_mips_instr.c,v 1.143 2007/06/28 13:36:46 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 42 * ins: Insert bitfield.
1153     *
1154     * arg[0] = pointer to rt
1155     * arg[1] = pointer to rs
1156     * arg[2] = (msb << 5) + lsb
1157     */
1158     X(ins)
1159     {
1160     int msb = ic->arg[2] >> 5, pos = ic->arg[2] & 0x1f;
1161     int size = msb + 1 - pos;
1162     uint32_t rt = reg(ic->arg[0]);
1163     uint32_t rs = reg(ic->arg[1]);
1164     uint32_t mask = (-1) << pos;
1165    
1166     mask <<= (32 - pos - size);
1167     mask >>= (32 - pos - size);
1168    
1169     reg(ic->arg[0]) = (int32_t) ((rt & ~mask) | ((rs << pos) & mask));
1170     }
1171    
1172    
1173     /*
1174 dpavlin 32 * ext: Extract bitfield.
1175     *
1176     * arg[0] = pointer to rt
1177     * arg[1] = pointer to rs
1178     * arg[2] = (msbd << 5) + lsb
1179     */
1180     X(ext)
1181     {
1182 dpavlin 42 int msbd = ic->arg[2] >> 5, lsb = ic->arg[2] & 0x1f;
1183     int size = msbd + 1;
1184     uint32_t rs = reg(ic->arg[1]);
1185     uint32_t x = (rs << (32-lsb-size)) >> (32-lsb-size);
1186     reg(ic->arg[0]) = (int32_t) (x >> lsb);
1187 dpavlin 32 }
1188    
1189    
1190     /*
1191 dpavlin 42 * dext: Extract bitfield (64-bit).
1192     *
1193     * arg[0] = pointer to rt
1194     * arg[1] = pointer to rs
1195     * arg[2] = (msbd << 6) + lsb
1196     */
1197     X(dext)
1198     {
1199     int msbd = ic->arg[2] >> 6, lsb = ic->arg[2] & 0x3f;
1200     int size = msbd + 1;
1201     uint64_t rs = reg(ic->arg[1]);
1202     uint64_t x = (rs << (uint64_t)(64-lsb-size)) >> (uint64_t)(64-lsb-size);
1203     reg(ic->arg[0]) = x >> lsb;
1204     }
1205    
1206    
1207     /*
1208 dpavlin 32 * dsbh: Doubleword swap bytes within half-word
1209     * dshd: Doubleword swap half-words within double-word
1210     * wsbh: Word swap bytes within half-word
1211     * seb: Sign-extend byte
1212     * seh: Sign-extend half-word
1213     *
1214     * arg[0] = pointer to rt
1215     * arg[1] = pointer to rd
1216     */
1217     X(dsbh)
1218     {
1219     uint64_t x = reg(ic->arg[0]);
1220     x = ((x & 0x00ff00ff00ff00ffULL) << 8)
1221     | ((x & 0xff00ff00ff00ff00ULL) >> 8);
1222     reg(ic->arg[1]) = x;
1223     }
1224     X(dshd)
1225     {
1226     uint64_t x = reg(ic->arg[0]);
1227     x = ((x & 0x000000000000ffffULL) << 48)
1228     | ((x & 0x00000000ffff0000ULL) << 16)
1229     | ((x & 0x0000ffff00000000ULL) >> 16)
1230     | ((x & 0xffff000000000000ULL) >> 48);
1231     reg(ic->arg[1]) = x;
1232     }
1233     X(wsbh)
1234     {
1235     uint32_t x = reg(ic->arg[0]);
1236     x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8);
1237     reg(ic->arg[1]) = (int32_t) x;
1238     }
1239     X(seb) { reg(ic->arg[1]) = (int8_t)reg(ic->arg[0]); }
1240     X(seh) { reg(ic->arg[1]) = (int16_t)reg(ic->arg[0]); }
1241    
1242    
1243     /*
1244 dpavlin 22 * 2-register + immediate:
1245     *
1246     * arg[0] = pointer to rs
1247     * arg[1] = pointer to rt
1248     * arg[2] = uint32_t immediate value
1249     */
1250 dpavlin 24 X(andi) { reg(ic->arg[1]) = reg(ic->arg[0]) & (uint32_t)ic->arg[2]; }
1251     X(ori) { reg(ic->arg[1]) = reg(ic->arg[0]) | (uint32_t)ic->arg[2]; }
1252     X(xori) { reg(ic->arg[1]) = reg(ic->arg[0]) ^ (uint32_t)ic->arg[2]; }
1253 dpavlin 22
1254    
1255     /*
1256     * 2-register:
1257 dpavlin 24 *
1258     * arg[0] = ptr to rs
1259     * arg[1] = ptr to rt
1260 dpavlin 22 */
1261 dpavlin 24 X(div)
1262     {
1263     int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1264     int32_t res, rem;
1265     if (b == 0)
1266     res = 0, rem = a;
1267     else
1268     res = a / b, rem = a - b*res;
1269 dpavlin 32 cpu->cd.mips.lo = (int32_t)res;
1270     cpu->cd.mips.hi = (int32_t)rem;
1271 dpavlin 24 }
1272     X(divu)
1273     {
1274     uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1275     uint32_t res, rem;
1276     if (b == 0)
1277     res = 0, rem = a;
1278     else
1279     res = a / b, rem = a - b*res;
1280 dpavlin 32 cpu->cd.mips.lo = (int32_t)res;
1281     cpu->cd.mips.hi = (int32_t)rem;
1282 dpavlin 24 }
1283     X(ddiv)
1284     {
1285     int64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1286     int64_t res, rem;
1287     if (b == 0)
1288     res = 0;
1289     else
1290     res = a / b;
1291     rem = a - b*res;
1292 dpavlin 32 cpu->cd.mips.lo = res;
1293     cpu->cd.mips.hi = rem;
1294 dpavlin 24 }
1295     X(ddivu)
1296     {
1297     uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1298     uint64_t res, rem;
1299     if (b == 0)
1300     res = 0;
1301     else
1302     res = a / b;
1303     rem = a - b*res;
1304 dpavlin 32 cpu->cd.mips.lo = res;
1305     cpu->cd.mips.hi = rem;
1306 dpavlin 24 }
1307 dpavlin 22 X(mult)
1308     {
1309     int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1310     int64_t res = (int64_t)a * (int64_t)b;
1311 dpavlin 32 cpu->cd.mips.lo = (int32_t)res;
1312     cpu->cd.mips.hi = (int32_t)(res >> 32);
1313 dpavlin 22 }
1314 dpavlin 24 X(mult_r5900)
1315     {
1316     /* C790/TX79/R5900 multiplication, stores result in
1317     hi, lo, and a third register */
1318     int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1319     int64_t res = (int64_t)a * (int64_t)b;
1320 dpavlin 32 cpu->cd.mips.lo = (int32_t)res;
1321     cpu->cd.mips.hi = (int32_t)(res >> 32);
1322 dpavlin 24 reg(ic->arg[2]) = (int32_t)res;
1323     }
1324 dpavlin 22 X(multu)
1325     {
1326     uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1327     uint64_t res = (uint64_t)a * (uint64_t)b;
1328 dpavlin 32 cpu->cd.mips.lo = (int32_t)res;
1329     cpu->cd.mips.hi = (int32_t)(res >> 32);
1330 dpavlin 22 }
1331 dpavlin 24 X(multu_r5900)
1332     {
1333     /* C790/TX79/R5900 multiplication, stores result in
1334     hi, lo, and a third register */
1335     uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1336     uint64_t res = (uint64_t)a * (uint64_t)b;
1337 dpavlin 32 cpu->cd.mips.lo = (int32_t)res;
1338     cpu->cd.mips.hi = (int32_t)(res >> 32);
1339 dpavlin 24 reg(ic->arg[2]) = (int32_t)res;
1340     }
1341     X(dmult)
1342     {
1343     uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1344     uint64_t hi = 0, lo = 0;
1345     int neg = 0;
1346     if (a >> 63)
1347     neg = !neg, a = -a;
1348     if (b >> 63)
1349     neg = !neg, b = -b;
1350     for (; a; a >>= 1) {
1351     if (a & 1) {
1352     uint64_t old_lo = lo;
1353     hi += c;
1354     lo += b;
1355     if (lo < old_lo)
1356     hi ++;
1357     }
1358     c = (c << 1) | (b >> 63); b <<= 1;
1359     }
1360     if (neg) {
1361     if (lo == 0)
1362     hi --;
1363     lo --;
1364     hi ^= (int64_t) -1;
1365     lo ^= (int64_t) -1;
1366     }
1367 dpavlin 32 cpu->cd.mips.lo = lo;
1368     cpu->cd.mips.hi = hi;
1369 dpavlin 24 }
1370     X(dmultu)
1371     {
1372     uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1373     uint64_t hi = 0, lo = 0;
1374     for (; a; a >>= 1) {
1375     if (a & 1) {
1376     uint64_t old_lo = lo;
1377     hi += c;
1378     lo += b;
1379     if (lo < old_lo)
1380     hi ++;
1381     }
1382     c = (c << 1) | (b >> 63); b <<= 1;
1383     }
1384 dpavlin 32 cpu->cd.mips.lo = lo;
1385     cpu->cd.mips.hi = hi;
1386 dpavlin 24 }
1387     X(tge)
1388     {
1389     MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1390     if (a >= b) {
1391     /* Synch. PC and cause an exception: */
1392     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1393     / sizeof(struct mips_instr_call);
1394     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1395     << MIPS_INSTR_ALIGNMENT_SHIFT);
1396     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1397     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1398     }
1399     }
1400     X(tgeu)
1401     {
1402     MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1403     if (a >= b) {
1404     /* Synch. PC and cause an exception: */
1405     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1406     / sizeof(struct mips_instr_call);
1407     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1408     << MIPS_INSTR_ALIGNMENT_SHIFT);
1409     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1410     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1411     }
1412     }
1413     X(tlt)
1414     {
1415     MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1416     if (a < b) {
1417     /* Synch. PC and cause an exception: */
1418     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1419     / sizeof(struct mips_instr_call);
1420     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1421     << MIPS_INSTR_ALIGNMENT_SHIFT);
1422     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1423     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1424     }
1425     }
1426     X(tltu)
1427     {
1428     MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1429     if (a < b) {
1430     /* Synch. PC and cause an exception: */
1431     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1432     / sizeof(struct mips_instr_call);
1433     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1434     << MIPS_INSTR_ALIGNMENT_SHIFT);
1435     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1436     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1437     }
1438     }
1439     X(teq)
1440     {
1441     MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1442     if (a == b) {
1443     /* Synch. PC and cause an exception: */
1444     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1445     / sizeof(struct mips_instr_call);
1446     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1447     << MIPS_INSTR_ALIGNMENT_SHIFT);
1448     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1449     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1450     }
1451     }
1452     X(tne)
1453     {
1454     MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1455     if (a != b) {
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_TR, 0, 0, 0, 0, 0, 0);
1463     }
1464     }
1465 dpavlin 22
1466    
1467     /*
1468 dpavlin 24 * 3-register arithmetic instructions:
1469     *
1470     * arg[0] = ptr to rs
1471     * arg[1] = ptr to rt
1472     * arg[2] = ptr to rd
1473 dpavlin 22 */
1474     X(addu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) + reg(ic->arg[1])); }
1475 dpavlin 24 X(add)
1476     {
1477     int32_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1478     int32_t rd = rs + rt;
1479    
1480     if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1481     /* Synch. PC and cause an exception: */
1482     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1483     / sizeof(struct mips_instr_call);
1484     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1485     << MIPS_INSTR_ALIGNMENT_SHIFT);
1486     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1487     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1488     } else
1489     reg(ic->arg[2]) = rd;
1490     }
1491     X(daddu){ reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }
1492     X(dadd)
1493     {
1494     int64_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1495     int64_t rd = rs + rt;
1496    
1497     if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1498     /* Synch. PC and cause an exception: */
1499     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1500     / sizeof(struct mips_instr_call);
1501     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1502     << MIPS_INSTR_ALIGNMENT_SHIFT);
1503     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1504     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1505     } else
1506     reg(ic->arg[2]) = rd;
1507     }
1508 dpavlin 22 X(subu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) - reg(ic->arg[1])); }
1509 dpavlin 24 X(sub)
1510     {
1511     /* NOTE: Negating rt and using addition. TODO: Is this correct? */
1512     int32_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1513     int32_t rd = rs + rt;
1514    
1515     if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1516     /* Synch. PC and cause an exception: */
1517     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1518     / sizeof(struct mips_instr_call);
1519     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1520     << MIPS_INSTR_ALIGNMENT_SHIFT);
1521     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1522     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1523     } else
1524     reg(ic->arg[2]) = rd;
1525     }
1526     X(dsubu){ reg(ic->arg[2]) = reg(ic->arg[0]) - reg(ic->arg[1]); }
1527     X(dsub)
1528     {
1529     /* NOTE: Negating rt and using addition. TODO: Is this correct? */
1530     int64_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1531     int64_t rd = rs + rt;
1532    
1533     if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1534     /* Synch. PC and cause an exception: */
1535     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1536     / sizeof(struct mips_instr_call);
1537     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1538     << MIPS_INSTR_ALIGNMENT_SHIFT);
1539     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1540     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1541     } else
1542     reg(ic->arg[2]) = rd;
1543     }
1544 dpavlin 22 X(slt) {
1545 dpavlin 24 reg(ic->arg[2]) =
1546     (MODE_int_t)reg(ic->arg[0]) < (MODE_int_t)reg(ic->arg[1]);
1547 dpavlin 22 }
1548     X(sltu) {
1549 dpavlin 24 reg(ic->arg[2]) =
1550     (MODE_uint_t)reg(ic->arg[0]) < (MODE_uint_t)reg(ic->arg[1]);
1551 dpavlin 22 }
1552 dpavlin 24 X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
1553     X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
1554 dpavlin 22 X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
1555     X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }
1556 dpavlin 24 X(sll) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << (int32_t)ic->arg[1]); }
1557     X(sllv){ int32_t sa = reg(ic->arg[1]) & 31;
1558     reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << sa); }
1559 dpavlin 22 X(srl) { reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1560 dpavlin 24 X(srlv){ int32_t sa = reg(ic->arg[1]) & 31;
1561     reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> sa); }
1562 dpavlin 22 X(sra) { reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1563 dpavlin 24 X(srav){ int32_t sa = reg(ic->arg[1]) & 31;
1564     reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> sa); }
1565     X(dsll) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) << (int64_t)ic->arg[1]; }
1566     X(dsllv){ int64_t sa = reg(ic->arg[1]) & 63;
1567     reg(ic->arg[2]) = reg(ic->arg[0]) << sa; }
1568     X(dsrl) { reg(ic->arg[2]) = (int64_t)((uint64_t)reg(ic->arg[0]) >>
1569     (uint64_t) ic->arg[1]);}
1570     X(dsrlv){ int64_t sa = reg(ic->arg[1]) & 63;
1571     reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) >> sa; }
1572     X(dsra) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> (int64_t)ic->arg[1]; }
1573     X(dsrav){ int64_t sa = reg(ic->arg[1]) & 63;
1574     reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> sa; }
1575 dpavlin 22 X(mul) { reg(ic->arg[2]) = (int32_t)
1576     ( (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]) ); }
1577 dpavlin 24 X(movn) { if (reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1578     X(movz) { if (!reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1579 dpavlin 22
1580 dpavlin 44 X(ror)
1581     {
1582     uint32_t result = reg(ic->arg[0]);
1583     int sa = ic->arg[1];
1584 dpavlin 22
1585 dpavlin 44 result = (result >> sa) | (result << (32-sa));
1586    
1587     reg(ic->arg[2]) = (int32_t) result;
1588     }
1589    
1590    
1591 dpavlin 22 /*
1592 dpavlin 24 * p*: 128-bit C790/TX79/R5900 stuff
1593     *
1594     * arg[0] = rs (note: not a pointer)
1595     * arg[1] = rt (note: not a pointer)
1596     * arg[2] = rd (note: not a pointer)
1597     */
1598     X(por)
1599     {
1600     cpu->cd.mips.gpr[ic->arg[2]] = cpu->cd.mips.gpr[ic->arg[0]] |
1601     cpu->cd.mips.gpr[ic->arg[1]];
1602     cpu->cd.mips.gpr_quadhi[ic->arg[2]] =
1603     cpu->cd.mips.gpr_quadhi[ic->arg[0]] |
1604     cpu->cd.mips.gpr_quadhi[ic->arg[1]];
1605     }
1606     X(pextlw)
1607     {
1608     uint64_t lo, hi;
1609    
1610     lo = (uint32_t)cpu->cd.mips.gpr[ic->arg[1]] |
1611     (uint64_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[0]] << 32);
1612     hi = (cpu->cd.mips.gpr[ic->arg[0]] & 0xffffffff00000000ULL) |
1613     (uint32_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[1]] >> 32);
1614    
1615     cpu->cd.mips.gpr[ic->arg[2]] = lo;
1616     cpu->cd.mips.gpr_quadhi[ic->arg[2]] = hi;
1617     }
1618    
1619    
1620     /*
1621     * madd, maddu, msub, msubu: Multiply-and-add/subtract
1622     *
1623     * arg[0] = ptr to rs
1624     * arg[1] = ptr to rt
1625     * arg[2] = ptr to rd (only used on R5900/TX79)
1626     */
1627     X(madd)
1628     {
1629     int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1630     int64_t sum = rs * rt,
1631     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1632     hilo += sum;
1633     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1634     }
1635     X(madd_rd)
1636     {
1637     int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1638     int64_t sum = rs * rt,
1639     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1640     hilo += sum;
1641     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1642     reg(ic->arg[2]) = (int32_t)hilo;
1643     }
1644     X(msub)
1645     {
1646     int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1647     int64_t sum = rs * rt,
1648     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1649     hilo -= sum;
1650     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1651     }
1652     X(maddu)
1653     {
1654     int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1655     int64_t sum = rs * rt,
1656     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1657     hilo += sum;
1658     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1659     }
1660     X(maddu_rd)
1661     {
1662     int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1663     int64_t sum = rs * rt,
1664     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1665     hilo += sum;
1666     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1667     reg(ic->arg[2]) = (int32_t)hilo;
1668     }
1669     X(msubu)
1670     {
1671     int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1672     int64_t sum = rs * rt,
1673     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1674     hilo -= sum;
1675     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1676     }
1677    
1678    
1679     /*
1680 dpavlin 22 * mov: Move one register into another.
1681     *
1682     * arg[0] = pointer to source
1683     * arg[2] = pointer to destination
1684     */
1685     X(mov) { reg(ic->arg[2]) = reg(ic->arg[0]); }
1686    
1687    
1688     /*
1689     * clz, clo, dclz, dclo: Count leading zeroes/ones.
1690     *
1691     * arg[0] = pointer to rs
1692     * arg[1] = pointer to rd
1693     */
1694     X(clz)
1695     {
1696     uint32_t x = reg(ic->arg[0]);
1697     int count;
1698     for (count=0; count<32; count++) {
1699     if (x & 0x80000000UL)
1700     break;
1701     x <<= 1;
1702     }
1703     reg(ic->arg[1]) = count;
1704     }
1705     X(clo)
1706     {
1707     uint32_t x = reg(ic->arg[0]);
1708     int count;
1709     for (count=0; count<32; count++) {
1710     if (!(x & 0x80000000UL))
1711     break;
1712     x <<= 1;
1713     }
1714     reg(ic->arg[1]) = count;
1715     }
1716     X(dclz)
1717     {
1718     uint64_t x = reg(ic->arg[0]);
1719     int count;
1720     for (count=0; count<64; count++) {
1721     if (x & 0x8000000000000000ULL)
1722     break;
1723     x <<= 1;
1724     }
1725     reg(ic->arg[1]) = count;
1726     }
1727     X(dclo)
1728     {
1729     uint64_t x = reg(ic->arg[0]);
1730     int count;
1731     for (count=0; count<64; count++) {
1732     if (!(x & 0x8000000000000000ULL))
1733     break;
1734     x <<= 1;
1735     }
1736     reg(ic->arg[1]) = count;
1737     }
1738    
1739    
1740     /*
1741 dpavlin 24 * addi, daddi: Add immediate, overflow detection.
1742     * addiu, daddiu: Add immediate.
1743     * slti: Set if less than immediate (signed 32-bit)
1744     * sltiu: Set if less than immediate (signed 32-bit, but unsigned compare)
1745 dpavlin 22 *
1746     * arg[0] = pointer to rs
1747     * arg[1] = pointer to rt
1748     * arg[2] = (int32_t) immediate value
1749     */
1750 dpavlin 24 X(addi)
1751     {
1752     int32_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1753     int32_t rt = rs + imm;
1754    
1755     if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1756     /* Synch. PC and cause an exception: */
1757     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1758     / sizeof(struct mips_instr_call);
1759     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1760     << MIPS_INSTR_ALIGNMENT_SHIFT);
1761     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1762     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1763     } else
1764     reg(ic->arg[1]) = rt;
1765     }
1766 dpavlin 22 X(addiu)
1767     {
1768     reg(ic->arg[1]) = (int32_t)
1769     ((int32_t)reg(ic->arg[0]) + (int32_t)ic->arg[2]);
1770     }
1771 dpavlin 24 X(daddi)
1772     {
1773     int64_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1774     int64_t rt = rs + imm;
1775 dpavlin 22
1776 dpavlin 24 if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1777     /* Synch. PC and cause an exception: */
1778     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1779     / sizeof(struct mips_instr_call);
1780     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1781     << MIPS_INSTR_ALIGNMENT_SHIFT);
1782     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1783     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1784     } else
1785     reg(ic->arg[1]) = rt;
1786     }
1787 dpavlin 22 X(daddiu)
1788     {
1789     reg(ic->arg[1]) = reg(ic->arg[0]) + (int32_t)ic->arg[2];
1790     }
1791 dpavlin 24 X(slti)
1792     {
1793     reg(ic->arg[1]) = (MODE_int_t)reg(ic->arg[0]) < (int32_t)ic->arg[2];
1794     }
1795     X(sltiu)
1796     {
1797     reg(ic->arg[1]) = (MODE_uint_t)reg(ic->arg[0]) <
1798     ((MODE_uint_t)(int32_t)ic->arg[2]);
1799     }
1800 dpavlin 22
1801    
1802     /*
1803     * set: Set a register to an immediate (signed) 32-bit value.
1804 dpavlin 32 * (This is the actual implementation of the lui instruction.)
1805 dpavlin 22 *
1806     * arg[0] = pointer to the register
1807     * arg[1] = (int32_t) immediate value
1808     */
1809     X(set)
1810     {
1811     reg(ic->arg[0]) = (int32_t)ic->arg[1];
1812     }
1813    
1814    
1815     /*
1816 dpavlin 24 * cfc0: Copy from Coprocessor 0.
1817 dpavlin 22 * mfc0, dmfc0: Move from Coprocessor 0.
1818     * mtc0, dmtc0: Move to Coprocessor 0.
1819     *
1820     * arg[0] = pointer to GPR (rt)
1821 dpavlin 24 * arg[1] = coprocessor 0 register number | (select << 5) (or for the
1822     * cfc0 instruction, the coprocessor control register number)
1823 dpavlin 22 * arg[2] = relative addr of this instruction within the page
1824     */
1825 dpavlin 24 X(cfc0)
1826     {
1827     int fs = ic->arg[1] & 31;
1828     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1829     cpu->pc |= ic->arg[2];
1830     /* TODO: cause exception if necessary */
1831     reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->fcr[fs];
1832     }
1833 dpavlin 22 X(mfc0)
1834     {
1835     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1836     uint64_t tmp;
1837     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1838     cpu->pc |= ic->arg[2];
1839     /* TODO: cause exception if necessary */
1840     coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select);
1841     reg(ic->arg[0]) = (int32_t)tmp;
1842     }
1843 dpavlin 32 X(mfc0_select0)
1844     {
1845     /* Fast int32_t read, with no side effects: */
1846     int rd = ic->arg[1] & 31;
1847     #if 0
1848     uint64_t tmp;
1849     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1850     cpu->pc |= ic->arg[2];
1851     /* TODO: cause exception if necessary */
1852     #endif
1853     reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->reg[rd];
1854     }
1855 dpavlin 22 X(mtc0)
1856     {
1857     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1858 dpavlin 24 uint64_t tmp = (int32_t) reg(ic->arg[0]);
1859 dpavlin 26
1860 dpavlin 22 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1861     cpu->pc |= ic->arg[2];
1862 dpavlin 24
1863 dpavlin 22 /* TODO: cause exception if necessary */
1864 dpavlin 24 coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd, &tmp, 0, select);
1865    
1866 dpavlin 26 /*
1867     * Interrupts enabled, and any interrupt pending? (Note/TODO: This
1868     * code is duplicated in cpu_dyntrans.c. Fix this?)
1869     */
1870     if (rd == COP0_STATUS && !cpu->delay_slot) {
1871 dpavlin 24 uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1872     uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1873     /* NOTE: STATUS_IE happens to match the enable bit also
1874     on R2000/R3000, so this is ok. */
1875 dpavlin 30 if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1876     if (status & (STATUS_EXL | STATUS_ERL))
1877     status &= ~STATUS_IE;
1878     }
1879 dpavlin 26 /* Ugly R5900 special case: (TODO: move this?) */
1880     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1881     !(status & R5900_STATUS_EIE))
1882     status &= ~STATUS_IE;
1883     if (status & STATUS_IE && (status & cause & STATUS_IM_MASK)) {
1884     cpu->pc += sizeof(uint32_t);
1885     mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0,0,0,0,0);
1886     }
1887 dpavlin 24 }
1888 dpavlin 22 }
1889     X(dmfc0)
1890     {
1891     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1892     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1893     cpu->pc |= ic->arg[2];
1894     /* TODO: cause exception if necessary */
1895     coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,
1896     (uint64_t *)ic->arg[0], select);
1897     }
1898 dpavlin 32 X(dmfc0_select0)
1899     {
1900     /* Fast int64_t read, with no side effects: */
1901     int rd = ic->arg[1] & 31;
1902     #if 0
1903     uint64_t tmp;
1904     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1905     cpu->pc |= ic->arg[2];
1906     /* TODO: cause exception if necessary */
1907     #endif
1908     reg(ic->arg[0]) = cpu->cd.mips.coproc[0]->reg[rd];
1909     }
1910 dpavlin 22 X(dmtc0)
1911     {
1912     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1913     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1914     cpu->pc |= ic->arg[2];
1915     /* TODO: cause exception if necessary */
1916     coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,
1917     (uint64_t *)ic->arg[0], 1, select);
1918     }
1919 dpavlin 24
1920    
1921     /*
1922     * cop1_bc: Floating point conditional branch.
1923     *
1924     * arg[0] = cc
1925     * arg[1] = nd (=2) and tf (=1) bits
1926     * arg[2] = offset (relative to start of this page)
1927     */
1928     X(cop1_bc)
1929 dpavlin 22 {
1930 dpavlin 24 MODE_int_t old_pc = cpu->pc;
1931 dpavlin 32 int x, cc = ic->arg[0];
1932 dpavlin 24
1933 dpavlin 32 COPROC_AVAILABILITY_CHECK(1);
1934 dpavlin 24
1935     /* Get the correct condition code bit: */
1936     if (cc == 0)
1937     x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1938     >> MIPS_FCSR_FCC0_SHIFT) & 1;
1939     else
1940     x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1941     >> (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;
1942    
1943     /* Branch on false? Then invert the truth value. */
1944     if (!(ic->arg[1] & 1))
1945     x ^= 1;
1946    
1947     /* Execute the delay slot (except if it is nullified): */
1948     cpu->delay_slot = TO_BE_DELAYED;
1949     if (x || !(ic->arg[1] & 2))
1950     ic[1].f(cpu, ic+1);
1951     cpu->n_translated_instrs ++;
1952    
1953     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1954     /* Note: Must be non-delayed when jumping to the new pc: */
1955     cpu->delay_slot = NOT_DELAYED;
1956     if (x) {
1957     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1958     MIPS_INSTR_ALIGNMENT_SHIFT);
1959     cpu->pc = old_pc + (int32_t)ic->arg[2];
1960     quick_pc_to_pointers(cpu);
1961     } else
1962     cpu->cd.mips.next_ic ++;
1963     } else
1964     cpu->delay_slot = NOT_DELAYED;
1965     }
1966    
1967    
1968     /*
1969     * cop1_slow: Fallback to legacy cop1 code. (Slow, but it should work.)
1970     */
1971     X(cop1_slow)
1972     {
1973 dpavlin 32 COPROC_AVAILABILITY_CHECK(1);
1974 dpavlin 24
1975     coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1976     }
1977    
1978    
1979     /*
1980     * syscall, break: Synchronize the PC and cause an exception.
1981     */
1982     X(syscall)
1983     {
1984     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1985     / sizeof(struct mips_instr_call);
1986     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1987     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1988     mips_cpu_exception(cpu, EXCEPTION_SYS, 0, 0, 0, 0, 0, 0);
1989     }
1990     X(break)
1991     {
1992     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1993     / sizeof(struct mips_instr_call);
1994     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1995     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1996     mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1997     }
1998 dpavlin 30 X(reboot)
1999     {
2000 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2001     return;
2002    
2003 dpavlin 30 cpu->running = 0;
2004     debugger_n_steps_left_before_interaction = 0;
2005     cpu->cd.mips.next_ic = &nothing_call;
2006     }
2007 dpavlin 24
2008    
2009     /*
2010     * promemul: PROM software emulation.
2011     */
2012     X(promemul)
2013     {
2014     /* Synchronize the PC and call the correct emulation layer: */
2015     MODE_int_t old_pc;
2016     int res, low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2017     / sizeof(struct mips_instr_call);
2018     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
2019     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2020     old_pc = cpu->pc;
2021    
2022     switch (cpu->machine->machine_type) {
2023     case MACHINE_PMAX:
2024     res = decstation_prom_emul(cpu);
2025     break;
2026     case MACHINE_PS2:
2027     res = playstation2_sifbios_emul(cpu);
2028     break;
2029     case MACHINE_ARC:
2030     case MACHINE_SGI:
2031     res = arcbios_emul(cpu);
2032     break;
2033     case MACHINE_EVBMIPS:
2034     res = yamon_emul(cpu);
2035     break;
2036     default:fatal("TODO: Unimplemented machine type for PROM magic trap\n");
2037     exit(1);
2038     }
2039    
2040     if (res) {
2041     /* Return from the PROM call: */
2042     cpu->pc = (MODE_int_t)cpu->cd.mips.gpr[MIPS_GPR_RA];
2043     cpu->delay_slot = NOT_DELAYED;
2044    
2045     if (cpu->machine->show_trace_tree)
2046     cpu_functioncall_trace_return(cpu);
2047     } else {
2048     /* The PROM call blocks. */
2049     cpu->n_translated_instrs += 10;
2050     cpu->pc = old_pc;
2051     }
2052    
2053     quick_pc_to_pointers(cpu);
2054     }
2055    
2056    
2057     /*
2058     * tlbw: TLB write indexed and random
2059     *
2060     * arg[0] = 1 for random, 0 for indexed
2061     * arg[2] = relative addr of this instruction within the page
2062     */
2063     X(tlbw)
2064     {
2065 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2066     return;
2067    
2068 dpavlin 22 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2069     cpu->pc |= ic->arg[2];
2070 dpavlin 24 coproc_tlbwri(cpu, ic->arg[0]);
2071 dpavlin 22 }
2072    
2073    
2074 dpavlin 24 /*
2075     * tlbp: TLB probe
2076     * tlbr: TLB read
2077     *
2078     * arg[2] = relative addr of this instruction within the page
2079     */
2080     X(tlbp)
2081     {
2082 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2083     return;
2084    
2085 dpavlin 24 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2086     cpu->pc |= ic->arg[2];
2087     coproc_tlbpr(cpu, 0);
2088     }
2089     X(tlbr)
2090     {
2091 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2092     return;
2093    
2094 dpavlin 24 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2095     cpu->pc |= ic->arg[2];
2096     coproc_tlbpr(cpu, 1);
2097     }
2098    
2099    
2100     /*
2101 dpavlin 42 * ei_or_di: MIPS32/64 rev 2, Enable or disable interrupts
2102     *
2103     * arg[0] = ptr to rt
2104     * arg[1] = non-zero to enable interrupts
2105     */
2106     X(ei_or_di)
2107     {
2108     reg(ic->arg[0]) = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
2109     if (ic->arg[1])
2110     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= STATUS_IE;
2111     else
2112     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_IE;
2113     }
2114    
2115    
2116     /*
2117 dpavlin 24 * rfe: Return from exception handler (R2000/R3000)
2118     */
2119     X(rfe)
2120     {
2121 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2122     return;
2123    
2124 dpavlin 28 /* Just rotate the interrupt/user bits: */
2125     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
2126     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
2127     ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
2128 dpavlin 24
2129 dpavlin 28 /*
2130     * Note: no pc to pointers conversion is necessary here. Usually the
2131     * rfe instruction resides in the delay slot of a jr k0/k1, and
2132     * it is up to that instruction to do the pointer conversion.
2133     */
2134 dpavlin 24 }
2135    
2136    
2137     /*
2138 dpavlin 28 * eret: Return from exception handler (non-R3000 style)
2139 dpavlin 24 */
2140     X(eret)
2141     {
2142 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2143     return;
2144    
2145 dpavlin 28 if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
2146     cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
2147     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
2148     } else {
2149     cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
2150     cpu->delay_slot = 0;
2151     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
2152     }
2153    
2154 dpavlin 24 quick_pc_to_pointers(cpu);
2155 dpavlin 28
2156     cpu->cd.mips.rmw = 0; /* the "LL bit" */
2157 dpavlin 24 }
2158    
2159    
2160     /*
2161     * deret: Return from debug (EJTAG) handler
2162     */
2163     X(deret)
2164     {
2165 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2166     return;
2167    
2168 dpavlin 24 /*
2169     * According to the MIPS64 manual, deret loads PC from the DEPC cop0
2170     * register, and jumps there immediately. No delay slot.
2171     *
2172     * TODO: This instruction is only available if the processor is in
2173     * debug mode. (What does that mean?)
2174     *
2175     * TODO: This instruction is undefined in a delay slot.
2176     */
2177    
2178     cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_DEPC];
2179     cpu->delay_slot = 0;
2180     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
2181     quick_pc_to_pointers(cpu);
2182     }
2183    
2184    
2185     /*
2186 dpavlin 32 * idle: Called from the implementation of wait, or netbsd_pmax_idle.
2187 dpavlin 30 */
2188 dpavlin 32 X(idle)
2189 dpavlin 30 {
2190     /*
2191     * If there is an interrupt, then just return. Otherwise
2192     * re-run the wait instruction (after a delay).
2193     */
2194     uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
2195     uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
2196    
2197     if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2198     if (status & (STATUS_EXL | STATUS_ERL))
2199     status &= ~STATUS_IE;
2200     }
2201 dpavlin 32
2202 dpavlin 30 /* Ugly R5900 special case: (TODO: move this?) */
2203     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
2204     !(status & R5900_STATUS_EIE))
2205     status &= ~STATUS_IE;
2206     if (status & STATUS_IE && (status & cause & STATUS_IM_MASK))
2207     return;
2208    
2209     cpu->cd.mips.next_ic = ic;
2210     cpu->is_halted = 1;
2211 dpavlin 32 cpu->has_been_idling = 1;
2212 dpavlin 30
2213     /*
2214     * There was no interrupt. Go to sleep.
2215     *
2216     * TODO:
2217     *
2218     * Think about how to actually implement this usleep stuff,
2219     * in an SMP and/or timing accurate environment.
2220     */
2221    
2222     if (cpu->machine->ncpus == 1) {
2223     static int x = 0;
2224 dpavlin 44
2225     if ((++x) == 300) {
2226     usleep(20);
2227 dpavlin 30 x = 0;
2228     }
2229 dpavlin 44
2230 dpavlin 30 cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
2231     }
2232     }
2233    
2234    
2235     /*
2236 dpavlin 32 * wait: Wait for external interrupt.
2237     */
2238     X(wait)
2239     {
2240     if (!cop0_availability_check(cpu, ic))
2241     return;
2242    
2243     instr(idle)(cpu, ic);
2244     }
2245    
2246    
2247     /*
2248 dpavlin 24 * rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
2249     *
2250     * arg[0] = ptr to rt (destination register)
2251     */
2252     X(rdhwr_cpunum)
2253     {
2254     reg(ic->arg[0]) = cpu->cpu_id;
2255     }
2256    
2257    
2258     #include "tmp_mips_loadstore.c"
2259    
2260    
2261     /*
2262     * Load linked / store conditional:
2263     *
2264     * A Load-linked instruction initiates a RMW (read-modify-write) sequence.
2265     * COP0_LLADDR is updated for diagnostic purposes, except for CPUs in the
2266     * R10000 family.
2267     *
2268     * A Store-conditional instruction ends the sequence.
2269     *
2270     * arg[0] = ptr to rt
2271     * arg[1] = ptr to rs
2272     * arg[2] = int32_t imm
2273     */
2274     X(ll)
2275     {
2276     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2277     int low_pc;
2278     uint8_t word[sizeof(uint32_t)];
2279    
2280     /* Synch. PC and load using slow memory_rw(): */
2281     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2282     / sizeof(struct mips_instr_call);
2283     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2284     << MIPS_INSTR_ALIGNMENT_SHIFT);
2285     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2286    
2287     if (addr & (sizeof(word)-1)) {
2288     fatal("TODO: load linked unaligned access: exception\n");
2289     exit(1);
2290     }
2291    
2292     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2293     sizeof(word), MEM_READ, CACHE_DATA)) {
2294     /* An exception occurred. */
2295     return;
2296     }
2297    
2298     cpu->cd.mips.rmw = 1;
2299     cpu->cd.mips.rmw_addr = addr;
2300     cpu->cd.mips.rmw_len = sizeof(word);
2301     if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2302     cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2303     (addr >> 4) & 0xffffffffULL;
2304    
2305     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2306     reg(ic->arg[0]) = (int32_t) (word[0] + (word[1] << 8)
2307     + (word[2] << 16) + (word[3] << 24));
2308     else
2309     reg(ic->arg[0]) = (int32_t) (word[3] + (word[2] << 8)
2310     + (word[1] << 16) + (word[0] << 24));
2311     }
2312     X(lld)
2313     {
2314     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2315     int low_pc;
2316     uint8_t word[sizeof(uint64_t)];
2317    
2318     /* Synch. PC and load using slow memory_rw(): */
2319     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2320     / sizeof(struct mips_instr_call);
2321     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2322     << MIPS_INSTR_ALIGNMENT_SHIFT);
2323     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2324    
2325     if (addr & (sizeof(word)-1)) {
2326     fatal("TODO: load linked unaligned access: exception\n");
2327     exit(1);
2328     }
2329    
2330     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2331     sizeof(word), MEM_READ, CACHE_DATA)) {
2332     /* An exception occurred. */
2333     return;
2334     }
2335    
2336     cpu->cd.mips.rmw = 1;
2337     cpu->cd.mips.rmw_addr = addr;
2338     cpu->cd.mips.rmw_len = sizeof(word);
2339     if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2340     cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2341     (addr >> 4) & 0xffffffffULL;
2342    
2343     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2344     reg(ic->arg[0]) = word[0] + (word[1] << 8)
2345     + (word[2] << 16) + ((uint64_t)word[3] << 24) +
2346     + ((uint64_t)word[4] << 32) + ((uint64_t)word[5] << 40)
2347     + ((uint64_t)word[6] << 48) + ((uint64_t)word[7] << 56);
2348     else
2349     reg(ic->arg[0]) = word[7] + (word[6] << 8)
2350     + (word[5] << 16) + ((uint64_t)word[4] << 24) +
2351     + ((uint64_t)word[3] << 32) + ((uint64_t)word[2] << 40)
2352     + ((uint64_t)word[1] << 48) + ((uint64_t)word[0] << 56);
2353     }
2354     X(sc)
2355     {
2356 dpavlin 42 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2357 dpavlin 24 uint64_t r = reg(ic->arg[0]);
2358     int low_pc, i;
2359     uint8_t word[sizeof(uint32_t)];
2360    
2361     /* Synch. PC and store using slow memory_rw(): */
2362     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2363     / sizeof(struct mips_instr_call);
2364     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2365     << MIPS_INSTR_ALIGNMENT_SHIFT);
2366     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2367    
2368     if (addr & (sizeof(word)-1)) {
2369     fatal("TODO: sc unaligned access: exception\n");
2370     exit(1);
2371     }
2372    
2373     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2374     word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2375     } else {
2376     word[3]=r; word[2]=r>>8; word[1]=r>>16; word[0]=r>>24;
2377     }
2378    
2379     /* If rmw is 0, then the store failed. (This cache-line was written
2380     to by someone else.) */
2381 dpavlin 44 if (cpu->cd.mips.rmw == 0 || (MODE_int_t)cpu->cd.mips.rmw_addr != addr
2382 dpavlin 24 || cpu->cd.mips.rmw_len != sizeof(word)) {
2383     reg(ic->arg[0]) = 0;
2384     cpu->cd.mips.rmw = 0;
2385     return;
2386     }
2387    
2388     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2389     sizeof(word), MEM_WRITE, CACHE_DATA)) {
2390     /* An exception occurred. */
2391     return;
2392     }
2393    
2394     /* We succeeded. Let's invalidate everybody else's store to this
2395     cache line: */
2396     for (i=0; i<cpu->machine->ncpus; i++) {
2397     if (cpu->machine->cpus[i]->cd.mips.rmw) {
2398     uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2399     cd.mips.rmw_addr;
2400     uint64_t mask = ~(cpu->machine->cpus[i]->
2401     cd.mips.cache_linesize[CACHE_DATA] - 1);
2402     xaddr &= mask;
2403     yaddr &= mask;
2404     if (xaddr == yaddr)
2405     cpu->machine->cpus[i]->cd.mips.rmw = 0;
2406     }
2407     }
2408    
2409     reg(ic->arg[0]) = 1;
2410     cpu->cd.mips.rmw = 0;
2411     }
2412     X(scd)
2413     {
2414 dpavlin 42 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2415 dpavlin 24 uint64_t r = reg(ic->arg[0]);
2416     int low_pc, i;
2417     uint8_t word[sizeof(uint64_t)];
2418    
2419     /* Synch. PC and store using slow memory_rw(): */
2420     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2421     / sizeof(struct mips_instr_call);
2422     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2423     << MIPS_INSTR_ALIGNMENT_SHIFT);
2424     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2425    
2426     if (addr & (sizeof(word)-1)) {
2427     fatal("TODO: sc unaligned access: exception\n");
2428     exit(1);
2429     }
2430    
2431     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2432     word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2433     word[4]=r>>32; word[5]=r>>40; word[6]=r>>48; word[7]=r>>56;
2434     } else {
2435     word[7]=r; word[6]=r>>8; word[5]=r>>16; word[4]=r>>24;
2436     word[3]=r>>32; word[2]=r>>40; word[1]=r>>48; word[0]=r>>56;
2437     }
2438    
2439     /* If rmw is 0, then the store failed. (This cache-line was written
2440     to by someone else.) */
2441 dpavlin 44 if (cpu->cd.mips.rmw == 0 || (MODE_int_t)cpu->cd.mips.rmw_addr != addr
2442 dpavlin 24 || cpu->cd.mips.rmw_len != sizeof(word)) {
2443     reg(ic->arg[0]) = 0;
2444     cpu->cd.mips.rmw = 0;
2445     return;
2446     }
2447    
2448     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2449     sizeof(word), MEM_WRITE, CACHE_DATA)) {
2450     /* An exception occurred. */
2451     return;
2452     }
2453    
2454     /* We succeeded. Let's invalidate everybody else's store to this
2455     cache line: */
2456     for (i=0; i<cpu->machine->ncpus; i++) {
2457     if (cpu->machine->cpus[i]->cd.mips.rmw) {
2458     uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2459     cd.mips.rmw_addr;
2460     uint64_t mask = ~(cpu->machine->cpus[i]->
2461     cd.mips.cache_linesize[CACHE_DATA] - 1);
2462     xaddr &= mask;
2463     yaddr &= mask;
2464     if (xaddr == yaddr)
2465     cpu->machine->cpus[i]->cd.mips.rmw = 0;
2466     }
2467     }
2468    
2469     reg(ic->arg[0]) = 1;
2470     cpu->cd.mips.rmw = 0;
2471     }
2472    
2473    
2474     /*
2475     * lwc1, swc1: Coprocessor 1 load/store (32-bit)
2476     * ldc1, sdc1: Coprocessor 1 load/store (64-bit)
2477     *
2478     * arg[0] = ptr to coprocessor register
2479     * arg[1] = ptr to rs (base pointer register)
2480     * arg[2] = int32_t imm
2481     */
2482     X(lwc1)
2483     {
2484 dpavlin 32 COPROC_AVAILABILITY_CHECK(1);
2485 dpavlin 24
2486     #ifdef MODE32
2487     mips32_loadstore
2488     #else
2489     mips_loadstore
2490     #endif
2491     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 2 * 2 + 1]
2492     (cpu, ic);
2493     }
2494     X(swc1)
2495     {
2496 dpavlin 32 COPROC_AVAILABILITY_CHECK(1);
2497 dpavlin 24
2498     #ifdef MODE32
2499     mips32_loadstore
2500     #else
2501     mips_loadstore
2502     #endif
2503     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 2 * 2]
2504     (cpu, ic);
2505     }
2506     X(ldc1)
2507     {
2508     int use_fp_pairs =
2509     !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2510     uint64_t fpr, *backup_ptr;
2511    
2512 dpavlin 32 COPROC_AVAILABILITY_CHECK(1);
2513 dpavlin 24
2514     backup_ptr = (uint64_t *) ic->arg[0];
2515     ic->arg[0] = (size_t) &fpr;
2516    
2517     #ifdef MODE32
2518     mips32_loadstore
2519     #else
2520     mips_loadstore
2521     #endif
2522     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 3 * 2 + 1]
2523     (cpu, ic);
2524    
2525     if (use_fp_pairs) {
2526     backup_ptr[0] = (int64_t)(int32_t) fpr;
2527     backup_ptr[1] = (int64_t)(int32_t) (fpr >> 32);
2528     } else {
2529     *backup_ptr = fpr;
2530     }
2531    
2532     ic->arg[0] = (size_t) backup_ptr;
2533     }
2534     X(sdc1)
2535     {
2536     int use_fp_pairs =
2537     !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2538     uint64_t fpr, *backup_ptr;
2539    
2540 dpavlin 32 COPROC_AVAILABILITY_CHECK(1);
2541 dpavlin 24
2542     backup_ptr = (uint64_t *) ic->arg[0];
2543     ic->arg[0] = (size_t) &fpr;
2544    
2545     if (use_fp_pairs) {
2546     uint32_t lo = backup_ptr[0];
2547     uint32_t hi = backup_ptr[1];
2548     fpr = (((uint64_t)hi) << 32) | lo;
2549     } else {
2550     fpr = *backup_ptr;
2551     }
2552    
2553     #ifdef MODE32
2554     mips32_loadstore
2555     #else
2556     mips_loadstore
2557     #endif
2558     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 3 * 2]
2559     (cpu, ic);
2560    
2561     ic->arg[0] = (size_t) backup_ptr;
2562     }
2563    
2564    
2565     /*
2566     * Unaligned loads/stores:
2567     *
2568     * arg[0] = ptr to rt
2569     * arg[1] = ptr to rs
2570     * arg[2] = int32_t imm
2571     */
2572     X(lwl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 0); }
2573     X(lwr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 0); }
2574     X(ldl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 0); }
2575     X(ldr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 0); }
2576     X(swl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 1); }
2577     X(swr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 1); }
2578     X(sdl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 1); }
2579     X(sdr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 1); }
2580    
2581    
2582     /*
2583     * di, ei: R5900 interrupt enable/disable.
2584     *
2585     * TODO: check the R5900_STATUS_EDI bit in the status register. If it is
2586     * cleared, and we are not running in kernel mode, then both the EI and DI
2587     * instructions should be treated as NOPs!
2588     */
2589     X(di_r5900)
2590     {
2591 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2592     return;
2593    
2594 dpavlin 24 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2595     }
2596     X(ei_r5900)
2597     {
2598 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2599     return;
2600    
2601 dpavlin 24 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2602     }
2603    
2604    
2605 dpavlin 22 /*****************************************************************************/
2606    
2607    
2608     /*
2609 dpavlin 28 * sw_loop:
2610     *
2611     * s: addiu rX,rX,4 rX = arg[0] and arg[1]
2612     * bne rY,rX,s (or rX,rY,s) rt=arg[1], rs=arg[0]
2613     * sw rZ,-4(rX) rt=arg[0], rs=arg[1]
2614     */
2615     X(sw_loop)
2616     {
2617     MODE_uint_t rX = reg(ic->arg[0]), rZ = reg(ic[2].arg[0]);
2618     uint64_t *rYp = (uint64_t *) ic[1].arg[0];
2619     MODE_uint_t rY, bytes_to_write;
2620     unsigned char *page;
2621     int partial = 0;
2622    
2623     page = cpu->cd.mips.host_store[rX >> 12];
2624    
2625     /* Fallback: */
2626     if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2627     instr(addiu)(cpu, ic);
2628     return;
2629 dpavlin 30 }
2630 dpavlin 28
2631     if (rYp == (uint64_t *) ic->arg[0])
2632     rYp = (uint64_t *) ic[1].arg[1];
2633    
2634     rY = reg(rYp);
2635    
2636     bytes_to_write = rY - rX;
2637     if ((rX & 0xfff) + bytes_to_write > 0x1000) {
2638     bytes_to_write = 0x1000 - (rX & 0xfff);
2639     partial = 1;
2640     }
2641    
2642     /* printf("rX = %08x\n", (int)rX);
2643     printf("rY = %08x\n", (int)rY);
2644     printf("rZ = %08x\n", (int)rZ);
2645     printf("%i bytes\n", (int)bytes_to_write); */
2646    
2647     memset(page + (rX & 0xfff), 0, bytes_to_write);
2648    
2649     reg(ic->arg[0]) = rX + bytes_to_write;
2650    
2651     cpu->n_translated_instrs += bytes_to_write / 4 * 3 - 1;
2652     cpu->cd.mips.next_ic = partial?
2653     (struct mips_instr_call *) &ic[0] :
2654     (struct mips_instr_call *) &ic[3];
2655     }
2656    
2657    
2658 dpavlin 30 #ifdef MODE32
2659 dpavlin 34 /* multi_{l,s}w_2, _3, etc. */
2660     #include "tmp_mips_loadstore_multi.c"
2661 dpavlin 30 #endif
2662    
2663    
2664 dpavlin 28 /*
2665 dpavlin 30 * multi_addu_3:
2666     */
2667     X(multi_addu_3)
2668     {
2669     /* Fallback: */
2670     if (cpu->delay_slot) {
2671     instr(addu)(cpu, ic);
2672     return;
2673     }
2674    
2675     reg(ic[0].arg[2]) = (int32_t)(reg(ic[0].arg[0]) + reg(ic[0].arg[1]));
2676     reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0]) + reg(ic[1].arg[1]));
2677     reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0]) + reg(ic[2].arg[1]));
2678     cpu->n_translated_instrs += 2;
2679 dpavlin 44 cpu->cd.mips.next_ic = ic + 3;
2680 dpavlin 30 }
2681    
2682    
2683     /*
2684 dpavlin 28 * netbsd_r3k_picache_do_inv:
2685     *
2686     * ic[0] mtc0 rV,status
2687     * 1 nop
2688     * 2 nop
2689     * 3 s: addiu rX,rX,4
2690     * 4 bne rY,rX,s
2691     * 5 sb zr,-4(rX)
2692     * 6 nop
2693     * 7 nop
2694     * 8 mtc0 rT,status
2695     */
2696     X(netbsd_r3k_picache_do_inv)
2697     {
2698     MODE_uint_t rx = reg(ic[3].arg[0]), ry = reg(ic[4].arg[1]);
2699    
2700     /* Fallback if the environment isn't exactly right: */
2701     if (!(reg(ic[0].arg[0]) & MIPS1_ISOL_CACHES) ||
2702     (rx & 3) || (ry & 3) || cpu->delay_slot) {
2703     instr(mtc0)(cpu, ic);
2704     return;
2705     }
2706    
2707     reg(ic[3].arg[0]) = ry;
2708     cpu->n_translated_instrs += (ry - rx + 4) / 4 * 3 + 4;
2709    
2710     /* Run the last mtc0 instruction: */
2711 dpavlin 44 cpu->cd.mips.next_ic = ic + 8;
2712 dpavlin 28 }
2713    
2714    
2715     #ifdef MODE32
2716     /*
2717 dpavlin 32 * netbsd_pmax_idle():
2718     *
2719     * s: lui rX, hi
2720     * lw rY, lo(rX)
2721     * nop
2722     * beq zr, rY, s
2723     * nop
2724     */
2725     X(netbsd_pmax_idle)
2726     {
2727     uint32_t addr, pageindex, i;
2728     int32_t *page;
2729    
2730     reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2731    
2732     addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2];
2733     pageindex = addr >> 12;
2734     i = (addr & 0xfff) >> 2;
2735     page = (int32_t *) cpu->cd.mips.host_load[pageindex];
2736    
2737     /* Fallback: */
2738     if (cpu->delay_slot || page == NULL || page[i] != 0)
2739     return;
2740    
2741     instr(idle)(cpu, ic);
2742     }
2743    
2744    
2745     /*
2746     * linux_pmax_idle():
2747     *
2748     * s: lui rX, hi
2749     * lw rX, lo(rX)
2750     * nop
2751     * bne zr, rX, ...
2752     * nop
2753     * lw rX, ofs(gp)
2754     * nop
2755     * beq zr, rX, s
2756     * nop
2757     */
2758     X(linux_pmax_idle)
2759     {
2760     uint32_t addr, addr2, pageindex, pageindex2, i, i2;
2761     int32_t *page, *page2;
2762    
2763     reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2764    
2765     addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2];
2766     pageindex = addr >> 12;
2767     i = (addr & 0xfff) >> 2;
2768     page = (int32_t *) cpu->cd.mips.host_load[pageindex];
2769    
2770     addr2 = reg(ic[5].arg[1]) + (int32_t)ic[5].arg[2];
2771     pageindex2 = addr2 >> 12;
2772     i2 = (addr2 & 0xfff) >> 2;
2773     page2 = (int32_t *) cpu->cd.mips.host_load[pageindex2];
2774    
2775     /* Fallback: */
2776     if (cpu->delay_slot || page == NULL || page[i] != 0 || page2[i2] != 0)
2777     return;
2778    
2779     instr(idle)(cpu, ic);
2780     }
2781    
2782    
2783     /*
2784 dpavlin 28 * netbsd_strlen():
2785     *
2786     * lb rV,0(rX)
2787     * s: addiu rX,rX,1
2788     * bne zr,rV,s
2789     * nop
2790     */
2791     X(netbsd_strlen)
2792     {
2793     MODE_uint_t rx = reg(ic[0].arg[1]);
2794     MODE_int_t rv;
2795     signed char *page;
2796     uint32_t pageindex = rx >> 12;
2797     int i;
2798    
2799     page = (signed char *) cpu->cd.mips.host_load[pageindex];
2800    
2801     /* Fallback: */
2802     if (cpu->delay_slot || page == NULL) {
2803     /*
2804     * Normal lb: NOTE: It doesn't matter whether [1] or
2805     * [16+1] is called here, because endianness for 8-bit
2806     * loads is irrelevant. :-)
2807     */
2808     mips32_loadstore[1](cpu, ic);
2809     return;
2810     }
2811    
2812     i = rx & 0xfff;
2813    
2814     /*
2815     * TODO: This loop can be optimized further for optimal
2816     * performance on the host, e.g. by reading full words...
2817     */
2818     do {
2819     rv = page[i ++];
2820     } while (i < 0x1000 && rv != 0);
2821    
2822     cpu->n_translated_instrs += (i - (rx & 0xfff)) * 4 - 1;
2823    
2824     reg(ic[0].arg[1]) = (rx & ~0xfff) + i;
2825     reg(ic[2].arg[0]) = rv;
2826    
2827     /* Done with the loop? Or continue on the next rx page? */
2828     if (rv == 0)
2829 dpavlin 44 cpu->cd.mips.next_ic = ic + 4;
2830 dpavlin 28 else
2831 dpavlin 44 cpu->cd.mips.next_ic = ic;
2832 dpavlin 28 }
2833     #endif
2834    
2835    
2836     /*
2837 dpavlin 30 * addiu_bne_samepage_addiu:
2838 dpavlin 28 */
2839 dpavlin 30 X(addiu_bne_samepage_addiu)
2840 dpavlin 28 {
2841 dpavlin 30 MODE_uint_t rs, rt;
2842    
2843     if (cpu->delay_slot) {
2844     instr(addiu)(cpu, ic);
2845     return;
2846     }
2847    
2848     cpu->n_translated_instrs += 2;
2849     reg(ic[0].arg[1]) = (int32_t)
2850     ((int32_t)reg(ic[0].arg[0]) + (int32_t)ic[0].arg[2]);
2851     rs = reg(ic[1].arg[0]);
2852     rt = reg(ic[1].arg[1]);
2853     reg(ic[2].arg[1]) = (int32_t)
2854     ((int32_t)reg(ic[2].arg[0]) + (int32_t)ic[2].arg[2]);
2855     if (rs != rt)
2856     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic[1].arg[2];
2857     else
2858 dpavlin 44 cpu->cd.mips.next_ic = ic + 3;
2859 dpavlin 30 }
2860    
2861    
2862     /*
2863     * xor_andi_sll:
2864     */
2865     X(xor_andi_sll)
2866     {
2867     /* Fallback: */
2868     if (cpu->delay_slot) {
2869     instr(xor)(cpu, ic);
2870     return;
2871     }
2872    
2873     reg(ic[0].arg[2]) = reg(ic[0].arg[0]) ^ reg(ic[0].arg[1]);
2874     reg(ic[1].arg[1]) = reg(ic[1].arg[0]) & (uint32_t)ic[1].arg[2];
2875     reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0])<<(int32_t)ic[2].arg[1]);
2876    
2877     cpu->n_translated_instrs += 2;
2878 dpavlin 44 cpu->cd.mips.next_ic = ic + 3;
2879 dpavlin 30 }
2880    
2881    
2882     /*
2883     * andi_sll:
2884     */
2885     X(andi_sll)
2886     {
2887     /* Fallback: */
2888     if (cpu->delay_slot) {
2889     instr(andi)(cpu, ic);
2890     return;
2891     }
2892    
2893     reg(ic[0].arg[1]) = reg(ic[0].arg[0]) & (uint32_t)ic[0].arg[2];
2894     reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0])<<(int32_t)ic[1].arg[1]);
2895    
2896 dpavlin 28 cpu->n_translated_instrs ++;
2897 dpavlin 44 cpu->cd.mips.next_ic = ic + 2;
2898 dpavlin 28 }
2899    
2900    
2901     /*
2902 dpavlin 30 * lui_ori:
2903     */
2904     X(lui_ori)
2905     {
2906     /* Fallback: */
2907     if (cpu->delay_slot) {
2908     instr(set)(cpu, ic);
2909     return;
2910     }
2911    
2912     reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2913     reg(ic[1].arg[1]) = reg(ic[1].arg[0]) | (uint32_t)ic[1].arg[2];
2914    
2915     cpu->n_translated_instrs ++;
2916 dpavlin 44 cpu->cd.mips.next_ic = ic + 2;
2917 dpavlin 30 }
2918    
2919    
2920     /*
2921     * lui_addiu:
2922     */
2923     X(lui_addiu)
2924     {
2925     /* Fallback: */
2926     if (cpu->delay_slot) {
2927     instr(set)(cpu, ic);
2928     return;
2929     }
2930    
2931     reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2932     reg(ic[1].arg[1]) = (int32_t)
2933     ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
2934    
2935     cpu->n_translated_instrs ++;
2936 dpavlin 44 cpu->cd.mips.next_ic = ic + 2;
2937 dpavlin 30 }
2938    
2939    
2940     /*
2941 dpavlin 22 * b_samepage_addiu:
2942     *
2943     * Combination of branch within the same page, followed by addiu.
2944     */
2945     X(b_samepage_addiu)
2946     {
2947 dpavlin 24 reg(ic[1].arg[1]) = (int32_t)
2948     ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
2949 dpavlin 22 cpu->n_translated_instrs ++;
2950     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2951     }
2952    
2953    
2954 dpavlin 24 /*
2955     * b_samepage_daddiu:
2956     *
2957     * Combination of branch within the same page, followed by daddiu.
2958     */
2959     X(b_samepage_daddiu)
2960     {
2961     *(uint64_t *)ic[1].arg[1] = *(uint64_t *)ic[1].arg[0] +
2962     (int32_t)ic[1].arg[2];
2963     cpu->n_translated_instrs ++;
2964     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2965     }
2966    
2967    
2968 dpavlin 22 /*****************************************************************************/
2969    
2970    
2971     X(end_of_page)
2972     {
2973     /* Update the PC: (offset 0, but on the next page) */
2974     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
2975     MIPS_INSTR_ALIGNMENT_SHIFT);
2976     cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);
2977    
2978 dpavlin 24 /* end_of_page doesn't count as an executed instruction: */
2979     cpu->n_translated_instrs --;
2980 dpavlin 22
2981 dpavlin 24 /*
2982     * Find the new physpage and update translation pointers.
2983     *
2984     * Note: This may cause an exception, if e.g. the new page is
2985     * not accessible.
2986     */
2987     quick_pc_to_pointers(cpu);
2988 dpavlin 22
2989 dpavlin 24 /* Simple jump to the next page (if we are lucky): */
2990     if (cpu->delay_slot == NOT_DELAYED)
2991     return;
2992 dpavlin 22
2993 dpavlin 24 /*
2994     * If we were in a delay slot, and we got an exception while doing
2995     * quick_pc_to_pointers, then return. The function which called
2996     * end_of_page should handle this case.
2997     */
2998     if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
2999 dpavlin 22 return;
3000    
3001 dpavlin 24 /*
3002     * Tricky situation; the delay slot is on the next virtual page.
3003     * Calling to_be_translated will translate one instruction manually,
3004     * execute it, and then discard it.
3005     */
3006 dpavlin 22 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
3007    
3008 dpavlin 24 instr(to_be_translated)(cpu, cpu->cd.mips.next_ic);
3009 dpavlin 22
3010     /* The instruction in the delay slot has now executed. */
3011 dpavlin 24 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
3012     cpu->delay_slot); */
3013 dpavlin 22
3014     /* Find the physpage etc of the instruction in the delay slot
3015     (or, if there was an exception, the exception handler): */
3016     quick_pc_to_pointers(cpu);
3017     }
3018    
3019    
3020     X(end_of_page2)
3021     {
3022 dpavlin 24 /* Synchronize PC on the _second_ instruction on the next page: */
3023     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
3024     / sizeof(struct mips_instr_call);
3025     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
3026     << MIPS_INSTR_ALIGNMENT_SHIFT);
3027     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
3028 dpavlin 22
3029 dpavlin 24 /* This doesn't count as an executed instruction. */
3030     cpu->n_translated_instrs --;
3031 dpavlin 22
3032 dpavlin 24 quick_pc_to_pointers(cpu);
3033 dpavlin 22
3034 dpavlin 24 if (cpu->delay_slot == NOT_DELAYED)
3035 dpavlin 22 return;
3036    
3037 dpavlin 24 fatal("end_of_page2: fatal error, we're in a delay slot\n");
3038 dpavlin 22 exit(1);
3039     }
3040    
3041    
3042     /*****************************************************************************/
3043    
3044    
3045     /*
3046 dpavlin 28 * Combine: Memory fill loop (addiu, bne, sw)
3047     *
3048     * s: addiu rX,rX,4
3049     * bne rY,rX,s
3050     * sw rZ,-4(rX)
3051 dpavlin 22 */
3052 dpavlin 28 void COMBINE(sw_loop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3053     {
3054     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3055     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3056    
3057     /* Only for 32-bit virtual address translation so far. */
3058     if (!cpu->is_32bit)
3059     return;
3060    
3061     if (n_back < 2)
3062     return;
3063    
3064     if (ic[-2].f == instr(addiu) && ic[-2].arg[0] == ic[-2].arg[1] &&
3065     (int32_t)ic[-2].arg[2] == 4 &&
3066     ic[-1].f == instr(bne_samepage) &&
3067     (ic[-1].arg[0] == ic[-2].arg[0] ||
3068     ic[-1].arg[1] == ic[-2].arg[0]) &&
3069     ic[-1].arg[0] != ic[-1].arg[1] &&
3070     ic[-1].arg[2] == (size_t) &ic[-2] &&
3071     ic[0].arg[0] != ic[0].arg[1] &&
3072     ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {
3073     ic[-2].f = instr(sw_loop);
3074     }
3075     }
3076    
3077    
3078 dpavlin 30 /* Only for 32-bit virtual address translation so far. */
3079     #ifdef MODE32
3080 dpavlin 28 /*
3081     * Combine: Multiple SW in a row using the same base register
3082     *
3083     * sw r?,???(rX)
3084     * sw r?,???(rX)
3085     * sw r?,???(rX)
3086     * ...
3087     */
3088     void COMBINE(multi_sw)(struct cpu *cpu, struct mips_instr_call *ic,
3089 dpavlin 22 int low_addr)
3090     {
3091     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3092     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3093    
3094 dpavlin 30 if (n_back < 3)
3095 dpavlin 28 return;
3096    
3097 dpavlin 30 /* Convert a multi_sw_3 to a multi_sw_4: */
3098     if ((ic[-3].f == instr(multi_sw_3_be) ||
3099     ic[-3].f == instr(multi_sw_3_le)) &&
3100     ic[-3].arg[1] == ic[0].arg[1]) {
3101     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3102     ic[-3].f = instr(multi_sw_4_le);
3103     else
3104     ic[-3].f = instr(multi_sw_4_be);
3105     }
3106 dpavlin 28
3107 dpavlin 30 /* Convert a multi_sw_2 to a multi_sw_3: */
3108     if ((ic[-2].f == instr(multi_sw_2_be) ||
3109     ic[-2].f == instr(multi_sw_2_le)) &&
3110     ic[-2].arg[1] == ic[0].arg[1]) {
3111     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3112     ic[-2].f = instr(multi_sw_3_le);
3113     else
3114     ic[-2].f = instr(multi_sw_3_be);
3115     }
3116    
3117     if (ic[-1].f == ic[0].f && ic[-1].arg[1] == ic[0].arg[1]) {
3118     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3119     ic[-1].f = instr(multi_sw_2_le);
3120     else
3121     ic[-1].f = instr(multi_sw_2_be);
3122     }
3123     }
3124     #endif
3125    
3126    
3127     /* Only for 32-bit virtual address translation so far. */
3128     #ifdef MODE32
3129     /*
3130     * Combine: Multiple LW in a row using the same base register
3131     *
3132     * lw r?,???(rX)
3133     * lw r?,???(rX)
3134     * lw r?,???(rX)
3135     * ...
3136     */
3137     void COMBINE(multi_lw)(struct cpu *cpu, struct mips_instr_call *ic,
3138     int low_addr)
3139     {
3140     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3141     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3142    
3143     if (n_back < 3)
3144 dpavlin 28 return;
3145    
3146 dpavlin 30 /* Convert a multi_lw_3 to a multi_lw_4: */
3147     if ((ic[-3].f == instr(multi_lw_3_be) ||
3148     ic[-3].f == instr(multi_lw_3_le)) &&
3149     ic[-3].arg[1] == ic[0].arg[1] &&
3150     ic[-1].arg[0] != ic[0].arg[1]) {
3151     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3152     ic[-3].f = instr(multi_lw_4_le);
3153     else
3154     ic[-3].f = instr(multi_lw_4_be);
3155     }
3156    
3157     /* Convert a multi_lw_2 to a multi_lw_3: */
3158     if ((ic[-2].f == instr(multi_lw_2_be) ||
3159     ic[-2].f == instr(multi_lw_2_le)) &&
3160 dpavlin 28 ic[-2].arg[1] == ic[0].arg[1] &&
3161 dpavlin 30 ic[-1].arg[0] != ic[0].arg[1]) {
3162 dpavlin 28 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3163 dpavlin 30 ic[-2].f = instr(multi_lw_3_le);
3164 dpavlin 28 else
3165 dpavlin 30 ic[-2].f = instr(multi_lw_3_be);
3166 dpavlin 28 }
3167 dpavlin 30
3168     /* Note: Loads to the base register are not allowed in slot -1. */
3169     if (ic[-1].f == ic[0].f &&
3170     ic[-1].arg[1] == ic[0].arg[1] &&
3171     ic[-1].arg[0] != ic[0].arg[1]) {
3172     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3173     ic[-1].f = instr(multi_lw_2_le);
3174     else
3175     ic[-1].f = instr(multi_lw_2_be);
3176     }
3177 dpavlin 28 }
3178 dpavlin 30 #endif
3179 dpavlin 28
3180    
3181     /*
3182     * Combine: NetBSD/pmax 3.0 R2000/R3000 physical cache invalidation loop
3183     *
3184     * Instruction cache loop:
3185     *
3186     * ic[-8] mtc0 rV,status
3187     * -7 nop
3188     * -6 nop
3189     * -5 s: addiu rX,rX,4
3190     * -4 bne rY,rX,s
3191     * -3 sb zr,-4(rX)
3192     * -2 nop
3193     * -1 nop
3194     * 0 mtc0 rT,status
3195     */
3196     void COMBINE(netbsd_r3k_cache_inv)(struct cpu *cpu,
3197     struct mips_instr_call *ic, int low_addr)
3198     {
3199     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3200     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3201    
3202     if (n_back < 8)
3203     return;
3204    
3205     if (ic[-8].f == instr(mtc0) && ic[-8].arg[1] == COP0_STATUS &&
3206     ic[-7].f == instr(nop) && ic[-6].f == instr(nop) &&
3207     ic[-5].f == instr(addiu) && ic[-5].arg[0] == ic[-5].arg[1] &&
3208     (int32_t)ic[-5].arg[2] == 4 && ic[-4].f == instr(bne_samepage) &&
3209     ic[-4].arg[0] == ic[-5].arg[0] && ic[-4].arg[0] != ic[-4].arg[1] &&
3210     ic[-4].arg[2] == (size_t) &ic[-5] &&
3211     ic[-3].arg[1] == ic[-5].arg[0] &&
3212     ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
3213     ic[-8].f = instr(netbsd_r3k_picache_do_inv);
3214     }
3215     }
3216    
3217    
3218     /*
3219     * Combine: something ending with a nop.
3220     *
3221     * NetBSD's strlen core.
3222     * [Conditional] branch, followed by nop.
3223 dpavlin 32 * NetBSD/pmax' idle loop (and possibly others as well).
3224     * Linux/pmax' idle loop.
3225 dpavlin 28 */
3226     void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3227     {
3228     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3229     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3230    
3231 dpavlin 32 if (n_back < 8)
3232     return;
3233    
3234 dpavlin 28 #ifdef MODE32
3235 dpavlin 32 if (ic[-8].f == instr(set) &&
3236     ic[-7].f == mips32_loadstore[4 + 1] &&
3237     ic[-7].arg[0] == ic[-1].arg[0] &&
3238     ic[-7].arg[0] == ic[-3].arg[0] &&
3239     ic[-7].arg[0] == ic[-5].arg[0] &&
3240     ic[-7].arg[0] == ic[-7].arg[1] &&
3241     ic[-7].arg[0] == ic[-8].arg[0] &&
3242     ic[-6].f == instr(nop) &&
3243     ic[-5].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3244     ic[-5].f == instr(bne_samepage_nop) &&
3245     ic[-4].f == instr(nop) &&
3246     ic[-3].f == mips32_loadstore[4 + 1] &&
3247     ic[-2].f == instr(nop) &&
3248     ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3249     ic[-1].arg[2] == (size_t) &ic[-8] &&
3250     ic[-1].f == instr(beq_samepage)) {
3251     ic[-8].f = instr(linux_pmax_idle);
3252 dpavlin 28 return;
3253 dpavlin 32 }
3254 dpavlin 28
3255 dpavlin 32 if (ic[-4].f == instr(set) &&
3256     ic[-3].f == mips32_loadstore[4 + 1] &&
3257     ic[-3].arg[0] == ic[-1].arg[0] &&
3258     ic[-3].arg[1] == ic[-4].arg[0] &&
3259     ic[-2].f == instr(nop) &&
3260     ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3261     ic[-1].arg[2] == (size_t) &ic[-4] &&
3262     ic[-1].f == instr(beq_samepage)) {
3263     ic[-4].f = instr(netbsd_pmax_idle);
3264     return;
3265     }
3266    
3267 dpavlin 28 if ((ic[-3].f == mips32_loadstore[1] ||
3268     ic[-3].f == mips32_loadstore[16 + 1]) &&
3269     ic[-3].arg[2] == 0 &&
3270     ic[-3].arg[0] == ic[-1].arg[0] && ic[-3].arg[1] == ic[-2].arg[0] &&
3271     ic[-2].arg[0] == ic[-2].arg[1] && ic[-2].arg[2] == 1 &&
3272     ic[-2].f == instr(addiu) && ic[-1].arg[2] == (size_t) &ic[-3] &&
3273     ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3274     ic[-1].f == instr(bne_samepage)) {
3275     ic[-3].f = instr(netbsd_strlen);
3276     return;
3277     }
3278     #endif
3279    
3280     if (ic[-1].f == instr(bne_samepage)) {
3281     ic[-1].f = instr(bne_samepage_nop);
3282     return;
3283     }
3284    
3285     if (ic[-1].f == instr(beq_samepage)) {
3286     ic[-1].f = instr(beq_samepage_nop);
3287     return;
3288     }
3289    
3290     /* TODO: other branches that are followed by nop should be here */
3291     }
3292    
3293    
3294     /*
3295     * Combine:
3296     *
3297 dpavlin 30 * xor + andi + sll
3298     * andi + sll
3299     */
3300     void COMBINE(sll)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3301     {
3302     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3303     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3304    
3305     if (n_back < 2)
3306     return;
3307    
3308     if (ic[-2].f == instr(xor) && ic[-1].f == instr(andi)) {
3309     ic[-2].f = instr(xor_andi_sll);
3310     return;
3311     }
3312    
3313     if (ic[-1].f == instr(andi)) {
3314     ic[-1].f = instr(andi_sll);
3315     return;
3316     }
3317     }
3318    
3319    
3320     /*
3321     * lui + ori
3322     */
3323     void COMBINE(ori)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3324     {
3325     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3326     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3327    
3328     if (n_back < 1)
3329     return;
3330    
3331     if (ic[-1].f == instr(set)) {
3332     ic[-1].f = instr(lui_ori);
3333     return;
3334     }
3335     }
3336    
3337    
3338     /*
3339     * addu + addu + addu
3340     */
3341     void COMBINE(addu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3342     {
3343     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3344     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3345    
3346     if (n_back < 4)
3347     return;
3348    
3349     /* Avoid "overlapping" instruction combinations: */
3350     if (ic[-4].f == instr(multi_addu_3) ||
3351     ic[-3].f == instr(multi_addu_3))
3352     return;
3353    
3354     if (ic[-2].f == instr(addu) && ic[-1].f == instr(addu)) {
3355     ic[-2].f = instr(multi_addu_3);
3356     return;
3357     }
3358     }
3359    
3360    
3361     /*
3362     * Combine:
3363     *
3364 dpavlin 28 * [Conditional] branch, followed by addiu.
3365     */
3366     void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3367     {
3368     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3369     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3370    
3371 dpavlin 30 if (n_back < 2)
3372 dpavlin 28 return;
3373    
3374 dpavlin 30 if (ic[-2].f == instr(addiu) &&
3375     ic[-1].f == instr(bne_samepage)) {
3376     ic[-2].f = instr(addiu_bne_samepage_addiu);
3377 dpavlin 28 return;
3378     }
3379    
3380 dpavlin 30 if (ic[-1].f == instr(set)) {
3381     ic[-1].f = instr(lui_addiu);
3382     return;
3383     }
3384    
3385 dpavlin 22 if (ic[-1].f == instr(b_samepage)) {
3386     ic[-1].f = instr(b_samepage_addiu);
3387 dpavlin 28 return;
3388 dpavlin 22 }
3389    
3390 dpavlin 28 if (ic[-1].f == instr(beq_samepage)) {
3391     ic[-1].f = instr(beq_samepage_addiu);
3392     return;
3393     }
3394    
3395     if (ic[-1].f == instr(bne_samepage)) {
3396     ic[-1].f = instr(bne_samepage_addiu);
3397     return;
3398     }
3399    
3400     if (ic[-1].f == instr(jr_ra)) {
3401     ic[-1].f = instr(jr_ra_addiu);
3402     return;
3403     }
3404    
3405 dpavlin 22 /* TODO: other branches that are followed by addiu should be here */
3406     }
3407    
3408    
3409 dpavlin 24 /*
3410     * Combine: [Conditional] branch, followed by daddiu.
3411     */
3412     void COMBINE(b_daddiu)(struct cpu *cpu, struct mips_instr_call *ic,
3413     int low_addr)
3414     {
3415     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3416     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3417    
3418     if (n_back < 1)
3419     return;
3420    
3421     if (ic[-1].f == instr(b_samepage)) {
3422     ic[-1].f = instr(b_samepage_daddiu);
3423     }
3424    
3425     /* TODO: other branches that are followed by daddiu should be here */
3426     }
3427    
3428    
3429 dpavlin 22 /*****************************************************************************/
3430    
3431    
3432     /*
3433     * mips_instr_to_be_translated():
3434     *
3435 dpavlin 24 * Translate an instruction word into a mips_instr_call. ic is filled in with
3436 dpavlin 22 * valid data for the translated instruction, or a "nothing" instruction if
3437     * there was a translation failure. The newly translated instruction is then
3438     * executed.
3439     */
3440     X(to_be_translated)
3441     {
3442     uint64_t addr, low_pc;
3443     uint32_t iword, imm;
3444     unsigned char *page;
3445     unsigned char ib[4];
3446 dpavlin 32 int main_opcode, rt, rs, rd, sa, s6, x64 = 0, s10;
3447 dpavlin 22 int in_crosspage_delayslot = 0;
3448     void (*samepage_function)(struct cpu *, struct mips_instr_call *);
3449 dpavlin 24 int store, signedness, size;
3450 dpavlin 22
3451     /* Figure out the (virtual) address of the instruction: */
3452     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
3453     / sizeof(struct mips_instr_call);
3454    
3455     /* Special case for branch with delayslot on the next page: */
3456 dpavlin 24 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
3457     /* fatal("[ delay-slot translation across page "
3458     "boundary ]\n"); */
3459 dpavlin 22 in_crosspage_delayslot = 1;
3460     }
3461    
3462     addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)
3463     << MIPS_INSTR_ALIGNMENT_SHIFT);
3464     addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
3465 dpavlin 24 cpu->pc = (MODE_int_t)addr;
3466 dpavlin 22 addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
3467    
3468     /* Read the instruction word from memory: */
3469 dpavlin 24 #ifdef MODE32
3470 dpavlin 22 page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
3471 dpavlin 24 #else
3472     {
3473     const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
3474     const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
3475     const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
3476     uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
3477     uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
3478     uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
3479     DYNTRANS_L3N)) & mask3;
3480     struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.mips.l1_64[x1];
3481     struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
3482     page = l3->host_load[x3];
3483     }
3484     #endif
3485 dpavlin 22
3486     if (page != NULL) {
3487     /* fatal("TRANSLATION HIT!\n"); */
3488 dpavlin 24 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
3489 dpavlin 22 } else {
3490     /* fatal("TRANSLATION MISS!\n"); */
3491     if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
3492     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
3493 dpavlin 24 fatal("to_be_translated(): read failed: TODO\n");
3494 dpavlin 22 goto bad;
3495     }
3496     }
3497    
3498     iword = *((uint32_t *)&ib[0]);
3499    
3500     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3501     iword = LE32_TO_HOST(iword);
3502     else
3503     iword = BE32_TO_HOST(iword);
3504    
3505    
3506     #define DYNTRANS_TO_BE_TRANSLATED_HEAD
3507     #include "cpu_dyntrans.c"
3508     #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
3509    
3510    
3511     /*
3512     * Translate the instruction:
3513     *
3514 dpavlin 24 * NOTE: _NEVER_ allow writes to the zero register; all instructions
3515     * that use the zero register as their destination should be treated
3516     * as NOPs, except those that access memory (they should use the
3517     * scratch register instead).
3518 dpavlin 22 */
3519    
3520     main_opcode = iword >> 26;
3521     rs = (iword >> 21) & 31;
3522     rt = (iword >> 16) & 31;
3523     rd = (iword >> 11) & 31;
3524     sa = (iword >> 6) & 31;
3525     imm = (int16_t)iword;
3526     s6 = iword & 63;
3527 dpavlin 32 s10 = (rs << 5) | sa;
3528 dpavlin 22
3529     switch (main_opcode) {
3530    
3531     case HI6_SPECIAL:
3532     switch (s6) {
3533    
3534     case SPECIAL_SLL:
3535 dpavlin 24 case SPECIAL_SLLV:
3536 dpavlin 22 case SPECIAL_SRL:
3537 dpavlin 24 case SPECIAL_SRLV:
3538 dpavlin 22 case SPECIAL_SRA:
3539 dpavlin 24 case SPECIAL_SRAV:
3540     case SPECIAL_DSRL:
3541     case SPECIAL_DSRLV:
3542     case SPECIAL_DSRL32:
3543     case SPECIAL_DSLL:
3544     case SPECIAL_DSLLV:
3545     case SPECIAL_DSLL32:
3546     case SPECIAL_DSRA:
3547     case SPECIAL_DSRAV:
3548     case SPECIAL_DSRA32:
3549 dpavlin 22 switch (s6) {
3550     case SPECIAL_SLL: ic->f = instr(sll); break;
3551 dpavlin 24 case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
3552 dpavlin 22 case SPECIAL_SRL: ic->f = instr(srl); break;
3553 dpavlin 24 case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
3554 dpavlin 22 case SPECIAL_SRA: ic->f = instr(sra); break;
3555 dpavlin 24 case SPECIAL_SRAV: ic->f = instr(srav); sa = -1; break;
3556     case SPECIAL_DSRL: ic->f = instr(dsrl); x64=1; break;
3557     case SPECIAL_DSRLV:ic->f = instr(dsrlv);
3558     x64 = 1; sa = -1; break;
3559     case SPECIAL_DSRL32:ic->f= instr(dsrl); x64=1;
3560     sa += 32; break;
3561     case SPECIAL_DSLL: ic->f = instr(dsll); x64=1; break;
3562     case SPECIAL_DSLLV:ic->f = instr(dsllv);
3563     x64 = 1; sa = -1; break;
3564     case SPECIAL_DSLL32:ic->f= instr(dsll); x64=1;
3565     sa += 32; break;
3566     case SPECIAL_DSRA: ic->f = instr(dsra); x64=1; break;
3567     case SPECIAL_DSRAV:ic->f = instr(dsrav);
3568     x64 = 1; sa = -1; break;
3569     case SPECIAL_DSRA32:ic->f = instr(dsra); x64=1;
3570     sa += 32; break;
3571 dpavlin 22 }
3572 dpavlin 44
3573 dpavlin 22 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3574 dpavlin 24 if (sa >= 0)
3575     ic->arg[1] = sa;
3576     else
3577     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3578 dpavlin 22 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3579 dpavlin 32
3580     /* Special checks for MIPS32/64 revision 2 opcodes,
3581     such as rotation instructions: */
3582     if (sa >= 0 && rs != 0x00) {
3583 dpavlin 44 if (cpu->cd.mips.cpu_type.isa_level < 32 ||
3584     cpu->cd.mips.cpu_type.isa_revision < 2) {
3585     static int warning_rotate = 0;
3586     if (!warning_rotate &&
3587     !cpu->translation_readahead) {
3588     fatal("[ WARNING! MIPS32/64 "
3589     "revision 2 rotate opcode"
3590     " used, but the %s process"
3591     "or does not implement "
3592     "such instructions. Only "
3593     "printing this "
3594     "warning once. ]\n",
3595     cpu->cd.mips.cpu_type.name);
3596     warning_rotate = 1;
3597     }
3598     ic->f = instr(reserved);
3599     break;
3600     }
3601 dpavlin 32 switch (rs) {
3602 dpavlin 44 case 0x01:
3603     switch (s6) {
3604     case SPECIAL_SRL: /* ror */
3605     ic->f = instr(ror);
3606     break;
3607     default:goto bad;
3608     }
3609     break;
3610 dpavlin 32 default:goto bad;
3611     }
3612     }
3613     if (sa < 0 && (s10 & 0x1f) != 0) {
3614     switch (s10 & 0x1f) {
3615     /* TODO: [d]rorv, etc. */
3616     default:goto bad;
3617     }
3618     }
3619 dpavlin 44
3620     if (rd == MIPS_GPR_ZERO)
3621     ic->f = instr(nop);
3622     if (ic->f == instr(sll))
3623     cpu->cd.mips.combination_check = COMBINE(sll);
3624     if (ic->f == instr(nop))
3625     cpu->cd.mips.combination_check = COMBINE(nop);
3626 dpavlin 22 break;
3627    
3628 dpavlin 24 case SPECIAL_ADD:
3629 dpavlin 22 case SPECIAL_ADDU:
3630 dpavlin 24 case SPECIAL_SUB:
3631 dpavlin 22 case SPECIAL_SUBU:
3632 dpavlin 24 case SPECIAL_DADD:
3633 dpavlin 22 case SPECIAL_DADDU:
3634 dpavlin 24 case SPECIAL_DSUB:
3635 dpavlin 22 case SPECIAL_DSUBU:
3636     case SPECIAL_SLT:
3637     case SPECIAL_SLTU:
3638 dpavlin 24 case SPECIAL_AND:
3639 dpavlin 22 case SPECIAL_OR:
3640     case SPECIAL_XOR:
3641     case SPECIAL_NOR:
3642 dpavlin 24 case SPECIAL_MOVN:
3643     case SPECIAL_MOVZ:
3644 dpavlin 22 case SPECIAL_MFHI:
3645     case SPECIAL_MFLO:
3646     case SPECIAL_MTHI:
3647     case SPECIAL_MTLO:
3648 dpavlin 24 case SPECIAL_DIV:
3649     case SPECIAL_DIVU:
3650     case SPECIAL_DDIV:
3651     case SPECIAL_DDIVU:
3652     case SPECIAL_MULT:
3653     case SPECIAL_MULTU:
3654     case SPECIAL_DMULT:
3655     case SPECIAL_DMULTU:
3656     case SPECIAL_TGE:
3657     case SPECIAL_TGEU:
3658     case SPECIAL_TLT:
3659     case SPECIAL_TLTU:
3660     case SPECIAL_TEQ:
3661     case SPECIAL_TNE:
3662 dpavlin 22 switch (s6) {
3663 dpavlin 24 case SPECIAL_ADD: ic->f = instr(add); break;
3664 dpavlin 22 case SPECIAL_ADDU: ic->f = instr(addu); break;
3665 dpavlin 24 case SPECIAL_SUB: ic->f = instr(sub); break;
3666 dpavlin 22 case SPECIAL_SUBU: ic->f = instr(subu); break;
3667 dpavlin 24 case SPECIAL_DADD: ic->f = instr(dadd); x64=1; break;
3668 dpavlin 22 case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
3669 dpavlin 24 case SPECIAL_DSUB: ic->f = instr(dsub); x64=1; break;
3670 dpavlin 22 case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;
3671     case SPECIAL_SLT: ic->f = instr(slt); break;
3672     case SPECIAL_SLTU: ic->f = instr(sltu); break;
3673 dpavlin 24 case SPECIAL_AND: ic->f = instr(and); break;
3674 dpavlin 22 case SPECIAL_OR: ic->f = instr(or); break;
3675     case SPECIAL_XOR: ic->f = instr(xor); break;
3676     case SPECIAL_NOR: ic->f = instr(nor); break;
3677     case SPECIAL_MFHI: ic->f = instr(mov); break;
3678     case SPECIAL_MFLO: ic->f = instr(mov); break;
3679     case SPECIAL_MTHI: ic->f = instr(mov); break;
3680     case SPECIAL_MTLO: ic->f = instr(mov); break;
3681 dpavlin 24 case SPECIAL_DIV: ic->f = instr(div); break;
3682     case SPECIAL_DIVU: ic->f = instr(divu); break;
3683     case SPECIAL_DDIV: ic->f = instr(ddiv); x64=1; break;
3684     case SPECIAL_DDIVU: ic->f = instr(ddivu); x64=1; break;
3685     case SPECIAL_MULT : ic->f = instr(mult); break;
3686     case SPECIAL_MULTU: ic->f = instr(multu); break;
3687     case SPECIAL_DMULT: ic->f = instr(dmult); x64=1; break;
3688     case SPECIAL_DMULTU:ic->f = instr(dmultu); x64=1; break;
3689     case SPECIAL_TGE: ic->f = instr(tge); break;
3690     case SPECIAL_TGEU: ic->f = instr(tgeu); break;
3691     case SPECIAL_TLT: ic->f = instr(tlt); break;
3692     case SPECIAL_TLTU: ic->f = instr(tltu); break;
3693     case SPECIAL_TEQ: ic->f = instr(teq); break;
3694     case SPECIAL_TNE: ic->f = instr(tne); break;
3695     case SPECIAL_MOVN: ic->f = instr(movn); break;
3696     case SPECIAL_MOVZ: ic->f = instr(movz); break;
3697 dpavlin 22 }
3698 dpavlin 44
3699 dpavlin 22 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3700     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3701     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3702 dpavlin 44
3703 dpavlin 22 switch (s6) {
3704     case SPECIAL_MFHI:
3705     ic->arg[0] = (size_t)&cpu->cd.mips.hi;
3706     break;
3707     case SPECIAL_MFLO:
3708     ic->arg[0] = (size_t)&cpu->cd.mips.lo;
3709     break;
3710     case SPECIAL_MTHI:
3711     ic->arg[2] = (size_t)&cpu->cd.mips.hi;
3712     break;
3713     case SPECIAL_MTLO:
3714     ic->arg[2] = (size_t)&cpu->cd.mips.lo;
3715     break;
3716     }
3717 dpavlin 24 /* Special cases for rd: */
3718 dpavlin 22 switch (s6) {
3719     case SPECIAL_MTHI:
3720     case SPECIAL_MTLO:
3721 dpavlin 24 case SPECIAL_DIV:
3722     case SPECIAL_DIVU:
3723     case SPECIAL_DDIV:
3724     case SPECIAL_DDIVU:
3725 dpavlin 22 case SPECIAL_MULT:
3726     case SPECIAL_MULTU:
3727     case SPECIAL_DMULT:
3728     case SPECIAL_DMULTU:
3729 dpavlin 24 case SPECIAL_TGE:
3730     case SPECIAL_TGEU:
3731     case SPECIAL_TLT:
3732     case SPECIAL_TLTU:
3733     case SPECIAL_TEQ:
3734     case SPECIAL_TNE:
3735     if (s6 == SPECIAL_MULT && rd != MIPS_GPR_ZERO) {
3736     if (cpu->cd.mips.cpu_type.rev ==
3737     MIPS_R5900) {
3738     ic->f = instr(mult_r5900);
3739     break;
3740     }
3741     break;
3742     }
3743     if (s6 == SPECIAL_MULTU && rd!=MIPS_GPR_ZERO) {
3744     if (cpu->cd.mips.cpu_type.rev ==
3745     MIPS_R5900) {
3746     ic->f = instr(multu_r5900);
3747     break;
3748     }
3749     }
3750 dpavlin 22 if (rd != MIPS_GPR_ZERO) {
3751 dpavlin 42 if (!cpu->translation_readahead)
3752     fatal("TODO: rd NON-zero\n");
3753 dpavlin 22 goto bad;
3754     }
3755 dpavlin 24 /* These instructions don't use rd. */
3756 dpavlin 22 break;
3757 dpavlin 24 default:if (rd == MIPS_GPR_ZERO)
3758     ic->f = instr(nop);
3759 dpavlin 22 }
3760 dpavlin 30
3761     if (ic->f == instr(addu))
3762     cpu->cd.mips.combination_check = COMBINE(addu);
3763 dpavlin 34
3764 dpavlin 22 break;
3765    
3766     case SPECIAL_JR:
3767     case SPECIAL_JALR:
3768     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3769     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
3770 dpavlin 24 if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
3771     s6 = SPECIAL_JR;
3772     ic->arg[2] = (addr & 0xffc) + 8;
3773     switch (s6) {
3774 dpavlin 22 case SPECIAL_JR:
3775     if (rs == MIPS_GPR_RA) {
3776     if (cpu->machine->show_trace_tree)
3777     ic->f = instr(jr_ra_trace);
3778     else
3779     ic->f = instr(jr_ra);
3780     } else {
3781     ic->f = instr(jr);
3782     }
3783 dpavlin 42 if (cpu->translation_readahead > 2)
3784     cpu->translation_readahead = 2;
3785 dpavlin 22 break;
3786     case SPECIAL_JALR:
3787     if (cpu->machine->show_trace_tree)
3788     ic->f = instr(jalr_trace);
3789     else
3790     ic->f = instr(jalr);
3791     break;
3792     }
3793 dpavlin 24 if (cpu->delay_slot) {
3794 dpavlin 42 if (!cpu->translation_readahead)
3795     fatal("TODO: branch in delay "
3796     "slot? (1)\n");
3797 dpavlin 24 goto bad;
3798 dpavlin 22 }
3799     break;
3800    
3801 dpavlin 24 case SPECIAL_SYSCALL:
3802     if (((iword >> 6) & 0xfffff) == 0x30378) {
3803     /* "Magic trap" for PROM emulation: */
3804     ic->f = instr(promemul);
3805     } else {
3806     ic->f = instr(syscall);
3807     }
3808     break;
3809    
3810     case SPECIAL_BREAK:
3811 dpavlin 30 if (((iword >> 6) & 0xfffff) == 0x30378) {
3812     /* "Magic trap" for REBOOT: */
3813     ic->f = instr(reboot);
3814     } else {
3815     ic->f = instr(break);
3816     }
3817 dpavlin 24 break;
3818    
3819 dpavlin 22 case SPECIAL_SYNC:
3820     ic->f = instr(nop);
3821     break;
3822    
3823     default:goto bad;
3824     }
3825     break;
3826    
3827     case HI6_BEQ:
3828     case HI6_BNE:
3829 dpavlin 24 case HI6_BEQL:
3830     case HI6_BNEL:
3831     case HI6_BLEZ:
3832     case HI6_BLEZL:
3833     case HI6_BGTZ:
3834     case HI6_BGTZL:
3835 dpavlin 22 samepage_function = NULL; /* get rid of a compiler warning */
3836     switch (main_opcode) {
3837     case HI6_BEQ:
3838     ic->f = instr(beq);
3839     samepage_function = instr(beq_samepage);
3840     /* Special case: comparing a register with itself: */
3841     if (rs == rt) {
3842     ic->f = instr(b);
3843     samepage_function = instr(b_samepage);
3844     }
3845     break;
3846     case HI6_BNE:
3847     ic->f = instr(bne);
3848     samepage_function = instr(bne_samepage);
3849 dpavlin 24 break;
3850     case HI6_BEQL:
3851     ic->f = instr(beql);
3852     samepage_function = instr(beql_samepage);
3853     /* Special case: comparing a register with itself: */
3854     if (rs == rt) {
3855     ic->f = instr(b);
3856     samepage_function = instr(b_samepage);
3857     }
3858     break;
3859     case HI6_BNEL:
3860     ic->f = instr(bnel);
3861     samepage_function = instr(bnel_samepage);
3862     break;
3863     case HI6_BLEZ:
3864     ic->f = instr(blez);
3865     samepage_function = instr(blez_samepage);
3866     break;
3867     case HI6_BLEZL:
3868     ic->f = instr(blezl);
3869     samepage_function = instr(blezl_samepage);
3870     break;
3871     case HI6_BGTZ:
3872     ic->f = instr(bgtz);
3873     samepage_function = instr(bgtz_samepage);
3874     break;
3875     case HI6_BGTZL:
3876     ic->f = instr(bgtzl);
3877     samepage_function = instr(bgtzl_samepage);
3878     break;
3879 dpavlin 22 }
3880     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3881     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3882 dpavlin 24 ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
3883     + (addr & 0xffc) + 4 );
3884 dpavlin 22 /* Is the offset from the start of the current page still
3885     within the same page? Then use the samepage_function: */
3886     if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE - 1)
3887     << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc) < 0xffc) {
3888     ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page +
3889     ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
3890     & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
3891     ic->f = samepage_function;
3892     }
3893 dpavlin 24 if (cpu->delay_slot) {
3894 dpavlin 42 if (!cpu->translation_readahead)
3895     fatal("TODO: branch in delay slot? (2)\n");
3896 dpavlin 24 goto bad;
3897 dpavlin 22 }
3898     break;
3899    
3900 dpavlin 24 case HI6_ADDI:
3901 dpavlin 22 case HI6_ADDIU:
3902 dpavlin 24 case HI6_SLTI:
3903     case HI6_SLTIU:
3904     case HI6_DADDI:
3905 dpavlin 22 case HI6_DADDIU:
3906     case HI6_ANDI:
3907     case HI6_ORI:
3908     case HI6_XORI:
3909     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3910     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3911     if (main_opcode == HI6_ADDI ||
3912     main_opcode == HI6_ADDIU ||
3913 dpavlin 24 main_opcode == HI6_SLTI ||
3914     main_opcode == HI6_SLTIU ||
3915 dpavlin 22 main_opcode == HI6_DADDI ||
3916     main_opcode == HI6_DADDIU)
3917     ic->arg[2] = (int16_t)iword;
3918     else
3919     ic->arg[2] = (uint16_t)iword;
3920 dpavlin 24
3921 dpavlin 22 switch (main_opcode) {
3922 dpavlin 24 case HI6_ADDI: ic->f = instr(addi); break;
3923 dpavlin 22 case HI6_ADDIU: ic->f = instr(addiu); break;
3924 dpavlin 24 case HI6_SLTI: ic->f = instr(slti); break;
3925     case HI6_SLTIU: ic->f = instr(sltiu); break;
3926     case HI6_DADDI: ic->f = instr(daddi); x64 = 1; break;
3927 dpavlin 22 case HI6_DADDIU: ic->f = instr(daddiu); x64 = 1; break;
3928     case HI6_ANDI: ic->f = instr(andi); break;
3929     case HI6_ORI: ic->f = instr(ori); break;
3930     case HI6_XORI: ic->f = instr(xori); break;
3931     }
3932 dpavlin 24
3933 dpavlin 28 if (ic->arg[2] == 0) {
3934     if ((cpu->is_32bit && ic->f == instr(addiu)) ||
3935     (!cpu->is_32bit && ic->f == instr(daddiu))) {
3936     ic->f = instr(mov);
3937     ic->arg[2] = ic->arg[1];
3938     }
3939     }
3940    
3941 dpavlin 22 if (rt == MIPS_GPR_ZERO)
3942     ic->f = instr(nop);
3943    
3944 dpavlin 30 if (ic->f == instr(ori))
3945     cpu->cd.mips.combination_check = COMBINE(ori);
3946 dpavlin 22 if (ic->f == instr(addiu))
3947 dpavlin 28 cpu->cd.mips.combination_check = COMBINE(addiu);
3948 dpavlin 24 if (ic->f == instr(daddiu))
3949     cpu->cd.mips.combination_check = COMBINE(b_daddiu);
3950 dpavlin 22 break;
3951    
3952     case HI6_LUI:
3953     ic->f = instr(set);
3954     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3955 dpavlin 24 ic->arg[1] = (int32_t) (imm << 16);
3956 dpavlin 28 /* NOTE: Don't use arg[2] here. It can be used with
3957     instruction combinations, to do lui + addiu, etc. */
3958 dpavlin 22 if (rt == MIPS_GPR_ZERO)
3959     ic->f = instr(nop);
3960     break;
3961    
3962 dpavlin 24 case HI6_J:
3963     case HI6_JAL:
3964     switch (main_opcode) {
3965     case HI6_J:
3966     ic->f = instr(j);
3967 dpavlin 42 if (cpu->translation_readahead > 2)
3968     cpu->translation_readahead = 2;
3969 dpavlin 24 break;
3970     case HI6_JAL:
3971     if (cpu->machine->show_trace_tree)
3972     ic->f = instr(jal_trace);
3973     else
3974     ic->f = instr(jal);
3975     break;
3976     }
3977     ic->arg[0] = (iword & 0x03ffffff) << 2;
3978     ic->arg[1] = (addr & 0xffc) + 8;
3979     if (cpu->delay_slot) {
3980 dpavlin 42 if (!cpu->translation_readahead)
3981     fatal("TODO: branch in delay slot (=%i)? (3);"
3982     " addr=%016"PRIx64" iword=%08"PRIx32"\n",
3983     cpu->delay_slot, (uint64_t)addr, iword);
3984 dpavlin 24 goto bad;
3985     }
3986     break;
3987    
3988 dpavlin 22 case HI6_COP0:
3989 dpavlin 24 /* TODO: Is checking bit 25 enough, or perhaps all bits
3990     25..21 must be checked? */
3991     if ((iword >> 25) & 1) {
3992     ic->arg[2] = addr & 0xffc;
3993     switch (iword & 0xff) {
3994     case COP0_TLBR:
3995     ic->f = instr(tlbr);
3996     break;
3997     case COP0_TLBWI:
3998     case COP0_TLBWR:
3999     ic->f = instr(tlbw);
4000     ic->arg[0] = (iword & 0xff) == COP0_TLBWR;
4001     break;
4002     case COP0_TLBP:
4003     ic->f = instr(tlbp);
4004     break;
4005     case COP0_RFE:
4006     ic->f = instr(rfe);
4007     break;
4008     case COP0_ERET:
4009     ic->f = instr(eret);
4010     break;
4011     case COP0_DERET:
4012     ic->f = instr(deret);
4013     break;
4014 dpavlin 30 case COP0_WAIT:
4015     ic->f = instr(wait);
4016     if (cpu->cd.mips.cpu_type.rev != MIPS_RM5200 &&
4017     cpu->cd.mips.cpu_type.isa_level < 32) {
4018     static int warned = 0;
4019     ic->f = instr(reserved);
4020 dpavlin 42 if (!warned &&
4021     !cpu->translation_readahead) {
4022 dpavlin 30 fatal("{ WARNING: Attempt to "
4023     "execute the WAIT instruct"
4024     "ion, but the emulated CPU "
4025     "is neither RM52xx, nor "
4026     "MIPS32/64! }\n");
4027     warned = 1;
4028     }
4029     }
4030     break;
4031 dpavlin 24 case COP0_STANDBY:
4032 dpavlin 32 /* NOTE: Reusing the 'wait' instruction: */
4033     ic->f = instr(wait);
4034     if (cpu->cd.mips.cpu_type.rev != MIPS_R4100) {
4035     static int warned = 0;
4036     ic->f = instr(reserved);
4037 dpavlin 42 if (!warned &&
4038     !cpu->translation_readahead) {
4039 dpavlin 32 fatal("{ WARNING: Attempt to "
4040     "execute a R41xx instruct"
4041     "ion, but the emulated CPU "
4042     "doesn't support it! }\n");
4043     warned = 1;
4044     }
4045     }
4046     break;
4047 dpavlin 24 case COP0_HIBERNATE:
4048     /* TODO */
4049 dpavlin 32 goto bad;
4050     case COP0_SUSPEND:
4051     /* Used by NetBSD on HPCmips (VR41xx) to
4052     halt the machine. */
4053     ic->f = instr(reboot);
4054 dpavlin 24 break;
4055     case COP0_EI:
4056     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4057     ic->f = instr(ei_r5900);
4058     } else
4059     goto bad;
4060     break;
4061     case COP0_DI:
4062     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4063     ic->f = instr(di_r5900);
4064     } else
4065     goto bad;
4066     break;
4067 dpavlin 42 default:if (!cpu->translation_readahead)
4068     fatal("UNIMPLEMENTED cop0 (func "
4069     "0x%02x)\n", iword & 0xff);
4070 dpavlin 24 goto bad;
4071     }
4072     break;
4073     }
4074    
4075 dpavlin 22 /* rs contains the coprocessor opcode! */
4076     switch (rs) {
4077 dpavlin 24 case COPz_CFCz:
4078     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4079     ic->arg[1] = rd + ((iword & 7) << 5);
4080     ic->arg[2] = addr & 0xffc;
4081     ic->f = instr(cfc0);
4082     if (rt == MIPS_GPR_ZERO)
4083     ic->f = instr(nop);
4084     break;
4085 dpavlin 22 case COPz_MFCz:
4086     case COPz_DMFCz:
4087     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4088     ic->arg[1] = rd + ((iword & 7) << 5);
4089     ic->arg[2] = addr & 0xffc;
4090     ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);
4091 dpavlin 32 if (rs == COPz_MFCz && (iword & 7) == 0 &&
4092     rd != COP0_COUNT)
4093     ic->f = instr(mfc0_select0);
4094     if (rs == COPz_DMFCz && (iword & 7) == 0 &&
4095     rd != COP0_COUNT)
4096     ic->f = instr(dmfc0_select0);
4097 dpavlin 22 if (rt == MIPS_GPR_ZERO)
4098     ic->f = instr(nop);
4099     break;
4100     case COPz_MTCz:
4101     case COPz_DMTCz:
4102     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4103     ic->arg[1] = rd + ((iword & 7) << 5);
4104     ic->arg[2] = addr & 0xffc;
4105     ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
4106 dpavlin 28
4107     if (cpu->cd.mips.cpu_type.exc_model == EXC3K &&
4108     rs == COPz_MTCz && rd == COP0_STATUS)
4109     cpu->cd.mips.combination_check =
4110     COMBINE(netbsd_r3k_cache_inv);
4111    
4112 dpavlin 22 break;
4113 dpavlin 42 case COPz_MFMCz:
4114     if ((iword & 0xffdf) == 0x6000) {
4115     /* MIPS32/64 rev 2 "ei" or "di": */
4116     if (cpu->cd.mips.cpu_type.isa_level < 32 ||
4117     cpu->cd.mips.cpu_type.isa_revision < 2) {
4118     static int warning_ei_di = 0;
4119     if (!warning_ei_di &&
4120     !cpu->translation_readahead) {
4121     fatal("[ WARNING! MIPS32/64 "
4122     "revision 2 di or ei opcode"
4123     " used, but the %s process"
4124     "or does not implement "
4125     "such instructions. Only "
4126     "printing this "
4127     "warning once. ]\n",
4128     cpu->cd.mips.cpu_type.name);
4129     warning_ei_di = 1;
4130     }
4131     ic->f = instr(reserved);
4132     break;
4133     }
4134     ic->f = instr(ei_or_di);
4135     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4136     if (rt == MIPS_GPR_ZERO)
4137     ic->arg[0] =
4138     (size_t)&cpu->cd.mips.scratch;
4139     ic->arg[1] = iword & 0x20;
4140     } else {
4141     if (!cpu->translation_readahead)
4142     fatal("Unimplemented COP0_MFMCz\n");
4143     goto bad;
4144     }
4145     break;
4146     case COPz_BCzc:
4147     if (iword == 0x4100ffff) {
4148 dpavlin 24 /* R2020 DECstation write-loop thingy. */
4149     ic->f = instr(nop);
4150     } else {
4151 dpavlin 42 if (!cpu->translation_readahead)
4152     fatal("Unimplemented COP0_BCzc\n");
4153 dpavlin 24 goto bad;
4154     }
4155     break;
4156    
4157 dpavlin 42 default:if (!cpu->translation_readahead)
4158     fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
4159 dpavlin 22 goto bad;
4160     }
4161     break;
4162    
4163     case HI6_COP1:
4164 dpavlin 24 /* Always cause a coprocessor unusable exception if
4165     there is no floating point coprocessor: */
4166     if (cpu->cd.mips.cpu_type.flags & NOFPU ||
4167     cpu->cd.mips.coproc[1] == NULL) {
4168     ic->f = instr(cpu);
4169     ic->arg[0] = 1;
4170     break;
4171     }
4172    
4173     /* Bits 25..21 are floating point main opcode: */
4174 dpavlin 22 switch (rs) {
4175 dpavlin 24
4176     case COPz_BCzc:
4177     /* Conditional branch: */
4178     /* TODO: Reimplement this in a faster way. */
4179     ic->f = instr(cop1_bc);
4180     ic->arg[0] = (iword >> 18) & 7; /* cc */
4181     ic->arg[1] = (iword >> 16) & 3; /* nd, tf bits */
4182     ic->arg[2] = (int32_t) ((imm <<
4183     MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);
4184     if (cpu->delay_slot) {
4185 dpavlin 42 if (!cpu->translation_readahead)
4186     fatal("TODO: branch in delay slot 4\n");
4187 dpavlin 24 goto bad;
4188     }
4189     if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
4190     ic->arg[0] != 0) {
4191 dpavlin 42 if (!cpu->translation_readahead)
4192     fatal("Attempt to execute a non-cc-0 "
4193     "BC* instruction on an isa level "
4194     "%i cpu. TODO: How should this be "
4195     "handled?\n",
4196     cpu->cd.mips.cpu_type.isa_level);
4197 dpavlin 24 goto bad;
4198     }
4199    
4200     break;
4201    
4202     case COPz_DMFCz:
4203     case COPz_DMTCz:
4204     x64 = 1;
4205     /* FALL-THROUGH */
4206     case COP1_FMT_S:
4207     case COP1_FMT_D:
4208     case COP1_FMT_W:
4209     case COP1_FMT_L:
4210     case COP1_FMT_PS:
4211 dpavlin 22 case COPz_CFCz:
4212 dpavlin 24 case COPz_CTCz:
4213     case COPz_MFCz:
4214     case COPz_MTCz:
4215     /* Fallback to slow pre-dyntrans code, for now. */
4216     /* TODO: Fix/optimize/rewrite. */
4217     ic->f = instr(cop1_slow);
4218     ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);
4219 dpavlin 22 break;
4220 dpavlin 24
4221 dpavlin 42 default:if (!cpu->translation_readahead)
4222     fatal("COP1 floating point opcode = 0x%02x\n", rs);
4223 dpavlin 22 goto bad;
4224     }
4225     break;
4226    
4227 dpavlin 24 case HI6_COP2:
4228     /* Always cause a coprocessor unusable exception if
4229     there is no coprocessor 2: */
4230     if (cpu->cd.mips.coproc[2] == NULL) {
4231     ic->f = instr(cpu);
4232     ic->arg[0] = 2;
4233     break;
4234     }
4235 dpavlin 42 if (!cpu->translation_readahead)
4236     fatal("COP2 functionality not yet implemented\n");
4237 dpavlin 24 goto bad;
4238     break;
4239    
4240 dpavlin 34 case HI6_COP3:
4241     /* Always cause a coprocessor unusable exception if
4242     there is no coprocessor 3: */
4243     if (cpu->cd.mips.coproc[3] == NULL) {
4244     ic->f = instr(cpu);
4245     ic->arg[0] = 3;
4246     break;
4247     }
4248    
4249     if (iword == 0x4d00ffff) {
4250     /* R2020 writeback thing, used by e.g. NetBSD/pmax
4251     on MIPSMATE. */
4252     ic->f = instr(nop);
4253     } else {
4254 dpavlin 42 if (!cpu->translation_readahead)
4255     fatal("COP3 iword=0x%08x\n", iword);
4256 dpavlin 34 goto bad;
4257     }
4258     break;
4259    
4260 dpavlin 22 case HI6_SPECIAL2:
4261 dpavlin 24 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4262     /* R5900, TX79/C790, have MMI instead of SPECIAL2: */
4263     int mmi_subopcode = (iword >> 6) & 0x1f;
4264    
4265     switch (s6) {
4266    
4267     case MMI_MADD:
4268     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4269     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4270     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4271     if (rd == MIPS_GPR_ZERO)
4272     ic->f = instr(madd);
4273     else
4274     ic->f = instr(madd_rd);
4275     break;
4276    
4277     case MMI_MADDU:
4278     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4279     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4280     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4281     if (rd == MIPS_GPR_ZERO)
4282     ic->f = instr(maddu);
4283     else
4284     ic->f = instr(maddu_rd);
4285     break;
4286    
4287     case MMI_MMI0:
4288     switch (mmi_subopcode) {
4289    
4290     case MMI0_PEXTLW:
4291     ic->arg[0] = rs;
4292     ic->arg[1] = rt;
4293     ic->arg[2] = rd;
4294     if (rd == MIPS_GPR_ZERO)
4295     ic->f = instr(nop);
4296     else
4297     ic->f = instr(pextlw);
4298     break;
4299    
4300     default:goto bad;
4301     }
4302     break;
4303    
4304     case MMI_MMI3:
4305     switch (mmi_subopcode) {
4306    
4307     case MMI3_POR:
4308     ic->arg[0] = rs;
4309     ic->arg[1] = rt;
4310     ic->arg[2] = rd;
4311     if (rd == MIPS_GPR_ZERO)
4312     ic->f = instr(nop);
4313     else
4314     ic->f = instr(por);
4315     break;
4316    
4317     default:goto bad;
4318     }
4319     break;
4320    
4321     default:goto bad;
4322     }
4323     break;
4324     }
4325    
4326     /* TODO: is this correct? Or are there other non-MIPS32/64
4327     MIPS processors that have support for SPECIAL2 opcodes? */
4328     if (cpu->cd.mips.cpu_type.isa_level < 32) {
4329     ic->f = instr(reserved);
4330     break;
4331     }
4332    
4333     /* SPECIAL2: */
4334 dpavlin 22 switch (s6) {
4335    
4336 dpavlin 24 case SPECIAL2_MADD:
4337     case SPECIAL2_MADDU:
4338     case SPECIAL2_MSUB:
4339     case SPECIAL2_MSUBU:
4340     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4341     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4342     switch (s6) {
4343     case SPECIAL2_MADD: ic->f = instr(madd); break;
4344     case SPECIAL2_MADDU:ic->f = instr(maddu); break;
4345     case SPECIAL2_MSUB: ic->f = instr(msub); break;
4346     case SPECIAL2_MSUBU:ic->f = instr(msubu); break;
4347     }
4348     break;
4349    
4350 dpavlin 22 case SPECIAL2_MUL:
4351     ic->f = instr(mul);
4352     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4353     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4354     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4355     if (rd == MIPS_GPR_ZERO)
4356     ic->f = instr(nop);
4357     break;
4358    
4359     case SPECIAL2_CLZ:
4360     case SPECIAL2_CLO:
4361     case SPECIAL2_DCLZ:
4362     case SPECIAL2_DCLO:
4363     switch (s6) {
4364     case SPECIAL2_CLZ: ic->f = instr(clz); break;
4365     case SPECIAL2_CLO: ic->f = instr(clo); break;
4366     case SPECIAL2_DCLZ: ic->f = instr(dclz); break;
4367     case SPECIAL2_DCLO: ic->f = instr(dclo); break;
4368     }
4369     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4370     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4371     if (rd == MIPS_GPR_ZERO)
4372     ic->f = instr(nop);
4373     break;
4374    
4375     default:goto bad;
4376     }
4377     break;
4378    
4379 dpavlin 24 case HI6_REGIMM:
4380     switch (rt) {
4381     case REGIMM_BGEZ:
4382     case REGIMM_BGEZL:
4383     case REGIMM_BLTZ:
4384     case REGIMM_BLTZL:
4385     case REGIMM_BGEZAL:
4386     case REGIMM_BGEZALL:
4387     case REGIMM_BLTZAL:
4388     case REGIMM_BLTZALL:
4389     samepage_function = NULL;
4390     switch (rt) {
4391     case REGIMM_BGEZ:
4392     ic->f = instr(bgez);
4393     samepage_function = instr(bgez_samepage);
4394     break;
4395     case REGIMM_BGEZL:
4396     ic->f = instr(bgezl);
4397     samepage_function = instr(bgezl_samepage);
4398     break;
4399     case REGIMM_BLTZ:
4400     ic->f = instr(bltz);
4401     samepage_function = instr(bltz_samepage);
4402     break;
4403     case REGIMM_BLTZL:
4404     ic->f = instr(bltzl);
4405     samepage_function = instr(bltzl_samepage);
4406     break;
4407     case REGIMM_BGEZAL:
4408     ic->f = instr(bgezal);
4409     samepage_function = instr(bgezal_samepage);
4410     break;
4411     case REGIMM_BGEZALL:
4412     ic->f = instr(bgezall);
4413     samepage_function = instr(bgezall_samepage);
4414     break;
4415     case REGIMM_BLTZAL:
4416     ic->f = instr(bltzal);
4417     samepage_function = instr(bltzal_samepage);
4418     break;
4419     case REGIMM_BLTZALL:
4420     ic->f = instr(bltzall);
4421     samepage_function = instr(bltzall_samepage);
4422     break;
4423     }
4424     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4425     ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
4426     + (addr & 0xffc) + 4;
4427     /* Is the offset from the start of the current page
4428     still within the same page? Then use the
4429     samepage_function: */
4430     if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE-1)
4431     << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc)
4432     < 0xffc) {
4433     ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page+
4434     ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
4435     & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
4436     ic->f = samepage_function;
4437     }
4438     if (cpu->delay_slot) {
4439 dpavlin 42 if (!cpu->translation_readahead)
4440     fatal("TODO: branch in delay slot:5\n");
4441 dpavlin 24 goto bad;
4442     }
4443     break;
4444 dpavlin 42
4445     default:if (!cpu->translation_readahead)
4446     fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
4447 dpavlin 24 goto bad;
4448     }
4449     break;
4450    
4451     case HI6_LB:
4452     case HI6_LBU:
4453     case HI6_SB:
4454     case HI6_LH:
4455     case HI6_LHU:
4456     case HI6_SH:
4457     case HI6_LW:
4458     case HI6_LWU:
4459     case HI6_SW:
4460     case HI6_LD:
4461     case HI6_SD:
4462     /* TODO: LWU should probably also be x64=1? */
4463     size = 2; signedness = 0; store = 0;
4464     switch (main_opcode) {
4465     case HI6_LB: size = 0; signedness = 1; break;
4466     case HI6_LBU: size = 0; break;
4467     case HI6_LH: size = 1; signedness = 1; break;
4468     case HI6_LHU: size = 1; break;
4469     case HI6_LW: signedness = 1; break;
4470     case HI6_LWU: break;
4471     case HI6_LD: size = 3; x64 = 1; break;
4472     case HI6_SB: store = 1; size = 0; break;
4473     case HI6_SH: store = 1; size = 1; break;
4474     case HI6_SW: store = 1; break;
4475     case HI6_SD: store = 1; size = 3; x64 = 1; break;
4476     }
4477    
4478     ic->f =
4479     #ifdef MODE32
4480     mips32_loadstore
4481     #else
4482     mips_loadstore
4483     #endif
4484     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16)
4485     + store * 8 + size * 2 + signedness];
4486     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4487     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4488     ic->arg[2] = (int32_t)imm;
4489    
4490     /* Load into the dummy scratch register, if rt = zero */
4491     if (!store && rt == MIPS_GPR_ZERO)
4492     ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4493 dpavlin 28
4494 dpavlin 30 /* Check for multiple loads or stores in a row using the same
4495 dpavlin 28 base register: */
4496 dpavlin 30 #ifdef MODE32
4497     if (main_opcode == HI6_LW)
4498     cpu->cd.mips.combination_check = COMBINE(multi_lw);
4499     if (main_opcode == HI6_SW)
4500 dpavlin 28 cpu->cd.mips.combination_check = COMBINE(multi_sw);
4501 dpavlin 30 #endif
4502 dpavlin 24 break;
4503    
4504     case HI6_LL:
4505     case HI6_LLD:
4506     case HI6_SC:
4507     case HI6_SCD:
4508     /* 32-bit load-linked/store-condition for ISA II and up: */
4509     /* (64-bit load-linked/store-condition for ISA III...) */
4510     if (cpu->cd.mips.cpu_type.isa_level < 2) {
4511     ic->f = instr(reserved);
4512     break;
4513     }
4514    
4515     store = 0;
4516     switch (main_opcode) {
4517     case HI6_LL: ic->f = instr(ll); break;
4518     case HI6_LLD: ic->f = instr(lld); x64 = 1; break;
4519     case HI6_SC: ic->f = instr(sc); store = 1; break;
4520     case HI6_SCD: ic->f = instr(scd); store = 1; x64 = 1; break;
4521     }
4522     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4523     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4524     ic->arg[2] = (int32_t)imm;
4525     if (!store && rt == MIPS_GPR_ZERO) {
4526 dpavlin 42 if (!cpu->translation_readahead)
4527     fatal("HM... unusual load linked\n");
4528 dpavlin 24 goto bad;
4529     }
4530     break;
4531    
4532     case HI6_LWL:
4533     case HI6_LWR:
4534     case HI6_LDL:
4535     case HI6_LDR:
4536     case HI6_SWL:
4537     case HI6_SWR:
4538     case HI6_SDL:
4539     case HI6_SDR:
4540     /* TODO: replace these with faster versions... */
4541     store = 0;
4542     switch (main_opcode) {
4543     case HI6_LWL: ic->f = instr(lwl); break;
4544     case HI6_LWR: ic->f = instr(lwr); break;
4545     case HI6_LDL: ic->f = instr(ldl); x64 = 1; break;
4546     case HI6_LDR: ic->f = instr(ldr); x64 = 1; break;
4547     case HI6_SWL: ic->f = instr(swl); store = 1; break;
4548     case HI6_SWR: ic->f = instr(swr); store = 1; break;
4549     case HI6_SDL: ic->f = instr(sdl); store = 1; x64 = 1; break;
4550     case HI6_SDR: ic->f = instr(sdr); store = 1; x64 = 1; break;
4551     }
4552     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4553     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4554     ic->arg[2] = (int32_t)imm;
4555    
4556     /* Load into the dummy scratch register, if rt = zero */
4557     if (!store && rt == MIPS_GPR_ZERO)
4558     ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4559     break;
4560    
4561     case HI6_LWC1:
4562     case HI6_SWC1:
4563     case HI6_LDC1:
4564     case HI6_SDC1:
4565     /* 64-bit floating-point load/store for ISA II and up... */
4566     if ((main_opcode == HI6_LDC1 || main_opcode == HI6_SDC1)
4567     && cpu->cd.mips.cpu_type.isa_level < 2) {
4568     ic->f = instr(reserved);
4569     break;
4570     }
4571    
4572     ic->arg[0] = (size_t)&cpu->cd.mips.coproc[1]->reg[rt];
4573     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4574     ic->arg[2] = (int32_t)imm;
4575     switch (main_opcode) {
4576     case HI6_LWC1: ic->f = instr(lwc1); break;
4577     case HI6_LDC1: ic->f = instr(ldc1); break;
4578     case HI6_SWC1: ic->f = instr(swc1); break;
4579     case HI6_SDC1: ic->f = instr(sdc1); break;
4580     }
4581    
4582     /* Cause a coprocessor unusable exception if
4583     there is no floating point coprocessor: */
4584     if (cpu->cd.mips.cpu_type.flags & NOFPU ||
4585     cpu->cd.mips.coproc[1] == NULL) {
4586     ic->f = instr(cpu);
4587     ic->arg[0] = 1;
4588     }
4589     break;
4590    
4591     case HI6_LWC3:
4592     /* PREF (prefetch) on ISA IV and MIPS32/64: */
4593     if (cpu->cd.mips.cpu_type.isa_level >= 4) {
4594     /* Treat as nop for now: */
4595     ic->f = instr(nop);
4596     } else {
4597 dpavlin 42 if (!cpu->translation_readahead)
4598     fatal("TODO: lwc3 not implemented yet\n");
4599 dpavlin 24 goto bad;
4600     }
4601     break;
4602    
4603     case HI6_LQ_MDMX:
4604     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4605 dpavlin 42 if (!cpu->translation_readahead)
4606     fatal("TODO: R5900 128-bit loads\n");
4607 dpavlin 24 goto bad;
4608     }
4609    
4610 dpavlin 42 if (!cpu->translation_readahead)
4611     fatal("TODO: MDMX\n");
4612    
4613 dpavlin 24 goto bad;
4614     /* break */
4615    
4616     case HI6_SQ_SPECIAL3:
4617     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4618 dpavlin 42 if (!cpu->translation_readahead)
4619     fatal("TODO: R5900 128-bit stores\n");
4620 dpavlin 24 goto bad;
4621     }
4622    
4623     if (cpu->cd.mips.cpu_type.isa_level < 32 ||
4624     cpu->cd.mips.cpu_type.isa_revision < 2) {
4625     static int warning = 0;
4626 dpavlin 42 if (!warning && !cpu->translation_readahead) {
4627 dpavlin 28 fatal("[ WARNING! SPECIAL3 opcode used, but"
4628     " the %s processor does not implement "
4629     "such instructions. Only printing this "
4630     "warning once. ]\n",
4631     cpu->cd.mips.cpu_type.name);
4632 dpavlin 24 warning = 1;
4633     }
4634     ic->f = instr(reserved);
4635     break;
4636     }
4637    
4638     switch (s6) {
4639    
4640 dpavlin 32 case SPECIAL3_EXT:
4641     {
4642     int msbd = rd, lsb = (iword >> 6) & 0x1f;
4643     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4644     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4645     ic->arg[2] = (msbd << 5) + lsb;
4646     ic->f = instr(ext);
4647     if (rt == MIPS_GPR_ZERO)
4648     ic->f = instr(nop);
4649     }
4650     break;
4651    
4652 dpavlin 42 case SPECIAL3_DEXT:
4653     case SPECIAL3_DEXTM:
4654     case SPECIAL3_DEXTU:
4655     {
4656     int msbd = rd, lsb = (iword >> 6) & 0x1f;
4657     if (s6 == SPECIAL3_DEXTM)
4658     msbd += 32;
4659     if (s6 == SPECIAL3_DEXTU)
4660     lsb += 32;
4661     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4662     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4663     ic->arg[2] = (msbd << 6) + lsb;
4664     ic->f = instr(dext);
4665     if (rt == MIPS_GPR_ZERO)
4666     ic->f = instr(nop);
4667     }
4668     break;
4669    
4670     case SPECIAL3_INS:
4671     {
4672     int msb = rd, lsb = (iword >> 6) & 0x1f;
4673     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4674     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4675     ic->arg[2] = (msb << 5) + lsb;
4676     ic->f = instr(ins);
4677     if (rt == MIPS_GPR_ZERO)
4678     ic->f = instr(nop);
4679     }
4680     break;
4681    
4682 dpavlin 32 case SPECIAL3_BSHFL:
4683     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4684     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4685     switch (s10) {
4686     case BSHFL_WSBH:
4687     ic->f = instr(wsbh);
4688     break;
4689     case BSHFL_SEB:
4690     ic->f = instr(seb);
4691     break;
4692     case BSHFL_SEH:
4693     ic->f = instr(seh);
4694     break;
4695     default:goto bad;
4696     }
4697     break;
4698    
4699     case SPECIAL3_DBSHFL:
4700     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4701     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4702     switch (s10) {
4703     case BSHFL_DSBH:
4704     ic->f = instr(dsbh);
4705     break;
4706     case BSHFL_DSHD:
4707     ic->f = instr(dshd);
4708     break;
4709     default:goto bad;
4710     }
4711     break;
4712    
4713 dpavlin 24 case SPECIAL3_RDHWR:
4714     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4715    
4716     switch (rd) {
4717    
4718     case 0: ic->f = instr(rdhwr_cpunum);
4719     if (rt == MIPS_GPR_ZERO)
4720     ic->f = instr(nop);
4721     break;
4722    
4723 dpavlin 42 default:if (!cpu->translation_readahead)
4724     fatal("unimplemented rdhwr "
4725     "register rd=%i\n", rd);
4726 dpavlin 24 goto bad;
4727     }
4728     break;
4729    
4730     default:goto bad;
4731     }
4732     break;
4733    
4734     case HI6_CACHE:
4735     /* TODO: rt and op etc... */
4736     ic->f = instr(cache);
4737     break;
4738    
4739 dpavlin 22 default:goto bad;
4740     }
4741    
4742 dpavlin 34
4743 dpavlin 24 #ifdef MODE32
4744     if (x64) {
4745     static int has_warned = 0;
4746 dpavlin 42 if (!has_warned && !cpu->translation_readahead) {
4747 dpavlin 24 fatal("[ WARNING/NOTE: attempt to execute a 64-bit"
4748     " instruction on an emulated 32-bit processor; "
4749     "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);
4750 dpavlin 42 has_warned = 1;
4751     }
4752     if (cpu->translation_readahead)
4753     goto bad;
4754     else
4755     ic->f = instr(reserved);
4756 dpavlin 24 }
4757     #endif
4758 dpavlin 22
4759 dpavlin 38
4760 dpavlin 22 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
4761     #include "cpu_dyntrans.c"
4762     #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
4763     }
4764    

  ViewVC Help
Powered by ViewVC 1.1.26