/[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 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (13 years, 3 months ago) by dpavlin
File MIME type: text/plain
File size: 99407 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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