filename | src/sh4/sh4core.in |
changeset | 1187:266e7a1bae90 |
prev | 1125:9dd5dee45db9 |
next | 1192:ba3df0bf2c23 |
author | nkeynes |
date | Fri Dec 02 18:14:27 2011 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Handle calls to sh4_disasm_instruction when the memory isn't mapped (as can happen if we try to print a translated block that's been unmapped) |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * SH4 emulation core, and parent module for all the SH4 peripheral
5 * modules.
6 *
7 * Copyright (c) 2005 Nathan Keynes.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
20 #define MODULE sh4_module
21 #include <assert.h>
22 #include <math.h>
23 #include "dream.h"
24 #include "dreamcast.h"
25 #include "eventq.h"
26 #include "mem.h"
27 #include "clock.h"
28 #include "syscall.h"
29 #include "sh4/sh4core.h"
30 #include "sh4/sh4mmio.h"
31 #include "sh4/sh4stat.h"
32 #include "sh4/mmu.h"
34 #define SH4_CALLTRACE 1
36 #define MAX_INT 0x7FFFFFFF
37 #define MIN_INT 0x80000000
38 #define MAX_INTF 2147483647.0
39 #define MIN_INTF -2147483648.0
41 /********************** SH4 Module Definition ****************************/
43 uint32_t sh4_emulate_run_slice( uint32_t nanosecs )
44 {
45 int i;
47 if( sh4_breakpoint_count == 0 ) {
48 for( ; sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
49 if( SH4_EVENT_PENDING() ) {
50 sh4_handle_pending_events();
51 }
52 if( !sh4_execute_instruction() ) {
53 break;
54 }
55 }
56 } else {
57 for( ;sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
58 if( SH4_EVENT_PENDING() ) {
59 sh4_handle_pending_events();
60 }
62 if( !sh4_execute_instruction() )
63 break;
64 #ifdef ENABLE_DEBUG_MODE
65 for( i=0; i<sh4_breakpoint_count; i++ ) {
66 if( sh4_breakpoints[i].address == sh4r.pc ) {
67 break;
68 }
69 }
70 if( i != sh4_breakpoint_count ) {
71 sh4_core_exit( CORE_EXIT_BREAKPOINT );
72 }
73 #endif
74 }
75 }
77 /* If we aborted early, but the cpu is still technically running,
78 * we're doing a hard abort - cut the timeslice back to what we
79 * actually executed
80 */
81 if( sh4r.slice_cycle != nanosecs && sh4r.sh4_state == SH4_STATE_RUNNING ) {
82 nanosecs = sh4r.slice_cycle;
83 }
84 if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
85 TMU_run_slice( nanosecs );
86 SCIF_run_slice( nanosecs );
87 }
88 return nanosecs;
89 }
91 /********************** SH4 emulation core ****************************/
93 #if(SH4_CALLTRACE == 1)
94 #define MAX_CALLSTACK 32
95 static struct call_stack {
96 sh4addr_t call_addr;
97 sh4addr_t target_addr;
98 sh4addr_t stack_pointer;
99 } call_stack[MAX_CALLSTACK];
101 static int call_stack_depth = 0;
102 int sh4_call_trace_on = 0;
104 static inline void trace_call( sh4addr_t source, sh4addr_t dest )
105 {
106 if( call_stack_depth < MAX_CALLSTACK ) {
107 call_stack[call_stack_depth].call_addr = source;
108 call_stack[call_stack_depth].target_addr = dest;
109 call_stack[call_stack_depth].stack_pointer = sh4r.r[15];
110 }
111 call_stack_depth++;
112 }
114 static inline void trace_return( sh4addr_t source, sh4addr_t dest )
115 {
116 if( call_stack_depth > 0 ) {
117 call_stack_depth--;
118 }
119 }
121 void fprint_stack_trace( FILE *f )
122 {
123 int i = call_stack_depth -1;
124 if( i >= MAX_CALLSTACK )
125 i = MAX_CALLSTACK - 1;
126 for( ; i >= 0; i-- ) {
127 fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n",
128 (call_stack_depth - i), call_stack[i].call_addr,
129 call_stack[i].target_addr, call_stack[i].stack_pointer );
130 }
131 }
133 #define TRACE_CALL( source, dest ) trace_call(source, dest)
134 #define TRACE_RETURN( source, dest ) trace_return(source, dest)
135 #else
136 #define TRACE_CALL( dest, rts )
137 #define TRACE_RETURN( source, dest )
138 #endif
140 static gboolean FASTCALL sh4_raise_slot_exception( int normal_code, int slot_code ) {
141 if( sh4r.in_delay_slot ) {
142 sh4_raise_exception(slot_code);
143 } else {
144 sh4_raise_exception(normal_code);
145 }
146 return TRUE;
147 }
150 #define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) { return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL ); }
151 #define CHECKRALIGN16(addr) if( (addr)&0x01 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
152 #define CHECKRALIGN32(addr) if( (addr)&0x03 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
153 #define CHECKRALIGN64(addr) if( (addr)&0x07 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
154 #define CHECKWALIGN16(addr) if( (addr)&0x01 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
155 #define CHECKWALIGN32(addr) if( (addr)&0x03 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
156 #define CHECKWALIGN64(addr) if( (addr)&0x07 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
158 #define CHECKFPUEN() if( !IS_FPU_ENABLED() ) { if( ir == 0xFFFD ) { UNDEF(ir); } else { return sh4_raise_slot_exception( EXC_FPU_DISABLED, EXC_SLOT_FPU_DISABLED ); } }
159 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }
160 #define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) { sh4_raise_exception(EXC_SLOT_ILLEGAL); return TRUE; }
162 #define ADDRSPACE (IS_SH4_PRIVMODE() ? sh4_address_space : sh4_user_address_space)
163 #define SQADDRSPACE (IS_SH4_PRIVMODE() ? storequeue_address_space : storequeue_user_address_space)
165 #ifdef HAVE_FRAME_ADDRESS
166 static FASTCALL __attribute__((noinline)) void *__first_arg(void *a, void *b) { return a; }
167 #define INIT_EXCEPTIONS(label) goto *__first_arg(&&fnstart,&&label); fnstart:
168 #define MEM_READ_BYTE( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_byte)((addr), &&except)
169 #define MEM_READ_BYTE_FOR_WRITE( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_byte_for_write)((addr), &&except)
170 #define MEM_READ_WORD( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_word)((addr), &&except)
171 #define MEM_READ_LONG( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_long)((addr), &&except)
172 #define MEM_WRITE_BYTE( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_byte)((addr), (val), &&except)
173 #define MEM_WRITE_WORD( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_word)((addr), (val), &&except)
174 #define MEM_WRITE_LONG( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_long)((addr), (val), &&except)
175 #define MEM_PREFETCH( addr ) ((mem_prefetch_exc_fn_t)ADDRSPACE[(addr)>>12]->prefetch)((addr), &&except)
176 #else
177 #define INIT_EXCEPTIONS(label)
178 #define MEM_READ_BYTE( addr, val ) val = ADDRSPACE[(addr)>>12]->read_byte(addr)
179 #define MEM_READ_BYTE_FOR_WRITE( addr, val ) val = ADDRSPACE[(addr)>>12]->read_byte_for_write(addr)
180 #define MEM_READ_WORD( addr, val ) val = ADDRSPACE[(addr)>>12]->read_word(addr)
181 #define MEM_READ_LONG( addr, val ) val = ADDRSPACE[(addr)>>12]->read_long(addr)
182 #define MEM_WRITE_BYTE( addr, val ) ADDRSPACE[(addr)>>12]->write_byte(addr, val)
183 #define MEM_WRITE_WORD( addr, val ) ADDRSPACE[(addr)>>12]->write_word(addr, val)
184 #define MEM_WRITE_LONG( addr, val ) ADDRSPACE[(addr)>>12]->write_long(addr, val)
185 #define MEM_PREFETCH( addr ) ADDRSPACE[(addr)>>12]->prefetch(addr)
186 #endif
188 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
190 #define MEM_FP_READ( addr, reg ) \
191 if( IS_FPU_DOUBLESIZE() ) { \
192 CHECKRALIGN64(addr); \
193 if( reg & 1 ) { \
194 MEM_READ_LONG( addr, *((uint32_t *)&XF((reg) & 0x0E)) ); \
195 MEM_READ_LONG( addr+4, *((uint32_t *)&XF(reg)) ); \
196 } else { \
197 MEM_READ_LONG( addr, *((uint32_t *)&FR(reg)) ); \
198 MEM_READ_LONG( addr+4, *((uint32_t *)&FR((reg)|0x01)) ); \
199 } \
200 } else { \
201 CHECKRALIGN32(addr); \
202 MEM_READ_LONG( addr, *((uint32_t *)&FR(reg)) ); \
203 }
204 #define MEM_FP_WRITE( addr, reg ) \
205 if( IS_FPU_DOUBLESIZE() ) { \
206 CHECKWALIGN64(addr); \
207 if( reg & 1 ) { \
208 MEM_WRITE_LONG( addr, *((uint32_t *)&XF((reg)&0x0E)) ); \
209 MEM_WRITE_LONG( addr+4, *((uint32_t *)&XF(reg)) ); \
210 } else { \
211 MEM_WRITE_LONG( addr, *((uint32_t *)&FR(reg)) ); \
212 MEM_WRITE_LONG( addr+4, *((uint32_t *)&FR((reg)|0x01)) ); \
213 } \
214 } else { \
215 CHECKWALIGN32(addr); \
216 MEM_WRITE_LONG(addr, *((uint32_t *)&FR((reg))) ); \
217 }
219 #define UNDEF(ir)
220 #define UNIMP(ir)
222 /**
223 * Perform instruction-completion following core exit of a partially completed
224 * instruction. NOTE: This is only allowed on memory writes, operation is not
225 * guaranteed in any other case.
226 */
227 void sh4_finalize_instruction( void )
228 {
229 unsigned short ir;
230 uint32_t tmp;
232 if( IS_SYSCALL(sh4r.pc) ) {
233 return;
234 }
235 assert( IS_IN_ICACHE(sh4r.pc) );
236 ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
238 /**
239 * Note - we can't take an exit on a control transfer instruction itself,
240 * which means the exit must have happened in the delay slot. So for these
241 * cases, finalize the delay slot instruction, and re-execute the control transfer.
242 *
243 * For delay slots which modify the argument used in the branch instruction,
244 * we pretty much just assume that that can't have already happened in an exit case.
245 */
247 %%
248 BRA disp {:
249 sh4r.pc += 2;
250 sh4_finalize_instruction();
251 sh4r.pc += disp;
252 :}
253 BRAF Rn {:
254 sh4r.pc += 2;
255 tmp = sh4r.r[Rn];
256 sh4_finalize_instruction();
257 sh4r.pc += tmp;
258 :}
259 BSR disp {:
260 /* Note: PR is already set */
261 sh4r.pc += 2;
262 sh4_finalize_instruction();
263 sh4r.pc += disp;
264 :}
265 BSRF Rn {:
266 /* Note: PR is already set */
267 sh4r.pc += 2;
268 tmp = sh4r.r[Rn];
269 sh4_finalize_instruction();
270 sh4r.pc += tmp;
271 :}
272 BF/S disp {:
273 sh4r.pc += 2;
274 sh4_finalize_instruction();
275 if( !sh4r.t ) {
276 sh4r.pc += disp;
277 }
278 :}
279 BT/S disp {:
280 sh4r.pc += 2;
281 sh4_finalize_instruction();
282 if( sh4r.t ) {
283 sh4r.pc += disp;
284 }
285 :}
286 JMP @Rn {:
287 sh4r.pc += 2;
288 tmp = sh4r.r[Rn];
289 sh4_finalize_instruction();
290 sh4r.pc = tmp;
291 sh4r.new_pc = tmp + 2;
292 sh4r.slice_cycle += sh4_cpu_period;
293 return;
294 :}
295 JSR @Rn {:
296 /* Note: PR is already set */
297 sh4r.pc += 2;
298 tmp = sh4r.r[Rn];
299 sh4_finalize_instruction();
300 sh4r.pc = tmp;
301 sh4r.new_pc = tmp + 2;
302 sh4r.slice_cycle += sh4_cpu_period;
303 return;
304 :}
305 RTS {:
306 sh4r.pc += 2;
307 sh4_finalize_instruction();
308 sh4r.pc = sh4r.pr;
309 sh4r.new_pc = sh4r.pr + 2;
310 sh4r.slice_cycle += sh4_cpu_period;
311 return;
312 :}
313 RTE {:
314 /* SR is already set */
315 sh4r.pc += 2;
316 sh4_finalize_instruction();
317 sh4r.pc = sh4r.spc;
318 sh4r.new_pc = sh4r.pr + 2;
319 sh4r.slice_cycle += sh4_cpu_period;
320 return;
321 :}
322 MOV.B Rm, @-Rn {: sh4r.r[Rn]--; :}
323 MOV.W Rm, @-Rn {: sh4r.r[Rn] -= 2; :}
324 MOV.L Rm, @-Rn {: sh4r.r[Rn] -= 4; :}
325 MOV.B @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] ++; } :}
326 MOV.W @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] += 2; } :}
327 MOV.L @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] += 4; } :}
328 %%
329 sh4r.in_delay_slot = 0;
330 sh4r.pc += 2;
331 sh4r.new_pc = sh4r.pc+2;
332 sh4r.slice_cycle += sh4_cpu_period;
333 }
335 #undef UNDEF
336 #undef UNIMP
338 #define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
339 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }while(0)
342 gboolean sh4_execute_instruction( void )
343 {
344 uint32_t pc;
345 unsigned short ir;
346 uint32_t tmp;
347 float ftmp;
348 double dtmp;
349 int64_t memtmp; // temporary holder for memory reads
351 INIT_EXCEPTIONS(except)
353 #define R0 sh4r.r[0]
354 pc = sh4r.pc;
355 if( pc > 0xFFFFFF00 ) {
356 /* SYSCALL Magic */
357 sh4r.in_delay_slot = 0;
358 sh4r.pc = sh4r.pr;
359 sh4r.new_pc = sh4r.pc + 2;
360 syscall_invoke( pc );
361 return TRUE;
362 }
363 CHECKRALIGN16(pc);
365 #ifdef ENABLE_SH4STATS
366 sh4_stats_add_by_pc(sh4r.pc);
367 #endif
369 /* Read instruction */
370 if( !IS_IN_ICACHE(pc) ) {
371 gboolean delay_slot = sh4r.in_delay_slot;
372 if( !mmu_update_icache(pc) ) {
373 if( delay_slot ) {
374 sh4r.spc -= 2;
375 }
376 // Fault - look for the fault handler
377 if( !mmu_update_icache(sh4r.pc) ) {
378 // double fault - halt
379 ERROR( "Double fault - halting" );
380 sh4_core_exit(CORE_EXIT_HALT);
381 return FALSE;
382 }
383 }
384 pc = sh4r.pc;
385 }
386 assert( IS_IN_ICACHE(pc) );
387 ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
389 /* FIXME: This is a bit of a hack, but the PC of the delay slot should not
390 * be visible until after the instruction has executed (for exception
391 * correctness)
392 */
393 if( sh4r.in_delay_slot ) {
394 sh4r.pc -= 2;
395 }
396 %%
397 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
398 AND #imm, R0 {: R0 &= imm; :}
399 AND.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & tmp ); :}
400 NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}
401 OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}
402 OR #imm, R0 {: R0 |= imm; :}
403 OR.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | tmp ); :}
404 TAS.B @Rn {:
405 MEM_READ_BYTE_FOR_WRITE( sh4r.r[Rn], tmp );
406 sh4r.t = ( tmp == 0 ? 1 : 0 );
407 MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );
408 :}
409 TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}
410 TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}
411 TST.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); sh4r.t = ( tmp & imm ? 0 : 1 ); :}
412 XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}
413 XOR #imm, R0 {: R0 ^= imm; :}
414 XOR.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ tmp ); :}
415 XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}
417 ROTL Rn {:
418 sh4r.t = sh4r.r[Rn] >> 31;
419 sh4r.r[Rn] <<= 1;
420 sh4r.r[Rn] |= sh4r.t;
421 :}
422 ROTR Rn {:
423 sh4r.t = sh4r.r[Rn] & 0x00000001;
424 sh4r.r[Rn] >>= 1;
425 sh4r.r[Rn] |= (sh4r.t << 31);
426 :}
427 ROTCL Rn {:
428 tmp = sh4r.r[Rn] >> 31;
429 sh4r.r[Rn] <<= 1;
430 sh4r.r[Rn] |= sh4r.t;
431 sh4r.t = tmp;
432 :}
433 ROTCR Rn {:
434 tmp = sh4r.r[Rn] & 0x00000001;
435 sh4r.r[Rn] >>= 1;
436 sh4r.r[Rn] |= (sh4r.t << 31 );
437 sh4r.t = tmp;
438 :}
439 SHAD Rm, Rn {:
440 tmp = sh4r.r[Rm];
441 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
442 else if( (tmp & 0x1F) == 0 )
443 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;
444 else
445 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);
446 :}
447 SHLD Rm, Rn {:
448 tmp = sh4r.r[Rm];
449 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
450 else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;
451 else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);
452 :}
453 SHAL Rn {:
454 sh4r.t = sh4r.r[Rn] >> 31;
455 sh4r.r[Rn] <<= 1;
456 :}
457 SHAR Rn {:
458 sh4r.t = sh4r.r[Rn] & 0x00000001;
459 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;
460 :}
461 SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}
462 SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}
463 SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}
464 SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}
465 SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}
466 SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}
467 SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}
468 SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}
470 EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}
471 EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}
472 EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}
473 EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}
474 SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}
475 SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}
477 CLRT {: sh4r.t = 0; :}
478 SETT {: sh4r.t = 1; :}
479 CLRMAC {: sh4r.mac = 0; :}
480 LDTLB {: MMU_ldtlb(); :}
481 CLRS {: sh4r.s = 0; :}
482 SETS {: sh4r.s = 1; :}
483 MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}
484 NOP {: /* NOP */ :}
486 PREF @Rn {:
487 MEM_PREFETCH(sh4r.r[Rn]);
488 :}
489 OCBI @Rn {: :}
490 OCBP @Rn {: :}
491 OCBWB @Rn {: :}
492 MOVCA.L R0, @Rn {:
493 tmp = sh4r.r[Rn];
494 CHECKWALIGN32(tmp);
495 MEM_WRITE_LONG( tmp, R0 );
496 :}
497 MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}
498 MOV.W Rm, @(R0, Rn) {:
499 CHECKWALIGN16( R0 + sh4r.r[Rn] );
500 MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );
501 :}
502 MOV.L Rm, @(R0, Rn) {:
503 CHECKWALIGN32( R0 + sh4r.r[Rn] );
504 MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );
505 :}
506 MOV.B @(R0, Rm), Rn {: MEM_READ_BYTE( R0 + sh4r.r[Rm], sh4r.r[Rn] ); :}
507 MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );
508 MEM_READ_WORD( R0 + sh4r.r[Rm], sh4r.r[Rn] );
509 :}
510 MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );
511 MEM_READ_LONG( R0 + sh4r.r[Rm], sh4r.r[Rn] );
512 :}
513 MOV.L Rm, @(disp, Rn) {:
514 tmp = sh4r.r[Rn] + disp;
515 CHECKWALIGN32( tmp );
516 MEM_WRITE_LONG( tmp, sh4r.r[Rm] );
517 :}
518 MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
519 MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
520 MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
521 MOV.B Rm, @-Rn {: MEM_WRITE_BYTE( sh4r.r[Rn]-1, sh4r.r[Rm] ); sh4r.r[Rn]--; :}
522 MOV.W Rm, @-Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn]-2, sh4r.r[Rm] ); sh4r.r[Rn] -= 2; :}
523 MOV.L Rm, @-Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r[Rm] ); sh4r.r[Rn] -= 4; :}
524 MOV.L @(disp, Rm), Rn {:
525 tmp = sh4r.r[Rm] + disp;
526 CHECKRALIGN32( tmp );
527 MEM_READ_LONG( tmp, sh4r.r[Rn] );
528 :}
529 MOV.B @Rm, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); :}
530 MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); :}
531 MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); :}
532 MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}
533 MOV.B @Rm+, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] ++; } :}
534 MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] += 2; } :}
535 MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] += 4; } :}
536 MOV.L @(disp, PC), Rn {:
537 CHECKSLOTILLEGAL();
538 tmp = (pc&0xFFFFFFFC) + disp + 4;
539 MEM_READ_LONG( tmp, sh4r.r[Rn] );
540 :}
541 MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}
542 MOV.W R0, @(disp, GBR) {:
543 tmp = sh4r.gbr + disp;
544 CHECKWALIGN16( tmp );
545 MEM_WRITE_WORD( tmp, R0 );
546 :}
547 MOV.L R0, @(disp, GBR) {:
548 tmp = sh4r.gbr + disp;
549 CHECKWALIGN32( tmp );
550 MEM_WRITE_LONG( tmp, R0 );
551 :}
552 MOV.B @(disp, GBR), R0 {: MEM_READ_BYTE( sh4r.gbr + disp, R0 ); :}
553 MOV.W @(disp, GBR), R0 {:
554 tmp = sh4r.gbr + disp;
555 CHECKRALIGN16( tmp );
556 MEM_READ_WORD( tmp, R0 );
557 :}
558 MOV.L @(disp, GBR), R0 {:
559 tmp = sh4r.gbr + disp;
560 CHECKRALIGN32( tmp );
561 MEM_READ_LONG( tmp, R0 );
562 :}
563 MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}
564 MOV.W R0, @(disp, Rn) {:
565 tmp = sh4r.r[Rn] + disp;
566 CHECKWALIGN16( tmp );
567 MEM_WRITE_WORD( tmp, R0 );
568 :}
569 MOV.B @(disp, Rm), R0 {: MEM_READ_BYTE( sh4r.r[Rm] + disp, R0 ); :}
570 MOV.W @(disp, Rm), R0 {:
571 tmp = sh4r.r[Rm] + disp;
572 CHECKRALIGN16( tmp );
573 MEM_READ_WORD( tmp, R0 );
574 :}
575 MOV.W @(disp, PC), Rn {:
576 CHECKSLOTILLEGAL();
577 tmp = pc + 4 + disp;
578 MEM_READ_WORD( tmp, sh4r.r[Rn] );
579 :}
580 MOVA @(disp, PC), R0 {:
581 CHECKSLOTILLEGAL();
582 R0 = (pc&0xFFFFFFFC) + disp + 4;
583 :}
584 MOV #imm, Rn {: sh4r.r[Rn] = imm; :}
586 FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
587 FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
588 FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
589 FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
590 FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
591 FMOV FRm, @-Rn {: MEM_FP_WRITE( sh4r.r[Rn] - FP_WIDTH, FRm ); sh4r.r[Rn] -= FP_WIDTH; :}
592 FMOV FRm, FRn {:
593 if( IS_FPU_DOUBLESIZE() )
594 DR(FRn) = DR(FRm);
595 else
596 FR(FRn) = FR(FRm);
597 :}
599 CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}
600 CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}
601 CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
602 CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
603 CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}
604 CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}
605 CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}
606 CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}
607 CMP/STR Rm, Rn {:
608 /* set T = 1 if any byte in RM & RN is the same */
609 tmp = sh4r.r[Rm] ^ sh4r.r[Rn];
610 sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
611 (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
612 :}
614 ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}
615 ADD #imm, Rn {: sh4r.r[Rn] += imm; :}
616 ADDC Rm, Rn {:
617 tmp = sh4r.r[Rn];
618 sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;
619 sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );
620 :}
621 ADDV Rm, Rn {:
622 tmp = sh4r.r[Rn] + sh4r.r[Rm];
623 sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
624 sh4r.r[Rn] = tmp;
625 :}
626 DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}
627 DIV0S Rm, Rn {:
628 sh4r.q = sh4r.r[Rn]>>31;
629 sh4r.m = sh4r.r[Rm]>>31;
630 sh4r.t = sh4r.q ^ sh4r.m;
631 :}
632 DIV1 Rm, Rn {:
633 /* This is derived from the sh4 manual with some simplifications */
634 uint32_t tmp0, tmp1, tmp2, dir;
636 dir = sh4r.q ^ sh4r.m;
637 sh4r.q = (sh4r.r[Rn] >> 31);
638 tmp2 = sh4r.r[Rm];
639 sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
640 tmp0 = sh4r.r[Rn];
641 if( dir ) {
642 sh4r.r[Rn] += tmp2;
643 tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
644 } else {
645 sh4r.r[Rn] -= tmp2;
646 tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
647 }
648 sh4r.q ^= sh4r.m ^ tmp1;
649 sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
650 :}
651 DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
652 DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
653 DT Rn {:
654 sh4r.r[Rn] --;
655 sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
656 :}
657 MAC.W @Rm+, @Rn+ {:
658 int32_t stmp;
659 if( Rm == Rn ) {
660 CHECKRALIGN16(sh4r.r[Rn]);
661 MEM_READ_WORD( sh4r.r[Rn], tmp );
662 stmp = SIGNEXT16(tmp);
663 MEM_READ_WORD( sh4r.r[Rn]+2, tmp );
664 stmp *= SIGNEXT16(tmp);
665 sh4r.r[Rn] += 4;
666 } else {
667 CHECKRALIGN16( sh4r.r[Rn] );
668 CHECKRALIGN16( sh4r.r[Rm] );
669 MEM_READ_WORD(sh4r.r[Rn], tmp);
670 stmp = SIGNEXT16(tmp);
671 MEM_READ_WORD(sh4r.r[Rm], tmp);
672 stmp = stmp * SIGNEXT16(tmp);
673 sh4r.r[Rn] += 2;
674 sh4r.r[Rm] += 2;
675 }
676 if( sh4r.s ) {
677 int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
678 if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
679 sh4r.mac = 0x000000017FFFFFFFLL;
680 } else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
681 sh4r.mac = 0x0000000180000000LL;
682 } else {
683 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
684 ((uint32_t)(sh4r.mac + stmp));
685 }
686 } else {
687 sh4r.mac += SIGNEXT32(stmp);
688 }
689 :}
690 MAC.L @Rm+, @Rn+ {:
691 int64_t tmpl;
692 if( Rm == Rn ) {
693 CHECKRALIGN32( sh4r.r[Rn] );
694 MEM_READ_LONG(sh4r.r[Rn], tmp);
695 tmpl = SIGNEXT32(tmp);
696 MEM_READ_LONG(sh4r.r[Rn]+4, tmp);
697 tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
698 sh4r.r[Rn] += 8;
699 } else {
700 CHECKRALIGN32( sh4r.r[Rm] );
701 CHECKRALIGN32( sh4r.r[Rn] );
702 MEM_READ_LONG(sh4r.r[Rn], tmp);
703 tmpl = SIGNEXT32(tmp);
704 MEM_READ_LONG(sh4r.r[Rm], tmp);
705 tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
706 sh4r.r[Rn] += 4;
707 sh4r.r[Rm] += 4;
708 }
709 if( sh4r.s ) {
710 /* 48-bit Saturation. Yuch */
711 if( tmpl < (int64_t)0xFFFF800000000000LL )
712 tmpl = 0xFFFF800000000000LL;
713 else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
714 tmpl = 0x00007FFFFFFFFFFFLL;
715 }
716 sh4r.mac = tmpl;
717 :}
718 MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
719 (sh4r.r[Rm] * sh4r.r[Rn]); :}
720 MULU.W Rm, Rn {:
721 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
722 (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
723 :}
724 MULS.W Rm, Rn {:
725 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
726 (uint32_t)(SIGNEXT32(sh4r.r[Rm]&0xFFFF) * SIGNEXT32(sh4r.r[Rn]&0xFFFF));
727 :}
728 NEGC Rm, Rn {:
729 tmp = 0 - sh4r.r[Rm];
730 sh4r.r[Rn] = tmp - sh4r.t;
731 sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
732 :}
733 NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
734 SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
735 SUBC Rm, Rn {:
736 tmp = sh4r.r[Rn];
737 sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
738 sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
739 :}
740 SUBV Rm, Rn {:
741 tmp = sh4r.r[Rn] - sh4r.r[Rm];
742 sh4r.t = ( (sh4r.r[Rn]>>31) != (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
743 sh4r.r[Rn] = tmp;
744 :}
745 BRAF Rn {:
746 CHECKSLOTILLEGAL();
747 CHECKDEST( pc + 4 + sh4r.r[Rn] );
748 sh4r.in_delay_slot = 1;
749 sh4r.pc = sh4r.new_pc;
750 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
751 return TRUE;
752 :}
753 BSRF Rn {:
754 CHECKSLOTILLEGAL();
755 CHECKDEST( pc + 4 + sh4r.r[Rn] );
756 sh4r.in_delay_slot = 1;
757 sh4r.pr = sh4r.pc + 4;
758 sh4r.pc = sh4r.new_pc;
759 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
760 TRACE_CALL( pc, sh4r.new_pc );
761 return TRUE;
762 :}
763 BT disp {:
764 CHECKSLOTILLEGAL();
765 if( sh4r.t ) {
766 CHECKDEST( sh4r.pc + disp + 4 )
767 sh4r.pc += disp + 4;
768 sh4r.new_pc = sh4r.pc + 2;
769 return TRUE;
770 }
771 :}
772 BF disp {:
773 CHECKSLOTILLEGAL();
774 if( !sh4r.t ) {
775 CHECKDEST( sh4r.pc + disp + 4 )
776 sh4r.pc += disp + 4;
777 sh4r.new_pc = sh4r.pc + 2;
778 return TRUE;
779 }
780 :}
781 BT/S disp {:
782 CHECKSLOTILLEGAL();
783 if( sh4r.t ) {
784 CHECKDEST( sh4r.pc + disp + 4 )
785 sh4r.in_delay_slot = 1;
786 sh4r.pc = sh4r.new_pc;
787 sh4r.new_pc = pc + disp + 4;
788 sh4r.in_delay_slot = 1;
789 return TRUE;
790 }
791 :}
792 BF/S disp {:
793 CHECKSLOTILLEGAL();
794 if( !sh4r.t ) {
795 CHECKDEST( sh4r.pc + disp + 4 )
796 sh4r.in_delay_slot = 1;
797 sh4r.pc = sh4r.new_pc;
798 sh4r.new_pc = pc + disp + 4;
799 return TRUE;
800 }
801 :}
802 BRA disp {:
803 CHECKSLOTILLEGAL();
804 CHECKDEST( sh4r.pc + disp + 4 );
805 sh4r.in_delay_slot = 1;
806 sh4r.pc = sh4r.new_pc;
807 sh4r.new_pc = pc + 4 + disp;
808 return TRUE;
809 :}
810 BSR disp {:
811 CHECKDEST( sh4r.pc + disp + 4 );
812 CHECKSLOTILLEGAL();
813 sh4r.in_delay_slot = 1;
814 sh4r.pr = pc + 4;
815 sh4r.pc = sh4r.new_pc;
816 sh4r.new_pc = pc + 4 + disp;
817 TRACE_CALL( pc, sh4r.new_pc );
818 return TRUE;
819 :}
820 TRAPA #imm {:
821 CHECKSLOTILLEGAL();
822 sh4r.pc += 2;
823 sh4_raise_trap( imm );
824 return TRUE;
825 :}
826 RTS {:
827 CHECKSLOTILLEGAL();
828 CHECKDEST( sh4r.pr );
829 sh4r.in_delay_slot = 1;
830 sh4r.pc = sh4r.new_pc;
831 sh4r.new_pc = sh4r.pr;
832 TRACE_RETURN( pc, sh4r.new_pc );
833 return TRUE;
834 :}
835 SLEEP {:
836 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
837 sh4r.sh4_state = SH4_STATE_STANDBY;
838 } else {
839 sh4r.sh4_state = SH4_STATE_SLEEP;
840 }
841 return FALSE; /* Halt CPU */
842 :}
843 RTE {:
844 CHECKPRIV();
845 CHECKDEST( sh4r.spc );
846 CHECKSLOTILLEGAL();
847 sh4r.in_delay_slot = 1;
848 sh4r.pc = sh4r.new_pc;
849 sh4r.new_pc = sh4r.spc;
850 sh4_write_sr( sh4r.ssr );
851 return TRUE;
852 :}
853 JMP @Rn {:
854 CHECKDEST( sh4r.r[Rn] );
855 CHECKSLOTILLEGAL();
856 sh4r.in_delay_slot = 1;
857 sh4r.pc = sh4r.new_pc;
858 sh4r.new_pc = sh4r.r[Rn];
859 return TRUE;
860 :}
861 JSR @Rn {:
862 CHECKDEST( sh4r.r[Rn] );
863 CHECKSLOTILLEGAL();
864 sh4r.in_delay_slot = 1;
865 sh4r.pc = sh4r.new_pc;
866 sh4r.new_pc = sh4r.r[Rn];
867 sh4r.pr = pc + 4;
868 TRACE_CALL( pc, sh4r.new_pc );
869 return TRUE;
870 :}
871 STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
872 STS.L MACH, @-Rn {:
873 CHECKWALIGN32( sh4r.r[Rn] );
874 MEM_WRITE_LONG( sh4r.r[Rn]-4, (sh4r.mac>>32) );
875 sh4r.r[Rn] -= 4;
876 :}
877 STC.L SR, @-Rn {:
878 CHECKPRIV();
879 CHECKWALIGN32( sh4r.r[Rn] );
880 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4_read_sr() );
881 sh4r.r[Rn] -= 4;
882 :}
883 LDS.L @Rm+, MACH {:
884 CHECKRALIGN32( sh4r.r[Rm] );
885 MEM_READ_LONG(sh4r.r[Rm], tmp);
886 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
887 (((uint64_t)tmp)<<32);
888 sh4r.r[Rm] += 4;
889 :}
890 LDC.L @Rm+, SR {:
891 CHECKSLOTILLEGAL();
892 CHECKPRIV();
893 CHECKWALIGN32( sh4r.r[Rm] );
894 MEM_READ_LONG(sh4r.r[Rm], tmp);
895 sh4_write_sr( tmp );
896 sh4r.r[Rm] +=4;
897 :}
898 LDS Rm, MACH {:
899 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
900 (((uint64_t)sh4r.r[Rm])<<32);
901 :}
902 LDC Rm, SR {:
903 CHECKSLOTILLEGAL();
904 CHECKPRIV();
905 sh4_write_sr( sh4r.r[Rm] );
906 :}
907 LDC Rm, SGR {:
908 CHECKPRIV();
909 sh4r.sgr = sh4r.r[Rm];
910 :}
911 LDC.L @Rm+, SGR {:
912 CHECKPRIV();
913 CHECKRALIGN32( sh4r.r[Rm] );
914 MEM_READ_LONG(sh4r.r[Rm], sh4r.sgr);
915 sh4r.r[Rm] +=4;
916 :}
917 STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
918 STS.L MACL, @-Rn {:
919 CHECKWALIGN32( sh4r.r[Rn] );
920 MEM_WRITE_LONG( sh4r.r[Rn]-4, (uint32_t)sh4r.mac );
921 sh4r.r[Rn] -= 4;
922 :}
923 STC.L GBR, @-Rn {:
924 CHECKWALIGN32( sh4r.r[Rn] );
925 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.gbr );
926 sh4r.r[Rn] -= 4;
927 :}
928 LDS.L @Rm+, MACL {:
929 CHECKRALIGN32( sh4r.r[Rm] );
930 MEM_READ_LONG(sh4r.r[Rm], tmp);
931 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
932 (uint64_t)((uint32_t)tmp);
933 sh4r.r[Rm] += 4;
934 :}
935 LDC.L @Rm+, GBR {:
936 CHECKRALIGN32( sh4r.r[Rm] );
937 MEM_READ_LONG(sh4r.r[Rm], sh4r.gbr);
938 sh4r.r[Rm] +=4;
939 :}
940 LDS Rm, MACL {:
941 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
942 (uint64_t)((uint32_t)(sh4r.r[Rm]));
943 :}
944 LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
945 STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
946 STS.L PR, @-Rn {:
947 CHECKWALIGN32( sh4r.r[Rn] );
948 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.pr );
949 sh4r.r[Rn] -= 4;
950 :}
951 STC.L VBR, @-Rn {:
952 CHECKPRIV();
953 CHECKWALIGN32( sh4r.r[Rn] );
954 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.vbr );
955 sh4r.r[Rn] -= 4;
956 :}
957 LDS.L @Rm+, PR {:
958 CHECKRALIGN32( sh4r.r[Rm] );
959 MEM_READ_LONG( sh4r.r[Rm], sh4r.pr );
960 sh4r.r[Rm] += 4;
961 :}
962 LDC.L @Rm+, VBR {:
963 CHECKPRIV();
964 CHECKRALIGN32( sh4r.r[Rm] );
965 MEM_READ_LONG(sh4r.r[Rm], sh4r.vbr);
966 sh4r.r[Rm] +=4;
967 :}
968 LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
969 LDC Rm, VBR {:
970 CHECKPRIV();
971 sh4r.vbr = sh4r.r[Rm];
972 :}
973 STC SGR, Rn {:
974 CHECKPRIV();
975 sh4r.r[Rn] = sh4r.sgr;
976 :}
977 STC.L SGR, @-Rn {:
978 CHECKPRIV();
979 CHECKWALIGN32( sh4r.r[Rn] );
980 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.sgr );
981 sh4r.r[Rn] -= 4;
982 :}
983 STC.L SSR, @-Rn {:
984 CHECKPRIV();
985 CHECKWALIGN32( sh4r.r[Rn] );
986 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.ssr );
987 sh4r.r[Rn] -= 4;
988 :}
989 LDC.L @Rm+, SSR {:
990 CHECKPRIV();
991 CHECKRALIGN32( sh4r.r[Rm] );
992 MEM_READ_LONG(sh4r.r[Rm], sh4r.ssr);
993 sh4r.r[Rm] +=4;
994 :}
995 LDC Rm, SSR {:
996 CHECKPRIV();
997 sh4r.ssr = sh4r.r[Rm];
998 :}
999 STC.L SPC, @-Rn {:
1000 CHECKPRIV();
1001 CHECKWALIGN32( sh4r.r[Rn] );
1002 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.spc );
1003 sh4r.r[Rn] -= 4;
1004 :}
1005 LDC.L @Rm+, SPC {:
1006 CHECKPRIV();
1007 CHECKRALIGN32( sh4r.r[Rm] );
1008 MEM_READ_LONG(sh4r.r[Rm], sh4r.spc);
1009 sh4r.r[Rm] +=4;
1010 :}
1011 LDC Rm, SPC {:
1012 CHECKPRIV();
1013 sh4r.spc = sh4r.r[Rm];
1014 :}
1015 STS FPUL, Rn {:
1016 CHECKFPUEN();
1017 sh4r.r[Rn] = FPULi;
1018 :}
1019 STS.L FPUL, @-Rn {:
1020 CHECKFPUEN();
1021 CHECKWALIGN32( sh4r.r[Rn] );
1022 MEM_WRITE_LONG( sh4r.r[Rn]-4, FPULi );
1023 sh4r.r[Rn] -= 4;
1024 :}
1025 LDS.L @Rm+, FPUL {:
1026 CHECKFPUEN();
1027 CHECKRALIGN32( sh4r.r[Rm] );
1028 MEM_READ_LONG(sh4r.r[Rm], FPULi);
1029 sh4r.r[Rm] +=4;
1030 :}
1031 LDS Rm, FPUL {:
1032 CHECKFPUEN();
1033 FPULi = sh4r.r[Rm];
1034 :}
1035 STS FPSCR, Rn {:
1036 CHECKFPUEN();
1037 sh4r.r[Rn] = sh4r.fpscr;
1038 :}
1039 STS.L FPSCR, @-Rn {:
1040 CHECKFPUEN();
1041 CHECKWALIGN32( sh4r.r[Rn] );
1042 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.fpscr );
1043 sh4r.r[Rn] -= 4;
1044 :}
1045 LDS.L @Rm+, FPSCR {:
1046 CHECKFPUEN();
1047 CHECKRALIGN32( sh4r.r[Rm] );
1048 MEM_READ_LONG(sh4r.r[Rm], tmp);
1049 sh4r.r[Rm] +=4;
1050 sh4_write_fpscr( tmp );
1051 :}
1052 LDS Rm, FPSCR {:
1053 CHECKFPUEN();
1054 sh4_write_fpscr( sh4r.r[Rm] );
1055 :}
1056 STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
1057 STC.L DBR, @-Rn {:
1058 CHECKPRIV();
1059 CHECKWALIGN32( sh4r.r[Rn] );
1060 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.dbr );
1061 sh4r.r[Rn] -= 4;
1062 :}
1063 LDC.L @Rm+, DBR {:
1064 CHECKPRIV();
1065 CHECKRALIGN32( sh4r.r[Rm] );
1066 MEM_READ_LONG(sh4r.r[Rm], sh4r.dbr);
1067 sh4r.r[Rm] +=4;
1068 :}
1069 LDC Rm, DBR {:
1070 CHECKPRIV();
1071 sh4r.dbr = sh4r.r[Rm];
1072 :}
1073 STC.L Rm_BANK, @-Rn {:
1074 CHECKPRIV();
1075 CHECKWALIGN32( sh4r.r[Rn] );
1076 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r_bank[Rm_BANK] );
1077 sh4r.r[Rn] -= 4;
1078 :}
1079 LDC.L @Rm+, Rn_BANK {:
1080 CHECKPRIV();
1081 CHECKRALIGN32( sh4r.r[Rm] );
1082 MEM_READ_LONG( sh4r.r[Rm], sh4r.r_bank[Rn_BANK] );
1083 sh4r.r[Rm] += 4;
1084 :}
1085 LDC Rm, Rn_BANK {:
1086 CHECKPRIV();
1087 sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
1088 :}
1089 STC SR, Rn {:
1090 CHECKPRIV();
1091 sh4r.r[Rn] = sh4_read_sr();
1092 :}
1093 STC GBR, Rn {:
1094 sh4r.r[Rn] = sh4r.gbr;
1095 :}
1096 STC VBR, Rn {:
1097 CHECKPRIV();
1098 sh4r.r[Rn] = sh4r.vbr;
1099 :}
1100 STC SSR, Rn {:
1101 CHECKPRIV();
1102 sh4r.r[Rn] = sh4r.ssr;
1103 :}
1104 STC SPC, Rn {:
1105 CHECKPRIV();
1106 sh4r.r[Rn] = sh4r.spc;
1107 :}
1108 STC Rm_BANK, Rn {:
1109 CHECKPRIV();
1110 sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
1111 :}
1113 FADD FRm, FRn {:
1114 CHECKFPUEN();
1115 if( IS_FPU_DOUBLEPREC() ) {
1116 DR(FRn) += DR(FRm);
1117 } else {
1118 FR(FRn) += FR(FRm);
1119 }
1120 :}
1121 FSUB FRm, FRn {:
1122 CHECKFPUEN();
1123 if( IS_FPU_DOUBLEPREC() ) {
1124 DR(FRn) -= DR(FRm);
1125 } else {
1126 FR(FRn) -= FR(FRm);
1127 }
1128 :}
1130 FMUL FRm, FRn {:
1131 CHECKFPUEN();
1132 if( IS_FPU_DOUBLEPREC() ) {
1133 DR(FRn) *= DR(FRm);
1134 } else {
1135 FR(FRn) *= FR(FRm);
1136 }
1137 :}
1139 FDIV FRm, FRn {:
1140 CHECKFPUEN();
1141 if( IS_FPU_DOUBLEPREC() ) {
1142 DR(FRn) /= DR(FRm);
1143 } else {
1144 FR(FRn) /= FR(FRm);
1145 }
1146 :}
1148 FCMP/EQ FRm, FRn {:
1149 CHECKFPUEN();
1150 if( IS_FPU_DOUBLEPREC() ) {
1151 sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
1152 } else {
1153 sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
1154 }
1155 :}
1157 FCMP/GT FRm, FRn {:
1158 CHECKFPUEN();
1159 if( IS_FPU_DOUBLEPREC() ) {
1160 sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
1161 } else {
1162 sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
1163 }
1164 :}
1166 FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
1167 FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
1168 FLOAT FPUL, FRn {:
1169 CHECKFPUEN();
1170 if( IS_FPU_DOUBLEPREC() ) {
1171 if( FRn&1 ) { // No, really...
1172 dtmp = (double)FPULi;
1173 FR(FRn) = *(((float *)&dtmp)+1);
1174 } else {
1175 DRF(FRn>>1) = (double)FPULi;
1176 }
1177 } else {
1178 FR(FRn) = (float)FPULi;
1179 }
1180 :}
1181 FTRC FRm, FPUL {:
1182 CHECKFPUEN();
1183 if( IS_FPU_DOUBLEPREC() ) {
1184 if( FRm&1 ) {
1185 dtmp = 0;
1186 *(((float *)&dtmp)+1) = FR(FRm);
1187 } else {
1188 dtmp = DRF(FRm>>1);
1189 }
1190 if( dtmp >= MAX_INTF )
1191 FPULi = MAX_INT;
1192 else if( dtmp <= MIN_INTF )
1193 FPULi = MIN_INT;
1194 else
1195 FPULi = (int32_t)dtmp;
1196 } else {
1197 ftmp = FR(FRm);
1198 if( ftmp >= MAX_INTF )
1199 FPULi = MAX_INT;
1200 else if( ftmp <= MIN_INTF )
1201 FPULi = MIN_INT;
1202 else
1203 FPULi = (int32_t)ftmp;
1204 }
1205 :}
1206 FNEG FRn {:
1207 CHECKFPUEN();
1208 if( IS_FPU_DOUBLEPREC() ) {
1209 DR(FRn) = -DR(FRn);
1210 } else {
1211 FR(FRn) = -FR(FRn);
1212 }
1213 :}
1214 FABS FRn {:
1215 CHECKFPUEN();
1216 if( IS_FPU_DOUBLEPREC() ) {
1217 DR(FRn) = fabs(DR(FRn));
1218 } else {
1219 FR(FRn) = fabsf(FR(FRn));
1220 }
1221 :}
1222 FSQRT FRn {:
1223 CHECKFPUEN();
1224 if( IS_FPU_DOUBLEPREC() ) {
1225 DR(FRn) = sqrt(DR(FRn));
1226 } else {
1227 FR(FRn) = sqrtf(FR(FRn));
1228 }
1229 :}
1230 FLDI0 FRn {:
1231 CHECKFPUEN();
1232 if( IS_FPU_DOUBLEPREC() ) {
1233 DR(FRn) = 0.0;
1234 } else {
1235 FR(FRn) = 0.0;
1236 }
1237 :}
1238 FLDI1 FRn {:
1239 CHECKFPUEN();
1240 if( IS_FPU_DOUBLEPREC() ) {
1241 DR(FRn) = 1.0;
1242 } else {
1243 FR(FRn) = 1.0;
1244 }
1245 :}
1246 FMAC FR0, FRm, FRn {:
1247 CHECKFPUEN();
1248 if( IS_FPU_DOUBLEPREC() ) {
1249 DR(FRn) += DR(FRm)*DR(0);
1250 } else {
1251 FR(FRn) += FR(FRm)*FR(0);
1252 }
1253 :}
1254 FRCHG {:
1255 CHECKFPUEN();
1256 sh4r.fpscr ^= FPSCR_FR;
1257 sh4_switch_fr_banks();
1258 :}
1259 FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
1260 FCNVSD FPUL, FRn {:
1261 CHECKFPUEN();
1262 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1263 DR(FRn) = (double)FPULf;
1264 }
1265 :}
1266 FCNVDS FRm, FPUL {:
1267 CHECKFPUEN();
1268 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1269 FPULf = (float)DR(FRm);
1270 }
1271 :}
1273 FSRRA FRn {:
1274 CHECKFPUEN();
1275 if( !IS_FPU_DOUBLEPREC() ) {
1276 FR(FRn) = 1.0/sqrtf(FR(FRn));
1277 }
1278 :}
1279 FIPR FVm, FVn {:
1280 CHECKFPUEN();
1281 if( !IS_FPU_DOUBLEPREC() ) {
1282 int tmp2 = FVn<<2;
1283 tmp = FVm<<2;
1284 FR(tmp2+3) = FR(tmp)*FR(tmp2) +
1285 FR(tmp+1)*FR(tmp2+1) +
1286 FR(tmp+2)*FR(tmp2+2) +
1287 FR(tmp+3)*FR(tmp2+3);
1288 }
1289 :}
1290 FSCA FPUL, FRn {:
1291 CHECKFPUEN();
1292 if( !IS_FPU_DOUBLEPREC() ) {
1293 sh4_fsca( FPULi, (float *)&(DRF(FRn>>1)) );
1294 }
1295 :}
1296 FTRV XMTRX, FVn {:
1297 CHECKFPUEN();
1298 if( !IS_FPU_DOUBLEPREC() ) {
1299 sh4_ftrv((float *)&(DRF(FVn<<1)) );
1300 }
1301 :}
1302 UNDEF {:
1303 UNDEF(ir);
1304 :}
1305 %%
1306 sh4r.pc = sh4r.new_pc;
1307 sh4r.new_pc += 2;
1309 except:
1310 sh4r.in_delay_slot = 0;
1311 return TRUE;
1312 }
.