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

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


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

  ViewVC Help
Powered by ViewVC 1.1.26