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

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

  ViewVC Help
Powered by ViewVC 1.1.26