/[gxemul]/trunk/src/cpus/cpu_sh_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_sh_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (show annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 99937 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1613 2007/06/15 20:11:26 debug Exp $
20070501	Continuing a little on m88k disassembly (control registers,
		more instructions).
		Adding a dummy mvme88k machine mode.
20070502	Re-adding MIPS load/store alignment exceptions.
20070503	Implementing more of the M88K disassembly code.
20070504	Adding disassembly of some more M88K load/store instructions.
		Implementing some relatively simple M88K instructions (br.n,
		xor[.u] imm, and[.u] imm).
20070505	Implementing M88K three-register and, or, xor, and jmp[.n],
		bsr[.n] including function call trace stuff.
		Applying a patch from Bruce M. Simpson which implements the
		SYSCON_BOARD_CPU_CLOCK_FREQ_ID object of the syscon call in
		the yamon PROM emulation.
20070506	Implementing M88K bb0[.n] and bb1[.n], and skeletons for
		ldcr and stcr (although no control regs are implemented yet).
20070509	Found and fixed the bug which caused Linux for QEMU_MIPS to
		stop working in 0.4.5.1: It was a faulty change to the MIPS
		'sc' and 'scd' instructions I made while going through gcc -W
		warnings on 20070428.
20070510	Updating the Linux/QEMU_MIPS section in guestoses.html to
		use mips-test-0.2.tar.gz instead of 0.1.
		A big thank you to Miod Vallat for sending me M88K manuals.
		Implementing more M88K instructions (addu, subu, div[u], mulu,
		ext[u], clr, set, cmp).
20070511	Fixing bugs in the M88K "and" and "and.u" instructions (found
		by comparing against the manual).
		Implementing more M88K instructions (mask[.u], mak, bcnd (auto-
		generated)) and some more control register details.
		Cleanup: Removing the experimental AVR emulation mode and
		corresponding devices; AVR emulation wasn't really meaningful.
		Implementing autogeneration of most M88K loads/stores. The
		rectangle drawing demo (with -O0) for M88K runs :-)
		Beginning on M88K exception handling.
		More M88K instructions: tb0, tb1, rte, sub, jsr[.n].
		Adding some skeleton MVME PROM ("BUG") emulation.
20070512	Fixing a bug in the M88K cmp instruction.
		Adding the M88K lda (scaled register) instruction.
		Fixing bugs in 64-bit (32-bit pairs) M88K loads/stores.
		Removing the unused tick_hz stuff from the machine struct.
		Implementing the M88K xmem instruction. OpenBSD/mvme88k gets
		far enough to display the Copyright banner :-)
		Implementing subu.co (guess), addu.co, addu.ci, ff0, and ff1.
		Adding a dev_mvme187, for MVME187-specific devices/registers.
		OpenBSD/mvme88k prints more boot messages. :)
20070515	Continuing on MVME187 emulation (adding more devices, beginning
		on the CMMUs, etc).
		Adding the M88K and.c, xor.c, and or.c instructions, and making
		sure that mul, div, etc cause exceptions if executed when SFD1
		is disabled.
20070517	Continuing on M88K and MVME187 emulation in general; moving
		the CMMU registers to the CPU struct, separating dev_pcc2 from
		dev_mvme187, and beginning on memory_m88k.c (BATC and PATC).
		Fixing a bug in 64-bit (32-bit pairs) M88K fast stores.
		Implementing the clock part of dev_mk48txx.
		Implementing the M88K fstcr and xcr instructions.
		Implementing m88k_cpu_tlbdump().
		Beginning on the implementation of a separate address space
		for M88K .usr loads/stores.
20070520	Removing the non-working (skeleton) Sandpoint, SonyNEWS, SHARK
		Dnard, and Zaurus machine modes.
		Experimenting with dyntrans to_be_translated read-ahead. It
		seems to give a very small performance increase for MIPS
		emulation, but a large performance degradation for SuperH. Hm.
20070522	Disabling correct SuperH ITLB emulation; it does not seem to be
		necessary in order to let SH4 guest OSes run, and it slows down
		userspace code.
		Implementing "samepage" branches for SuperH emulation, and some
		other minor speed hacks.
20070525	Continuing on M88K memory-related stuff: exceptions, memory
		transaction register contents, etc.
		Implementing the M88K subu.ci instruction.
		Removing the non-working (skeleton) Iyonix machine mode.
		OpenBSD/mvme88k reaches userland :-), starts executing
		/sbin/init's instructions, and issues a few syscalls, before
		crashing.
20070526	Fixing bugs in dev_mk48txx, so that OpenBSD/mvme88k detects
		the correct time-of-day.
		Implementing a generic IRQ controller for the test machines
		(dev_irqc), similar to a proposed patch from Petr Stepan.
		Experimenting some more with translation read-ahead.
		Adding an "expect" script for automated OpenBSD/landisk
		install regression/performance tests.
20070527	Adding a dummy mmEye (SH3) machine mode skeleton.
		FINALLY found the strange M88K bug I have been hunting: I had
		not emulated the SNIP value for exceptions occurring in
		branch delay slots correctly.
		Implementing correct exceptions for 64-bit M88K loads/stores.
		Address to symbol lookups are now disabled when M88K is
		running in usermode (because usermode addresses don't have
		anything to do with supervisor addresses).
20070531	Removing the mmEye machine mode skeleton.
20070604	Some minor code cleanup.
20070605	Moving src/useremul.c into a subdir (src/useremul/), and
		cleaning up some more legacy constructs.
		Adding -Wstrict-aliasing and -fstrict-aliasing detection to
		the configure script.
20070606	Adding a check for broken GCC on Solaris to the configure
		script. (GCC 3.4.3 on Solaris cannot handle static variables
		which are initialized to 0 or NULL. :-/)
		Removing the old (non-working) ARC emulation modes: NEC RD94,
		R94, R96, and R98, and the last traces of Olivetti M700 and
		Deskstation Tyne.
		Removing the non-working skeleton WDSC device (dev_wdsc).
20070607	Thinking about how to use the host's cc + ld at runtime to
		generate native code. (See experiments/native_cc_ld_test.i
		for an example.)
20070608	Adding a program counter sampling timer, which could be useful
		for native code generation experiments.
		The KN02_CSR_NRMMOD bit in the DECstation 5000/200 (KN02) CSR
		should always be set, to allow a 5000/200 PROM to boot.
20070609	Moving out breakpoint details from the machine struct into
		a helper struct, and removing the limit on max nr of
		breakpoints.
20070610	Moving out tick functions into a helper struct as well (which
		also gets rid of the max limit).
20070612	FINALLY figured out why Debian/DECstation stopped working when
		translation read-ahead was enabled: in src/memory_rw.c, the
		call to invalidate_code_translation was made also if the
		memory access was an instruction load (if the page was mapped
		as writable); it shouldn't be called in that case.
20070613	Implementing some more MIPS32/64 revision 2 instructions: di,
		ei, ext, dext, dextm, dextu, and ins.
20070614	Implementing an instruction combination for the NetBSD/arm
		idle loop (making the host not use any cpu if NetBSD/arm
		inside the emulator is not using any cpu).
		Increasing the nr of ARM VPH entries from 128 to 384.
20070615	Removing the ENABLE_arch stuff from the configure script, so
		that all included architectures are included in both release
		and development builds.
		Moving memory related helper functions from misc.c to memory.c.
		Adding preliminary instructions for netbooting NetBSD/pmppc to
		guestoses.html; it doesn't work yet, there are weird timeouts.
		Beginning a total rewrite of the userland emulation modes
		(removing all emulation modes, beginning from scratch with
		NetBSD/MIPS and FreeBSD/Alpha only).
20070616	After fixing a bug in the DEC21143 NIC (the TDSTAT_OWN bit was
		only cleared for the last segment when transmitting, not all
		segments), NetBSD/pmppc boots with root-on-nfs without the
		timeouts. Updating guestoses.html.
		Removing the skeleton PSP (Playstation Portable) mode.
		Moving X11-related stuff in the machine struct into a helper
		struct.
		Cleanup of out-of-memory checks, to use a new CHECK_ALLOCATION
		macro (which prints a meaningful error message).
		Adding a COMMENT to each machine and device (for automagic
		.index comment generation).
		Doing regression testing for the next release.

==============  RELEASE 0.4.6  ==============


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_sh_instr.c,v 1.61 2007/06/04 06:32:25 debug Exp $
29 *
30 * SH 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 #define SYNCH_PC { \
40 int low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page) \
41 / sizeof(struct sh_instr_call); \
42 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1) \
43 << SH_INSTR_ALIGNMENT_SHIFT); \
44 cpu->pc += (low_pc << SH_INSTR_ALIGNMENT_SHIFT); \
45 }
46
47 #define RES_INST_IF_NOT_MD \
48 if (!(cpu->cd.sh.sr & SH_SR_MD)) { \
49 SYNCH_PC; \
50 sh_exception(cpu, EXPEVT_RES_INST, 0, 0); \
51 return; \
52 }
53
54 #define FLOATING_POINT_AVAILABLE_CHECK \
55 if (cpu->cd.sh.sr & SH_SR_FD) { \
56 /* FPU disabled: Cause exception. */ \
57 SYNCH_PC; \
58 if (cpu->delay_slot) \
59 sh_exception(cpu, EXPEVT_FPU_SLOT_DISABLE, 0, 0);\
60 else \
61 sh_exception(cpu, EXPEVT_FPU_DISABLE, 0, 0); \
62 return; \
63 }
64
65
66 /*
67 * nop: Nothing
68 */
69 X(nop)
70 {
71 }
72
73
74 /*
75 * sleep: Wait for interrupt
76 */
77 X(sleep)
78 {
79 RES_INST_IF_NOT_MD;
80
81 /*
82 * If there is an interrupt, then just return. Otherwise
83 * re-run the sleep instruction (after a delay).
84 */
85 if (cpu->cd.sh.int_to_assert > 0 && !(cpu->cd.sh.sr & SH_SR_BL)
86 && ((cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT)
87 < cpu->cd.sh.int_level)
88 return;
89
90 cpu->cd.sh.next_ic = ic;
91 cpu->is_halted = 1;
92 cpu->has_been_idling = 1;
93
94 /*
95 * There was no interrupt. Let the host sleep for a while.
96 *
97 * TODO:
98 *
99 * Think about how to actually implement this usleep stuff,
100 * in an SMP and/or timing accurate environment.
101 */
102
103 if (cpu->machine->ncpus == 1) {
104 static int x = 0;
105 if ((++x) == 600) {
106 usleep(10);
107 x = 0;
108 }
109 cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
110 }
111 }
112
113
114 /*
115 * sett: t = 1
116 * sets: s = 1
117 * clrt: t = 1
118 * clrs: s = 1
119 * movt_rn: rn = t
120 * clrmac: mach = macl = 0
121 *
122 * arg[1] = ptr to rn
123 */
124 X(sett) { cpu->cd.sh.sr |= SH_SR_T; }
125 X(sets) { cpu->cd.sh.sr |= SH_SR_S; }
126 X(clrt) { cpu->cd.sh.sr &= ~SH_SR_T; }
127 X(clrs) { cpu->cd.sh.sr &= ~SH_SR_S; }
128 X(movt_rn) { reg(ic->arg[1]) = cpu->cd.sh.sr & SH_SR_T? 1 : 0; }
129 X(clrmac) { cpu->cd.sh.macl = cpu->cd.sh.mach = 0; }
130
131
132 /*
133 * mov_rm_rn: rn = rm
134 * neg_rm_rn: rn = -rm
135 * negc_rm_rn: rn = -rm - t, t = borrow
136 * not_rm_rn: rn = ~rm
137 * swap_b_rm_rn: rn = rm with lowest 2 bytes swapped
138 * swap_w_rm_rn: rn = rm with high and low 16-bit words swapped
139 * exts_b_rm_rn: rn = (int8_t) rm
140 * extu_b_rm_rn: rn = (uint8_t) rm
141 * exts_w_rm_rn: rn = (int16_t) rm
142 * extu_w_rm_rn: rn = (uint16_t) rm
143 *
144 * arg[0] = ptr to rm
145 * arg[1] = ptr to rn
146 */
147 X(mov_rm_rn) { reg(ic->arg[1]) = reg(ic->arg[0]); }
148 X(not_rm_rn) { reg(ic->arg[1]) = ~reg(ic->arg[0]); }
149 X(neg_rm_rn) { reg(ic->arg[1]) = -reg(ic->arg[0]); }
150 X(negc_rm_rn)
151 {
152 uint64_t res = 0;
153 res -= (uint64_t) reg(ic->arg[0]);
154 if (cpu->cd.sh.sr & SH_SR_T)
155 res --;
156 if ((res >> 32) & 1)
157 cpu->cd.sh.sr |= SH_SR_T;
158 else
159 cpu->cd.sh.sr &= ~SH_SR_T;
160 reg(ic->arg[1]) = (uint32_t) res;
161 }
162 X(swap_b_rm_rn)
163 {
164 uint32_t r = reg(ic->arg[0]);
165 reg(ic->arg[1]) = (r & 0xffff0000) | ((r >> 8)&0xff) | ((r&0xff) << 8);
166 }
167 X(swap_w_rm_rn)
168 {
169 uint32_t r = reg(ic->arg[0]);
170 reg(ic->arg[1]) = (r >> 16) | (r << 16);
171 }
172 X(exts_b_rm_rn) { reg(ic->arg[1]) = (int8_t)reg(ic->arg[0]); }
173 X(extu_b_rm_rn) { reg(ic->arg[1]) = (uint8_t)reg(ic->arg[0]); }
174 X(exts_w_rm_rn) { reg(ic->arg[1]) = (int16_t)reg(ic->arg[0]); }
175 X(extu_w_rm_rn) { reg(ic->arg[1]) = (uint16_t)reg(ic->arg[0]); }
176 /* Note: rm and rn are the same on these: */
177 X(extu_b_rm) { reg(ic->arg[1]) = (uint8_t)reg(ic->arg[1]); }
178 X(extu_w_rm) { reg(ic->arg[1]) = (uint16_t)reg(ic->arg[1]); }
179
180
181 /*
182 * and_imm_r0: r0 &= imm
183 * xor_imm_r0: r0 ^= imm
184 * tst_imm_r0: t = (r0 & imm) == 0
185 * or_imm_r0: r0 |= imm
186 *
187 * arg[0] = imm
188 */
189 X(and_imm_r0) { cpu->cd.sh.r[0] &= ic->arg[0]; }
190 X(xor_imm_r0) { cpu->cd.sh.r[0] ^= ic->arg[0]; }
191 X(or_imm_r0) { cpu->cd.sh.r[0] |= ic->arg[0]; }
192 X(tst_imm_r0)
193 {
194 if (cpu->cd.sh.r[0] & ic->arg[0])
195 cpu->cd.sh.sr &= ~SH_SR_T;
196 else
197 cpu->cd.sh.sr |= SH_SR_T;
198 }
199
200
201 /*
202 * xor_b_imm_r0_gbr: mem[r0+gbr] |= imm
203 * or_b_imm_r0_gbr: mem[r0+gbr] ^= imm
204 * and_b_imm_r0_gbr: mem[r0+gbr] &= imm
205 *
206 * arg[0] = imm
207 */
208 X(xor_b_imm_r0_gbr)
209 {
210 uint32_t addr = cpu->cd.sh.gbr + cpu->cd.sh.r[0];
211 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
212
213 if (p != NULL) {
214 p[addr & 0xfff] ^= ic->arg[0];
215 } else {
216 uint8_t data;
217 SYNCH_PC;
218 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
219 sizeof(data), MEM_READ, CACHE_DATA)) {
220 /* Exception. */
221 return;
222 }
223 data ^= ic->arg[0];
224 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
225 sizeof(data), MEM_WRITE, CACHE_DATA)) {
226 /* Exception. */
227 return;
228 }
229 }
230 }
231 X(or_b_imm_r0_gbr)
232 {
233 uint32_t addr = cpu->cd.sh.gbr + cpu->cd.sh.r[0];
234 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
235
236 if (p != NULL) {
237 p[addr & 0xfff] |= ic->arg[0];
238 } else {
239 uint8_t data;
240 SYNCH_PC;
241 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
242 sizeof(data), MEM_READ, CACHE_DATA)) {
243 /* Exception. */
244 return;
245 }
246 data |= ic->arg[0];
247 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
248 sizeof(data), MEM_WRITE, CACHE_DATA)) {
249 /* Exception. */
250 return;
251 }
252 }
253 }
254 X(and_b_imm_r0_gbr)
255 {
256 uint32_t addr = cpu->cd.sh.gbr + cpu->cd.sh.r[0];
257 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
258
259 if (p != NULL) {
260 p[addr & 0xfff] &= ic->arg[0];
261 } else {
262 uint8_t data;
263 SYNCH_PC;
264 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
265 sizeof(data), MEM_READ, CACHE_DATA)) {
266 /* Exception. */
267 return;
268 }
269 data &= ic->arg[0];
270 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
271 sizeof(data), MEM_WRITE, CACHE_DATA)) {
272 /* Exception. */
273 return;
274 }
275 }
276 }
277
278
279 /*
280 * mov_imm_rn: Set rn to a signed 8-bit value
281 * add_imm_rn: Add a signed 8-bit value to Rn
282 *
283 * arg[0] = int8_t imm, extended to at least int32_t
284 * arg[1] = ptr to rn
285 */
286 X(mov_imm_rn) { reg(ic->arg[1]) = ic->arg[0]; }
287 X(mov_0_rn) { reg(ic->arg[1]) = 0; }
288 X(add_imm_rn) { reg(ic->arg[1]) += ic->arg[0]; }
289 X(inc_rn) { reg(ic->arg[1]) ++; }
290 X(add_4_rn) { reg(ic->arg[1]) += 4; }
291 X(sub_4_rn) { reg(ic->arg[1]) -= 4; }
292 X(dec_rn) { reg(ic->arg[1]) --; }
293
294
295 /*
296 * mov_b_rm_predec_rn: mov.b reg,@-Rn
297 * mov_w_rm_predec_rn: mov.w reg,@-Rn
298 * mov_l_rm_predec_rn: mov.l reg,@-Rn
299 * stc_l_rm_predec_rn_md: mov.l reg,@-Rn, with MD status bit check
300 *
301 * arg[0] = ptr to rm (or other register)
302 * arg[1] = ptr to rn
303 */
304 X(mov_b_rm_predec_rn)
305 {
306 uint32_t addr = reg(ic->arg[1]) - sizeof(uint8_t);
307 int8_t *p = (int8_t *) cpu->cd.sh.host_store[addr >> 12];
308 int8_t data = reg(ic->arg[0]);
309 if (p != NULL) {
310 p[addr & 0xfff] = data;
311 reg(ic->arg[1]) = addr;
312 } else {
313 SYNCH_PC;
314 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
315 sizeof(data), MEM_WRITE, CACHE_DATA)) {
316 /* Exception. */
317 return;
318 }
319 /* The store was ok: */
320 reg(ic->arg[1]) = addr;
321 }
322 }
323 X(mov_w_rm_predec_rn)
324 {
325 uint32_t addr = reg(ic->arg[1]) - sizeof(uint16_t);
326 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
327 uint16_t data = reg(ic->arg[0]);
328
329 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
330 data = LE16_TO_HOST(data);
331 else
332 data = BE16_TO_HOST(data);
333
334 if (p != NULL) {
335 p[(addr & 0xfff) >> 1] = data;
336 reg(ic->arg[1]) = addr;
337 } else {
338 SYNCH_PC;
339 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
340 sizeof(data), MEM_WRITE, CACHE_DATA)) {
341 /* Exception. */
342 return;
343 }
344 /* The store was ok: */
345 reg(ic->arg[1]) = addr;
346 }
347 }
348 X(mov_l_rm_predec_rn)
349 {
350 uint32_t addr = reg(ic->arg[1]) - sizeof(uint32_t);
351 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
352 uint32_t data = reg(ic->arg[0]);
353
354 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
355 data = LE32_TO_HOST(data);
356 else
357 data = BE32_TO_HOST(data);
358
359 if (p != NULL) {
360 p[(addr & 0xfff) >> 2] = data;
361 reg(ic->arg[1]) = addr;
362 } else {
363 SYNCH_PC;
364 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
365 sizeof(data), MEM_WRITE, CACHE_DATA)) {
366 /* Exception. */
367 return;
368 }
369 /* The store was ok: */
370 reg(ic->arg[1]) = addr;
371 }
372 }
373 X(stc_l_rm_predec_rn_md)
374 {
375 uint32_t addr = reg(ic->arg[1]) - sizeof(uint32_t);
376 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
377 uint32_t data = reg(ic->arg[0]);
378
379 RES_INST_IF_NOT_MD;
380
381 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
382 data = LE32_TO_HOST(data);
383 else
384 data = BE32_TO_HOST(data);
385
386 if (p != NULL) {
387 p[(addr & 0xfff) >> 2] = data;
388 reg(ic->arg[1]) = addr;
389 } else {
390 SYNCH_PC;
391 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
392 sizeof(data), MEM_WRITE, CACHE_DATA)) {
393 /* Exception. */
394 return;
395 }
396 /* The store was ok: */
397 reg(ic->arg[1]) = addr;
398 }
399 }
400
401
402 /*
403 * mov_l_disp_pc_rn: Load a 32-bit value into a register,
404 * from an immediate address relative to the pc.
405 *
406 * arg[0] = offset from beginning of the current pc's page
407 * arg[1] = ptr to rn
408 */
409 X(mov_l_disp_pc_rn)
410 {
411 uint32_t addr = ic->arg[0] + (cpu->pc &
412 ~((SH_IC_ENTRIES_PER_PAGE-1) << SH_INSTR_ALIGNMENT_SHIFT));
413 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
414 uint32_t data;
415
416 if (p != NULL) {
417 data = p[(addr & 0xfff) >> 2];
418 } else {
419 SYNCH_PC;
420 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
421 sizeof(data), MEM_READ, CACHE_DATA)) {
422 /* Exception. */
423 return;
424 }
425 }
426 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
427 data = LE32_TO_HOST(data);
428 else
429 data = BE32_TO_HOST(data);
430 reg(ic->arg[1]) = data;
431 }
432
433
434 /*
435 * mova_r0: Set r0 to an address close to the program counter.
436 *
437 * arg[0] = relative offset from beginning of the current pc's page
438 */
439 X(mova_r0)
440 {
441 cpu->cd.sh.r[0] = ic->arg[0] + (cpu->pc &
442 ~((SH_IC_ENTRIES_PER_PAGE-1) << SH_INSTR_ALIGNMENT_SHIFT));
443 }
444
445
446 /*
447 * mov_w_disp_pc_rn: Load a 16-bit value into a register,
448 * from an immediate address relative to the pc.
449 *
450 * arg[0] = offset from beginning of the current pc's page
451 * arg[1] = ptr to rn
452 */
453 X(mov_w_disp_pc_rn)
454 {
455 uint32_t addr = ic->arg[0] + (cpu->pc &
456 ~((SH_IC_ENTRIES_PER_PAGE-1) << SH_INSTR_ALIGNMENT_SHIFT));
457 uint16_t *p = (uint16_t *) cpu->cd.sh.host_load[addr >> 12];
458 uint16_t data;
459
460 if (p != NULL) {
461 data = p[(addr & 0xfff) >> 1];
462 } else {
463 SYNCH_PC;
464 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
465 sizeof(data), MEM_READ, CACHE_DATA)) {
466 /* Exception. */
467 return;
468 }
469 }
470
471 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
472 data = LE16_TO_HOST(data);
473 else
474 data = BE16_TO_HOST(data);
475
476 reg(ic->arg[1]) = (int16_t)data;
477 }
478
479
480 /*
481 * load_b_rm_rn: Load an int8_t value into Rn from address Rm.
482 * load_w_rm_rn: Load an int16_t value into Rn from address Rm.
483 * load_l_rm_rn: Load a 32-bit value into Rn from address Rm.
484 * fmov_rm_frn: Load a floating point value into FRn from address Rm.
485 * fmov_r0_rm_frn: Load a floating point value into FRn from address R0+Rm.
486 * fmov_rm_postinc_frn: Load a floating point value into FRn from address Rm.
487 * mov_b_r0_rm_rn: Load an int8_t value into Rn from address Rm + R0.
488 * mov_w_r0_rm_rn: Load an int16_t value into Rn from address Rm + R0.
489 * mov_l_r0_rm_rn: Load a 32-bit value into Rn from address Rm + R0.
490 * mov_l_disp_rm_rn: Load a 32-bit value into Rn from address Rm + disp.
491 * mov_b_disp_rn_r0: Load an int8_t from Rn+disp into R0.
492 * mov_w_disp_rn_r0: Load an int16_t from Rn+disp into R0.
493 * mov_b_disp_gbr_r0: Load an int8_t from GBR+disp into R0.
494 * mov_w_disp_gbr_r0: Load an int16_t from GBR+disp into R0.
495 * mov_l_disp_gbr_r0: Load an int32_t from GBR+disp into R0.
496 * mov_b_arg1_postinc_to_arg0:
497 * mov_w_arg1_postinc_to_arg0:
498 * mov_l_arg1_postinc_to_arg0:
499 * mov_l_arg1_postinc_to_arg0_md: With MD (privilege level) check.
500 * mov_l_arg1_postinc_to_arg0_fp: With FP check.
501 *
502 * arg[0] = ptr to rm (or rm + (lo4 << 4) for disp)
503 * arg[1] = ptr to rn
504 */
505 X(load_b_rm_rn)
506 {
507 uint32_t addr = reg(ic->arg[0]);
508 uint8_t *p = (uint8_t *) cpu->cd.sh.host_load[addr >> 12];
509 uint8_t data;
510
511 if (p != NULL) {
512 data = p[addr & 0xfff];
513 } else {
514 SYNCH_PC;
515 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
516 sizeof(data), MEM_READ, CACHE_DATA)) {
517 /* Exception. */
518 return;
519 }
520 }
521 reg(ic->arg[1]) = (int8_t) data;
522 }
523 X(load_w_rm_rn)
524 {
525 uint32_t addr = reg(ic->arg[0]);
526 int16_t *p = (int16_t *) cpu->cd.sh.host_load[addr >> 12];
527 int16_t data;
528
529 if (p != NULL) {
530 data = p[(addr & 0xfff) >> 1];
531 } else {
532 SYNCH_PC;
533 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
534 sizeof(data), MEM_READ, CACHE_DATA)) {
535 /* Exception. */
536 return;
537 }
538 }
539 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
540 data = LE16_TO_HOST(data);
541 else
542 data = BE16_TO_HOST(data);
543 reg(ic->arg[1]) = data;
544 }
545 X(load_l_rm_rn)
546 {
547 uint32_t addr = reg(ic->arg[0]);
548 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
549 uint32_t data;
550
551 if (p != NULL) {
552 data = p[(addr & 0xfff) >> 2];
553 } else {
554 SYNCH_PC;
555 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
556 sizeof(data), MEM_READ, CACHE_DATA)) {
557 /* Exception. */
558 return;
559 }
560 }
561
562 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
563 data = LE32_TO_HOST(data);
564 else
565 data = BE32_TO_HOST(data);
566 reg(ic->arg[1]) = data;
567 }
568 X(fmov_rm_frn)
569 {
570 uint32_t addr = reg(ic->arg[0]);
571 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
572 uint32_t data;
573
574 FLOATING_POINT_AVAILABLE_CHECK;
575
576 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
577 fatal("fmov_rm_frn: sz=1 (register pair): TODO\n");
578 exit(1);
579 }
580
581 if (p != NULL) {
582 data = p[(addr & 0xfff) >> 2];
583 } else {
584 SYNCH_PC;
585 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
586 sizeof(data), MEM_READ, CACHE_DATA)) {
587 /* Exception. */
588 return;
589 }
590 }
591
592 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
593 data = LE32_TO_HOST(data);
594 else
595 data = BE32_TO_HOST(data);
596
597 reg(ic->arg[1]) = data;
598 }
599 X(fmov_r0_rm_frn)
600 {
601 uint32_t data, addr = reg(ic->arg[0]) + cpu->cd.sh.r[0];
602 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
603
604 FLOATING_POINT_AVAILABLE_CHECK;
605
606 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
607 fatal("fmov_rm_frn: sz=1 (register pair): TODO\n");
608 exit(1);
609 }
610
611 if (p != NULL) {
612 data = p[(addr & 0xfff) >> 2];
613 } else {
614 SYNCH_PC;
615 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
616 sizeof(data), MEM_READ, CACHE_DATA)) {
617 /* Exception. */
618 return;
619 }
620 }
621
622 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
623 data = LE32_TO_HOST(data);
624 else
625 data = BE32_TO_HOST(data);
626
627 reg(ic->arg[1]) = data;
628 }
629 X(fmov_rm_postinc_frn)
630 {
631 int d = cpu->cd.sh.fpscr & SH_FPSCR_SZ;
632 uint32_t data, data2, addr = reg(ic->arg[0]);
633 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
634 size_t r1 = ic->arg[1];
635
636 if (d) {
637 /* xd instead of dr? */
638 int ofs = (r1 - (size_t)&cpu->cd.sh.fr[0]) / sizeof(uint32_t);
639 if (ofs & 1)
640 r1 = (size_t)&cpu->cd.sh.xf[ofs & ~1];
641 }
642
643 FLOATING_POINT_AVAILABLE_CHECK;
644
645 if (p != NULL) {
646 data = p[(addr & 0xfff) >> 2];
647 } else {
648 SYNCH_PC;
649 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
650 sizeof(data), MEM_READ, CACHE_DATA)) {
651 /* Exception. */
652 return;
653 }
654 }
655
656 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
657 data = LE32_TO_HOST(data);
658 else
659 data = BE32_TO_HOST(data);
660
661 if (d) {
662 /* Double-precision load: */
663 addr += 4;
664 SYNCH_PC;
665 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned
666 char *)&data2, sizeof(data2), MEM_READ, CACHE_DATA))
667 return;
668
669 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
670 data2 = LE32_TO_HOST(data2);
671 else
672 data2 = BE32_TO_HOST(data2);
673 reg(r1 + 4) = data2;
674 }
675
676 reg(r1) = data;
677 reg(ic->arg[0]) = addr + sizeof(uint32_t);
678 }
679 X(mov_b_disp_gbr_r0)
680 {
681 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
682 int8_t *p = (int8_t *) cpu->cd.sh.host_load[addr >> 12];
683 int8_t data;
684 if (p != NULL) {
685 data = p[addr & 0xfff];
686 } else {
687 SYNCH_PC;
688 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
689 sizeof(data), MEM_READ, CACHE_DATA)) {
690 /* Exception. */
691 return;
692 }
693 }
694 cpu->cd.sh.r[0] = data;
695 }
696 X(mov_w_disp_gbr_r0)
697 {
698 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
699 int16_t *p = (int16_t *) cpu->cd.sh.host_load[addr >> 12];
700 int16_t data;
701 if (p != NULL) {
702 data = p[(addr & 0xfff) >> 1];
703 } else {
704 SYNCH_PC;
705 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
706 sizeof(data), MEM_READ, CACHE_DATA)) {
707 /* Exception. */
708 return;
709 }
710 }
711 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
712 data = LE16_TO_HOST(data);
713 else
714 data = BE16_TO_HOST(data);
715 cpu->cd.sh.r[0] = data;
716 }
717 X(mov_l_disp_gbr_r0)
718 {
719 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
720 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
721 uint32_t data;
722 if (p != NULL) {
723 data = p[(addr & 0xfff) >> 2];
724 } else {
725 SYNCH_PC;
726 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
727 sizeof(data), MEM_READ, CACHE_DATA)) {
728 /* Exception. */
729 return;
730 }
731 }
732 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
733 data = LE32_TO_HOST(data);
734 else
735 data = BE32_TO_HOST(data);
736 cpu->cd.sh.r[0] = data;
737 }
738 X(mov_b_arg1_postinc_to_arg0)
739 {
740 uint32_t addr = reg(ic->arg[1]);
741 int8_t *p = (int8_t *) cpu->cd.sh.host_load[addr >> 12];
742 int8_t data;
743 if (p != NULL) {
744 data = p[addr & 0xfff];
745 } else {
746 SYNCH_PC;
747 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
748 sizeof(data), MEM_READ, CACHE_DATA)) {
749 /* Exception. */
750 return;
751 }
752 }
753 /* The load was ok: */
754 reg(ic->arg[1]) = addr + sizeof(int8_t);
755 reg(ic->arg[0]) = data;
756 }
757 X(mov_w_arg1_postinc_to_arg0)
758 {
759 uint32_t addr = reg(ic->arg[1]);
760 uint16_t *p = (uint16_t *) cpu->cd.sh.host_load[addr >> 12];
761 uint16_t data;
762
763 if (p != NULL) {
764 data = p[(addr & 0xfff) >> 1];
765 } else {
766 SYNCH_PC;
767 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
768 sizeof(data), MEM_READ, CACHE_DATA)) {
769 /* Exception. */
770 return;
771 }
772 }
773
774 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
775 data = LE16_TO_HOST(data);
776 else
777 data = BE16_TO_HOST(data);
778 reg(ic->arg[1]) = addr + sizeof(data);
779 reg(ic->arg[0]) = (int16_t)data;
780 }
781 X(mov_l_arg1_postinc_to_arg0)
782 {
783 uint32_t addr = reg(ic->arg[1]);
784 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
785 uint32_t data;
786
787 if (p != NULL) {
788 data = p[(addr & 0xfff) >> 2];
789 } else {
790 SYNCH_PC;
791 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
792 sizeof(data), MEM_READ, CACHE_DATA)) {
793 /* Exception. */
794 return;
795 }
796 }
797 /* The load was ok: */
798 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
799 data = LE32_TO_HOST(data);
800 else
801 data = BE32_TO_HOST(data);
802 reg(ic->arg[1]) = addr + sizeof(data);
803 reg(ic->arg[0]) = data;
804 }
805 X(mov_l_arg1_postinc_to_arg0_md)
806 {
807 uint32_t addr = reg(ic->arg[1]);
808 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
809 uint32_t data;
810
811 RES_INST_IF_NOT_MD;
812
813 if (p != NULL) {
814 data = p[(addr & 0xfff) >> 2];
815 } else {
816 SYNCH_PC;
817 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
818 sizeof(data), MEM_READ, CACHE_DATA)) {
819 /* Exception. */
820 return;
821 }
822 }
823 /* The load was ok: */
824 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
825 data = LE32_TO_HOST(data);
826 else
827 data = BE32_TO_HOST(data);
828 reg(ic->arg[1]) = addr + sizeof(data);
829
830 /* Special case when loading into the SR register: */
831 if (ic->arg[0] == (size_t)&cpu->cd.sh.sr)
832 sh_update_sr(cpu, data);
833 else
834 reg(ic->arg[0]) = data;
835 }
836 X(mov_l_arg1_postinc_to_arg0_fp)
837 {
838 uint32_t addr = reg(ic->arg[1]);
839 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
840 uint32_t data;
841
842 FLOATING_POINT_AVAILABLE_CHECK;
843
844 if (p != NULL) {
845 data = p[(addr & 0xfff) >> 2];
846 } else {
847 SYNCH_PC;
848 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
849 sizeof(data), MEM_READ, CACHE_DATA)) {
850 /* Exception. */
851 return;
852 }
853 }
854 /* The load was ok: */
855 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
856 data = LE32_TO_HOST(data);
857 else
858 data = BE32_TO_HOST(data);
859 reg(ic->arg[1]) = addr + sizeof(data);
860
861 /* Ugly special case for FPSCR: */
862 if (ic->arg[0] == (size_t)&cpu->cd.sh.fpscr)
863 sh_update_fpscr(cpu, data);
864 else
865 reg(ic->arg[0]) = data;
866 }
867 X(mov_b_r0_rm_rn)
868 {
869 uint32_t addr = reg(ic->arg[0]) + cpu->cd.sh.r[0];
870 int8_t *p = (int8_t *) cpu->cd.sh.host_load[addr >> 12];
871 int8_t data;
872
873 if (p != NULL) {
874 data = p[addr & 0xfff];
875 } else {
876 SYNCH_PC;
877 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
878 sizeof(data), MEM_READ, CACHE_DATA)) {
879 /* Exception. */
880 return;
881 }
882 }
883
884 reg(ic->arg[1]) = data;
885 }
886 X(mov_w_r0_rm_rn)
887 {
888 uint32_t addr = reg(ic->arg[0]) + cpu->cd.sh.r[0];
889 int16_t *p = (int16_t *) cpu->cd.sh.host_load[addr >> 12];
890 int16_t data;
891
892 if (p != NULL) {
893 data = p[(addr & 0xfff) >> 1];
894 } else {
895 SYNCH_PC;
896 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
897 sizeof(data), MEM_READ, CACHE_DATA)) {
898 /* Exception. */
899 return;
900 }
901 }
902
903 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
904 data = LE16_TO_HOST(data);
905 else
906 data = BE16_TO_HOST(data);
907 reg(ic->arg[1]) = data;
908 }
909 X(mov_l_r0_rm_rn)
910 {
911 uint32_t addr = reg(ic->arg[0]) + cpu->cd.sh.r[0];
912 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
913 uint32_t data;
914
915 if (p != NULL) {
916 data = p[(addr & 0xfff) >> 2];
917 } else {
918 SYNCH_PC;
919 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
920 sizeof(data), MEM_READ, CACHE_DATA)) {
921 /* Exception. */
922 return;
923 }
924 }
925
926 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
927 data = LE32_TO_HOST(data);
928 else
929 data = BE32_TO_HOST(data);
930 reg(ic->arg[1]) = data;
931 }
932 X(mov_l_disp_rm_rn)
933 {
934 uint32_t addr = cpu->cd.sh.r[ic->arg[0] & 0xf] +
935 ((ic->arg[0] >> 4) << 2);
936 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
937 uint32_t data;
938
939 if (p != NULL) {
940 data = p[(addr & 0xfff) >> 2];
941 } else {
942 SYNCH_PC;
943 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
944 sizeof(data), MEM_READ, CACHE_DATA)) {
945 /* Exception. */
946 return;
947 }
948 }
949
950 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
951 data = LE32_TO_HOST(data);
952 else
953 data = BE32_TO_HOST(data);
954 reg(ic->arg[1]) = data;
955 }
956 X(mov_b_disp_rn_r0)
957 {
958 uint32_t addr = reg(ic->arg[0]) + ic->arg[1];
959 uint8_t *p = (uint8_t *) cpu->cd.sh.host_load[addr >> 12];
960 uint8_t data;
961
962 if (p != NULL) {
963 data = p[addr & 0xfff];
964 } else {
965 SYNCH_PC;
966 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
967 sizeof(data), MEM_READ, CACHE_DATA)) {
968 /* Exception. */
969 return;
970 }
971 }
972
973 cpu->cd.sh.r[0] = (int8_t) data;
974 }
975 X(mov_w_disp_rn_r0)
976 {
977 uint32_t addr = reg(ic->arg[0]) + ic->arg[1];
978 uint16_t *p = (uint16_t *) cpu->cd.sh.host_load[addr >> 12];
979 uint16_t data;
980
981 if (p != NULL) {
982 data = p[(addr & 0xfff) >> 1];
983 } else {
984 SYNCH_PC;
985 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
986 sizeof(data), MEM_READ, CACHE_DATA)) {
987 /* Exception. */
988 return;
989 }
990 }
991
992 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
993 data = LE16_TO_HOST(data);
994 else
995 data = BE16_TO_HOST(data);
996 cpu->cd.sh.r[0] = (int16_t) data;
997 }
998
999
1000 /*
1001 * mov_b_store_rm_rn: Store Rm to address Rn (8-bit).
1002 * mov_w_store_rm_rn: Store Rm to address Rn (16-bit).
1003 * mov_l_store_rm_rn: Store Rm to address Rn (32-bit).
1004 * fmov_frm_rn: Store FRm to address Rn.
1005 * fmov_frm_r0_rn: Store FRm to address R0 + Rn.
1006 * fmov_frm_predec_rn: Store FRm to address Rn - 4 (or 8), update Rn.
1007 * mov_b_rm_r0_rn: Store Rm to address Rn + R0 (8-bit).
1008 * mov_w_rm_r0_rn: Store Rm to address Rn + R0 (16-bit).
1009 * mov_l_rm_r0_rn: Store Rm to address Rn + R0 (32-bit).
1010 * mov_b_r0_disp_gbr: Store R0 to address disp + GBR (8-bit).
1011 * mov_w_r0_disp_gbr: Store R0 to address disp + GBR (16-bit).
1012 * mov_l_r0_disp_gbr: Store R0 to address disp + GBR (32-bit).
1013 * mov_l_rm_disp_rn: Store Rm to address disp + Rn.
1014 * mov_b_r0_disp_rn: Store R0 to address disp + Rn (8-bit).
1015 * mov_w_r0_disp_rn: Store R0 to address disp + Rn (16-bit).
1016 *
1017 * arg[0] = ptr to rm
1018 * arg[1] = ptr to rn (or Rn+(disp<<4) for mov_l_rm_disp_rn)
1019 * (or disp for mov_*_r0_disp_gbr)
1020 */
1021 X(mov_b_store_rm_rn)
1022 {
1023 uint32_t addr = reg(ic->arg[1]);
1024 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
1025 uint8_t data = reg(ic->arg[0]);
1026
1027 if (p != NULL) {
1028 p[addr & 0xfff] = data;
1029 } else {
1030 SYNCH_PC;
1031 if (!cpu->memory_rw(cpu, cpu->mem, addr, &data,
1032 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1033 /* Exception. */
1034 return;
1035 }
1036 }
1037 }
1038 X(mov_w_store_rm_rn)
1039 {
1040 uint32_t addr = reg(ic->arg[1]);
1041 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
1042 uint16_t data = reg(ic->arg[0]);
1043
1044 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1045 data = LE16_TO_HOST(data);
1046 else
1047 data = BE16_TO_HOST(data);
1048
1049 if (p != NULL) {
1050 p[(addr & 0xfff) >> 1] = data;
1051 } else {
1052 SYNCH_PC;
1053 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1054 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1055 /* Exception. */
1056 return;
1057 }
1058 }
1059 }
1060 X(mov_l_store_rm_rn)
1061 {
1062 uint32_t addr = reg(ic->arg[1]);
1063 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1064 uint32_t data = reg(ic->arg[0]);
1065
1066 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1067 data = LE32_TO_HOST(data);
1068 else
1069 data = BE32_TO_HOST(data);
1070
1071 if (p != NULL) {
1072 p[(addr & 0xfff) >> 2] = data;
1073 } else {
1074 SYNCH_PC;
1075 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1076 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1077 /* Exception. */
1078 return;
1079 }
1080 }
1081 }
1082 X(fmov_frm_rn)
1083 {
1084 uint32_t addr = reg(ic->arg[1]);
1085 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1086 uint32_t data = reg(ic->arg[0]);
1087
1088 FLOATING_POINT_AVAILABLE_CHECK;
1089
1090 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1091 fatal("fmov_frm_rn: sz=1 (register pair): TODO\n");
1092 exit(1);
1093 }
1094
1095 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1096 data = LE32_TO_HOST(data);
1097 else
1098 data = BE32_TO_HOST(data);
1099
1100 if (p != NULL) {
1101 p[(addr & 0xfff) >> 2] = data;
1102 } else {
1103 SYNCH_PC;
1104 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1105 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1106 /* Exception. */
1107 return;
1108 }
1109 }
1110 }
1111 X(fmov_frm_r0_rn)
1112 {
1113 uint32_t addr = reg(ic->arg[1]) + cpu->cd.sh.r[0];
1114 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1115 uint32_t data = reg(ic->arg[0]);
1116
1117 FLOATING_POINT_AVAILABLE_CHECK;
1118
1119 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1120 fatal("fmov_frm_r0_rn: sz=1 (register pair): TODO\n");
1121 exit(1);
1122 }
1123
1124 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1125 data = LE32_TO_HOST(data);
1126 else
1127 data = BE32_TO_HOST(data);
1128
1129 if (p != NULL) {
1130 p[(addr & 0xfff) >> 2] = data;
1131 } else {
1132 SYNCH_PC;
1133 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1134 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1135 /* Exception. */
1136 return;
1137 }
1138 }
1139 }
1140 X(fmov_frm_predec_rn)
1141 {
1142 int d = cpu->cd.sh.fpscr & SH_FPSCR_SZ? 1 : 0;
1143 uint32_t data, addr = reg(ic->arg[1]) - (d? 8 : 4);
1144 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1145 size_t r0 = ic->arg[0];
1146
1147 if (d) {
1148 /* xd instead of dr? */
1149 int ofs0 = (r0 - (size_t)&cpu->cd.sh.fr[0]) / sizeof(uint32_t);
1150 if (ofs0 & 1)
1151 r0 = (size_t)&cpu->cd.sh.xf[ofs0 & ~1];
1152 }
1153
1154 data = reg(r0);
1155
1156 FLOATING_POINT_AVAILABLE_CHECK;
1157
1158 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1159 data = LE32_TO_HOST(data);
1160 else
1161 data = BE32_TO_HOST(data);
1162
1163 if (p != NULL) {
1164 p[(addr & 0xfff) >> 2] = data;
1165 } else {
1166 SYNCH_PC;
1167 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1168 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1169 /* Exception. */
1170 return;
1171 }
1172 }
1173
1174 if (d) {
1175 /* Store second single-precision floating point word: */
1176 data = reg(r0 + 4);
1177 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1178 data = LE32_TO_HOST(data);
1179 else
1180 data = BE32_TO_HOST(data);
1181 SYNCH_PC;
1182 if (!cpu->memory_rw(cpu, cpu->mem, addr + 4, (unsigned
1183 char *)&data, sizeof(data), MEM_WRITE, CACHE_DATA))
1184 return;
1185 }
1186
1187 reg(ic->arg[1]) = addr;
1188 }
1189 X(mov_b_rm_r0_rn)
1190 {
1191 uint32_t addr = reg(ic->arg[1]) + cpu->cd.sh.r[0];
1192 int8_t *p = (int8_t *) cpu->cd.sh.host_store[addr >> 12];
1193 int8_t data = reg(ic->arg[0]);
1194 if (p != NULL) {
1195 p[addr & 0xfff] = data;
1196 } else {
1197 SYNCH_PC;
1198 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1199 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1200 /* Exception. */
1201 return;
1202 }
1203 }
1204 }
1205 X(mov_w_rm_r0_rn)
1206 {
1207 uint32_t addr = reg(ic->arg[1]) + cpu->cd.sh.r[0];
1208 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
1209 uint16_t data = reg(ic->arg[0]);
1210
1211 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1212 data = LE16_TO_HOST(data);
1213 else
1214 data = BE16_TO_HOST(data);
1215
1216 if (p != NULL) {
1217 p[(addr & 0xfff) >> 1] = data;
1218 } else {
1219 SYNCH_PC;
1220 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1221 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1222 /* Exception. */
1223 return;
1224 }
1225 }
1226 }
1227 X(mov_l_rm_r0_rn)
1228 {
1229 uint32_t addr = reg(ic->arg[1]) + cpu->cd.sh.r[0];
1230 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1231 uint32_t data = reg(ic->arg[0]);
1232
1233 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1234 data = LE32_TO_HOST(data);
1235 else
1236 data = BE32_TO_HOST(data);
1237
1238 if (p != NULL) {
1239 p[(addr & 0xfff) >> 2] = data;
1240 } else {
1241 SYNCH_PC;
1242 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1243 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1244 /* Exception. */
1245 return;
1246 }
1247 }
1248 }
1249 X(mov_b_r0_disp_gbr)
1250 {
1251 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
1252 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
1253 uint8_t data = cpu->cd.sh.r[0];
1254 if (p != NULL) {
1255 p[addr & 0xfff] = data;
1256 } else {
1257 SYNCH_PC;
1258 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1259 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1260 /* Exception. */
1261 return;
1262 }
1263 }
1264 }
1265 X(mov_w_r0_disp_gbr)
1266 {
1267 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
1268 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
1269 uint16_t data = cpu->cd.sh.r[0];
1270
1271 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1272 data = LE16_TO_HOST(data);
1273 else
1274 data = BE16_TO_HOST(data);
1275
1276 if (p != NULL) {
1277 p[(addr & 0xfff) >> 1] = data;
1278 } else {
1279 SYNCH_PC;
1280 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1281 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1282 /* Exception. */
1283 return;
1284 }
1285 }
1286 }
1287 X(mov_l_r0_disp_gbr)
1288 {
1289 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
1290 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1291 uint32_t data = cpu->cd.sh.r[0];
1292
1293 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1294 data = LE32_TO_HOST(data);
1295 else
1296 data = BE32_TO_HOST(data);
1297
1298 if (p != NULL) {
1299 p[(addr & 0xfff) >> 2] = data;
1300 } else {
1301 SYNCH_PC;
1302 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1303 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1304 /* Exception. */
1305 return;
1306 }
1307 }
1308 }
1309 X(mov_l_rm_disp_rn)
1310 {
1311 uint32_t addr = cpu->cd.sh.r[ic->arg[1] & 0xf] +
1312 ((ic->arg[1] >> 4) << 2);
1313 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1314 uint32_t data = reg(ic->arg[0]);
1315
1316 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1317 data = LE32_TO_HOST(data);
1318 else
1319 data = BE32_TO_HOST(data);
1320
1321 if (p != NULL) {
1322 p[(addr & 0xfff) >> 2] = data;
1323 } else {
1324 SYNCH_PC;
1325 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1326 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1327 /* Exception. */
1328 return;
1329 }
1330 }
1331 }
1332 X(mov_b_r0_disp_rn)
1333 {
1334 uint32_t addr = reg(ic->arg[0]) + ic->arg[1];
1335 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
1336 uint8_t data = cpu->cd.sh.r[0];
1337
1338 if (p != NULL) {
1339 p[addr & 0xfff] = data;
1340 } else {
1341 SYNCH_PC;
1342 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1343 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1344 /* Exception. */
1345 return;
1346 }
1347 }
1348 }
1349 X(mov_w_r0_disp_rn)
1350 {
1351 uint32_t addr = reg(ic->arg[0]) + ic->arg[1];
1352 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
1353 uint16_t data = cpu->cd.sh.r[0];
1354
1355 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1356 data = LE16_TO_HOST(data);
1357 else
1358 data = BE16_TO_HOST(data);
1359
1360 if (p != NULL) {
1361 p[(addr & 0xfff) >> 1] = data;
1362 } else {
1363 SYNCH_PC;
1364 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1365 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1366 /* Exception. */
1367 return;
1368 }
1369 }
1370 }
1371
1372
1373 /*
1374 * add_rm_rn: rn = rn + rm
1375 * addc_rm_rn: rn = rn + rm + t
1376 * and_rm_rn: rn = rn & rm
1377 * xor_rm_rn: rn = rn ^ rm
1378 * or_rm_rn: rn = rn | rm
1379 * sub_rm_rn: rn = rn - rm
1380 * subc_rm_rn: rn = rn - rm - t; t = borrow
1381 * tst_rm_rn: t = ((rm & rn) == 0)
1382 * tst_rm: t = (rm == 0)
1383 * xtrct_rm_rn: rn = (rn >> 16) | (rm << 16)
1384 *
1385 * arg[0] = ptr to rm
1386 * arg[1] = ptr to rn
1387 */
1388 X(add_rm_rn) { reg(ic->arg[1]) += reg(ic->arg[0]); }
1389 X(addc_rm_rn)
1390 {
1391 uint64_t res = reg(ic->arg[1]);
1392 res += (uint64_t) reg(ic->arg[0]);
1393 if (cpu->cd.sh.sr & SH_SR_T)
1394 res ++;
1395 if ((res >> 32) & 1)
1396 cpu->cd.sh.sr |= SH_SR_T;
1397 else
1398 cpu->cd.sh.sr &= ~SH_SR_T;
1399 reg(ic->arg[1]) = (uint32_t) res;
1400 }
1401 X(and_rm_rn) { reg(ic->arg[1]) &= reg(ic->arg[0]); }
1402 X(xor_rm_rn) { reg(ic->arg[1]) ^= reg(ic->arg[0]); }
1403 X(or_rm_rn) { reg(ic->arg[1]) |= reg(ic->arg[0]); }
1404 X(sub_rm_rn) { reg(ic->arg[1]) -= reg(ic->arg[0]); }
1405 X(subc_rm_rn)
1406 {
1407 uint64_t res = reg(ic->arg[1]);
1408 res -= (uint64_t) reg(ic->arg[0]);
1409 if (cpu->cd.sh.sr & SH_SR_T)
1410 res --;
1411 if ((res >> 32) & 1)
1412 cpu->cd.sh.sr |= SH_SR_T;
1413 else
1414 cpu->cd.sh.sr &= ~SH_SR_T;
1415 reg(ic->arg[1]) = (uint32_t) res;
1416 }
1417 X(tst_rm_rn)
1418 {
1419 if (reg(ic->arg[1]) & reg(ic->arg[0]))
1420 cpu->cd.sh.sr &= ~SH_SR_T;
1421 else
1422 cpu->cd.sh.sr |= SH_SR_T;
1423 }
1424 X(tst_rm)
1425 {
1426 if (reg(ic->arg[0]))
1427 cpu->cd.sh.sr &= ~SH_SR_T;
1428 else
1429 cpu->cd.sh.sr |= SH_SR_T;
1430 }
1431 X(xtrct_rm_rn)
1432 {
1433 uint32_t rn = reg(ic->arg[1]), rm = reg(ic->arg[0]);
1434 reg(ic->arg[1]) = (rn >> 16) | (rm << 16);
1435 }
1436
1437
1438 /*
1439 * div0u: Division step 0; prepare for unsigned division.
1440 * div0s_rm_rn: Division step 0; prepare for signed division.
1441 * div1_rm_rn: Division step 1.
1442 *
1443 * arg[0] = ptr to rm
1444 * arg[1] = ptr to rn
1445 */
1446 X(div0u)
1447 {
1448 cpu->cd.sh.sr &= ~(SH_SR_Q | SH_SR_M | SH_SR_T);
1449 }
1450 X(div0s_rm_rn)
1451 {
1452 int q = reg(ic->arg[1]) & 0x80000000;
1453 int m = reg(ic->arg[0]) & 0x80000000;
1454 uint32_t new_sr = cpu->cd.sh.sr & ~(SH_SR_Q | SH_SR_M | SH_SR_T);
1455 if (q)
1456 new_sr |= SH_SR_Q;
1457 if (m)
1458 new_sr |= SH_SR_M;
1459 if (m ^ q)
1460 new_sr |= SH_SR_T;
1461 cpu->cd.sh.sr = new_sr;
1462 }
1463 X(div1_rm_rn)
1464 {
1465 uint32_t q, old_q = (cpu->cd.sh.sr & SH_SR_Q)? 1 : 0;
1466 uint32_t m = (cpu->cd.sh.sr & SH_SR_M)? 1 : 0;
1467 uint32_t t = (cpu->cd.sh.sr & SH_SR_T)? 1 : 0;
1468 uint32_t op1 = reg(ic->arg[0]), op2 = reg(ic->arg[1]);
1469 uint64_t op2_64;
1470
1471 q = op2 >> 31;
1472 op2_64 = (uint32_t) ((op2 << 1) + t);
1473 if (old_q == m)
1474 op2_64 -= (uint64_t)op1;
1475 else
1476 op2_64 += (uint64_t)op1;
1477 q ^= m ^ ((op2_64 >> 32) & 1);
1478 t = 1 - (q ^ m);
1479 cpu->cd.sh.sr &= ~(SH_SR_Q | SH_SR_T);
1480 if (q)
1481 cpu->cd.sh.sr |= SH_SR_Q;
1482 if (t)
1483 cpu->cd.sh.sr |= SH_SR_T;
1484 reg(ic->arg[1]) = (uint32_t) op2_64;
1485 }
1486
1487
1488 /*
1489 * mul_l_rm_rn: MACL = Rm * Rn (32-bit)
1490 * muls_w_rm_rn: MACL = Rm * Rn (signed 16-bit * 16-bit ==> 32-bit)
1491 * mulu_w_rm_rn: MACL = Rm * Rn (unsigned 16-bit * 16-bit ==> 32-bit)
1492 * dmuls_l_rm_rn: MACH:MACL = Rm * Rn (signed, 64-bit result)
1493 * dmulu_l_rm_rn: MACH:MACL = Rm * Rn (unsigned, 64-bit result)
1494 *
1495 * arg[0] = ptr to rm
1496 * arg[1] = ptr to rn
1497 */
1498 X(mul_l_rm_rn)
1499 {
1500 cpu->cd.sh.macl = reg(ic->arg[0]) * reg(ic->arg[1]);
1501 }
1502 X(muls_w_rm_rn)
1503 {
1504 cpu->cd.sh.macl = (int32_t)(int16_t)reg(ic->arg[0]) *
1505 (int32_t)(int16_t)reg(ic->arg[1]);
1506 }
1507 X(mulu_w_rm_rn)
1508 {
1509 cpu->cd.sh.macl = (int32_t)(uint16_t)reg(ic->arg[0]) *
1510 (int32_t)(uint16_t)reg(ic->arg[1]);
1511 }
1512 X(dmuls_l_rm_rn)
1513 {
1514 uint64_t rm = (int32_t)reg(ic->arg[0]), rn = (int32_t)reg(ic->arg[1]);
1515 uint64_t res = rm * rn;
1516 cpu->cd.sh.mach = (uint32_t) (res >> 32);
1517 cpu->cd.sh.macl = (uint32_t) res;
1518 }
1519 X(dmulu_l_rm_rn)
1520 {
1521 uint64_t rm = reg(ic->arg[0]), rn = reg(ic->arg[1]), res;
1522 res = rm * rn;
1523 cpu->cd.sh.mach = (uint32_t) (res >> 32);
1524 cpu->cd.sh.macl = (uint32_t) res;
1525 }
1526
1527
1528 /*
1529 * cmpeq_imm_r0: rn == int8_t immediate
1530 * cmpeq_rm_rn: rn == rm
1531 * cmphs_rm_rn: rn >= rm, unsigned
1532 * cmpge_rm_rn: rn >= rm, signed
1533 * cmphi_rm_rn: rn > rm, unsigned
1534 * cmpgt_rm_rn: rn > rm, signed
1535 * cmppz_rn: rn >= 0, signed
1536 * cmppl_rn: rn > 0, signed
1537 * cmp_str_rm_rn: t=1 if any bytes in rm and rn match, 0 otherwise
1538 *
1539 * arg[0] = ptr to rm (or imm, for cmpeq_imm_r0)
1540 * arg[1] = ptr to rn
1541 */
1542 X(cmpeq_imm_r0)
1543 {
1544 if (cpu->cd.sh.r[0] == (uint32_t)ic->arg[0])
1545 cpu->cd.sh.sr |= SH_SR_T;
1546 else
1547 cpu->cd.sh.sr &= ~SH_SR_T;
1548 }
1549 X(cmpeq_rm_rn)
1550 {
1551 if (reg(ic->arg[1]) == reg(ic->arg[0]))
1552 cpu->cd.sh.sr |= SH_SR_T;
1553 else
1554 cpu->cd.sh.sr &= ~SH_SR_T;
1555 }
1556 X(cmphs_rm_rn)
1557 {
1558 if (reg(ic->arg[1]) >= reg(ic->arg[0]))
1559 cpu->cd.sh.sr |= SH_SR_T;
1560 else
1561 cpu->cd.sh.sr &= ~SH_SR_T;
1562 }
1563 X(cmpge_rm_rn)
1564 {
1565 if ((int32_t)reg(ic->arg[1]) >= (int32_t)reg(ic->arg[0]))
1566 cpu->cd.sh.sr |= SH_SR_T;
1567 else
1568 cpu->cd.sh.sr &= ~SH_SR_T;
1569 }
1570 X(cmphi_rm_rn)
1571 {
1572 if (reg(ic->arg[1]) > reg(ic->arg[0]))
1573 cpu->cd.sh.sr |= SH_SR_T;
1574 else
1575 cpu->cd.sh.sr &= ~SH_SR_T;
1576 }
1577 X(cmpgt_rm_rn)
1578 {
1579 if ((int32_t)reg(ic->arg[1]) > (int32_t)reg(ic->arg[0]))
1580 cpu->cd.sh.sr |= SH_SR_T;
1581 else
1582 cpu->cd.sh.sr &= ~SH_SR_T;
1583 }
1584 X(cmppz_rn)
1585 {
1586 if ((int32_t)reg(ic->arg[1]) >= 0)
1587 cpu->cd.sh.sr |= SH_SR_T;
1588 else
1589 cpu->cd.sh.sr &= ~SH_SR_T;
1590 }
1591 X(cmppl_rn)
1592 {
1593 if ((int32_t)reg(ic->arg[1]) > 0)
1594 cpu->cd.sh.sr |= SH_SR_T;
1595 else
1596 cpu->cd.sh.sr &= ~SH_SR_T;
1597 }
1598 X(cmp_str_rm_rn)
1599 {
1600 uint32_t r0 = reg(ic->arg[0]), r1 = reg(ic->arg[1]);
1601 int t = 0;
1602 if ((r0 & 0xff000000) == (r1 & 0xff000000))
1603 t = 1;
1604 else if ((r0 & 0xff0000) == (r1 & 0xff0000))
1605 t = 1;
1606 else if ((r0 & 0xff00) == (r1 & 0xff00))
1607 t = 1;
1608 else if ((r0 & 0xff) == (r1 & 0xff))
1609 t = 1;
1610 if (t)
1611 cpu->cd.sh.sr |= SH_SR_T;
1612 else
1613 cpu->cd.sh.sr &= ~SH_SR_T;
1614 }
1615
1616
1617 /*
1618 * shll_rn: Shift rn left by 1 (t = bit that was shifted out)
1619 * shlr_rn: Shift rn right by 1 (t = bit that was shifted out)
1620 * rotl_rn: Shift rn left by 1 (t = bit that was shifted out)
1621 * rotr_rn: Shift rn right by 1 (t = bit that was shifted out)
1622 * shar_rn: Shift rn right arithmetically by 1 (t = bit that was shifted out)
1623 * shllX_rn: Shift rn left logically by X bits
1624 * shlrX_rn: Shift rn right logically by X bits
1625 * rotcl_rn: Rotate rn left via the t bit
1626 * rotcr_rn: Rotate rn right via the t bit
1627 * dt_rn: Decrease rn; t = (rn == 0)
1628 *
1629 * arg[1] = ptr to rn
1630 */
1631 X(shll_rn)
1632 {
1633 uint32_t rn = reg(ic->arg[1]);
1634 if (rn & 0x80000000)
1635 cpu->cd.sh.sr |= SH_SR_T;
1636 else
1637 cpu->cd.sh.sr &= ~SH_SR_T;
1638 reg(ic->arg[1]) = rn << 1;
1639 }
1640 X(shlr_rn)
1641 {
1642 uint32_t rn = reg(ic->arg[1]);
1643 if (rn & 1)
1644 cpu->cd.sh.sr |= SH_SR_T;
1645 else
1646 cpu->cd.sh.sr &= ~SH_SR_T;
1647 reg(ic->arg[1]) = rn >> 1;
1648 }
1649 X(rotl_rn)
1650 {
1651 uint32_t rn = reg(ic->arg[1]), x;
1652 if (rn & 0x80000000) {
1653 x = 1;
1654 cpu->cd.sh.sr |= SH_SR_T;
1655 } else {
1656 x = 0;
1657 cpu->cd.sh.sr &= ~SH_SR_T;
1658 }
1659 reg(ic->arg[1]) = (rn << 1) | x;
1660 }
1661 X(rotr_rn)
1662 {
1663 uint32_t rn = reg(ic->arg[1]);
1664 if (rn & 1)
1665 cpu->cd.sh.sr |= SH_SR_T;
1666 else
1667 cpu->cd.sh.sr &= ~SH_SR_T;
1668 reg(ic->arg[1]) = (rn >> 1) | (rn << 31);
1669 }
1670 X(shar_rn)
1671 {
1672 int32_t rn = reg(ic->arg[1]);
1673 if (rn & 1)
1674 cpu->cd.sh.sr |= SH_SR_T;
1675 else
1676 cpu->cd.sh.sr &= ~SH_SR_T;
1677 reg(ic->arg[1]) = rn >> 1;
1678 }
1679 X(rotcl_rn)
1680 {
1681 uint32_t rn = reg(ic->arg[1]), top;
1682 top = rn & 0x80000000;
1683 rn <<= 1;
1684 if (cpu->cd.sh.sr & SH_SR_T)
1685 rn ++;
1686 if (top)
1687 cpu->cd.sh.sr |= SH_SR_T;
1688 else
1689 cpu->cd.sh.sr &= ~SH_SR_T;
1690 reg(ic->arg[1]) = rn;
1691 }
1692 X(rotcr_rn)
1693 {
1694 uint32_t rn = reg(ic->arg[1]), bottom;
1695 bottom = rn & 1;
1696 rn >>= 1;
1697 if (cpu->cd.sh.sr & SH_SR_T)
1698 rn |= 0x80000000;
1699 if (bottom)
1700 cpu->cd.sh.sr |= SH_SR_T;
1701 else
1702 cpu->cd.sh.sr &= ~SH_SR_T;
1703 reg(ic->arg[1]) = rn;
1704 }
1705 X(dt_rn)
1706 {
1707 uint32_t rn = reg(ic->arg[1]) - 1;
1708 if (rn == 0)
1709 cpu->cd.sh.sr |= SH_SR_T;
1710 else
1711 cpu->cd.sh.sr &= ~SH_SR_T;
1712 reg(ic->arg[1]) = rn;
1713 }
1714 X(shll2_rn) { reg(ic->arg[1]) <<= 2; }
1715 X(shll8_rn) { reg(ic->arg[1]) <<= 8; }
1716 X(shll16_rn) { reg(ic->arg[1]) <<= 16; }
1717 X(shlr2_rn) { reg(ic->arg[1]) >>= 2; }
1718 X(shlr8_rn) { reg(ic->arg[1]) >>= 8; }
1719 X(shlr16_rn) { reg(ic->arg[1]) >>= 16; }
1720
1721
1722 /*
1723 * shad: Shift Rn arithmetic left/right, as indicated by Rm. Result in Rn.
1724 * shld: Shift Rn logically left/right, as indicated by Rm. Result in Rn.
1725 *
1726 * arg[0] = ptr to rm
1727 * arg[1] = ptr to rn
1728 */
1729 X(shad)
1730 {
1731 int32_t rn = reg(ic->arg[1]);
1732 int32_t rm = reg(ic->arg[0]);
1733 int sa = rm & 0x1f;
1734
1735 if (rm >= 0)
1736 rn <<= sa;
1737 else if (sa != 0)
1738 rn >>= (32 - sa);
1739 else if (rn < 0)
1740 rn = -1;
1741 else
1742 rn = 0;
1743
1744 reg(ic->arg[1]) = rn;
1745 }
1746 X(shld)
1747 {
1748 uint32_t rn = reg(ic->arg[1]);
1749 int32_t rm = reg(ic->arg[0]);
1750 int sa = rm & 0x1f;
1751
1752 if (rm >= 0)
1753 rn <<= sa;
1754 else if (sa != 0)
1755 rn >>= (32 - sa);
1756 else
1757 rn = 0;
1758
1759 reg(ic->arg[1]) = rn;
1760 }
1761
1762
1763 /*
1764 * bra: Branch using PC relative immediace displacement (with delay-slot)
1765 * bsr: Like bra, but also sets PR to the return address
1766 * braf: Like bra, but using a register instead of an immediate
1767 * bsrf: Like braf, but also sets PR to the return address
1768 *
1769 * arg[0] = immediate offset relative to start of page,
1770 * or ptr to target instruction, for samepage branches
1771 * arg[1] = ptr to Rn (for braf/bsrf)
1772 */
1773 X(bra)
1774 {
1775 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1776 SH_INSTR_ALIGNMENT_SHIFT);
1777 target += ic->arg[0];
1778 cpu->delay_slot = TO_BE_DELAYED;
1779 ic[1].f(cpu, ic+1);
1780 cpu->n_translated_instrs ++;
1781 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1782 cpu->pc = target;
1783 cpu->delay_slot = NOT_DELAYED;
1784 quick_pc_to_pointers(cpu);
1785 } else
1786 cpu->delay_slot = NOT_DELAYED;
1787 }
1788 X(bra_samepage)
1789 {
1790 cpu->delay_slot = TO_BE_DELAYED;
1791 ic[1].f(cpu, ic+1);
1792 cpu->n_translated_instrs ++;
1793 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT))
1794 cpu->cd.sh.next_ic = (struct sh_instr_call *) ic->arg[0];
1795 cpu->delay_slot = NOT_DELAYED;
1796 }
1797 X(bsr)
1798 {
1799 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1800 SH_INSTR_ALIGNMENT_SHIFT);
1801 uint32_t old_pc;
1802 SYNCH_PC;
1803 old_pc = cpu->pc;
1804 target += ic->arg[0];
1805 cpu->delay_slot = TO_BE_DELAYED;
1806 ic[1].f(cpu, ic+1);
1807 cpu->n_translated_instrs ++;
1808 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1809 cpu->cd.sh.pr = old_pc + 4;
1810 cpu->pc = target;
1811 cpu->delay_slot = NOT_DELAYED;
1812 quick_pc_to_pointers(cpu);
1813 } else
1814 cpu->delay_slot = NOT_DELAYED;
1815 }
1816 X(bsr_samepage)
1817 {
1818 uint32_t old_pc;
1819 SYNCH_PC;
1820 old_pc = cpu->pc;
1821 cpu->delay_slot = TO_BE_DELAYED;
1822 ic[1].f(cpu, ic+1);
1823 cpu->n_translated_instrs ++;
1824 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1825 cpu->cd.sh.pr = old_pc + 4;
1826 cpu->cd.sh.next_ic = (struct sh_instr_call *) ic->arg[0];
1827 }
1828 cpu->delay_slot = NOT_DELAYED;
1829 }
1830 X(braf_rn)
1831 {
1832 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1833 SH_INSTR_ALIGNMENT_SHIFT);
1834 target += ic->arg[0] + reg(ic->arg[1]);
1835 cpu->delay_slot = TO_BE_DELAYED;
1836 ic[1].f(cpu, ic+1);
1837 cpu->n_translated_instrs ++;
1838 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1839 cpu->pc = target;
1840 cpu->delay_slot = NOT_DELAYED;
1841 quick_pc_to_pointers(cpu);
1842 } else
1843 cpu->delay_slot = NOT_DELAYED;
1844 }
1845 X(bsrf_rn)
1846 {
1847 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1848 SH_INSTR_ALIGNMENT_SHIFT);
1849 uint32_t old_pc;
1850 SYNCH_PC;
1851 old_pc = cpu->pc;
1852 target += ic->arg[0] + reg(ic->arg[1]);
1853 cpu->delay_slot = TO_BE_DELAYED;
1854 ic[1].f(cpu, ic+1);
1855 cpu->n_translated_instrs ++;
1856 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1857 cpu->cd.sh.pr = old_pc + 4;
1858 cpu->pc = target;
1859 cpu->delay_slot = NOT_DELAYED;
1860 quick_pc_to_pointers(cpu);
1861 } else
1862 cpu->delay_slot = NOT_DELAYED;
1863 }
1864
1865
1866 /*
1867 * bt: Branch if true
1868 * bf: Branch if false
1869 * bt/s: Branch if true (with delay-slot)
1870 * bf/s: Branch if false (with delay-slot)
1871 *
1872 * arg[0] = immediate offset relative to start of page
1873 * arg[1] = for samepage functions, the new instruction pointer
1874 */
1875 X(bt)
1876 {
1877 if (cpu->cd.sh.sr & SH_SR_T) {
1878 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1879 SH_INSTR_ALIGNMENT_SHIFT);
1880 cpu->pc += ic->arg[0];
1881 quick_pc_to_pointers(cpu);
1882 }
1883 }
1884 X(bf)
1885 {
1886 if (!(cpu->cd.sh.sr & SH_SR_T)) {
1887 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1888 SH_INSTR_ALIGNMENT_SHIFT);
1889 cpu->pc += ic->arg[0];
1890 quick_pc_to_pointers(cpu);
1891 }
1892 }
1893 X(bt_samepage)
1894 {
1895 if (cpu->cd.sh.sr & SH_SR_T)
1896 cpu->cd.sh.next_ic = (struct sh_instr_call *) ic->arg[1];
1897 }
1898 X(bf_samepage)
1899 {
1900 if (!(cpu->cd.sh.sr & SH_SR_T))
1901 cpu->cd.sh.next_ic = (struct sh_instr_call *) ic->arg[1];
1902 }
1903 X(bt_s)
1904 {
1905 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1906 SH_INSTR_ALIGNMENT_SHIFT);
1907 int cond = cpu->cd.sh.sr & SH_SR_T;
1908 target += ic->arg[0];
1909 cpu->delay_slot = TO_BE_DELAYED;
1910 ic[1].f(cpu, ic+1);
1911 cpu->n_translated_instrs ++;
1912 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1913 cpu->delay_slot = NOT_DELAYED;
1914 if (cond) {
1915 cpu->pc = target;
1916 quick_pc_to_pointers(cpu);
1917 } else
1918 cpu->cd.sh.next_ic ++;
1919 } else
1920 cpu->delay_slot = NOT_DELAYED;
1921 }
1922 X(bf_s)
1923 {
1924 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1925 SH_INSTR_ALIGNMENT_SHIFT);
1926 int cond = !(cpu->cd.sh.sr & SH_SR_T);
1927 target += ic->arg[0];
1928 cpu->delay_slot = TO_BE_DELAYED;
1929 ic[1].f(cpu, ic+1);
1930 cpu->n_translated_instrs ++;
1931 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1932 cpu->delay_slot = NOT_DELAYED;
1933 if (cond) {
1934 cpu->pc = target;
1935 quick_pc_to_pointers(cpu);
1936 } else
1937 cpu->cd.sh.next_ic ++;
1938 } else
1939 cpu->delay_slot = NOT_DELAYED;
1940 }
1941 X(bt_s_samepage)
1942 {
1943 int cond = cpu->cd.sh.sr & SH_SR_T;
1944 cpu->delay_slot = TO_BE_DELAYED;
1945 ic[1].f(cpu, ic+1);
1946 cpu->n_translated_instrs ++;
1947 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1948 cpu->delay_slot = NOT_DELAYED;
1949 if (cond)
1950 cpu->cd.sh.next_ic =
1951 (struct sh_instr_call *) ic->arg[1];
1952 else
1953 cpu->cd.sh.next_ic ++;
1954 } else
1955 cpu->delay_slot = NOT_DELAYED;
1956 }
1957 X(bf_s_samepage)
1958 {
1959 int cond = !(cpu->cd.sh.sr & SH_SR_T);
1960 cpu->delay_slot = TO_BE_DELAYED;
1961 ic[1].f(cpu, ic+1);
1962 cpu->n_translated_instrs ++;
1963 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1964 cpu->delay_slot = NOT_DELAYED;
1965 if (cond)
1966 cpu->cd.sh.next_ic =
1967 (struct sh_instr_call *) ic->arg[1];
1968 else
1969 cpu->cd.sh.next_ic ++;
1970 } else
1971 cpu->delay_slot = NOT_DELAYED;
1972 }
1973
1974
1975 /*
1976 * jmp_rn: Jump to Rn
1977 * jsr_rn: Jump to Rn, store return address in PR.
1978 *
1979 * arg[0] = ptr to rn
1980 */
1981 X(jmp_rn)
1982 {
1983 MODE_int_t target = reg(ic->arg[0]);
1984 cpu->delay_slot = TO_BE_DELAYED;
1985 ic[1].f(cpu, ic+1);
1986 cpu->n_translated_instrs ++;
1987 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1988 cpu->pc = target;
1989 cpu->delay_slot = NOT_DELAYED;
1990 quick_pc_to_pointers(cpu);
1991 } else
1992 cpu->delay_slot = NOT_DELAYED;
1993 }
1994 X(jmp_rn_trace)
1995 {
1996 MODE_int_t target = reg(ic->arg[0]);
1997 cpu->delay_slot = TO_BE_DELAYED;
1998 ic[1].f(cpu, ic+1);
1999 cpu->n_translated_instrs ++;
2000 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
2001 cpu->pc = target;
2002 #if 0
2003 /* NOTE: Jmp works like both a return, and a subroutine
2004 call. */
2005 cpu_functioncall_trace_return(cpu);
2006 cpu_functioncall_trace(cpu, cpu->pc);
2007 #endif
2008 cpu->delay_slot = NOT_DELAYED;
2009 quick_pc_to_pointers(cpu);
2010 } else
2011 cpu->delay_slot = NOT_DELAYED;
2012 }
2013 X(jsr_rn)
2014 {
2015 MODE_int_t target = reg(ic->arg[0]), retaddr;
2016 cpu->delay_slot = TO_BE_DELAYED;
2017 retaddr = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
2018 SH_INSTR_ALIGNMENT_SHIFT);
2019 ic[1].f(cpu, ic+1);
2020 cpu->n_translated_instrs ++;
2021 cpu->cd.sh.pr = retaddr + (int32_t)ic->arg[1];
2022 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
2023 cpu->pc = target;
2024 cpu->delay_slot = NOT_DELAYED;
2025 quick_pc_to_pointers(cpu);
2026 } else
2027 cpu->delay_slot = NOT_DELAYED;
2028 }
2029 X(jsr_rn_trace)
2030 {
2031 MODE_int_t target = reg(ic->arg[0]), retaddr;
2032 cpu->delay_slot = TO_BE_DELAYED;
2033 retaddr = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
2034 SH_INSTR_ALIGNMENT_SHIFT);
2035 ic[1].f(cpu, ic+1);
2036 cpu->n_translated_instrs ++;
2037 cpu->cd.sh.pr = retaddr + (int32_t)ic->arg[1];
2038 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
2039 cpu->pc = target;
2040 cpu_functioncall_trace(cpu, cpu->pc);
2041 cpu->delay_slot = NOT_DELAYED;
2042 quick_pc_to_pointers(cpu);
2043 } else
2044 cpu->delay_slot = NOT_DELAYED;
2045 }
2046
2047
2048 /*
2049 * rts: Jump to PR.
2050 */
2051 X(rts)
2052 {
2053 MODE_int_t target = cpu->cd.sh.pr;
2054 cpu->delay_slot = TO_BE_DELAYED;
2055 ic[1].f(cpu, ic+1);
2056 cpu->n_translated_instrs ++;
2057 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
2058 cpu->pc = target;
2059 cpu->delay_slot = NOT_DELAYED;
2060 quick_pc_to_pointers(cpu);
2061 } else
2062 cpu->delay_slot = NOT_DELAYED;
2063 }
2064 X(rts_trace)
2065 {
2066 MODE_int_t target = cpu->cd.sh.pr;
2067 cpu->delay_slot = TO_BE_DELAYED;
2068 ic[1].f(cpu, ic+1);
2069 cpu->n_translated_instrs ++;
2070 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
2071 cpu->pc = target;
2072 cpu_functioncall_trace_return(cpu);
2073 cpu->delay_slot = NOT_DELAYED;
2074 quick_pc_to_pointers(cpu);
2075 } else
2076 cpu->delay_slot = NOT_DELAYED;
2077 }
2078
2079
2080 /*
2081 * rte: Return from exception.
2082 */
2083 X(rte)
2084 {
2085 RES_INST_IF_NOT_MD;
2086
2087 cpu->delay_slot = TO_BE_DELAYED;
2088 ic[1].f(cpu, ic+1);
2089 cpu->n_translated_instrs ++;
2090 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
2091 cpu->pc = cpu->cd.sh.spc;
2092 cpu->delay_slot = NOT_DELAYED;
2093 sh_update_sr(cpu, cpu->cd.sh.ssr);
2094 quick_pc_to_pointers(cpu);
2095 } else
2096 cpu->delay_slot = NOT_DELAYED;
2097 }
2098
2099
2100 /*
2101 * ldtlb: Load UTLB entry.
2102 */
2103 X(ldtlb)
2104 {
2105 uint32_t old_hi, old_lo;
2106 int urc = (cpu->cd.sh.mmucr & SH4_MMUCR_URC_MASK)
2107 >> SH4_MMUCR_URC_SHIFT;
2108
2109 RES_INST_IF_NOT_MD;
2110
2111 old_hi = cpu->cd.sh.utlb_hi[urc];
2112 old_lo = cpu->cd.sh.utlb_lo[urc];
2113
2114 cpu->cd.sh.utlb_hi[urc] = cpu->cd.sh.pteh;
2115 cpu->cd.sh.utlb_lo[urc] = cpu->cd.sh.ptel;
2116
2117 /* Invalidate the old mapping, if it belonged to the same ASID: */
2118 if ((old_hi & SH4_PTEH_ASID_MASK) ==
2119 (cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK)) {
2120 if ((old_lo & SH4_PTEL_SZ_MASK) == SH4_PTEL_SZ_4K)
2121 cpu->invalidate_translation_caches(cpu,
2122 old_hi & 0xfffff000, INVALIDATE_VADDR);
2123 else
2124 cpu->invalidate_translation_caches(cpu,
2125 0, INVALIDATE_ALL);
2126 }
2127 }
2128
2129
2130 /*
2131 * copy_privileged_register: Copy normal into privileged register, or vice
2132 * versa, after checking the MD status bit.
2133 *
2134 * arg[0] = ptr to source register
2135 * arg[1] = ptr to destination register
2136 */
2137 X(copy_privileged_register)
2138 {
2139 RES_INST_IF_NOT_MD;
2140 reg(ic->arg[1]) = reg(ic->arg[0]);
2141 }
2142
2143
2144 /*
2145 * ldc_rm_sr: Copy Rm into SR, after checking the MD status bit.
2146 *
2147 * arg[1] = ptr to rm
2148 */
2149 X(ldc_rm_sr)
2150 {
2151 RES_INST_IF_NOT_MD;
2152 sh_update_sr(cpu, reg(ic->arg[1]));
2153
2154 #if 0
2155 /* NOTE: This code causes NetBSD/landisk to get past a point where it
2156 otherwise hangs, but it causes Linux/Dreamcast to bug out instead. :/ */
2157
2158 if (!(cpu->cd.sh.sr & SH_SR_BL) && cpu->cd.sh.int_to_assert > 0 &&
2159 ( (cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT)
2160 < cpu->cd.sh.int_level) {
2161 /* Cause interrupt immediately, by dropping out of the
2162 main dyntrans loop: */
2163 cpu->cd.sh.next_ic = &nothing_call;
2164 }
2165 #endif
2166 }
2167
2168
2169 /*
2170 * trapa: Immediate trap.
2171 *
2172 * arg[0] = imm << 2
2173 */
2174 X(trapa)
2175 {
2176 SYNCH_PC;
2177
2178 if (cpu->delay_slot) {
2179 sh_exception(cpu, EXPEVT_SLOT_INST, 0, 0);
2180 return;
2181 }
2182
2183 cpu->cd.sh.tra = ic->arg[0];
2184 sh_exception(cpu, EXPEVT_TRAPA, 0, 0);
2185 }
2186
2187
2188 /*
2189 * copy_fp_register: Copy a register into another, with FP avail check.
2190 * lds_rm_fpscr: Copy Rm into FPSCR.
2191 *
2192 * arg[0] = ptr to source
2193 * arg[1] = ptr to destination
2194 */
2195 X(copy_fp_register)
2196 {
2197 FLOATING_POINT_AVAILABLE_CHECK;
2198 reg(ic->arg[1]) = reg(ic->arg[0]);
2199 }
2200 X(lds_rm_fpscr)
2201 {
2202 FLOATING_POINT_AVAILABLE_CHECK;
2203 sh_update_fpscr(cpu, reg(ic->arg[1]));
2204 }
2205
2206
2207 /*
2208 * fmov_frm_frn: Copy one floating-point register (or pair) to another.
2209 *
2210 * arg[0] = ptr to source float register or pair
2211 * arg[1] = ptr to destination float register or pair
2212 */
2213 X(fmov_frm_frn)
2214 {
2215 size_t r0, r1;
2216 int ofs0, ofs1;
2217
2218 FLOATING_POINT_AVAILABLE_CHECK;
2219
2220 /* Simplest case, single-precision: */
2221 if (!(cpu->cd.sh.fpscr & SH_FPSCR_SZ)) {
2222 reg(ic->arg[1]) = reg(ic->arg[0]);
2223 return;
2224 }
2225
2226 /* Double-precision: */
2227 r0 = ic->arg[0]; r1 = ic->arg[1];
2228 ofs0 = (r0 - (size_t)&cpu->cd.sh.fr[0]) / sizeof(uint32_t);
2229 ofs1 = (r1 - (size_t)&cpu->cd.sh.fr[0]) / sizeof(uint32_t);
2230 if (ofs0 & 1)
2231 r0 = (size_t)&cpu->cd.sh.xf[ofs0 & ~1];
2232 if (ofs1 & 1)
2233 r1 = (size_t)&cpu->cd.sh.xf[ofs1 & ~1];
2234
2235 reg(r1) = reg(r0);
2236 reg(r1 + 4) = reg(r0 + 4);
2237 }
2238
2239
2240 /*
2241 * float_fpul_frn: Load FPUL into float register.
2242 *
2243 * arg[0] = ptr to float register, or float register pair
2244 */
2245 X(float_fpul_frn)
2246 {
2247 int32_t fpul = cpu->cd.sh.fpul;
2248
2249 FLOATING_POINT_AVAILABLE_CHECK;
2250
2251 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2252 /* Double-precision, using a pair of registers: */
2253 uint64_t ieee = ieee_store_float_value(fpul, IEEE_FMT_D, 0);
2254 reg(ic->arg[0]) = (uint32_t) (ieee >> 32);
2255 reg(ic->arg[0] + sizeof(uint32_t)) = (uint32_t) ieee;
2256 } else {
2257 /* Single-precision: */
2258 uint32_t ieee = ieee_store_float_value(fpul, IEEE_FMT_S, 0);
2259 reg(ic->arg[0]) = (uint32_t) ieee;
2260 }
2261 }
2262
2263
2264 /*
2265 * ftrc_frm_fpul: Truncate a float register into FPUL.
2266 *
2267 * arg[0] = ptr to float register, or float register pair
2268 */
2269 X(ftrc_frm_fpul)
2270 {
2271 struct ieee_float_value op1;
2272
2273 FLOATING_POINT_AVAILABLE_CHECK;
2274
2275 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2276 /* Double-precision, using a pair of registers: */
2277 int64_t r1 = ((uint64_t)reg(ic->arg[0]) << 32) +
2278 reg(ic->arg[0] + sizeof(uint32_t));
2279 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2280 cpu->cd.sh.fpul = (int32_t) op1.f;
2281 } else {
2282 /* Single-precision: */
2283 ieee_interpret_float_value(reg(ic->arg[0]), &op1, IEEE_FMT_S);
2284 cpu->cd.sh.fpul = (int32_t) op1.f;
2285 }
2286 }
2287
2288
2289 /*
2290 * fcnvsd_fpul_drn: Convert single-precision to double-precision.
2291 * fcnvds_drm_fpul: Convert double-precision to single-precision.
2292 *
2293 * arg[0] = ptr to destination (double- or single-precision float)
2294 */
2295 X(fcnvsd_fpul_drn)
2296 {
2297 struct ieee_float_value op1;
2298 int64_t ieee;
2299
2300 FLOATING_POINT_AVAILABLE_CHECK;
2301
2302 ieee_interpret_float_value(cpu->cd.sh.fpul, &op1, IEEE_FMT_S);
2303 cpu->cd.sh.fpul = (int32_t) op1.f;
2304
2305 /* Store double-precision result: */
2306 ieee = ieee_store_float_value(op1.f, IEEE_FMT_D, 0);
2307 reg(ic->arg[0]) = (uint32_t) (ieee >> 32);
2308 reg(ic->arg[0] + sizeof(uint32_t)) = (uint32_t) ieee;
2309 }
2310 X(fcnvds_drm_fpul)
2311 {
2312 struct ieee_float_value op1;
2313 int64_t r1;
2314
2315 FLOATING_POINT_AVAILABLE_CHECK;
2316
2317 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2318 ((uint64_t)reg(ic->arg[0]) << 32);
2319 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2320
2321 cpu->cd.sh.fpul = ieee_store_float_value(op1.f, IEEE_FMT_S, 0);
2322 }
2323
2324
2325 /*
2326 * fsca_fpul_drn: Sinus/cosinus approximation.
2327 *
2328 * Note: This is an interesting instruction. It is not included in the SH4
2329 * manual. Some googling indicated that this might be an SH4X instruction.
2330 * On the other hand, it is used by Dreamcast code (and the Dreamcast has an
2331 * SH4), and a cvs comment for gdb said that this is an SH4 instruction, not
2332 * an SH4A instruction. Well well...
2333 *
2334 * arg[0] = ptr to single-precision float register pair
2335 */
2336 X(fsca_fpul_drn)
2337 {
2338 double fpul = ((double) (int32_t)cpu->cd.sh.fpul) / 32768.0;
2339
2340 FLOATING_POINT_AVAILABLE_CHECK;
2341
2342 reg(ic->arg[0]) = ieee_store_float_value(sin(fpul), IEEE_FMT_S, 0);
2343 reg(ic->arg[0] + sizeof(uint32_t)) =
2344 ieee_store_float_value(cos(fpul), IEEE_FMT_S, 0);
2345 }
2346
2347
2348 /*
2349 * ftrv_xmtrx_fvn: Matrix * vector ==> vector
2350 *
2351 * arg[0] = ptr to FVn
2352 */
2353 X(ftrv_xmtrx_fvn)
2354 {
2355 int i;
2356 struct ieee_float_value xmtrx[16], frn[4];
2357 double frnp0 = 0.0, frnp1 = 0.0, frnp2 = 0.0, frnp3 = 0.0;
2358
2359 ieee_interpret_float_value(reg(ic->arg[0] + 0), &frn[0], IEEE_FMT_S);
2360 ieee_interpret_float_value(reg(ic->arg[0] + 4), &frn[1], IEEE_FMT_S);
2361 ieee_interpret_float_value(reg(ic->arg[0] + 8), &frn[2], IEEE_FMT_S);
2362 ieee_interpret_float_value(reg(ic->arg[0] + 12), &frn[3], IEEE_FMT_S);
2363
2364 for (i=0; i<16; i++)
2365 ieee_interpret_float_value(cpu->cd.sh.xf[i],
2366 &xmtrx[i], IEEE_FMT_S);
2367
2368 for (i=0; i<4; i++)
2369 frnp0 += xmtrx[i*4].f * frn[i].f;
2370
2371 for (i=0; i<4; i++)
2372 frnp1 += xmtrx[i*4 + 1].f * frn[i].f;
2373
2374 for (i=0; i<4; i++)
2375 frnp2 += xmtrx[i*4 + 2].f * frn[i].f;
2376
2377 for (i=0; i<4; i++)
2378 frnp3 += xmtrx[i*4 + 3].f * frn[i].f;
2379
2380 reg(ic->arg[0] + 0) = ieee_store_float_value(frnp0, IEEE_FMT_S, 0);
2381 reg(ic->arg[0] + 4) = ieee_store_float_value(frnp1, IEEE_FMT_S, 0);
2382 reg(ic->arg[0] + 8) = ieee_store_float_value(frnp2, IEEE_FMT_S, 0);
2383 reg(ic->arg[0] + 12) = ieee_store_float_value(frnp3, IEEE_FMT_S, 0);
2384 }
2385
2386
2387 /*
2388 * fldi: Load immediate (0.0 or 1.0) into floating point register.
2389 * fneg: Negate a floating point register
2390 * fabs: Get the absolute value of a floating point register
2391 * fsqrt: Calculate square root
2392 *
2393 * arg[0] = ptr to fp register
2394 * arg[1] = (uint32_t) immediate value (for fldi)
2395 */
2396 X(fldi_frn)
2397 {
2398 FLOATING_POINT_AVAILABLE_CHECK;
2399 reg(ic->arg[0]) = ic->arg[1];
2400 }
2401 X(fneg_frn)
2402 {
2403 FLOATING_POINT_AVAILABLE_CHECK;
2404 /* Note: This also works for double-precision. */
2405 reg(ic->arg[0]) ^= 0x80000000;
2406 }
2407 X(fabs_frn)
2408 {
2409 FLOATING_POINT_AVAILABLE_CHECK;
2410 /* Note: This also works for double-precision. */
2411 reg(ic->arg[0]) &= 0x7fffffff;
2412 }
2413 X(fsqrt_frn)
2414 {
2415 struct ieee_float_value op1;
2416
2417 FLOATING_POINT_AVAILABLE_CHECK;
2418
2419 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2420 /* Double-precision: */
2421 int64_t r1, ieee;
2422 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2423 ((uint64_t)reg(ic->arg[0]) << 32);
2424 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2425 ieee = ieee_store_float_value(sqrt(op1.f), IEEE_FMT_D, 0);
2426 reg(ic->arg[0]) = (uint32_t) (ieee >> 32);
2427 reg(ic->arg[0] + sizeof(uint32_t)) = (uint32_t) ieee;
2428 } else {
2429 /* Single-precision: */
2430 int32_t ieee, r1 = reg(ic->arg[0]);
2431 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2432 ieee = ieee_store_float_value(sqrt(op1.f), IEEE_FMT_S, 0);
2433 reg(ic->arg[0]) = ieee;
2434 }
2435 }
2436
2437
2438 /*
2439 * fadd_frm_frn: Floating point addition.
2440 * fsub_frm_frn: Floating point subtraction.
2441 * fmul_frm_frn: Floating point multiplication.
2442 * fdiv_frm_frn: Floating point division.
2443 * fmac_fr0_frm_frn: Multiply-and-accumulate.
2444 * fcmp_eq_frm_frn: Floating point greater-than comparison.
2445 * fcmp_gt_frm_frn: Floating point greater-than comparison.
2446 *
2447 * arg[0] = ptr to float register FRm
2448 * arg[1] = ptr to float register FRn
2449 */
2450 X(fadd_frm_frn)
2451 {
2452 struct ieee_float_value op1, op2;
2453
2454 FLOATING_POINT_AVAILABLE_CHECK;
2455
2456 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2457 /* Double-precision, using a pair of registers: */
2458 int64_t r1, r2, ieee;
2459 double result;
2460
2461 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2462 ((uint64_t)reg(ic->arg[0]) << 32);
2463 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2464 ((uint64_t)reg(ic->arg[1]) << 32);
2465 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2466 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2467
2468 result = op2.f + op1.f;
2469 ieee = ieee_store_float_value(result, IEEE_FMT_D, 0);
2470 reg(ic->arg[1]) = (uint32_t) (ieee >> 32);
2471 reg(ic->arg[1] + sizeof(uint32_t)) = (uint32_t) ieee;
2472 } else {
2473 /* Single-precision: */
2474 uint32_t r1, r2, ieee;
2475 double result;
2476
2477 r1 = reg(ic->arg[0]);
2478 r2 = reg(ic->arg[1]);
2479 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2480 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2481
2482 result = op2.f + op1.f;
2483 ieee = ieee_store_float_value(result, IEEE_FMT_S, 0);
2484 reg(ic->arg[1]) = (uint32_t) ieee;
2485 }
2486 }
2487 X(fsub_frm_frn)
2488 {
2489 struct ieee_float_value op1, op2;
2490
2491 FLOATING_POINT_AVAILABLE_CHECK;
2492
2493 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2494 /* Double-precision, using a pair of registers: */
2495 int64_t r1, r2, ieee;
2496 double result;
2497 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2498 ((uint64_t)reg(ic->arg[0]) << 32);
2499 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2500 ((uint64_t)reg(ic->arg[1]) << 32);
2501 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2502 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2503 result = op2.f - op1.f;
2504 ieee = ieee_store_float_value(result, IEEE_FMT_D, 0);
2505 reg(ic->arg[1]) = (uint32_t) (ieee >> 32);
2506 reg(ic->arg[1] + sizeof(uint32_t)) = (uint32_t) ieee;
2507 } else {
2508 /* Single-precision: */
2509 uint32_t r1, r2, ieee;
2510 double result;
2511 r1 = reg(ic->arg[0]);
2512 r2 = reg(ic->arg[1]);
2513 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2514 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2515 result = op2.f - op1.f;
2516 ieee = ieee_store_float_value(result, IEEE_FMT_S, 0);
2517 reg(ic->arg[1]) = (uint32_t) ieee;
2518 }
2519 }
2520 X(fmul_frm_frn)
2521 {
2522 struct ieee_float_value op1, op2;
2523
2524 FLOATING_POINT_AVAILABLE_CHECK;
2525
2526 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2527 /* Double-precision, using a pair of registers: */
2528 int64_t r1, r2, ieee;
2529 double result;
2530
2531 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2532 ((uint64_t)reg(ic->arg[0]) << 32);
2533 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2534 ((uint64_t)reg(ic->arg[1]) << 32);
2535 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2536 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2537
2538 result = op2.f * op1.f;
2539 ieee = ieee_store_float_value(result, IEEE_FMT_D, 0);
2540 reg(ic->arg[1]) = (uint32_t) (ieee >> 32);
2541 reg(ic->arg[1] + sizeof(uint32_t)) = (uint32_t) ieee;
2542 } else {
2543 /* Single-precision: */
2544 uint32_t r1, r2, ieee;
2545 double result;
2546
2547 r1 = reg(ic->arg[0]);
2548 r2 = reg(ic->arg[1]);
2549 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2550 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2551
2552 result = op2.f * op1.f;
2553 ieee = ieee_store_float_value(result, IEEE_FMT_S, 0);
2554 reg(ic->arg[1]) = (uint32_t) ieee;
2555 }
2556 }
2557 X(fdiv_frm_frn)
2558 {
2559 struct ieee_float_value op1, op2;
2560
2561 FLOATING_POINT_AVAILABLE_CHECK;
2562
2563 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2564 /* Double-precision, using a pair of registers: */
2565 int64_t r1, r2, ieee;
2566 double result;
2567
2568 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2569 ((uint64_t)reg(ic->arg[0]) << 32);
2570 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2571 ((uint64_t)reg(ic->arg[1]) << 32);
2572 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2573 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2574
2575 if (op1.f != 0.0)
2576 result = op2.f / op1.f;
2577 else
2578 result = 0.0;
2579
2580 ieee = ieee_store_float_value(result, IEEE_FMT_D, 0);
2581
2582 reg(ic->arg[1]) = (uint32_t) (ieee >> 32);
2583 reg(ic->arg[1] + sizeof(uint32_t)) = (uint32_t) ieee;
2584 } else {
2585 /* Single-precision: */
2586 uint32_t r1, r2, ieee;
2587 double result;
2588
2589 r1 = reg(ic->arg[0]);
2590 r2 = reg(ic->arg[1]);
2591 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2592 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2593
2594 if (op1.f != 0.0)
2595 result = op2.f / op1.f;
2596 else
2597 result = 0.0;
2598
2599 ieee = ieee_store_float_value(result, IEEE_FMT_S, 0);
2600
2601 reg(ic->arg[1]) = (uint32_t) ieee;
2602 }
2603 }
2604 X(fmac_fr0_frm_frn)
2605 {
2606 struct ieee_float_value op1, op2, op0;
2607 int32_t r1, r2, fr0 = cpu->cd.sh.fr[0], ieee;
2608
2609 FLOATING_POINT_AVAILABLE_CHECK;
2610
2611 r1 = reg(ic->arg[0]), r2 = reg(ic->arg[1]);
2612 ieee_interpret_float_value(fr0, &op0, IEEE_FMT_S);
2613 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2614 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2615 ieee = ieee_store_float_value(op0.f * op1.f + op2.f, IEEE_FMT_S, 0);
2616 reg(ic->arg[1]) = ieee;
2617 }
2618 X(fcmp_eq_frm_frn)
2619 {
2620 struct ieee_float_value op1, op2;
2621
2622 FLOATING_POINT_AVAILABLE_CHECK;
2623
2624 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2625 /* Double-precision, using a pair of registers: */
2626 int64_t r1, r2;
2627 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2628 ((uint64_t)reg(ic->arg[0]) << 32);
2629 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2630 ((uint64_t)reg(ic->arg[1]) << 32);
2631 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2632 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2633 } else {
2634 /* Single-precision: */
2635 uint32_t r1 = reg(ic->arg[0]), r2 = reg(ic->arg[1]);
2636 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2637 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2638 }
2639
2640 if (op2.f == op1.f)
2641 cpu->cd.sh.sr |= SH_SR_T;
2642 else
2643 cpu->cd.sh.sr &= ~SH_SR_T;
2644 }
2645 X(fcmp_gt_frm_frn)
2646 {
2647 struct ieee_float_value op1, op2;
2648
2649 FLOATING_POINT_AVAILABLE_CHECK;
2650
2651 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2652 /* Double-precision, using a pair of registers: */
2653 int64_t r1, r2;
2654 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2655 ((uint64_t)reg(ic->arg[0]) << 32);
2656 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2657 ((uint64_t)reg(ic->arg[1]) << 32);
2658 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2659 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2660 } else {
2661 /* Single-precision: */
2662 uint32_t r1 = reg(ic->arg[0]), r2 = reg(ic->arg[1]);
2663 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2664 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2665 }
2666
2667 if (op2.f > op1.f)
2668 cpu->cd.sh.sr |= SH_SR_T;
2669 else
2670 cpu->cd.sh.sr &= ~SH_SR_T;
2671 }
2672
2673
2674 /*
2675 * frchg: Change floating-point register banks.
2676 * fschg: Change floating-point register size.
2677 */
2678 X(frchg)
2679 {
2680 FLOATING_POINT_AVAILABLE_CHECK;
2681 sh_update_fpscr(cpu, cpu->cd.sh.fpscr ^ SH_FPSCR_FR);
2682 }
2683 X(fschg)
2684 {
2685 FLOATING_POINT_AVAILABLE_CHECK;
2686 sh_update_fpscr(cpu, cpu->cd.sh.fpscr ^ SH_FPSCR_SZ);
2687 }
2688
2689
2690 /*
2691 * pref_rn: Prefetch.
2692 *
2693 * arg[1] = ptr to Rn
2694 */
2695 X(pref_rn)
2696 {
2697 uint32_t addr = reg(ic->arg[1]), extaddr;
2698 int sq_nr, ofs;
2699
2700 if (addr < 0xe0000000 || addr >= 0xe4000000)
2701 return;
2702
2703 /* Send Store Queue contents to external memory: */
2704 extaddr = addr & 0x03ffffe0;
2705 sq_nr = addr & 0x20? 1 : 0;
2706
2707 if (cpu->cd.sh.mmucr & SH4_MMUCR_AT) {
2708 fatal("Store Queue to external memory, when "
2709 "MMU enabled: TODO\n");
2710 exit(1);
2711 }
2712
2713 if (sq_nr == 0)
2714 extaddr |= (((cpu->cd.sh.qacr0 >> 2) & 7) << 26);
2715 else
2716 extaddr |= (((cpu->cd.sh.qacr1 >> 2) & 7) << 26);
2717
2718 /* fatal("extaddr = 0x%08x\n", extaddr); */
2719
2720 SYNCH_PC;
2721 for (ofs = 0; ofs < 32; ofs += sizeof(uint32_t)) {
2722 uint32_t word;
2723 cpu->memory_rw(cpu, cpu->mem, 0xe0000000 + ofs
2724 + sq_nr * 0x20, (unsigned char *)
2725 &word, sizeof(word), MEM_READ, PHYSICAL);
2726 cpu->memory_rw(cpu, cpu->mem, extaddr+ofs, (unsigned char *)
2727 &word, sizeof(word), MEM_WRITE, PHYSICAL);
2728 }
2729 }
2730
2731
2732 /*
2733 * tas_b_rn: Test-and-Set.
2734 *
2735 * arg[1] = ptr to Rn
2736 */
2737 X(tas_b_rn)
2738 {
2739 uint32_t addr = reg(ic->arg[1]);
2740 uint8_t byte, newbyte;
2741
2742 SYNCH_PC;
2743
2744 if (!cpu->memory_rw(cpu, cpu->mem, addr, &byte, 1, MEM_READ,
2745 CACHE_DATA)) {
2746 /* Exception. */
2747 return;
2748 }
2749
2750 newbyte = byte | 0x80;
2751
2752 if (!cpu->memory_rw(cpu, cpu->mem, addr, &newbyte, 1, MEM_WRITE,
2753 CACHE_DATA)) {
2754 /* Exception. */
2755 return;
2756 }
2757
2758 if (byte == 0)
2759 cpu->cd.sh.sr |= SH_SR_T;
2760 else
2761 cpu->cd.sh.sr &= ~SH_SR_T;
2762 }
2763
2764
2765 /*
2766 * prom_emul:
2767 */
2768 X(prom_emul)
2769 {
2770 uint32_t old_pc;
2771 SYNCH_PC;
2772 old_pc = cpu->pc;
2773
2774 switch (cpu->machine->machine_type) {
2775 case MACHINE_DREAMCAST:
2776 dreamcast_emul(cpu);
2777 break;
2778 case MACHINE_LANDISK:
2779 sh_ipl_g_emul(cpu);
2780 break;
2781 default:
2782 fatal("SH prom_emul: unimplemented machine type.\n");
2783 exit(1);
2784 }
2785
2786 if (!cpu->running) {
2787 cpu->n_translated_instrs --;
2788 cpu->cd.sh.next_ic = &nothing_call;
2789 } else if ((uint32_t)cpu->pc != old_pc) {
2790 /* The PC value was changed by the PROM call. */
2791 quick_pc_to_pointers(cpu);
2792 }
2793 }
2794
2795
2796 /*****************************************************************************/
2797
2798
2799 X(end_of_page)
2800 {
2801 /* Update the PC: (offset 0, but on the next page) */
2802 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1) <<
2803 SH_INSTR_ALIGNMENT_SHIFT);
2804 cpu->pc += (SH_IC_ENTRIES_PER_PAGE << SH_INSTR_ALIGNMENT_SHIFT);
2805
2806 /* end_of_page doesn't count as an executed instruction: */
2807 cpu->n_translated_instrs --;
2808
2809 /*
2810 * Find the new physpage and update translation pointers.
2811 *
2812 * Note: This may cause an exception, if e.g. the new page is
2813 * not accessible.
2814 */
2815 quick_pc_to_pointers(cpu);
2816
2817 /* Simple jump to the next page (if we are lucky): */
2818 if (cpu->delay_slot == NOT_DELAYED)
2819 return;
2820
2821 /*
2822 * If we were in a delay slot, and we got an exception while doing
2823 * quick_pc_to_pointers, then return. The function which called
2824 * end_of_page should handle this case.
2825 */
2826 if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
2827 return;
2828
2829 /*
2830 * Tricky situation; the delay slot is on the next virtual page.
2831 * Calling to_be_translated will translate one instruction manually,
2832 * execute it, and then discard it.
2833 */
2834 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
2835
2836 instr(to_be_translated)(cpu, cpu->cd.sh.next_ic);
2837
2838 /* The instruction in the delay slot has now executed. */
2839 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
2840 cpu->delay_slot); */
2841
2842 /* Find the physpage etc of the instruction in the delay slot
2843 (or, if there was an exception, the exception handler): */
2844 quick_pc_to_pointers(cpu);
2845 }
2846
2847
2848 X(end_of_page2)
2849 {
2850 /* Synchronize PC on the _second_ instruction on the next page: */
2851 int low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page)
2852 / sizeof(struct sh_instr_call);
2853 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1)
2854 << SH_INSTR_ALIGNMENT_SHIFT);
2855 cpu->pc += (low_pc << SH_INSTR_ALIGNMENT_SHIFT);
2856
2857 /* This doesn't count as an executed instruction. */
2858 cpu->n_translated_instrs --;
2859
2860 quick_pc_to_pointers(cpu);
2861
2862 if (cpu->delay_slot == NOT_DELAYED)
2863 return;
2864
2865 fatal("end_of_page2: fatal error, we're in a delay slot\n");
2866 exit(1);
2867 }
2868
2869
2870 /*****************************************************************************/
2871
2872
2873 /*
2874 * sh_instr_to_be_translated():
2875 *
2876 * Translate an instruction word into an sh_instr_call. ic is filled in with
2877 * valid data for the translated instruction, or a "nothing" instruction if
2878 * there was a translation failure. The newly translated instruction is then
2879 * executed.
2880 */
2881 X(to_be_translated)
2882 {
2883 uint64_t addr, low_pc;
2884 uint32_t iword;
2885 unsigned char *page;
2886 unsigned char ib[2];
2887 int main_opcode, isize = sizeof(ib);
2888 int in_crosspage_delayslot = 0, r8, r4, lo4, lo8;
2889 void (*samepage_function)(struct cpu *, struct sh_instr_call *);
2890
2891 /* Figure out the (virtual) address of the instruction: */
2892 low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page)
2893 / sizeof(struct sh_instr_call);
2894
2895 /* Special case for branch with delayslot on the next page: */
2896 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
2897 /* fatal("[ delay-slot translation across page "
2898 "boundary ]\n"); */
2899 in_crosspage_delayslot = 1;
2900 }
2901
2902 addr = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1)
2903 << SH_INSTR_ALIGNMENT_SHIFT);
2904 addr += (low_pc << SH_INSTR_ALIGNMENT_SHIFT);
2905 cpu->pc = (MODE_int_t)addr;
2906 addr &= ~((1 << SH_INSTR_ALIGNMENT_SHIFT) - 1);
2907
2908 /* Read the instruction word from memory: */
2909 #ifdef MODE32
2910 page = cpu->cd.sh.host_load[(uint32_t)addr >> 12];
2911 #else
2912 {
2913 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2914 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2915 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2916 uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2917 uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2918 uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2919 DYNTRANS_L3N)) & mask3;
2920 struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.sh.l1_64[x1];
2921 struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2922 page = l3->host_load[x3];
2923 }
2924 #endif
2925
2926 if (page != NULL) {
2927 /* fatal("TRANSLATION HIT!\n"); */
2928 memcpy(ib, page + (addr & 0xfff), isize);
2929 } else {
2930 /* fatal("TRANSLATION MISS!\n"); */
2931 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2932 isize, MEM_READ, CACHE_INSTRUCTION)) {
2933 fatal("to_be_translated(): read failed: TODO\n");
2934 goto bad;
2935 }
2936 }
2937
2938 iword = *((uint16_t *)&ib[0]);
2939 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2940 iword = LE16_TO_HOST(iword);
2941 else
2942 iword = BE16_TO_HOST(iword);
2943 main_opcode = iword >> 12;
2944 r8 = (iword >> 8) & 0xf;
2945 r4 = (iword >> 4) & 0xf;
2946 lo8 = iword & 0xff;
2947 lo4 = iword & 0xf;
2948
2949
2950 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
2951 #include "cpu_dyntrans.c"
2952 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
2953
2954
2955 /*
2956 * Translate the instruction:
2957 */
2958
2959 /* Default args. for many instructions: */
2960 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
2961 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
2962
2963 switch (main_opcode) {
2964
2965 case 0x0:
2966 if (lo4 == 0x4) {
2967 /* MOV.B Rm,@(R0,Rn) */
2968 ic->f = instr(mov_b_rm_r0_rn);
2969 } else if (lo4 == 0x5) {
2970 /* MOV.W Rm,@(R0,Rn) */
2971 ic->f = instr(mov_w_rm_r0_rn);
2972 } else if (lo4 == 0x6) {
2973 /* MOV.L Rm,@(R0,Rn) */
2974 ic->f = instr(mov_l_rm_r0_rn);
2975 } else if (lo4 == 0x7) {
2976 /* MUL.L Rm,Rn */
2977 ic->f = instr(mul_l_rm_rn);
2978 } else if (iword == 0x000b) {
2979 if (cpu->machine->show_trace_tree)
2980 ic->f = instr(rts_trace);
2981 else
2982 ic->f = instr(rts);
2983 } else if (lo4 == 0xc) {
2984 /* MOV.B @(R0,Rm),Rn */
2985 ic->f = instr(mov_b_r0_rm_rn);
2986 } else if (lo4 == 0xd) {
2987 /* MOV.W @(R0,Rm),Rn */
2988 ic->f = instr(mov_w_r0_rm_rn);
2989 } else if (lo4 == 0xe) {
2990 /* MOV.L @(R0,Rm),Rn */
2991 ic->f = instr(mov_l_r0_rm_rn);
2992 } else if (iword == 0x0008) {
2993 /* CLRT */
2994 ic->f = instr(clrt);
2995 } else if (iword == 0x0018) {
2996 /* SETT */
2997 ic->f = instr(sett);
2998 } else if (iword == 0x0019) {
2999 /* DIV0U */
3000 ic->f = instr(div0u);
3001 } else if (iword == 0x001b) {
3002 /* SLEEP */
3003 ic->f = instr(sleep);
3004 } else if (iword == 0x0028) {
3005 /* CLRMAC */
3006 ic->f = instr(clrmac);
3007 } else if (iword == 0x002b) {
3008 /* RTE */
3009 ic->f = instr(rte);
3010 } else if (iword == 0x0038) {
3011 /* LDTLB */
3012 ic->f = instr(ldtlb);
3013 } else if (iword == 0x0048) {
3014 /* CLRS */
3015 ic->f = instr(clrs);
3016 } else if (iword == 0x0058) {
3017 /* SETS */
3018 ic->f = instr(sets);
3019 } else if ((lo8 & 0x8f) == 0x82) {
3020 /* STC Rm_BANK, Rn */
3021 ic->f = instr(copy_privileged_register);
3022 ic->arg[0] = (size_t)&cpu->cd.sh.r_bank[(lo8 >> 4) & 7];
3023 } else if (iword == SH_INVALID_INSTR) {
3024 /* PROM emulation (GXemul specific) */
3025 ic->f = instr(prom_emul);
3026 } else {
3027 switch (lo8) {
3028 case 0x02: /* STC SR,Rn */
3029 ic->f = instr(copy_privileged_register);
3030 ic->arg[0] = (size_t)&cpu->cd.sh.sr;
3031 break;
3032 case 0x03: /* BSRF Rn */
3033 ic->f = instr(bsrf_rn);
3034 ic->arg[0] = (int32_t) (addr &
3035 ((SH_IC_ENTRIES_PER_PAGE-1)
3036 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4;
3037 /* arg[1] is Rn */
3038 break;
3039 case 0x09: /* NOP */
3040 ic->f = instr(nop);
3041 if (iword & 0x0f00) {
3042 if (!cpu->translation_readahead)
3043 fatal("Unimplemented NOP"
3044 " variant?\n");
3045 goto bad;
3046 }
3047 break;
3048 case 0x0a: /* STS MACH,Rn */
3049 ic->f = instr(mov_rm_rn);
3050 ic->arg[0] = (size_t)&cpu->cd.sh.mach;
3051 break;
3052 case 0x12: /* STC GBR,Rn */
3053 ic->f = instr(mov_rm_rn);
3054 ic->arg[0] = (size_t)&cpu->cd.sh.gbr;
3055 break;
3056 case 0x1a: /* STS MACL,Rn */
3057 ic->f = instr(mov_rm_rn);
3058 ic->arg[0] = (size_t)&cpu->cd.sh.macl;
3059 break;
3060 case 0x22: /* STC VBR,Rn */
3061 ic->f = instr(copy_privileged_register);
3062 ic->arg[0] = (size_t)&cpu->cd.sh.vbr;
3063 break;
3064 case 0x23: /* BRAF Rn */
3065 ic->f = instr(braf_rn);
3066 ic->arg[0] = (int32_t) (addr &
3067 ((SH_IC_ENTRIES_PER_PAGE-1)
3068 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4;
3069 /* arg[1] is Rn */
3070 break;
3071 case 0x29: /* MOVT Rn */
3072 ic->f = instr(movt_rn);
3073 break;
3074 case 0x2a: /* STS PR,Rn */
3075 ic->f = instr(mov_rm_rn);
3076 ic->arg[0] = (size_t)&cpu->cd.sh.pr;
3077 break;
3078 case 0x32: /* STC SSR,Rn */
3079 ic->f = instr(copy_privileged_register);
3080 ic->arg[0] = (size_t)&cpu->cd.sh.ssr;
3081 break;
3082 case 0x42: /* STC SPC,Rn */
3083 ic->f = instr(copy_privileged_register);
3084 ic->arg[0] = (size_t)&cpu->cd.sh.spc;
3085 break;
3086 case 0x5a: /* STS FPUL,Rn */
3087 ic->f = instr(copy_fp_register);
3088 ic->arg[0] = (size_t)&cpu->cd.sh.fpul;
3089 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3090 break;
3091 case 0x6a: /* STS FPSCR,Rn */
3092 ic->f = instr(copy_fp_register);
3093 ic->arg[0] = (size_t)&cpu->cd.sh.fpscr;
3094 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3095 break;
3096 case 0x83: /* PREF @Rn */
3097 ic->f = instr(pref_rn);
3098 break;
3099 case 0x93: /* OCBI @Rn */
3100 /* Treat as nop for now: */
3101 /* TODO: Implement this. */
3102 ic->f = instr(nop);
3103 break;
3104 case 0xa3: /* OCBP @Rn */
3105 /* Treat as nop for now: */
3106 /* TODO: Implement this. */
3107 ic->f = instr(nop);
3108 break;
3109 case 0xb3: /* OCBWB @Rn */
3110 /* Treat as nop for now: */
3111 /* TODO: Implement this. */
3112 ic->f = instr(nop);
3113 break;
3114 case 0xc3: /* MOVCA.L R0,@Rn */
3115 /* Treat as nop for now: */
3116 /* TODO: Implement this. */
3117 ic->f = instr(nop);
3118 break;
3119 case 0xfa: /* STC DBR,Rn */
3120 ic->f = instr(copy_privileged_register);
3121 ic->arg[0] = (size_t)&cpu->cd.sh.dbr;
3122 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3123 break;
3124 default:if (!cpu->translation_readahead)
3125 fatal("Unimplemented opcode 0x%x,"
3126 "0x%03x\n", main_opcode,
3127 iword & 0xfff);
3128 goto bad;
3129 }
3130 }
3131 break;
3132
3133 case 0x1:
3134 ic->f = instr(mov_l_rm_disp_rn);
3135 ic->arg[1] = r8 + (lo4 << 4);
3136 break;
3137
3138 case 0x2:
3139 switch (lo4) {
3140 case 0x0: /* MOV.B Rm,@Rn */
3141 ic->f = instr(mov_b_store_rm_rn);
3142 break;
3143 case 0x1: /* MOV.W Rm,@Rn */
3144 ic->f = instr(mov_w_store_rm_rn);
3145 break;
3146 case 0x2: /* MOV.L Rm,@Rn */
3147 ic->f = instr(mov_l_store_rm_rn);
3148 break;
3149 case 0x4: /* MOV.B Rm,@-Rn */
3150 ic->f = instr(mov_b_rm_predec_rn);
3151 break;
3152 case 0x5: /* MOV.W Rm,@-Rn */
3153 ic->f = instr(mov_w_rm_predec_rn);
3154 break;
3155 case 0x6: /* MOV.L Rm,@-Rn */
3156 ic->f = instr(mov_l_rm_predec_rn);
3157 break;
3158 case 0x7: /* DIV0S Rm,Rn */
3159 ic->f = instr(div0s_rm_rn);
3160 break;
3161 case 0x8: /* TST Rm,Rn */
3162 ic->f = instr(tst_rm_rn);
3163 if (r8 == r4)
3164 ic->f = instr(tst_rm);
3165 break;
3166 case 0x9: /* AND Rm,Rn */
3167 ic->f = instr(and_rm_rn);
3168 break;
3169 case 0xa: /* XOR Rm,Rn */
3170 ic->f = instr(xor_rm_rn);
3171 break;
3172 case 0xb: /* OR Rm,Rn */
3173 ic->f = instr(or_rm_rn);
3174 break;
3175 case 0xc: /* CMP/STR Rm,Rn */
3176 ic->f = instr(cmp_str_rm_rn);
3177 break;
3178 case 0xd: /* XTRCT Rm,Rn */
3179 ic->f = instr(xtrct_rm_rn);
3180 break;
3181 case 0xe: /* MULU.W Rm,Rn */
3182 ic->f = instr(mulu_w_rm_rn);
3183 break;
3184 case 0xf: /* MULS.W Rm,Rn */
3185 ic->f = instr(muls_w_rm_rn);
3186 break;
3187 default:if (!cpu->translation_readahead)
3188 fatal("Unimplemented opcode 0x%x,0x%x\n",
3189 main_opcode, lo4);
3190 goto bad;
3191 }
3192 break;
3193
3194 case 0x3:
3195 switch (lo4) {
3196 case 0x0: /* CMP/EQ Rm,Rn */
3197 ic->f = instr(cmpeq_rm_rn);
3198 break;
3199 case 0x2: /* CMP/HS Rm,Rn */
3200 ic->f = instr(cmphs_rm_rn);
3201 break;
3202 case 0x3: /* CMP/GE Rm,Rn */
3203 ic->f = instr(cmpge_rm_rn);
3204 break;
3205 case 0x4: /* DIV1 Rm,Rn */
3206 ic->f = instr(div1_rm_rn);
3207 break;
3208 case 0x5: /* DMULU.L Rm,Rn */
3209 ic->f = instr(dmulu_l_rm_rn);
3210 break;
3211 case 0x6: /* CMP/HI Rm,Rn */
3212 ic->f = instr(cmphi_rm_rn);
3213 break;
3214 case 0x7: /* CMP/GT Rm,Rn */
3215 ic->f = instr(cmpgt_rm_rn);
3216 break;
3217 case 0x8: /* SUB Rm,Rn */
3218 ic->f = instr(sub_rm_rn);
3219 break;
3220 case 0xa: /* SUBC Rm,Rn */
3221 ic->f = instr(subc_rm_rn);
3222 break;
3223 case 0xc: /* ADD Rm,Rn */
3224 ic->f = instr(add_rm_rn);
3225 break;
3226 case 0xd: /* DMULS.L Rm,Rn */
3227 ic->f = instr(dmuls_l_rm_rn);
3228 break;
3229 case 0xe: /* ADDC Rm,Rn */
3230 ic->f = instr(addc_rm_rn);
3231 break;
3232 default:if (!cpu->translation_readahead)
3233 fatal("Unimplemented opcode 0x%x,0x%x\n",
3234 main_opcode, lo4);
3235 goto bad;
3236 }
3237 break;
3238
3239 case 0x4:
3240 if (lo4 == 0xc) {
3241 ic->f = instr(shad);
3242 } else if (lo4 == 0xd) {
3243 ic->f = instr(shld);
3244 } else if ((lo8 & 0x8f) == 0x83) {
3245 /* STC.L Rm_BANK,@-Rn */
3246 ic->f = instr(stc_l_rm_predec_rn_md);
3247 ic->arg[0] = (size_t)&cpu->cd.sh.r_bank[
3248 (lo8 >> 4) & 7]; /* m */
3249 } else if ((lo8 & 0x8f) == 0x87) {
3250 /* LDC.L @Rm+,Rn_BANK */
3251 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3252 ic->arg[0] = (size_t)&cpu->cd.sh.r_bank[(lo8 >> 4) & 7];
3253 } else if ((lo8 & 0x8f) == 0x8e) {
3254 /* LDC Rm, Rn_BANK */
3255 ic->f = instr(copy_privileged_register);
3256 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8];
3257 ic->arg[1] = (size_t)&cpu->cd.sh.r_bank[(lo8 >> 4) & 7];
3258 } else {
3259 switch (lo8) {
3260 case 0x00: /* SHLL Rn */
3261 ic->f = instr(shll_rn);
3262 break;
3263 case 0x01: /* SHLR Rn */
3264 ic->f = instr(shlr_rn);
3265 break;
3266 case 0x02: /* STS.L MACH,@-Rn */
3267 ic->f = instr(mov_l_rm_predec_rn);
3268 ic->arg[0] = (size_t)&cpu->cd.sh.mach;
3269 break;
3270 case 0x03: /* STC.L SR,@-Rn */
3271 ic->f = instr(stc_l_rm_predec_rn_md);
3272 ic->arg[0] = (size_t)&cpu->cd.sh.sr;
3273 break;
3274 case 0x04: /* ROTL Rn */
3275 ic->f = instr(rotl_rn);
3276 break;
3277 case 0x05: /* ROTR Rn */
3278 ic->f = instr(rotr_rn);
3279 break;
3280 case 0x06: /* LDS.L @Rm+,MACH */
3281 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3282 ic->arg[0] = (size_t)&cpu->cd.sh.mach;
3283 break;
3284 case 0x07: /* LDC.L @Rm+,SR */
3285 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3286 ic->arg[0] = (size_t)&cpu->cd.sh.sr;
3287 break;
3288 case 0x08: /* SHLL2 Rn */
3289 ic->f = instr(shll2_rn);
3290 break;
3291 case 0x09: /* SHLR2 Rn */
3292 ic->f = instr(shlr2_rn);
3293 break;
3294 case 0x0b: /* JSR @Rn */
3295 if (cpu->machine->show_trace_tree)
3296 ic->f = instr(jsr_rn_trace);
3297 else
3298 ic->f = instr(jsr_rn);
3299 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3300 ic->arg[1] = (addr & 0xffe) + 4;
3301 break;
3302 case 0x0e: /* LDC Rm,SR */
3303 ic->f = instr(ldc_rm_sr);
3304 break;
3305 case 0x10: /* DT Rn */
3306 ic->f = instr(dt_rn);
3307 break;
3308 case 0x11: /* CMP/PZ Rn */
3309 ic->f = instr(cmppz_rn);
3310 break;
3311 case 0x12: /* STS.L MACL,@-Rn */
3312 ic->f = instr(mov_l_rm_predec_rn);
3313 ic->arg[0] = (size_t)&cpu->cd.sh.macl;
3314 break;
3315 case 0x13: /* STC.L GBR,@-Rn */
3316 ic->f = instr(mov_l_rm_predec_rn);
3317 ic->arg[0] = (size_t)&cpu->cd.sh.gbr;
3318 break;
3319 case 0x15: /* CMP/PL Rn */
3320 ic->f = instr(cmppl_rn);
3321 break;
3322 case 0x16: /* LDS.L @Rm+,MACL */
3323 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3324 ic->arg[0] = (size_t)&cpu->cd.sh.macl;
3325 break;
3326 case 0x17: /* LDC.L @Rm+,GBR */
3327 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3328 ic->arg[0] = (size_t)&cpu->cd.sh.gbr;
3329 break;
3330 case 0x18: /* SHLL8 Rn */
3331 ic->f = instr(shll8_rn);
3332 break;
3333 case 0x19: /* SHLR8 Rn */
3334 ic->f = instr(shlr8_rn);
3335 break;
3336 case 0x1b: /* TAS.B @Rn */
3337 ic->f = instr(tas_b_rn);
3338 break;
3339 case 0x1e: /* LDC Rm,GBR */
3340 ic->f = instr(mov_rm_rn);
3341 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3342 ic->arg[1] = (size_t)&cpu->cd.sh.gbr;
3343 break;
3344 case 0x20: /* SHAL Rn */
3345 ic->f = instr(shll_rn); /* NOTE: shll */
3346 break;
3347 case 0x21: /* SHAR Rn */
3348 ic->f = instr(shar_rn);
3349 break;
3350 case 0x22: /* STS.L PR,@-Rn */
3351 ic->f = instr(mov_l_rm_predec_rn);
3352 ic->arg[0] = (size_t)&cpu->cd.sh.pr; /* m */
3353 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3354 break;
3355 case 0x23: /* STC.L VBR,@-Rn */
3356 ic->f = instr(stc_l_rm_predec_rn_md);
3357 ic->arg[0] = (size_t)&cpu->cd.sh.vbr;
3358 break;
3359 case 0x24: /* ROTCL Rn */
3360 ic->f = instr(rotcl_rn);
3361 break;
3362 case 0x25: /* ROTCR Rn */
3363 ic->f = instr(rotcr_rn);
3364 break;
3365 case 0x26: /* LDS.L @Rm+,PR */
3366 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3367 ic->arg[0] = (size_t)&cpu->cd.sh.pr;
3368 break;
3369 case 0x27: /* LDC.L @Rm+,VBR */
3370 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3371 ic->arg[0] = (size_t)&cpu->cd.sh.vbr;
3372 break;
3373 case 0x28: /* SHLL16 Rn */
3374 ic->f = instr(shll16_rn);
3375 break;
3376 case 0x29: /* SHLR16 Rn */
3377 ic->f = instr(shlr16_rn);
3378 break;
3379 case 0x2a: /* LDS Rm,PR */
3380 ic->f = instr(mov_rm_rn);
3381 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3382 ic->arg[1] = (size_t)&cpu->cd.sh.pr;
3383 break;
3384 case 0x2b: /* JMP @Rn */
3385 if (cpu->machine->show_trace_tree)
3386 ic->f = instr(jmp_rn_trace);
3387 else
3388 ic->f = instr(jmp_rn);
3389 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3390 ic->arg[1] = (addr & 0xffe) + 4;
3391 break;
3392 case 0x2e: /* LDC Rm,VBR */
3393 ic->f = instr(copy_privileged_register);
3394 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3395 ic->arg[1] = (size_t)&cpu->cd.sh.vbr;
3396 break;
3397 case 0x33: /* STC.L SSR,@-Rn */
3398 ic->f = instr(stc_l_rm_predec_rn_md);
3399 ic->arg[0] = (size_t)&cpu->cd.sh.ssr;
3400 break;
3401 case 0x37: /* LDC.L @Rm+,SSR */
3402 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3403 ic->arg[0] = (size_t)&cpu->cd.sh.ssr;
3404 break;
3405 case 0x3e: /* LDC rm,SSR */
3406 ic->f = instr(copy_privileged_register);
3407 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3408 ic->arg[1] = (size_t)&cpu->cd.sh.ssr;
3409 break;
3410 case 0x43: /* STC.L SPC,@-Rn */
3411 ic->f = instr(stc_l_rm_predec_rn_md);
3412 ic->arg[0] = (size_t)&cpu->cd.sh.spc;
3413 break;
3414 case 0x47: /* LDC.L @Rm+,SPC */
3415 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3416 ic->arg[0] = (size_t)&cpu->cd.sh.spc;
3417 break;
3418 case 0x4e: /* LDC rm,SPC */
3419 ic->f = instr(copy_privileged_register);
3420 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3421 ic->arg[1] = (size_t)&cpu->cd.sh.spc;
3422 break;
3423 case 0x52: /* STS.L FPUL,@-Rn */
3424 ic->f = instr(mov_l_rm_predec_rn);
3425 ic->arg[0] = (size_t)&cpu->cd.sh.fpul;
3426 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3427 break;
3428 case 0x56: /* LDS.L @Rm+,FPUL */
3429 ic->f = instr(mov_l_arg1_postinc_to_arg0_fp);
3430 ic->arg[0] = (size_t)&cpu->cd.sh.fpul;
3431 break;
3432 case 0x5a: /* LDS Rm,FPUL */
3433 ic->f = instr(copy_fp_register);
3434 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3435 ic->arg[1] = (size_t)&cpu->cd.sh.fpul;
3436 break;
3437 case 0x62: /* STS.L FPSCR,@-Rn */
3438 ic->f = instr(mov_l_rm_predec_rn);
3439 ic->arg[0] = (size_t)&cpu->cd.sh.fpscr;
3440 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3441 break;
3442 case 0x66: /* LDS.L @Rm+,FPSCR */
3443 /* Note: Loading into FPSCR is a specia
3444 case (need to call sh_update_fpsrc()). */
3445 ic->f = instr(mov_l_arg1_postinc_to_arg0_fp);
3446 ic->arg[0] = (size_t)&cpu->cd.sh.fpscr;
3447 break;
3448 case 0x6a: /* LDS Rm,FPSCR */
3449 ic->f = instr(lds_rm_fpscr);
3450 /* arg 1 = R8 = Rm */
3451 break;
3452 case 0xfa: /* LDC Rm,DBR */
3453 ic->f = instr(copy_privileged_register);
3454 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8];
3455 ic->arg[1] = (size_t)&cpu->cd.sh.dbr;
3456 break;
3457 default:if (!cpu->translation_readahead)
3458 fatal("Unimplemented opcode 0x%x,"
3459 "0x%02x\n", main_opcode, lo8);
3460 goto bad;
3461 }
3462 }
3463 break;
3464
3465 case 0x5:
3466 ic->f = instr(mov_l_disp_rm_rn);
3467 ic->arg[0] = r4 + (lo4 << 4);
3468 break;
3469
3470 case 0x6:
3471 switch (lo4) {
3472 case 0x0: /* MOV.B @Rm,Rn */
3473 ic->f = instr(load_b_rm_rn);
3474 break;
3475 case 0x1: /* MOV.W @Rm,Rn */
3476 ic->f = instr(load_w_rm_rn);
3477 break;
3478 case 0x2: /* MOV.L @Rm,Rn */
3479 ic->f = instr(load_l_rm_rn);
3480 break;
3481 case 0x3: /* MOV Rm,Rn */
3482 ic->f = instr(mov_rm_rn);
3483 break;
3484 case 0x4: /* MOV.B @Rm+,Rn */
3485 ic->f = instr(mov_b_arg1_postinc_to_arg0);
3486 /* Note: Order */
3487 ic->arg[1] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3488 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3489 break;
3490 case 0x5: /* MOV.W @Rm+,Rn */
3491 ic->f = instr(mov_w_arg1_postinc_to_arg0);
3492 /* Note: Order */
3493 ic->arg[1] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3494 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3495 break;
3496 case 0x6: /* MOV.L @Rm+,Rn */
3497 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3498 /* Note: Order */
3499 ic->arg[1] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3500 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3501 break;
3502 case 0x7: /* NOT Rm,Rn */
3503 ic->f = instr(not_rm_rn);
3504 break;
3505 case 0x8: /* SWAP.B Rm,Rn */
3506 ic->f = instr(swap_b_rm_rn);
3507 break;
3508 case 0x9: /* SWAP.W Rm,Rn */
3509 ic->f = instr(swap_w_rm_rn);
3510 break;
3511 case 0xa: /* NEGC Rm,Rn */
3512 ic->f = instr(negc_rm_rn);
3513 break;
3514 case 0xb: /* NEG Rm,Rn */
3515 ic->f = instr(neg_rm_rn);
3516 break;
3517 case 0xc: /* EXTU.B Rm,Rn */
3518 ic->f = instr(extu_b_rm_rn);
3519 if (r8 == r4)
3520 ic->f = instr(extu_b_rm);
3521 break;
3522 case 0xd: /* EXTU.W Rm,Rn */
3523 ic->f = instr(extu_w_rm_rn);
3524 if (r8 == r4)
3525 ic->f = instr(extu_w_rm);
3526 break;
3527 case 0xe: /* EXTS.B Rm,Rn */
3528 ic->f = instr(exts_b_rm_rn);
3529 break;
3530 case 0xf: /* EXTS.W Rm,Rn */
3531 ic->f = instr(exts_w_rm_rn);
3532 break;
3533 default:if (!cpu->translation_readahead)
3534 fatal("Unimplemented opcode 0x%x,0x%x\n",
3535 main_opcode, lo4);
3536 goto bad;
3537 }
3538 break;
3539
3540 case 0x7: /* ADD #imm,Rn */
3541 ic->f = instr(add_imm_rn);
3542 ic->arg[0] = (int8_t)lo8;
3543 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3544 if (lo8 == 1)
3545 ic->f = instr(inc_rn);
3546 if (lo8 == 4)
3547 ic->f = instr(add_4_rn);
3548 if (lo8 == 0xfc)
3549 ic->f = instr(sub_4_rn);
3550 if (lo8 == 0xff)
3551 ic->f = instr(dec_rn);
3552 break;
3553
3554 case 0x8:
3555 /* Displacement from beginning of page = default arg 0. */
3556 ic->arg[0] = (int8_t)lo8 * 2 +
3557 (addr & ((SH_IC_ENTRIES_PER_PAGE-1)
3558 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4;
3559 samepage_function = NULL;
3560
3561 switch (r8) {
3562 case 0x0: /* MOV.B R0,@(disp,Rn) */
3563 ic->f = instr(mov_b_r0_disp_rn);
3564 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* n */
3565 ic->arg[1] = lo4;
3566 break;
3567 case 0x1: /* MOV.W R0,@(disp,Rn) */
3568 ic->f = instr(mov_w_r0_disp_rn);
3569 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* n */
3570 ic->arg[1] = lo4 * 2;
3571 break;
3572 case 0x4: /* MOV.B @(disp,Rn),R0 */
3573 ic->f = instr(mov_b_disp_rn_r0);
3574 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* n */
3575 ic->arg[1] = lo4;
3576 break;
3577 case 0x5: /* MOV.W @(disp,Rn),R0 */
3578 ic->f = instr(mov_w_disp_rn_r0);
3579 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* n */
3580 ic->arg[1] = lo4 * 2;
3581 break;
3582 case 0x8: /* CMP/EQ #imm,R0 */
3583 ic->f = instr(cmpeq_imm_r0);
3584 ic->arg[0] = (int8_t)lo8;
3585 break;
3586 case 0x9: /* BT (disp,PC) */
3587 ic->f = instr(bt);
3588 samepage_function = instr(bt_samepage);
3589 break;
3590 case 0xb: /* BF (disp,PC) */
3591 ic->f = instr(bf);
3592 samepage_function = instr(bf_samepage);
3593 break;
3594 case 0xd: /* BT/S (disp,PC) */
3595 ic->f = instr(bt_s);
3596 samepage_function = instr(bt_s_samepage);
3597 break;
3598 case 0xf: /* BF/S (disp,PC) */
3599 ic->f = instr(bf_s);
3600 samepage_function = instr(bf_s_samepage);
3601 break;
3602 default:if (!cpu->translation_readahead)
3603 fatal("Unimplemented opcode 0x%x,0x%x\n",
3604 main_opcode, r8);
3605 goto bad;
3606 }
3607
3608 /* samepage branches: */
3609 if (samepage_function != NULL && ic->arg[0] < 0x1000 &&
3610 (addr & 0xfff) < 0xffe) {
3611 ic->arg[1] = (size_t) (cpu->cd.sh.cur_ic_page +
3612 (ic->arg[0] >> SH_INSTR_ALIGNMENT_SHIFT));
3613 ic->f = samepage_function;
3614 }
3615
3616 break;
3617
3618 case 0x9: /* MOV.W @(disp,PC),Rn */
3619 ic->f = instr(mov_w_disp_pc_rn);
3620 ic->arg[0] = lo8 * 2 + (addr & ((SH_IC_ENTRIES_PER_PAGE-1)
3621 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4;
3622
3623 /* If the word is reachable from the same page as the
3624 current address, then optimize it as a mov_imm_rn: */
3625 if (ic->arg[0] < 0x1000 && page != NULL) {
3626 uint16_t *p = (uint16_t *) page;
3627 uint16_t data = p[ic->arg[0] >> 1];
3628 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3629 data = LE16_TO_HOST(data);
3630 else
3631 data = BE16_TO_HOST(data);
3632 ic->f = instr(mov_imm_rn);
3633 ic->arg[0] = (int16_t) data;
3634 }
3635 break;
3636
3637 case 0xa: /* BRA disp */
3638 case 0xb: /* BSR disp */
3639 samepage_function = NULL;
3640
3641 switch (main_opcode) {
3642 case 0xa:
3643 ic->f = instr(bra);
3644 samepage_function = instr(bra_samepage);
3645 break;
3646 case 0xb:
3647 ic->f = instr(bsr);
3648 samepage_function = instr(bsr_samepage);
3649 break;
3650 }
3651
3652 ic->arg[0] = (int32_t) ( (addr & ((SH_IC_ENTRIES_PER_PAGE-1)
3653 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4 +
3654 (((int32_t)(int16_t)((iword & 0xfff) << 4)) >> 3) );
3655
3656 /* samepage branches: */
3657 if (samepage_function != NULL && ic->arg[0] < 0x1000 &&
3658 (addr & 0xfff) < 0xffe) {
3659 ic->arg[0] = (size_t) (cpu->cd.sh.cur_ic_page +
3660 (ic->arg[0] >> SH_INSTR_ALIGNMENT_SHIFT));
3661 ic->f = samepage_function;
3662 }
3663 break;
3664
3665 case 0xc:
3666 switch (r8) {
3667 case 0x0:
3668 ic->f = instr(mov_b_r0_disp_gbr);
3669 ic->arg[1] = lo8;
3670 break;
3671 case 0x1:
3672 ic->f = instr(mov_w_r0_disp_gbr);
3673 ic->arg[1] = lo8 << 1;
3674 break;
3675 case 0x2:
3676 ic->f = instr(mov_l_r0_disp_gbr);
3677 ic->arg[1] = lo8 << 2;
3678 break;
3679 case 0x3:
3680 ic->f = instr(trapa);
3681 ic->arg[0] = lo8 << 2;
3682 break;
3683 case 0x4:
3684 ic->f = instr(mov_b_disp_gbr_r0);
3685 ic->arg[1] = lo8;
3686 break;
3687 case 0x5:
3688 ic->f = instr(mov_w_disp_gbr_r0);
3689 ic->arg[1] = lo8 << 1;
3690 break;
3691 case 0x6:
3692 ic->f = instr(mov_l_disp_gbr_r0);
3693 ic->arg[1] = lo8 << 2;
3694 break;
3695 case 0x7: /* MOVA @(disp,pc),R0 */
3696 ic->f = instr(mova_r0);
3697 ic->arg[0] = lo8 * 4 + (addr &
3698 ((SH_IC_ENTRIES_PER_PAGE-1)
3699 << SH_INSTR_ALIGNMENT_SHIFT) & ~3) + 4;
3700 break;
3701 case 0x8: /* TST #imm,R0 */
3702 ic->f = instr(tst_imm_r0);
3703 ic->arg[0] = lo8;
3704 break;
3705 case 0x9: /* AND #imm,R0 */
3706 ic->f = instr(and_imm_r0);
3707 ic->arg[0] = lo8;
3708 break;
3709 case 0xa: /* XOR #imm,R0 */
3710 ic->f = instr(xor_imm_r0);
3711 ic->arg[0] = lo8;
3712 break;
3713 case 0xb: /* OR #imm,R0 */
3714 ic->f = instr(or_imm_r0);
3715 ic->arg[0] = lo8;
3716 break;
3717 case 0xd: /* AND.B #imm,@(R0,GBR) */
3718 ic->f = instr(and_b_imm_r0_gbr);
3719 ic->arg[0] = lo8;
3720 break;
3721 case 0xe: /* XOR.B #imm,@(R0,GBR) */
3722 ic->f = instr(xor_b_imm_r0_gbr);
3723 ic->arg[0] = lo8;
3724 break;
3725 case 0xf: /* OR.B #imm,@(R0,GBR) */
3726 ic->f = instr(or_b_imm_r0_gbr);
3727 ic->arg[0] = lo8;
3728 break;
3729 default:if (!cpu->translation_readahead)
3730 fatal("Unimplemented opcode 0x%x,0x%x\n",
3731 main_opcode, r8);
3732 goto bad;
3733 }
3734 break;
3735
3736 case 0xd: /* MOV.L @(disp,PC),Rn */
3737 ic->f = instr(mov_l_disp_pc_rn);
3738 ic->arg[0] = lo8 * 4 + (addr & ((SH_IC_ENTRIES_PER_PAGE-1)
3739 << SH_INSTR_ALIGNMENT_SHIFT) & ~3) + 4;
3740
3741 /* If the word is reachable from the same page as the
3742 current address, then optimize it as a mov_imm_rn: */
3743 if (ic->arg[0] < 0x1000 && page != NULL) {
3744 uint32_t *p = (uint32_t *) page;
3745 uint32_t data = p[ic->arg[0] >> 2];
3746 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3747 data = LE32_TO_HOST(data);
3748 else
3749 data = BE32_TO_HOST(data);
3750 ic->f = instr(mov_imm_rn);
3751 ic->arg[0] = data;
3752 }
3753 break;
3754
3755 case 0xe: /* MOV #imm,Rn */
3756 ic->f = instr(mov_imm_rn);
3757 ic->arg[0] = (int8_t)lo8;
3758 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3759 if (lo8 == 0)
3760 ic->f = instr(mov_0_rn);
3761 break;
3762
3763 case 0xf:
3764 if (lo4 == 0x0) {
3765 /* FADD FRm,FRn */
3766 ic->f = instr(fadd_frm_frn);
3767 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3768 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3769 } else if (lo4 == 0x1) {
3770 /* FSUB FRm,FRn */
3771 ic->f = instr(fsub_frm_frn);
3772 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3773 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3774 } else if (lo4 == 0x2) {
3775 /* FMUL FRm,FRn */
3776 ic->f = instr(fmul_frm_frn);
3777 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3778 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3779 } else if (lo4 == 0x3) {
3780 /* FDIV FRm,FRn */
3781 ic->f = instr(fdiv_frm_frn);
3782 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3783 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3784 } else if (lo4 == 0x4) {
3785 /* FCMP/EQ FRm,FRn */
3786 ic->f = instr(fcmp_eq_frm_frn);
3787 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3788 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3789 } else if (lo4 == 0x5) {
3790 /* FCMP/GT FRm,FRn */
3791 ic->f = instr(fcmp_gt_frm_frn);
3792 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3793 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3794 } else if (lo4 == 0x6) {
3795 /* FMOV @(R0,Rm),FRn */
3796 ic->f = instr(fmov_r0_rm_frn);
3797 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3798 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3799 } else if (lo4 == 0x7) {
3800 /* FMOV FRm,@(R0,Rn) */
3801 ic->f = instr(fmov_frm_r0_rn);
3802 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4]; /* m */
3803 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3804 } else if (lo4 == 0x8) {
3805 /* FMOV @Rm,FRn */
3806 ic->f = instr(fmov_rm_frn);
3807 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3808 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3809 } else if (lo4 == 0x9) {
3810 /* FMOV @Rm+,FRn */
3811 ic->f = instr(fmov_rm_postinc_frn);
3812 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3813 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3814 } else if (lo4 == 0xa) {
3815 /* FMOV FRm,@Rn */
3816 ic->f = instr(fmov_frm_rn);
3817 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4]; /* m */
3818 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3819 } else if (lo4 == 0xb) {
3820 /* FMOV FRm,@-Rn */
3821 ic->f = instr(fmov_frm_predec_rn);
3822 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4]; /* m */
3823 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3824 } else if (lo4 == 0xc) {
3825 /* FMOV FRm,FRn */
3826 ic->f = instr(fmov_frm_frn);
3827 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3828 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3829 } else if (lo8 == 0x0d) {
3830 /* FSTS FPUL,FRn */
3831 ic->f = instr(copy_fp_register);
3832 ic->arg[0] = (size_t)&cpu->cd.sh.fpul;
3833 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3834 } else if (lo8 == 0x1d) {
3835 /* FLDS FRn,FPUL */
3836 ic->f = instr(copy_fp_register);
3837 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3838 ic->arg[1] = (size_t)&cpu->cd.sh.fpul;
3839 } else if (lo8 == 0x2d) {
3840 /* FLOAT FPUL,FRn */
3841 ic->f = instr(float_fpul_frn);
3842 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3843 } else if (lo8 == 0x3d) {
3844 /* FTRC FRm,FPUL */
3845 ic->f = instr(ftrc_frm_fpul);
3846 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3847 } else if (lo8 == 0x4d) {
3848 /* FNEG FRn */
3849 ic->f = instr(fneg_frn);
3850 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3851 } else if (lo8 == 0x5d) {
3852 /* FABS FRn */
3853 ic->f = instr(fabs_frn);
3854 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3855 } else if (lo8 == 0x6d) {
3856 /* FSQRT FRn */
3857 ic->f = instr(fsqrt_frn);
3858 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3859 } else if (lo8 == 0x8d) {
3860 /* FLDI0 FRn */
3861 ic->f = instr(fldi_frn);
3862 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3863 ic->arg[1] = 0x00000000;
3864 } else if (lo8 == 0x9d) {
3865 /* FLDI1 FRn */
3866 ic->f = instr(fldi_frn);
3867 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3868 ic->arg[1] = 0x3f800000;
3869 } else if ((iword & 0x01ff) == 0x00ad) {
3870 /* FCNVSD FPUL,DRn */
3871 ic->f = instr(fcnvsd_fpul_drn);
3872 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3873 } else if ((iword & 0x01ff) == 0x00bd) {
3874 /* FCNVDS DRm,FPUL */
3875 ic->f = instr(fcnvds_drm_fpul);
3876 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3877 } else if ((iword & 0x01ff) == 0x00fd) {
3878 /* FSCA FPUL,DRn */
3879 ic->f = instr(fsca_fpul_drn);
3880 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3881 } else if (iword == 0xf3fd) {
3882 /* FSCHG */
3883 ic->f = instr(fschg);
3884 } else if (iword == 0xfbfd) {
3885 /* FRCHG */
3886 ic->f = instr(frchg);
3887 } else if ((iword & 0xf3ff) == 0xf1fd) {
3888 /* FTRV XMTRX, FVn */
3889 ic->f = instr(ftrv_xmtrx_fvn);
3890 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8 & 0xc];
3891 } else if (lo4 == 0xe) {
3892 /* FMAC FR0,FRm,FRn */
3893 ic->f = instr(fmac_fr0_frm_frn);
3894 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3895 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3896 } else {
3897 if (!cpu->translation_readahead)
3898 fatal("Unimplemented opcode 0x%x,0x%02x\n",
3899 main_opcode, lo8);
3900 goto bad;
3901 }
3902 break;
3903
3904 default:if (!cpu->translation_readahead)
3905 fatal("Unimplemented main opcode 0x%x\n", main_opcode);
3906 goto bad;
3907 }
3908
3909
3910 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
3911 #include "cpu_dyntrans.c"
3912 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
3913 }
3914

  ViewVC Help
Powered by ViewVC 1.1.26