2 * $Id: armcore.c,v 1.7 2005-12-26 06:38:51 nkeynes Exp $
4 * ARM7TDMI CPU emulation core.
6 * Copyright (c) 2005 Nathan Keynes.
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.
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.
19 #define MODULE aica_module
21 #include "aica/armcore.h"
23 struct arm_registers armr;
25 void arm_set_mode( int mode );
27 uint32_t arm_exceptions[][2] = {{ MODE_SVC, 0x00000000 },
28 { MODE_UND, 0x00000004 },
29 { MODE_SVC, 0x00000008 },
30 { MODE_ABT, 0x0000000C },
31 { MODE_ABT, 0x00000010 },
32 { MODE_IRQ, 0x00000018 },
33 { MODE_FIQ, 0x0000001C } };
36 #define EXC_UNDEFINED 1
37 #define EXC_SOFTWARE 2
38 #define EXC_PREFETCH_ABORT 3
39 #define EXC_DATA_ABORT 4
41 #define EXC_FAST_IRQ 6
43 uint32_t arm_cpu_freq = ARM_BASE_RATE;
44 uint32_t arm_cpu_period = 1000 / ARM_BASE_RATE;
46 uint32_t arm_run_slice( uint32_t nanosecs )
48 uint32_t target = armr.icount + nanosecs / arm_cpu_period;
49 uint32_t start = armr.icount;
50 while( armr.icount < target ) {
52 if( !arm_execute_instruction() )
56 if( target != armr.icount ) {
57 /* Halted - compute time actually executed */
58 nanosecs = (armr.icount - start) * arm_cpu_period;
63 void arm_save_state( FILE *f )
65 fwrite( &armr, sizeof(armr), 1, f );
68 int arm_load_state( FILE *f )
70 fread( &armr, sizeof(armr), 1, f );
75 void arm_reset( void )
77 /* Wipe all processor state */
78 memset( &armr, 0, sizeof(armr) );
80 armr.cpsr = MODE_SVC | CPSR_I | CPSR_F;
81 armr.r[15] = 0x00000000;
84 #define SET_CPSR_CONTROL 0x00010000
85 #define SET_CPSR_EXTENSION 0x00020000
86 #define SET_CPSR_STATUS 0x00040000
87 #define SET_CPSR_FLAGS 0x00080000
89 uint32_t arm_get_cpsr( void )
91 /* write back all flags to the cpsr */
92 armr.cpsr = armr.cpsr & CPSR_COMPACT_MASK;
93 if( armr.n ) armr.cpsr |= CPSR_N;
94 if( armr.z ) armr.cpsr |= CPSR_Z;
95 if( armr.c ) armr.cpsr |= CPSR_C;
96 if( armr.v ) armr.cpsr |= CPSR_V;
97 if( armr.t ) armr.cpsr |= CPSR_T;
102 * Set the CPSR to the specified value.
104 * @param value values to set in CPSR
105 * @param fields set of mask values to define which sections of the
106 * CPSR to set (one of the SET_CPSR_* values above)
108 void arm_set_cpsr( uint32_t value, uint32_t fields )
110 if( IS_PRIVILEGED_MODE() ) {
111 if( fields & SET_CPSR_CONTROL ) {
112 int mode = value & CPSR_MODE;
113 arm_set_mode( mode );
114 armr.t = ( value & CPSR_T ); /* Technically illegal to change */
115 armr.cpsr = (armr.cpsr & 0xFFFFFF00) | (value & 0x000000FF);
118 /* Middle 16 bits not currently defined */
120 if( fields & SET_CPSR_FLAGS ) {
121 /* Break flags directly out of given value - don't bother writing
124 armr.n = ( value & CPSR_N );
125 armr.z = ( value & CPSR_Z );
126 armr.c = ( value & CPSR_C );
127 armr.v = ( value & CPSR_V );
131 void arm_set_spsr( uint32_t value, uint32_t fields )
133 /* Only defined if we actually have an SPSR register */
134 if( IS_EXCEPTION_MODE() ) {
135 if( fields & SET_CPSR_CONTROL ) {
136 armr.spsr = (armr.spsr & 0xFFFFFF00) | (value & 0x000000FF);
139 /* Middle 16 bits not currently defined */
141 if( fields & SET_CPSR_FLAGS ) {
142 armr.spsr = (armr.spsr & 0x00FFFFFF) | (value & 0xFF000000);
148 * Raise an ARM exception (other than reset, which uses arm_reset().
149 * @param exception one of the EXC_* exception codes defined above.
151 void arm_raise_exception( int exception )
153 int mode = arm_exceptions[exception][0];
154 uint32_t spsr = arm_get_cpsr();
155 arm_set_mode( mode );
157 armr.r[14] = armr.r[15];
158 armr.cpsr = (spsr & (~CPSR_T)) | CPSR_I;
159 if( mode == MODE_FIQ )
161 armr.r[15] = arm_exceptions[exception][1];
164 void arm_restore_cpsr( void )
166 int spsr = armr.spsr;
167 int mode = spsr & CPSR_MODE;
168 arm_set_mode( mode );
170 armr.n = ( spsr & CPSR_N );
171 armr.z = ( spsr & CPSR_Z );
172 armr.c = ( spsr & CPSR_C );
173 armr.v = ( spsr & CPSR_V );
174 armr.t = ( spsr & CPSR_T );
180 * Change the current executing ARM mode to the requested mode.
181 * Saves any required registers to banks and restores those for the
182 * correct mode. (Note does not actually update CPSR at the moment).
184 void arm_set_mode( int targetMode )
186 int currentMode = armr.cpsr & CPSR_MODE;
187 if( currentMode == targetMode )
190 switch( currentMode ) {
193 armr.user_r[5] = armr.r[13];
194 armr.user_r[6] = armr.r[14];
197 armr.svc_r[0] = armr.r[13];
198 armr.svc_r[1] = armr.r[14];
199 armr.svc_r[2] = armr.spsr;
202 armr.abt_r[0] = armr.r[13];
203 armr.abt_r[1] = armr.r[14];
204 armr.abt_r[2] = armr.spsr;
207 armr.und_r[0] = armr.r[13];
208 armr.und_r[1] = armr.r[14];
209 armr.und_r[2] = armr.spsr;
212 armr.irq_r[0] = armr.r[13];
213 armr.irq_r[1] = armr.r[14];
214 armr.irq_r[2] = armr.spsr;
217 armr.fiq_r[0] = armr.r[8];
218 armr.fiq_r[1] = armr.r[9];
219 armr.fiq_r[2] = armr.r[10];
220 armr.fiq_r[3] = armr.r[11];
221 armr.fiq_r[4] = armr.r[12];
222 armr.fiq_r[5] = armr.r[13];
223 armr.fiq_r[6] = armr.r[14];
224 armr.fiq_r[7] = armr.spsr;
225 armr.r[8] = armr.user_r[0];
226 armr.r[9] = armr.user_r[1];
227 armr.r[10] = armr.user_r[2];
228 armr.r[11] = armr.user_r[3];
229 armr.r[12] = armr.user_r[4];
233 switch( targetMode ) {
236 armr.r[13] = armr.user_r[5];
237 armr.r[14] = armr.user_r[6];
240 armr.r[13] = armr.svc_r[0];
241 armr.r[14] = armr.svc_r[1];
242 armr.spsr = armr.svc_r[2];
245 armr.r[13] = armr.abt_r[0];
246 armr.r[14] = armr.abt_r[1];
247 armr.spsr = armr.abt_r[2];
250 armr.r[13] = armr.und_r[0];
251 armr.r[14] = armr.und_r[1];
252 armr.spsr = armr.und_r[2];
255 armr.r[13] = armr.irq_r[0];
256 armr.r[14] = armr.irq_r[1];
257 armr.spsr = armr.irq_r[2];
260 armr.user_r[0] = armr.r[8];
261 armr.user_r[1] = armr.r[9];
262 armr.user_r[2] = armr.r[10];
263 armr.user_r[3] = armr.r[11];
264 armr.user_r[4] = armr.r[12];
265 armr.r[8] = armr.fiq_r[0];
266 armr.r[9] = armr.fiq_r[1];
267 armr.r[10] = armr.fiq_r[2];
268 armr.r[11] = armr.fiq_r[3];
269 armr.r[12] = armr.fiq_r[4];
270 armr.r[13] = armr.fiq_r[5];
271 armr.r[14] = armr.fiq_r[6];
272 armr.spsr = armr.fiq_r[7];
277 /* Page references are as per ARM DDI 0100E (June 2000) */
279 #define MEM_READ_BYTE( addr ) arm_read_byte(addr)
280 #define MEM_READ_WORD( addr ) arm_read_word(addr)
281 #define MEM_READ_LONG( addr ) arm_read_long(addr)
282 #define MEM_WRITE_BYTE( addr, val ) arm_write_byte(addr, val)
283 #define MEM_WRITE_WORD( addr, val ) arm_write_word(addr, val)
284 #define MEM_WRITE_LONG( addr, val ) arm_write_long(addr, val)
287 #define IS_NOTBORROW( result, op1, op2 ) (op2 > op1 ? 0 : 1)
288 #define IS_CARRY( result, op1, op2 ) (result < op1 ? 1 : 0)
289 #define IS_SUBOVERFLOW( result, op1, op2 ) (((op1^op2) & (result^op1)) >> 31)
290 #define IS_ADDOVERFLOW( result, op1, op2 ) (((op1&op2) & (result^op1)) >> 31)
292 #define PC armr.r[15]
294 /* Instruction fields */
295 #define COND(ir) (ir>>28)
296 #define GRP(ir) ((ir>>26)&0x03)
297 #define OPCODE(ir) ((ir>>20)&0x1F)
298 #define IFLAG(ir) (ir&0x02000000)
299 #define SFLAG(ir) (ir&0x00100000)
300 #define PFLAG(ir) (ir&0x01000000)
301 #define UFLAG(ir) (ir&0x00800000)
302 #define BFLAG(ir) (ir&0x00400000)
303 #define WFLAG(ir) (IR&0x00200000)
304 #define LFLAG(ir) SFLAG(ir)
305 #define RN(ir) (armr.r[((ir>>16)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
306 #define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>12)&0x0F) == 0x0F ? 4 : 0))
307 #define RDn(ir) ((ir>>12)&0x0F)
308 #define RS(ir) (armr.r[((ir>>8)&0x0F)] + (((ir>>8)&0x0F) == 0x0F ? 4 : 0))
309 #define RM(ir) (armr.r[(ir&0x0F)] + (((ir&0x0F) == 0x0F ? 4 : 0)) )
310 #define LRN(ir) armr.r[((ir>>16)&0x0F)]
311 #define LRD(ir) armr.r[((ir>>12)&0x0F)]
312 #define LRS(ir) armr.r[((ir>>8)&0x0F)]
313 #define LRM(ir) armr.r[(ir&0x0F)]
315 #define IMM8(ir) (ir&0xFF)
316 #define IMM12(ir) (ir&0xFFF)
317 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
318 #define IMMROT(ir) ((ir>>7)&0x1E)
319 #define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
320 #define SIGNEXT24(n) ((n&0x00800000) ? (n|0xFF000000) : (n&0x00FFFFFF))
321 #define SHIFT(ir) ((ir>>4)&0x07)
322 #define DISP24(ir) ((ir&0x00FFFFFF))
323 #define UNDEF(ir) do{ arm_raise_exception( EXC_UNDEFINED ); return TRUE; } while(0)
324 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC, ir ); return FALSE; }while(0)
327 * Determine the value of the shift-operand for a data processing instruction,
328 * without determing a value for shift_C (optimized form for instructions that
329 * don't require shift_C ).
330 * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
332 static uint32_t arm_get_shift_operand( uint32_t ir )
334 uint32_t operand, tmp;
335 if( IFLAG(ir) == 0 ) {
338 case 0: /* (Rm << imm) */
339 operand = operand << SHIFTIMM(ir);
341 case 1: /* (Rm << Rs) */
343 if( tmp > 31 ) operand = 0;
344 else operand = operand << tmp;
346 case 2: /* (Rm >> imm) */
347 operand = operand >> SHIFTIMM(ir);
349 case 3: /* (Rm >> Rs) */
351 if( tmp > 31 ) operand = 0;
352 else operand = operand >> ir;
354 case 4: /* (Rm >>> imm) */
356 if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
357 else operand = ((int32_t)operand) >> tmp;
359 case 5: /* (Rm >>> Rs) */
361 if( tmp > 31 ) operand = ((int32_t)operand) >> 31;
362 else operand = ((int32_t)operand) >> tmp;
366 if( tmp == 0 ) /* RRX aka rotate with carry */
367 operand = (operand >> 1) | (armr.c<<31);
369 operand = ROTATE_RIGHT_LONG(operand,tmp);
373 operand = ROTATE_RIGHT_LONG(operand,tmp);
379 operand = ROTATE_RIGHT_LONG(operand, tmp);
385 * Determine the value of the shift-operand for a data processing instruction,
386 * and set armr.shift_c accordingly.
387 * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
389 static uint32_t arm_get_shift_operand_s( uint32_t ir )
391 uint32_t operand, tmp;
392 if( IFLAG(ir) == 0 ) {
395 case 0: /* (Rm << imm) */
397 if( tmp == 0 ) { /* Rm */
398 armr.shift_c = armr.c;
399 } else { /* Rm << imm */
400 armr.shift_c = (operand >> (32-tmp)) & 0x01;
401 operand = operand << tmp;
404 case 1: /* (Rm << Rs) */
407 armr.shift_c = armr.c;
410 armr.shift_c = (operand >> (32-tmp)) & 0x01;
411 else armr.shift_c = 0;
413 operand = operand << tmp;
417 case 2: /* (Rm >> imm) */
420 armr.shift_c = operand >> 31;
423 armr.shift_c = (operand >> (tmp-1)) & 0x01;
424 operand = RM(ir) >> tmp;
427 case 3: /* (Rm >> Rs) */
430 armr.shift_c = armr.c;
433 armr.shift_c = (operand >> (tmp-1))&0x01;
434 else armr.shift_c = 0;
436 operand = operand >> tmp;
440 case 4: /* (Rm >>> imm) */
443 armr.shift_c = operand >> 31;
444 operand = -armr.shift_c;
446 armr.shift_c = (operand >> (tmp-1)) & 0x01;
447 operand = ((int32_t)operand) >> tmp;
450 case 5: /* (Rm >>> Rs) */
453 armr.shift_c = armr.c;
456 armr.shift_c = (operand >> (tmp-1))&0x01;
457 operand = ((int32_t)operand) >> tmp;
459 armr.shift_c = operand >> 31;
460 operand = ((int32_t)operand) >> 31;
466 if( tmp == 0 ) { /* RRX aka rotate with carry */
467 armr.shift_c = operand&0x01;
468 operand = (operand >> 1) | (armr.c<<31);
470 armr.shift_c = operand>>(tmp-1);
471 operand = ROTATE_RIGHT_LONG(operand,tmp);
477 armr.shift_c = armr.c;
481 armr.shift_c = operand>>31;
483 armr.shift_c = (operand>>(tmp-1))&0x1;
484 operand = ROTATE_RIGHT_LONG(operand,tmp);
493 armr.shift_c = armr.c;
495 operand = ROTATE_RIGHT_LONG(operand, tmp);
496 armr.shift_c = operand>>31;
503 * Another variant of the shifter code for index-based memory addressing.
504 * Distinguished by the fact that it doesn't support register shifts, and
505 * ignores the I flag (WTF do the load/store instructions use the I flag to
506 * mean the _exact opposite_ of what it means for the data processing
509 static uint32_t arm_get_address_index( uint32_t ir )
511 uint32_t operand = RM(ir);
515 case 0: /* (Rm << imm) */
516 operand = operand << SHIFTIMM(ir);
518 case 2: /* (Rm >> imm) */
519 operand = operand >> SHIFTIMM(ir);
521 case 4: /* (Rm >>> imm) */
523 if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
524 else operand = ((int32_t)operand) >> tmp;
528 if( tmp == 0 ) /* RRX aka rotate with carry */
529 operand = (operand >> 1) | (armr.c<<31);
531 operand = ROTATE_RIGHT_LONG(operand,tmp);
539 * Determine the address operand of a load/store instruction, including
540 * applying any pre/post adjustments to the address registers.
541 * @see s5.2 Addressing Mode 2 - Load and Store Word or Unsigned Byte
542 * @param The instruction word.
543 * @return The calculated address
545 static uint32_t arm_get_address_operand( uint32_t ir )
550 switch( (ir>>21)&0x1D ) {
551 case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
554 LRN(ir) = addr - IMM12(ir);
556 case 4: /* Rn += imm offsett (post-indexed) [5.2.8 A5-28] */
559 LRN(ir) = addr + IMM12(ir);
561 case 8: /* Rn - imm offset [5.2.2 A5-20] */
562 addr = RN(ir) - IMM12(ir);
564 case 9: /* Rn -= imm offset (pre-indexed) [5.2.5 A5-24] */
565 addr = RN(ir) - IMM12(ir);
568 case 12: /* Rn + imm offset [5.2.2 A5-20] */
569 addr = RN(ir) + IMM12(ir);
571 case 13: /* Rn += imm offset [5.2.5 A5-24 ] */
572 addr = RN(ir) + IMM12(ir);
575 case 16: /* Rn -= Rm (post-indexed) [5.2.10 A5-32 ] */
578 LRN(ir) = addr - arm_get_address_index(ir);
580 case 20: /* Rn += Rm (post-indexed) [5.2.10 A5-32 ] */
583 LRN(ir) = addr - arm_get_address_index(ir);
585 case 24: /* Rn - Rm [5.2.4 A5-23] */
586 addr = RN(ir) - arm_get_address_index(ir);
588 case 25: /* RN -= Rm (pre-indexed) [5.2.7 A5-26] */
589 addr = RN(ir) - arm_get_address_index(ir);
592 case 28: /* Rn + Rm [5.2.4 A5-23] */
593 addr = RN(ir) + arm_get_address_index(ir);
595 case 29: /* RN += Rm (pre-indexed) [5.2.7 A5-26] */
596 addr = RN(ir) + arm_get_address_index(ir);
603 gboolean arm_execute_instruction( void )
606 uint32_t ir = MEM_READ_LONG(pc);
607 uint32_t operand, operand2, tmp, cond;
613 * Check the condition bits first - if the condition fails return
614 * immediately without actually looking at the rest of the instruction.
642 cond = armr.c && !armr.z;
645 cond = (!armr.c) || armr.z;
648 cond = (armr.n == armr.v);
651 cond = (armr.n != armr.v);
654 cond = (!armr.z) && (armr.n == armr.v);
657 cond = armr.z || (armr.n != armr.v);
670 * Condition passed, now for the actual instructions...
674 if( (ir & 0x0D900000) == 0x01000000 ) {
675 /* Instructions that aren't actual data processing even though
676 * they sit in the DP instruction block.
678 switch( ir & 0x0FF000F0 ) {
679 case 0x01200010: /* BX Rd */
681 armr.r[15] = RM(ir) & 0xFFFFFFFE;
683 case 0x01000000: /* MRS Rd, CPSR */
684 LRD(ir) = arm_get_cpsr();
686 case 0x01400000: /* MRS Rd, SPSR */
689 case 0x01200000: /* MSR CPSR, Rd */
690 arm_set_cpsr( RM(ir), ir );
692 case 0x01600000: /* MSR SPSR, Rd */
693 arm_set_spsr( RM(ir), ir );
695 case 0x03200000: /* MSR CPSR, imm */
696 arm_set_cpsr( ROTIMM12(ir), ir );
698 case 0x03600000: /* MSR SPSR, imm */
699 arm_set_spsr( ROTIMM12(ir), ir );
704 } else if( (ir & 0x0E000090) == 0x00000090 ) {
705 /* Neither are these */
706 switch( (ir>>5)&0x03 ) {
708 /* Arithmetic extension area */
724 case 11: /* UMLALS */
728 case 13: /* SMULLS */
732 case 15: /* SMLALS */
765 /* Data processing */
768 case 0: /* AND Rd, Rn, operand */
769 LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
771 case 1: /* ANDS Rd, Rn, operand */
772 operand = arm_get_shift_operand_s(ir) & RN(ir);
774 if( RDn(ir) == 15 ) {
777 armr.n = operand>>31;
778 armr.z = (operand == 0);
779 armr.c = armr.shift_c;
782 case 2: /* EOR Rd, Rn, operand */
783 LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
785 case 3: /* EORS Rd, Rn, operand */
786 operand = arm_get_shift_operand_s(ir) ^ RN(ir);
788 if( RDn(ir) == 15 ) {
791 armr.n = operand>>31;
792 armr.z = (operand == 0);
793 armr.c = armr.shift_c;
796 case 4: /* SUB Rd, Rn, operand */
797 LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
799 case 5: /* SUBS Rd, Rn, operand */
801 operand2 = arm_get_shift_operand(ir);
802 tmp = operand - operand2;
804 if( RDn(ir) == 15 ) {
809 armr.c = IS_NOTBORROW(tmp,operand,operand2);
810 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
813 case 6: /* RSB Rd, operand, Rn */
814 LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
816 case 7: /* RSBS Rd, operand, Rn */
817 operand = arm_get_shift_operand(ir);
819 tmp = operand - operand2;
821 if( RDn(ir) == 15 ) {
826 armr.c = IS_NOTBORROW(tmp,operand,operand2);
827 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
830 case 8: /* ADD Rd, Rn, operand */
831 LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
833 case 9: /* ADDS Rd, Rn, operand */
834 operand = arm_get_shift_operand(ir);
836 tmp = operand + operand2;
838 if( RDn(ir) == 15 ) {
843 armr.c = IS_CARRY(tmp,operand,operand2);
844 armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
854 case 17: /* TST Rn, operand */
855 operand = arm_get_shift_operand_s(ir) & RN(ir);
856 armr.n = operand>>31;
857 armr.z = (operand == 0);
858 armr.c = armr.shift_c;
860 case 19: /* TEQ Rn, operand */
861 operand = arm_get_shift_operand_s(ir) ^ RN(ir);
862 armr.n = operand>>31;
863 armr.z = (operand == 0);
864 armr.c = armr.shift_c;
866 case 21: /* CMP Rn, operand */
868 operand2 = arm_get_shift_operand(ir);
869 tmp = operand - operand2;
872 armr.c = IS_NOTBORROW(tmp,operand,operand2);
873 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
875 case 23: /* CMN Rn, operand */
877 operand2 = arm_get_shift_operand(ir);
878 tmp = operand + operand2;
881 armr.c = IS_CARRY(tmp,operand,operand2);
882 armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
884 case 24: /* ORR Rd, Rn, operand */
885 LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
887 case 25: /* ORRS Rd, Rn, operand */
888 operand = arm_get_shift_operand_s(ir) | RN(ir);
890 if( RDn(ir) == 15 ) {
893 armr.n = operand>>31;
894 armr.z = (operand == 0);
895 armr.c = armr.shift_c;
898 case 26: /* MOV Rd, operand */
899 LRD(ir) = arm_get_shift_operand(ir);
901 case 27: /* MOVS Rd, operand */
902 operand = arm_get_shift_operand_s(ir);
904 if( RDn(ir) == 15 ) {
907 armr.n = operand>>31;
908 armr.z = (operand == 0);
909 armr.c = armr.shift_c;
912 case 28: /* BIC Rd, Rn, operand */
913 LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
915 case 29: /* BICS Rd, Rn, operand */
916 operand = RN(ir) & (~arm_get_shift_operand_s(ir));
918 if( RDn(ir) == 15 ) {
921 armr.n = operand>>31;
922 armr.z = (operand == 0);
923 armr.c = armr.shift_c;
926 case 30: /* MVN Rd, operand */
927 LRD(ir) = ~arm_get_shift_operand(ir);
929 case 31: /* MVNS Rd, operand */
930 operand = ~arm_get_shift_operand_s(ir);
932 if( RDn(ir) == 15 ) {
935 armr.n = operand>>31;
936 armr.z = (operand == 0);
937 armr.c = armr.shift_c;
945 case 1: /* Load/store */
946 operand = arm_get_address_operand(ir);
947 switch( (ir>>20)&0x17 ) {
948 case 0: case 16: case 18: /* STR Rd, address */
949 arm_write_long( operand, RD(ir) );
951 case 1: case 17: case 19: /* LDR Rd, address */
952 LRD(ir) = arm_read_long(operand);
954 case 2: /* STRT Rd, address */
955 arm_write_long_user( operand, RD(ir) );
957 case 3: /* LDRT Rd, address */
958 LRD(ir) = arm_read_long_user( operand );
960 case 4: case 20: case 22: /* STRB Rd, address */
961 arm_write_byte( operand, RD(ir) );
963 case 5: case 21: case 23: /* LDRB Rd, address */
964 LRD(ir) = arm_read_byte( operand );
966 case 6: /* STRBT Rd, address */
967 arm_write_byte_user( operand, RD(ir) );
969 case 7: /* LDRBT Rd, address */
970 LRD(ir) = arm_read_byte_user( operand );
974 case 2: /* Load/store multiple, branch*/
975 if( (ir & 0x02000000) == 0x02000000 ) { /* B[L] imm24 */
976 operand = (SIGNEXT24(ir&0x00FFFFFF) << 2);
977 if( (ir & 0x01000000) == 0x01000000 ) {
978 armr.r[14] = pc; /* BL */
980 armr.r[15] = pc + 4 + operand;
981 } else { /* Load/store multiple */
.