Search
lxdream.org :: lxdream/src/aica/armcore.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armcore.c
changeset 46:30d123047e16
prev44:8da2cbcffe24
next49:6290c467cfbd
author nkeynes
date Tue Dec 27 08:42:57 2005 +0000 (14 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 +0000
1.2 +++ b/src/aica/armcore.c Tue Dec 27 08:42:57 2005 +0000
1.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.25
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 SPSR
1.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 banks
1.59 + * instead of the active ones. Aka the truly evil case
1.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 */
.