/[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 36 - (hide annotations)
Mon Oct 8 16:21:34 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 93822 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1497 2007/03/18 03:41:36 debug Exp $
20070224	Minor update to the initialization of the ns16550 in
		machine_walnut.c, to allow that machine type to boot with the
		new interrupt system (although it is still a dummy machine).
		Adding a wdc at 0x14000000 to machine_landisk.c, and fixing
		the SCIF serial interrupts of the SH4 cpu enough to get
		NetBSD/landisk booting from a disk image :-)  Adding a
		preliminary install instruction skeleton to guestoses.html.
20070306	Adding SH-IPL+G PROM emulation, and also passing the "end"
		symbol in r5 on bootup, for Landisk emulation. This is enough
		to get OpenBSD/landisk to install :)  Adding a preliminary
		install instruction skeleton to the documentation. SuperH
		emulation is still shaky, though :-/
20070307	Fixed a strangeness in memory_sh.c (read/write was never
		returned for any page). (Unknown whether this fixes any actual
		problems, though.)
20070308	dev_ram.c fix: invalidate code translations on writes to
		RAM, emulated as separate devices. Linux/dreamcast gets
		further in the boot process than before, but still bugs out
		in userland.
		Fixing bugs in the "stc.l gbr,@-rN" and "ldc.l @rN+,gbr" SuperH 
		instructions (they should NOT check the MD bit), allowing the
		Linux/dreamcast Live CD to reach userland correctly :-)
20070310	Changing the cpu name "Alpha" in src/useremul.c to "21364" to
		unbreak userland syscall emulation of FreeBSD/Alpha binaries.
20070314	Applying a patch from Michael Yaroslavtsev which fixes the
		previous Linux lib64 patch to the configure script.
20070315	Adding a (dummy) sun4v machine type, and SPARC T1 cpu type.
20070316	Creating a new directory, src/disk, and moving diskimage.c
		to it. Separating out bootblock loading stuff from emul.c into
		new files in src/disk.
		Adding some more SPARC registers.
20070318	Preparing/testing for a minirelease, 0.4.4.1.

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

  ViewVC Help
Powered by ViewVC 1.1.26