filename | src/sh4/sh4core.in |
changeset | 378:f10fbdd4e24b |
prev | 374:8f80a795513e |
next | 384:c9d5c194984b |
author | nkeynes |
date | Wed Sep 12 09:20:38 2007 +0000 (16 years ago) |
permissions | -rw-r--r-- |
last change | Start splitting the common SH4 parts into sh4.c, with sh4core.c to become just the emulation core. |
view | annotate | diff | log | raw |
1 /**
2 * $Id: sh4core.in,v 1.5 2007-09-12 09:20:38 nkeynes Exp $
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 <math.h>
22 #include "dream.h"
23 #include "sh4/sh4core.h"
24 #include "sh4/sh4mmio.h"
25 #include "sh4/intc.h"
26 #include "mem.h"
27 #include "clock.h"
28 #include "syscall.h"
30 #define SH4_CALLTRACE 1
32 #define MAX_INT 0x7FFFFFFF
33 #define MIN_INT 0x80000000
34 #define MAX_INTF 2147483647.0
35 #define MIN_INTF -2147483648.0
37 #define EXV_EXCEPTION 0x100 /* General exception vector */
38 #define EXV_TLBMISS 0x400 /* TLB-miss exception vector */
39 #define EXV_INTERRUPT 0x600 /* External interrupt vector */
41 /********************** SH4 Module Definition ****************************/
43 uint32_t sh4_run_slice( uint32_t );
45 static uint16_t *sh4_icache = NULL;
46 static uint32_t sh4_icache_addr = 0;
48 uint32_t sh4_run_slice( uint32_t nanosecs )
49 {
50 int i;
51 sh4r.slice_cycle = 0;
53 if( sh4r.sh4_state != SH4_STATE_RUNNING ) {
54 if( sh4r.event_pending < nanosecs ) {
55 sh4r.sh4_state = SH4_STATE_RUNNING;
56 sh4r.slice_cycle = sh4r.event_pending;
57 }
58 }
60 if( sh4_breakpoint_count == 0 ) {
61 for( ; sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
62 if( SH4_EVENT_PENDING() ) {
63 if( sh4r.event_types & PENDING_EVENT ) {
64 event_execute();
65 }
66 /* Eventq execute may (quite likely) deliver an immediate IRQ */
67 if( sh4r.event_types & PENDING_IRQ ) {
68 sh4_accept_interrupt();
69 }
70 }
71 if( !sh4_execute_instruction() ) {
72 break;
73 }
74 }
75 } else {
76 for( ;sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
77 if( SH4_EVENT_PENDING() ) {
78 if( sh4r.event_types & PENDING_EVENT ) {
79 event_execute();
80 }
81 /* Eventq execute may (quite likely) deliver an immediate IRQ */
82 if( sh4r.event_types & PENDING_IRQ ) {
83 sh4_accept_interrupt();
84 }
85 }
87 if( !sh4_execute_instruction() )
88 break;
89 #ifdef ENABLE_DEBUG_MODE
90 for( i=0; i<sh4_breakpoint_count; i++ ) {
91 if( sh4_breakpoints[i].address == sh4r.pc ) {
92 break;
93 }
94 }
95 if( i != sh4_breakpoint_count ) {
96 dreamcast_stop();
97 if( sh4_breakpoints[i].type == BREAK_ONESHOT )
98 sh4_clear_breakpoint( sh4r.pc, BREAK_ONESHOT );
99 break;
100 }
101 #endif
102 }
103 }
105 /* If we aborted early, but the cpu is still technically running,
106 * we're doing a hard abort - cut the timeslice back to what we
107 * actually executed
108 */
109 if( sh4r.slice_cycle != nanosecs && sh4r.sh4_state == SH4_STATE_RUNNING ) {
110 nanosecs = sh4r.slice_cycle;
111 }
112 if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
113 TMU_run_slice( nanosecs );
114 SCIF_run_slice( nanosecs );
115 }
116 return nanosecs;
117 }
119 /********************** SH4 emulation core ****************************/
121 void sh4_set_pc( int pc )
122 {
123 sh4r.pc = pc;
124 sh4r.new_pc = pc+2;
125 }
127 #define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
128 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); dreamcast_stop(); return FALSE; }while(0)
130 #if(SH4_CALLTRACE == 1)
131 #define MAX_CALLSTACK 32
132 static struct call_stack {
133 sh4addr_t call_addr;
134 sh4addr_t target_addr;
135 sh4addr_t stack_pointer;
136 } call_stack[MAX_CALLSTACK];
138 static int call_stack_depth = 0;
139 int sh4_call_trace_on = 0;
141 static inline trace_call( sh4addr_t source, sh4addr_t dest )
142 {
143 if( call_stack_depth < MAX_CALLSTACK ) {
144 call_stack[call_stack_depth].call_addr = source;
145 call_stack[call_stack_depth].target_addr = dest;
146 call_stack[call_stack_depth].stack_pointer = sh4r.r[15];
147 }
148 call_stack_depth++;
149 }
151 static inline trace_return( sh4addr_t source, sh4addr_t dest )
152 {
153 if( call_stack_depth > 0 ) {
154 call_stack_depth--;
155 }
156 }
158 void fprint_stack_trace( FILE *f )
159 {
160 int i = call_stack_depth -1;
161 if( i >= MAX_CALLSTACK )
162 i = MAX_CALLSTACK - 1;
163 for( ; i >= 0; i-- ) {
164 fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n",
165 (call_stack_depth - i), call_stack[i].call_addr,
166 call_stack[i].target_addr, call_stack[i].stack_pointer );
167 }
168 }
170 #define TRACE_CALL( source, dest ) trace_call(source, dest)
171 #define TRACE_RETURN( source, dest ) trace_return(source, dest)
172 #else
173 #define TRACE_CALL( dest, rts )
174 #define TRACE_RETURN( source, dest )
175 #endif
177 #define RAISE( x, v ) do{ \
178 if( sh4r.vbr == 0 ) { \
179 ERROR( "%08X: VBR not initialized while raising exception %03X, halting", sh4r.pc, x ); \
180 dreamcast_stop(); return FALSE; \
181 } else { \
182 sh4r.spc = sh4r.pc; \
183 sh4r.ssr = sh4_read_sr(); \
184 sh4r.sgr = sh4r.r[15]; \
185 MMIO_WRITE(MMU,EXPEVT,x); \
186 sh4r.pc = sh4r.vbr + v; \
187 sh4r.new_pc = sh4r.pc + 2; \
188 sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \
189 if( sh4r.in_delay_slot ) { \
190 sh4r.in_delay_slot = 0; \
191 sh4r.spc -= 2; \
192 } \
193 } \
194 return TRUE; } while(0)
196 #define MEM_READ_BYTE( addr ) sh4_read_byte(addr)
197 #define MEM_READ_WORD( addr ) sh4_read_word(addr)
198 #define MEM_READ_LONG( addr ) sh4_read_long(addr)
199 #define MEM_WRITE_BYTE( addr, val ) sh4_write_byte(addr, val)
200 #define MEM_WRITE_WORD( addr, val ) sh4_write_word(addr, val)
201 #define MEM_WRITE_LONG( addr, val ) sh4_write_long(addr, val)
203 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
205 #define MEM_FP_READ( addr, reg ) sh4_read_float( addr, reg );
206 #define MEM_FP_WRITE( addr, reg ) sh4_write_float( addr, reg );
208 #define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL )
209 #define CHECKRALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
210 #define CHECKRALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
211 #define CHECKWALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
212 #define CHECKWALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
214 #define CHECKFPUEN() if( !IS_FPU_ENABLED() ) { if( ir == 0xFFFD ) { UNDEF(ir); } else { return sh4_raise_slot_exception( EXC_FPU_DISABLED, EXC_SLOT_FPU_DISABLED ); } }
215 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); dreamcast_stop(); return FALSE; }
216 #define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) return sh4_raise_exception(EXC_SLOT_ILLEGAL)
218 static void sh4_switch_banks( )
219 {
220 uint32_t tmp[8];
222 memcpy( tmp, sh4r.r, sizeof(uint32_t)*8 );
223 memcpy( sh4r.r, sh4r.r_bank, sizeof(uint32_t)*8 );
224 memcpy( sh4r.r_bank, tmp, sizeof(uint32_t)*8 );
225 }
227 void sh4_write_sr( uint32_t newval )
228 {
229 if( (newval ^ sh4r.sr) & SR_RB )
230 sh4_switch_banks();
231 sh4r.sr = newval;
232 sh4r.t = (newval&SR_T) ? 1 : 0;
233 sh4r.s = (newval&SR_S) ? 1 : 0;
234 sh4r.m = (newval&SR_M) ? 1 : 0;
235 sh4r.q = (newval&SR_Q) ? 1 : 0;
236 intc_mask_changed();
237 }
239 static void sh4_write_float( uint32_t addr, int reg )
240 {
241 if( IS_FPU_DOUBLESIZE() ) {
242 if( reg & 1 ) {
243 sh4_write_long( addr, *((uint32_t *)&XF((reg)&0x0E)) );
244 sh4_write_long( addr+4, *((uint32_t *)&XF(reg)) );
245 } else {
246 sh4_write_long( addr, *((uint32_t *)&FR(reg)) );
247 sh4_write_long( addr+4, *((uint32_t *)&FR((reg)|0x01)) );
248 }
249 } else {
250 sh4_write_long( addr, *((uint32_t *)&FR((reg))) );
251 }
252 }
254 static void sh4_read_float( uint32_t addr, int reg )
255 {
256 if( IS_FPU_DOUBLESIZE() ) {
257 if( reg & 1 ) {
258 *((uint32_t *)&XF((reg) & 0x0E)) = sh4_read_long(addr);
259 *((uint32_t *)&XF(reg)) = sh4_read_long(addr+4);
260 } else {
261 *((uint32_t *)&FR(reg)) = sh4_read_long(addr);
262 *((uint32_t *)&FR((reg) | 0x01)) = sh4_read_long(addr+4);
263 }
264 } else {
265 *((uint32_t *)&FR(reg)) = sh4_read_long(addr);
266 }
267 }
269 uint32_t sh4_read_sr( void )
270 {
271 /* synchronize sh4r.sr with the various bitflags */
272 sh4r.sr &= SR_MQSTMASK;
273 if( sh4r.t ) sh4r.sr |= SR_T;
274 if( sh4r.s ) sh4r.sr |= SR_S;
275 if( sh4r.m ) sh4r.sr |= SR_M;
276 if( sh4r.q ) sh4r.sr |= SR_Q;
277 return sh4r.sr;
278 }
280 /**
281 * Raise a general CPU exception for the specified exception code.
282 * (NOT for TRAPA or TLB exceptions)
283 */
284 gboolean sh4_raise_exception( int code )
285 {
286 RAISE( code, EXV_EXCEPTION );
287 }
289 gboolean sh4_raise_slot_exception( int normal_code, int slot_code ) {
290 if( sh4r.in_delay_slot ) {
291 return sh4_raise_exception(slot_code);
292 } else {
293 return sh4_raise_exception(normal_code);
294 }
295 }
297 gboolean sh4_raise_tlb_exception( int code )
298 {
299 RAISE( code, EXV_TLBMISS );
300 }
302 void sh4_accept_interrupt( void )
303 {
304 uint32_t code = intc_accept_interrupt();
305 sh4r.ssr = sh4_read_sr();
306 sh4r.spc = sh4r.pc;
307 sh4r.sgr = sh4r.r[15];
308 sh4_write_sr( sh4r.ssr|SR_BL|SR_MD|SR_RB );
309 MMIO_WRITE( MMU, INTEVT, code );
310 sh4r.pc = sh4r.vbr + 0x600;
311 sh4r.new_pc = sh4r.pc + 2;
312 // WARN( "Accepting interrupt %03X, from %08X => %08X", code, sh4r.spc, sh4r.pc );
313 }
315 gboolean sh4_execute_instruction( void )
316 {
317 uint32_t pc;
318 unsigned short ir;
319 uint32_t tmp;
320 float ftmp;
321 double dtmp;
323 #define R0 sh4r.r[0]
324 pc = sh4r.pc;
325 if( pc > 0xFFFFFF00 ) {
326 /* SYSCALL Magic */
327 syscall_invoke( pc );
328 sh4r.in_delay_slot = 0;
329 pc = sh4r.pc = sh4r.pr;
330 sh4r.new_pc = sh4r.pc + 2;
331 }
332 CHECKRALIGN16(pc);
334 /* Read instruction */
335 uint32_t pageaddr = pc >> 12;
336 if( sh4_icache != NULL && pageaddr == sh4_icache_addr ) {
337 ir = sh4_icache[(pc&0xFFF)>>1];
338 } else {
339 sh4_icache = (uint16_t *)mem_get_page(pc);
340 if( ((uint32_t)sh4_icache) < MAX_IO_REGIONS ) {
341 /* If someone's actually been so daft as to try to execute out of an IO
342 * region, fallback on the full-blown memory read
343 */
344 sh4_icache = NULL;
345 ir = MEM_READ_WORD(pc);
346 } else {
347 sh4_icache_addr = pageaddr;
348 ir = sh4_icache[(pc&0xFFF)>>1];
349 }
350 }
351 %%
352 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
353 AND #imm, R0 {: R0 &= imm; :}
354 AND.B #imm, @(R0, GBR) {: MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & MEM_READ_BYTE(R0 + sh4r.gbr) ); :}
355 NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}
356 OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}
357 OR #imm, R0 {: R0 |= imm; :}
358 OR.B #imm, @(R0, GBR) {: MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | MEM_READ_BYTE(R0 + sh4r.gbr) ); :}
359 TAS.B @Rn {:
360 tmp = MEM_READ_BYTE( sh4r.r[Rn] );
361 sh4r.t = ( tmp == 0 ? 1 : 0 );
362 MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );
363 :}
364 TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}
365 TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}
366 TST.B #imm, @(R0, GBR) {: sh4r.t = ( MEM_READ_BYTE(R0 + sh4r.gbr) & imm ? 0 : 1 ); :}
367 XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}
368 XOR #imm, R0 {: R0 ^= imm; :}
369 XOR.B #imm, @(R0, GBR) {: MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ MEM_READ_BYTE(R0 + sh4r.gbr) ); :}
370 XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}
372 ROTL Rn {:
373 sh4r.t = sh4r.r[Rn] >> 31;
374 sh4r.r[Rn] <<= 1;
375 sh4r.r[Rn] |= sh4r.t;
376 :}
377 ROTR Rn {:
378 sh4r.t = sh4r.r[Rn] & 0x00000001;
379 sh4r.r[Rn] >>= 1;
380 sh4r.r[Rn] |= (sh4r.t << 31);
381 :}
382 ROTCL Rn {:
383 tmp = sh4r.r[Rn] >> 31;
384 sh4r.r[Rn] <<= 1;
385 sh4r.r[Rn] |= sh4r.t;
386 sh4r.t = tmp;
387 :}
388 ROTCR Rn {:
389 tmp = sh4r.r[Rn] & 0x00000001;
390 sh4r.r[Rn] >>= 1;
391 sh4r.r[Rn] |= (sh4r.t << 31 );
392 sh4r.t = tmp;
393 :}
394 SHAD Rm, Rn {:
395 tmp = sh4r.r[Rm];
396 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
397 else if( (tmp & 0x1F) == 0 )
398 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;
399 else
400 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);
401 :}
402 SHLD Rm, Rn {:
403 tmp = sh4r.r[Rm];
404 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
405 else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;
406 else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);
407 :}
408 SHAL Rn {:
409 sh4r.t = sh4r.r[Rn] >> 31;
410 sh4r.r[Rn] <<= 1;
411 :}
412 SHAR Rn {:
413 sh4r.t = sh4r.r[Rn] & 0x00000001;
414 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;
415 :}
416 SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}
417 SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}
418 SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}
419 SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}
420 SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}
421 SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}
422 SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}
423 SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}
425 EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}
426 EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}
427 EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}
428 EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}
429 SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}
430 SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}
432 CLRT {: sh4r.t = 0; :}
433 SETT {: sh4r.t = 1; :}
434 CLRMAC {: sh4r.mac = 0; :}
435 LDTLB {: /* TODO */ :}
436 CLRS {: sh4r.s = 0; :}
437 SETS {: sh4r.s = 1; :}
438 MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}
439 NOP {: /* NOP */ :}
441 PREF @Rn {:
442 tmp = sh4r.r[Rn];
443 if( (tmp & 0xFC000000) == 0xE0000000 ) {
444 sh4_flush_store_queue(tmp);
445 }
446 :}
447 OCBI @Rn {: :}
448 OCBP @Rn {: :}
449 OCBWB @Rn {: :}
450 MOVCA.L R0, @Rn {:
451 tmp = sh4r.r[Rn];
452 CHECKWALIGN32(tmp);
453 MEM_WRITE_LONG( tmp, R0 );
454 :}
455 MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}
456 MOV.W Rm, @(R0, Rn) {:
457 CHECKWALIGN16( R0 + sh4r.r[Rn] );
458 MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );
459 :}
460 MOV.L Rm, @(R0, Rn) {:
461 CHECKWALIGN32( R0 + sh4r.r[Rn] );
462 MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );
463 :}
464 MOV.B @(R0, Rm), Rn {: sh4r.r[Rn] = MEM_READ_BYTE( R0 + sh4r.r[Rm] ); :}
465 MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );
466 sh4r.r[Rn] = MEM_READ_WORD( R0 + sh4r.r[Rm] );
467 :}
468 MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );
469 sh4r.r[Rn] = MEM_READ_LONG( R0 + sh4r.r[Rm] );
470 :}
471 MOV.L Rm, @(disp, Rn) {:
472 tmp = sh4r.r[Rn] + disp;
473 CHECKWALIGN32( tmp );
474 MEM_WRITE_LONG( tmp, sh4r.r[Rm] );
475 :}
476 MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
477 MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
478 MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
479 MOV.B Rm, @-Rn {: sh4r.r[Rn] --; MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
480 MOV.W Rm, @-Rn {: sh4r.r[Rn] -= 2; CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
481 MOV.L Rm, @-Rn {: sh4r.r[Rn] -= 4; CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
482 MOV.L @(disp, Rm), Rn {:
483 tmp = sh4r.r[Rm] + disp;
484 CHECKRALIGN32( tmp );
485 sh4r.r[Rn] = MEM_READ_LONG( tmp );
486 :}
487 MOV.B @Rm, Rn {: sh4r.r[Rn] = MEM_READ_BYTE( sh4r.r[Rm] ); :}
488 MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_WORD( sh4r.r[Rm] ); :}
489 MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_LONG( sh4r.r[Rm] ); :}
490 MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}
491 MOV.B @Rm+, Rn {: sh4r.r[Rn] = MEM_READ_BYTE( sh4r.r[Rm] ); sh4r.r[Rm] ++; :}
492 MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_WORD( sh4r.r[Rm] ); sh4r.r[Rm] += 2; :}
493 MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_LONG( sh4r.r[Rm] ); sh4r.r[Rm] += 4; :}
494 MOV.L @(disp, PC), Rn {:
495 CHECKSLOTILLEGAL();
496 tmp = (pc&0xFFFFFFFC) + disp + 4;
497 sh4r.r[Rn] = MEM_READ_LONG( tmp );
498 :}
499 MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}
500 MOV.W R0, @(disp, GBR) {:
501 tmp = sh4r.gbr + disp;
502 CHECKWALIGN16( tmp );
503 MEM_WRITE_WORD( tmp, R0 );
504 :}
505 MOV.L R0, @(disp, GBR) {:
506 tmp = sh4r.gbr + disp;
507 CHECKWALIGN32( tmp );
508 MEM_WRITE_LONG( tmp, R0 );
509 :}
510 MOV.B @(disp, GBR), R0 {: R0 = MEM_READ_BYTE( sh4r.gbr + disp ); :}
511 MOV.W @(disp, GBR), R0 {:
512 tmp = sh4r.gbr + disp;
513 CHECKRALIGN16( tmp );
514 R0 = MEM_READ_WORD( tmp );
515 :}
516 MOV.L @(disp, GBR), R0 {:
517 tmp = sh4r.gbr + disp;
518 CHECKRALIGN32( tmp );
519 R0 = MEM_READ_LONG( tmp );
520 :}
521 MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}
522 MOV.W R0, @(disp, Rn) {:
523 tmp = sh4r.r[Rn] + disp;
524 CHECKWALIGN16( tmp );
525 MEM_WRITE_WORD( tmp, R0 );
526 :}
527 MOV.B @(disp, Rm), R0 {: R0 = MEM_READ_BYTE( sh4r.r[Rm] + disp ); :}
528 MOV.W @(disp, Rm), R0 {:
529 tmp = sh4r.r[Rm] + disp;
530 CHECKRALIGN16( tmp );
531 R0 = MEM_READ_WORD( tmp );
532 :}
533 MOV.W @(disp, PC), Rn {:
534 CHECKSLOTILLEGAL();
535 tmp = pc + 4 + disp;
536 sh4r.r[Rn] = MEM_READ_WORD( tmp );
537 :}
538 MOVA @(disp, PC), R0 {:
539 CHECKSLOTILLEGAL();
540 R0 = (pc&0xFFFFFFFC) + disp + 4;
541 :}
542 MOV #imm, Rn {: sh4r.r[Rn] = imm; :}
544 CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}
545 CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}
546 CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
547 CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
548 CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}
549 CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}
550 CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}
551 CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}
552 CMP/STR Rm, Rn {:
553 /* set T = 1 if any byte in RM & RN is the same */
554 tmp = sh4r.r[Rm] ^ sh4r.r[Rn];
555 sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
556 (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
557 :}
559 ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}
560 ADD #imm, Rn {: sh4r.r[Rn] += imm; :}
561 ADDC Rm, Rn {:
562 tmp = sh4r.r[Rn];
563 sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;
564 sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );
565 :}
566 ADDV Rm, Rn {:
567 tmp = sh4r.r[Rn] + sh4r.r[Rm];
568 sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
569 sh4r.r[Rn] = tmp;
570 :}
571 DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}
572 DIV0S Rm, Rn {:
573 sh4r.q = sh4r.r[Rn]>>31;
574 sh4r.m = sh4r.r[Rm]>>31;
575 sh4r.t = sh4r.q ^ sh4r.m;
576 :}
577 DIV1 Rm, Rn {:
578 /* This is just from the sh4p manual with some
579 * simplifications (someone want to check it's correct? :)
580 * Why they couldn't just provide a real DIV instruction...
581 */
582 uint32_t tmp0, tmp1, tmp2, dir;
584 dir = sh4r.q ^ sh4r.m;
585 sh4r.q = (sh4r.r[Rn] >> 31);
586 tmp2 = sh4r.r[Rm];
587 sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
588 tmp0 = sh4r.r[Rn];
589 if( dir ) {
590 sh4r.r[Rn] += tmp2;
591 tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
592 } else {
593 sh4r.r[Rn] -= tmp2;
594 tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
595 }
596 sh4r.q ^= sh4r.m ^ tmp1;
597 sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
598 :}
599 DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
600 DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
601 DT Rn {:
602 sh4r.r[Rn] --;
603 sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
604 :}
605 MAC.W @Rm+, @Rn+ {:
606 CHECKRALIGN16( sh4r.r[Rn] );
607 CHECKRALIGN16( sh4r.r[Rm] );
608 int32_t stmp = SIGNEXT16(MEM_READ_WORD(sh4r.r[Rn]));
609 sh4r.r[Rn] += 2;
610 stmp = stmp * SIGNEXT16(MEM_READ_WORD(sh4r.r[Rm]));
611 sh4r.r[Rm] += 2;
612 if( sh4r.s ) {
613 int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
614 if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
615 sh4r.mac = 0x000000017FFFFFFFLL;
616 } else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
617 sh4r.mac = 0x0000000180000000LL;
618 } else {
619 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
620 ((uint32_t)(sh4r.mac + stmp));
621 }
622 } else {
623 sh4r.mac += SIGNEXT32(stmp);
624 }
625 :}
626 MAC.L @Rm+, @Rn+ {:
627 CHECKRALIGN32( sh4r.r[Rm] );
628 CHECKRALIGN32( sh4r.r[Rn] );
629 int64_t tmpl = SIGNEXT32(MEM_READ_LONG(sh4r.r[Rn]));
630 sh4r.r[Rn] += 4;
631 tmpl = tmpl * SIGNEXT32(MEM_READ_LONG(sh4r.r[Rm])) + sh4r.mac;
632 sh4r.r[Rm] += 4;
633 if( sh4r.s ) {
634 /* 48-bit Saturation. Yuch */
635 if( tmpl < (int64_t)0xFFFF800000000000LL )
636 tmpl = 0xFFFF800000000000LL;
637 else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
638 tmpl = 0x00007FFFFFFFFFFFLL;
639 }
640 sh4r.mac = tmpl;
641 :}
642 MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
643 (sh4r.r[Rm] * sh4r.r[Rn]); :}
644 MULU.W Rm, Rn {:
645 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
646 (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
647 :}
648 MULS.W Rm, Rn {:
649 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
650 (uint32_t)(SIGNEXT32(sh4r.r[Rm]&0xFFFF) * SIGNEXT32(sh4r.r[Rn]&0xFFFF));
651 :}
652 NEGC Rm, Rn {:
653 tmp = 0 - sh4r.r[Rm];
654 sh4r.r[Rn] = tmp - sh4r.t;
655 sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
656 :}
657 NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
658 SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
659 SUBC Rm, Rn {:
660 tmp = sh4r.r[Rn];
661 sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
662 sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
663 :}
665 BRAF Rn {:
666 CHECKSLOTILLEGAL();
667 CHECKDEST( pc + 4 + sh4r.r[Rn] );
668 sh4r.in_delay_slot = 1;
669 sh4r.pc = sh4r.new_pc;
670 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
671 return TRUE;
672 :}
673 BSRF Rn {:
674 CHECKSLOTILLEGAL();
675 CHECKDEST( pc + 4 + sh4r.r[Rn] );
676 sh4r.in_delay_slot = 1;
677 sh4r.pr = sh4r.pc + 4;
678 sh4r.pc = sh4r.new_pc;
679 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
680 TRACE_CALL( pc, sh4r.new_pc );
681 return TRUE;
682 :}
683 BT disp {:
684 CHECKSLOTILLEGAL();
685 if( sh4r.t ) {
686 CHECKDEST( sh4r.pc + disp + 4 )
687 sh4r.pc += disp + 4;
688 sh4r.new_pc = sh4r.pc + 2;
689 return TRUE;
690 }
691 :}
692 BF disp {:
693 CHECKSLOTILLEGAL();
694 if( !sh4r.t ) {
695 CHECKDEST( sh4r.pc + disp + 4 )
696 sh4r.pc += disp + 4;
697 sh4r.new_pc = sh4r.pc + 2;
698 return TRUE;
699 }
700 :}
701 BT/S disp {:
702 CHECKSLOTILLEGAL();
703 if( sh4r.t ) {
704 CHECKDEST( sh4r.pc + disp + 4 )
705 sh4r.in_delay_slot = 1;
706 sh4r.pc = sh4r.new_pc;
707 sh4r.new_pc = pc + disp + 4;
708 sh4r.in_delay_slot = 1;
709 return TRUE;
710 }
711 :}
712 BF/S disp {:
713 CHECKSLOTILLEGAL();
714 if( !sh4r.t ) {
715 CHECKDEST( sh4r.pc + disp + 4 )
716 sh4r.in_delay_slot = 1;
717 sh4r.pc = sh4r.new_pc;
718 sh4r.new_pc = pc + disp + 4;
719 return TRUE;
720 }
721 :}
722 BRA disp {:
723 CHECKSLOTILLEGAL();
724 CHECKDEST( sh4r.pc + disp + 4 );
725 sh4r.in_delay_slot = 1;
726 sh4r.pc = sh4r.new_pc;
727 sh4r.new_pc = pc + 4 + disp;
728 return TRUE;
729 :}
730 BSR disp {:
731 CHECKDEST( sh4r.pc + disp + 4 );
732 CHECKSLOTILLEGAL();
733 sh4r.in_delay_slot = 1;
734 sh4r.pr = pc + 4;
735 sh4r.pc = sh4r.new_pc;
736 sh4r.new_pc = pc + 4 + disp;
737 TRACE_CALL( pc, sh4r.new_pc );
738 return TRUE;
739 :}
740 TRAPA #imm {:
741 CHECKSLOTILLEGAL();
742 MMIO_WRITE( MMU, TRA, imm<<2 );
743 sh4r.pc += 2;
744 sh4_raise_exception( EXC_TRAP );
745 :}
746 RTS {:
747 CHECKSLOTILLEGAL();
748 CHECKDEST( sh4r.pr );
749 sh4r.in_delay_slot = 1;
750 sh4r.pc = sh4r.new_pc;
751 sh4r.new_pc = sh4r.pr;
752 TRACE_RETURN( pc, sh4r.new_pc );
753 return TRUE;
754 :}
755 SLEEP {:
756 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
757 sh4r.sh4_state = SH4_STATE_STANDBY;
758 } else {
759 sh4r.sh4_state = SH4_STATE_SLEEP;
760 }
761 return FALSE; /* Halt CPU */
762 :}
763 RTE {:
764 CHECKPRIV();
765 CHECKDEST( sh4r.spc );
766 CHECKSLOTILLEGAL();
767 sh4r.in_delay_slot = 1;
768 sh4r.pc = sh4r.new_pc;
769 sh4r.new_pc = sh4r.spc;
770 sh4_write_sr( sh4r.ssr );
771 return TRUE;
772 :}
773 JMP @Rn {:
774 CHECKDEST( sh4r.r[Rn] );
775 CHECKSLOTILLEGAL();
776 sh4r.in_delay_slot = 1;
777 sh4r.pc = sh4r.new_pc;
778 sh4r.new_pc = sh4r.r[Rn];
779 return TRUE;
780 :}
781 JSR @Rn {:
782 CHECKDEST( sh4r.r[Rn] );
783 CHECKSLOTILLEGAL();
784 sh4r.in_delay_slot = 1;
785 sh4r.pc = sh4r.new_pc;
786 sh4r.new_pc = sh4r.r[Rn];
787 sh4r.pr = pc + 4;
788 TRACE_CALL( pc, sh4r.new_pc );
789 return TRUE;
790 :}
791 STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
792 STS.L MACH, @-Rn {:
793 sh4r.r[Rn] -= 4;
794 CHECKWALIGN32( sh4r.r[Rn] );
795 MEM_WRITE_LONG( sh4r.r[Rn], (sh4r.mac>>32) );
796 :}
797 STC.L SR, @-Rn {:
798 CHECKPRIV();
799 sh4r.r[Rn] -= 4;
800 CHECKWALIGN32( sh4r.r[Rn] );
801 MEM_WRITE_LONG( sh4r.r[Rn], sh4_read_sr() );
802 :}
803 LDS.L @Rm+, MACH {:
804 CHECKRALIGN32( sh4r.r[Rm] );
805 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
806 (((uint64_t)MEM_READ_LONG(sh4r.r[Rm]))<<32);
807 sh4r.r[Rm] += 4;
808 :}
809 LDC.L @Rm+, SR {:
810 CHECKSLOTILLEGAL();
811 CHECKPRIV();
812 CHECKWALIGN32( sh4r.r[Rm] );
813 sh4_write_sr( MEM_READ_LONG(sh4r.r[Rm]) );
814 sh4r.r[Rm] +=4;
815 :}
816 LDS Rm, MACH {:
817 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
818 (((uint64_t)sh4r.r[Rm])<<32);
819 :}
820 LDC Rm, SR {:
821 CHECKSLOTILLEGAL();
822 CHECKPRIV();
823 sh4_write_sr( sh4r.r[Rm] );
824 :}
825 LDC Rm, SGR {:
826 CHECKPRIV();
827 sh4r.sgr = sh4r.r[Rm];
828 :}
829 LDC.L @Rm+, SGR {:
830 CHECKPRIV();
831 CHECKRALIGN32( sh4r.r[Rm] );
832 sh4r.sgr = MEM_READ_LONG(sh4r.r[Rm]);
833 sh4r.r[Rm] +=4;
834 :}
835 STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
836 STS.L MACL, @-Rn {:
837 sh4r.r[Rn] -= 4;
838 CHECKWALIGN32( sh4r.r[Rn] );
839 MEM_WRITE_LONG( sh4r.r[Rn], (uint32_t)sh4r.mac );
840 :}
841 STC.L GBR, @-Rn {:
842 sh4r.r[Rn] -= 4;
843 CHECKWALIGN32( sh4r.r[Rn] );
844 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.gbr );
845 :}
846 LDS.L @Rm+, MACL {:
847 CHECKRALIGN32( sh4r.r[Rm] );
848 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
849 (uint64_t)((uint32_t)MEM_READ_LONG(sh4r.r[Rm]));
850 sh4r.r[Rm] += 4;
851 :}
852 LDC.L @Rm+, GBR {:
853 CHECKRALIGN32( sh4r.r[Rm] );
854 sh4r.gbr = MEM_READ_LONG(sh4r.r[Rm]);
855 sh4r.r[Rm] +=4;
856 :}
857 LDS Rm, MACL {:
858 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
859 (uint64_t)((uint32_t)(sh4r.r[Rm]));
860 :}
861 LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
862 STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
863 STS.L PR, @-Rn {:
864 sh4r.r[Rn] -= 4;
865 CHECKWALIGN32( sh4r.r[Rn] );
866 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.pr );
867 :}
868 STC.L VBR, @-Rn {:
869 CHECKPRIV();
870 sh4r.r[Rn] -= 4;
871 CHECKWALIGN32( sh4r.r[Rn] );
872 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.vbr );
873 :}
874 LDS.L @Rm+, PR {:
875 CHECKRALIGN32( sh4r.r[Rm] );
876 sh4r.pr = MEM_READ_LONG( sh4r.r[Rm] );
877 sh4r.r[Rm] += 4;
878 :}
879 LDC.L @Rm+, VBR {:
880 CHECKPRIV();
881 CHECKRALIGN32( sh4r.r[Rm] );
882 sh4r.vbr = MEM_READ_LONG(sh4r.r[Rm]);
883 sh4r.r[Rm] +=4;
884 :}
885 LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
886 LDC Rm, VBR {:
887 CHECKPRIV();
888 sh4r.vbr = sh4r.r[Rm];
889 :}
890 STC SGR, Rn {:
891 CHECKPRIV();
892 sh4r.r[Rn] = sh4r.sgr;
893 :}
894 STC.L SGR, @-Rn {:
895 CHECKPRIV();
896 sh4r.r[Rn] -= 4;
897 CHECKWALIGN32( sh4r.r[Rn] );
898 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.sgr );
899 :}
900 STC.L SSR, @-Rn {:
901 CHECKPRIV();
902 sh4r.r[Rn] -= 4;
903 CHECKWALIGN32( sh4r.r[Rn] );
904 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.ssr );
905 :}
906 LDC.L @Rm+, SSR {:
907 CHECKPRIV();
908 CHECKRALIGN32( sh4r.r[Rm] );
909 sh4r.ssr = MEM_READ_LONG(sh4r.r[Rm]);
910 sh4r.r[Rm] +=4;
911 :}
912 LDC Rm, SSR {:
913 CHECKPRIV();
914 sh4r.ssr = sh4r.r[Rm];
915 :}
916 STC.L SPC, @-Rn {:
917 CHECKPRIV();
918 sh4r.r[Rn] -= 4;
919 CHECKWALIGN32( sh4r.r[Rn] );
920 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.spc );
921 :}
922 LDC.L @Rm+, SPC {:
923 CHECKPRIV();
924 CHECKRALIGN32( sh4r.r[Rm] );
925 sh4r.spc = MEM_READ_LONG(sh4r.r[Rm]);
926 sh4r.r[Rm] +=4;
927 :}
928 LDC Rm, SPC {:
929 CHECKPRIV();
930 sh4r.spc = sh4r.r[Rm];
931 :}
932 STS FPUL, Rn {: sh4r.r[Rn] = sh4r.fpul; :}
933 STS.L FPUL, @-Rn {:
934 sh4r.r[Rn] -= 4;
935 CHECKWALIGN32( sh4r.r[Rn] );
936 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.fpul );
937 :}
938 LDS.L @Rm+, FPUL {:
939 CHECKRALIGN32( sh4r.r[Rm] );
940 sh4r.fpul = MEM_READ_LONG(sh4r.r[Rm]);
941 sh4r.r[Rm] +=4;
942 :}
943 LDS Rm, FPUL {: sh4r.fpul = sh4r.r[Rm]; :}
944 STS FPSCR, Rn {: sh4r.r[Rn] = sh4r.fpscr; :}
945 STS.L FPSCR, @-Rn {:
946 sh4r.r[Rn] -= 4;
947 CHECKWALIGN32( sh4r.r[Rn] );
948 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.fpscr );
949 :}
950 LDS.L @Rm+, FPSCR {:
951 CHECKRALIGN32( sh4r.r[Rm] );
952 sh4r.fpscr = MEM_READ_LONG(sh4r.r[Rm]);
953 sh4r.r[Rm] +=4;
954 sh4r.fr_bank = &sh4r.fr[(sh4r.fpscr&FPSCR_FR)>>21][0];
955 :}
956 LDS Rm, FPSCR {:
957 sh4r.fpscr = sh4r.r[Rm];
958 sh4r.fr_bank = &sh4r.fr[(sh4r.fpscr&FPSCR_FR)>>21][0];
959 :}
960 STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
961 STC.L DBR, @-Rn {:
962 CHECKPRIV();
963 sh4r.r[Rn] -= 4;
964 CHECKWALIGN32( sh4r.r[Rn] );
965 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.dbr );
966 :}
967 LDC.L @Rm+, DBR {:
968 CHECKPRIV();
969 CHECKRALIGN32( sh4r.r[Rm] );
970 sh4r.dbr = MEM_READ_LONG(sh4r.r[Rm]);
971 sh4r.r[Rm] +=4;
972 :}
973 LDC Rm, DBR {:
974 CHECKPRIV();
975 sh4r.dbr = sh4r.r[Rm];
976 :}
977 STC.L Rm_BANK, @-Rn {:
978 CHECKPRIV();
979 sh4r.r[Rn] -= 4;
980 CHECKWALIGN32( sh4r.r[Rn] );
981 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r_bank[Rm_BANK] );
982 :}
983 LDC.L @Rm+, Rn_BANK {:
984 CHECKPRIV();
985 CHECKRALIGN32( sh4r.r[Rm] );
986 sh4r.r_bank[Rn_BANK] = MEM_READ_LONG( sh4r.r[Rm] );
987 sh4r.r[Rm] += 4;
988 :}
989 LDC Rm, Rn_BANK {:
990 CHECKPRIV();
991 sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
992 :}
993 STC SR, Rn {:
994 CHECKPRIV();
995 sh4r.r[Rn] = sh4_read_sr();
996 :}
997 STC GBR, Rn {:
998 CHECKPRIV();
999 sh4r.r[Rn] = sh4r.gbr;
1000 :}
1001 STC VBR, Rn {:
1002 CHECKPRIV();
1003 sh4r.r[Rn] = sh4r.vbr;
1004 :}
1005 STC SSR, Rn {:
1006 CHECKPRIV();
1007 sh4r.r[Rn] = sh4r.ssr;
1008 :}
1009 STC SPC, Rn {:
1010 CHECKPRIV();
1011 sh4r.r[Rn] = sh4r.spc;
1012 :}
1013 STC Rm_BANK, Rn {:
1014 CHECKPRIV();
1015 sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
1016 :}
1018 FADD FRm, FRn {:
1019 CHECKFPUEN();
1020 if( IS_FPU_DOUBLEPREC() ) {
1021 DR(FRn) += DR(FRm);
1022 } else {
1023 FR(FRn) += FR(FRm);
1024 }
1025 :}
1026 FSUB FRm, FRn {:
1027 CHECKFPUEN();
1028 if( IS_FPU_DOUBLEPREC() ) {
1029 DR(FRn) -= DR(FRm);
1030 } else {
1031 FR(FRn) -= FR(FRm);
1032 }
1033 :}
1035 FMUL FRm, FRn {:
1036 CHECKFPUEN();
1037 if( IS_FPU_DOUBLEPREC() ) {
1038 DR(FRn) *= DR(FRm);
1039 } else {
1040 FR(FRn) *= FR(FRm);
1041 }
1042 :}
1044 FDIV FRm, FRn {:
1045 CHECKFPUEN();
1046 if( IS_FPU_DOUBLEPREC() ) {
1047 DR(FRn) /= DR(FRm);
1048 } else {
1049 FR(FRn) /= FR(FRm);
1050 }
1051 :}
1053 FCMP/EQ FRm, FRn {:
1054 CHECKFPUEN();
1055 if( IS_FPU_DOUBLEPREC() ) {
1056 sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
1057 } else {
1058 sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
1059 }
1060 :}
1062 FCMP/GT FRm, FRn {:
1063 CHECKFPUEN();
1064 if( IS_FPU_DOUBLEPREC() ) {
1065 sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
1066 } else {
1067 sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
1068 }
1069 :}
1071 FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
1072 FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
1073 FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
1074 FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
1075 FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
1076 FMOV FRm, @-Rn {: sh4r.r[Rn] -= FP_WIDTH; MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
1077 FMOV FRm, FRn {:
1078 if( IS_FPU_DOUBLESIZE() )
1079 DR(FRn) = DR(FRm);
1080 else
1081 FR(FRn) = FR(FRm);
1082 :}
1083 FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
1084 FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
1085 FLOAT FPUL, FRn {:
1086 CHECKFPUEN();
1087 if( IS_FPU_DOUBLEPREC() ) {
1088 if( FRn&1 ) { // No, really...
1089 dtmp = (double)FPULi;
1090 FR(FRn) = *(((float *)&dtmp)+1);
1091 } else {
1092 DRF(FRn>>1) = (double)FPULi;
1093 }
1094 } else {
1095 FR(FRn) = (float)FPULi;
1096 }
1097 :}
1098 FTRC FRm, FPUL {:
1099 CHECKFPUEN();
1100 if( IS_FPU_DOUBLEPREC() ) {
1101 if( FRm&1 ) {
1102 dtmp = 0;
1103 *(((float *)&dtmp)+1) = FR(FRm);
1104 } else {
1105 dtmp = DRF(FRm>>1);
1106 }
1107 if( dtmp >= MAX_INTF )
1108 FPULi = MAX_INT;
1109 else if( dtmp <= MIN_INTF )
1110 FPULi = MIN_INT;
1111 else
1112 FPULi = (int32_t)dtmp;
1113 } else {
1114 ftmp = FR(FRm);
1115 if( ftmp >= MAX_INTF )
1116 FPULi = MAX_INT;
1117 else if( ftmp <= MIN_INTF )
1118 FPULi = MIN_INT;
1119 else
1120 FPULi = (int32_t)ftmp;
1121 }
1122 :}
1123 FNEG FRn {:
1124 CHECKFPUEN();
1125 if( IS_FPU_DOUBLEPREC() ) {
1126 DR(FRn) = -DR(FRn);
1127 } else {
1128 FR(FRn) = -FR(FRn);
1129 }
1130 :}
1131 FABS FRn {:
1132 CHECKFPUEN();
1133 if( IS_FPU_DOUBLEPREC() ) {
1134 DR(FRn) = fabs(DR(FRn));
1135 } else {
1136 FR(FRn) = fabsf(FR(FRn));
1137 }
1138 :}
1139 FSQRT FRn {:
1140 CHECKFPUEN();
1141 if( IS_FPU_DOUBLEPREC() ) {
1142 DR(FRn) = sqrt(DR(FRn));
1143 } else {
1144 FR(FRn) = sqrtf(FR(FRn));
1145 }
1146 :}
1147 FLDI0 FRn {:
1148 CHECKFPUEN();
1149 if( IS_FPU_DOUBLEPREC() ) {
1150 DR(FRn) = 0.0;
1151 } else {
1152 FR(FRn) = 0.0;
1153 }
1154 :}
1155 FLDI1 FRn {:
1156 CHECKFPUEN();
1157 if( IS_FPU_DOUBLEPREC() ) {
1158 DR(FRn) = 1.0;
1159 } else {
1160 FR(FRn) = 1.0;
1161 }
1162 :}
1163 FMAC FR0, FRm, FRn {:
1164 CHECKFPUEN();
1165 if( IS_FPU_DOUBLEPREC() ) {
1166 DR(FRn) += DR(FRm)*DR(0);
1167 } else {
1168 FR(FRn) += FR(FRm)*FR(0);
1169 }
1170 :}
1171 FRCHG {:
1172 CHECKFPUEN();
1173 sh4r.fpscr ^= FPSCR_FR;
1174 sh4r.fr_bank = &sh4r.fr[(sh4r.fpscr&FPSCR_FR)>>21][0];
1175 :}
1176 FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
1177 FCNVSD FPUL, FRn {:
1178 CHECKFPUEN();
1179 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1180 DR(FRn) = (double)FPULf;
1181 }
1182 :}
1183 FCNVDS FRm, FPUL {:
1184 CHECKFPUEN();
1185 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1186 FPULf = (float)DR(FRm);
1187 }
1188 :}
1190 FSRRA FRn {:
1191 CHECKFPUEN();
1192 if( !IS_FPU_DOUBLEPREC() ) {
1193 FR(FRn) = 1.0/sqrtf(FR(FRn));
1194 }
1195 :}
1196 FIPR FVm, FVn {:
1197 CHECKFPUEN();
1198 if( !IS_FPU_DOUBLEPREC() ) {
1199 int tmp2 = FVn<<2;
1200 tmp = FVm<<2;
1201 FR(tmp2+3) = FR(tmp)*FR(tmp2) +
1202 FR(tmp+1)*FR(tmp2+1) +
1203 FR(tmp+2)*FR(tmp2+2) +
1204 FR(tmp+3)*FR(tmp2+3);
1205 }
1206 :}
1207 FSCA FPUL, FRn {:
1208 CHECKFPUEN();
1209 if( !IS_FPU_DOUBLEPREC() ) {
1210 float angle = (((float)(FPULi&0xFFFF))/65536.0) * 2 * M_PI;
1211 FR(FRn) = sinf(angle);
1212 FR((FRn)+1) = cosf(angle);
1213 }
1214 :}
1215 FTRV XMTRX, FVn {:
1216 CHECKFPUEN();
1217 if( !IS_FPU_DOUBLEPREC() ) {
1218 tmp = FVn<<2;
1219 float *xf = &sh4r.fr[((~sh4r.fpscr)&FPSCR_FR)>>21][0];
1220 float fv[4] = { FR(tmp), FR(tmp+1), FR(tmp+2), FR(tmp+3) };
1221 FR(tmp) = xf[1] * fv[0] + xf[5]*fv[1] +
1222 xf[9]*fv[2] + xf[13]*fv[3];
1223 FR(tmp+1) = xf[0] * fv[0] + xf[4]*fv[1] +
1224 xf[8]*fv[2] + xf[12]*fv[3];
1225 FR(tmp+2) = xf[3] * fv[0] + xf[7]*fv[1] +
1226 xf[11]*fv[2] + xf[15]*fv[3];
1227 FR(tmp+3) = xf[2] * fv[0] + xf[6]*fv[1] +
1228 xf[10]*fv[2] + xf[14]*fv[3];
1229 }
1230 :}
1231 UNDEF {:
1232 UNDEF(ir);
1233 :}
1234 %%
1235 sh4r.pc = sh4r.new_pc;
1236 sh4r.new_pc += 2;
1237 sh4r.in_delay_slot = 0;
1238 return TRUE;
1239 }
.