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