Search
lxdream.org :: lxdream/src/sh4/sh4core.in :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4core.in
changeset 359:c588dce7ebde
next367: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 +0000
1.2 +++ b/src/sh4/sh4core.in Thu Aug 23 12:33:27 2007 +0000
1.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 peripheral
1.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 modify
1.13 + * it under the terms of the GNU General Public License as published by
1.14 + * the Free Software Foundation; either version 2 of the License, or
1.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 of
1.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.20 + * GNU General Public License for more details.
1.21 + */
1.22 +
1.23 +#define MODULE sh4_module
1.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 1
1.34 +
1.35 +#define MAX_INT 0x7FFFFFFF
1.36 +#define MIN_INT 0x80000000
1.37 +#define MAX_INTF 2147483647.0
1.38 +#define MIN_INTF -2147483648.0
1.39 +
1.40 +/* CPU-generated exception code/vector pairs */
1.41 +#define EXC_POWER_RESET 0x000 /* vector special */
1.42 +#define EXC_MANUAL_RESET 0x020
1.43 +#define EXC_READ_ADDR_ERR 0x0E0
1.44 +#define EXC_WRITE_ADDR_ERR 0x100
1.45 +#define EXC_SLOT_ILLEGAL 0x1A0
1.46 +#define EXC_ILLEGAL 0x180
1.47 +#define EXC_TRAP 0x160
1.48 +#define EXC_FPDISABLE 0x800
1.49 +#define EXC_SLOT_FPDISABLE 0x820
1.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_MODE
1.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 +#endif
1.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 we
1.203 + * actually executed
1.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 32
1.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 +#else
1.292 +#define TRACE_CALL( dest, rts )
1.293 +#define TRACE_RETURN( source, dest )
1.294 +#endif
1.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 IO
1.461 + * region, fallback on the full-blown memory read
1.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 + else
1.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 some
1.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 + else
1.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 + else
1.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 + else
1.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 + else
1.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 +}
.