Search
lxdream.org :: lxdream/src/aica/armcore.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armcore.c
changeset 51:ed6c27067502
prev49:6290c467cfbd
next52:429b7fc6b843
author nkeynes
date Wed Dec 28 22:49:26 2005 +0000 (14 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 +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;
.