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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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


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

  ViewVC Help
Powered by ViewVC 1.1.26