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

Annotation of /trunk/src/cpus/cpu_sh_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (hide annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 7 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 dpavlin 14 /*
2 dpavlin 34 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 dpavlin 14 *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 42 * $Id: cpu_sh_instr.c,v 1.61 2007/06/04 06:32:25 debug Exp $
29 dpavlin 14 *
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 dpavlin 32 #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 dpavlin 14 /*
67 dpavlin 30 * nop: Nothing
68 dpavlin 14 */
69     X(nop)
70     {
71     }
72    
73    
74 dpavlin 30 /*
75 dpavlin 32 * 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 dpavlin 30 *
122 dpavlin 32 * 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 dpavlin 30 * arg[0] = ptr to rm
145     * arg[1] = ptr to rn
146     */
147 dpavlin 32 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 dpavlin 30 {
152 dpavlin 32 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 dpavlin 30 }
162 dpavlin 32 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 dpavlin 42 /* 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 dpavlin 30
180    
181     /*
182 dpavlin 32 * 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 dpavlin 30 *
187 dpavlin 32 * 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 dpavlin 34 * 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 dpavlin 32 * 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 dpavlin 30 * arg[0] = int8_t imm, extended to at least int32_t
284     * arg[1] = ptr to rn
285     */
286 dpavlin 42 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 dpavlin 32
294    
295     /*
296 dpavlin 36 * 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 dpavlin 32 *
301     * arg[0] = ptr to rm (or other register)
302     * arg[1] = ptr to rn
303     */
304     X(mov_b_rm_predec_rn)
305 dpavlin 30 {
306 dpavlin 32 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 dpavlin 30 }
323 dpavlin 32 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 dpavlin 30
329 dpavlin 32 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
330     data = LE16_TO_HOST(data);
331     else
332     data = BE16_TO_HOST(data);
333 dpavlin 30
334 dpavlin 32 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 dpavlin 36 X(stc_l_rm_predec_rn_md)
374 dpavlin 32 {
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 dpavlin 30 /*
403 dpavlin 32 * mov_l_disp_pc_rn: Load a 32-bit value into a register,
404     * from an immediate address relative to the pc.
405 dpavlin 30 *
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 dpavlin 32 uint32_t addr = ic->arg[0] + (cpu->pc &
412 dpavlin 30 ~((SH_IC_ENTRIES_PER_PAGE-1) << SH_INSTR_ALIGNMENT_SHIFT));
413 dpavlin 32 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 dpavlin 30 }
432    
433    
434     /*
435 dpavlin 32 * mova_r0: Set r0 to an address close to the program counter.
436 dpavlin 30 *
437 dpavlin 32 * 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 dpavlin 40
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 dpavlin 32 }
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 dpavlin 40 /* Ugly special case for FPSCR: */
862     if (ic->arg[0] == (size_t)&cpu->cd.sh.fpscr)
863 dpavlin 32 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 dpavlin 30 * arg[0] = ptr to rm
1018 dpavlin 32 * 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 dpavlin 42 * tst_rm: t = (rm == 0)
1383 dpavlin 32 * xtrct_rm_rn: rn = (rn >> 16) | (rm << 16)
1384     *
1385     * arg[0] = ptr to rm
1386 dpavlin 30 * arg[1] = ptr to rn
1387     */
1388 dpavlin 32 X(add_rm_rn) { reg(ic->arg[1]) += reg(ic->arg[0]); }
1389     X(addc_rm_rn)
1390 dpavlin 30 {
1391 dpavlin 32 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 dpavlin 30 }
1401 dpavlin 32 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 dpavlin 42 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 dpavlin 32 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 dpavlin 30
1437    
1438     /*
1439 dpavlin 32 * 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 dpavlin 30 *
1443 dpavlin 32 * arg[0] = ptr to rm
1444     * arg[1] = ptr to rn
1445 dpavlin 30 */
1446 dpavlin 32 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 dpavlin 42 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 dpavlin 32 if (q)
1456 dpavlin 42 new_sr |= SH_SR_Q;
1457 dpavlin 32 if (m)
1458 dpavlin 42 new_sr |= SH_SR_M;
1459 dpavlin 32 if (m ^ q)
1460 dpavlin 42 new_sr |= SH_SR_T;
1461     cpu->cd.sh.sr = new_sr;
1462 dpavlin 32 }
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 dpavlin 30 X(shll_rn)
1632     {
1633 dpavlin 32 uint32_t rn = reg(ic->arg[1]);
1634 dpavlin 42 if (rn & 0x80000000)
1635 dpavlin 30 cpu->cd.sh.sr |= SH_SR_T;
1636     else
1637     cpu->cd.sh.sr &= ~SH_SR_T;
1638 dpavlin 32 reg(ic->arg[1]) = rn << 1;
1639 dpavlin 30 }
1640 dpavlin 32 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 dpavlin 42 uint32_t rn = reg(ic->arg[1]), x;
1652     if (rn & 0x80000000) {
1653     x = 1;
1654 dpavlin 32 cpu->cd.sh.sr |= SH_SR_T;
1655 dpavlin 42 } else {
1656     x = 0;
1657 dpavlin 32 cpu->cd.sh.sr &= ~SH_SR_T;
1658 dpavlin 42 }
1659     reg(ic->arg[1]) = (rn << 1) | x;
1660 dpavlin 32 }
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 dpavlin 30
1721    
1722     /*
1723 dpavlin 32 * 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 dpavlin 30 *
1726 dpavlin 32 * arg[0] = ptr to rm
1727     * arg[1] = ptr to rn
1728 dpavlin 30 */
1729 dpavlin 32 X(shad)
1730 dpavlin 30 {
1731 dpavlin 32 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 dpavlin 42 * arg[0] = immediate offset relative to start of page,
1770     * or ptr to target instruction, for samepage branches
1771 dpavlin 32 * 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 dpavlin 42 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 dpavlin 32 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 dpavlin 42 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 dpavlin 32 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 dpavlin 42 * arg[1] = for samepage functions, the new instruction pointer
1874 dpavlin 32 */
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 dpavlin 30 }
1883 dpavlin 32 }
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 dpavlin 42 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 dpavlin 32 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 dpavlin 42 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 dpavlin 30
1974 dpavlin 32
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 dpavlin 30 }
1994 dpavlin 32 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 dpavlin 30
2047    
2048     /*
2049 dpavlin 32 * 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 dpavlin 34 /* 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 dpavlin 40 0, INVALIDATE_ALL);
2126 dpavlin 34 }
2127 dpavlin 32 }
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 dpavlin 30 X(ldc_rm_sr)
2150     {
2151 dpavlin 32 RES_INST_IF_NOT_MD;
2152     sh_update_sr(cpu, reg(ic->arg[1]));
2153 dpavlin 40
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 dpavlin 32 }
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 dpavlin 40 * 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 dpavlin 32 * 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 dpavlin 30 exit(1);
2711     }
2712    
2713 dpavlin 32 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 dpavlin 30 }
2730    
2731    
2732 dpavlin 32 /*
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 dpavlin 36 * prom_emul:
2767 dpavlin 32 */
2768 dpavlin 36 X(prom_emul)
2769 dpavlin 32 {
2770     uint32_t old_pc;
2771     SYNCH_PC;
2772     old_pc = cpu->pc;
2773    
2774 dpavlin 36 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 dpavlin 32
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 dpavlin 14 /*****************************************************************************/
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 dpavlin 32 cpu->pc += (SH_IC_ENTRIES_PER_PAGE << SH_INSTR_ALIGNMENT_SHIFT);
2805 dpavlin 14
2806     /* end_of_page doesn't count as an executed instruction: */
2807     cpu->n_translated_instrs --;
2808 dpavlin 32
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 dpavlin 14 }
2846    
2847    
2848 dpavlin 32 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 dpavlin 14 /*****************************************************************************/
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 dpavlin 20 uint64_t addr, low_pc;
2884 dpavlin 14 uint32_t iword;
2885     unsigned char *page;
2886 dpavlin 42 unsigned char ib[2];
2887     int main_opcode, isize = sizeof(ib);
2888 dpavlin 30 int in_crosspage_delayslot = 0, r8, r4, lo4, lo8;
2889 dpavlin 42 void (*samepage_function)(struct cpu *, struct sh_instr_call *);
2890 dpavlin 14
2891     /* Figure out the (virtual) address of the instruction: */
2892 dpavlin 30 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 dpavlin 14 }
2901    
2902 dpavlin 30 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 dpavlin 14 /* Read the instruction word from memory: */
2909 dpavlin 30 #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 dpavlin 14
2926     if (page != NULL) {
2927     /* fatal("TRANSLATION HIT!\n"); */
2928 dpavlin 30 memcpy(ib, page + (addr & 0xfff), isize);
2929 dpavlin 14 } else {
2930     /* fatal("TRANSLATION MISS!\n"); */
2931     if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2932 dpavlin 30 isize, MEM_READ, CACHE_INSTRUCTION)) {
2933     fatal("to_be_translated(): read failed: TODO\n");
2934 dpavlin 14 goto bad;
2935     }
2936     }
2937    
2938 dpavlin 42 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 dpavlin 14
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 dpavlin 32 /* 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 dpavlin 14 switch (main_opcode) {
2964    
2965 dpavlin 30 case 0x0:
2966 dpavlin 32 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 dpavlin 34 } else if (iword == SH_INVALID_INSTR) {
3024 dpavlin 36 /* PROM emulation (GXemul specific) */
3025     ic->f = instr(prom_emul);
3026 dpavlin 32 } 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 dpavlin 42 if (!cpu->translation_readahead)
3043     fatal("Unimplemented NOP"
3044     " variant?\n");
3045 dpavlin 32 goto bad;
3046     }
3047     break;
3048     case 0x0a: /* STS MACH,Rn */
3049 dpavlin 40 ic->f = instr(mov_rm_rn);
3050     ic->arg[0] = (size_t)&cpu->cd.sh.mach;
3051 dpavlin 32 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 dpavlin 40 ic->f = instr(mov_rm_rn);
3058     ic->arg[0] = (size_t)&cpu->cd.sh.macl;
3059 dpavlin 32 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 dpavlin 40 ic->f = instr(mov_rm_rn);
3076     ic->arg[0] = (size_t)&cpu->cd.sh.pr;
3077 dpavlin 32 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 dpavlin 42 default:if (!cpu->translation_readahead)
3125     fatal("Unimplemented opcode 0x%x,"
3126     "0x%03x\n", main_opcode,
3127     iword & 0xfff);
3128 dpavlin 30 goto bad;
3129     }
3130     }
3131     break;
3132    
3133 dpavlin 32 case 0x1:
3134     ic->f = instr(mov_l_rm_disp_rn);
3135     ic->arg[1] = r8 + (lo4 << 4);
3136     break;
3137    
3138 dpavlin 30 case 0x2:
3139     switch (lo4) {
3140 dpavlin 32 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 dpavlin 42 if (r8 == r4)
3164     ic->f = instr(tst_rm);
3165 dpavlin 32 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 dpavlin 30 case 0xb: /* OR Rm,Rn */
3173     ic->f = instr(or_rm_rn);
3174     break;
3175 dpavlin 32 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 dpavlin 42 default:if (!cpu->translation_readahead)
3188     fatal("Unimplemented opcode 0x%x,0x%x\n",
3189     main_opcode, lo4);
3190 dpavlin 30 goto bad;
3191     }
3192     break;
3193    
3194 dpavlin 32 case 0x3:
3195     switch (lo4) {
3196     case 0x0: /* CMP/EQ Rm,Rn */
3197     ic->f = instr(cmpeq_rm_rn);
3198 dpavlin 30 break;
3199 dpavlin 32 case 0x2: /* CMP/HS Rm,Rn */
3200     ic->f = instr(cmphs_rm_rn);
3201 dpavlin 30 break;
3202 dpavlin 32 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 dpavlin 42 default:if (!cpu->translation_readahead)
3233     fatal("Unimplemented opcode 0x%x,0x%x\n",
3234     main_opcode, lo4);
3235 dpavlin 30 goto bad;
3236     }
3237     break;
3238    
3239 dpavlin 32 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 dpavlin 36 ic->f = instr(stc_l_rm_predec_rn_md);
3247 dpavlin 32 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 dpavlin 36 ic->f = instr(stc_l_rm_predec_rn_md);
3272 dpavlin 32 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 dpavlin 36 ic->f = instr(mov_l_rm_predec_rn);
3317 dpavlin 32 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 dpavlin 36 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3328 dpavlin 32 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 dpavlin 34 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 dpavlin 32 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 dpavlin 36 ic->f = instr(stc_l_rm_predec_rn_md);
3357 dpavlin 32 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 dpavlin 36 ic->f = instr(stc_l_rm_predec_rn_md);
3399 dpavlin 32 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 dpavlin 36 ic->f = instr(stc_l_rm_predec_rn_md);
3412 dpavlin 32 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 dpavlin 40 /* Note: Loading into FPSCR is a specia
3444     case (need to call sh_update_fpsrc()). */
3445 dpavlin 32 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 dpavlin 42 default:if (!cpu->translation_readahead)
3458     fatal("Unimplemented opcode 0x%x,"
3459     "0x%02x\n", main_opcode, lo8);
3460 dpavlin 32 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 dpavlin 30 case 0x6:
3471     switch (lo4) {
3472 dpavlin 32 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 dpavlin 30 case 0x3: /* MOV Rm,Rn */
3482     ic->f = instr(mov_rm_rn);
3483     break;
3484 dpavlin 32 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 dpavlin 42 if (r8 == r4)
3520     ic->f = instr(extu_b_rm);
3521 dpavlin 32 break;
3522     case 0xd: /* EXTU.W Rm,Rn */
3523     ic->f = instr(extu_w_rm_rn);
3524 dpavlin 42 if (r8 == r4)
3525     ic->f = instr(extu_w_rm);
3526 dpavlin 32 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 dpavlin 42 default:if (!cpu->translation_readahead)
3534     fatal("Unimplemented opcode 0x%x,0x%x\n",
3535     main_opcode, lo4);
3536 dpavlin 30 goto bad;
3537     }
3538     break;
3539    
3540 dpavlin 32 case 0x7: /* ADD #imm,Rn */
3541     ic->f = instr(add_imm_rn);
3542     ic->arg[0] = (int8_t)lo8;
3543 dpavlin 42 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 dpavlin 32 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 dpavlin 42 samepage_function = NULL;
3560    
3561 dpavlin 32 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 dpavlin 42 samepage_function = instr(bt_samepage);
3589 dpavlin 32 break;
3590     case 0xb: /* BF (disp,PC) */
3591     ic->f = instr(bf);
3592 dpavlin 42 samepage_function = instr(bf_samepage);
3593 dpavlin 32 break;
3594     case 0xd: /* BT/S (disp,PC) */
3595     ic->f = instr(bt_s);
3596 dpavlin 42 samepage_function = instr(bt_s_samepage);
3597 dpavlin 32 break;
3598     case 0xf: /* BF/S (disp,PC) */
3599     ic->f = instr(bf_s);
3600 dpavlin 42 samepage_function = instr(bf_s_samepage);
3601 dpavlin 32 break;
3602 dpavlin 42 default:if (!cpu->translation_readahead)
3603     fatal("Unimplemented opcode 0x%x,0x%x\n",
3604     main_opcode, r8);
3605 dpavlin 32 goto bad;
3606     }
3607 dpavlin 42
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 dpavlin 32 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 dpavlin 42
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 dpavlin 32 break;
3636    
3637     case 0xa: /* BRA disp */
3638     case 0xb: /* BSR disp */
3639 dpavlin 42 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 dpavlin 32 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 dpavlin 42
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 dpavlin 32 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 dpavlin 34 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 dpavlin 42 default:if (!cpu->translation_readahead)
3730     fatal("Unimplemented opcode 0x%x,0x%x\n",
3731     main_opcode, r8);
3732 dpavlin 32 goto bad;
3733     }
3734     break;
3735    
3736 dpavlin 30 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 dpavlin 42
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 dpavlin 30 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 dpavlin 42 if (lo8 == 0)
3760     ic->f = instr(mov_0_rn);
3761 dpavlin 30 break;
3762    
3763 dpavlin 32 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 dpavlin 40 } 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 dpavlin 32 } 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 dpavlin 42 if (!cpu->translation_readahead)
3898     fatal("Unimplemented opcode 0x%x,0x%02x\n",
3899     main_opcode, lo8);
3900 dpavlin 32 goto bad;
3901     }
3902     break;
3903    
3904 dpavlin 42 default:if (!cpu->translation_readahead)
3905     fatal("Unimplemented main opcode 0x%x\n", main_opcode);
3906 dpavlin 30 goto bad;
3907 dpavlin 14 }
3908    
3909 dpavlin 30
3910 dpavlin 14 #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