filename | src/sh4/sh4core.in |
changeset | 359:c588dce7ebde |
next | 367:9c52dcbad3fb |
author | nkeynes |
date | Thu Aug 23 12:33:27 2007 +0000 (13 years ago) |
permissions | -rw-r--r-- |
last change | Commit decoder generator Translator work in progress Fix mac.l, mac.w in emu core |
file | annotate | diff | log | raw |
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +00001.2 +++ b/src/sh4/sh4core.in Thu Aug 23 12:33:27 2007 +00001.3 @@ -0,0 +1,1340 @@1.4 +/**1.5 + * $Id: sh4core.in,v 1.1 2007-08-23 12:33:27 nkeynes Exp $1.6 + *1.7 + * SH4 emulation core, and parent module for all the SH4 peripheral1.8 + * modules.1.9 + *1.10 + * Copyright (c) 2005 Nathan Keynes.1.11 + *1.12 + * This program is free software; you can redistribute it and/or modify1.13 + * it under the terms of the GNU General Public License as published by1.14 + * the Free Software Foundation; either version 2 of the License, or1.15 + * (at your option) any later version.1.16 + *1.17 + * This program is distributed in the hope that it will be useful,1.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of1.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1.20 + * GNU General Public License for more details.1.21 + */1.22 +1.23 +#define MODULE sh4_module1.24 +#include <math.h>1.25 +#include "dream.h"1.26 +#include "sh4/sh4core.h"1.27 +#include "sh4/sh4mmio.h"1.28 +#include "sh4/intc.h"1.29 +#include "mem.h"1.30 +#include "clock.h"1.31 +#include "syscall.h"1.32 +1.33 +#define SH4_CALLTRACE 11.34 +1.35 +#define MAX_INT 0x7FFFFFFF1.36 +#define MIN_INT 0x800000001.37 +#define MAX_INTF 2147483647.01.38 +#define MIN_INTF -2147483648.01.39 +1.40 +/* CPU-generated exception code/vector pairs */1.41 +#define EXC_POWER_RESET 0x000 /* vector special */1.42 +#define EXC_MANUAL_RESET 0x0201.43 +#define EXC_READ_ADDR_ERR 0x0E01.44 +#define EXC_WRITE_ADDR_ERR 0x1001.45 +#define EXC_SLOT_ILLEGAL 0x1A01.46 +#define EXC_ILLEGAL 0x1801.47 +#define EXC_TRAP 0x1601.48 +#define EXC_FPDISABLE 0x8001.49 +#define EXC_SLOT_FPDISABLE 0x8201.50 +1.51 +#define EXV_EXCEPTION 0x100 /* General exception vector */1.52 +#define EXV_TLBMISS 0x400 /* TLB-miss exception vector */1.53 +#define EXV_INTERRUPT 0x600 /* External interrupt vector */1.54 +1.55 +/********************** SH4 Module Definition ****************************/1.56 +1.57 +void sh4_init( void );1.58 +void sh4_reset( void );1.59 +uint32_t sh4_run_slice( uint32_t );1.60 +void sh4_start( void );1.61 +void sh4_stop( void );1.62 +void sh4_save_state( FILE *f );1.63 +int sh4_load_state( FILE *f );1.64 +void sh4_accept_interrupt( void );1.65 +1.66 +struct dreamcast_module sh4_module = { "SH4", sh4_init, sh4_reset,1.67 + NULL, sh4_run_slice, sh4_stop,1.68 + sh4_save_state, sh4_load_state };1.69 +1.70 +struct sh4_registers sh4r;1.71 +1.72 +void sh4_init(void)1.73 +{1.74 + register_io_regions( mmio_list_sh4mmio );1.75 + MMU_init();1.76 + sh4_reset();1.77 +}1.78 +1.79 +void sh4_reset(void)1.80 +{1.81 + /* zero everything out, for the sake of having a consistent state. */1.82 + memset( &sh4r, 0, sizeof(sh4r) );1.83 +1.84 + /* Resume running if we were halted */1.85 + sh4r.sh4_state = SH4_STATE_RUNNING;1.86 +1.87 + sh4r.pc = 0xA0000000;1.88 + sh4r.new_pc= 0xA0000002;1.89 + sh4r.vbr = 0x00000000;1.90 + sh4r.fpscr = 0x00040001;1.91 + sh4r.sr = 0x700000F0;1.92 +1.93 + /* Mem reset will do this, but if we want to reset _just_ the SH4... */1.94 + MMIO_WRITE( MMU, EXPEVT, EXC_POWER_RESET );1.95 +1.96 + /* Peripheral modules */1.97 + CPG_reset();1.98 + INTC_reset();1.99 + MMU_reset();1.100 + TMU_reset();1.101 + SCIF_reset();1.102 +}1.103 +1.104 +static struct breakpoint_struct sh4_breakpoints[MAX_BREAKPOINTS];1.105 +static int sh4_breakpoint_count = 0;1.106 +static uint16_t *sh4_icache = NULL;1.107 +static uint32_t sh4_icache_addr = 0;1.108 +1.109 +void sh4_set_breakpoint( uint32_t pc, int type )1.110 +{1.111 + sh4_breakpoints[sh4_breakpoint_count].address = pc;1.112 + sh4_breakpoints[sh4_breakpoint_count].type = type;1.113 + sh4_breakpoint_count++;1.114 +}1.115 +1.116 +gboolean sh4_clear_breakpoint( uint32_t pc, int type )1.117 +{1.118 + int i;1.119 +1.120 + for( i=0; i<sh4_breakpoint_count; i++ ) {1.121 + if( sh4_breakpoints[i].address == pc &&1.122 + sh4_breakpoints[i].type == type ) {1.123 + while( ++i < sh4_breakpoint_count ) {1.124 + sh4_breakpoints[i-1].address = sh4_breakpoints[i].address;1.125 + sh4_breakpoints[i-1].type = sh4_breakpoints[i].type;1.126 + }1.127 + sh4_breakpoint_count--;1.128 + return TRUE;1.129 + }1.130 + }1.131 + return FALSE;1.132 +}1.133 +1.134 +int sh4_get_breakpoint( uint32_t pc )1.135 +{1.136 + int i;1.137 + for( i=0; i<sh4_breakpoint_count; i++ ) {1.138 + if( sh4_breakpoints[i].address == pc )1.139 + return sh4_breakpoints[i].type;1.140 + }1.141 + return 0;1.142 +}1.143 +1.144 +uint32_t sh4_run_slice( uint32_t nanosecs )1.145 +{1.146 + int i;1.147 + sh4r.slice_cycle = 0;1.148 +1.149 + if( sh4r.sh4_state != SH4_STATE_RUNNING ) {1.150 + if( sh4r.event_pending < nanosecs ) {1.151 + sh4r.sh4_state = SH4_STATE_RUNNING;1.152 + sh4r.slice_cycle = sh4r.event_pending;1.153 + }1.154 + }1.155 +1.156 + if( sh4_breakpoint_count == 0 ) {1.157 + for( ; sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {1.158 + if( SH4_EVENT_PENDING() ) {1.159 + if( sh4r.event_types & PENDING_EVENT ) {1.160 + event_execute();1.161 + }1.162 + /* Eventq execute may (quite likely) deliver an immediate IRQ */1.163 + if( sh4r.event_types & PENDING_IRQ ) {1.164 + sh4_accept_interrupt();1.165 + }1.166 + }1.167 + if( !sh4_execute_instruction() ) {1.168 + break;1.169 + }1.170 + }1.171 + } else {1.172 + for( ;sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {1.173 + if( SH4_EVENT_PENDING() ) {1.174 + if( sh4r.event_types & PENDING_EVENT ) {1.175 + event_execute();1.176 + }1.177 + /* Eventq execute may (quite likely) deliver an immediate IRQ */1.178 + if( sh4r.event_types & PENDING_IRQ ) {1.179 + sh4_accept_interrupt();1.180 + }1.181 + }1.182 +1.183 + if( !sh4_execute_instruction() )1.184 + break;1.185 +#ifdef ENABLE_DEBUG_MODE1.186 + for( i=0; i<sh4_breakpoint_count; i++ ) {1.187 + if( sh4_breakpoints[i].address == sh4r.pc ) {1.188 + break;1.189 + }1.190 + }1.191 + if( i != sh4_breakpoint_count ) {1.192 + dreamcast_stop();1.193 + if( sh4_breakpoints[i].type == BREAK_ONESHOT )1.194 + sh4_clear_breakpoint( sh4r.pc, BREAK_ONESHOT );1.195 + break;1.196 + }1.197 +#endif1.198 + }1.199 + }1.200 +1.201 + /* If we aborted early, but the cpu is still technically running,1.202 + * we're doing a hard abort - cut the timeslice back to what we1.203 + * actually executed1.204 + */1.205 + if( sh4r.slice_cycle != nanosecs && sh4r.sh4_state == SH4_STATE_RUNNING ) {1.206 + nanosecs = sh4r.slice_cycle;1.207 + }1.208 + if( sh4r.sh4_state != SH4_STATE_STANDBY ) {1.209 + TMU_run_slice( nanosecs );1.210 + SCIF_run_slice( nanosecs );1.211 + }1.212 + return nanosecs;1.213 +}1.214 +1.215 +void sh4_stop(void)1.216 +{1.217 +1.218 +}1.219 +1.220 +void sh4_save_state( FILE *f )1.221 +{1.222 + fwrite( &sh4r, sizeof(sh4r), 1, f );1.223 + MMU_save_state( f );1.224 + INTC_save_state( f );1.225 + TMU_save_state( f );1.226 + SCIF_save_state( f );1.227 +}1.228 +1.229 +int sh4_load_state( FILE * f )1.230 +{1.231 + fread( &sh4r, sizeof(sh4r), 1, f );1.232 + MMU_load_state( f );1.233 + INTC_load_state( f );1.234 + TMU_load_state( f );1.235 + return SCIF_load_state( f );1.236 +}1.237 +1.238 +/********************** SH4 emulation core ****************************/1.239 +1.240 +void sh4_set_pc( int pc )1.241 +{1.242 + sh4r.pc = pc;1.243 + sh4r.new_pc = pc+2;1.244 +}1.245 +1.246 +#define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)1.247 +#define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); dreamcast_stop(); return FALSE; }while(0)1.248 +1.249 +#if(SH4_CALLTRACE == 1)1.250 +#define MAX_CALLSTACK 321.251 +static struct call_stack {1.252 + sh4addr_t call_addr;1.253 + sh4addr_t target_addr;1.254 + sh4addr_t stack_pointer;1.255 +} call_stack[MAX_CALLSTACK];1.256 +1.257 +static int call_stack_depth = 0;1.258 +int sh4_call_trace_on = 0;1.259 +1.260 +static inline trace_call( sh4addr_t source, sh4addr_t dest )1.261 +{1.262 + if( call_stack_depth < MAX_CALLSTACK ) {1.263 + call_stack[call_stack_depth].call_addr = source;1.264 + call_stack[call_stack_depth].target_addr = dest;1.265 + call_stack[call_stack_depth].stack_pointer = sh4r.r[15];1.266 + }1.267 + call_stack_depth++;1.268 +}1.269 +1.270 +static inline trace_return( sh4addr_t source, sh4addr_t dest )1.271 +{1.272 + if( call_stack_depth > 0 ) {1.273 + call_stack_depth--;1.274 + }1.275 +}1.276 +1.277 +void fprint_stack_trace( FILE *f )1.278 +{1.279 + int i = call_stack_depth -1;1.280 + if( i >= MAX_CALLSTACK )1.281 + i = MAX_CALLSTACK - 1;1.282 + for( ; i >= 0; i-- ) {1.283 + fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n",1.284 + (call_stack_depth - i), call_stack[i].call_addr,1.285 + call_stack[i].target_addr, call_stack[i].stack_pointer );1.286 + }1.287 +}1.288 +1.289 +#define TRACE_CALL( source, dest ) trace_call(source, dest)1.290 +#define TRACE_RETURN( source, dest ) trace_return(source, dest)1.291 +#else1.292 +#define TRACE_CALL( dest, rts )1.293 +#define TRACE_RETURN( source, dest )1.294 +#endif1.295 +1.296 +#define RAISE( x, v ) do{ \1.297 + if( sh4r.vbr == 0 ) { \1.298 + ERROR( "%08X: VBR not initialized while raising exception %03X, halting", sh4r.pc, x ); \1.299 + dreamcast_stop(); return FALSE; \1.300 + } else { \1.301 + sh4r.spc = sh4r.pc; \1.302 + sh4r.ssr = sh4_read_sr(); \1.303 + sh4r.sgr = sh4r.r[15]; \1.304 + MMIO_WRITE(MMU,EXPEVT,x); \1.305 + sh4r.pc = sh4r.vbr + v; \1.306 + sh4r.new_pc = sh4r.pc + 2; \1.307 + sh4_load_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \1.308 + if( sh4r.in_delay_slot ) { \1.309 + sh4r.in_delay_slot = 0; \1.310 + sh4r.spc -= 2; \1.311 + } \1.312 + } \1.313 + return TRUE; } while(0)1.314 +1.315 +#define MEM_READ_BYTE( addr ) sh4_read_byte(addr)1.316 +#define MEM_READ_WORD( addr ) sh4_read_word(addr)1.317 +#define MEM_READ_LONG( addr ) sh4_read_long(addr)1.318 +#define MEM_WRITE_BYTE( addr, val ) sh4_write_byte(addr, val)1.319 +#define MEM_WRITE_WORD( addr, val ) sh4_write_word(addr, val)1.320 +#define MEM_WRITE_LONG( addr, val ) sh4_write_long(addr, val)1.321 +1.322 +#define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)1.323 +1.324 +#define MEM_FP_READ( addr, reg ) sh4_read_float( addr, reg );1.325 +#define MEM_FP_WRITE( addr, reg ) sh4_write_float( addr, reg );1.326 +1.327 +#define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL )1.328 +#define CHECKRALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_READ_ADDR_ERR )1.329 +#define CHECKRALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_READ_ADDR_ERR )1.330 +#define CHECKWALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_WRITE_ADDR_ERR )1.331 +#define CHECKWALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_WRITE_ADDR_ERR )1.332 +1.333 +#define CHECKFPUEN() if( !IS_FPU_ENABLED() ) { if( ir == 0xFFFD ) { UNDEF(ir); } else { return sh4_raise_slot_exception( EXC_FPDISABLE, EXC_SLOT_FPDISABLE ); } }1.334 +#define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); dreamcast_stop(); return FALSE; }1.335 +#define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) return sh4_raise_exception(EXC_SLOT_ILLEGAL)1.336 +1.337 +static void sh4_switch_banks( )1.338 +{1.339 + uint32_t tmp[8];1.340 +1.341 + memcpy( tmp, sh4r.r, sizeof(uint32_t)*8 );1.342 + memcpy( sh4r.r, sh4r.r_bank, sizeof(uint32_t)*8 );1.343 + memcpy( sh4r.r_bank, tmp, sizeof(uint32_t)*8 );1.344 +}1.345 +1.346 +static void sh4_load_sr( uint32_t newval )1.347 +{1.348 + if( (newval ^ sh4r.sr) & SR_RB )1.349 + sh4_switch_banks();1.350 + sh4r.sr = newval;1.351 + sh4r.t = (newval&SR_T) ? 1 : 0;1.352 + sh4r.s = (newval&SR_S) ? 1 : 0;1.353 + sh4r.m = (newval&SR_M) ? 1 : 0;1.354 + sh4r.q = (newval&SR_Q) ? 1 : 0;1.355 + intc_mask_changed();1.356 +}1.357 +1.358 +static void sh4_write_float( uint32_t addr, int reg )1.359 +{1.360 + if( IS_FPU_DOUBLESIZE() ) {1.361 + if( reg & 1 ) {1.362 + sh4_write_long( addr, *((uint32_t *)&XF((reg)&0x0E)) );1.363 + sh4_write_long( addr+4, *((uint32_t *)&XF(reg)) );1.364 + } else {1.365 + sh4_write_long( addr, *((uint32_t *)&FR(reg)) );1.366 + sh4_write_long( addr+4, *((uint32_t *)&FR((reg)|0x01)) );1.367 + }1.368 + } else {1.369 + sh4_write_long( addr, *((uint32_t *)&FR((reg))) );1.370 + }1.371 +}1.372 +1.373 +static void sh4_read_float( uint32_t addr, int reg )1.374 +{1.375 + if( IS_FPU_DOUBLESIZE() ) {1.376 + if( reg & 1 ) {1.377 + *((uint32_t *)&XF((reg) & 0x0E)) = sh4_read_long(addr);1.378 + *((uint32_t *)&XF(reg)) = sh4_read_long(addr+4);1.379 + } else {1.380 + *((uint32_t *)&FR(reg)) = sh4_read_long(addr);1.381 + *((uint32_t *)&FR((reg) | 0x01)) = sh4_read_long(addr+4);1.382 + }1.383 + } else {1.384 + *((uint32_t *)&FR(reg)) = sh4_read_long(addr);1.385 + }1.386 +}1.387 +1.388 +static uint32_t sh4_read_sr( void )1.389 +{1.390 + /* synchronize sh4r.sr with the various bitflags */1.391 + sh4r.sr &= SR_MQSTMASK;1.392 + if( sh4r.t ) sh4r.sr |= SR_T;1.393 + if( sh4r.s ) sh4r.sr |= SR_S;1.394 + if( sh4r.m ) sh4r.sr |= SR_M;1.395 + if( sh4r.q ) sh4r.sr |= SR_Q;1.396 + return sh4r.sr;1.397 +}1.398 +1.399 +/**1.400 + * Raise a general CPU exception for the specified exception code.1.401 + * (NOT for TRAPA or TLB exceptions)1.402 + */1.403 +gboolean sh4_raise_exception( int code )1.404 +{1.405 + RAISE( code, EXV_EXCEPTION );1.406 +}1.407 +1.408 +gboolean sh4_raise_slot_exception( int normal_code, int slot_code ) {1.409 + if( sh4r.in_delay_slot ) {1.410 + return sh4_raise_exception(slot_code);1.411 + } else {1.412 + return sh4_raise_exception(normal_code);1.413 + }1.414 +}1.415 +1.416 +gboolean sh4_raise_tlb_exception( int code )1.417 +{1.418 + RAISE( code, EXV_TLBMISS );1.419 +}1.420 +1.421 +void sh4_accept_interrupt( void )1.422 +{1.423 + uint32_t code = intc_accept_interrupt();1.424 + sh4r.ssr = sh4_read_sr();1.425 + sh4r.spc = sh4r.pc;1.426 + sh4r.sgr = sh4r.r[15];1.427 + sh4_load_sr( sh4r.ssr|SR_BL|SR_MD|SR_RB );1.428 + MMIO_WRITE( MMU, INTEVT, code );1.429 + sh4r.pc = sh4r.vbr + 0x600;1.430 + sh4r.new_pc = sh4r.pc + 2;1.431 + // WARN( "Accepting interrupt %03X, from %08X => %08X", code, sh4r.spc, sh4r.pc );1.432 +}1.433 +1.434 +gboolean sh4_execute_instruction( void )1.435 +{1.436 + uint32_t pc;1.437 + unsigned short ir;1.438 + uint32_t tmp;1.439 + float ftmp;1.440 + double dtmp;1.441 +1.442 +#define R0 sh4r.r[0]1.443 + pc = sh4r.pc;1.444 + if( pc > 0xFFFFFF00 ) {1.445 + /* SYSCALL Magic */1.446 + syscall_invoke( pc );1.447 + sh4r.in_delay_slot = 0;1.448 + pc = sh4r.pc = sh4r.pr;1.449 + sh4r.new_pc = sh4r.pc + 2;1.450 + }1.451 + CHECKRALIGN16(pc);1.452 +1.453 + /* Read instruction */1.454 + uint32_t pageaddr = pc >> 12;1.455 + if( sh4_icache != NULL && pageaddr == sh4_icache_addr ) {1.456 + ir = sh4_icache[(pc&0xFFF)>>1];1.457 + } else {1.458 + sh4_icache = (uint16_t *)mem_get_page(pc);1.459 + if( ((uint32_t)sh4_icache) < MAX_IO_REGIONS ) {1.460 + /* If someone's actually been so daft as to try to execute out of an IO1.461 + * region, fallback on the full-blown memory read1.462 + */1.463 + sh4_icache = NULL;1.464 + ir = MEM_READ_WORD(pc);1.465 + } else {1.466 + sh4_icache_addr = pageaddr;1.467 + ir = sh4_icache[(pc&0xFFF)>>1];1.468 + }1.469 + }1.470 +%%1.471 +AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}1.472 +AND #imm, R0 {: R0 &= imm; :}1.473 +AND.B #imm, @(R0, GBR) {: MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & MEM_READ_BYTE(R0 + sh4r.gbr) ); :}1.474 +NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}1.475 +OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}1.476 +OR #imm, R0 {: R0 |= imm; :}1.477 +OR.B #imm, @(R0, GBR) {: MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | MEM_READ_BYTE(R0 + sh4r.gbr) ); :}1.478 +TAS.B @Rn {:1.479 + tmp = MEM_READ_BYTE( sh4r.r[Rn] );1.480 + sh4r.t = ( tmp == 0 ? 1 : 0 );1.481 + MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );1.482 +:}1.483 +TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}1.484 +TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}1.485 +TST.B #imm, @(R0, GBR) {: sh4r.t = ( MEM_READ_BYTE(R0 + sh4r.gbr) & imm ? 0 : 1 ); :}1.486 +XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}1.487 +XOR #imm, R0 {: R0 ^= imm; :}1.488 +XOR.B #imm, @(R0, GBR) {: MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ MEM_READ_BYTE(R0 + sh4r.gbr) ); :}1.489 +XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}1.490 +1.491 +ROTL Rn {:1.492 + sh4r.t = sh4r.r[Rn] >> 31;1.493 + sh4r.r[Rn] <<= 1;1.494 + sh4r.r[Rn] |= sh4r.t;1.495 +:}1.496 +ROTR Rn {:1.497 + sh4r.t = sh4r.r[Rn] & 0x00000001;1.498 + sh4r.r[Rn] >>= 1;1.499 + sh4r.r[Rn] |= (sh4r.t << 31);1.500 +:}1.501 +ROTCL Rn {:1.502 + tmp = sh4r.r[Rn] >> 31;1.503 + sh4r.r[Rn] <<= 1;1.504 + sh4r.r[Rn] |= sh4r.t;1.505 + sh4r.t = tmp;1.506 +:}1.507 +ROTCR Rn {:1.508 + tmp = sh4r.r[Rn] & 0x00000001;1.509 + sh4r.r[Rn] >>= 1;1.510 + sh4r.r[Rn] |= (sh4r.t << 31 );1.511 + sh4r.t = tmp;1.512 +:}1.513 +SHAD Rm, Rn {:1.514 + tmp = sh4r.r[Rm];1.515 + if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);1.516 + else if( (tmp & 0x1F) == 0 )1.517 + sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;1.518 + else1.519 + sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);1.520 +:}1.521 +SHLD Rm, Rn {:1.522 + tmp = sh4r.r[Rm];1.523 + if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);1.524 + else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;1.525 + else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);1.526 +:}1.527 +SHAL Rn {:1.528 + sh4r.t = sh4r.r[Rn] >> 31;1.529 + sh4r.r[Rn] <<= 1;1.530 +:}1.531 +SHAR Rn {:1.532 + sh4r.t = sh4r.r[Rn] & 0x00000001;1.533 + sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;1.534 +:}1.535 +SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}1.536 +SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}1.537 +SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}1.538 +SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}1.539 +SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}1.540 +SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}1.541 +SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}1.542 +SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}1.543 +1.544 +EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}1.545 +EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}1.546 +EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}1.547 +EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}1.548 +SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}1.549 +SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}1.550 +1.551 +CLRT {: sh4r.t = 0; :}1.552 +SETT {: sh4r.t = 1; :}1.553 +CLRMAC {: sh4r.mac = 0; :}1.554 +LDTLB {: /* TODO */ :}1.555 +CLRS {: sh4r.s = 0; :}1.556 +SETS {: sh4r.s = 1; :}1.557 +MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}1.558 +NOP {: /* NOP */ :}1.559 +1.560 +PREF @Rn {:1.561 + tmp = sh4r.r[Rn];1.562 + if( (tmp & 0xFC000000) == 0xE0000000 ) {1.563 + /* Store queue operation */1.564 + int queue = (tmp&0x20)>>2;1.565 + int32_t *src = &sh4r.store_queue[queue];1.566 + uint32_t hi = (MMIO_READ( MMU, (queue == 0 ? QACR0 : QACR1) ) & 0x1C) << 24;1.567 + uint32_t target = tmp&0x03FFFFE0 | hi;1.568 + mem_copy_to_sh4( target, src, 32 );1.569 + }1.570 +:}1.571 +OCBI @Rn {: :}1.572 +OCBP @Rn {: :}1.573 +OCBWB @Rn {: :}1.574 +MOVCA.L R0, @Rn {:1.575 + tmp = sh4r.r[Rn];1.576 + CHECKWALIGN32(tmp);1.577 + MEM_WRITE_LONG( tmp, R0 );1.578 +:}1.579 +MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}1.580 +MOV.W Rm, @(R0, Rn) {:1.581 + CHECKWALIGN16( R0 + sh4r.r[Rn] );1.582 + MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );1.583 +:}1.584 +MOV.L Rm, @(R0, Rn) {:1.585 + CHECKWALIGN32( R0 + sh4r.r[Rn] );1.586 + MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );1.587 +:}1.588 +MOV.B @(R0, Rm), Rn {: sh4r.r[Rn] = MEM_READ_BYTE( R0 + sh4r.r[Rm] ); :}1.589 +MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );1.590 + sh4r.r[Rn] = MEM_READ_WORD( R0 + sh4r.r[Rm] );1.591 +:}1.592 +MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );1.593 + sh4r.r[Rn] = MEM_READ_LONG( R0 + sh4r.r[Rm] );1.594 +:}1.595 +MOV.L Rm, @(disp, Rn) {:1.596 + tmp = sh4r.r[Rn] + disp;1.597 + CHECKWALIGN32( tmp );1.598 + MEM_WRITE_LONG( tmp, sh4r.r[Rm] );1.599 +:}1.600 +MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}1.601 +MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}1.602 +MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}1.603 +MOV.B Rm, @-Rn {: sh4r.r[Rn] --; MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}1.604 +MOV.W Rm, @-Rn {: sh4r.r[Rn] -= 2; CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}1.605 +MOV.L Rm, @-Rn {: sh4r.r[Rn] -= 4; CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}1.606 +MOV.L @(disp, Rm), Rn {:1.607 + tmp = sh4r.r[Rm] + disp;1.608 + CHECKRALIGN32( tmp );1.609 + sh4r.r[Rn] = MEM_READ_LONG( tmp );1.610 +:}1.611 +MOV.B @Rm, Rn {: sh4r.r[Rn] = MEM_READ_BYTE( sh4r.r[Rm] ); :}1.612 +MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_WORD( sh4r.r[Rm] ); :}1.613 +MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_LONG( sh4r.r[Rm] ); :}1.614 +MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}1.615 +MOV.B @Rm+, Rn {: sh4r.r[Rn] = MEM_READ_BYTE( sh4r.r[Rm] ); sh4r.r[Rm] ++; :}1.616 +MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_WORD( sh4r.r[Rm] ); sh4r.r[Rm] += 2; :}1.617 +MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_LONG( sh4r.r[Rm] ); sh4r.r[Rm] += 4; :}1.618 +MOV.L @(disp, PC), Rn {:1.619 + CHECKSLOTILLEGAL();1.620 + tmp = (pc&0xFFFFFFFC) + disp + 4;1.621 + sh4r.r[Rn] = MEM_READ_LONG( tmp );1.622 +:}1.623 +MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}1.624 +MOV.W R0, @(disp, GBR) {:1.625 + tmp = sh4r.gbr + disp;1.626 + CHECKWALIGN16( tmp );1.627 + MEM_WRITE_WORD( tmp, R0 );1.628 +:}1.629 +MOV.L R0, @(disp, GBR) {:1.630 + tmp = sh4r.gbr + disp;1.631 + CHECKWALIGN32( tmp );1.632 + MEM_WRITE_LONG( tmp, R0 );1.633 +:}1.634 +MOV.B @(disp, GBR), R0 {: R0 = MEM_READ_BYTE( sh4r.gbr + disp ); :}1.635 +MOV.W @(disp, GBR), R0 {:1.636 + tmp = sh4r.gbr + disp;1.637 + CHECKRALIGN16( tmp );1.638 + R0 = MEM_READ_WORD( tmp );1.639 +:}1.640 +MOV.L @(disp, GBR), R0 {:1.641 + tmp = sh4r.gbr + disp;1.642 + CHECKRALIGN32( tmp );1.643 + R0 = MEM_READ_LONG( tmp );1.644 +:}1.645 +MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}1.646 +MOV.W R0, @(disp, Rn) {:1.647 + tmp = sh4r.r[Rn] + disp;1.648 + CHECKWALIGN16( tmp );1.649 + MEM_WRITE_WORD( tmp, R0 );1.650 +:}1.651 +MOV.B @(disp, Rm), R0 {: R0 = MEM_READ_BYTE( sh4r.r[Rm] + disp ); :}1.652 +MOV.W @(disp, Rm), R0 {:1.653 + tmp = sh4r.r[Rm] + disp;1.654 + CHECKRALIGN16( tmp );1.655 + R0 = MEM_READ_WORD( tmp );1.656 +:}1.657 +MOV.W @(disp, PC), Rn {:1.658 + CHECKSLOTILLEGAL();1.659 + tmp = pc + 4 + disp;1.660 + sh4r.r[Rn] = MEM_READ_WORD( tmp );1.661 +:}1.662 +MOVA @(disp, PC), R0 {:1.663 + CHECKSLOTILLEGAL();1.664 + R0 = (pc&0xFFFFFFFC) + disp + 4;1.665 +:}1.666 +MOV #imm, Rn {: sh4r.r[Rn] = imm; :}1.667 +1.668 +CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}1.669 +CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}1.670 +CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}1.671 +CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}1.672 +CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}1.673 +CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}1.674 +CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}1.675 +CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}1.676 +CMP/STR Rm, Rn {:1.677 + /* set T = 1 if any byte in RM & RN is the same */1.678 + tmp = sh4r.r[Rm] ^ sh4r.r[Rn];1.679 + sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||1.680 + (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;1.681 +:}1.682 +1.683 +ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}1.684 +ADD #imm, Rn {: sh4r.r[Rn] += imm; :}1.685 +ADDC Rm, Rn {:1.686 + tmp = sh4r.r[Rn];1.687 + sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;1.688 + sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );1.689 +:}1.690 +ADDV Rm, Rn {:1.691 + tmp = sh4r.r[Rn] + sh4r.r[Rm];1.692 + sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );1.693 + sh4r.r[Rn] = tmp;1.694 +:}1.695 +DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}1.696 +DIV0S Rm, Rn {:1.697 + sh4r.q = sh4r.r[Rn]>>31;1.698 + sh4r.m = sh4r.r[Rm]>>31;1.699 + sh4r.t = sh4r.q ^ sh4r.m;1.700 +:}1.701 +DIV1 Rm, Rn {:1.702 + /* This is just from the sh4p manual with some1.703 + * simplifications (someone want to check it's correct? :)1.704 + * Why they couldn't just provide a real DIV instruction...1.705 + */1.706 + uint32_t tmp0, tmp1, tmp2, dir;1.707 +1.708 + dir = sh4r.q ^ sh4r.m;1.709 + sh4r.q = (sh4r.r[Rn] >> 31);1.710 + tmp2 = sh4r.r[Rm];1.711 + sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;1.712 + tmp0 = sh4r.r[Rn];1.713 + if( dir ) {1.714 + sh4r.r[Rn] += tmp2;1.715 + tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );1.716 + } else {1.717 + sh4r.r[Rn] -= tmp2;1.718 + tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );1.719 + }1.720 + sh4r.q ^= sh4r.m ^ tmp1;1.721 + sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );1.722 +:}1.723 +DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}1.724 +DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}1.725 +DT Rn {:1.726 + sh4r.r[Rn] --;1.727 + sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );1.728 +:}1.729 +MAC.W @Rm+, @Rn+ {:1.730 + CHECKRALIGN16( sh4r.r[Rn] );1.731 + CHECKRALIGN16( sh4r.r[Rm] );1.732 + int32_t stmp = SIGNEXT16(MEM_READ_WORD(sh4r.r[Rn]));1.733 + sh4r.r[Rn] += 2;1.734 + stmp = stmp * SIGNEXT16(MEM_READ_WORD(sh4r.r[Rm]));1.735 + sh4r.r[Rm] += 2;1.736 + if( sh4r.s ) {1.737 + int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;1.738 + if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {1.739 + sh4r.mac = 0x000000017FFFFFFFLL;1.740 + } else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {1.741 + sh4r.mac = 0x0000000180000000LL;1.742 + } else {1.743 + sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |1.744 + ((uint32_t)(sh4r.mac + stmp));1.745 + }1.746 + } else {1.747 + sh4r.mac += SIGNEXT32(stmp);1.748 + }1.749 +:}1.750 +MAC.L @Rm+, @Rn+ {:1.751 + CHECKRALIGN32( sh4r.r[Rm] );1.752 + CHECKRALIGN32( sh4r.r[Rn] );1.753 + int64_t tmpl = SIGNEXT32(MEM_READ_LONG(sh4r.r[Rn]));1.754 + sh4r.r[Rn] += 4;1.755 + tmpl = tmpl * SIGNEXT32(MEM_READ_LONG(sh4r.r[Rm])) + sh4r.mac;1.756 + sh4r.r[Rm] += 4;1.757 + if( sh4r.s ) {1.758 + /* 48-bit Saturation. Yuch */1.759 + if( tmpl < (int64_t)0xFFFF800000000000LL )1.760 + tmpl = 0xFFFF800000000000LL;1.761 + else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )1.762 + tmpl = 0x00007FFFFFFFFFFFLL;1.763 + }1.764 + sh4r.mac = tmpl;1.765 +:}1.766 +MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |1.767 + (sh4r.r[Rm] * sh4r.r[Rn]); :}1.768 +MULU.W Rm, Rn {:1.769 + sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |1.770 + (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));1.771 +:}1.772 +MULS.W Rm, Rn {:1.773 + sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |1.774 + (uint32_t)(SIGNEXT32(sh4r.r[Rm]&0xFFFF) * SIGNEXT32(sh4r.r[Rn]&0xFFFF));1.775 +:}1.776 +NEGC Rm, Rn {:1.777 + tmp = 0 - sh4r.r[Rm];1.778 + sh4r.r[Rn] = tmp - sh4r.t;1.779 + sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );1.780 +:}1.781 +NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}1.782 +SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}1.783 +SUBC Rm, Rn {:1.784 + tmp = sh4r.r[Rn];1.785 + sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;1.786 + sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));1.787 +:}1.788 +1.789 +BRAF Rn {:1.790 + CHECKSLOTILLEGAL();1.791 + CHECKDEST( pc + 4 + sh4r.r[Rn] );1.792 + sh4r.in_delay_slot = 1;1.793 + sh4r.pc = sh4r.new_pc;1.794 + sh4r.new_pc = pc + 4 + sh4r.r[Rn];1.795 + return TRUE;1.796 +:}1.797 +BSRF Rn {:1.798 + CHECKSLOTILLEGAL();1.799 + CHECKDEST( pc + 4 + sh4r.r[Rn] );1.800 + sh4r.in_delay_slot = 1;1.801 + sh4r.pr = sh4r.pc + 4;1.802 + sh4r.pc = sh4r.new_pc;1.803 + sh4r.new_pc = pc + 4 + sh4r.r[Rn];1.804 + TRACE_CALL( pc, sh4r.new_pc );1.805 + return TRUE;1.806 +:}1.807 +BT disp {:1.808 + CHECKSLOTILLEGAL();1.809 + if( sh4r.t ) {1.810 + CHECKDEST( sh4r.pc + disp + 4 )1.811 + sh4r.pc += disp + 4;1.812 + sh4r.new_pc = sh4r.pc + 2;1.813 + return TRUE;1.814 + }1.815 +:}1.816 +BF disp {:1.817 + CHECKSLOTILLEGAL();1.818 + if( !sh4r.t ) {1.819 + CHECKDEST( sh4r.pc + disp + 4 )1.820 + sh4r.pc += disp + 4;1.821 + sh4r.new_pc = sh4r.pc + 2;1.822 + return TRUE;1.823 + }1.824 +:}1.825 +BT/S disp {:1.826 + CHECKSLOTILLEGAL();1.827 + if( sh4r.t ) {1.828 + CHECKDEST( sh4r.pc + disp + 4 )1.829 + sh4r.in_delay_slot = 1;1.830 + sh4r.pc = sh4r.new_pc;1.831 + sh4r.new_pc = pc + disp + 4;1.832 + sh4r.in_delay_slot = 1;1.833 + return TRUE;1.834 + }1.835 +:}1.836 +BF/S disp {:1.837 + CHECKSLOTILLEGAL();1.838 + if( !sh4r.t ) {1.839 + CHECKDEST( sh4r.pc + disp + 4 )1.840 + sh4r.in_delay_slot = 1;1.841 + sh4r.pc = sh4r.new_pc;1.842 + sh4r.new_pc = pc + disp + 4;1.843 + return TRUE;1.844 + }1.845 +:}1.846 +BRA disp {:1.847 + CHECKSLOTILLEGAL();1.848 + CHECKDEST( sh4r.pc + disp + 4 );1.849 + sh4r.in_delay_slot = 1;1.850 + sh4r.pc = sh4r.new_pc;1.851 + sh4r.new_pc = pc + 4 + disp;1.852 + return TRUE;1.853 +:}1.854 +BSR disp {:1.855 + CHECKDEST( sh4r.pc + disp + 4 );1.856 + CHECKSLOTILLEGAL();1.857 + sh4r.in_delay_slot = 1;1.858 + sh4r.pr = pc + 4;1.859 + sh4r.pc = sh4r.new_pc;1.860 + sh4r.new_pc = pc + 4 + disp;1.861 + TRACE_CALL( pc, sh4r.new_pc );1.862 + return TRUE;1.863 +:}1.864 +TRAPA #imm {:1.865 + CHECKSLOTILLEGAL();1.866 + MMIO_WRITE( MMU, TRA, imm<<2 );1.867 + sh4r.pc += 2;1.868 + sh4_raise_exception( EXC_TRAP );1.869 +:}1.870 +RTS {:1.871 + CHECKSLOTILLEGAL();1.872 + CHECKDEST( sh4r.pr );1.873 + sh4r.in_delay_slot = 1;1.874 + sh4r.pc = sh4r.new_pc;1.875 + sh4r.new_pc = sh4r.pr;1.876 + TRACE_RETURN( pc, sh4r.new_pc );1.877 + return TRUE;1.878 +:}1.879 +SLEEP {:1.880 + if( MMIO_READ( CPG, STBCR ) & 0x80 ) {1.881 + sh4r.sh4_state = SH4_STATE_STANDBY;1.882 + } else {1.883 + sh4r.sh4_state = SH4_STATE_SLEEP;1.884 + }1.885 + return FALSE; /* Halt CPU */1.886 +:}1.887 +RTE {:1.888 + CHECKPRIV();1.889 + CHECKDEST( sh4r.spc );1.890 + CHECKSLOTILLEGAL();1.891 + sh4r.in_delay_slot = 1;1.892 + sh4r.pc = sh4r.new_pc;1.893 + sh4r.new_pc = sh4r.spc;1.894 + sh4_load_sr( sh4r.ssr );1.895 + return TRUE;1.896 +:}1.897 +JMP @Rn {:1.898 + CHECKDEST( sh4r.r[Rn] );1.899 + CHECKSLOTILLEGAL();1.900 + sh4r.in_delay_slot = 1;1.901 + sh4r.pc = sh4r.new_pc;1.902 + sh4r.new_pc = sh4r.r[Rn];1.903 + return TRUE;1.904 +:}1.905 +JSR @Rn {:1.906 + CHECKDEST( sh4r.r[Rn] );1.907 + CHECKSLOTILLEGAL();1.908 + sh4r.in_delay_slot = 1;1.909 + sh4r.pc = sh4r.new_pc;1.910 + sh4r.new_pc = sh4r.r[Rn];1.911 + sh4r.pr = pc + 4;1.912 + TRACE_CALL( pc, sh4r.new_pc );1.913 + return TRUE;1.914 +:}1.915 +STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}1.916 +STS.L MACH, @-Rn {:1.917 + sh4r.r[Rn] -= 4;1.918 + CHECKWALIGN32( sh4r.r[Rn] );1.919 + MEM_WRITE_LONG( sh4r.r[Rn], (sh4r.mac>>32) );1.920 +:}1.921 +STC.L SR, @-Rn {:1.922 + CHECKPRIV();1.923 + sh4r.r[Rn] -= 4;1.924 + CHECKWALIGN32( sh4r.r[Rn] );1.925 + MEM_WRITE_LONG( sh4r.r[Rn], sh4_read_sr() );1.926 +:}1.927 +LDS.L @Rm+, MACH {:1.928 + CHECKRALIGN32( sh4r.r[Rm] );1.929 + sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |1.930 + (((uint64_t)MEM_READ_LONG(sh4r.r[Rm]))<<32);1.931 + sh4r.r[Rm] += 4;1.932 +:}1.933 +LDC.L @Rm+, SR {:1.934 + CHECKSLOTILLEGAL();1.935 + CHECKPRIV();1.936 + CHECKWALIGN32( sh4r.r[Rm] );1.937 + sh4_load_sr( MEM_READ_LONG(sh4r.r[Rm]) );1.938 + sh4r.r[Rm] +=4;1.939 +:}1.940 +LDS Rm, MACH {:1.941 + sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |1.942 + (((uint64_t)sh4r.r[Rm])<<32);1.943 +:}1.944 +LDC Rm, SR {:1.945 + CHECKSLOTILLEGAL();1.946 + CHECKPRIV();1.947 + sh4_load_sr( sh4r.r[Rm] );1.948 +:}1.949 +LDC Rm, SGR {:1.950 + CHECKPRIV();1.951 + sh4r.sgr = sh4r.r[Rm];1.952 +:}1.953 +LDC.L @Rm+, SGR {:1.954 + CHECKPRIV();1.955 + CHECKRALIGN32( sh4r.r[Rm] );1.956 + sh4r.sgr = MEM_READ_LONG(sh4r.r[Rm]);1.957 + sh4r.r[Rm] +=4;1.958 +:}1.959 +STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}1.960 +STS.L MACL, @-Rn {:1.961 + sh4r.r[Rn] -= 4;1.962 + CHECKWALIGN32( sh4r.r[Rn] );1.963 + MEM_WRITE_LONG( sh4r.r[Rn], (uint32_t)sh4r.mac );1.964 +:}1.965 +STC.L GBR, @-Rn {:1.966 + sh4r.r[Rn] -= 4;1.967 + CHECKWALIGN32( sh4r.r[Rn] );1.968 + MEM_WRITE_LONG( sh4r.r[Rn], sh4r.gbr );1.969 +:}1.970 +LDS.L @Rm+, MACL {:1.971 + CHECKRALIGN32( sh4r.r[Rm] );1.972 + sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |1.973 + (uint64_t)((uint32_t)MEM_READ_LONG(sh4r.r[Rm]));1.974 + sh4r.r[Rm] += 4;1.975 +:}1.976 +LDC.L @Rm+, GBR {:1.977 + CHECKRALIGN32( sh4r.r[Rm] );1.978 + sh4r.gbr = MEM_READ_LONG(sh4r.r[Rm]);1.979 + sh4r.r[Rm] +=4;1.980 +:}1.981 +LDS Rm, MACL {:1.982 + sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |1.983 + (uint64_t)((uint32_t)(sh4r.r[Rm]));1.984 +:}1.985 +LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}1.986 +STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}1.987 +STS.L PR, @-Rn {:1.988 + sh4r.r[Rn] -= 4;1.989 + CHECKWALIGN32( sh4r.r[Rn] );1.990 + MEM_WRITE_LONG( sh4r.r[Rn], sh4r.pr );1.991 +:}1.992 +STC.L VBR, @-Rn {:1.993 + CHECKPRIV();1.994 + sh4r.r[Rn] -= 4;1.995 + CHECKWALIGN32( sh4r.r[Rn] );1.996 + MEM_WRITE_LONG( sh4r.r[Rn], sh4r.vbr );1.997 +:}1.998 +LDS.L @Rm+, PR {:1.999 + CHECKRALIGN32( sh4r.r[Rm] );1.1000 + sh4r.pr = MEM_READ_LONG( sh4r.r[Rm] );1.1001 + sh4r.r[Rm] += 4;1.1002 +:}1.1003 +LDC.L @Rm+, VBR {:1.1004 + CHECKPRIV();1.1005 + CHECKRALIGN32( sh4r.r[Rm] );1.1006 + sh4r.vbr = MEM_READ_LONG(sh4r.r[Rm]);1.1007 + sh4r.r[Rm] +=4;1.1008 +:}1.1009 +LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}1.1010 +LDC Rm, VBR {:1.1011 + CHECKPRIV();1.1012 + sh4r.vbr = sh4r.r[Rm];1.1013 +:}1.1014 +STC SGR, Rn {:1.1015 + CHECKPRIV();1.1016 + sh4r.r[Rn] = sh4r.sgr;1.1017 +:}1.1018 +STC.L SGR, @-Rn {:1.1019 + CHECKPRIV();1.1020 + sh4r.r[Rn] -= 4;1.1021 + CHECKWALIGN32( sh4r.r[Rn] );1.1022 + MEM_WRITE_LONG( sh4r.r[Rn], sh4r.sgr );1.1023 +:}1.1024 +STC.L SSR, @-Rn {:1.1025 + CHECKPRIV();1.1026 + sh4r.r[Rn] -= 4;1.1027 + CHECKWALIGN32( sh4r.r[Rn] );1.1028 + MEM_WRITE_LONG( sh4r.r[Rn], sh4r.ssr );1.1029 +:}1.1030 +LDC.L @Rm+, SSR {:1.1031 + CHECKPRIV();1.1032 + CHECKRALIGN32( sh4r.r[Rm] );1.1033 + sh4r.ssr = MEM_READ_LONG(sh4r.r[Rm]);1.1034 + sh4r.r[Rm] +=4;1.1035 +:}1.1036 +LDC Rm, SSR {:1.1037 + CHECKPRIV();1.1038 + sh4r.ssr = sh4r.r[Rm];1.1039 +:}1.1040 +STC.L SPC, @-Rn {:1.1041 + CHECKPRIV();1.1042 + sh4r.r[Rn] -= 4;1.1043 + CHECKWALIGN32( sh4r.r[Rn] );1.1044 + MEM_WRITE_LONG( sh4r.r[Rn], sh4r.spc );1.1045 +:}1.1046 +LDC.L @Rm+, SPC {:1.1047 + CHECKPRIV();1.1048 + CHECKRALIGN32( sh4r.r[Rm] );1.1049 + sh4r.spc = MEM_READ_LONG(sh4r.r[Rm]);1.1050 + sh4r.r[Rm] +=4;1.1051 +:}1.1052 +LDC Rm, SPC {:1.1053 + CHECKPRIV();1.1054 + sh4r.spc = sh4r.r[Rm];1.1055 +:}1.1056 +STS FPUL, Rn {: sh4r.r[Rn] = sh4r.fpul; :}1.1057 +STS.L FPUL, @-Rn {:1.1058 + sh4r.r[Rn] -= 4;1.1059 + CHECKWALIGN32( sh4r.r[Rn] );1.1060 + MEM_WRITE_LONG( sh4r.r[Rn], sh4r.fpul );1.1061 +:}1.1062 +LDS.L @Rm+, FPUL {:1.1063 + CHECKRALIGN32( sh4r.r[Rm] );1.1064 + sh4r.fpul = MEM_READ_LONG(sh4r.r[Rm]);1.1065 + sh4r.r[Rm] +=4;1.1066 +:}1.1067 +LDS Rm, FPUL {: sh4r.fpul = sh4r.r[Rm]; :}1.1068 +STS FPSCR, Rn {: sh4r.r[Rn] = sh4r.fpscr; :}1.1069 +STS.L FPSCR, @-Rn {:1.1070 + sh4r.r[Rn] -= 4;1.1071 + CHECKWALIGN32( sh4r.r[Rn] );1.1072 + MEM_WRITE_LONG( sh4r.r[Rn], sh4r.fpscr );1.1073 +:}1.1074 +LDS.L @Rm+, FPSCR {:1.1075 + CHECKRALIGN32( sh4r.r[Rm] );1.1076 + sh4r.fpscr = MEM_READ_LONG(sh4r.r[Rm]);1.1077 + sh4r.r[Rm] +=4;1.1078 +:}1.1079 +LDS Rm, FPSCR {: sh4r.fpscr = sh4r.r[Rm]; :}1.1080 +STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}1.1081 +STC.L DBR, @-Rn {:1.1082 + CHECKPRIV();1.1083 + sh4r.r[Rn] -= 4;1.1084 + CHECKWALIGN32( sh4r.r[Rn] );1.1085 + MEM_WRITE_LONG( sh4r.r[Rn], sh4r.dbr );1.1086 +:}1.1087 +LDC.L @Rm+, DBR {:1.1088 + CHECKPRIV();1.1089 + CHECKRALIGN32( sh4r.r[Rm] );1.1090 + sh4r.dbr = MEM_READ_LONG(sh4r.r[Rm]);1.1091 + sh4r.r[Rm] +=4;1.1092 +:}1.1093 +LDC Rm, DBR {:1.1094 + CHECKPRIV();1.1095 + sh4r.dbr = sh4r.r[Rm];1.1096 +:}1.1097 +STC.L Rm_BANK, @-Rn {:1.1098 + CHECKPRIV();1.1099 + sh4r.r[Rn] -= 4;1.1100 + CHECKWALIGN32( sh4r.r[Rn] );1.1101 + MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r_bank[Rm_BANK] );1.1102 +:}1.1103 +LDC.L @Rm+, Rn_BANK {:1.1104 + CHECKPRIV();1.1105 + CHECKRALIGN32( sh4r.r[Rm] );1.1106 + sh4r.r_bank[Rn_BANK] = MEM_READ_LONG( sh4r.r[Rm] );1.1107 + sh4r.r[Rm] += 4;1.1108 +:}1.1109 +LDC Rm, Rn_BANK {:1.1110 + CHECKPRIV();1.1111 + sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];1.1112 +:}1.1113 +STC SR, Rn {:1.1114 + CHECKPRIV();1.1115 + sh4r.r[Rn] = sh4_read_sr();1.1116 +:}1.1117 +STC GBR, Rn {:1.1118 + CHECKPRIV();1.1119 + sh4r.r[Rn] = sh4r.gbr;1.1120 +:}1.1121 +STC VBR, Rn {:1.1122 + CHECKPRIV();1.1123 + sh4r.r[Rn] = sh4r.vbr;1.1124 +:}1.1125 +STC SSR, Rn {:1.1126 + CHECKPRIV();1.1127 + sh4r.r[Rn] = sh4r.ssr;1.1128 +:}1.1129 +STC SPC, Rn {:1.1130 + CHECKPRIV();1.1131 + sh4r.r[Rn] = sh4r.spc;1.1132 +:}1.1133 +STC Rm_BANK, Rn {:1.1134 + CHECKPRIV();1.1135 + sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];1.1136 +:}1.1137 +1.1138 +FADD FRm, FRn {:1.1139 + CHECKFPUEN();1.1140 + if( IS_FPU_DOUBLEPREC() ) {1.1141 + DR(FRn) += DR(FRm);1.1142 + } else {1.1143 + FR(FRn) += FR(FRm);1.1144 + }1.1145 +:}1.1146 +FSUB FRm, FRn {:1.1147 + CHECKFPUEN();1.1148 + if( IS_FPU_DOUBLEPREC() ) {1.1149 + DR(FRn) -= DR(FRm);1.1150 + } else {1.1151 + FR(FRn) -= FR(FRm);1.1152 + }1.1153 +:}1.1154 +1.1155 +FMUL FRm, FRn {:1.1156 + CHECKFPUEN();1.1157 + if( IS_FPU_DOUBLEPREC() ) {1.1158 + DR(FRn) *= DR(FRm);1.1159 + } else {1.1160 + FR(FRn) *= FR(FRm);1.1161 + }1.1162 +:}1.1163 +1.1164 +FDIV FRm, FRn {:1.1165 + CHECKFPUEN();1.1166 + if( IS_FPU_DOUBLEPREC() ) {1.1167 + DR(FRn) /= DR(FRm);1.1168 + } else {1.1169 + FR(FRn) /= FR(FRm);1.1170 + }1.1171 +:}1.1172 +1.1173 +FCMP/EQ FRm, FRn {:1.1174 + CHECKFPUEN();1.1175 + if( IS_FPU_DOUBLEPREC() ) {1.1176 + sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );1.1177 + } else {1.1178 + sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );1.1179 + }1.1180 +:}1.1181 +1.1182 +FCMP/GT FRm, FRn {:1.1183 + CHECKFPUEN();1.1184 + if( IS_FPU_DOUBLEPREC() ) {1.1185 + sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );1.1186 + } else {1.1187 + sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );1.1188 + }1.1189 +:}1.1190 +1.1191 +FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}1.1192 +FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}1.1193 +FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}1.1194 +FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}1.1195 +FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}1.1196 +FMOV FRm, @-Rn {: sh4r.r[Rn] -= FP_WIDTH; MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}1.1197 +FMOV FRm, FRn {:1.1198 + if( IS_FPU_DOUBLESIZE() )1.1199 + DR(FRn) = DR(FRm);1.1200 + else1.1201 + FR(FRn) = FR(FRm);1.1202 +:}1.1203 +FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}1.1204 +FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}1.1205 +FLOAT FPUL, FRn {:1.1206 + CHECKFPUEN();1.1207 + if( IS_FPU_DOUBLEPREC() )1.1208 + DR(FRn) = (float)FPULi;1.1209 + else1.1210 + FR(FRn) = (float)FPULi;1.1211 +:}1.1212 +FTRC FRm, FPUL {:1.1213 + CHECKFPUEN();1.1214 + if( IS_FPU_DOUBLEPREC() ) {1.1215 + dtmp = DR(FRm);1.1216 + if( dtmp >= MAX_INTF )1.1217 + FPULi = MAX_INT;1.1218 + else if( dtmp <= MIN_INTF )1.1219 + FPULi = MIN_INT;1.1220 + else1.1221 + FPULi = (int32_t)dtmp;1.1222 + } else {1.1223 + ftmp = FR(FRm);1.1224 + if( ftmp >= MAX_INTF )1.1225 + FPULi = MAX_INT;1.1226 + else if( ftmp <= MIN_INTF )1.1227 + FPULi = MIN_INT;1.1228 + else1.1229 + FPULi = (int32_t)ftmp;1.1230 + }1.1231 +:}1.1232 +FNEG FRn {:1.1233 + CHECKFPUEN();1.1234 + if( IS_FPU_DOUBLEPREC() ) {1.1235 + DR(FRn) = -DR(FRn);1.1236 + } else {1.1237 + FR(FRn) = -FR(FRn);1.1238 + }1.1239 +:}1.1240 +FABS FRn {:1.1241 + CHECKFPUEN();1.1242 + if( IS_FPU_DOUBLEPREC() ) {1.1243 + DR(FRn) = fabs(DR(FRn));1.1244 + } else {1.1245 + FR(FRn) = fabsf(FR(FRn));1.1246 + }1.1247 +:}1.1248 +FSQRT FRn {:1.1249 + CHECKFPUEN();1.1250 + if( IS_FPU_DOUBLEPREC() ) {1.1251 + DR(FRn) = sqrt(DR(FRn));1.1252 + } else {1.1253 + FR(FRn) = sqrtf(FR(FRn));1.1254 + }1.1255 +:}1.1256 +FLDI0 FRn {:1.1257 + CHECKFPUEN();1.1258 + if( IS_FPU_DOUBLEPREC() ) {1.1259 + DR(FRn) = 0.0;1.1260 + } else {1.1261 + FR(FRn) = 0.0;1.1262 + }1.1263 +:}1.1264 +FLDI1 FRn {:1.1265 + CHECKFPUEN();1.1266 + if( IS_FPU_DOUBLEPREC() ) {1.1267 + DR(FRn) = 1.0;1.1268 + } else {1.1269 + FR(FRn) = 1.0;1.1270 + }1.1271 +:}1.1272 +FMAC FR0, FRm, FRn {:1.1273 + CHECKFPUEN();1.1274 + if( IS_FPU_DOUBLEPREC() ) {1.1275 + DR(FRn) += DR(FRm)*DR(0);1.1276 + } else {1.1277 + FR(FRn) += FR(FRm)*FR(0);1.1278 + }1.1279 +:}1.1280 +FRCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_FR; :}1.1281 +FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}1.1282 +FCNVSD FPUL, FRn {:1.1283 + CHECKFPUEN();1.1284 + if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {1.1285 + DR(FRn) = (double)FPULf;1.1286 + }1.1287 +:}1.1288 +FCNVDS FRm, FPUL {:1.1289 + CHECKFPUEN();1.1290 + if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {1.1291 + FPULf = (float)DR(FRm);1.1292 + }1.1293 +:}1.1294 +1.1295 +FSRRA FRn {:1.1296 + CHECKFPUEN();1.1297 + if( !IS_FPU_DOUBLEPREC() ) {1.1298 + FR(FRn) = 1.0/sqrtf(FR(FRn));1.1299 + }1.1300 +:}1.1301 +FIPR FVm, FVn {:1.1302 + CHECKFPUEN();1.1303 + if( !IS_FPU_DOUBLEPREC() ) {1.1304 + int tmp2 = FVn<<2;1.1305 + tmp = FVm<<2;1.1306 + FR(tmp2+3) = FR(tmp)*FR(tmp2) +1.1307 + FR(tmp+1)*FR(tmp2+1) +1.1308 + FR(tmp+2)*FR(tmp2+2) +1.1309 + FR(tmp+3)*FR(tmp2+3);1.1310 + }1.1311 +:}1.1312 +FSCA FPUL, FRn {:1.1313 + CHECKFPUEN();1.1314 + if( !IS_FPU_DOUBLEPREC() ) {1.1315 + float angle = (((float)(FPULi&0xFFFF))/65536.0) * 2 * M_PI;1.1316 + FR(FRn) = sinf(angle);1.1317 + FR((FRn)+1) = cosf(angle);1.1318 + }1.1319 +:}1.1320 +FTRV XMTRX, FVn {:1.1321 + CHECKFPUEN();1.1322 + if( !IS_FPU_DOUBLEPREC() ) {1.1323 + tmp = FVn<<2;1.1324 + float fv[4] = { FR(tmp), FR(tmp+1), FR(tmp+2), FR(tmp+3) };1.1325 + FR(tmp) = XF(0) * fv[0] + XF(4)*fv[1] +1.1326 + XF(8)*fv[2] + XF(12)*fv[3];1.1327 + FR(tmp+1) = XF(1) * fv[0] + XF(5)*fv[1] +1.1328 + XF(9)*fv[2] + XF(13)*fv[3];1.1329 + FR(tmp+2) = XF(2) * fv[0] + XF(6)*fv[1] +1.1330 + XF(10)*fv[2] + XF(14)*fv[3];1.1331 + FR(tmp+3) = XF(3) * fv[0] + XF(7)*fv[1] +1.1332 + XF(11)*fv[2] + XF(15)*fv[3];1.1333 + }1.1334 +:}1.1335 +UNDEF {:1.1336 + UNDEF(ir);1.1337 +:}1.1338 +%%1.1339 + sh4r.pc = sh4r.new_pc;1.1340 + sh4r.new_pc += 2;1.1341 + sh4r.in_delay_slot = 0;1.1342 + return TRUE;1.1343 +}
.