filename | src/sh4/sh4core.in |
changeset | 927:17b6b9e245d8 |
prev | 758:99ae000d4e09 |
next | 939:6f2302afeb89 |
next | 953:f4a156508ad1 |
author | nkeynes |
date | Sat Dec 27 02:59:35 2008 +0000 (15 years ago) |
branch | lxdream-mem |
permissions | -rw-r--r-- |
last change | Replace fpscr_mask/fpscr flags in xlat_cache_block with a single xlat_sh4_mode, which tracks the field of the same name in sh4r - actually a little faster this way. Now depends on SR.MD, FPSCR.PR and FPSCR.SZ (although it doesn't benefit from the SR flag yet). Also fixed the failure to check the flags in the common case (code address returned by previous block) which took away the performance benefits, but oh well. |
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/intc.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 if( sh4r.event_types & PENDING_EVENT ) {
51 event_execute();
52 }
53 /* Eventq execute may (quite likely) deliver an immediate IRQ */
54 if( sh4r.event_types & PENDING_IRQ ) {
55 sh4_accept_interrupt();
56 }
57 }
58 if( !sh4_execute_instruction() ) {
59 break;
60 }
61 }
62 } else {
63 for( ;sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
64 if( SH4_EVENT_PENDING() ) {
65 if( sh4r.event_types & PENDING_EVENT ) {
66 event_execute();
67 }
68 /* Eventq execute may (quite likely) deliver an immediate IRQ */
69 if( sh4r.event_types & PENDING_IRQ ) {
70 sh4_accept_interrupt();
71 }
72 }
74 if( !sh4_execute_instruction() )
75 break;
76 #ifdef ENABLE_DEBUG_MODE
77 for( i=0; i<sh4_breakpoint_count; i++ ) {
78 if( sh4_breakpoints[i].address == sh4r.pc ) {
79 break;
80 }
81 }
82 if( i != sh4_breakpoint_count ) {
83 sh4_core_exit( CORE_EXIT_BREAKPOINT );
84 }
85 #endif
86 }
87 }
89 /* If we aborted early, but the cpu is still technically running,
90 * we're doing a hard abort - cut the timeslice back to what we
91 * actually executed
92 */
93 if( sh4r.slice_cycle != nanosecs && sh4r.sh4_state == SH4_STATE_RUNNING ) {
94 nanosecs = sh4r.slice_cycle;
95 }
96 if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
97 TMU_run_slice( nanosecs );
98 SCIF_run_slice( nanosecs );
99 }
100 return nanosecs;
101 }
103 /********************** SH4 emulation core ****************************/
105 #define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
106 #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)
108 #if(SH4_CALLTRACE == 1)
109 #define MAX_CALLSTACK 32
110 static struct call_stack {
111 sh4addr_t call_addr;
112 sh4addr_t target_addr;
113 sh4addr_t stack_pointer;
114 } call_stack[MAX_CALLSTACK];
116 static int call_stack_depth = 0;
117 int sh4_call_trace_on = 0;
119 static inline void trace_call( sh4addr_t source, sh4addr_t dest )
120 {
121 if( call_stack_depth < MAX_CALLSTACK ) {
122 call_stack[call_stack_depth].call_addr = source;
123 call_stack[call_stack_depth].target_addr = dest;
124 call_stack[call_stack_depth].stack_pointer = sh4r.r[15];
125 }
126 call_stack_depth++;
127 }
129 static inline void trace_return( sh4addr_t source, sh4addr_t dest )
130 {
131 if( call_stack_depth > 0 ) {
132 call_stack_depth--;
133 }
134 }
136 void fprint_stack_trace( FILE *f )
137 {
138 int i = call_stack_depth -1;
139 if( i >= MAX_CALLSTACK )
140 i = MAX_CALLSTACK - 1;
141 for( ; i >= 0; i-- ) {
142 fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n",
143 (call_stack_depth - i), call_stack[i].call_addr,
144 call_stack[i].target_addr, call_stack[i].stack_pointer );
145 }
146 }
148 #define TRACE_CALL( source, dest ) trace_call(source, dest)
149 #define TRACE_RETURN( source, dest ) trace_return(source, dest)
150 #else
151 #define TRACE_CALL( dest, rts )
152 #define TRACE_RETURN( source, dest )
153 #endif
155 #define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL )
156 #define CHECKRALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
157 #define CHECKRALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
158 #define CHECKRALIGN64(addr) if( (addr)&0x07 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
159 #define CHECKWALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
160 #define CHECKWALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
161 #define CHECKWALIGN64(addr) if( (addr)&0x07 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
163 #define CHECKFPUEN() if( !IS_FPU_ENABLED() ) { if( ir == 0xFFFD ) { UNDEF(ir); } else { return sh4_raise_slot_exception( EXC_FPU_DISABLED, EXC_SLOT_FPU_DISABLED ); } }
164 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }
165 #define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) return sh4_raise_exception(EXC_SLOT_ILLEGAL)
167 #ifdef HAVE_FRAME_ADDRESS
168 static FASTCALL __attribute__((noinline)) void *__first_arg(void *a, void *b) { return a; }
169 #define INIT_EXCEPTIONS(label) goto *__first_arg(&&fnstart,&&label); fnstart:
170 #define MMU_TRANSLATE_READ( addr ) memtmp = mmu_vma_to_phys_read(addr, &&except )
171 #define MMU_TRANSLATE_WRITE( addr ) memtmp = mmu_vma_to_phys_write(addr, &&except )
172 #else
173 #define INIT_EXCEPTIONS(label)
174 #define MMU_TRANSLATE_READ( addr ) if( (memtmp = mmu_vma_to_phys_read(addr)) == MMU_VMA_ERROR ) { return TRUE; }
175 #define MMU_TRANSLATE_WRITE( addr ) if( (memtmp = mmu_vma_to_phys_write(addr)) == MMU_VMA_ERROR ) { return TRUE; }
176 #endif
178 #define MEM_READ_BYTE( addr, val ) MMU_TRANSLATE_READ(addr); val = sh4_read_byte(memtmp)
179 #define MEM_READ_WORD( addr, val ) MMU_TRANSLATE_READ(addr); val = sh4_read_word(memtmp)
180 #define MEM_READ_LONG( addr, val ) MMU_TRANSLATE_READ(addr); val = sh4_read_long(memtmp)
181 #define MEM_WRITE_BYTE( addr, val ) MMU_TRANSLATE_WRITE(addr); sh4_write_byte(memtmp, val)
182 #define MEM_WRITE_WORD( addr, val ) MMU_TRANSLATE_WRITE(addr); sh4_write_word(memtmp, val)
183 #define MEM_WRITE_LONG( addr, val ) MMU_TRANSLATE_WRITE(addr); sh4_write_long(memtmp, val)
186 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
188 #define MEM_FP_READ( addr, reg ) \
189 if( IS_FPU_DOUBLESIZE() ) { \
190 CHECKRALIGN64(addr); \
191 MMU_TRANSLATE_READ(addr); \
192 if( reg & 1 ) { \
193 *((uint32_t *)&XF((reg) & 0x0E)) = sh4_read_long(memtmp); \
194 *((uint32_t *)&XF(reg)) = sh4_read_long(memtmp+4); \
195 } else { \
196 *((uint32_t *)&FR(reg)) = sh4_read_long(memtmp); \
197 *((uint32_t *)&FR((reg) | 0x01)) = sh4_read_long(memtmp+4); \
198 } \
199 } else { \
200 CHECKRALIGN32(addr); \
201 MMU_TRANSLATE_READ(addr); \
202 *((uint32_t *)&FR(reg)) = sh4_read_long(memtmp); \
203 }
204 #define MEM_FP_WRITE( addr, reg ) \
205 if( IS_FPU_DOUBLESIZE() ) { \
206 CHECKWALIGN64(addr); \
207 MMU_TRANSLATE_WRITE(addr); \
208 if( reg & 1 ) { \
209 sh4_write_long( memtmp, *((uint32_t *)&XF((reg)&0x0E)) ); \
210 sh4_write_long( memtmp+4, *((uint32_t *)&XF(reg)) ); \
211 } else { \
212 sh4_write_long( memtmp, *((uint32_t *)&FR(reg)) ); \
213 sh4_write_long( memtmp+4, *((uint32_t *)&FR((reg)|0x01)) ); \
214 } \
215 } else { \
216 CHECKWALIGN32(addr); \
217 MMU_TRANSLATE_WRITE(addr); \
218 sh4_write_long( memtmp, *((uint32_t *)&FR((reg))) ); \
219 }
221 gboolean sh4_execute_instruction( void )
222 {
223 uint32_t pc;
224 unsigned short ir;
225 uint32_t tmp;
226 float ftmp;
227 double dtmp;
228 int64_t memtmp; // temporary holder for memory reads
230 INIT_EXCEPTIONS(except)
232 #define R0 sh4r.r[0]
233 pc = sh4r.pc;
234 if( pc > 0xFFFFFF00 ) {
235 /* SYSCALL Magic */
236 syscall_invoke( pc );
237 sh4r.in_delay_slot = 0;
238 pc = sh4r.pc = sh4r.pr;
239 sh4r.new_pc = sh4r.pc + 2;
240 return TRUE;
241 }
242 CHECKRALIGN16(pc);
244 #ifdef ENABLE_SH4STATS
245 sh4_stats_add_by_pc(sh4r.pc);
246 #endif
248 /* Read instruction */
249 if( !IS_IN_ICACHE(pc) ) {
250 if( !mmu_update_icache(pc) ) {
251 // Fault - look for the fault handler
252 if( !mmu_update_icache(sh4r.pc) ) {
253 // double fault - halt
254 ERROR( "Double fault - halting" );
255 sh4_core_exit(CORE_EXIT_HALT);
256 return FALSE;
257 }
258 }
259 pc = sh4r.pc;
260 }
261 assert( IS_IN_ICACHE(pc) );
262 ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
263 %%
264 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
265 AND #imm, R0 {: R0 &= imm; :}
266 AND.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & tmp ); :}
267 NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}
268 OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}
269 OR #imm, R0 {: R0 |= imm; :}
270 OR.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | tmp ); :}
271 TAS.B @Rn {:
272 MEM_READ_BYTE( sh4r.r[Rn], tmp );
273 sh4r.t = ( tmp == 0 ? 1 : 0 );
274 MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );
275 :}
276 TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}
277 TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}
278 TST.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); sh4r.t = ( tmp & imm ? 0 : 1 ); :}
279 XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}
280 XOR #imm, R0 {: R0 ^= imm; :}
281 XOR.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ tmp ); :}
282 XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}
284 ROTL Rn {:
285 sh4r.t = sh4r.r[Rn] >> 31;
286 sh4r.r[Rn] <<= 1;
287 sh4r.r[Rn] |= sh4r.t;
288 :}
289 ROTR Rn {:
290 sh4r.t = sh4r.r[Rn] & 0x00000001;
291 sh4r.r[Rn] >>= 1;
292 sh4r.r[Rn] |= (sh4r.t << 31);
293 :}
294 ROTCL Rn {:
295 tmp = sh4r.r[Rn] >> 31;
296 sh4r.r[Rn] <<= 1;
297 sh4r.r[Rn] |= sh4r.t;
298 sh4r.t = tmp;
299 :}
300 ROTCR Rn {:
301 tmp = sh4r.r[Rn] & 0x00000001;
302 sh4r.r[Rn] >>= 1;
303 sh4r.r[Rn] |= (sh4r.t << 31 );
304 sh4r.t = tmp;
305 :}
306 SHAD Rm, Rn {:
307 tmp = sh4r.r[Rm];
308 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
309 else if( (tmp & 0x1F) == 0 )
310 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;
311 else
312 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);
313 :}
314 SHLD Rm, Rn {:
315 tmp = sh4r.r[Rm];
316 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
317 else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;
318 else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);
319 :}
320 SHAL Rn {:
321 sh4r.t = sh4r.r[Rn] >> 31;
322 sh4r.r[Rn] <<= 1;
323 :}
324 SHAR Rn {:
325 sh4r.t = sh4r.r[Rn] & 0x00000001;
326 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;
327 :}
328 SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}
329 SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}
330 SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}
331 SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}
332 SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}
333 SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}
334 SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}
335 SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}
337 EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}
338 EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}
339 EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}
340 EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}
341 SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}
342 SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}
344 CLRT {: sh4r.t = 0; :}
345 SETT {: sh4r.t = 1; :}
346 CLRMAC {: sh4r.mac = 0; :}
347 LDTLB {: MMU_ldtlb(); :}
348 CLRS {: sh4r.s = 0; :}
349 SETS {: sh4r.s = 1; :}
350 MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}
351 NOP {: /* NOP */ :}
353 PREF @Rn {:
354 tmp = sh4r.r[Rn];
355 if( (tmp & 0xFC000000) == 0xE0000000 ) {
356 sh4_flush_store_queue(tmp);
357 }
358 :}
359 OCBI @Rn {: :}
360 OCBP @Rn {: :}
361 OCBWB @Rn {: :}
362 MOVCA.L R0, @Rn {:
363 tmp = sh4r.r[Rn];
364 CHECKWALIGN32(tmp);
365 MEM_WRITE_LONG( tmp, R0 );
366 :}
367 MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}
368 MOV.W Rm, @(R0, Rn) {:
369 CHECKWALIGN16( R0 + sh4r.r[Rn] );
370 MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );
371 :}
372 MOV.L Rm, @(R0, Rn) {:
373 CHECKWALIGN32( R0 + sh4r.r[Rn] );
374 MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );
375 :}
376 MOV.B @(R0, Rm), Rn {: MEM_READ_BYTE( R0 + sh4r.r[Rm], sh4r.r[Rn] ); :}
377 MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );
378 MEM_READ_WORD( R0 + sh4r.r[Rm], sh4r.r[Rn] );
379 :}
380 MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );
381 MEM_READ_LONG( R0 + sh4r.r[Rm], sh4r.r[Rn] );
382 :}
383 MOV.L Rm, @(disp, Rn) {:
384 tmp = sh4r.r[Rn] + disp;
385 CHECKWALIGN32( tmp );
386 MEM_WRITE_LONG( tmp, sh4r.r[Rm] );
387 :}
388 MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
389 MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
390 MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
391 MOV.B Rm, @-Rn {: MEM_WRITE_BYTE( sh4r.r[Rn]-1, sh4r.r[Rm] ); sh4r.r[Rn]--; :}
392 MOV.W Rm, @-Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn]-2, sh4r.r[Rm] ); sh4r.r[Rn] -= 2; :}
393 MOV.L Rm, @-Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r[Rm] ); sh4r.r[Rn] -= 4; :}
394 MOV.L @(disp, Rm), Rn {:
395 tmp = sh4r.r[Rm] + disp;
396 CHECKRALIGN32( tmp );
397 MEM_READ_LONG( tmp, sh4r.r[Rn] );
398 :}
399 MOV.B @Rm, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); :}
400 MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); :}
401 MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); :}
402 MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}
403 MOV.B @Rm+, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); sh4r.r[Rm] ++; :}
404 MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); sh4r.r[Rm] += 2; :}
405 MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); sh4r.r[Rm] += 4; :}
406 MOV.L @(disp, PC), Rn {:
407 CHECKSLOTILLEGAL();
408 tmp = (pc&0xFFFFFFFC) + disp + 4;
409 MEM_READ_LONG( tmp, sh4r.r[Rn] );
410 :}
411 MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}
412 MOV.W R0, @(disp, GBR) {:
413 tmp = sh4r.gbr + disp;
414 CHECKWALIGN16( tmp );
415 MEM_WRITE_WORD( tmp, R0 );
416 :}
417 MOV.L R0, @(disp, GBR) {:
418 tmp = sh4r.gbr + disp;
419 CHECKWALIGN32( tmp );
420 MEM_WRITE_LONG( tmp, R0 );
421 :}
422 MOV.B @(disp, GBR), R0 {: MEM_READ_BYTE( sh4r.gbr + disp, R0 ); :}
423 MOV.W @(disp, GBR), R0 {:
424 tmp = sh4r.gbr + disp;
425 CHECKRALIGN16( tmp );
426 MEM_READ_WORD( tmp, R0 );
427 :}
428 MOV.L @(disp, GBR), R0 {:
429 tmp = sh4r.gbr + disp;
430 CHECKRALIGN32( tmp );
431 MEM_READ_LONG( tmp, R0 );
432 :}
433 MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}
434 MOV.W R0, @(disp, Rn) {:
435 tmp = sh4r.r[Rn] + disp;
436 CHECKWALIGN16( tmp );
437 MEM_WRITE_WORD( tmp, R0 );
438 :}
439 MOV.B @(disp, Rm), R0 {: MEM_READ_BYTE( sh4r.r[Rm] + disp, R0 ); :}
440 MOV.W @(disp, Rm), R0 {:
441 tmp = sh4r.r[Rm] + disp;
442 CHECKRALIGN16( tmp );
443 MEM_READ_WORD( tmp, R0 );
444 :}
445 MOV.W @(disp, PC), Rn {:
446 CHECKSLOTILLEGAL();
447 tmp = pc + 4 + disp;
448 MEM_READ_WORD( tmp, sh4r.r[Rn] );
449 :}
450 MOVA @(disp, PC), R0 {:
451 CHECKSLOTILLEGAL();
452 R0 = (pc&0xFFFFFFFC) + disp + 4;
453 :}
454 MOV #imm, Rn {: sh4r.r[Rn] = imm; :}
456 FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
457 FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
458 FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
459 FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
460 FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
461 FMOV FRm, @-Rn {: MEM_FP_WRITE( sh4r.r[Rn] - FP_WIDTH, FRm ); sh4r.r[Rn] -= FP_WIDTH; :}
462 FMOV FRm, FRn {:
463 if( IS_FPU_DOUBLESIZE() )
464 DR(FRn) = DR(FRm);
465 else
466 FR(FRn) = FR(FRm);
467 :}
469 CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}
470 CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}
471 CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
472 CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
473 CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}
474 CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}
475 CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}
476 CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}
477 CMP/STR Rm, Rn {:
478 /* set T = 1 if any byte in RM & RN is the same */
479 tmp = sh4r.r[Rm] ^ sh4r.r[Rn];
480 sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
481 (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
482 :}
484 ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}
485 ADD #imm, Rn {: sh4r.r[Rn] += imm; :}
486 ADDC Rm, Rn {:
487 tmp = sh4r.r[Rn];
488 sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;
489 sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );
490 :}
491 ADDV Rm, Rn {:
492 tmp = sh4r.r[Rn] + sh4r.r[Rm];
493 sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
494 sh4r.r[Rn] = tmp;
495 :}
496 DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}
497 DIV0S Rm, Rn {:
498 sh4r.q = sh4r.r[Rn]>>31;
499 sh4r.m = sh4r.r[Rm]>>31;
500 sh4r.t = sh4r.q ^ sh4r.m;
501 :}
502 DIV1 Rm, Rn {:
503 /* This is derived from the sh4 manual with some simplifications */
504 uint32_t tmp0, tmp1, tmp2, dir;
506 dir = sh4r.q ^ sh4r.m;
507 sh4r.q = (sh4r.r[Rn] >> 31);
508 tmp2 = sh4r.r[Rm];
509 sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
510 tmp0 = sh4r.r[Rn];
511 if( dir ) {
512 sh4r.r[Rn] += tmp2;
513 tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
514 } else {
515 sh4r.r[Rn] -= tmp2;
516 tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
517 }
518 sh4r.q ^= sh4r.m ^ tmp1;
519 sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
520 :}
521 DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
522 DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
523 DT Rn {:
524 sh4r.r[Rn] --;
525 sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
526 :}
527 MAC.W @Rm+, @Rn+ {:
528 int32_t stmp;
529 if( Rm == Rn ) {
530 CHECKRALIGN16(sh4r.r[Rn]);
531 MEM_READ_WORD( sh4r.r[Rn], tmp );
532 stmp = SIGNEXT16(tmp);
533 MEM_READ_WORD( sh4r.r[Rn]+2, tmp );
534 stmp *= SIGNEXT16(tmp);
535 sh4r.r[Rn] += 4;
536 } else {
537 CHECKRALIGN16( sh4r.r[Rn] );
538 CHECKRALIGN16( sh4r.r[Rm] );
539 MEM_READ_WORD(sh4r.r[Rn], tmp);
540 stmp = SIGNEXT16(tmp);
541 MEM_READ_WORD(sh4r.r[Rm], tmp);
542 stmp = stmp * SIGNEXT16(tmp);
543 sh4r.r[Rn] += 2;
544 sh4r.r[Rm] += 2;
545 }
546 if( sh4r.s ) {
547 int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
548 if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
549 sh4r.mac = 0x000000017FFFFFFFLL;
550 } else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
551 sh4r.mac = 0x0000000180000000LL;
552 } else {
553 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
554 ((uint32_t)(sh4r.mac + stmp));
555 }
556 } else {
557 sh4r.mac += SIGNEXT32(stmp);
558 }
559 :}
560 MAC.L @Rm+, @Rn+ {:
561 int64_t tmpl;
562 if( Rm == Rn ) {
563 CHECKRALIGN32( sh4r.r[Rn] );
564 MEM_READ_LONG(sh4r.r[Rn], tmp);
565 tmpl = SIGNEXT32(tmp);
566 MEM_READ_LONG(sh4r.r[Rn]+4, tmp);
567 tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
568 sh4r.r[Rn] += 8;
569 } else {
570 CHECKRALIGN32( sh4r.r[Rm] );
571 CHECKRALIGN32( sh4r.r[Rn] );
572 MEM_READ_LONG(sh4r.r[Rn], tmp);
573 tmpl = SIGNEXT32(tmp);
574 MEM_READ_LONG(sh4r.r[Rm], tmp);
575 tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
576 sh4r.r[Rn] += 4;
577 sh4r.r[Rm] += 4;
578 }
579 if( sh4r.s ) {
580 /* 48-bit Saturation. Yuch */
581 if( tmpl < (int64_t)0xFFFF800000000000LL )
582 tmpl = 0xFFFF800000000000LL;
583 else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
584 tmpl = 0x00007FFFFFFFFFFFLL;
585 }
586 sh4r.mac = tmpl;
587 :}
588 MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
589 (sh4r.r[Rm] * sh4r.r[Rn]); :}
590 MULU.W Rm, Rn {:
591 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
592 (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
593 :}
594 MULS.W Rm, Rn {:
595 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
596 (uint32_t)(SIGNEXT32(sh4r.r[Rm]&0xFFFF) * SIGNEXT32(sh4r.r[Rn]&0xFFFF));
597 :}
598 NEGC Rm, Rn {:
599 tmp = 0 - sh4r.r[Rm];
600 sh4r.r[Rn] = tmp - sh4r.t;
601 sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
602 :}
603 NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
604 SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
605 SUBC Rm, Rn {:
606 tmp = sh4r.r[Rn];
607 sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
608 sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
609 :}
611 BRAF Rn {:
612 CHECKSLOTILLEGAL();
613 CHECKDEST( pc + 4 + sh4r.r[Rn] );
614 sh4r.in_delay_slot = 1;
615 sh4r.pc = sh4r.new_pc;
616 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
617 return TRUE;
618 :}
619 BSRF Rn {:
620 CHECKSLOTILLEGAL();
621 CHECKDEST( pc + 4 + sh4r.r[Rn] );
622 sh4r.in_delay_slot = 1;
623 sh4r.pr = sh4r.pc + 4;
624 sh4r.pc = sh4r.new_pc;
625 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
626 TRACE_CALL( pc, sh4r.new_pc );
627 return TRUE;
628 :}
629 BT disp {:
630 CHECKSLOTILLEGAL();
631 if( sh4r.t ) {
632 CHECKDEST( sh4r.pc + disp + 4 )
633 sh4r.pc += disp + 4;
634 sh4r.new_pc = sh4r.pc + 2;
635 return TRUE;
636 }
637 :}
638 BF disp {:
639 CHECKSLOTILLEGAL();
640 if( !sh4r.t ) {
641 CHECKDEST( sh4r.pc + disp + 4 )
642 sh4r.pc += disp + 4;
643 sh4r.new_pc = sh4r.pc + 2;
644 return TRUE;
645 }
646 :}
647 BT/S disp {:
648 CHECKSLOTILLEGAL();
649 if( sh4r.t ) {
650 CHECKDEST( sh4r.pc + disp + 4 )
651 sh4r.in_delay_slot = 1;
652 sh4r.pc = sh4r.new_pc;
653 sh4r.new_pc = pc + disp + 4;
654 sh4r.in_delay_slot = 1;
655 return TRUE;
656 }
657 :}
658 BF/S disp {:
659 CHECKSLOTILLEGAL();
660 if( !sh4r.t ) {
661 CHECKDEST( sh4r.pc + disp + 4 )
662 sh4r.in_delay_slot = 1;
663 sh4r.pc = sh4r.new_pc;
664 sh4r.new_pc = pc + disp + 4;
665 return TRUE;
666 }
667 :}
668 BRA disp {:
669 CHECKSLOTILLEGAL();
670 CHECKDEST( sh4r.pc + disp + 4 );
671 sh4r.in_delay_slot = 1;
672 sh4r.pc = sh4r.new_pc;
673 sh4r.new_pc = pc + 4 + disp;
674 return TRUE;
675 :}
676 BSR disp {:
677 CHECKDEST( sh4r.pc + disp + 4 );
678 CHECKSLOTILLEGAL();
679 sh4r.in_delay_slot = 1;
680 sh4r.pr = pc + 4;
681 sh4r.pc = sh4r.new_pc;
682 sh4r.new_pc = pc + 4 + disp;
683 TRACE_CALL( pc, sh4r.new_pc );
684 return TRUE;
685 :}
686 TRAPA #imm {:
687 CHECKSLOTILLEGAL();
688 sh4r.pc += 2;
689 sh4_raise_trap( imm );
690 return TRUE;
691 :}
692 RTS {:
693 CHECKSLOTILLEGAL();
694 CHECKDEST( sh4r.pr );
695 sh4r.in_delay_slot = 1;
696 sh4r.pc = sh4r.new_pc;
697 sh4r.new_pc = sh4r.pr;
698 TRACE_RETURN( pc, sh4r.new_pc );
699 return TRUE;
700 :}
701 SLEEP {:
702 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
703 sh4r.sh4_state = SH4_STATE_STANDBY;
704 } else {
705 sh4r.sh4_state = SH4_STATE_SLEEP;
706 }
707 return FALSE; /* Halt CPU */
708 :}
709 RTE {:
710 CHECKPRIV();
711 CHECKDEST( sh4r.spc );
712 CHECKSLOTILLEGAL();
713 sh4r.in_delay_slot = 1;
714 sh4r.pc = sh4r.new_pc;
715 sh4r.new_pc = sh4r.spc;
716 sh4_write_sr( sh4r.ssr );
717 return TRUE;
718 :}
719 JMP @Rn {:
720 CHECKDEST( sh4r.r[Rn] );
721 CHECKSLOTILLEGAL();
722 sh4r.in_delay_slot = 1;
723 sh4r.pc = sh4r.new_pc;
724 sh4r.new_pc = sh4r.r[Rn];
725 return TRUE;
726 :}
727 JSR @Rn {:
728 CHECKDEST( sh4r.r[Rn] );
729 CHECKSLOTILLEGAL();
730 sh4r.in_delay_slot = 1;
731 sh4r.pc = sh4r.new_pc;
732 sh4r.new_pc = sh4r.r[Rn];
733 sh4r.pr = pc + 4;
734 TRACE_CALL( pc, sh4r.new_pc );
735 return TRUE;
736 :}
737 STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
738 STS.L MACH, @-Rn {:
739 CHECKWALIGN32( sh4r.r[Rn] );
740 MEM_WRITE_LONG( sh4r.r[Rn]-4, (sh4r.mac>>32) );
741 sh4r.r[Rn] -= 4;
742 :}
743 STC.L SR, @-Rn {:
744 CHECKPRIV();
745 CHECKWALIGN32( sh4r.r[Rn] );
746 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4_read_sr() );
747 sh4r.r[Rn] -= 4;
748 :}
749 LDS.L @Rm+, MACH {:
750 CHECKRALIGN32( sh4r.r[Rm] );
751 MEM_READ_LONG(sh4r.r[Rm], tmp);
752 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
753 (((uint64_t)tmp)<<32);
754 sh4r.r[Rm] += 4;
755 :}
756 LDC.L @Rm+, SR {:
757 CHECKSLOTILLEGAL();
758 CHECKPRIV();
759 CHECKWALIGN32( sh4r.r[Rm] );
760 MEM_READ_LONG(sh4r.r[Rm], tmp);
761 sh4_write_sr( tmp );
762 sh4r.r[Rm] +=4;
763 :}
764 LDS Rm, MACH {:
765 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
766 (((uint64_t)sh4r.r[Rm])<<32);
767 :}
768 LDC Rm, SR {:
769 CHECKSLOTILLEGAL();
770 CHECKPRIV();
771 sh4_write_sr( sh4r.r[Rm] );
772 :}
773 LDC Rm, SGR {:
774 CHECKPRIV();
775 sh4r.sgr = sh4r.r[Rm];
776 :}
777 LDC.L @Rm+, SGR {:
778 CHECKPRIV();
779 CHECKRALIGN32( sh4r.r[Rm] );
780 MEM_READ_LONG(sh4r.r[Rm], sh4r.sgr);
781 sh4r.r[Rm] +=4;
782 :}
783 STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
784 STS.L MACL, @-Rn {:
785 CHECKWALIGN32( sh4r.r[Rn] );
786 MEM_WRITE_LONG( sh4r.r[Rn]-4, (uint32_t)sh4r.mac );
787 sh4r.r[Rn] -= 4;
788 :}
789 STC.L GBR, @-Rn {:
790 CHECKWALIGN32( sh4r.r[Rn] );
791 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.gbr );
792 sh4r.r[Rn] -= 4;
793 :}
794 LDS.L @Rm+, MACL {:
795 CHECKRALIGN32( sh4r.r[Rm] );
796 MEM_READ_LONG(sh4r.r[Rm], tmp);
797 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
798 (uint64_t)((uint32_t)tmp);
799 sh4r.r[Rm] += 4;
800 :}
801 LDC.L @Rm+, GBR {:
802 CHECKRALIGN32( sh4r.r[Rm] );
803 MEM_READ_LONG(sh4r.r[Rm], sh4r.gbr);
804 sh4r.r[Rm] +=4;
805 :}
806 LDS Rm, MACL {:
807 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
808 (uint64_t)((uint32_t)(sh4r.r[Rm]));
809 :}
810 LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
811 STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
812 STS.L PR, @-Rn {:
813 CHECKWALIGN32( sh4r.r[Rn] );
814 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.pr );
815 sh4r.r[Rn] -= 4;
816 :}
817 STC.L VBR, @-Rn {:
818 CHECKPRIV();
819 CHECKWALIGN32( sh4r.r[Rn] );
820 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.vbr );
821 sh4r.r[Rn] -= 4;
822 :}
823 LDS.L @Rm+, PR {:
824 CHECKRALIGN32( sh4r.r[Rm] );
825 MEM_READ_LONG( sh4r.r[Rm], sh4r.pr );
826 sh4r.r[Rm] += 4;
827 :}
828 LDC.L @Rm+, VBR {:
829 CHECKPRIV();
830 CHECKRALIGN32( sh4r.r[Rm] );
831 MEM_READ_LONG(sh4r.r[Rm], sh4r.vbr);
832 sh4r.r[Rm] +=4;
833 :}
834 LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
835 LDC Rm, VBR {:
836 CHECKPRIV();
837 sh4r.vbr = sh4r.r[Rm];
838 :}
839 STC SGR, Rn {:
840 CHECKPRIV();
841 sh4r.r[Rn] = sh4r.sgr;
842 :}
843 STC.L SGR, @-Rn {:
844 CHECKPRIV();
845 CHECKWALIGN32( sh4r.r[Rn] );
846 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.sgr );
847 sh4r.r[Rn] -= 4;
848 :}
849 STC.L SSR, @-Rn {:
850 CHECKPRIV();
851 CHECKWALIGN32( sh4r.r[Rn] );
852 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.ssr );
853 sh4r.r[Rn] -= 4;
854 :}
855 LDC.L @Rm+, SSR {:
856 CHECKPRIV();
857 CHECKRALIGN32( sh4r.r[Rm] );
858 MEM_READ_LONG(sh4r.r[Rm], sh4r.ssr);
859 sh4r.r[Rm] +=4;
860 :}
861 LDC Rm, SSR {:
862 CHECKPRIV();
863 sh4r.ssr = sh4r.r[Rm];
864 :}
865 STC.L SPC, @-Rn {:
866 CHECKPRIV();
867 CHECKWALIGN32( sh4r.r[Rn] );
868 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.spc );
869 sh4r.r[Rn] -= 4;
870 :}
871 LDC.L @Rm+, SPC {:
872 CHECKPRIV();
873 CHECKRALIGN32( sh4r.r[Rm] );
874 MEM_READ_LONG(sh4r.r[Rm], sh4r.spc);
875 sh4r.r[Rm] +=4;
876 :}
877 LDC Rm, SPC {:
878 CHECKPRIV();
879 sh4r.spc = sh4r.r[Rm];
880 :}
881 STS FPUL, Rn {:
882 CHECKFPUEN();
883 sh4r.r[Rn] = FPULi;
884 :}
885 STS.L FPUL, @-Rn {:
886 CHECKFPUEN();
887 CHECKWALIGN32( sh4r.r[Rn] );
888 MEM_WRITE_LONG( sh4r.r[Rn]-4, FPULi );
889 sh4r.r[Rn] -= 4;
890 :}
891 LDS.L @Rm+, FPUL {:
892 CHECKFPUEN();
893 CHECKRALIGN32( sh4r.r[Rm] );
894 MEM_READ_LONG(sh4r.r[Rm], FPULi);
895 sh4r.r[Rm] +=4;
896 :}
897 LDS Rm, FPUL {:
898 CHECKFPUEN();
899 FPULi = sh4r.r[Rm];
900 :}
901 STS FPSCR, Rn {:
902 CHECKFPUEN();
903 sh4r.r[Rn] = sh4r.fpscr;
904 :}
905 STS.L FPSCR, @-Rn {:
906 CHECKFPUEN();
907 CHECKWALIGN32( sh4r.r[Rn] );
908 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.fpscr );
909 sh4r.r[Rn] -= 4;
910 :}
911 LDS.L @Rm+, FPSCR {:
912 CHECKFPUEN();
913 CHECKRALIGN32( sh4r.r[Rm] );
914 MEM_READ_LONG(sh4r.r[Rm], tmp);
915 sh4r.r[Rm] +=4;
916 sh4_write_fpscr( tmp );
917 :}
918 LDS Rm, FPSCR {:
919 CHECKFPUEN();
920 sh4_write_fpscr( sh4r.r[Rm] );
921 :}
922 STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
923 STC.L DBR, @-Rn {:
924 CHECKPRIV();
925 CHECKWALIGN32( sh4r.r[Rn] );
926 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.dbr );
927 sh4r.r[Rn] -= 4;
928 :}
929 LDC.L @Rm+, DBR {:
930 CHECKPRIV();
931 CHECKRALIGN32( sh4r.r[Rm] );
932 MEM_READ_LONG(sh4r.r[Rm], sh4r.dbr);
933 sh4r.r[Rm] +=4;
934 :}
935 LDC Rm, DBR {:
936 CHECKPRIV();
937 sh4r.dbr = sh4r.r[Rm];
938 :}
939 STC.L Rm_BANK, @-Rn {:
940 CHECKPRIV();
941 CHECKWALIGN32( sh4r.r[Rn] );
942 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r_bank[Rm_BANK] );
943 sh4r.r[Rn] -= 4;
944 :}
945 LDC.L @Rm+, Rn_BANK {:
946 CHECKPRIV();
947 CHECKRALIGN32( sh4r.r[Rm] );
948 MEM_READ_LONG( sh4r.r[Rm], sh4r.r_bank[Rn_BANK] );
949 sh4r.r[Rm] += 4;
950 :}
951 LDC Rm, Rn_BANK {:
952 CHECKPRIV();
953 sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
954 :}
955 STC SR, Rn {:
956 CHECKPRIV();
957 sh4r.r[Rn] = sh4_read_sr();
958 :}
959 STC GBR, Rn {:
960 sh4r.r[Rn] = sh4r.gbr;
961 :}
962 STC VBR, Rn {:
963 CHECKPRIV();
964 sh4r.r[Rn] = sh4r.vbr;
965 :}
966 STC SSR, Rn {:
967 CHECKPRIV();
968 sh4r.r[Rn] = sh4r.ssr;
969 :}
970 STC SPC, Rn {:
971 CHECKPRIV();
972 sh4r.r[Rn] = sh4r.spc;
973 :}
974 STC Rm_BANK, Rn {:
975 CHECKPRIV();
976 sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
977 :}
979 FADD FRm, FRn {:
980 CHECKFPUEN();
981 if( IS_FPU_DOUBLEPREC() ) {
982 DR(FRn) += DR(FRm);
983 } else {
984 FR(FRn) += FR(FRm);
985 }
986 :}
987 FSUB FRm, FRn {:
988 CHECKFPUEN();
989 if( IS_FPU_DOUBLEPREC() ) {
990 DR(FRn) -= DR(FRm);
991 } else {
992 FR(FRn) -= FR(FRm);
993 }
994 :}
996 FMUL FRm, FRn {:
997 CHECKFPUEN();
998 if( IS_FPU_DOUBLEPREC() ) {
999 DR(FRn) *= DR(FRm);
1000 } else {
1001 FR(FRn) *= FR(FRm);
1002 }
1003 :}
1005 FDIV FRm, FRn {:
1006 CHECKFPUEN();
1007 if( IS_FPU_DOUBLEPREC() ) {
1008 DR(FRn) /= DR(FRm);
1009 } else {
1010 FR(FRn) /= FR(FRm);
1011 }
1012 :}
1014 FCMP/EQ FRm, FRn {:
1015 CHECKFPUEN();
1016 if( IS_FPU_DOUBLEPREC() ) {
1017 sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
1018 } else {
1019 sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
1020 }
1021 :}
1023 FCMP/GT FRm, FRn {:
1024 CHECKFPUEN();
1025 if( IS_FPU_DOUBLEPREC() ) {
1026 sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
1027 } else {
1028 sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
1029 }
1030 :}
1032 FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
1033 FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
1034 FLOAT FPUL, FRn {:
1035 CHECKFPUEN();
1036 if( IS_FPU_DOUBLEPREC() ) {
1037 if( FRn&1 ) { // No, really...
1038 dtmp = (double)FPULi;
1039 FR(FRn) = *(((float *)&dtmp)+1);
1040 } else {
1041 DRF(FRn>>1) = (double)FPULi;
1042 }
1043 } else {
1044 FR(FRn) = (float)FPULi;
1045 }
1046 :}
1047 FTRC FRm, FPUL {:
1048 CHECKFPUEN();
1049 if( IS_FPU_DOUBLEPREC() ) {
1050 if( FRm&1 ) {
1051 dtmp = 0;
1052 *(((float *)&dtmp)+1) = FR(FRm);
1053 } else {
1054 dtmp = DRF(FRm>>1);
1055 }
1056 if( dtmp >= MAX_INTF )
1057 FPULi = MAX_INT;
1058 else if( dtmp <= MIN_INTF )
1059 FPULi = MIN_INT;
1060 else
1061 FPULi = (int32_t)dtmp;
1062 } else {
1063 ftmp = FR(FRm);
1064 if( ftmp >= MAX_INTF )
1065 FPULi = MAX_INT;
1066 else if( ftmp <= MIN_INTF )
1067 FPULi = MIN_INT;
1068 else
1069 FPULi = (int32_t)ftmp;
1070 }
1071 :}
1072 FNEG FRn {:
1073 CHECKFPUEN();
1074 if( IS_FPU_DOUBLEPREC() ) {
1075 DR(FRn) = -DR(FRn);
1076 } else {
1077 FR(FRn) = -FR(FRn);
1078 }
1079 :}
1080 FABS FRn {:
1081 CHECKFPUEN();
1082 if( IS_FPU_DOUBLEPREC() ) {
1083 DR(FRn) = fabs(DR(FRn));
1084 } else {
1085 FR(FRn) = fabsf(FR(FRn));
1086 }
1087 :}
1088 FSQRT FRn {:
1089 CHECKFPUEN();
1090 if( IS_FPU_DOUBLEPREC() ) {
1091 DR(FRn) = sqrt(DR(FRn));
1092 } else {
1093 FR(FRn) = sqrtf(FR(FRn));
1094 }
1095 :}
1096 FLDI0 FRn {:
1097 CHECKFPUEN();
1098 if( IS_FPU_DOUBLEPREC() ) {
1099 DR(FRn) = 0.0;
1100 } else {
1101 FR(FRn) = 0.0;
1102 }
1103 :}
1104 FLDI1 FRn {:
1105 CHECKFPUEN();
1106 if( IS_FPU_DOUBLEPREC() ) {
1107 DR(FRn) = 1.0;
1108 } else {
1109 FR(FRn) = 1.0;
1110 }
1111 :}
1112 FMAC FR0, FRm, FRn {:
1113 CHECKFPUEN();
1114 if( IS_FPU_DOUBLEPREC() ) {
1115 DR(FRn) += DR(FRm)*DR(0);
1116 } else {
1117 FR(FRn) += FR(FRm)*FR(0);
1118 }
1119 :}
1120 FRCHG {:
1121 CHECKFPUEN();
1122 sh4r.fpscr ^= FPSCR_FR;
1123 sh4_switch_fr_banks();
1124 :}
1125 FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
1126 FCNVSD FPUL, FRn {:
1127 CHECKFPUEN();
1128 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1129 DR(FRn) = (double)FPULf;
1130 }
1131 :}
1132 FCNVDS FRm, FPUL {:
1133 CHECKFPUEN();
1134 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1135 FPULf = (float)DR(FRm);
1136 }
1137 :}
1139 FSRRA FRn {:
1140 CHECKFPUEN();
1141 if( !IS_FPU_DOUBLEPREC() ) {
1142 FR(FRn) = 1.0/sqrtf(FR(FRn));
1143 }
1144 :}
1145 FIPR FVm, FVn {:
1146 CHECKFPUEN();
1147 if( !IS_FPU_DOUBLEPREC() ) {
1148 int tmp2 = FVn<<2;
1149 tmp = FVm<<2;
1150 FR(tmp2+3) = FR(tmp)*FR(tmp2) +
1151 FR(tmp+1)*FR(tmp2+1) +
1152 FR(tmp+2)*FR(tmp2+2) +
1153 FR(tmp+3)*FR(tmp2+3);
1154 }
1155 :}
1156 FSCA FPUL, FRn {:
1157 CHECKFPUEN();
1158 if( !IS_FPU_DOUBLEPREC() ) {
1159 sh4_fsca( FPULi, (float *)&(DRF(FRn>>1)) );
1160 /*
1161 float angle = (((float)(FPULi&0xFFFF))/65536.0) * 2 * M_PI;
1162 FR(FRn) = sinf(angle);
1163 FR((FRn)+1) = cosf(angle);
1164 */
1165 }
1166 :}
1167 FTRV XMTRX, FVn {:
1168 CHECKFPUEN();
1169 if( !IS_FPU_DOUBLEPREC() ) {
1170 sh4_ftrv((float *)&(DRF(FVn<<1)) );
1171 }
1172 :}
1173 UNDEF {:
1174 UNDEF(ir);
1175 :}
1176 %%
1177 sh4r.pc = sh4r.new_pc;
1178 sh4r.new_pc += 2;
1180 except:
1181 sh4r.in_delay_slot = 0;
1182 return TRUE;
1183 }
.