Search
lxdream.org :: lxdream/src/aica/armcore.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/armcore.c
changeset 811:7ff871670e58
prev736:a02d1475ccfd
next814:f1a21df54e19
author nkeynes
date Wed Aug 13 10:27:49 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Implement LDRH/STRH/LDRSH/LDRSB instructions
file annotate diff log raw
1.1 --- a/src/aica/armcore.c Mon Jul 14 07:44:42 2008 +0000
1.2 +++ b/src/aica/armcore.c Wed Aug 13 10:27:49 2008 +0000
1.3 @@ -401,10 +401,13 @@
1.4
1.5 #define IMM8(ir) (ir&0xFF)
1.6 #define IMM12(ir) (ir&0xFFF)
1.7 +#define IMMSPLIT8(ir) (((ir&0xF00)>>4)|(ir&0x0F))
1.8 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
1.9 #define IMMROT(ir) ((ir>>7)&0x1E)
1.10 #define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
1.11 #define SIGNEXT24(n) (((n)&0x00800000) ? ((n)|0xFF000000) : ((n)&0x00FFFFFF))
1.12 +#define SIGNEXT8(n) ((int32_t)((int8_t)(n)))
1.13 +#define SIGNEXT16(n) ((int32_t)((int16_t)(n)))
1.14 #define SHIFT(ir) ((ir>>4)&0x07)
1.15 #define DISP24(ir) ((ir&0x00FFFFFF))
1.16 #define UNDEF(ir) do{ arm_raise_exception( EXC_UNDEFINED ); return TRUE; } while(0)
1.17 @@ -687,6 +690,72 @@
1.18 return addr;
1.19 }
1.20
1.21 +/**
1.22 + * Determine the address operand of a miscellaneous load/store instruction,
1.23 + * including applying any pre/post adjustments to the address registers.
1.24 + * @see s5.3 Addressing Mode 3 - Miscellaneous Loads and Stores
1.25 + * @param The instruction word.
1.26 + * @return The calculated address
1.27 + */
1.28 +static uint32_t arm_get_address3_operand( uint32_t ir )
1.29 +{
1.30 + uint32_t addr=0;
1.31 +
1.32 + /* x x P U x W */
1.33 + switch( (ir>>21)&0x0F ) {
1.34 + case 0: /* Rn -= Rm (post-indexed) [5.3.7 A5-48] */
1.35 + case 1: /* UNPREDICTABLE */
1.36 + addr = RN(ir);
1.37 + LRN(ir) -= RM(ir);
1.38 + break;
1.39 + case 2: /* Rn -= imm (post-indexed) [5.3.6 A5-46] */
1.40 + case 3: /* UNPREDICTABLE */
1.41 + addr = RN(ir);
1.42 + LRN(ir) -= IMMSPLIT8(ir);
1.43 + break;
1.44 + case 4: /* Rn += Rm (post-indexed) [5.3.7 A5-48] */
1.45 + case 5: /* UNPREDICTABLE */
1.46 + addr = RN(ir);
1.47 + LRN(ir) += RM(ir);
1.48 + break;
1.49 + case 6: /* Rn += imm (post-indexed) [5.3.6 A5-44] */
1.50 + case 7: /* UNPREDICTABLE */
1.51 + addr = RN(ir);
1.52 + LRN(ir) += IMMSPLIT8(ir);
1.53 + break;
1.54 + case 8: /* Rn - Rm [5.3.3 A5-38] */
1.55 + addr = RN(ir) - RM(ir);
1.56 + break;
1.57 + case 9: /* Rn -= Rm (pre-indexed) [5.3.5 A5-42] */
1.58 + addr = RN(ir) - RM(ir);
1.59 + LRN(ir) = addr;
1.60 + break;
1.61 + case 10: /* Rn - imm offset [5.3.2 A5-36] */
1.62 + addr = RN(ir) - IMMSPLIT8(ir);
1.63 + break;
1.64 + case 11: /* Rn -= imm offset (pre-indexed) [5.3.4 A5-40] */
1.65 + addr = RN(ir) - IMMSPLIT8(ir);
1.66 + LRN(ir) = addr;
1.67 + break;
1.68 + case 12: /* Rn + Rm [5.3.3 A5-38] */
1.69 + addr = RN(ir) + RM(ir);
1.70 + break;
1.71 + case 13: /* Rn += Rm (pre-indexed) [5.3.5 A5-42] */
1.72 + addr = RN(ir) + RM(ir);
1.73 + LRN(ir) = addr;
1.74 + break;
1.75 + case 14: /* Rn + imm offset [5.3.2 A5-36] */
1.76 + addr = RN(ir) + IMMSPLIT8(ir);
1.77 + break;
1.78 + case 15: /* Rn += imm offset (pre-indexed) [5.3.4 A5-40] */
1.79 + addr = RN(ir) + IMMSPLIT8(ir);
1.80 + LRN(ir) = addr;
1.81 + break;
1.82 +
1.83 + }
1.84 + return addr;
1.85 +}
1.86 +
1.87 gboolean arm_execute_instruction( void )
1.88 {
1.89 uint32_t pc;
1.90 @@ -859,26 +928,28 @@
1.91 }
1.92 break;
1.93 case 1:
1.94 - if( LFLAG(ir) ) {
1.95 - /* LDRH */
1.96 - } else {
1.97 - /* STRH */
1.98 + operand = arm_get_address3_operand(ir);
1.99 + if( LFLAG(ir) ) { /* LDRH */
1.100 + LRD(ir) = MEM_READ_WORD( operand ) & 0x0000FFFF;
1.101 + } else { /* STRH */
1.102 + MEM_WRITE_WORD( operand, RD(ir) );
1.103 }
1.104 - UNIMP(ir);
1.105 break;
1.106 case 2:
1.107 - if( LFLAG(ir) ) {
1.108 - /* LDRSB */
1.109 + if( LFLAG(ir) ) { /* LDRSB */
1.110 + operand = arm_get_address3_operand(ir);
1.111 + LRD(ir) = SIGNEXT8( MEM_READ_BYTE( operand ) );
1.112 } else {
1.113 + UNIMP(ir);
1.114 }
1.115 - UNIMP(ir);
1.116 break;
1.117 case 3:
1.118 - if( LFLAG(ir) ) {
1.119 - /* LDRSH */
1.120 + if( LFLAG(ir) ) { /* LDRSH */
1.121 + operand = arm_get_address3_operand(ir);
1.122 + LRD(ir) = SIGNEXT16( MEM_READ_WORD( operand ) );
1.123 } else {
1.124 + UNIMP(ir);
1.125 }
1.126 - UNIMP(ir);
1.127 break;
1.128 }
1.129 } else {
.