filename | src/aica/armcore.c |
changeset | 46:30d123047e16 |
prev | 44:8da2cbcffe24 |
next | 49:6290c467cfbd |
author | nkeynes |
date | Tue Dec 27 08:42:57 2005 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Implement LDM/STM opcodes Add a few more unknown aica registers |
file | annotate | diff | log | raw |
1.1 --- a/src/aica/armcore.c Mon Dec 26 11:52:56 2005 +00001.2 +++ b/src/aica/armcore.c Tue Dec 27 08:42:57 2005 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: armcore.c,v 1.9 2005-12-26 11:52:56 nkeynes Exp $1.6 + * $Id: armcore.c,v 1.10 2005-12-27 08:42:57 nkeynes Exp $1.7 *1.8 * ARM7TDMI CPU emulation core.1.9 *1.10 @@ -354,7 +354,7 @@1.11 #define PFLAG(ir) (ir&0x01000000)1.12 #define UFLAG(ir) (ir&0x00800000)1.13 #define BFLAG(ir) (ir&0x00400000)1.14 -#define WFLAG(ir) (IR&0x00200000)1.15 +#define WFLAG(ir) (ir&0x00200000)1.16 #define LFLAG(ir) SFLAG(ir)1.17 #define RN(ir) (armr.r[((ir>>16)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))1.18 #define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>12)&0x0F) == 0x0F ? 4 : 0))1.19 @@ -375,7 +375,7 @@1.20 #define SHIFT(ir) ((ir>>4)&0x07)1.21 #define DISP24(ir) ((ir&0x00FFFFFF))1.22 #define UNDEF(ir) do{ arm_raise_exception( EXC_UNDEFINED ); return TRUE; } while(0)1.23 -#define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC-4, ir ); dreamcast_stop(); return FALSE; }while(0)1.24 +#define UNIMP(ir) do{ PC-=4; ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC, ir ); dreamcast_stop(); return FALSE; }while(0)1.26 /**1.27 * Determine the value of the shift-operand for a data processing instruction,1.28 @@ -1033,7 +1033,89 @@1.29 }1.30 armr.r[15] = pc + 4 + operand;1.31 } else { /* Load/store multiple */1.32 - UNIMP(ir);1.33 + int prestep, poststep;1.34 + if( PFLAG(ir) ) {1.35 + prestep = 0;1.36 + poststep = UFLAG(ir) ? 4 : -4;1.37 + } else {1.38 + prestep = UFLAG(ir) ? 4 : -4;1.39 + poststep = 0 ;1.40 + }1.41 + operand = RN(ir);1.42 + if( BFLAG(ir) ) {1.43 + /* Actually S - bit 22. Means "make massively complicated" */1.44 + if( LFLAG(ir) && (ir&0x00008000) ) {1.45 + /* LDM (3). Much like normal LDM but also copies SPSR1.46 + * back to CPSR */1.47 + for( tmp=0; tmp < 16; tmp++ ) {1.48 + if( (ir & (1<<tmp)) ) {1.49 + operand += prestep;1.50 + armr.r[tmp] = arm_read_long(operand);1.51 + operand += poststep;1.52 + }1.53 + }1.54 + arm_restore_cpsr();1.55 + if( armr.t ) PC &= 0xFFFFFFFE;1.56 + else PC &= 0xFFFFFFFC;1.57 + } else {1.58 + /* LDM/STM (2). As normal LDM but accesses the User banks1.59 + * instead of the active ones. Aka the truly evil case1.60 + */1.61 + int bank_start;1.62 + if( IS_FIQ_MODE() )1.63 + bank_start = 8;1.64 + else if( IS_EXCEPTION_MODE() )1.65 + bank_start = 13;1.66 + else bank_start = 15;1.67 + for( tmp=0; tmp<bank_start; tmp++ ) {1.68 + if( (ir & (1<<tmp)) ) {1.69 + operand += prestep;1.70 + if( LFLAG(ir) ) {1.71 + armr.r[tmp] = arm_read_long(operand);1.72 + } else {1.73 + arm_write_long( operand, armr.r[tmp] );1.74 + }1.75 + operand += poststep;1.76 + }1.77 + }1.78 + for( ; tmp < 15; tmp ++ ) {1.79 + if( (ir & (1<<tmp)) ) {1.80 + operand += prestep;1.81 + if( LFLAG(ir) ) {1.82 + armr.user_r[tmp-8] = arm_read_long(operand);1.83 + } else {1.84 + arm_write_long( operand, armr.user_r[tmp-8] );1.85 + }1.86 + operand += poststep;1.87 + }1.88 + }1.89 + if( ir & 0x8000 ) {1.90 + operand += prestep;1.91 + if( LFLAG(ir) ) {1.92 + /* Actually can't happen, but anyway... */1.93 + armr.r[15] = arm_read_long(operand);1.94 + } else {1.95 + arm_write_long( operand, armr.r[15]+4 );1.96 + }1.97 + operand += poststep;1.98 + }1.99 + }1.100 + } else {1.101 + /* Normal LDM/STM */1.102 + for( tmp=0; tmp < 16; tmp++ ) {1.103 + if( (ir & (1<<tmp)) ) {1.104 + operand += prestep;1.105 + if( LFLAG(ir) ) {1.106 + armr.r[tmp] = arm_read_long(operand);1.107 + } else {1.108 + arm_write_long( operand, armr.r[tmp] );1.109 + }1.110 + operand += poststep;1.111 + }1.112 + }1.113 + }1.114 + if( WFLAG(ir) )1.115 + LRN(ir) = operand;1.116 }1.117 break;1.118 case 3: /* Copro */
.