filename | src/aica/armcore.c |
changeset | 51:ed6c27067502 |
prev | 49:6290c467cfbd |
next | 52:429b7fc6b843 |
author | nkeynes |
date | Wed Dec 28 22:49:26 2005 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Add several missing M instructions Add SWI instruction Fix disasm of LDM Accept interrupts |
file | annotate | diff | log | raw |
1.1 --- a/src/aica/armcore.c Tue Dec 27 12:42:29 2005 +00001.2 +++ b/src/aica/armcore.c Wed Dec 28 22:49:26 2005 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: armcore.c,v 1.11 2005-12-27 12:42:29 nkeynes Exp $1.6 + * $Id: armcore.c,v 1.12 2005-12-28 22:49:26 nkeynes Exp $1.7 *1.8 * ARM7TDMI CPU emulation core.1.9 *1.10 @@ -21,6 +21,8 @@1.11 #include "aica/armcore.h"1.12 #include "mem.h"1.14 +#define STM_R15_OFFSET 121.15 +1.16 struct arm_registers armr;1.18 void arm_set_mode( int mode );1.19 @@ -660,6 +662,15 @@1.20 uint32_t ir = MEM_READ_LONG(pc);1.21 uint32_t operand, operand2, tmp, tmp2, cond;1.23 + tmp = armr.int_pending & armr.cpsr;1.24 + if( tmp ) {1.25 + if( tmp & CPSR_F ) {1.26 + arm_raise_exception( EXC_FAST_IRQ );1.27 + } else {1.28 + arm_raise_exception( EXC_IRQ );1.29 + }1.30 + }1.31 +1.32 pc += 4;1.33 PC = pc;1.35 @@ -763,12 +774,22 @@1.36 /* Arithmetic extension area */1.37 switch(OPCODE(ir)) {1.38 case 0: /* MUL */1.39 + LRN(ir) = RM(ir) * RS(ir);1.40 break;1.41 case 1: /* MULS */1.42 + tmp = RM(ir) * RS(ir);1.43 + LRN(ir) = tmp;1.44 + armr.n = tmp>>31;1.45 + armr.z = (tmp == 0);1.46 break;1.47 case 2: /* MLA */1.48 + LRN(ir) = RM(ir) * RS(ir) + RD(ir);1.49 break;1.50 case 3: /* MLAS */1.51 + tmp = RM(ir) * RS(ir) + RD(ir);1.52 + LRN(ir) = tmp;1.53 + armr.n = tmp>>31;1.54 + armr.z = (tmp == 0);1.55 break;1.56 case 8: /* UMULL */1.57 break;1.58 @@ -787,8 +808,25 @@1.59 case 15: /* SMLALS */1.60 break;1.61 case 16: /* SWP */1.62 + tmp = arm_read_long( RN(ir) );1.63 + switch( RN(ir) & 0x03 ) {1.64 + case 1:1.65 + tmp = ROTATE_RIGHT_LONG(tmp, 8);1.66 + break;1.67 + case 2:1.68 + tmp = ROTATE_RIGHT_LONG(tmp, 16);1.69 + break;1.70 + case 3:1.71 + tmp = ROTATE_RIGHT_LONG(tmp, 24);1.72 + break;1.73 + }1.74 + arm_write_long( RN(ir), RM(ir) );1.75 + LRD(ir) = tmp;1.76 break;1.77 case 20: /* SWPB */1.78 + tmp = arm_read_byte( RN(ir) );1.79 + arm_write_byte( RN(ir), RM(ir) );1.80 + LRD(ir) = tmp;1.81 break;1.82 default:1.83 UNIMP(ir);1.84 @@ -1151,7 +1189,7 @@1.85 /* Actually can't happen, but anyway... */1.86 armr.r[15] = arm_read_long(operand);1.87 } else {1.88 - arm_write_long( operand, armr.r[15]+4 );1.89 + arm_write_long( operand, armr.r[15]+ STM_R15_OFFSET - 4 );1.90 }1.91 operand += poststep;1.92 }1.93 @@ -1164,7 +1202,11 @@1.94 if( LFLAG(ir) ) {1.95 armr.r[tmp] = arm_read_long(operand);1.96 } else {1.97 - arm_write_long( operand, armr.r[tmp] );1.98 + if( tmp == 15 )1.99 + arm_write_long( operand,1.100 + armr.r[15] + STM_R15_OFFSET - 4 );1.101 + else1.102 + arm_write_long( operand, armr.r[tmp] );1.103 }1.104 operand += poststep;1.105 }1.106 @@ -1175,7 +1217,11 @@1.107 }1.108 break;1.109 case 3: /* Copro */1.110 - UNIMP(ir);1.111 + if( (ir & 0x0F000000) == 0x0F000000 ) { /* SWI */1.112 + arm_raise_exception( EXC_SOFTWARE );1.113 + } else {1.114 + UNIMP(ir);1.115 + }1.116 break;1.117 }1.118 return TRUE;
.