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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (show annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 5 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 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_sh_instr.c,v 1.64 2007/06/28 13:36:47 debug Exp $
29 *
30 * SH instructions.
31 *
32 * Individual functions should keep track of cpu->n_translated_instrs.
33 * (If no instruction was executed, then it should be decreased. If, say, 4
34 * instructions were combined into one function and executed, then it should
35 * be increased by 3.)
36 */
37
38
39 #define SYNCH_PC { \
40 int low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page) \
41 / sizeof(struct sh_instr_call); \
42 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1) \
43 << SH_INSTR_ALIGNMENT_SHIFT); \
44 cpu->pc += (low_pc << SH_INSTR_ALIGNMENT_SHIFT); \
45 }
46
47 #define RES_INST_IF_NOT_MD \
48 if (!(cpu->cd.sh.sr & SH_SR_MD)) { \
49 SYNCH_PC; \
50 sh_exception(cpu, EXPEVT_RES_INST, 0, 0); \
51 return; \
52 }
53
54 #define FLOATING_POINT_AVAILABLE_CHECK \
55 if (cpu->cd.sh.sr & SH_SR_FD) { \
56 /* FPU disabled: Cause exception. */ \
57 SYNCH_PC; \
58 if (cpu->delay_slot) \
59 sh_exception(cpu, EXPEVT_FPU_SLOT_DISABLE, 0, 0);\
60 else \
61 sh_exception(cpu, EXPEVT_FPU_DISABLE, 0, 0); \
62 return; \
63 }
64
65
66 /*
67 * nop: Nothing
68 */
69 X(nop)
70 {
71 }
72
73
74 /*
75 * sleep: Wait for interrupt
76 */
77 X(sleep)
78 {
79 RES_INST_IF_NOT_MD;
80
81 /*
82 * If there is an interrupt, then just return. Otherwise
83 * re-run the sleep instruction (after a delay).
84 */
85 if (cpu->cd.sh.int_to_assert > 0 && !(cpu->cd.sh.sr & SH_SR_BL)
86 && ((cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT)
87 < cpu->cd.sh.int_level)
88 return;
89
90 cpu->cd.sh.next_ic = ic;
91 cpu->is_halted = 1;
92 cpu->has_been_idling = 1;
93
94 /*
95 * There was no interrupt. Let the host sleep for a while.
96 *
97 * TODO:
98 *
99 * Think about how to actually implement this usleep stuff,
100 * in an SMP and/or timing accurate environment.
101 */
102
103 if (cpu->machine->ncpus == 1) {
104 static int x = 0;
105
106 if ((++x) == 600) {
107 usleep(10);
108 x = 0;
109 }
110
111 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 *
124 * 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 * arg[0] = ptr to rm
147 * arg[1] = ptr to rn
148 */
149 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 {
154 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 }
164 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 /* 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
182
183 /*
184 * 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 *
189 * 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 * 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 * 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 * arg[0] = int8_t imm, extended to at least int32_t
286 * arg[1] = ptr to rn
287 */
288 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
296
297 /*
298 * 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 *
303 * arg[0] = ptr to rm (or other register)
304 * arg[1] = ptr to rn
305 */
306 X(mov_b_rm_predec_rn)
307 {
308 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 }
325 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
331 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
332 data = LE16_TO_HOST(data);
333 else
334 data = BE16_TO_HOST(data);
335
336 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 X(stc_l_rm_predec_rn_md)
376 {
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 /*
405 * mov_l_disp_pc_rn: Load a 32-bit value into a register,
406 * from an immediate address relative to the pc.
407 *
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 uint32_t addr = ic->arg[0] + (cpu->pc &
414 ~((SH_IC_ENTRIES_PER_PAGE-1) << SH_INSTR_ALIGNMENT_SHIFT));
415 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 }
434
435
436 /*
437 * mova_r0: Set r0 to an address close to the program counter.
438 *
439 * 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
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 }
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 /* Ugly special case for FPSCR: */
864 if (ic->arg[0] == (size_t)&cpu->cd.sh.fpscr)
865 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 * arg[0] = ptr to rm
1020 * 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 * tst_rm: t = (rm == 0)
1385 * xtrct_rm_rn: rn = (rn >> 16) | (rm << 16)
1386 *
1387 * arg[0] = ptr to rm
1388 * arg[1] = ptr to rn
1389 */
1390 X(add_rm_rn) { reg(ic->arg[1]) += reg(ic->arg[0]); }
1391 X(addc_rm_rn)
1392 {
1393 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 }
1403 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 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 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
1439
1440 /*
1441 * 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 *
1445 * arg[0] = ptr to rm
1446 * arg[1] = ptr to rn
1447 */
1448 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 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 if (q)
1458 new_sr |= SH_SR_Q;
1459 if (m)
1460 new_sr |= SH_SR_M;
1461 if (m ^ q)
1462 new_sr |= SH_SR_T;
1463 cpu->cd.sh.sr = new_sr;
1464 }
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 X(shll_rn)
1634 {
1635 uint32_t rn = reg(ic->arg[1]);
1636 if (rn & 0x80000000)
1637 cpu->cd.sh.sr |= SH_SR_T;
1638 else
1639 cpu->cd.sh.sr &= ~SH_SR_T;
1640 reg(ic->arg[1]) = rn << 1;
1641 }
1642 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 uint32_t rn = reg(ic->arg[1]), x;
1654 if (rn & 0x80000000) {
1655 x = 1;
1656 cpu->cd.sh.sr |= SH_SR_T;
1657 } else {
1658 x = 0;
1659 cpu->cd.sh.sr &= ~SH_SR_T;
1660 }
1661 reg(ic->arg[1]) = (rn << 1) | x;
1662 }
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
1723
1724 /*
1725 * 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 *
1728 * arg[0] = ptr to rm
1729 * arg[1] = ptr to rn
1730 */
1731 X(shad)
1732 {
1733 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 * arg[0] = immediate offset relative to start of page,
1772 * or ptr to target instruction, for samepage branches
1773 * 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 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 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 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 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 * arg[1] = for samepage functions, the new instruction pointer
1876 */
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 }
1885 }
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 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 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 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
1976
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 }
1996 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
2049
2050 /*
2051 * 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 /* 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 0, INVALIDATE_ALL);
2128 }
2129 }
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 X(ldc_rm_sr)
2152 {
2153 RES_INST_IF_NOT_MD;
2154 sh_update_sr(cpu, reg(ic->arg[1]));
2155
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 }
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 * 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 * 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 exit(1);
2713 }
2714
2715 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 }
2732
2733
2734 /*
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 * prom_emul:
2769 */
2770 X(prom_emul)
2771 {
2772 uint32_t old_pc;
2773 SYNCH_PC;
2774 old_pc = cpu->pc;
2775
2776 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
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 /*****************************************************************************/
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 cpu->pc += (SH_IC_ENTRIES_PER_PAGE << SH_INSTR_ALIGNMENT_SHIFT);
2807
2808 /* end_of_page doesn't count as an executed instruction: */
2809 cpu->n_translated_instrs --;
2810
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 }
2848
2849
2850 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 /*****************************************************************************/
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 uint32_t addr, low_pc, iword;
2886 unsigned char *page;
2887 unsigned char ib[2];
2888 int main_opcode, isize = sizeof(ib);
2889 int in_crosspage_delayslot = 0, r8, r4, lo4, lo8;
2890 void (*samepage_function)(struct cpu *, struct sh_instr_call *);
2891
2892 /* Figure out the (virtual) address of the instruction: */
2893 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 }
2902
2903 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 /* Read the instruction word from memory: */
2910 page = cpu->cd.sh.host_load[(uint32_t)addr >> 12];
2911
2912 if (page != NULL) {
2913 /* fatal("TRANSLATION HIT!\n"); */
2914 memcpy(ib, page + (addr & 0xfff), isize);
2915 } else {
2916 /* fatal("TRANSLATION MISS!\n"); */
2917 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2918 isize, MEM_READ, CACHE_INSTRUCTION)) {
2919 fatal("to_be_translated(): read failed: TODO\n");
2920 goto bad;
2921 }
2922 }
2923
2924 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
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 /* 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 switch (main_opcode) {
2950
2951 case 0x0:
2952 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 } else if (iword == SH_INVALID_INSTR) {
3010 /* PROM emulation (GXemul specific) */
3011 ic->f = instr(prom_emul);
3012 } 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 if (!cpu->translation_readahead)
3029 fatal("Unimplemented NOP"
3030 " variant?\n");
3031 goto bad;
3032 }
3033 break;
3034 case 0x0a: /* STS MACH,Rn */
3035 ic->f = instr(mov_rm_rn);
3036 ic->arg[0] = (size_t)&cpu->cd.sh.mach;
3037 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 ic->f = instr(mov_rm_rn);
3044 ic->arg[0] = (size_t)&cpu->cd.sh.macl;
3045 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 ic->f = instr(mov_rm_rn);
3062 ic->arg[0] = (size_t)&cpu->cd.sh.pr;
3063 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 default:if (!cpu->translation_readahead)
3111 fatal("Unimplemented opcode 0x%x,"
3112 "0x%03x\n", main_opcode,
3113 iword & 0xfff);
3114 goto bad;
3115 }
3116 }
3117 break;
3118
3119 case 0x1:
3120 ic->f = instr(mov_l_rm_disp_rn);
3121 ic->arg[1] = r8 + (lo4 << 4);
3122 break;
3123
3124 case 0x2:
3125 switch (lo4) {
3126 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 if (r8 == r4)
3150 ic->f = instr(tst_rm);
3151 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 case 0xb: /* OR Rm,Rn */
3159 ic->f = instr(or_rm_rn);
3160 break;
3161 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 default:if (!cpu->translation_readahead)
3174 fatal("Unimplemented opcode 0x%x,0x%x\n",
3175 main_opcode, lo4);
3176 goto bad;
3177 }
3178 break;
3179
3180 case 0x3:
3181 switch (lo4) {
3182 case 0x0: /* CMP/EQ Rm,Rn */
3183 ic->f = instr(cmpeq_rm_rn);
3184 break;
3185 case 0x2: /* CMP/HS Rm,Rn */
3186 ic->f = instr(cmphs_rm_rn);
3187 break;
3188 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 default:if (!cpu->translation_readahead)
3219 fatal("Unimplemented opcode 0x%x,0x%x\n",
3220 main_opcode, lo4);
3221 goto bad;
3222 }
3223 break;
3224
3225 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 ic->f = instr(stc_l_rm_predec_rn_md);
3233 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 ic->f = instr(stc_l_rm_predec_rn_md);
3258 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 ic->f = instr(mov_l_rm_predec_rn);
3303 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 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3314 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 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 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 ic->f = instr(stc_l_rm_predec_rn_md);
3343 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 ic->f = instr(stc_l_rm_predec_rn_md);
3385 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 ic->f = instr(stc_l_rm_predec_rn_md);
3398 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 /* Note: Loading into FPSCR is a specia
3430 case (need to call sh_update_fpsrc()). */
3431 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 default:if (!cpu->translation_readahead)
3444 fatal("Unimplemented opcode 0x%x,"
3445 "0x%02x\n", main_opcode, lo8);
3446 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 case 0x6:
3457 switch (lo4) {
3458 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 case 0x3: /* MOV Rm,Rn */
3468 ic->f = instr(mov_rm_rn);
3469 break;
3470 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 if (r8 == r4)
3506 ic->f = instr(extu_b_rm);
3507 break;
3508 case 0xd: /* EXTU.W Rm,Rn */
3509 ic->f = instr(extu_w_rm_rn);
3510 if (r8 == r4)
3511 ic->f = instr(extu_w_rm);
3512 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 default:if (!cpu->translation_readahead)
3520 fatal("Unimplemented opcode 0x%x,0x%x\n",
3521 main_opcode, lo4);
3522 goto bad;
3523 }
3524 break;
3525
3526 case 0x7: /* ADD #imm,Rn */
3527 ic->f = instr(add_imm_rn);
3528 ic->arg[0] = (int8_t)lo8;
3529 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 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 samepage_function = NULL;
3546
3547 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 samepage_function = instr(bt_samepage);
3575 break;
3576 case 0xb: /* BF (disp,PC) */
3577 ic->f = instr(bf);
3578 samepage_function = instr(bf_samepage);
3579 break;
3580 case 0xd: /* BT/S (disp,PC) */
3581 ic->f = instr(bt_s);
3582 samepage_function = instr(bt_s_samepage);
3583 break;
3584 case 0xf: /* BF/S (disp,PC) */
3585 ic->f = instr(bf_s);
3586 samepage_function = instr(bf_s_samepage);
3587 break;
3588 default:if (!cpu->translation_readahead)
3589 fatal("Unimplemented opcode 0x%x,0x%x\n",
3590 main_opcode, r8);
3591 goto bad;
3592 }
3593
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 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
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 break;
3622
3623 case 0xa: /* BRA disp */
3624 case 0xb: /* BSR disp */
3625 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 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
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 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 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 default:if (!cpu->translation_readahead)
3716 fatal("Unimplemented opcode 0x%x,0x%x\n",
3717 main_opcode, r8);
3718 goto bad;
3719 }
3720 break;
3721
3722 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
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 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 if (lo8 == 0)
3746 ic->f = instr(mov_0_rn);
3747 break;
3748
3749 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 ic->f = instr(fmov_rm_postinc_frn);
3798 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3799 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3800 } else if (lo4 == 0xa) {
3801 /* FMOV FRm,@Rn */
3802 ic->f = instr(fmov_frm_rn);
3803 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4]; /* m */
3804 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3805 } else if (lo4 == 0xb) {
3806 /* FMOV FRm,@-Rn */
3807 ic->f = instr(fmov_frm_predec_rn);
3808 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4]; /* m */
3809 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3810 } else if (lo4 == 0xc) {
3811 /* FMOV FRm,FRn */
3812 ic->f = instr(fmov_frm_frn);
3813 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3814 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3815 } else if (lo8 == 0x0d) {
3816 /* FSTS FPUL,FRn */
3817 ic->f = instr(copy_fp_register);
3818 ic->arg[0] = (size_t)&cpu->cd.sh.fpul;
3819 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3820 } else if (lo8 == 0x1d) {
3821 /* FLDS FRn,FPUL */
3822 ic->f = instr(copy_fp_register);
3823 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3824 ic->arg[1] = (size_t)&cpu->cd.sh.fpul;
3825 } else if (lo8 == 0x2d) {
3826 /* FLOAT FPUL,FRn */
3827 ic->f = instr(float_fpul_frn);
3828 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3829 } else if (lo8 == 0x3d) {
3830 /* FTRC FRm,FPUL */
3831 ic->f = instr(ftrc_frm_fpul);
3832 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3833 } else if (lo8 == 0x4d) {
3834 /* FNEG FRn */
3835 ic->f = instr(fneg_frn);
3836 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3837 } else if (lo8 == 0x5d) {
3838 /* FABS FRn */
3839 ic->f = instr(fabs_frn);
3840 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3841 } else if (lo8 == 0x6d) {
3842 /* FSQRT FRn */
3843 ic->f = instr(fsqrt_frn);
3844 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3845 } else if (lo8 == 0x8d) {
3846 /* FLDI0 FRn */
3847 ic->f = instr(fldi_frn);
3848 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3849 ic->arg[1] = 0x00000000;
3850 } else if (lo8 == 0x9d) {
3851 /* FLDI1 FRn */
3852 ic->f = instr(fldi_frn);
3853 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3854 ic->arg[1] = 0x3f800000;
3855 } else if ((iword & 0x01ff) == 0x00ad) {
3856 /* FCNVSD FPUL,DRn */
3857 ic->f = instr(fcnvsd_fpul_drn);
3858 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3859 } else if ((iword & 0x01ff) == 0x00bd) {
3860 /* FCNVDS DRm,FPUL */
3861 ic->f = instr(fcnvds_drm_fpul);
3862 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3863 } else if ((iword & 0x01ff) == 0x00fd) {
3864 /* FSCA FPUL,DRn */
3865 ic->f = instr(fsca_fpul_drn);
3866 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3867 } else if (iword == 0xf3fd) {
3868 /* FSCHG */
3869 ic->f = instr(fschg);
3870 } else if (iword == 0xfbfd) {
3871 /* FRCHG */
3872 ic->f = instr(frchg);
3873 } else if ((iword & 0xf3ff) == 0xf1fd) {
3874 /* FTRV XMTRX, FVn */
3875 ic->f = instr(ftrv_xmtrx_fvn);
3876 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8 & 0xc];
3877 } else if (lo4 == 0xe) {
3878 /* FMAC FR0,FRm,FRn */
3879 ic->f = instr(fmac_fr0_frm_frn);
3880 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3881 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3882 } else {
3883 if (!cpu->translation_readahead)
3884 fatal("Unimplemented opcode 0x%x,0x%02x\n",
3885 main_opcode, lo8);
3886 goto bad;
3887 }
3888 break;
3889
3890 default:if (!cpu->translation_readahead)
3891 fatal("Unimplemented main opcode 0x%x\n", main_opcode);
3892 goto bad;
3893 }
3894
3895
3896 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
3897 #include "cpu_dyntrans.c"
3898 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
3899 }
3900

  ViewVC Help
Powered by ViewVC 1.1.26