/[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 34 - (hide annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 93626 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

==============  RELEASE 0.4.4  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26