Search
lxdream.org :: lxdream :: r51:ed6c27067502
lxdream 0.9.1
released Jun 29
Download Now
changeset51:ed6c27067502
parent50:704b11c879cb
child52:429b7fc6b843
authornkeynes
dateWed Dec 28 22:49:26 2005 +0000 (17 years ago)
Add several missing M instructions
Add SWI instruction
Fix disasm of LDM
Accept interrupts
src/aica/armcore.c
src/aica/armcore.h
src/aica/armdasm.c
1.1 --- a/src/aica/armcore.c Wed Dec 28 22:47:44 2005 +0000
1.2 +++ b/src/aica/armcore.c Wed Dec 28 22:49:26 2005 +0000
1.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.13
1.14 +#define STM_R15_OFFSET 12
1.15 +
1.16 struct arm_registers armr;
1.17
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.22
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.34
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 + else
1.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 +0000
2.2 +++ b/src/aica/armcore.h Wed Dec 28 22:49:26 2005 +0000
2.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.12
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 +0000
3.2 +++ b/src/aica/armdasm.c Wed Dec 28 22:49:26 2005 +0000
3.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) disassembler
3.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.18
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 }
3.106
.