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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 40 - (hide annotations)
Mon Oct 8 16:22:11 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 95559 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1539 2007/05/01 04:03:51 debug Exp $
20070415	Landisk PCLOCK should be 33.33 MHz, not 50 MHz. (This makes
		the clock run at correct speed.)
		FINALLY found and fixed the bug which caused OpenBSD/landisk
		to randomly bug out: an &-sign was missing in the special case
		handling of FPSCR in the 'LDS.L @Rm+,FPSCR' instruction.
		Adding similar special case handling for 'LDC.L @Rm+,SR'
		(calling sh_update_sr() instead of just loading).
		Implementing the 'FCNVSD FPUL,DRn' and 'FCNVDS DRm,FPUL'
		SuperH instructions.
		The 'LDC Rm,SR' instruction now immediately breaks out of the
		dyntrans loop if an interrupt is to be triggered.
20070416	In memory_rw.c, if mapping a page as writable, make sure to
		invalidate code translations even if the data access was a
		read.
		Minor SuperH updates.
20070418	Removing the dummy M68K emulation mode.
		Minor SH update (turning unnecessary sts_mach_rn, sts_macl_rn,
		and sts_pr_rn instruction handlers into mov_rm_rn).
20070419	Beginning to add a skeleton for an M88K mode: Adding a hack to
		allow OpenBSD/m88k a.out binaries to be loaded, and disassembly
		of a few simple 88K instructions.
		Commenting out the 'LDC Rm,SR' fix from a few days ago, because
		it made Linux/dreamcast bug out.
		Adding a hack to dev_sh4.c (an extra translation cache
		invalidation), which allows OpenBSD/landisk to boot ok after
		an install. Upgrading the Landisk machine mode to stable,
		updating documentation, etc.
20070420	Experimenting with adding a PCI controller (pcic) to dev_sh4.
		Adding a dummy Realtek 8139C+ skeleton device (dev_rtl8139c).
		Implementing the first M88K instructions (br, or[.u] imm), and
		adding disassembly of some more instructions.
20070421	Continuing a little on dev_rtl8139c.
20070422	Implementing the 9346 EEPROM "read" command for dev_rtl8139c.
		Finally found and fixed an old bug in the log n symbol search
		(it sometimes missed symbols). Debug trace (-i, -t etc) should
		now show more symbols. :-)
20070423	Continuing a little on M88K disassembly.
20070428	Fixing a memset arg order bug in src/net/net.c (thanks to
		Nigel Horne for noticing the bug).
		Applying parts of a patch from Carl van Schaik to clear out
		bottom bits of MIPS addresses more correctly, when using large
		page sizes, and doing some other minor cleanup/refactoring.
		Fixing a couple of warnings given by gcc with the -W option (a
		few more warnings than just plain -Wall).
		Reducing SuperH dyntrans physical address space from 64-bit to
		32-bit (since SH5/SH64 isn't imlemented yet anyway).
		Adding address-to-symbol annotation to a few more instructions
		in the SuperH instruction trace output.
		Beginning regression testing for the next release.
		Reverting the value of SCIF_DELAYED_TX_VALUE from 1 to 2,
		because OpenBSD/landisk may otherwise hang randomly.
20070429	The ugly hack/workaround to get OpenBSD/landisk booting without
		crashing does NOT work anymore (with the April 21 snapshot
		of OpenBSD/landisk). Strangely enough, removing the hack
		completely causes OpenBSD/landisk to work (!).
		More regression testing (re-testing everything SuperH-related,
		and some other things).
		Cobalt interrupts were actually broken; fixing by commenting
		out the DEC21143s in the Cobalt machine.
20070430	More regression testing.
20070501	Updating the OpenBSD/landisk install instructions to use
		4.1 instead of the current snapshot.
		GAAAH! OpenBSD/landisk 4.1 _needs_ the ugly hack/workaround;
		reintroducing it again. (The 4.1 kernel is actually from
		2007-03-11.)
		Simplifying the NetBSD/evbarm install instructions a bit.
		More regression testing.

==============  RELEASE 0.4.5.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26