/[gxemul]/trunk/src/cpus/cpu_sh_instr.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (show annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 6 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 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_sh_instr.c,v 1.49 2007/01/28 16:59:06 debug Exp $
29 *
30 * SH instructions.
31 *
32 * Individual functions should keep track of cpu->n_translated_instrs.
33 * (If no instruction was executed, then it should be decreased. If, say, 4
34 * instructions were combined into one function and executed, then it should
35 * be increased by 3.)
36 */
37
38
39 #define SYNCH_PC { \
40 int low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page) \
41 / sizeof(struct sh_instr_call); \
42 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1) \
43 << SH_INSTR_ALIGNMENT_SHIFT); \
44 cpu->pc += (low_pc << SH_INSTR_ALIGNMENT_SHIFT); \
45 }
46
47 #define RES_INST_IF_NOT_MD \
48 if (!(cpu->cd.sh.sr & SH_SR_MD)) { \
49 SYNCH_PC; \
50 sh_exception(cpu, EXPEVT_RES_INST, 0, 0); \
51 return; \
52 }
53
54 #define FLOATING_POINT_AVAILABLE_CHECK \
55 if (cpu->cd.sh.sr & SH_SR_FD) { \
56 /* FPU disabled: Cause exception. */ \
57 SYNCH_PC; \
58 if (cpu->delay_slot) \
59 sh_exception(cpu, EXPEVT_FPU_SLOT_DISABLE, 0, 0);\
60 else \
61 sh_exception(cpu, EXPEVT_FPU_DISABLE, 0, 0); \
62 return; \
63 }
64
65
66 /*
67 * nop: Nothing
68 */
69 X(nop)
70 {
71 }
72
73
74 /*
75 * sleep: Wait for interrupt
76 */
77 X(sleep)
78 {
79 RES_INST_IF_NOT_MD;
80
81 /*
82 * If there is an interrupt, then just return. Otherwise
83 * re-run the sleep instruction (after a delay).
84 */
85 if (cpu->cd.sh.int_to_assert > 0 && !(cpu->cd.sh.sr & SH_SR_BL)
86 && ((cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT)
87 < cpu->cd.sh.int_level)
88 return;
89
90 cpu->cd.sh.next_ic = ic;
91 cpu->is_halted = 1;
92 cpu->has_been_idling = 1;
93
94 /*
95 * There was no interrupt. Let the host sleep for a while.
96 *
97 * TODO:
98 *
99 * Think about how to actually implement this usleep stuff,
100 * in an SMP and/or timing accurate environment.
101 */
102
103 if (cpu->machine->ncpus == 1) {
104 static int x = 0;
105 if ((++x) == 600) {
106 usleep(10);
107 x = 0;
108 }
109 cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
110 }
111 }
112
113
114 /*
115 * sett: t = 1
116 * sets: s = 1
117 * clrt: t = 1
118 * clrs: s = 1
119 * movt_rn: rn = t
120 * clrmac: mach = macl = 0
121 *
122 * arg[1] = ptr to rn
123 */
124 X(sett) { cpu->cd.sh.sr |= SH_SR_T; }
125 X(sets) { cpu->cd.sh.sr |= SH_SR_S; }
126 X(clrt) { cpu->cd.sh.sr &= ~SH_SR_T; }
127 X(clrs) { cpu->cd.sh.sr &= ~SH_SR_S; }
128 X(movt_rn) { reg(ic->arg[1]) = cpu->cd.sh.sr & SH_SR_T? 1 : 0; }
129 X(clrmac) { cpu->cd.sh.macl = cpu->cd.sh.mach = 0; }
130
131
132 /*
133 * mov_rm_rn: rn = rm
134 * neg_rm_rn: rn = -rm
135 * negc_rm_rn: rn = -rm - t, t = borrow
136 * not_rm_rn: rn = ~rm
137 * swap_b_rm_rn: rn = rm with lowest 2 bytes swapped
138 * swap_w_rm_rn: rn = rm with high and low 16-bit words swapped
139 * exts_b_rm_rn: rn = (int8_t) rm
140 * extu_b_rm_rn: rn = (uint8_t) rm
141 * exts_w_rm_rn: rn = (int16_t) rm
142 * extu_w_rm_rn: rn = (uint16_t) rm
143 *
144 * arg[0] = ptr to rm
145 * arg[1] = ptr to rn
146 */
147 X(mov_rm_rn) { reg(ic->arg[1]) = reg(ic->arg[0]); }
148 X(not_rm_rn) { reg(ic->arg[1]) = ~reg(ic->arg[0]); }
149 X(neg_rm_rn) { reg(ic->arg[1]) = -reg(ic->arg[0]); }
150 X(negc_rm_rn)
151 {
152 uint64_t res = 0;
153 res -= (uint64_t) reg(ic->arg[0]);
154 if (cpu->cd.sh.sr & SH_SR_T)
155 res --;
156 if ((res >> 32) & 1)
157 cpu->cd.sh.sr |= SH_SR_T;
158 else
159 cpu->cd.sh.sr &= ~SH_SR_T;
160 reg(ic->arg[1]) = (uint32_t) res;
161 }
162 X(swap_b_rm_rn)
163 {
164 uint32_t r = reg(ic->arg[0]);
165 reg(ic->arg[1]) = (r & 0xffff0000) | ((r >> 8)&0xff) | ((r&0xff) << 8);
166 }
167 X(swap_w_rm_rn)
168 {
169 uint32_t r = reg(ic->arg[0]);
170 reg(ic->arg[1]) = (r >> 16) | (r << 16);
171 }
172 X(exts_b_rm_rn) { reg(ic->arg[1]) = (int8_t)reg(ic->arg[0]); }
173 X(extu_b_rm_rn) { reg(ic->arg[1]) = (uint8_t)reg(ic->arg[0]); }
174 X(exts_w_rm_rn) { reg(ic->arg[1]) = (int16_t)reg(ic->arg[0]); }
175 X(extu_w_rm_rn) { reg(ic->arg[1]) = (uint16_t)reg(ic->arg[0]); }
176
177
178 /*
179 * 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 *
184 * 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 * 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 * 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 * arg[0] = int8_t imm, extended to at least int32_t
281 * arg[1] = ptr to rn
282 */
283 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 {
298 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 }
315 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
321 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
322 data = LE16_TO_HOST(data);
323 else
324 data = BE16_TO_HOST(data);
325
326 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 /*
395 * mov_l_disp_pc_rn: Load a 32-bit value into a register,
396 * from an immediate address relative to the pc.
397 *
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 uint32_t addr = ic->arg[0] + (cpu->pc &
404 ~((SH_IC_ENTRIES_PER_PAGE-1) << SH_INSTR_ALIGNMENT_SHIFT));
405 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 }
424
425
426 /*
427 * mova_r0: Set r0 to an address close to the program counter.
428 *
429 * 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 * arg[0] = ptr to rm
1004 * 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 * arg[1] = ptr to rn
1372 */
1373 X(add_rm_rn) { reg(ic->arg[1]) += reg(ic->arg[0]); }
1374 X(addc_rm_rn)
1375 {
1376 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 }
1386 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
1415
1416 /*
1417 * 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 *
1421 * arg[0] = ptr to rm
1422 * arg[1] = ptr to rn
1423 */
1424 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 X(shll_rn)
1608 {
1609 uint32_t rn = reg(ic->arg[1]);
1610 if (rn >> 31)
1611 cpu->cd.sh.sr |= SH_SR_T;
1612 else
1613 cpu->cd.sh.sr &= ~SH_SR_T;
1614 reg(ic->arg[1]) = rn << 1;
1615 }
1616 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
1694
1695 /*
1696 * 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 *
1699 * arg[0] = ptr to rm
1700 * arg[1] = ptr to rn
1701 */
1702 X(shad)
1703 {
1704 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 }
1831 }
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
1880
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 }
1900 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
1953
1954 /*
1955 * 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 *
1991 * arg[1] = ptr to rn
1992 */
1993 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 /* 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 }
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 X(ldc_rm_sr)
2068 {
2069 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 exit(1);
2580 }
2581
2582 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 }
2599
2600
2601 /*
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 /*****************************************************************************/
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 cpu->pc += (SH_IC_ENTRIES_PER_PAGE << SH_INSTR_ALIGNMENT_SHIFT);
2664
2665 /* end_of_page doesn't count as an executed instruction: */
2666 cpu->n_translated_instrs --;
2667
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 }
2705
2706
2707 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 /*****************************************************************************/
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 uint64_t addr, low_pc;
2743 uint32_t iword;
2744 unsigned char *page;
2745 unsigned char ib[4];
2746 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
2750 /* Figure out the (virtual) address of the instruction: */
2751 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 }
2760
2761 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 /* Read the instruction word from memory: */
2768 #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
2785 if (page != NULL) {
2786 /* fatal("TRANSLATION HIT!\n"); */
2787 memcpy(ib, page + (addr & 0xfff), isize);
2788 } else {
2789 /* fatal("TRANSLATION MISS!\n"); */
2790 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2791 isize, MEM_READ, CACHE_INSTRUCTION)) {
2792 fatal("to_be_translated(): read failed: TODO\n");
2793 goto bad;
2794 }
2795 }
2796
2797 if (cpu->cd.sh.compact) {
2798 iword = *((uint16_t *)&ib[0]);
2799 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 iword = *((uint32_t *)&ib[0]);
2810 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
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 /* 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 switch (main_opcode) {
2834
2835 case 0x0:
2836 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 } else if (iword == SH_INVALID_INSTR) {
2894 /* 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 goto bad;
2992 }
2993 }
2994 break;
2995
2996 case 0x1:
2997 ic->f = instr(mov_l_rm_disp_rn);
2998 ic->arg[1] = r8 + (lo4 << 4);
2999 break;
3000
3001 case 0x2:
3002 switch (lo4) {
3003 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 case 0xb: /* OR Rm,Rn */
3034 ic->f = instr(or_rm_rn);
3035 break;
3036 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 default:fatal("Unimplemented opcode 0x%x,0x%x\n",
3049 main_opcode, lo4);
3050 goto bad;
3051 }
3052 break;
3053
3054 case 0x3:
3055 switch (lo4) {
3056 case 0x0: /* CMP/EQ Rm,Rn */
3057 ic->f = instr(cmpeq_rm_rn);
3058 break;
3059 case 0x2: /* CMP/HS Rm,Rn */
3060 ic->f = instr(cmphs_rm_rn);
3061 break;
3062 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 goto bad;
3095 }
3096 break;
3097
3098 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 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 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 case 0x6:
3327 switch (lo4) {
3328 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 case 0x3: /* MOV Rm,Rn */
3338 ic->f = instr(mov_rm_rn);
3339 break;
3340 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 default:fatal("Unimplemented opcode 0x%x,0x%x\n",
3386 main_opcode, lo4);
3387 goto bad;
3388 }
3389 break;
3390
3391 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 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 default:fatal("Unimplemented opcode 0x%x,0x%x\n",
3525 main_opcode, r8);
3526 goto bad;
3527 }
3528 break;
3529
3530 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 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 default:fatal("Unimplemented main opcode 0x%x\n", main_opcode);
3675 goto bad;
3676 }
3677
3678
3679 #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