filename | src/sh4/sh4core.in |
changeset | 384:c9d5c194984b |
prev | 378:f10fbdd4e24b |
next | 391:16afb90b5d47 |
author | nkeynes |
date | Sun Sep 16 07:01:07 2007 +0000 (16 years ago) |
permissions | -rw-r--r-- |
last change | Add DIV1 test cases Update comment against opcode since it looks to be validated now |
view | annotate | diff | log | raw |
1 /**
2 * $Id: sh4core.in,v 1.6 2007-09-16 07:01:07 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 derived from the sh4 manual with some simplifications */
579 uint32_t tmp0, tmp1, tmp2, dir;
581 dir = sh4r.q ^ sh4r.m;
582 sh4r.q = (sh4r.r[Rn] >> 31);
583 tmp2 = sh4r.r[Rm];
584 sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
585 tmp0 = sh4r.r[Rn];
586 if( dir ) {
587 sh4r.r[Rn] += tmp2;
588 tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
589 } else {
590 sh4r.r[Rn] -= tmp2;
591 tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
592 }
593 sh4r.q ^= sh4r.m ^ tmp1;
594 sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
595 :}
596 DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
597 DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
598 DT Rn {:
599 sh4r.r[Rn] --;
600 sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
601 :}
602 MAC.W @Rm+, @Rn+ {:
603 CHECKRALIGN16( sh4r.r[Rn] );
604 CHECKRALIGN16( sh4r.r[Rm] );
605 int32_t stmp = SIGNEXT16(MEM_READ_WORD(sh4r.r[Rn]));
606 sh4r.r[Rn] += 2;
607 stmp = stmp * SIGNEXT16(MEM_READ_WORD(sh4r.r[Rm]));
608 sh4r.r[Rm] += 2;
609 if( sh4r.s ) {
610 int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
611 if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
612 sh4r.mac = 0x000000017FFFFFFFLL;
613 } else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
614 sh4r.mac = 0x0000000180000000LL;
615 } else {
616 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
617 ((uint32_t)(sh4r.mac + stmp));
618 }
619 } else {
620 sh4r.mac += SIGNEXT32(stmp);
621 }
622 :}
623 MAC.L @Rm+, @Rn+ {:
624 CHECKRALIGN32( sh4r.r[Rm] );
625 CHECKRALIGN32( sh4r.r[Rn] );
626 int64_t tmpl = SIGNEXT32(MEM_READ_LONG(sh4r.r[Rn]));
627 sh4r.r[Rn] += 4;
628 tmpl = tmpl * SIGNEXT32(MEM_READ_LONG(sh4r.r[Rm])) + sh4r.mac;
629 sh4r.r[Rm] += 4;
630 if( sh4r.s ) {
631 /* 48-bit Saturation. Yuch */
632 if( tmpl < (int64_t)0xFFFF800000000000LL )
633 tmpl = 0xFFFF800000000000LL;
634 else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
635 tmpl = 0x00007FFFFFFFFFFFLL;
636 }
637 sh4r.mac = tmpl;
638 :}
639 MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
640 (sh4r.r[Rm] * sh4r.r[Rn]); :}
641 MULU.W Rm, Rn {:
642 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
643 (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
644 :}
645 MULS.W Rm, Rn {:
646 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
647 (uint32_t)(SIGNEXT32(sh4r.r[Rm]&0xFFFF) * SIGNEXT32(sh4r.r[Rn]&0xFFFF));
648 :}
649 NEGC Rm, Rn {:
650 tmp = 0 - sh4r.r[Rm];
651 sh4r.r[Rn] = tmp - sh4r.t;
652 sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
653 :}
654 NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
655 SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
656 SUBC Rm, Rn {:
657 tmp = sh4r.r[Rn];
658 sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
659 sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
660 :}
662 BRAF Rn {:
663 CHECKSLOTILLEGAL();
664 CHECKDEST( pc + 4 + sh4r.r[Rn] );
665 sh4r.in_delay_slot = 1;
666 sh4r.pc = sh4r.new_pc;
667 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
668 return TRUE;
669 :}
670 BSRF Rn {:
671 CHECKSLOTILLEGAL();
672 CHECKDEST( pc + 4 + sh4r.r[Rn] );
673 sh4r.in_delay_slot = 1;
674 sh4r.pr = sh4r.pc + 4;
675 sh4r.pc = sh4r.new_pc;
676 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
677 TRACE_CALL( pc, sh4r.new_pc );
678 return TRUE;
679 :}
680 BT disp {:
681 CHECKSLOTILLEGAL();
682 if( sh4r.t ) {
683 CHECKDEST( sh4r.pc + disp + 4 )
684 sh4r.pc += disp + 4;
685 sh4r.new_pc = sh4r.pc + 2;
686 return TRUE;
687 }
688 :}
689 BF disp {:
690 CHECKSLOTILLEGAL();
691 if( !sh4r.t ) {
692 CHECKDEST( sh4r.pc + disp + 4 )
693 sh4r.pc += disp + 4;
694 sh4r.new_pc = sh4r.pc + 2;
695 return TRUE;
696 }
697 :}
698 BT/S disp {:
699 CHECKSLOTILLEGAL();
700 if( sh4r.t ) {
701 CHECKDEST( sh4r.pc + disp + 4 )
702 sh4r.in_delay_slot = 1;
703 sh4r.pc = sh4r.new_pc;
704 sh4r.new_pc = pc + disp + 4;
705 sh4r.in_delay_slot = 1;
706 return TRUE;
707 }
708 :}
709 BF/S disp {:
710 CHECKSLOTILLEGAL();
711 if( !sh4r.t ) {
712 CHECKDEST( sh4r.pc + disp + 4 )
713 sh4r.in_delay_slot = 1;
714 sh4r.pc = sh4r.new_pc;
715 sh4r.new_pc = pc + disp + 4;
716 return TRUE;
717 }
718 :}
719 BRA disp {:
720 CHECKSLOTILLEGAL();
721 CHECKDEST( sh4r.pc + disp + 4 );
722 sh4r.in_delay_slot = 1;
723 sh4r.pc = sh4r.new_pc;
724 sh4r.new_pc = pc + 4 + disp;
725 return TRUE;
726 :}
727 BSR disp {:
728 CHECKDEST( sh4r.pc + disp + 4 );
729 CHECKSLOTILLEGAL();
730 sh4r.in_delay_slot = 1;
731 sh4r.pr = pc + 4;
732 sh4r.pc = sh4r.new_pc;
733 sh4r.new_pc = pc + 4 + disp;
734 TRACE_CALL( pc, sh4r.new_pc );
735 return TRUE;
736 :}
737 TRAPA #imm {:
738 CHECKSLOTILLEGAL();
739 MMIO_WRITE( MMU, TRA, imm<<2 );
740 sh4r.pc += 2;
741 sh4_raise_exception( EXC_TRAP );
742 :}
743 RTS {:
744 CHECKSLOTILLEGAL();
745 CHECKDEST( sh4r.pr );
746 sh4r.in_delay_slot = 1;
747 sh4r.pc = sh4r.new_pc;
748 sh4r.new_pc = sh4r.pr;
749 TRACE_RETURN( pc, sh4r.new_pc );
750 return TRUE;
751 :}
752 SLEEP {:
753 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
754 sh4r.sh4_state = SH4_STATE_STANDBY;
755 } else {
756 sh4r.sh4_state = SH4_STATE_SLEEP;
757 }
758 return FALSE; /* Halt CPU */
759 :}
760 RTE {:
761 CHECKPRIV();
762 CHECKDEST( sh4r.spc );
763 CHECKSLOTILLEGAL();
764 sh4r.in_delay_slot = 1;
765 sh4r.pc = sh4r.new_pc;
766 sh4r.new_pc = sh4r.spc;
767 sh4_write_sr( sh4r.ssr );
768 return TRUE;
769 :}
770 JMP @Rn {:
771 CHECKDEST( sh4r.r[Rn] );
772 CHECKSLOTILLEGAL();
773 sh4r.in_delay_slot = 1;
774 sh4r.pc = sh4r.new_pc;
775 sh4r.new_pc = sh4r.r[Rn];
776 return TRUE;
777 :}
778 JSR @Rn {:
779 CHECKDEST( sh4r.r[Rn] );
780 CHECKSLOTILLEGAL();
781 sh4r.in_delay_slot = 1;
782 sh4r.pc = sh4r.new_pc;
783 sh4r.new_pc = sh4r.r[Rn];
784 sh4r.pr = pc + 4;
785 TRACE_CALL( pc, sh4r.new_pc );
786 return TRUE;
787 :}
788 STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
789 STS.L MACH, @-Rn {:
790 sh4r.r[Rn] -= 4;
791 CHECKWALIGN32( sh4r.r[Rn] );
792 MEM_WRITE_LONG( sh4r.r[Rn], (sh4r.mac>>32) );
793 :}
794 STC.L SR, @-Rn {:
795 CHECKPRIV();
796 sh4r.r[Rn] -= 4;
797 CHECKWALIGN32( sh4r.r[Rn] );
798 MEM_WRITE_LONG( sh4r.r[Rn], sh4_read_sr() );
799 :}
800 LDS.L @Rm+, MACH {:
801 CHECKRALIGN32( sh4r.r[Rm] );
802 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
803 (((uint64_t)MEM_READ_LONG(sh4r.r[Rm]))<<32);
804 sh4r.r[Rm] += 4;
805 :}
806 LDC.L @Rm+, SR {:
807 CHECKSLOTILLEGAL();
808 CHECKPRIV();
809 CHECKWALIGN32( sh4r.r[Rm] );
810 sh4_write_sr( MEM_READ_LONG(sh4r.r[Rm]) );
811 sh4r.r[Rm] +=4;
812 :}
813 LDS Rm, MACH {:
814 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
815 (((uint64_t)sh4r.r[Rm])<<32);
816 :}
817 LDC Rm, SR {:
818 CHECKSLOTILLEGAL();
819 CHECKPRIV();
820 sh4_write_sr( sh4r.r[Rm] );
821 :}
822 LDC Rm, SGR {:
823 CHECKPRIV();
824 sh4r.sgr = sh4r.r[Rm];
825 :}
826 LDC.L @Rm+, SGR {:
827 CHECKPRIV();
828 CHECKRALIGN32( sh4r.r[Rm] );
829 sh4r.sgr = MEM_READ_LONG(sh4r.r[Rm]);
830 sh4r.r[Rm] +=4;
831 :}
832 STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
833 STS.L MACL, @-Rn {:
834 sh4r.r[Rn] -= 4;
835 CHECKWALIGN32( sh4r.r[Rn] );
836 MEM_WRITE_LONG( sh4r.r[Rn], (uint32_t)sh4r.mac );
837 :}
838 STC.L GBR, @-Rn {:
839 sh4r.r[Rn] -= 4;
840 CHECKWALIGN32( sh4r.r[Rn] );
841 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.gbr );
842 :}
843 LDS.L @Rm+, MACL {:
844 CHECKRALIGN32( sh4r.r[Rm] );
845 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
846 (uint64_t)((uint32_t)MEM_READ_LONG(sh4r.r[Rm]));
847 sh4r.r[Rm] += 4;
848 :}
849 LDC.L @Rm+, GBR {:
850 CHECKRALIGN32( sh4r.r[Rm] );
851 sh4r.gbr = MEM_READ_LONG(sh4r.r[Rm]);
852 sh4r.r[Rm] +=4;
853 :}
854 LDS Rm, MACL {:
855 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
856 (uint64_t)((uint32_t)(sh4r.r[Rm]));
857 :}
858 LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
859 STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
860 STS.L PR, @-Rn {:
861 sh4r.r[Rn] -= 4;
862 CHECKWALIGN32( sh4r.r[Rn] );
863 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.pr );
864 :}
865 STC.L VBR, @-Rn {:
866 CHECKPRIV();
867 sh4r.r[Rn] -= 4;
868 CHECKWALIGN32( sh4r.r[Rn] );
869 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.vbr );
870 :}
871 LDS.L @Rm+, PR {:
872 CHECKRALIGN32( sh4r.r[Rm] );
873 sh4r.pr = MEM_READ_LONG( sh4r.r[Rm] );
874 sh4r.r[Rm] += 4;
875 :}
876 LDC.L @Rm+, VBR {:
877 CHECKPRIV();
878 CHECKRALIGN32( sh4r.r[Rm] );
879 sh4r.vbr = MEM_READ_LONG(sh4r.r[Rm]);
880 sh4r.r[Rm] +=4;
881 :}
882 LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
883 LDC Rm, VBR {:
884 CHECKPRIV();
885 sh4r.vbr = sh4r.r[Rm];
886 :}
887 STC SGR, Rn {:
888 CHECKPRIV();
889 sh4r.r[Rn] = sh4r.sgr;
890 :}
891 STC.L SGR, @-Rn {:
892 CHECKPRIV();
893 sh4r.r[Rn] -= 4;
894 CHECKWALIGN32( sh4r.r[Rn] );
895 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.sgr );
896 :}
897 STC.L SSR, @-Rn {:
898 CHECKPRIV();
899 sh4r.r[Rn] -= 4;
900 CHECKWALIGN32( sh4r.r[Rn] );
901 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.ssr );
902 :}
903 LDC.L @Rm+, SSR {:
904 CHECKPRIV();
905 CHECKRALIGN32( sh4r.r[Rm] );
906 sh4r.ssr = MEM_READ_LONG(sh4r.r[Rm]);
907 sh4r.r[Rm] +=4;
908 :}
909 LDC Rm, SSR {:
910 CHECKPRIV();
911 sh4r.ssr = sh4r.r[Rm];
912 :}
913 STC.L SPC, @-Rn {:
914 CHECKPRIV();
915 sh4r.r[Rn] -= 4;
916 CHECKWALIGN32( sh4r.r[Rn] );
917 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.spc );
918 :}
919 LDC.L @Rm+, SPC {:
920 CHECKPRIV();
921 CHECKRALIGN32( sh4r.r[Rm] );
922 sh4r.spc = MEM_READ_LONG(sh4r.r[Rm]);
923 sh4r.r[Rm] +=4;
924 :}
925 LDC Rm, SPC {:
926 CHECKPRIV();
927 sh4r.spc = sh4r.r[Rm];
928 :}
929 STS FPUL, Rn {: sh4r.r[Rn] = sh4r.fpul; :}
930 STS.L FPUL, @-Rn {:
931 sh4r.r[Rn] -= 4;
932 CHECKWALIGN32( sh4r.r[Rn] );
933 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.fpul );
934 :}
935 LDS.L @Rm+, FPUL {:
936 CHECKRALIGN32( sh4r.r[Rm] );
937 sh4r.fpul = MEM_READ_LONG(sh4r.r[Rm]);
938 sh4r.r[Rm] +=4;
939 :}
940 LDS Rm, FPUL {: sh4r.fpul = sh4r.r[Rm]; :}
941 STS FPSCR, Rn {: sh4r.r[Rn] = sh4r.fpscr; :}
942 STS.L FPSCR, @-Rn {:
943 sh4r.r[Rn] -= 4;
944 CHECKWALIGN32( sh4r.r[Rn] );
945 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.fpscr );
946 :}
947 LDS.L @Rm+, FPSCR {:
948 CHECKRALIGN32( sh4r.r[Rm] );
949 sh4r.fpscr = MEM_READ_LONG(sh4r.r[Rm]);
950 sh4r.r[Rm] +=4;
951 sh4r.fr_bank = &sh4r.fr[(sh4r.fpscr&FPSCR_FR)>>21][0];
952 :}
953 LDS Rm, FPSCR {:
954 sh4r.fpscr = sh4r.r[Rm];
955 sh4r.fr_bank = &sh4r.fr[(sh4r.fpscr&FPSCR_FR)>>21][0];
956 :}
957 STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
958 STC.L DBR, @-Rn {:
959 CHECKPRIV();
960 sh4r.r[Rn] -= 4;
961 CHECKWALIGN32( sh4r.r[Rn] );
962 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.dbr );
963 :}
964 LDC.L @Rm+, DBR {:
965 CHECKPRIV();
966 CHECKRALIGN32( sh4r.r[Rm] );
967 sh4r.dbr = MEM_READ_LONG(sh4r.r[Rm]);
968 sh4r.r[Rm] +=4;
969 :}
970 LDC Rm, DBR {:
971 CHECKPRIV();
972 sh4r.dbr = sh4r.r[Rm];
973 :}
974 STC.L Rm_BANK, @-Rn {:
975 CHECKPRIV();
976 sh4r.r[Rn] -= 4;
977 CHECKWALIGN32( sh4r.r[Rn] );
978 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r_bank[Rm_BANK] );
979 :}
980 LDC.L @Rm+, Rn_BANK {:
981 CHECKPRIV();
982 CHECKRALIGN32( sh4r.r[Rm] );
983 sh4r.r_bank[Rn_BANK] = MEM_READ_LONG( sh4r.r[Rm] );
984 sh4r.r[Rm] += 4;
985 :}
986 LDC Rm, Rn_BANK {:
987 CHECKPRIV();
988 sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
989 :}
990 STC SR, Rn {:
991 CHECKPRIV();
992 sh4r.r[Rn] = sh4_read_sr();
993 :}
994 STC GBR, Rn {:
995 CHECKPRIV();
996 sh4r.r[Rn] = sh4r.gbr;
997 :}
998 STC VBR, Rn {:
999 CHECKPRIV();
1000 sh4r.r[Rn] = sh4r.vbr;
1001 :}
1002 STC SSR, Rn {:
1003 CHECKPRIV();
1004 sh4r.r[Rn] = sh4r.ssr;
1005 :}
1006 STC SPC, Rn {:
1007 CHECKPRIV();
1008 sh4r.r[Rn] = sh4r.spc;
1009 :}
1010 STC Rm_BANK, Rn {:
1011 CHECKPRIV();
1012 sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
1013 :}
1015 FADD FRm, FRn {:
1016 CHECKFPUEN();
1017 if( IS_FPU_DOUBLEPREC() ) {
1018 DR(FRn) += DR(FRm);
1019 } else {
1020 FR(FRn) += FR(FRm);
1021 }
1022 :}
1023 FSUB FRm, FRn {:
1024 CHECKFPUEN();
1025 if( IS_FPU_DOUBLEPREC() ) {
1026 DR(FRn) -= DR(FRm);
1027 } else {
1028 FR(FRn) -= FR(FRm);
1029 }
1030 :}
1032 FMUL FRm, FRn {:
1033 CHECKFPUEN();
1034 if( IS_FPU_DOUBLEPREC() ) {
1035 DR(FRn) *= DR(FRm);
1036 } else {
1037 FR(FRn) *= FR(FRm);
1038 }
1039 :}
1041 FDIV FRm, FRn {:
1042 CHECKFPUEN();
1043 if( IS_FPU_DOUBLEPREC() ) {
1044 DR(FRn) /= DR(FRm);
1045 } else {
1046 FR(FRn) /= FR(FRm);
1047 }
1048 :}
1050 FCMP/EQ FRm, FRn {:
1051 CHECKFPUEN();
1052 if( IS_FPU_DOUBLEPREC() ) {
1053 sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
1054 } else {
1055 sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
1056 }
1057 :}
1059 FCMP/GT FRm, FRn {:
1060 CHECKFPUEN();
1061 if( IS_FPU_DOUBLEPREC() ) {
1062 sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
1063 } else {
1064 sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
1065 }
1066 :}
1068 FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
1069 FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
1070 FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
1071 FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
1072 FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
1073 FMOV FRm, @-Rn {: sh4r.r[Rn] -= FP_WIDTH; MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
1074 FMOV FRm, FRn {:
1075 if( IS_FPU_DOUBLESIZE() )
1076 DR(FRn) = DR(FRm);
1077 else
1078 FR(FRn) = FR(FRm);
1079 :}
1080 FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
1081 FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
1082 FLOAT FPUL, FRn {:
1083 CHECKFPUEN();
1084 if( IS_FPU_DOUBLEPREC() ) {
1085 if( FRn&1 ) { // No, really...
1086 dtmp = (double)FPULi;
1087 FR(FRn) = *(((float *)&dtmp)+1);
1088 } else {
1089 DRF(FRn>>1) = (double)FPULi;
1090 }
1091 } else {
1092 FR(FRn) = (float)FPULi;
1093 }
1094 :}
1095 FTRC FRm, FPUL {:
1096 CHECKFPUEN();
1097 if( IS_FPU_DOUBLEPREC() ) {
1098 if( FRm&1 ) {
1099 dtmp = 0;
1100 *(((float *)&dtmp)+1) = FR(FRm);
1101 } else {
1102 dtmp = DRF(FRm>>1);
1103 }
1104 if( dtmp >= MAX_INTF )
1105 FPULi = MAX_INT;
1106 else if( dtmp <= MIN_INTF )
1107 FPULi = MIN_INT;
1108 else
1109 FPULi = (int32_t)dtmp;
1110 } else {
1111 ftmp = FR(FRm);
1112 if( ftmp >= MAX_INTF )
1113 FPULi = MAX_INT;
1114 else if( ftmp <= MIN_INTF )
1115 FPULi = MIN_INT;
1116 else
1117 FPULi = (int32_t)ftmp;
1118 }
1119 :}
1120 FNEG FRn {:
1121 CHECKFPUEN();
1122 if( IS_FPU_DOUBLEPREC() ) {
1123 DR(FRn) = -DR(FRn);
1124 } else {
1125 FR(FRn) = -FR(FRn);
1126 }
1127 :}
1128 FABS FRn {:
1129 CHECKFPUEN();
1130 if( IS_FPU_DOUBLEPREC() ) {
1131 DR(FRn) = fabs(DR(FRn));
1132 } else {
1133 FR(FRn) = fabsf(FR(FRn));
1134 }
1135 :}
1136 FSQRT FRn {:
1137 CHECKFPUEN();
1138 if( IS_FPU_DOUBLEPREC() ) {
1139 DR(FRn) = sqrt(DR(FRn));
1140 } else {
1141 FR(FRn) = sqrtf(FR(FRn));
1142 }
1143 :}
1144 FLDI0 FRn {:
1145 CHECKFPUEN();
1146 if( IS_FPU_DOUBLEPREC() ) {
1147 DR(FRn) = 0.0;
1148 } else {
1149 FR(FRn) = 0.0;
1150 }
1151 :}
1152 FLDI1 FRn {:
1153 CHECKFPUEN();
1154 if( IS_FPU_DOUBLEPREC() ) {
1155 DR(FRn) = 1.0;
1156 } else {
1157 FR(FRn) = 1.0;
1158 }
1159 :}
1160 FMAC FR0, FRm, FRn {:
1161 CHECKFPUEN();
1162 if( IS_FPU_DOUBLEPREC() ) {
1163 DR(FRn) += DR(FRm)*DR(0);
1164 } else {
1165 FR(FRn) += FR(FRm)*FR(0);
1166 }
1167 :}
1168 FRCHG {:
1169 CHECKFPUEN();
1170 sh4r.fpscr ^= FPSCR_FR;
1171 sh4r.fr_bank = &sh4r.fr[(sh4r.fpscr&FPSCR_FR)>>21][0];
1172 :}
1173 FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
1174 FCNVSD FPUL, FRn {:
1175 CHECKFPUEN();
1176 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1177 DR(FRn) = (double)FPULf;
1178 }
1179 :}
1180 FCNVDS FRm, FPUL {:
1181 CHECKFPUEN();
1182 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1183 FPULf = (float)DR(FRm);
1184 }
1185 :}
1187 FSRRA FRn {:
1188 CHECKFPUEN();
1189 if( !IS_FPU_DOUBLEPREC() ) {
1190 FR(FRn) = 1.0/sqrtf(FR(FRn));
1191 }
1192 :}
1193 FIPR FVm, FVn {:
1194 CHECKFPUEN();
1195 if( !IS_FPU_DOUBLEPREC() ) {
1196 int tmp2 = FVn<<2;
1197 tmp = FVm<<2;
1198 FR(tmp2+3) = FR(tmp)*FR(tmp2) +
1199 FR(tmp+1)*FR(tmp2+1) +
1200 FR(tmp+2)*FR(tmp2+2) +
1201 FR(tmp+3)*FR(tmp2+3);
1202 }
1203 :}
1204 FSCA FPUL, FRn {:
1205 CHECKFPUEN();
1206 if( !IS_FPU_DOUBLEPREC() ) {
1207 float angle = (((float)(FPULi&0xFFFF))/65536.0) * 2 * M_PI;
1208 FR(FRn) = sinf(angle);
1209 FR((FRn)+1) = cosf(angle);
1210 }
1211 :}
1212 FTRV XMTRX, FVn {:
1213 CHECKFPUEN();
1214 if( !IS_FPU_DOUBLEPREC() ) {
1215 tmp = FVn<<2;
1216 float *xf = &sh4r.fr[((~sh4r.fpscr)&FPSCR_FR)>>21][0];
1217 float fv[4] = { FR(tmp), FR(tmp+1), FR(tmp+2), FR(tmp+3) };
1218 FR(tmp) = xf[1] * fv[0] + xf[5]*fv[1] +
1219 xf[9]*fv[2] + xf[13]*fv[3];
1220 FR(tmp+1) = xf[0] * fv[0] + xf[4]*fv[1] +
1221 xf[8]*fv[2] + xf[12]*fv[3];
1222 FR(tmp+2) = xf[3] * fv[0] + xf[7]*fv[1] +
1223 xf[11]*fv[2] + xf[15]*fv[3];
1224 FR(tmp+3) = xf[2] * fv[0] + xf[6]*fv[1] +
1225 xf[10]*fv[2] + xf[14]*fv[3];
1226 }
1227 :}
1228 UNDEF {:
1229 UNDEF(ir);
1230 :}
1231 %%
1232 sh4r.pc = sh4r.new_pc;
1233 sh4r.new_pc += 2;
1234 sh4r.in_delay_slot = 0;
1235 return TRUE;
1236 }
.