Search
lxdream.org :: lxdream/src/aica/armcore.c
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
view annotate diff log raw
     1 /**
     2  * $Id$
     3  * 
     4  * ARM7TDMI CPU emulation core.
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #define MODULE aica_module
    20 #include "dream.h"
    21 #include "dreamcast.h"
    22 #include "mem.h"
    23 #include "aica/armcore.h"
    24 #include "aica/aica.h"
    26 #define STM_R15_OFFSET 12
    28 struct arm_registers armr;
    30 void arm_set_mode( int mode );
    32 uint32_t arm_exceptions[][2] = {{ MODE_SVC, 0x00000000 },
    33         { MODE_UND, 0x00000004 },
    34         { MODE_SVC, 0x00000008 },
    35         { MODE_ABT, 0x0000000C },
    36         { MODE_ABT, 0x00000010 },
    37         { MODE_IRQ, 0x00000018 },
    38         { MODE_FIQ, 0x0000001C } };
    40 #define EXC_RESET 0
    41 #define EXC_UNDEFINED 1
    42 #define EXC_SOFTWARE 2
    43 #define EXC_PREFETCH_ABORT 3
    44 #define EXC_DATA_ABORT 4
    45 #define EXC_IRQ 5
    46 #define EXC_FAST_IRQ 6
    48 uint32_t arm_cpu_freq = ARM_BASE_RATE;
    49 uint32_t arm_cpu_period = 1000 / ARM_BASE_RATE;
    51 #define CYCLES_PER_SAMPLE ((ARM_BASE_RATE * 1000000) / AICA_SAMPLE_RATE)
    53 static struct breakpoint_struct arm_breakpoints[MAX_BREAKPOINTS];
    54 static int arm_breakpoint_count = 0;
    56 void arm_set_breakpoint( uint32_t pc, breakpoint_type_t type )
    57 {
    58     arm_breakpoints[arm_breakpoint_count].address = pc;
    59     arm_breakpoints[arm_breakpoint_count].type = type;
    60     arm_breakpoint_count++;
    61 }
    63 gboolean arm_clear_breakpoint( uint32_t pc, breakpoint_type_t type )
    64 {
    65     int i;
    67     for( i=0; i<arm_breakpoint_count; i++ ) {
    68         if( arm_breakpoints[i].address == pc && 
    69                 arm_breakpoints[i].type == type ) {
    70             while( ++i < arm_breakpoint_count ) {
    71                 arm_breakpoints[i-1].address = arm_breakpoints[i].address;
    72                 arm_breakpoints[i-1].type = arm_breakpoints[i].type;
    73             }
    74             arm_breakpoint_count--;
    75             return TRUE;
    76         }
    77     }
    78     return FALSE;
    79 }
    81 int arm_get_breakpoint( uint32_t pc )
    82 {
    83     int i;
    84     for( i=0; i<arm_breakpoint_count; i++ ) {
    85         if( arm_breakpoints[i].address == pc )
    86             return arm_breakpoints[i].type;
    87     }
    88     return 0;
    89 }
    91 uint32_t arm_run_slice( uint32_t num_samples )
    92 {
    93     int i,j,k;
    95     if( !armr.running )
    96         return num_samples;
    98     for( i=0; i<num_samples; i++ ) {
    99         for( j=0; j < CYCLES_PER_SAMPLE; j++ ) {
   100             armr.icount++;
   101             if( !arm_execute_instruction() )
   102                 return i;
   103 #ifdef ENABLE_DEBUG_MODE
   104             for( k=0; k<arm_breakpoint_count; k++ ) {
   105                 if( arm_breakpoints[k].address == armr.r[15] ) {
   106                     dreamcast_stop();
   107                     if( arm_breakpoints[k].type == BREAK_ONESHOT )
   108                         arm_clear_breakpoint( armr.r[15], BREAK_ONESHOT );
   109                     return i;
   110                 }
   111             }
   112 #endif	
   113         }
   115         k = MMIO_READ( AICA2, AICA_TCR );
   116         uint8_t val = MMIO_READ( AICA2, AICA_TIMER );
   117         val++;
   118         if( val == 0 ) {
   119             aica_event( AICA_EVENT_TIMER );
   120             // MMIO_WRITE( AICA2, AICA_TCR, k & ~0x40 );
   121         }
   122         MMIO_WRITE( AICA2, AICA_TIMER, val );
   123         if( !dreamcast_is_running() )
   124             break;
   125     }
   127     return i;
   128 }
   130 void arm_save_state( FILE *f )
   131 {
   132     fwrite( &armr, sizeof(armr), 1, f );
   133 }
   135 int arm_load_state( FILE *f )
   136 {
   137     fread( &armr, sizeof(armr), 1, f );
   138     return 0;
   139 }
   141 /* Exceptions */
   142 void arm_reset( void )
   143 {
   144     /* Wipe all processor state */
   145     memset( &armr, 0, sizeof(armr) );
   147     armr.cpsr = MODE_SVC | CPSR_I | CPSR_F;
   148     armr.r[15] = 0x00000000;
   149     armr.running = TRUE;
   150 }
   152 #define SET_CPSR_CONTROL   0x00010000
   153 #define SET_CPSR_EXTENSION 0x00020000
   154 #define SET_CPSR_STATUS    0x00040000
   155 #define SET_CPSR_FLAGS     0x00080000
   157 uint32_t arm_get_cpsr( void )
   158 {
   159     /* write back all flags to the cpsr */
   160     armr.cpsr = armr.cpsr & CPSR_COMPACT_MASK;
   161     if( armr.n ) armr.cpsr |= CPSR_N;
   162     if( armr.z ) armr.cpsr |= CPSR_Z;
   163     if( armr.c ) armr.cpsr |= CPSR_C;
   164     if( armr.v ) armr.cpsr |= CPSR_V;
   165     if( armr.t ) armr.cpsr |= CPSR_T;  
   166     return armr.cpsr;
   167 }
   169 /**
   170  * Return a pointer to the specified register in the user bank,
   171  * regardless of the active bank
   172  */
   173 static uint32_t *arm_user_reg( int reg )
   174 {
   175     if( IS_EXCEPTION_MODE() ) {
   176         if( reg == 13 || reg == 14 )
   177             return &armr.user_r[reg-8];
   178         if( IS_FIQ_MODE() ) {
   179             if( reg >= 8 || reg <= 12 )
   180                 return &armr.user_r[reg-8];
   181         }
   182     }
   183     return &armr.r[reg];
   184 }
   186 #define USER_R(n) *arm_user_reg(n)
   188 /**
   189  * Set the CPSR to the specified value.
   190  *
   191  * @param value values to set in CPSR
   192  * @param fields set of mask values to define which sections of the 
   193  *   CPSR to set (one of the SET_CPSR_* values above)
   194  */
   195 void arm_set_cpsr( uint32_t value, uint32_t fields )
   196 {
   197     if( IS_PRIVILEGED_MODE() ) {
   198         if( fields & SET_CPSR_CONTROL ) {
   199             int mode = value & CPSR_MODE;
   200             arm_set_mode( mode );
   201             armr.t = ( value & CPSR_T ); /* Technically illegal to change */
   202             armr.cpsr = (armr.cpsr & 0xFFFFFF00) | (value & 0x000000FF);
   203         }
   205         /* Middle 16 bits not currently defined */
   206     }
   207     if( fields & SET_CPSR_FLAGS ) {
   208         /* Break flags directly out of given value - don't bother writing
   209          * back to CPSR 
   210          */
   211         armr.n = ( value & CPSR_N );
   212         armr.z = ( value & CPSR_Z );
   213         armr.c = ( value & CPSR_C );
   214         armr.v = ( value & CPSR_V );
   215     }
   216 }
   218 void arm_set_spsr( uint32_t value, uint32_t fields )
   219 {
   220     /* Only defined if we actually have an SPSR register */
   221     if( IS_EXCEPTION_MODE() ) {
   222         if( fields & SET_CPSR_CONTROL ) {
   223             armr.spsr = (armr.spsr & 0xFFFFFF00) | (value & 0x000000FF);
   224         }
   226         /* Middle 16 bits not currently defined */
   228         if( fields & SET_CPSR_FLAGS ) {
   229             armr.spsr = (armr.spsr & 0x00FFFFFF) | (value & 0xFF000000);
   230         }
   231     }
   232 }
   234 /**
   235  * Raise an ARM exception (other than reset, which uses arm_reset().
   236  * @param exception one of the EXC_* exception codes defined above.
   237  */
   238 void arm_raise_exception( int exception )
   239 {
   240     int mode = arm_exceptions[exception][0];
   241     uint32_t spsr = arm_get_cpsr();
   242     arm_set_mode( mode );
   243     armr.spsr = spsr;
   244     armr.r[14] = armr.r[15] + 4;
   245     armr.cpsr = (spsr & 0xFFFFFF00) | mode | CPSR_I; 
   246     if( mode == MODE_FIQ )
   247         armr.cpsr |= CPSR_F;
   248     armr.r[15] = arm_exceptions[exception][1];
   249 }
   251 void arm_restore_cpsr( void )
   252 {
   253     int spsr = armr.spsr;
   254     int mode = spsr & CPSR_MODE;
   255     arm_set_mode( mode );
   256     armr.cpsr = spsr;
   257     armr.n = ( spsr & CPSR_N );
   258     armr.z = ( spsr & CPSR_Z );
   259     armr.c = ( spsr & CPSR_C );
   260     armr.v = ( spsr & CPSR_V );
   261     armr.t = ( spsr & CPSR_T );
   262 }
   266 /**
   267  * Change the current executing ARM mode to the requested mode.
   268  * Saves any required registers to banks and restores those for the
   269  * correct mode. (Note does not actually update CPSR at the moment).
   270  */
   271 void arm_set_mode( int targetMode )
   272 {
   273     int currentMode = armr.cpsr & CPSR_MODE;
   274     if( currentMode == targetMode )
   275         return;
   277     switch( currentMode ) {
   278     case MODE_USER:
   279     case MODE_SYS:
   280         armr.user_r[5] = armr.r[13];
   281         armr.user_r[6] = armr.r[14];
   282         break;
   283     case MODE_SVC:
   284         armr.svc_r[0] = armr.r[13];
   285         armr.svc_r[1] = armr.r[14];
   286         armr.svc_r[2] = armr.spsr;
   287         break;
   288     case MODE_ABT:
   289         armr.abt_r[0] = armr.r[13];
   290         armr.abt_r[1] = armr.r[14];
   291         armr.abt_r[2] = armr.spsr;
   292         break;
   293     case MODE_UND:
   294         armr.und_r[0] = armr.r[13];
   295         armr.und_r[1] = armr.r[14];
   296         armr.und_r[2] = armr.spsr;
   297         break;
   298     case MODE_IRQ:
   299         armr.irq_r[0] = armr.r[13];
   300         armr.irq_r[1] = armr.r[14];
   301         armr.irq_r[2] = armr.spsr;
   302         break;
   303     case MODE_FIQ:
   304         armr.fiq_r[0] = armr.r[8];
   305         armr.fiq_r[1] = armr.r[9];
   306         armr.fiq_r[2] = armr.r[10];
   307         armr.fiq_r[3] = armr.r[11];
   308         armr.fiq_r[4] = armr.r[12];
   309         armr.fiq_r[5] = armr.r[13];
   310         armr.fiq_r[6] = armr.r[14];
   311         armr.fiq_r[7] = armr.spsr;
   312         armr.r[8] = armr.user_r[0];
   313         armr.r[9] = armr.user_r[1];
   314         armr.r[10] = armr.user_r[2];
   315         armr.r[11] = armr.user_r[3];
   316         armr.r[12] = armr.user_r[4];
   317         break;
   318     }
   320     switch( targetMode ) {
   321     case MODE_USER:
   322     case MODE_SYS:
   323         armr.r[13] = armr.user_r[5];
   324         armr.r[14] = armr.user_r[6];
   325         break;
   326     case MODE_SVC:
   327         armr.r[13] = armr.svc_r[0];
   328         armr.r[14] = armr.svc_r[1];
   329         armr.spsr = armr.svc_r[2];
   330         break;
   331     case MODE_ABT:
   332         armr.r[13] = armr.abt_r[0];
   333         armr.r[14] = armr.abt_r[1];
   334         armr.spsr = armr.abt_r[2];
   335         break;
   336     case MODE_UND:
   337         armr.r[13] = armr.und_r[0];
   338         armr.r[14] = armr.und_r[1];
   339         armr.spsr = armr.und_r[2];
   340         break;
   341     case MODE_IRQ:
   342         armr.r[13] = armr.irq_r[0];
   343         armr.r[14] = armr.irq_r[1];
   344         armr.spsr = armr.irq_r[2];
   345         break;
   346     case MODE_FIQ:
   347         armr.user_r[0] = armr.r[8];
   348         armr.user_r[1] = armr.r[9];
   349         armr.user_r[2] = armr.r[10];
   350         armr.user_r[3] = armr.r[11];
   351         armr.user_r[4] = armr.r[12];
   352         armr.r[8] = armr.fiq_r[0];
   353         armr.r[9] = armr.fiq_r[1];
   354         armr.r[10] = armr.fiq_r[2];
   355         armr.r[11] = armr.fiq_r[3];
   356         armr.r[12] = armr.fiq_r[4];
   357         armr.r[13] = armr.fiq_r[5];
   358         armr.r[14] = armr.fiq_r[6];
   359         armr.spsr = armr.fiq_r[7];
   360         break;
   361     }
   362 }
   364 /* Page references are as per ARM DDI 0100E (June 2000) */
   366 #define MEM_READ_BYTE( addr ) arm_read_byte(addr)
   367 #define MEM_READ_WORD( addr ) arm_read_word(addr)
   368 #define MEM_READ_LONG( addr ) arm_read_long(addr)
   369 #define MEM_WRITE_BYTE( addr, val ) arm_write_byte(addr, val)
   370 #define MEM_WRITE_WORD( addr, val ) arm_write_word(addr, val)
   371 #define MEM_WRITE_LONG( addr, val ) arm_write_long(addr, val)
   374 #define IS_NOTBORROW( result, op1, op2 ) (op2 > op1 ? 0 : 1)
   375 #define IS_CARRY( result, op1, op2 ) (result < op1 ? 1 : 0)
   376 #define IS_SUBOVERFLOW( result, op1, op2 ) (((op1^op2) & (result^op1)) >> 31)
   377 #define IS_ADDOVERFLOW( result, op1, op2 ) (((op1&op2) & (result^op1)) >> 31)
   379 #define PC armr.r[15]
   381 /* Instruction fields */
   382 #define COND(ir) (ir>>28)
   383 #define GRP(ir) ((ir>>26)&0x03)
   384 #define OPCODE(ir) ((ir>>20)&0x1F)
   385 #define IFLAG(ir) (ir&0x02000000)
   386 #define SFLAG(ir) (ir&0x00100000)
   387 #define PFLAG(ir) (ir&0x01000000)
   388 #define UFLAG(ir) (ir&0x00800000)
   389 #define BFLAG(ir) (ir&0x00400000)
   390 #define WFLAG(ir) (ir&0x00200000)
   391 #define LFLAG(ir) SFLAG(ir)
   392 #define RN(ir) (armr.r[((ir>>16)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
   393 #define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>12)&0x0F) == 0x0F ? 4 : 0))
   394 #define RDn(ir) ((ir>>12)&0x0F)
   395 #define RS(ir) (armr.r[((ir>>8)&0x0F)] + (((ir>>8)&0x0F) == 0x0F ? 4 : 0))
   396 #define RM(ir) (armr.r[(ir&0x0F)] + (((ir&0x0F) == 0x0F ? 4 : 0)) )
   397 #define LRN(ir) armr.r[((ir>>16)&0x0F)]
   398 #define LRD(ir) armr.r[((ir>>12)&0x0F)]
   399 #define LRS(ir) armr.r[((ir>>8)&0x0F)]
   400 #define LRM(ir) armr.r[(ir&0x0F)]
   402 #define IMM8(ir) (ir&0xFF)
   403 #define IMM12(ir) (ir&0xFFF)
   404 #define IMMSPLIT8(ir) (((ir&0xF00)>>4)|(ir&0x0F))
   405 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
   406 #define IMMROT(ir) ((ir>>7)&0x1E)
   407 #define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
   408 #define SIGNEXT24(n) (((n)&0x00800000) ? ((n)|0xFF000000) : ((n)&0x00FFFFFF))
   409 #define SIGNEXT8(n) ((int32_t)((int8_t)(n)))
   410 #define SIGNEXT16(n) ((int32_t)((int16_t)(n)))
   411 #define SHIFT(ir) ((ir>>4)&0x07)
   412 #define DISP24(ir) ((ir&0x00FFFFFF))
   413 #define UNDEF(ir) do{ arm_raise_exception( EXC_UNDEFINED ); return TRUE; } while(0)
   414 #define UNIMP(ir) do{ PC-=4; ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC, ir ); dreamcast_stop(); return FALSE; }while(0)
   416 /**
   417  * Determine the value of the shift-operand for a data processing instruction,
   418  * without determing a value for shift_C (optimized form for instructions that
   419  * don't require shift_C ).
   420  * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
   421  */
   422 static uint32_t arm_get_shift_operand( uint32_t ir )
   423 {
   424     uint32_t operand, tmp;
   425     if( IFLAG(ir) == 0 ) {
   426         operand = RM(ir);
   427         switch(SHIFT(ir)) {
   428         case 0: /* (Rm << imm) */
   429             operand = operand << SHIFTIMM(ir);
   430             break;
   431         case 1: /* (Rm << Rs) */
   432             tmp = RS(ir)&0xFF;
   433             if( tmp > 31 ) operand = 0;
   434             else operand = operand << tmp;
   435             break;
   436         case 2: /* (Rm >> imm) */
   437             operand = operand >> SHIFTIMM(ir);
   438             break;
   439         case 3: /* (Rm >> Rs) */
   440             tmp = RS(ir) & 0xFF;
   441             if( tmp > 31 ) operand = 0;
   442             else operand = operand >> ir;
   443             break;
   444         case 4: /* (Rm >>> imm) */
   445             tmp = SHIFTIMM(ir);
   446             if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
   447             else operand = ((int32_t)operand) >> tmp;
   448             break;
   449         case 5: /* (Rm >>> Rs) */
   450             tmp = RS(ir) & 0xFF;
   451             if( tmp > 31 ) operand = ((int32_t)operand) >> 31;
   452             else operand = ((int32_t)operand) >> tmp;
   453             break;
   454         case 6:
   455             tmp = SHIFTIMM(ir);
   456             if( tmp == 0 ) /* RRX aka rotate with carry */
   457                 operand = (operand >> 1) | (armr.c<<31);
   458             else
   459                 operand = ROTATE_RIGHT_LONG(operand,tmp);
   460             break;
   461         case 7:
   462             tmp = RS(ir)&0x1F;
   463             operand = ROTATE_RIGHT_LONG(operand,tmp);
   464             break;
   465         }
   466     } else {
   467         operand = IMM8(ir);
   468         tmp = IMMROT(ir);
   469         operand = ROTATE_RIGHT_LONG(operand, tmp);
   470     }
   471     return operand;
   472 }
   474 /**
   475  * Determine the value of the shift-operand for a data processing instruction,
   476  * and set armr.shift_c accordingly.
   477  * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
   478  */
   479 static uint32_t arm_get_shift_operand_s( uint32_t ir )
   480 {
   481     uint32_t operand, tmp;
   482     if( IFLAG(ir) == 0 ) {
   483         operand = RM(ir);
   484         switch(SHIFT(ir)) {
   485         case 0: /* (Rm << imm) */
   486             tmp = SHIFTIMM(ir);
   487             if( tmp == 0 ) { /* Rm */
   488                 armr.shift_c = armr.c;
   489             } else { /* Rm << imm */
   490                 armr.shift_c = (operand >> (32-tmp)) & 0x01;
   491                 operand = operand << tmp;
   492             }
   493             break;
   494         case 1: /* (Rm << Rs) */
   495             tmp = RS(ir)&0xFF;
   496             if( tmp == 0 ) {
   497                 armr.shift_c = armr.c;
   498             } else {
   499                 if( tmp <= 32 )
   500                     armr.shift_c = (operand >> (32-tmp)) & 0x01;
   501                 else armr.shift_c = 0;
   502                 if( tmp < 32 )
   503                     operand = operand << tmp;
   504                 else operand = 0;
   505             }
   506             break;
   507         case 2: /* (Rm >> imm) */
   508             tmp = SHIFTIMM(ir);
   509             if( tmp == 0 ) {
   510                 armr.shift_c = operand >> 31;
   511                 operand = 0;
   512             } else {
   513                 armr.shift_c = (operand >> (tmp-1)) & 0x01;
   514                 operand = RM(ir) >> tmp;
   515             }
   516             break;
   517         case 3: /* (Rm >> Rs) */
   518             tmp = RS(ir) & 0xFF;
   519             if( tmp == 0 ) {
   520                 armr.shift_c = armr.c;
   521             } else {
   522                 if( tmp <= 32 )
   523                     armr.shift_c = (operand >> (tmp-1))&0x01;
   524                 else armr.shift_c = 0;
   525                 if( tmp < 32 )
   526                     operand = operand >> tmp;
   527                 else operand = 0;
   528             }
   529             break;
   530         case 4: /* (Rm >>> imm) */
   531             tmp = SHIFTIMM(ir);
   532             if( tmp == 0 ) {
   533                 armr.shift_c = operand >> 31;
   534                 operand = -armr.shift_c;
   535             } else {
   536                 armr.shift_c = (operand >> (tmp-1)) & 0x01;
   537                 operand = ((int32_t)operand) >> tmp;
   538             }
   539             break;
   540         case 5: /* (Rm >>> Rs) */
   541             tmp = RS(ir) & 0xFF;
   542             if( tmp == 0 ) {
   543                 armr.shift_c = armr.c;
   544             } else {
   545                 if( tmp < 32 ) {
   546                     armr.shift_c = (operand >> (tmp-1))&0x01;
   547                     operand = ((int32_t)operand) >> tmp;
   548                 } else {
   549                     armr.shift_c = operand >> 31;
   550                     operand = ((int32_t)operand) >> 31;
   551                 }
   552             }
   553             break;
   554         case 6:
   555             tmp = SHIFTIMM(ir);
   556             if( tmp == 0 ) { /* RRX aka rotate with carry */
   557                 armr.shift_c = operand&0x01;
   558                 operand = (operand >> 1) | (armr.c<<31);
   559             } else {
   560                 armr.shift_c = operand>>(tmp-1);
   561                 operand = ROTATE_RIGHT_LONG(operand,tmp);
   562             }
   563             break;
   564         case 7:
   565             tmp = RS(ir)&0xFF;
   566             if( tmp == 0 ) {
   567                 armr.shift_c = armr.c;
   568             } else {
   569                 tmp &= 0x1F;
   570                 if( tmp == 0 ) {
   571                     armr.shift_c = operand>>31;
   572                 } else {
   573                     armr.shift_c = (operand>>(tmp-1))&0x1;
   574                     operand = ROTATE_RIGHT_LONG(operand,tmp);
   575                 }
   576             }
   577             break;
   578         }
   579     } else {
   580         operand = IMM8(ir);
   581         tmp = IMMROT(ir);
   582         if( tmp == 0 ) {
   583             armr.shift_c = armr.c;
   584         } else {
   585             operand = ROTATE_RIGHT_LONG(operand, tmp);
   586             armr.shift_c = operand>>31;
   587         }
   588     }
   589     return operand;
   590 }
   592 /**
   593  * Another variant of the shifter code for index-based memory addressing.
   594  * Distinguished by the fact that it doesn't support register shifts, and
   595  * ignores the I flag (WTF do the load/store instructions use the I flag to
   596  * mean the _exact opposite_ of what it means for the data processing 
   597  * instructions ???)
   598  */
   599 static uint32_t arm_get_address_index( uint32_t ir )
   600 {
   601     uint32_t operand = RM(ir);
   602     uint32_t tmp;
   604     switch(SHIFT(ir)) {
   605     case 0: /* (Rm << imm) */
   606         operand = operand << SHIFTIMM(ir);
   607         break;
   608     case 2: /* (Rm >> imm) */
   609         operand = operand >> SHIFTIMM(ir);
   610         break;
   611     case 4: /* (Rm >>> imm) */
   612         tmp = SHIFTIMM(ir);
   613         if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
   614         else operand = ((int32_t)operand) >> tmp;
   615         break;
   616     case 6:
   617         tmp = SHIFTIMM(ir);
   618         if( tmp == 0 ) /* RRX aka rotate with carry */
   619             operand = (operand >> 1) | (armr.c<<31);
   620         else
   621             operand = ROTATE_RIGHT_LONG(operand,tmp);
   622         break;
   623     default: UNIMP(ir);
   624     }
   625     return operand;	
   626 }
   628 /**
   629  * Determine the address operand of a load/store instruction, including
   630  * applying any pre/post adjustments to the address registers.
   631  * @see s5.2 Addressing Mode 2 - Load and Store Word or Unsigned Byte
   632  * @param The instruction word.
   633  * @return The calculated address
   634  */
   635 static uint32_t arm_get_address_operand( uint32_t ir )
   636 {
   637     uint32_t addr=0;
   639     /* I P U . W */
   640     switch( (ir>>21)&0x1D ) {
   641     case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
   642     case 1:
   643         addr = RN(ir);
   644         LRN(ir) = addr - IMM12(ir);
   645         break;
   646     case 4: /* Rn += imm offsett (post-indexed) [5.2.8 A5-28] */
   647     case 5:
   648         addr = RN(ir);
   649         LRN(ir) = addr + IMM12(ir);
   650         break;
   651     case 8: /* Rn - imm offset  [5.2.2 A5-20] */
   652         addr = RN(ir) - IMM12(ir);
   653         break;
   654     case 9: /* Rn -= imm offset (pre-indexed)  [5.2.5 A5-24] */
   655         addr = RN(ir) - IMM12(ir);
   656         LRN(ir) = addr;
   657         break;
   658     case 12: /* Rn + imm offset  [5.2.2 A5-20] */
   659         addr = RN(ir) + IMM12(ir);
   660         break;
   661     case 13: /* Rn += imm offset  [5.2.5 A5-24 ] */
   662         addr = RN(ir) + IMM12(ir);
   663         LRN(ir) = addr;
   664         break;
   665     case 16: /* Rn -= Rm (post-indexed)  [5.2.10 A5-32 ] */
   666     case 17:
   667         addr = RN(ir);
   668         LRN(ir) = addr - arm_get_address_index(ir);
   669         break;
   670     case 20: /* Rn += Rm (post-indexed)  [5.2.10 A5-32 ] */
   671     case 21:
   672         addr = RN(ir);
   673         LRN(ir) = addr - arm_get_address_index(ir);
   674         break;
   675     case 24: /* Rn - Rm  [5.2.4 A5-23] */
   676         addr = RN(ir) - arm_get_address_index(ir);
   677         break;
   678     case 25: /* RN -= Rm (pre-indexed)  [5.2.7 A5-26] */
   679         addr = RN(ir) - arm_get_address_index(ir);
   680         LRN(ir) = addr;
   681         break;
   682     case 28: /* Rn + Rm  [5.2.4 A5-23] */
   683         addr = RN(ir) + arm_get_address_index(ir);
   684         break;
   685     case 29: /* RN += Rm (pre-indexed) [5.2.7 A5-26] */
   686         addr = RN(ir) + arm_get_address_index(ir);
   687         LRN(ir) = addr;
   688         break;
   689     }
   690     return addr;
   691 }
   693 /**
   694  * Determine the address operand of a miscellaneous load/store instruction, 
   695  * including applying any pre/post adjustments to the address registers.
   696  * @see s5.3 Addressing Mode 3 - Miscellaneous Loads and Stores
   697  * @param The instruction word.
   698  * @return The calculated address
   699  */
   700 static uint32_t arm_get_address3_operand( uint32_t ir )
   701 {
   702     uint32_t addr=0;
   704     /* x x P U x W */
   705     switch( (ir>>21)&0x0F ) {
   706     case 0: /* Rn -= Rm (post-indexed) [5.3.7 A5-48] */
   707     case 1: /* UNPREDICTABLE */
   708     	addr = RN(ir);
   709     	LRN(ir) -= RM(ir);
   710     	break;
   711     case 2: /* Rn -= imm (post-indexed) [5.3.6 A5-46] */
   712     case 3: /* UNPREDICTABLE */
   713     	addr = RN(ir);
   714     	LRN(ir) -= IMMSPLIT8(ir);
   715     	break;
   716     case 4: /* Rn += Rm (post-indexed) [5.3.7 A5-48] */
   717     case 5: /* UNPREDICTABLE */
   718     	addr = RN(ir);
   719     	LRN(ir) += RM(ir);
   720     	break;
   721     case 6: /* Rn += imm (post-indexed) [5.3.6 A5-44] */
   722     case 7: /* UNPREDICTABLE */
   723     	addr = RN(ir);
   724     	LRN(ir) += IMMSPLIT8(ir);
   725     	break;
   726     case 8: /* Rn - Rm [5.3.3 A5-38] */
   727     	addr = RN(ir) - RM(ir);
   728     	break;
   729     case 9: /* Rn -= Rm (pre-indexed) [5.3.5 A5-42] */
   730     	addr = RN(ir) - RM(ir);
   731     	LRN(ir) = addr;
   732     	break;
   733     case 10: /* Rn - imm offset [5.3.2 A5-36] */
   734     	addr = RN(ir) - IMMSPLIT8(ir);
   735     	break;
   736     case 11: /* Rn -= imm offset (pre-indexed) [5.3.4 A5-40] */
   737     	addr = RN(ir) - IMMSPLIT8(ir);
   738     	LRN(ir) = addr;
   739     	break;
   740     case 12: /* Rn + Rm [5.3.3 A5-38] */
   741     	addr = RN(ir) + RM(ir);
   742     	break;
   743     case 13: /* Rn += Rm (pre-indexed) [5.3.5 A5-42] */
   744     	addr = RN(ir) + RM(ir);
   745     	LRN(ir) = addr;
   746     	break;
   747     case 14: /* Rn + imm offset [5.3.2 A5-36] */
   748     	addr = RN(ir) + IMMSPLIT8(ir);
   749     	break;
   750     case 15: /* Rn += imm offset (pre-indexed) [5.3.4 A5-40] */
   751     	addr = RN(ir) + IMMSPLIT8(ir);
   752     	LRN(ir) = addr;
   753     	break;
   755     }
   756     return addr;	
   757 }
   759 gboolean arm_execute_instruction( void ) 
   760 {
   761     uint32_t pc;
   762     uint32_t ir;
   763     uint32_t operand, operand2, tmp, tmp2, cond;
   764     int i;
   766     tmp = armr.int_pending & (~armr.cpsr);
   767     if( tmp ) {
   768         if( tmp & CPSR_F ) {
   769             arm_raise_exception( EXC_FAST_IRQ );
   770         } else {
   771             arm_raise_exception( EXC_IRQ );
   772         }
   773     }
   775     ir = MEM_READ_LONG(PC);
   776     pc = PC + 4;
   777     PC = pc;
   779     /** 
   780      * Check the condition bits first - if the condition fails return 
   781      * immediately without actually looking at the rest of the instruction.
   782      */
   783     switch( COND(ir) ) {
   784     case 0: /* EQ */ 
   785         cond = armr.z;
   786         break;
   787     case 1: /* NE */
   788         cond = !armr.z;
   789         break;
   790     case 2: /* CS/HS */
   791         cond = armr.c;
   792         break;
   793     case 3: /* CC/LO */
   794         cond = !armr.c;
   795         break;
   796     case 4: /* MI */
   797         cond = armr.n;
   798         break;
   799     case 5: /* PL */
   800         cond = !armr.n;
   801         break;
   802     case 6: /* VS */
   803         cond = armr.v;
   804         break;
   805     case 7: /* VC */
   806         cond = !armr.v;
   807         break;
   808     case 8: /* HI */
   809         cond = armr.c && !armr.z;
   810         break;
   811     case 9: /* LS */
   812         cond = (!armr.c) || armr.z;
   813         break;
   814     case 10: /* GE */
   815         cond = (armr.n == armr.v);
   816         break;
   817     case 11: /* LT */
   818         cond = (armr.n != armr.v);
   819         break;
   820     case 12: /* GT */
   821         cond = (!armr.z) && (armr.n == armr.v);
   822         break;
   823     case 13: /* LE */
   824         cond = armr.z || (armr.n != armr.v);
   825         break;
   826     case 14: /* AL */
   827         cond = 1;
   828         break;
   829     case 15: /* (NV) */
   830     default:
   831         cond = 0;
   832         UNDEF(ir);
   833     }
   834     if( cond ) {
   836         /**
   837          * Condition passed, now for the actual instructions...
   838          */
   839         switch( GRP(ir) ) {
   840         case 0:
   841             if( (ir & 0x0D900000) == 0x01000000 ) {
   842                 /* Instructions that aren't actual data processing even though
   843                  * they sit in the DP instruction block.
   844                  */
   845                 switch( ir & 0x0FF000F0 ) {
   846                 case 0x01200010: /* BX Rd */
   847                     armr.t = ir & 0x01;
   848                     armr.r[15] = RM(ir) & 0xFFFFFFFE;
   849                     break;
   850                 case 0x01000000: /* MRS Rd, CPSR */
   851                     LRD(ir) = arm_get_cpsr();
   852                     break;
   853                 case 0x01400000: /* MRS Rd, SPSR */
   854                     LRD(ir) = armr.spsr;
   855                     break;
   856                 case 0x01200000: /* MSR CPSR, Rd */
   857                     arm_set_cpsr( RM(ir), ir );
   858                     break;
   859                 case 0x01600000: /* MSR SPSR, Rd */
   860                     arm_set_spsr( RM(ir), ir );
   861                     break;
   862                 case 0x03200000: /* MSR CPSR, imm */
   863                     arm_set_cpsr( ROTIMM12(ir), ir );
   864                     break;
   865                 case 0x03600000: /* MSR SPSR, imm */
   866                     arm_set_spsr( ROTIMM12(ir), ir );
   867                     break;
   868                 default:
   869                     UNIMP(ir);
   870                 }
   871             } else if( (ir & 0x0E000090) == 0x00000090 ) {
   872                 /* Neither are these */
   873                 switch( (ir>>5)&0x03 ) {
   874                 case 0:
   875                     /* Arithmetic extension area */
   876                     switch(OPCODE(ir)) {
   877                     case 0: /* MUL */
   878                         LRN(ir) = RM(ir) * RS(ir);
   879                         break;
   880                     case 1: /* MULS */
   881                         tmp = RM(ir) * RS(ir);
   882                         LRN(ir) = tmp;
   883                         armr.n = tmp>>31;
   884                         armr.z = (tmp == 0);
   885                         break;
   886                     case 2: /* MLA */
   887                         LRN(ir) = RM(ir) * RS(ir) + RD(ir);
   888                         break;
   889                     case 3: /* MLAS */
   890                         tmp = RM(ir) * RS(ir) + RD(ir);
   891                         LRN(ir) = tmp;
   892                         armr.n = tmp>>31;
   893                         armr.z = (tmp == 0);
   894                         break;
   895                     case 8: /* UMULL */
   896                     case 9: /* UMULLS */
   897                     case 10: /* UMLAL */
   898                     case 11: /* UMLALS */
   899                     case 12: /* SMULL */
   900                     case 13: /* SMULLS */
   901                     case 14: /* SMLAL */
   902                     case 15: /* SMLALS */
   903                         UNIMP(ir);
   904                         break;
   905                     case 16: /* SWP */
   906                         tmp = arm_read_long( RN(ir) );
   907                         switch( RN(ir) & 0x03 ) {
   908                         case 1:
   909                             tmp = ROTATE_RIGHT_LONG(tmp, 8);
   910                             break;
   911                         case 2:
   912                             tmp = ROTATE_RIGHT_LONG(tmp, 16);
   913                             break;
   914                         case 3:
   915                             tmp = ROTATE_RIGHT_LONG(tmp, 24);
   916                             break;
   917                         }
   918                         arm_write_long( RN(ir), RM(ir) );
   919                         LRD(ir) = tmp;
   920                         break;
   921                         case 20: /* SWPB */
   922                             tmp = arm_read_byte( RN(ir) );
   923                             arm_write_byte( RN(ir), RM(ir) );
   924                             LRD(ir) = tmp;
   925                             break;
   926                         default:
   927                             UNIMP(ir);
   928                     }
   929                     break;
   930                     case 1:
   931                     	operand = arm_get_address3_operand(ir);
   932                         if( LFLAG(ir) ) { /* LDRH */
   933                         	LRD(ir) = MEM_READ_WORD( operand ) & 0x0000FFFF;
   934                         } else { /* STRH */
   935                         	MEM_WRITE_WORD( operand, RD(ir) );
   936                         }
   937                         break;
   938                     case 2:
   939                         if( LFLAG(ir) ) { /* LDRSB */
   940                         	operand = arm_get_address3_operand(ir);
   941                         	LRD(ir) = SIGNEXT8( MEM_READ_BYTE( operand ) );
   942                         } else {
   943                             UNIMP(ir);
   944                         }
   945                         break;
   946                     case 3:
   947                         if( LFLAG(ir) ) { /* LDRSH */
   948                         	operand = arm_get_address3_operand(ir);
   949                         	LRD(ir) = SIGNEXT16( MEM_READ_WORD( operand ) );
   950                         } else {
   951                             UNIMP(ir);
   952                         }
   953                         break;
   954                 }
   955             } else {
   956                 /* Data processing */
   958                 switch(OPCODE(ir)) {
   959                 case 0: /* AND Rd, Rn, operand */
   960                     LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
   961                     break;
   962                 case 1: /* ANDS Rd, Rn, operand */
   963                     operand = arm_get_shift_operand_s(ir) & RN(ir);
   964                     LRD(ir) = operand;
   965                     if( RDn(ir) == 15 ) {
   966                         arm_restore_cpsr();
   967                     } else {
   968                         armr.n = operand>>31;
   969                         armr.z = (operand == 0);
   970                         armr.c = armr.shift_c;
   971                     }
   972                     break;
   973                 case 2: /* EOR Rd, Rn, operand */
   974                     LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
   975                     break;
   976                 case 3: /* EORS Rd, Rn, operand */
   977                     operand = arm_get_shift_operand_s(ir) ^ RN(ir);
   978                     LRD(ir) = operand;
   979                     if( RDn(ir) == 15 ) {
   980                         arm_restore_cpsr();
   981                     } else {
   982                         armr.n = operand>>31;
   983                         armr.z = (operand == 0);
   984                         armr.c = armr.shift_c;
   985                     }
   986                     break;
   987                 case 4: /* SUB Rd, Rn, operand */
   988                     LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
   989                     break;
   990                 case 5: /* SUBS Rd, Rn, operand */
   991                     operand = RN(ir);
   992                     operand2 = arm_get_shift_operand(ir);
   993                     tmp = operand - operand2;
   994                     LRD(ir) = tmp;
   995                     if( RDn(ir) == 15 ) {
   996                         arm_restore_cpsr();
   997                     } else {
   998                         armr.n = tmp>>31;
   999                         armr.z = (tmp == 0);
  1000                         armr.c = IS_NOTBORROW(tmp,operand,operand2);
  1001                         armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
  1003                     break;
  1004                 case 6: /* RSB Rd, operand, Rn */
  1005                     LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
  1006                     break;
  1007                 case 7: /* RSBS Rd, operand, Rn */
  1008                     operand = arm_get_shift_operand(ir);
  1009                     operand2 = RN(ir);
  1010                     tmp = operand - operand2;
  1011                     LRD(ir) = tmp;
  1012                     if( RDn(ir) == 15 ) {
  1013                         arm_restore_cpsr();
  1014                     } else {
  1015                         armr.n = tmp>>31;
  1016                         armr.z = (tmp == 0);
  1017                         armr.c = IS_NOTBORROW(tmp,operand,operand2);
  1018                         armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
  1020                     break;
  1021                 case 8: /* ADD Rd, Rn, operand */
  1022                     LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
  1023                     break;
  1024                 case 9: /* ADDS Rd, Rn, operand */
  1025                     operand = arm_get_shift_operand(ir);
  1026                     operand2 = RN(ir);
  1027                     tmp = operand + operand2;
  1028                     LRD(ir) = tmp;
  1029                     if( RDn(ir) == 15 ) {
  1030                         arm_restore_cpsr();
  1031                     } else {
  1032                         armr.n = tmp>>31;
  1033                         armr.z = (tmp == 0);
  1034                         armr.c = IS_CARRY(tmp,operand,operand2);
  1035                         armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
  1037                     break;			
  1038                 case 10: /* ADC */
  1039                     LRD(ir) = RN(ir) + arm_get_shift_operand(ir) + 
  1040                     (armr.c ? 1 : 0);
  1041                     break;
  1042                 case 11: /* ADCS */
  1043                     operand = arm_get_shift_operand(ir);
  1044                     operand2 = RN(ir);
  1045                     tmp = operand + operand2;
  1046                     tmp2 = tmp + armr.c ? 1 : 0;
  1047                     LRD(ir) = tmp2;
  1048                     if( RDn(ir) == 15 ) {
  1049                         arm_restore_cpsr();
  1050                     } else {
  1051                         armr.n = tmp >> 31;
  1052                         armr.z = (tmp == 0 );
  1053                         armr.c = IS_CARRY(tmp,operand,operand2) ||
  1054                         (tmp2 < tmp);
  1055                         armr.v = IS_ADDOVERFLOW(tmp,operand, operand2) ||
  1056                         ((tmp&0x80000000) != (tmp2&0x80000000));
  1058                     break;
  1059                 case 12: /* SBC */
  1060                     LRD(ir) = RN(ir) - arm_get_shift_operand(ir) - 
  1061                     (armr.c ? 0 : 1);
  1062                     break;
  1063                 case 13: /* SBCS */
  1064                     operand = RN(ir);
  1065                     operand2 = arm_get_shift_operand(ir);
  1066                     tmp = operand - operand2;
  1067                     tmp2 = tmp - (armr.c ? 0 : 1);
  1068                     if( RDn(ir) == 15 ) {
  1069                         arm_restore_cpsr();
  1070                     } else {
  1071                         armr.n = tmp >> 31;
  1072                         armr.z = (tmp == 0 );
  1073                         armr.c = IS_NOTBORROW(tmp,operand,operand2) &&
  1074                         (tmp2<tmp);
  1075                         armr.v = IS_SUBOVERFLOW(tmp,operand,operand2) ||
  1076                         ((tmp&0x80000000) != (tmp2&0x80000000));
  1078                     break;
  1079                 case 14: /* RSC */
  1080                     LRD(ir) = arm_get_shift_operand(ir) - RN(ir) -
  1081                     (armr.c ? 0 : 1);
  1082                     break;
  1083                 case 15: /* RSCS */
  1084                     operand = arm_get_shift_operand(ir);
  1085                     operand2 = RN(ir);
  1086                     tmp = operand - operand2;
  1087                     tmp2 = tmp - (armr.c ? 0 : 1);
  1088                     if( RDn(ir) == 15 ) {
  1089                         arm_restore_cpsr();
  1090                     } else {
  1091                         armr.n = tmp >> 31;
  1092                         armr.z = (tmp == 0 );
  1093                         armr.c = IS_NOTBORROW(tmp,operand,operand2) &&
  1094                         (tmp2<tmp);
  1095                         armr.v = IS_SUBOVERFLOW(tmp,operand,operand2) ||
  1096                         ((tmp&0x80000000) != (tmp2&0x80000000));
  1098                     break;
  1099                 case 17: /* TST Rn, operand */
  1100                     operand = arm_get_shift_operand_s(ir) & RN(ir);
  1101                     armr.n = operand>>31;
  1102                     armr.z = (operand == 0);
  1103                     armr.c = armr.shift_c;
  1104                     break;
  1105                 case 19: /* TEQ Rn, operand */
  1106                     operand = arm_get_shift_operand_s(ir) ^ RN(ir);
  1107                     armr.n = operand>>31;
  1108                     armr.z = (operand == 0);
  1109                     armr.c = armr.shift_c;
  1110                     break;				
  1111                 case 21: /* CMP Rn, operand */
  1112                     operand = RN(ir);
  1113                     operand2 = arm_get_shift_operand(ir);
  1114                     tmp = operand - operand2;
  1115                     armr.n = tmp>>31;
  1116                     armr.z = (tmp == 0);
  1117                     armr.c = IS_NOTBORROW(tmp,operand,operand2);
  1118                     armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
  1119                     break;
  1120                 case 23: /* CMN Rn, operand */
  1121                     operand = RN(ir);
  1122                     operand2 = arm_get_shift_operand(ir);
  1123                     tmp = operand + operand2;
  1124                     armr.n = tmp>>31;
  1125                     armr.z = (tmp == 0);
  1126                     armr.c = IS_CARRY(tmp,operand,operand2);
  1127                     armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
  1128                     break;
  1129                 case 24: /* ORR Rd, Rn, operand */
  1130                     LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
  1131                     break;
  1132                 case 25: /* ORRS Rd, Rn, operand */
  1133                     operand = arm_get_shift_operand_s(ir) | RN(ir);
  1134                     LRD(ir) = operand;
  1135                     if( RDn(ir) == 15 ) {
  1136                         arm_restore_cpsr();
  1137                     } else {
  1138                         armr.n = operand>>31;
  1139                         armr.z = (operand == 0);
  1140                         armr.c = armr.shift_c;
  1142                     break;
  1143                 case 26: /* MOV Rd, operand */
  1144                     LRD(ir) = arm_get_shift_operand(ir);
  1145                     break;
  1146                 case 27: /* MOVS Rd, operand */
  1147                     operand = arm_get_shift_operand_s(ir);
  1148                     LRD(ir) = operand;
  1149                     if( RDn(ir) == 15 ) {
  1150                         arm_restore_cpsr();
  1151                     } else {
  1152                         armr.n = operand>>31;
  1153                         armr.z = (operand == 0);
  1154                         armr.c = armr.shift_c;
  1156                     break;
  1157                 case 28: /* BIC Rd, Rn, operand */
  1158                     LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
  1159                     break;
  1160                 case 29: /* BICS Rd, Rn, operand */
  1161                     operand = RN(ir) & (~arm_get_shift_operand_s(ir));
  1162                     LRD(ir) = operand;
  1163                     if( RDn(ir) == 15 ) {
  1164                         arm_restore_cpsr();
  1165                     } else {
  1166                         armr.n = operand>>31;
  1167                         armr.z = (operand == 0);
  1168                         armr.c = armr.shift_c;
  1170                     break;
  1171                 case 30: /* MVN Rd, operand */
  1172                     LRD(ir) = ~arm_get_shift_operand(ir);
  1173                     break;
  1174                 case 31: /* MVNS Rd, operand */
  1175                     operand = ~arm_get_shift_operand_s(ir);
  1176                     LRD(ir) = operand;
  1177                     if( RDn(ir) == 15 ) {
  1178                         arm_restore_cpsr();
  1179                     } else {
  1180                         armr.n = operand>>31;
  1181                         armr.z = (operand == 0);
  1182                         armr.c = armr.shift_c;
  1184                     break;
  1185                 default:
  1186                     UNIMP(ir);
  1189             break;
  1190         case 1: /* Load/store */
  1191             operand = arm_get_address_operand(ir);
  1192             switch( (ir>>20)&0x17 ) {
  1193             case 0: case 16: case 18: /* STR Rd, address */
  1194                 arm_write_long( operand, RD(ir) );
  1195                 break;
  1196             case 1: case 17: case 19: /* LDR Rd, address */
  1197                 LRD(ir) = arm_read_long(operand);
  1198                 break;
  1199             case 2: /* STRT Rd, address */
  1200                 arm_write_long_user( operand, RD(ir) );
  1201                 break;
  1202             case 3: /* LDRT Rd, address */
  1203                 LRD(ir) = arm_read_long_user( operand );
  1204                 break;
  1205             case 4: case 20: case 22: /* STRB Rd, address */
  1206                 arm_write_byte( operand, RD(ir) );
  1207                 break;
  1208             case 5: case 21: case 23: /* LDRB Rd, address */
  1209                 LRD(ir) = arm_read_byte( operand );
  1210                 break;
  1211             case 6: /* STRBT Rd, address */
  1212                 arm_write_byte_user( operand, RD(ir) );
  1213                 break;
  1214             case 7: /* LDRBT Rd, address */
  1215                 LRD(ir) = arm_read_byte_user( operand );
  1216                 break;
  1218             break;
  1219             case 2: /* Load/store multiple, branch*/
  1220                 if( (ir & 0x02000000) == 0x02000000 ) { /* B[L] imm24 */
  1221                     operand = (SIGNEXT24(ir&0x00FFFFFF) << 2);
  1222                     if( (ir & 0x01000000) == 0x01000000 ) { 
  1223                         armr.r[14] = pc; /* BL */
  1225                     armr.r[15] = pc + 4 + operand;
  1226                 } else { /* Load/store multiple */
  1227                     gboolean needRestore = FALSE;
  1228                     operand = RN(ir);
  1230                     switch( (ir & 0x01D00000) >> 20 ) {
  1231                     case 0: /* STMDA */
  1232                         if( ir & 0x8000 ) {
  1233                             arm_write_long( operand, armr.r[15]+4 );
  1234                             operand -= 4;
  1236                         for( i=14; i>= 0; i-- ) {
  1237                             if( (ir & (1<<i)) ) {
  1238                                 arm_write_long( operand, armr.r[i] );
  1239                                 operand -= 4;
  1242                         break;
  1243                     case 1: /* LDMDA */
  1244                         for( i=15; i>= 0; i-- ) {
  1245                             if( (ir & (1<<i)) ) {
  1246                                 armr.r[i] = arm_read_long( operand );
  1247                                 operand -= 4;
  1250                         break;
  1251                     case 4: /* STMDA (S) */
  1252                         if( ir & 0x8000 ) {
  1253                             arm_write_long( operand, armr.r[15]+4 );
  1254                             operand -= 4;
  1256                         for( i=14; i>= 0; i-- ) {
  1257                             if( (ir & (1<<i)) ) {
  1258                                 arm_write_long( operand, USER_R(i) );
  1259                                 operand -= 4;
  1262                         break;
  1263                     case 5: /* LDMDA (S) */
  1264                         if( (ir&0x00008000) ) { /* Load PC */
  1265                             for( i=15; i>= 0; i-- ) {
  1266                                 if( (ir & (1<<i)) ) {
  1267                                     armr.r[i] = arm_read_long( operand );
  1268                                     operand -= 4;
  1271                             needRestore = TRUE;
  1272                         } else {
  1273                             for( i=15; i>= 0; i-- ) {
  1274                                 if( (ir & (1<<i)) ) {
  1275                                     USER_R(i) = arm_read_long( operand );
  1276                                     operand -= 4;
  1280                         break;
  1281                     case 8: /* STMIA */
  1282                         for( i=0; i< 15; i++ ) {
  1283                             if( (ir & (1<<i)) ) {
  1284                                 arm_write_long( operand, armr.r[i] );
  1285                                 operand += 4;
  1288                         if( ir & 0x8000 ) {
  1289                             arm_write_long( operand, armr.r[15]+4 );
  1290                             operand += 4;
  1292                         break;
  1293                     case 9: /* LDMIA */
  1294                         for( i=0; i< 16; i++ ) {
  1295                             if( (ir & (1<<i)) ) {
  1296                                 armr.r[i] = arm_read_long( operand );
  1297                                 operand += 4;
  1300                         break;
  1301                     case 12: /* STMIA (S) */
  1302                         for( i=0; i< 15; i++ ) {
  1303                             if( (ir & (1<<i)) ) {
  1304                                 arm_write_long( operand, USER_R(i) );
  1305                                 operand += 4;
  1308                         if( ir & 0x8000 ) {
  1309                             arm_write_long( operand, armr.r[15]+4 );
  1310                             operand += 4;
  1312                         break;
  1313                     case 13: /* LDMIA (S) */
  1314                         if( (ir&0x00008000) ) { /* Load PC */
  1315                             for( i=0; i < 16; i++ ) {
  1316                                 if( (ir & (1<<i)) ) {
  1317                                     armr.r[i] = arm_read_long( operand );
  1318                                     operand += 4;
  1321                             needRestore = TRUE;
  1322                         } else {
  1323                             for( i=0; i < 16; i++ ) {
  1324                                 if( (ir & (1<<i)) ) {
  1325                                     USER_R(i) = arm_read_long( operand );
  1326                                     operand += 4;
  1330                         break;
  1331                     case 16: /* STMDB */
  1332                         if( ir & 0x8000 ) {
  1333                             operand -= 4;
  1334                             arm_write_long( operand, armr.r[15]+4 );
  1336                         for( i=14; i>= 0; i-- ) {
  1337                             if( (ir & (1<<i)) ) {
  1338                                 operand -= 4;
  1339                                 arm_write_long( operand, armr.r[i] );
  1342                         break;
  1343                     case 17: /* LDMDB */
  1344                         for( i=15; i>= 0; i-- ) {
  1345                             if( (ir & (1<<i)) ) {
  1346                                 operand -= 4;
  1347                                 armr.r[i] = arm_read_long( operand );
  1350                         break;
  1351                     case 20: /* STMDB (S) */
  1352                         if( ir & 0x8000 ) {
  1353                             operand -= 4;
  1354                             arm_write_long( operand, armr.r[15]+4 );
  1356                         for( i=14; i>= 0; i-- ) {
  1357                             if( (ir & (1<<i)) ) {
  1358                                 operand -= 4;
  1359                                 arm_write_long( operand, USER_R(i) );
  1362                         break;
  1363                     case 21: /* LDMDB (S) */
  1364                         if( (ir&0x00008000) ) { /* Load PC */
  1365                             for( i=15; i>= 0; i-- ) {
  1366                                 if( (ir & (1<<i)) ) {
  1367                                     operand -= 4;
  1368                                     armr.r[i] = arm_read_long( operand );
  1371                             needRestore = TRUE;
  1372                         } else {
  1373                             for( i=15; i>= 0; i-- ) {
  1374                                 if( (ir & (1<<i)) ) {
  1375                                     operand -= 4;
  1376                                     USER_R(i) = arm_read_long( operand );
  1380                         break;
  1381                     case 24: /* STMIB */
  1382                         for( i=0; i< 15; i++ ) {
  1383                             if( (ir & (1<<i)) ) {
  1384                                 operand += 4;
  1385                                 arm_write_long( operand, armr.r[i] );
  1388                         if( ir & 0x8000 ) {
  1389                             operand += 4;
  1390                             arm_write_long( operand, armr.r[15]+4 );
  1392                         break;
  1393                     case 25: /* LDMIB */
  1394                         for( i=0; i< 16; i++ ) {
  1395                             if( (ir & (1<<i)) ) {
  1396                                 operand += 4;
  1397                                 armr.r[i] = arm_read_long( operand );
  1400                         break;
  1401                     case 28: /* STMIB (S) */
  1402                         for( i=0; i< 15; i++ ) {
  1403                             if( (ir & (1<<i)) ) {
  1404                                 operand += 4;
  1405                                 arm_write_long( operand, USER_R(i) );
  1408                         if( ir & 0x8000 ) {
  1409                             operand += 4;
  1410                             arm_write_long( operand, armr.r[15]+4 );
  1412                         break;
  1413                     case 29: /* LDMIB (S) */
  1414                         if( (ir&0x00008000) ) { /* Load PC */
  1415                             for( i=0; i < 16; i++ ) {
  1416                                 if( (ir & (1<<i)) ) {
  1417                                     operand += 4;
  1418                                     armr.r[i] = arm_read_long( operand );
  1421                             needRestore = TRUE;
  1422                         } else {
  1423                             for( i=0; i < 16; i++ ) {
  1424                                 if( (ir & (1<<i)) ) {
  1425                                     operand += 4;
  1426                                     USER_R(i) = arm_read_long( operand );
  1430                         break;
  1433                     if( WFLAG(ir) ) 
  1434                         LRN(ir) = operand;
  1435                     if( needRestore ) 
  1436                         arm_restore_cpsr();
  1438                 break;
  1439             case 3: /* Copro */
  1440                 if( (ir & 0x0F000000) == 0x0F000000 ) { /* SWI */
  1441                     arm_raise_exception( EXC_SOFTWARE );
  1442                 } else {
  1443                     UNIMP(ir);
  1445                 break;
  1450     if( armr.r[15] >= 0x00200000 ) {
  1451         armr.running = FALSE;
  1452         WARN( "ARM Halted: BRANCH to invalid address %08X at %08X", armr.r[15], pc );
  1453         return FALSE;
  1455     return TRUE;
.