filename | src/sh4/sh4core.in |
changeset | 1231:d63c808ddcd3 |
prev | 1217:677b1d85f1b4 |
prev | 1230:64a91ef571fc |
author | nkeynes |
date | Tue Feb 28 17:25:26 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Implement display output for the GLES2 case (no fixed function rendering) |
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 #define MEM_READ_BYTE( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_read(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { val = fntmp->read_byte(addrtmp); }
166 #define MEM_READ_BYTE_FOR_WRITE( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_write(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { val = fntmp->read_byte_for_write(addrtmp); }
167 #define MEM_READ_WORD( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_read(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { val = fntmp->read_word(addrtmp); }
168 #define MEM_READ_LONG( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_read(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { val = fntmp->read_long(addrtmp); }
169 #define MEM_WRITE_BYTE( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_write(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { fntmp->write_byte(addrtmp,val); }
170 #define MEM_WRITE_WORD( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_write(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { fntmp->write_word(addrtmp,val); }
171 #define MEM_WRITE_LONG( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_write(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { fntmp->write_long(addrtmp,val); }
172 #define MEM_PREFETCH( addr ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_prefetch(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { fntmp->prefetch(addrtmp); }
174 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
176 #define MEM_FP_READ( addr, reg ) \
177 if( IS_FPU_DOUBLESIZE() ) { \
178 CHECKRALIGN64(addr); \
179 if( reg & 1 ) { \
180 MEM_READ_LONG( addr, *((uint32_t *)&XF((reg) & 0x0E)) ); \
181 MEM_READ_LONG( addr+4, *((uint32_t *)&XF(reg)) ); \
182 } else { \
183 MEM_READ_LONG( addr, *((uint32_t *)&FR(reg)) ); \
184 MEM_READ_LONG( addr+4, *((uint32_t *)&FR((reg)|0x01)) ); \
185 } \
186 } else { \
187 CHECKRALIGN32(addr); \
188 MEM_READ_LONG( addr, *((uint32_t *)&FR(reg)) ); \
189 }
190 #define MEM_FP_WRITE( addr, reg ) \
191 if( IS_FPU_DOUBLESIZE() ) { \
192 CHECKWALIGN64(addr); \
193 if( reg & 1 ) { \
194 MEM_WRITE_LONG( addr, *((uint32_t *)&XF((reg)&0x0E)) ); \
195 MEM_WRITE_LONG( addr+4, *((uint32_t *)&XF(reg)) ); \
196 } else { \
197 MEM_WRITE_LONG( addr, *((uint32_t *)&FR(reg)) ); \
198 MEM_WRITE_LONG( addr+4, *((uint32_t *)&FR((reg)|0x01)) ); \
199 } \
200 } else { \
201 CHECKWALIGN32(addr); \
202 MEM_WRITE_LONG(addr, *((uint32_t *)&FR((reg))) ); \
203 }
205 #define UNDEF(ir)
206 #define UNIMP(ir)
208 /**
209 * Perform instruction-completion following core exit of a partially completed
210 * instruction. NOTE: This is only allowed on memory writes, operation is not
211 * guaranteed in any other case.
212 */
213 void sh4_finalize_instruction( void )
214 {
215 unsigned short ir;
216 uint32_t tmp;
218 if( IS_SYSCALL(sh4r.pc) ) {
219 return;
220 }
221 assert( IS_IN_ICACHE(sh4r.pc) );
222 ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
224 /**
225 * Note - we can't take an exit on a control transfer instruction itself,
226 * which means the exit must have happened in the delay slot. So for these
227 * cases, finalize the delay slot instruction, and re-execute the control transfer.
228 *
229 * For delay slots which modify the argument used in the branch instruction,
230 * we pretty much just assume that that can't have already happened in an exit case.
231 */
233 %%
234 BRA disp {:
235 sh4r.pc += 2;
236 sh4_finalize_instruction();
237 sh4r.pc += disp;
238 :}
239 BRAF Rn {:
240 sh4r.pc += 2;
241 tmp = sh4r.r[Rn];
242 sh4_finalize_instruction();
243 sh4r.pc += tmp;
244 :}
245 BSR disp {:
246 /* Note: PR is already set */
247 sh4r.pc += 2;
248 sh4_finalize_instruction();
249 sh4r.pc += disp;
250 :}
251 BSRF Rn {:
252 /* Note: PR is already set */
253 sh4r.pc += 2;
254 tmp = sh4r.r[Rn];
255 sh4_finalize_instruction();
256 sh4r.pc += tmp;
257 :}
258 BF/S disp {:
259 sh4r.pc += 2;
260 sh4_finalize_instruction();
261 if( !sh4r.t ) {
262 sh4r.pc += disp;
263 }
264 :}
265 BT/S disp {:
266 sh4r.pc += 2;
267 sh4_finalize_instruction();
268 if( sh4r.t ) {
269 sh4r.pc += disp;
270 }
271 :}
272 JMP @Rn {:
273 sh4r.pc += 2;
274 tmp = sh4r.r[Rn];
275 sh4_finalize_instruction();
276 sh4r.pc = tmp;
277 sh4r.new_pc = tmp + 2;
278 sh4r.slice_cycle += sh4_cpu_period;
279 return;
280 :}
281 JSR @Rn {:
282 /* Note: PR is already set */
283 sh4r.pc += 2;
284 tmp = sh4r.r[Rn];
285 sh4_finalize_instruction();
286 sh4r.pc = tmp;
287 sh4r.new_pc = tmp + 2;
288 sh4r.slice_cycle += sh4_cpu_period;
289 return;
290 :}
291 RTS {:
292 sh4r.pc += 2;
293 sh4_finalize_instruction();
294 sh4r.pc = sh4r.pr;
295 sh4r.new_pc = sh4r.pr + 2;
296 sh4r.slice_cycle += sh4_cpu_period;
297 return;
298 :}
299 RTE {:
300 /* SR is already set */
301 sh4r.pc += 2;
302 sh4_finalize_instruction();
303 sh4r.pc = sh4r.spc;
304 sh4r.new_pc = sh4r.pr + 2;
305 sh4r.slice_cycle += sh4_cpu_period;
306 return;
307 :}
308 MOV.B Rm, @-Rn {: sh4r.r[Rn]--; :}
309 MOV.W Rm, @-Rn {: sh4r.r[Rn] -= 2; :}
310 MOV.L Rm, @-Rn {: sh4r.r[Rn] -= 4; :}
311 MOV.B @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] ++; } :}
312 MOV.W @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] += 2; } :}
313 MOV.L @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] += 4; } :}
314 %%
315 sh4r.in_delay_slot = 0;
316 sh4r.pc += 2;
317 sh4r.new_pc = sh4r.pc+2;
318 sh4r.slice_cycle += sh4_cpu_period;
319 }
321 #undef UNDEF
322 #undef UNIMP
324 #define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
325 #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)
328 gboolean sh4_execute_instruction( void )
329 {
330 uint32_t pc;
331 unsigned short ir;
332 uint32_t tmp;
333 float ftmp;
334 double dtmp;
335 sh4addr_t addrtmp; // temporary holder for memory addresses
336 mem_region_fn_t fntmp;
339 #define R0 sh4r.r[0]
340 pc = sh4r.pc;
341 if( pc > 0xFFFFFF00 ) {
342 /* SYSCALL Magic */
343 sh4r.in_delay_slot = 0;
344 sh4r.pc = sh4r.pr;
345 sh4r.new_pc = sh4r.pc + 2;
346 syscall_invoke( pc );
347 return TRUE;
348 }
349 CHECKRALIGN16(pc);
351 #ifdef ENABLE_SH4STATS
352 sh4_stats_add_by_pc(sh4r.pc);
353 #endif
355 /* Read instruction */
356 if( !IS_IN_ICACHE(pc) ) {
357 gboolean delay_slot = sh4r.in_delay_slot;
358 if( !mmu_update_icache(pc) ) {
359 if( delay_slot ) {
360 sh4r.spc -= 2;
361 }
362 // Fault - look for the fault handler
363 if( !mmu_update_icache(sh4r.pc) ) {
364 // double fault - halt
365 ERROR( "Double fault - halting" );
366 sh4_core_exit(CORE_EXIT_HALT);
367 return FALSE;
368 }
369 }
370 pc = sh4r.pc;
371 }
372 assert( IS_IN_ICACHE(pc) );
373 ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
375 /* FIXME: This is a bit of a hack, but the PC of the delay slot should not
376 * be visible until after the instruction has executed (for exception
377 * correctness)
378 */
379 if( sh4r.in_delay_slot ) {
380 sh4r.pc -= 2;
381 }
382 %%
383 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
384 AND #imm, R0 {: R0 &= imm; :}
385 AND.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & tmp ); :}
386 NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}
387 OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}
388 OR #imm, R0 {: R0 |= imm; :}
389 OR.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | tmp ); :}
390 TAS.B @Rn {:
391 MEM_READ_BYTE_FOR_WRITE( sh4r.r[Rn], tmp );
392 sh4r.t = ( tmp == 0 ? 1 : 0 );
393 MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );
394 :}
395 TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}
396 TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}
397 TST.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); sh4r.t = ( tmp & imm ? 0 : 1 ); :}
398 XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}
399 XOR #imm, R0 {: R0 ^= imm; :}
400 XOR.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ tmp ); :}
401 XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}
403 ROTL Rn {:
404 sh4r.t = sh4r.r[Rn] >> 31;
405 sh4r.r[Rn] <<= 1;
406 sh4r.r[Rn] |= sh4r.t;
407 :}
408 ROTR Rn {:
409 sh4r.t = sh4r.r[Rn] & 0x00000001;
410 sh4r.r[Rn] >>= 1;
411 sh4r.r[Rn] |= (sh4r.t << 31);
412 :}
413 ROTCL Rn {:
414 tmp = sh4r.r[Rn] >> 31;
415 sh4r.r[Rn] <<= 1;
416 sh4r.r[Rn] |= sh4r.t;
417 sh4r.t = tmp;
418 :}
419 ROTCR Rn {:
420 tmp = sh4r.r[Rn] & 0x00000001;
421 sh4r.r[Rn] >>= 1;
422 sh4r.r[Rn] |= (sh4r.t << 31 );
423 sh4r.t = tmp;
424 :}
425 SHAD Rm, Rn {:
426 tmp = sh4r.r[Rm];
427 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
428 else if( (tmp & 0x1F) == 0 )
429 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;
430 else
431 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);
432 :}
433 SHLD Rm, Rn {:
434 tmp = sh4r.r[Rm];
435 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
436 else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;
437 else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);
438 :}
439 SHAL Rn {:
440 sh4r.t = sh4r.r[Rn] >> 31;
441 sh4r.r[Rn] <<= 1;
442 :}
443 SHAR Rn {:
444 sh4r.t = sh4r.r[Rn] & 0x00000001;
445 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;
446 :}
447 SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}
448 SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}
449 SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}
450 SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}
451 SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}
452 SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}
453 SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}
454 SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}
456 EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}
457 EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}
458 EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}
459 EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}
460 SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}
461 SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}
463 CLRT {: sh4r.t = 0; :}
464 SETT {: sh4r.t = 1; :}
465 CLRMAC {: sh4r.mac = 0; :}
466 LDTLB {: MMU_ldtlb(); :}
467 CLRS {: sh4r.s = 0; :}
468 SETS {: sh4r.s = 1; :}
469 MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}
470 NOP {: /* NOP */ :}
472 PREF @Rn {:
473 MEM_PREFETCH(sh4r.r[Rn]);
474 :}
475 OCBI @Rn {: :}
476 OCBP @Rn {: :}
477 OCBWB @Rn {: :}
478 MOVCA.L R0, @Rn {:
479 tmp = sh4r.r[Rn];
480 CHECKWALIGN32(tmp);
481 MEM_WRITE_LONG( tmp, R0 );
482 :}
483 MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}
484 MOV.W Rm, @(R0, Rn) {:
485 CHECKWALIGN16( R0 + sh4r.r[Rn] );
486 MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );
487 :}
488 MOV.L Rm, @(R0, Rn) {:
489 CHECKWALIGN32( R0 + sh4r.r[Rn] );
490 MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );
491 :}
492 MOV.B @(R0, Rm), Rn {: MEM_READ_BYTE( R0 + sh4r.r[Rm], sh4r.r[Rn] ); :}
493 MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );
494 MEM_READ_WORD( R0 + sh4r.r[Rm], sh4r.r[Rn] );
495 :}
496 MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );
497 MEM_READ_LONG( R0 + sh4r.r[Rm], sh4r.r[Rn] );
498 :}
499 MOV.L Rm, @(disp, Rn) {:
500 tmp = sh4r.r[Rn] + disp;
501 CHECKWALIGN32( tmp );
502 MEM_WRITE_LONG( tmp, sh4r.r[Rm] );
503 :}
504 MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
505 MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
506 MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
507 MOV.B Rm, @-Rn {: MEM_WRITE_BYTE( sh4r.r[Rn]-1, sh4r.r[Rm] ); sh4r.r[Rn]--; :}
508 MOV.W Rm, @-Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn]-2, sh4r.r[Rm] ); sh4r.r[Rn] -= 2; :}
509 MOV.L Rm, @-Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r[Rm] ); sh4r.r[Rn] -= 4; :}
510 MOV.L @(disp, Rm), Rn {:
511 tmp = sh4r.r[Rm] + disp;
512 CHECKRALIGN32( tmp );
513 MEM_READ_LONG( tmp, sh4r.r[Rn] );
514 :}
515 MOV.B @Rm, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); :}
516 MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); :}
517 MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); :}
518 MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}
519 MOV.B @Rm+, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] ++; } :}
520 MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] += 2; } :}
521 MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] += 4; } :}
522 MOV.L @(disp, PC), Rn {:
523 CHECKSLOTILLEGAL();
524 tmp = (pc&0xFFFFFFFC) + disp + 4;
525 MEM_READ_LONG( tmp, sh4r.r[Rn] );
526 :}
527 MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}
528 MOV.W R0, @(disp, GBR) {:
529 tmp = sh4r.gbr + disp;
530 CHECKWALIGN16( tmp );
531 MEM_WRITE_WORD( tmp, R0 );
532 :}
533 MOV.L R0, @(disp, GBR) {:
534 tmp = sh4r.gbr + disp;
535 CHECKWALIGN32( tmp );
536 MEM_WRITE_LONG( tmp, R0 );
537 :}
538 MOV.B @(disp, GBR), R0 {: MEM_READ_BYTE( sh4r.gbr + disp, R0 ); :}
539 MOV.W @(disp, GBR), R0 {:
540 tmp = sh4r.gbr + disp;
541 CHECKRALIGN16( tmp );
542 MEM_READ_WORD( tmp, R0 );
543 :}
544 MOV.L @(disp, GBR), R0 {:
545 tmp = sh4r.gbr + disp;
546 CHECKRALIGN32( tmp );
547 MEM_READ_LONG( tmp, R0 );
548 :}
549 MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}
550 MOV.W R0, @(disp, Rn) {:
551 tmp = sh4r.r[Rn] + disp;
552 CHECKWALIGN16( tmp );
553 MEM_WRITE_WORD( tmp, R0 );
554 :}
555 MOV.B @(disp, Rm), R0 {: MEM_READ_BYTE( sh4r.r[Rm] + disp, R0 ); :}
556 MOV.W @(disp, Rm), R0 {:
557 tmp = sh4r.r[Rm] + disp;
558 CHECKRALIGN16( tmp );
559 MEM_READ_WORD( tmp, R0 );
560 :}
561 MOV.W @(disp, PC), Rn {:
562 CHECKSLOTILLEGAL();
563 tmp = pc + 4 + disp;
564 MEM_READ_WORD( tmp, sh4r.r[Rn] );
565 :}
566 MOVA @(disp, PC), R0 {:
567 CHECKSLOTILLEGAL();
568 R0 = (pc&0xFFFFFFFC) + disp + 4;
569 :}
570 MOV #imm, Rn {: sh4r.r[Rn] = imm; :}
572 FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
573 FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
574 FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
575 FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
576 FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
577 FMOV FRm, @-Rn {: MEM_FP_WRITE( sh4r.r[Rn] - FP_WIDTH, FRm ); sh4r.r[Rn] -= FP_WIDTH; :}
578 FMOV FRm, FRn {:
579 if( IS_FPU_DOUBLESIZE() )
580 DR(FRn) = DR(FRm);
581 else
582 FR(FRn) = FR(FRm);
583 :}
585 CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}
586 CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}
587 CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
588 CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
589 CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}
590 CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}
591 CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}
592 CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}
593 CMP/STR Rm, Rn {:
594 /* set T = 1 if any byte in RM & RN is the same */
595 tmp = sh4r.r[Rm] ^ sh4r.r[Rn];
596 sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
597 (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
598 :}
600 ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}
601 ADD #imm, Rn {: sh4r.r[Rn] += imm; :}
602 ADDC Rm, Rn {:
603 tmp = sh4r.r[Rn];
604 sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;
605 sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );
606 :}
607 ADDV Rm, Rn {:
608 tmp = sh4r.r[Rn] + sh4r.r[Rm];
609 sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
610 sh4r.r[Rn] = tmp;
611 :}
612 DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}
613 DIV0S Rm, Rn {:
614 sh4r.q = sh4r.r[Rn]>>31;
615 sh4r.m = sh4r.r[Rm]>>31;
616 sh4r.t = sh4r.q ^ sh4r.m;
617 :}
618 DIV1 Rm, Rn {:
619 /* This is derived from the sh4 manual with some simplifications */
620 uint32_t tmp0, tmp1, tmp2, dir;
622 dir = sh4r.q ^ sh4r.m;
623 sh4r.q = (sh4r.r[Rn] >> 31);
624 tmp2 = sh4r.r[Rm];
625 sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
626 tmp0 = sh4r.r[Rn];
627 if( dir ) {
628 sh4r.r[Rn] += tmp2;
629 tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
630 } else {
631 sh4r.r[Rn] -= tmp2;
632 tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
633 }
634 sh4r.q ^= sh4r.m ^ tmp1;
635 sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
636 :}
637 DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
638 DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
639 DT Rn {:
640 sh4r.r[Rn] --;
641 sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
642 :}
643 MAC.W @Rm+, @Rn+ {:
644 int32_t stmp;
645 if( Rm == Rn ) {
646 CHECKRALIGN16(sh4r.r[Rn]);
647 MEM_READ_WORD( sh4r.r[Rn], tmp );
648 stmp = SIGNEXT16(tmp);
649 MEM_READ_WORD( sh4r.r[Rn]+2, tmp );
650 stmp *= SIGNEXT16(tmp);
651 sh4r.r[Rn] += 4;
652 } else {
653 CHECKRALIGN16( sh4r.r[Rn] );
654 MEM_READ_WORD(sh4r.r[Rn], tmp);
655 stmp = SIGNEXT16(tmp);
656 CHECKRALIGN16( sh4r.r[Rm] );
657 MEM_READ_WORD(sh4r.r[Rm], tmp);
658 stmp = stmp * SIGNEXT16(tmp);
659 sh4r.r[Rn] += 2;
660 sh4r.r[Rm] += 2;
661 }
662 if( sh4r.s ) {
663 int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
664 if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
665 sh4r.mac = 0x000000017FFFFFFFLL;
666 } else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
667 sh4r.mac = 0x0000000180000000LL;
668 } else {
669 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
670 ((uint32_t)(sh4r.mac + stmp));
671 }
672 } else {
673 sh4r.mac += SIGNEXT32(stmp);
674 }
675 :}
676 MAC.L @Rm+, @Rn+ {:
677 int64_t tmpl;
678 if( Rm == Rn ) {
679 CHECKRALIGN32( sh4r.r[Rn] );
680 MEM_READ_LONG(sh4r.r[Rn], tmp);
681 tmpl = SIGNEXT32(tmp);
682 MEM_READ_LONG(sh4r.r[Rn]+4, tmp);
683 tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
684 sh4r.r[Rn] += 8;
685 } else {
686 CHECKRALIGN32( sh4r.r[Rm] );
687 CHECKRALIGN32( sh4r.r[Rn] );
688 MEM_READ_LONG(sh4r.r[Rn], tmp);
689 tmpl = SIGNEXT32(tmp);
690 MEM_READ_LONG(sh4r.r[Rm], tmp);
691 tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
692 sh4r.r[Rn] += 4;
693 sh4r.r[Rm] += 4;
694 }
695 if( sh4r.s ) {
696 /* 48-bit Saturation. Yuch */
697 if( tmpl < (int64_t)0xFFFF800000000000LL )
698 tmpl = 0xFFFF800000000000LL;
699 else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
700 tmpl = 0x00007FFFFFFFFFFFLL;
701 }
702 sh4r.mac = tmpl;
703 :}
704 MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
705 (sh4r.r[Rm] * sh4r.r[Rn]); :}
706 MULU.W Rm, Rn {:
707 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
708 (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
709 :}
710 MULS.W Rm, Rn {:
711 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
712 (uint32_t)(SIGNEXT32((int16_t)(sh4r.r[Rm])) * SIGNEXT32((int16_t)(sh4r.r[Rn])));
713 :}
714 NEGC Rm, Rn {:
715 tmp = 0 - sh4r.r[Rm];
716 sh4r.r[Rn] = tmp - sh4r.t;
717 sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
718 :}
719 NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
720 SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
721 SUBC Rm, Rn {:
722 tmp = sh4r.r[Rn];
723 sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
724 sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
725 :}
726 SUBV Rm, Rn {:
727 tmp = sh4r.r[Rn] - sh4r.r[Rm];
728 sh4r.t = ( (sh4r.r[Rn]>>31) != (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
729 sh4r.r[Rn] = tmp;
730 :}
731 BRAF Rn {:
732 CHECKSLOTILLEGAL();
733 CHECKDEST( pc + 4 + sh4r.r[Rn] );
734 sh4r.in_delay_slot = 1;
735 sh4r.pc = sh4r.new_pc;
736 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
737 return TRUE;
738 :}
739 BSRF Rn {:
740 CHECKSLOTILLEGAL();
741 CHECKDEST( pc + 4 + sh4r.r[Rn] );
742 sh4r.in_delay_slot = 1;
743 sh4r.pr = sh4r.pc + 4;
744 sh4r.pc = sh4r.new_pc;
745 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
746 TRACE_CALL( pc, sh4r.new_pc );
747 return TRUE;
748 :}
749 BT disp {:
750 CHECKSLOTILLEGAL();
751 if( sh4r.t ) {
752 CHECKDEST( sh4r.pc + disp + 4 )
753 sh4r.pc += disp + 4;
754 sh4r.new_pc = sh4r.pc + 2;
755 return TRUE;
756 }
757 :}
758 BF disp {:
759 CHECKSLOTILLEGAL();
760 if( !sh4r.t ) {
761 CHECKDEST( sh4r.pc + disp + 4 )
762 sh4r.pc += disp + 4;
763 sh4r.new_pc = sh4r.pc + 2;
764 return TRUE;
765 }
766 :}
767 BT/S disp {:
768 CHECKSLOTILLEGAL();
769 if( sh4r.t ) {
770 CHECKDEST( sh4r.pc + disp + 4 )
771 sh4r.in_delay_slot = 1;
772 sh4r.pc = sh4r.new_pc;
773 sh4r.new_pc = pc + disp + 4;
774 sh4r.in_delay_slot = 1;
775 return TRUE;
776 }
777 :}
778 BF/S disp {:
779 CHECKSLOTILLEGAL();
780 if( !sh4r.t ) {
781 CHECKDEST( sh4r.pc + disp + 4 )
782 sh4r.in_delay_slot = 1;
783 sh4r.pc = sh4r.new_pc;
784 sh4r.new_pc = pc + disp + 4;
785 return TRUE;
786 }
787 :}
788 BRA disp {:
789 CHECKSLOTILLEGAL();
790 CHECKDEST( sh4r.pc + disp + 4 );
791 sh4r.in_delay_slot = 1;
792 sh4r.pc = sh4r.new_pc;
793 sh4r.new_pc = pc + 4 + disp;
794 return TRUE;
795 :}
796 BSR disp {:
797 CHECKDEST( sh4r.pc + disp + 4 );
798 CHECKSLOTILLEGAL();
799 sh4r.in_delay_slot = 1;
800 sh4r.pr = pc + 4;
801 sh4r.pc = sh4r.new_pc;
802 sh4r.new_pc = pc + 4 + disp;
803 TRACE_CALL( pc, sh4r.new_pc );
804 return TRUE;
805 :}
806 TRAPA #imm {:
807 CHECKSLOTILLEGAL();
808 sh4r.pc += 2;
809 sh4_raise_trap( imm );
810 return TRUE;
811 :}
812 RTS {:
813 CHECKSLOTILLEGAL();
814 CHECKDEST( sh4r.pr );
815 sh4r.in_delay_slot = 1;
816 sh4r.pc = sh4r.new_pc;
817 sh4r.new_pc = sh4r.pr;
818 TRACE_RETURN( pc, sh4r.new_pc );
819 return TRUE;
820 :}
821 SLEEP {:
822 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
823 sh4r.sh4_state = SH4_STATE_STANDBY;
824 } else {
825 sh4r.sh4_state = SH4_STATE_SLEEP;
826 }
827 return FALSE; /* Halt CPU */
828 :}
829 RTE {:
830 CHECKPRIV();
831 CHECKDEST( sh4r.spc );
832 CHECKSLOTILLEGAL();
833 sh4r.in_delay_slot = 1;
834 sh4r.pc = sh4r.new_pc;
835 sh4r.new_pc = sh4r.spc;
836 sh4_write_sr( sh4r.ssr );
837 return TRUE;
838 :}
839 JMP @Rn {:
840 CHECKDEST( sh4r.r[Rn] );
841 CHECKSLOTILLEGAL();
842 sh4r.in_delay_slot = 1;
843 sh4r.pc = sh4r.new_pc;
844 sh4r.new_pc = sh4r.r[Rn];
845 return TRUE;
846 :}
847 JSR @Rn {:
848 CHECKDEST( sh4r.r[Rn] );
849 CHECKSLOTILLEGAL();
850 sh4r.in_delay_slot = 1;
851 sh4r.pc = sh4r.new_pc;
852 sh4r.new_pc = sh4r.r[Rn];
853 sh4r.pr = pc + 4;
854 TRACE_CALL( pc, sh4r.new_pc );
855 return TRUE;
856 :}
857 STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
858 STS.L MACH, @-Rn {:
859 CHECKWALIGN32( sh4r.r[Rn] );
860 MEM_WRITE_LONG( sh4r.r[Rn]-4, (sh4r.mac>>32) );
861 sh4r.r[Rn] -= 4;
862 :}
863 STC.L SR, @-Rn {:
864 CHECKPRIV();
865 CHECKWALIGN32( sh4r.r[Rn] );
866 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4_read_sr() );
867 sh4r.r[Rn] -= 4;
868 :}
869 LDS.L @Rm+, MACH {:
870 CHECKRALIGN32( sh4r.r[Rm] );
871 MEM_READ_LONG(sh4r.r[Rm], tmp);
872 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
873 (((uint64_t)tmp)<<32);
874 sh4r.r[Rm] += 4;
875 :}
876 LDC.L @Rm+, SR {:
877 CHECKSLOTILLEGAL();
878 CHECKPRIV();
879 CHECKWALIGN32( sh4r.r[Rm] );
880 MEM_READ_LONG(sh4r.r[Rm], tmp);
881 sh4_write_sr( tmp );
882 sh4r.r[Rm] +=4;
883 :}
884 LDS Rm, MACH {:
885 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
886 (((uint64_t)sh4r.r[Rm])<<32);
887 :}
888 LDC Rm, SR {:
889 CHECKSLOTILLEGAL();
890 CHECKPRIV();
891 sh4_write_sr( sh4r.r[Rm] );
892 :}
893 LDC Rm, SGR {:
894 CHECKPRIV();
895 sh4r.sgr = sh4r.r[Rm];
896 :}
897 LDC.L @Rm+, SGR {:
898 CHECKPRIV();
899 CHECKRALIGN32( sh4r.r[Rm] );
900 MEM_READ_LONG(sh4r.r[Rm], sh4r.sgr);
901 sh4r.r[Rm] +=4;
902 :}
903 STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
904 STS.L MACL, @-Rn {:
905 CHECKWALIGN32( sh4r.r[Rn] );
906 MEM_WRITE_LONG( sh4r.r[Rn]-4, (uint32_t)sh4r.mac );
907 sh4r.r[Rn] -= 4;
908 :}
909 STC.L GBR, @-Rn {:
910 CHECKWALIGN32( sh4r.r[Rn] );
911 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.gbr );
912 sh4r.r[Rn] -= 4;
913 :}
914 LDS.L @Rm+, MACL {:
915 CHECKRALIGN32( sh4r.r[Rm] );
916 MEM_READ_LONG(sh4r.r[Rm], tmp);
917 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
918 (uint64_t)((uint32_t)tmp);
919 sh4r.r[Rm] += 4;
920 :}
921 LDC.L @Rm+, GBR {:
922 CHECKRALIGN32( sh4r.r[Rm] );
923 MEM_READ_LONG(sh4r.r[Rm], sh4r.gbr);
924 sh4r.r[Rm] +=4;
925 :}
926 LDS Rm, MACL {:
927 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
928 (uint64_t)((uint32_t)(sh4r.r[Rm]));
929 :}
930 LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
931 STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
932 STS.L PR, @-Rn {:
933 CHECKWALIGN32( sh4r.r[Rn] );
934 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.pr );
935 sh4r.r[Rn] -= 4;
936 :}
937 STC.L VBR, @-Rn {:
938 CHECKPRIV();
939 CHECKWALIGN32( sh4r.r[Rn] );
940 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.vbr );
941 sh4r.r[Rn] -= 4;
942 :}
943 LDS.L @Rm+, PR {:
944 CHECKRALIGN32( sh4r.r[Rm] );
945 MEM_READ_LONG( sh4r.r[Rm], sh4r.pr );
946 sh4r.r[Rm] += 4;
947 :}
948 LDC.L @Rm+, VBR {:
949 CHECKPRIV();
950 CHECKRALIGN32( sh4r.r[Rm] );
951 MEM_READ_LONG(sh4r.r[Rm], sh4r.vbr);
952 sh4r.r[Rm] +=4;
953 :}
954 LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
955 LDC Rm, VBR {:
956 CHECKPRIV();
957 sh4r.vbr = sh4r.r[Rm];
958 :}
959 STC SGR, Rn {:
960 CHECKPRIV();
961 sh4r.r[Rn] = sh4r.sgr;
962 :}
963 STC.L SGR, @-Rn {:
964 CHECKPRIV();
965 CHECKWALIGN32( sh4r.r[Rn] );
966 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.sgr );
967 sh4r.r[Rn] -= 4;
968 :}
969 STC.L SSR, @-Rn {:
970 CHECKPRIV();
971 CHECKWALIGN32( sh4r.r[Rn] );
972 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.ssr );
973 sh4r.r[Rn] -= 4;
974 :}
975 LDC.L @Rm+, SSR {:
976 CHECKPRIV();
977 CHECKRALIGN32( sh4r.r[Rm] );
978 MEM_READ_LONG(sh4r.r[Rm], sh4r.ssr);
979 sh4r.r[Rm] +=4;
980 :}
981 LDC Rm, SSR {:
982 CHECKPRIV();
983 sh4r.ssr = sh4r.r[Rm];
984 :}
985 STC.L SPC, @-Rn {:
986 CHECKPRIV();
987 CHECKWALIGN32( sh4r.r[Rn] );
988 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.spc );
989 sh4r.r[Rn] -= 4;
990 :}
991 LDC.L @Rm+, SPC {:
992 CHECKPRIV();
993 CHECKRALIGN32( sh4r.r[Rm] );
994 MEM_READ_LONG(sh4r.r[Rm], sh4r.spc);
995 sh4r.r[Rm] +=4;
996 :}
997 LDC Rm, SPC {:
998 CHECKPRIV();
999 sh4r.spc = sh4r.r[Rm];
1000 :}
1001 STS FPUL, Rn {:
1002 CHECKFPUEN();
1003 sh4r.r[Rn] = FPULi;
1004 :}
1005 STS.L FPUL, @-Rn {:
1006 CHECKFPUEN();
1007 CHECKWALIGN32( sh4r.r[Rn] );
1008 MEM_WRITE_LONG( sh4r.r[Rn]-4, FPULi );
1009 sh4r.r[Rn] -= 4;
1010 :}
1011 LDS.L @Rm+, FPUL {:
1012 CHECKFPUEN();
1013 CHECKRALIGN32( sh4r.r[Rm] );
1014 MEM_READ_LONG(sh4r.r[Rm], FPULi);
1015 sh4r.r[Rm] +=4;
1016 :}
1017 LDS Rm, FPUL {:
1018 CHECKFPUEN();
1019 FPULi = sh4r.r[Rm];
1020 :}
1021 STS FPSCR, Rn {:
1022 CHECKFPUEN();
1023 sh4r.r[Rn] = sh4r.fpscr;
1024 :}
1025 STS.L FPSCR, @-Rn {:
1026 CHECKFPUEN();
1027 CHECKWALIGN32( sh4r.r[Rn] );
1028 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.fpscr );
1029 sh4r.r[Rn] -= 4;
1030 :}
1031 LDS.L @Rm+, FPSCR {:
1032 CHECKFPUEN();
1033 CHECKRALIGN32( sh4r.r[Rm] );
1034 MEM_READ_LONG(sh4r.r[Rm], tmp);
1035 sh4r.r[Rm] +=4;
1036 sh4_write_fpscr( tmp );
1037 :}
1038 LDS Rm, FPSCR {:
1039 CHECKFPUEN();
1040 sh4_write_fpscr( sh4r.r[Rm] );
1041 :}
1042 STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
1043 STC.L DBR, @-Rn {:
1044 CHECKPRIV();
1045 CHECKWALIGN32( sh4r.r[Rn] );
1046 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.dbr );
1047 sh4r.r[Rn] -= 4;
1048 :}
1049 LDC.L @Rm+, DBR {:
1050 CHECKPRIV();
1051 CHECKRALIGN32( sh4r.r[Rm] );
1052 MEM_READ_LONG(sh4r.r[Rm], sh4r.dbr);
1053 sh4r.r[Rm] +=4;
1054 :}
1055 LDC Rm, DBR {:
1056 CHECKPRIV();
1057 sh4r.dbr = sh4r.r[Rm];
1058 :}
1059 STC.L Rm_BANK, @-Rn {:
1060 CHECKPRIV();
1061 CHECKWALIGN32( sh4r.r[Rn] );
1062 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r_bank[Rm_BANK] );
1063 sh4r.r[Rn] -= 4;
1064 :}
1065 LDC.L @Rm+, Rn_BANK {:
1066 CHECKPRIV();
1067 CHECKRALIGN32( sh4r.r[Rm] );
1068 MEM_READ_LONG( sh4r.r[Rm], sh4r.r_bank[Rn_BANK] );
1069 sh4r.r[Rm] += 4;
1070 :}
1071 LDC Rm, Rn_BANK {:
1072 CHECKPRIV();
1073 sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
1074 :}
1075 STC SR, Rn {:
1076 CHECKPRIV();
1077 sh4r.r[Rn] = sh4_read_sr();
1078 :}
1079 STC GBR, Rn {:
1080 sh4r.r[Rn] = sh4r.gbr;
1081 :}
1082 STC VBR, Rn {:
1083 CHECKPRIV();
1084 sh4r.r[Rn] = sh4r.vbr;
1085 :}
1086 STC SSR, Rn {:
1087 CHECKPRIV();
1088 sh4r.r[Rn] = sh4r.ssr;
1089 :}
1090 STC SPC, Rn {:
1091 CHECKPRIV();
1092 sh4r.r[Rn] = sh4r.spc;
1093 :}
1094 STC Rm_BANK, Rn {:
1095 CHECKPRIV();
1096 sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
1097 :}
1099 FADD FRm, FRn {:
1100 CHECKFPUEN();
1101 if( IS_FPU_DOUBLEPREC() ) {
1102 DR(FRn) += DR(FRm);
1103 } else {
1104 FR(FRn) += FR(FRm);
1105 }
1106 :}
1107 FSUB FRm, FRn {:
1108 CHECKFPUEN();
1109 if( IS_FPU_DOUBLEPREC() ) {
1110 DR(FRn) -= DR(FRm);
1111 } else {
1112 FR(FRn) -= FR(FRm);
1113 }
1114 :}
1116 FMUL FRm, FRn {:
1117 CHECKFPUEN();
1118 if( IS_FPU_DOUBLEPREC() ) {
1119 DR(FRn) *= DR(FRm);
1120 } else {
1121 FR(FRn) *= FR(FRm);
1122 }
1123 :}
1125 FDIV FRm, FRn {:
1126 CHECKFPUEN();
1127 if( IS_FPU_DOUBLEPREC() ) {
1128 DR(FRn) /= DR(FRm);
1129 } else {
1130 FR(FRn) /= FR(FRm);
1131 }
1132 :}
1134 FCMP/EQ FRm, FRn {:
1135 CHECKFPUEN();
1136 if( IS_FPU_DOUBLEPREC() ) {
1137 sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
1138 } else {
1139 sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
1140 }
1141 :}
1143 FCMP/GT FRm, FRn {:
1144 CHECKFPUEN();
1145 if( IS_FPU_DOUBLEPREC() ) {
1146 sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
1147 } else {
1148 sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
1149 }
1150 :}
1152 FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
1153 FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
1154 FLOAT FPUL, FRn {:
1155 CHECKFPUEN();
1156 if( IS_FPU_DOUBLEPREC() ) {
1157 if( FRn&1 ) { // No, really...
1158 dtmp = (double)FPULi;
1159 FR(FRn) = *(((float *)&dtmp)+1);
1160 } else {
1161 DRF(FRn>>1) = (double)FPULi;
1162 }
1163 } else {
1164 FR(FRn) = (float)FPULi;
1165 }
1166 :}
1167 FTRC FRm, FPUL {:
1168 CHECKFPUEN();
1169 if( IS_FPU_DOUBLEPREC() ) {
1170 if( FRm&1 ) {
1171 dtmp = 0;
1172 *(((float *)&dtmp)+1) = FR(FRm);
1173 } else {
1174 dtmp = DRF(FRm>>1);
1175 }
1176 if( dtmp >= MAX_INTF )
1177 FPULi = MAX_INT;
1178 else if( dtmp <= MIN_INTF )
1179 FPULi = MIN_INT;
1180 else
1181 FPULi = (int32_t)dtmp;
1182 } else {
1183 ftmp = FR(FRm);
1184 if( ftmp >= MAX_INTF )
1185 FPULi = MAX_INT;
1186 else if( ftmp <= MIN_INTF )
1187 FPULi = MIN_INT;
1188 else
1189 FPULi = (int32_t)ftmp;
1190 }
1191 :}
1192 FNEG FRn {:
1193 CHECKFPUEN();
1194 if( IS_FPU_DOUBLEPREC() ) {
1195 DR(FRn) = -DR(FRn);
1196 } else {
1197 FR(FRn) = -FR(FRn);
1198 }
1199 :}
1200 FABS FRn {:
1201 CHECKFPUEN();
1202 if( IS_FPU_DOUBLEPREC() ) {
1203 DR(FRn) = fabs(DR(FRn));
1204 } else {
1205 FR(FRn) = fabsf(FR(FRn));
1206 }
1207 :}
1208 FSQRT FRn {:
1209 CHECKFPUEN();
1210 if( IS_FPU_DOUBLEPREC() ) {
1211 DR(FRn) = sqrt(DR(FRn));
1212 } else {
1213 FR(FRn) = sqrtf(FR(FRn));
1214 }
1215 :}
1216 FLDI0 FRn {:
1217 CHECKFPUEN();
1218 if( IS_FPU_DOUBLEPREC() ) {
1219 DR(FRn) = 0.0;
1220 } else {
1221 FR(FRn) = 0.0;
1222 }
1223 :}
1224 FLDI1 FRn {:
1225 CHECKFPUEN();
1226 if( IS_FPU_DOUBLEPREC() ) {
1227 DR(FRn) = 1.0;
1228 } else {
1229 FR(FRn) = 1.0;
1230 }
1231 :}
1232 FMAC FR0, FRm, FRn {:
1233 CHECKFPUEN();
1234 if( IS_FPU_DOUBLEPREC() ) {
1235 DR(FRn) += DR(FRm)*DR(0);
1236 } else {
1237 FR(FRn) += (double)FR(FRm)*(double)FR(0);
1238 }
1239 :}
1240 FRCHG {:
1241 CHECKFPUEN();
1242 sh4r.fpscr ^= FPSCR_FR;
1243 sh4_switch_fr_banks();
1244 :}
1245 FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
1246 FCNVSD FPUL, FRn {:
1247 CHECKFPUEN();
1248 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1249 DR(FRn) = (double)FPULf;
1250 }
1251 :}
1252 FCNVDS FRm, FPUL {:
1253 CHECKFPUEN();
1254 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1255 FPULf = (float)DR(FRm);
1256 }
1257 :}
1259 FSRRA FRn {:
1260 CHECKFPUEN();
1261 if( !IS_FPU_DOUBLEPREC() ) {
1262 FR(FRn) = 1.0/sqrt(FR(FRn));
1263 }
1264 :}
1265 FIPR FVm, FVn {:
1266 CHECKFPUEN();
1267 if( !IS_FPU_DOUBLEPREC() ) {
1268 int tmp2 = FVn<<2;
1269 tmp = FVm<<2;
1270 FR(tmp2+3) = FR(tmp)*FR(tmp2) +
1271 FR(tmp+1)*FR(tmp2+1) +
1272 FR(tmp+2)*FR(tmp2+2) +
1273 FR(tmp+3)*FR(tmp2+3);
1274 }
1275 :}
1276 FSCA FPUL, FRn {:
1277 CHECKFPUEN();
1278 if( !IS_FPU_DOUBLEPREC() ) {
1279 sh4_fsca( FPULi, (float *)&(DRF(FRn>>1)) );
1280 }
1281 :}
1282 FTRV XMTRX, FVn {:
1283 CHECKFPUEN();
1284 if( !IS_FPU_DOUBLEPREC() ) {
1285 sh4_ftrv((float *)&(DRF(FVn<<1)) );
1286 }
1287 :}
1288 UNDEF {:
1289 UNDEF(ir);
1290 :}
1291 %%
1292 sh4r.pc = sh4r.new_pc;
1293 sh4r.new_pc += 2;
1295 sh4r.in_delay_slot = 0;
1296 return TRUE;
1297 }
.