revision 51:ed6c27067502
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 51:ed6c27067502 |
parent | 50:704b11c879cb |
child | 52:429b7fc6b843 |
author | nkeynes |
date | Wed Dec 28 22:49:26 2005 +0000 (17 years ago) |
Add several missing M instructions
Add SWI instruction
Fix disasm of LDM
Accept interrupts
Add SWI instruction
Fix disasm of LDM
Accept interrupts
![]() | src/aica/armcore.c | view | annotate | diff | log | |
![]() | src/aica/armcore.h | view | annotate | diff | log | |
![]() | src/aica/armdasm.c | view | annotate | diff | log |
1.1 --- a/src/aica/armcore.c Wed Dec 28 22:47:44 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;
2.1 --- a/src/aica/armcore.h Wed Dec 28 22:47:44 2005 +00002.2 +++ b/src/aica/armcore.h Wed Dec 28 22:49:26 2005 +00002.3 @@ -1,5 +1,5 @@2.4 /**2.5 - * $Id: armcore.h,v 1.10 2005-12-27 08:42:57 nkeynes Exp $2.6 + * $Id: armcore.h,v 1.11 2005-12-28 22:49:26 nkeynes Exp $2.7 *2.8 * Interface definitions for the ARM CPU emulation core proper.2.9 *2.10 @@ -49,6 +49,7 @@2.11 uint32_t c,n,z,v,t;2.13 /* "fake" registers */2.14 + uint32_t int_pending; /* Mask of CPSR_I and CPSR_F */2.15 uint32_t shift_c; /* used for temporary storage of shifter results */2.16 uint32_t icount; /* Instruction counter */2.17 };
3.1 --- a/src/aica/armdasm.c Wed Dec 28 22:47:44 2005 +00003.2 +++ b/src/aica/armdasm.c Wed Dec 28 22:49:26 2005 +00003.3 @@ -1,5 +1,5 @@3.4 /**3.5 - * $Id: armdasm.c,v 1.8 2005-12-27 12:42:00 nkeynes Exp $3.6 + * $Id: armdasm.c,v 1.9 2005-12-28 22:49:26 nkeynes Exp $3.7 *3.8 * armdasm.c 21 Aug 2004 - ARM7tdmi (ARMv4) disassembler3.9 *3.10 @@ -119,7 +119,7 @@3.11 operand = IMM8(ir);3.12 tmp = IMMROT(ir);3.13 operand = ROTATE_RIGHT_LONG(operand, tmp);3.14 - return snprintf(buf, len, "%08X", operand );3.15 + return snprintf(buf, len, "#%08Xh", operand );3.16 }3.17 }3.19 @@ -159,17 +159,17 @@3.20 switch( (ir>>21)&0x19 ) {3.21 case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */3.22 case 1:3.23 - return snprintf( buf, len, "[R%d], R%d %c= %04X", RN(ir), RN(ir), sign, IMM12(ir) );3.24 + return snprintf( buf, len, "[R%d], R%d %c= #%04Xh", RN(ir), RN(ir), sign, IMM12(ir) );3.25 case 8: /* Rn - imm offset [5.2.2 A5-20] */3.26 if( RN(ir) == 15 ) { /* PC relative - decode here */3.27 uint32_t addr = pc + 8 + (UFLAG(ir) ? IMM12(ir) : -IMM12(ir));3.28 return snprintf( buf, len, "[$%08Xh] <- #%08Xh", addr,3.29 arm_read_long( addr ) );3.30 } else {3.31 - return snprintf( buf, len, "[R%d %c %04X]", RN(ir), sign, IMM12(ir) );3.32 + return snprintf( buf, len, "[R%d %c #%04Xh]", RN(ir), sign, IMM12(ir) );3.33 }3.34 case 9: /* Rn -= imm offset (pre-indexed) [5.2.5 A5-24] */3.35 - return snprintf( buf, len, "[R%d %c= %04X]", RN(ir), sign, IMM12(ir) );3.36 + return snprintf( buf, len, "[R%d %c= #%04Xh]", RN(ir), sign, IMM12(ir) );3.37 case 16: /* Rn -= Rm (post-indexed) [5.2.10 A5-32 ] */3.38 case 17:3.39 arm_disasm_address_index( ir, shift, sizeof(shift) );3.40 @@ -391,11 +391,19 @@3.41 arm_disasm_shift_operand(ir, operand, sizeof(operand));3.42 snprintf(buf, len, "ORRS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);3.43 break;3.44 - case 26: /* MOV Rd, Rn, operand */3.45 + case 26: /* MOV Rd, operand */3.46 + if( ir == 0xE1A00000 ) {3.47 + /* Not technically a different instruction,3.48 + * but this one is commonly used as a NOP,3.49 + * so...3.50 + */3.51 + snprintf(buf, len, "NOP");3.52 + } else {3.53 arm_disasm_shift_operand(ir, operand, sizeof(operand));3.54 snprintf(buf, len, "MOV%s R%d, %s", cond, RD(ir), operand);3.55 - break;3.56 - case 27: /* MOVS Rd, Rn, operand */3.57 + }3.58 + break;3.59 + case 27: /* MOVS Rd, operand */3.60 arm_disasm_shift_operand(ir, operand, sizeof(operand));3.61 snprintf(buf, len, "MOVS%s R%d, %s", cond, RD(ir), operand);3.62 break;3.63 @@ -461,9 +469,9 @@3.64 if( (ir & 0x02000000) == 0x02000000 ) {3.65 int32_t offset = SIGNEXT24(ir&0x00FFFFFF) << 2;3.66 if( (ir & 0x01000000) == 0x01000000 ) {3.67 - snprintf( buf, len, "BL%s $%08Xh", cond, pc + offset + 8 );3.68 + snprintf( buf, len, "BL%s $%08Xh", cond, pc + offset + 8 );3.69 } else {3.70 - snprintf( buf, len, "B%s $%08Xh", cond, pc + offset + 8 );3.71 + snprintf( buf, len, "B%s $%08Xh", cond, pc + offset + 8 );3.72 }3.73 } else {3.74 /* Load/store multiple */3.75 @@ -472,20 +480,24 @@3.76 buf += j;3.77 len -= j;3.78 for( i = 0; i<16 && len > 2; i++ ) {3.79 - if( (ir >> i)&1 ) {3.80 - j = snprintf( buf, len, "R%d", i );3.81 - buf+=j;3.82 - len-=j;3.83 - }3.84 + if( ir & (1<<i) ) {3.85 + j = snprintf( buf, len, "R%d", i );3.86 + buf+=j;3.87 + len-=j;3.88 + }3.89 }3.90 - if( SFLAG(ir) && len > 0 ) {3.91 + if( BFLAG(ir) && len > 0 ) {3.92 buf[0] = '^';3.93 buf[1] = '\0';3.94 }3.95 }3.96 break;3.97 case 3: /* Copro */3.98 - UNIMP(ir);3.99 + if( (ir & 0x0F000000) == 0x0F000000 ) {3.100 + snprintf( buf, len, "SWI%s #%08Xh", SIGNEXT24(ir) );3.101 + } else {3.102 + UNIMP(ir);3.103 + }3.104 break;3.105 }
.