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