filename | src/aica/armcore.c |
changeset | 86:f151e63f9754 |
prev | 81:1c1d53584da4 |
next | 431:248dd77a9e44 |
author | nkeynes |
date | Sat Jan 06 04:06:36 2007 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Implement event queue. Fix pvr2 timing (yes, again). |
view | annotate | diff | log | raw |
1 /**
2 * $Id: armcore.c,v 1.20 2006-01-22 22:40:05 nkeynes Exp $
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 "mem.h"
22 #include "aica/armcore.h"
23 #include "aica/aica.h"
25 #define STM_R15_OFFSET 12
27 struct arm_registers armr;
29 void arm_set_mode( int mode );
31 uint32_t arm_exceptions[][2] = {{ MODE_SVC, 0x00000000 },
32 { MODE_UND, 0x00000004 },
33 { MODE_SVC, 0x00000008 },
34 { MODE_ABT, 0x0000000C },
35 { MODE_ABT, 0x00000010 },
36 { MODE_IRQ, 0x00000018 },
37 { MODE_FIQ, 0x0000001C } };
39 #define EXC_RESET 0
40 #define EXC_UNDEFINED 1
41 #define EXC_SOFTWARE 2
42 #define EXC_PREFETCH_ABORT 3
43 #define EXC_DATA_ABORT 4
44 #define EXC_IRQ 5
45 #define EXC_FAST_IRQ 6
47 uint32_t arm_cpu_freq = ARM_BASE_RATE;
48 uint32_t arm_cpu_period = 1000 / ARM_BASE_RATE;
50 #define CYCLES_PER_SAMPLE ((ARM_BASE_RATE * 1000000) / AICA_SAMPLE_RATE)
52 static struct breakpoint_struct arm_breakpoints[MAX_BREAKPOINTS];
53 static int arm_breakpoint_count = 0;
55 void arm_set_breakpoint( uint32_t pc, int type )
56 {
57 arm_breakpoints[arm_breakpoint_count].address = pc;
58 arm_breakpoints[arm_breakpoint_count].type = type;
59 arm_breakpoint_count++;
60 }
62 gboolean arm_clear_breakpoint( uint32_t pc, int type )
63 {
64 int i;
66 for( i=0; i<arm_breakpoint_count; i++ ) {
67 if( arm_breakpoints[i].address == pc &&
68 arm_breakpoints[i].type == type ) {
69 while( ++i < arm_breakpoint_count ) {
70 arm_breakpoints[i-1].address = arm_breakpoints[i].address;
71 arm_breakpoints[i-1].type = arm_breakpoints[i].type;
72 }
73 arm_breakpoint_count--;
74 return TRUE;
75 }
76 }
77 return FALSE;
78 }
80 int arm_get_breakpoint( uint32_t pc )
81 {
82 int i;
83 for( i=0; i<arm_breakpoint_count; i++ ) {
84 if( arm_breakpoints[i].address == pc )
85 return arm_breakpoints[i].type;
86 }
87 return 0;
88 }
90 uint32_t arm_run_slice( uint32_t num_samples )
91 {
92 int i,j,k;
94 if( !armr.running )
95 return num_samples;
97 for( i=0; i<num_samples; i++ ) {
98 for( j=0; j < CYCLES_PER_SAMPLE; j++ ) {
99 armr.icount++;
100 if( !arm_execute_instruction() )
101 return i;
102 #ifdef ENABLE_DEBUG_MODE
103 for( k=0; k<arm_breakpoint_count; k++ ) {
104 if( arm_breakpoints[k].address == armr.r[15] ) {
105 dreamcast_stop();
106 if( arm_breakpoints[k].type == BREAK_ONESHOT )
107 arm_clear_breakpoint( armr.r[15], BREAK_ONESHOT );
108 return i;
109 }
110 }
111 #endif
112 }
114 k = MMIO_READ( AICA2, AICA_TCR );
115 if( k & 0x40 ) {
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 }
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 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 SHIFT(ir) ((ir>>4)&0x07)
410 #define DISP24(ir) ((ir&0x00FFFFFF))
411 #define UNDEF(ir) do{ arm_raise_exception( EXC_UNDEFINED ); return TRUE; } while(0)
412 #define UNIMP(ir) do{ PC-=4; ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC, ir ); dreamcast_stop(); return FALSE; }while(0)
414 /**
415 * Determine the value of the shift-operand for a data processing instruction,
416 * without determing a value for shift_C (optimized form for instructions that
417 * don't require shift_C ).
418 * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
419 */
420 static uint32_t arm_get_shift_operand( uint32_t ir )
421 {
422 uint32_t operand, tmp;
423 if( IFLAG(ir) == 0 ) {
424 operand = RM(ir);
425 switch(SHIFT(ir)) {
426 case 0: /* (Rm << imm) */
427 operand = operand << SHIFTIMM(ir);
428 break;
429 case 1: /* (Rm << Rs) */
430 tmp = RS(ir)&0xFF;
431 if( tmp > 31 ) operand = 0;
432 else operand = operand << tmp;
433 break;
434 case 2: /* (Rm >> imm) */
435 operand = operand >> SHIFTIMM(ir);
436 break;
437 case 3: /* (Rm >> Rs) */
438 tmp = RS(ir) & 0xFF;
439 if( tmp > 31 ) operand = 0;
440 else operand = operand >> ir;
441 break;
442 case 4: /* (Rm >>> imm) */
443 tmp = SHIFTIMM(ir);
444 if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
445 else operand = ((int32_t)operand) >> tmp;
446 break;
447 case 5: /* (Rm >>> Rs) */
448 tmp = RS(ir) & 0xFF;
449 if( tmp > 31 ) operand = ((int32_t)operand) >> 31;
450 else operand = ((int32_t)operand) >> tmp;
451 break;
452 case 6:
453 tmp = SHIFTIMM(ir);
454 if( tmp == 0 ) /* RRX aka rotate with carry */
455 operand = (operand >> 1) | (armr.c<<31);
456 else
457 operand = ROTATE_RIGHT_LONG(operand,tmp);
458 break;
459 case 7:
460 tmp = RS(ir)&0x1F;
461 operand = ROTATE_RIGHT_LONG(operand,tmp);
462 break;
463 }
464 } else {
465 operand = IMM8(ir);
466 tmp = IMMROT(ir);
467 operand = ROTATE_RIGHT_LONG(operand, tmp);
468 }
469 return operand;
470 }
472 /**
473 * Determine the value of the shift-operand for a data processing instruction,
474 * and set armr.shift_c accordingly.
475 * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
476 */
477 static uint32_t arm_get_shift_operand_s( uint32_t ir )
478 {
479 uint32_t operand, tmp;
480 if( IFLAG(ir) == 0 ) {
481 operand = RM(ir);
482 switch(SHIFT(ir)) {
483 case 0: /* (Rm << imm) */
484 tmp = SHIFTIMM(ir);
485 if( tmp == 0 ) { /* Rm */
486 armr.shift_c = armr.c;
487 } else { /* Rm << imm */
488 armr.shift_c = (operand >> (32-tmp)) & 0x01;
489 operand = operand << tmp;
490 }
491 break;
492 case 1: /* (Rm << Rs) */
493 tmp = RS(ir)&0xFF;
494 if( tmp == 0 ) {
495 armr.shift_c = armr.c;
496 } else {
497 if( tmp <= 32 )
498 armr.shift_c = (operand >> (32-tmp)) & 0x01;
499 else armr.shift_c = 0;
500 if( tmp < 32 )
501 operand = operand << tmp;
502 else operand = 0;
503 }
504 break;
505 case 2: /* (Rm >> imm) */
506 tmp = SHIFTIMM(ir);
507 if( tmp == 0 ) {
508 armr.shift_c = operand >> 31;
509 operand = 0;
510 } else {
511 armr.shift_c = (operand >> (tmp-1)) & 0x01;
512 operand = RM(ir) >> tmp;
513 }
514 break;
515 case 3: /* (Rm >> Rs) */
516 tmp = RS(ir) & 0xFF;
517 if( tmp == 0 ) {
518 armr.shift_c = armr.c;
519 } else {
520 if( tmp <= 32 )
521 armr.shift_c = (operand >> (tmp-1))&0x01;
522 else armr.shift_c = 0;
523 if( tmp < 32 )
524 operand = operand >> tmp;
525 else operand = 0;
526 }
527 break;
528 case 4: /* (Rm >>> imm) */
529 tmp = SHIFTIMM(ir);
530 if( tmp == 0 ) {
531 armr.shift_c = operand >> 31;
532 operand = -armr.shift_c;
533 } else {
534 armr.shift_c = (operand >> (tmp-1)) & 0x01;
535 operand = ((int32_t)operand) >> tmp;
536 }
537 break;
538 case 5: /* (Rm >>> Rs) */
539 tmp = RS(ir) & 0xFF;
540 if( tmp == 0 ) {
541 armr.shift_c = armr.c;
542 } else {
543 if( tmp < 32 ) {
544 armr.shift_c = (operand >> (tmp-1))&0x01;
545 operand = ((int32_t)operand) >> tmp;
546 } else {
547 armr.shift_c = operand >> 31;
548 operand = ((int32_t)operand) >> 31;
549 }
550 }
551 break;
552 case 6:
553 tmp = SHIFTIMM(ir);
554 if( tmp == 0 ) { /* RRX aka rotate with carry */
555 armr.shift_c = operand&0x01;
556 operand = (operand >> 1) | (armr.c<<31);
557 } else {
558 armr.shift_c = operand>>(tmp-1);
559 operand = ROTATE_RIGHT_LONG(operand,tmp);
560 }
561 break;
562 case 7:
563 tmp = RS(ir)&0xFF;
564 if( tmp == 0 ) {
565 armr.shift_c = armr.c;
566 } else {
567 tmp &= 0x1F;
568 if( tmp == 0 ) {
569 armr.shift_c = operand>>31;
570 } else {
571 armr.shift_c = (operand>>(tmp-1))&0x1;
572 operand = ROTATE_RIGHT_LONG(operand,tmp);
573 }
574 }
575 break;
576 }
577 } else {
578 operand = IMM8(ir);
579 tmp = IMMROT(ir);
580 if( tmp == 0 ) {
581 armr.shift_c = armr.c;
582 } else {
583 operand = ROTATE_RIGHT_LONG(operand, tmp);
584 armr.shift_c = operand>>31;
585 }
586 }
587 return operand;
588 }
590 /**
591 * Another variant of the shifter code for index-based memory addressing.
592 * Distinguished by the fact that it doesn't support register shifts, and
593 * ignores the I flag (WTF do the load/store instructions use the I flag to
594 * mean the _exact opposite_ of what it means for the data processing
595 * instructions ???)
596 */
597 static uint32_t arm_get_address_index( uint32_t ir )
598 {
599 uint32_t operand = RM(ir);
600 uint32_t tmp;
602 switch(SHIFT(ir)) {
603 case 0: /* (Rm << imm) */
604 operand = operand << SHIFTIMM(ir);
605 break;
606 case 2: /* (Rm >> imm) */
607 operand = operand >> SHIFTIMM(ir);
608 break;
609 case 4: /* (Rm >>> imm) */
610 tmp = SHIFTIMM(ir);
611 if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
612 else operand = ((int32_t)operand) >> tmp;
613 break;
614 case 6:
615 tmp = SHIFTIMM(ir);
616 if( tmp == 0 ) /* RRX aka rotate with carry */
617 operand = (operand >> 1) | (armr.c<<31);
618 else
619 operand = ROTATE_RIGHT_LONG(operand,tmp);
620 break;
621 default: UNIMP(ir);
622 }
623 return operand;
624 }
626 /**
627 * Determine the address operand of a load/store instruction, including
628 * applying any pre/post adjustments to the address registers.
629 * @see s5.2 Addressing Mode 2 - Load and Store Word or Unsigned Byte
630 * @param The instruction word.
631 * @return The calculated address
632 */
633 static uint32_t arm_get_address_operand( uint32_t ir )
634 {
635 uint32_t addr;
637 /* I P U . W */
638 switch( (ir>>21)&0x1D ) {
639 case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
640 case 1:
641 addr = RN(ir);
642 LRN(ir) = addr - IMM12(ir);
643 break;
644 case 4: /* Rn += imm offsett (post-indexed) [5.2.8 A5-28] */
645 case 5:
646 addr = RN(ir);
647 LRN(ir) = addr + IMM12(ir);
648 break;
649 case 8: /* Rn - imm offset [5.2.2 A5-20] */
650 addr = RN(ir) - IMM12(ir);
651 break;
652 case 9: /* Rn -= imm offset (pre-indexed) [5.2.5 A5-24] */
653 addr = RN(ir) - IMM12(ir);
654 LRN(ir) = addr;
655 break;
656 case 12: /* Rn + imm offset [5.2.2 A5-20] */
657 addr = RN(ir) + IMM12(ir);
658 break;
659 case 13: /* Rn += imm offset [5.2.5 A5-24 ] */
660 addr = RN(ir) + IMM12(ir);
661 LRN(ir) = addr;
662 break;
663 case 16: /* Rn -= Rm (post-indexed) [5.2.10 A5-32 ] */
664 case 17:
665 addr = RN(ir);
666 LRN(ir) = addr - arm_get_address_index(ir);
667 break;
668 case 20: /* Rn += Rm (post-indexed) [5.2.10 A5-32 ] */
669 case 21:
670 addr = RN(ir);
671 LRN(ir) = addr - arm_get_address_index(ir);
672 break;
673 case 24: /* Rn - Rm [5.2.4 A5-23] */
674 addr = RN(ir) - arm_get_address_index(ir);
675 break;
676 case 25: /* RN -= Rm (pre-indexed) [5.2.7 A5-26] */
677 addr = RN(ir) - arm_get_address_index(ir);
678 LRN(ir) = addr;
679 break;
680 case 28: /* Rn + Rm [5.2.4 A5-23] */
681 addr = RN(ir) + arm_get_address_index(ir);
682 break;
683 case 29: /* RN += Rm (pre-indexed) [5.2.7 A5-26] */
684 addr = RN(ir) + arm_get_address_index(ir);
685 LRN(ir) = addr;
686 break;
687 }
688 return addr;
689 }
691 gboolean arm_execute_instruction( void )
692 {
693 uint32_t pc;
694 uint32_t ir;
695 uint32_t operand, operand2, tmp, tmp2, cond;
696 int i;
698 tmp = armr.int_pending & (~armr.cpsr);
699 if( tmp ) {
700 if( tmp & CPSR_F ) {
701 arm_raise_exception( EXC_FAST_IRQ );
702 } else {
703 arm_raise_exception( EXC_IRQ );
704 }
705 }
707 ir = MEM_READ_LONG(PC);
708 pc = PC + 4;
709 PC = pc;
711 /**
712 * Check the condition bits first - if the condition fails return
713 * immediately without actually looking at the rest of the instruction.
714 */
715 switch( COND(ir) ) {
716 case 0: /* EQ */
717 cond = armr.z;
718 break;
719 case 1: /* NE */
720 cond = !armr.z;
721 break;
722 case 2: /* CS/HS */
723 cond = armr.c;
724 break;
725 case 3: /* CC/LO */
726 cond = !armr.c;
727 break;
728 case 4: /* MI */
729 cond = armr.n;
730 break;
731 case 5: /* PL */
732 cond = !armr.n;
733 break;
734 case 6: /* VS */
735 cond = armr.v;
736 break;
737 case 7: /* VC */
738 cond = !armr.v;
739 break;
740 case 8: /* HI */
741 cond = armr.c && !armr.z;
742 break;
743 case 9: /* LS */
744 cond = (!armr.c) || armr.z;
745 break;
746 case 10: /* GE */
747 cond = (armr.n == armr.v);
748 break;
749 case 11: /* LT */
750 cond = (armr.n != armr.v);
751 break;
752 case 12: /* GT */
753 cond = (!armr.z) && (armr.n == armr.v);
754 break;
755 case 13: /* LE */
756 cond = armr.z || (armr.n != armr.v);
757 break;
758 case 14: /* AL */
759 cond = 1;
760 break;
761 case 15: /* (NV) */
762 cond = 0;
763 UNDEF(ir);
764 }
765 if( cond ) {
767 /**
768 * Condition passed, now for the actual instructions...
769 */
770 switch( GRP(ir) ) {
771 case 0:
772 if( (ir & 0x0D900000) == 0x01000000 ) {
773 /* Instructions that aren't actual data processing even though
774 * they sit in the DP instruction block.
775 */
776 switch( ir & 0x0FF000F0 ) {
777 case 0x01200010: /* BX Rd */
778 armr.t = ir & 0x01;
779 armr.r[15] = RM(ir) & 0xFFFFFFFE;
780 break;
781 case 0x01000000: /* MRS Rd, CPSR */
782 LRD(ir) = arm_get_cpsr();
783 break;
784 case 0x01400000: /* MRS Rd, SPSR */
785 LRD(ir) = armr.spsr;
786 break;
787 case 0x01200000: /* MSR CPSR, Rd */
788 arm_set_cpsr( RM(ir), ir );
789 break;
790 case 0x01600000: /* MSR SPSR, Rd */
791 arm_set_spsr( RM(ir), ir );
792 break;
793 case 0x03200000: /* MSR CPSR, imm */
794 arm_set_cpsr( ROTIMM12(ir), ir );
795 break;
796 case 0x03600000: /* MSR SPSR, imm */
797 arm_set_spsr( ROTIMM12(ir), ir );
798 break;
799 default:
800 UNIMP(ir);
801 }
802 } else if( (ir & 0x0E000090) == 0x00000090 ) {
803 /* Neither are these */
804 switch( (ir>>5)&0x03 ) {
805 case 0:
806 /* Arithmetic extension area */
807 switch(OPCODE(ir)) {
808 case 0: /* MUL */
809 LRN(ir) = RM(ir) * RS(ir);
810 break;
811 case 1: /* MULS */
812 tmp = RM(ir) * RS(ir);
813 LRN(ir) = tmp;
814 armr.n = tmp>>31;
815 armr.z = (tmp == 0);
816 break;
817 case 2: /* MLA */
818 LRN(ir) = RM(ir) * RS(ir) + RD(ir);
819 break;
820 case 3: /* MLAS */
821 tmp = RM(ir) * RS(ir) + RD(ir);
822 LRN(ir) = tmp;
823 armr.n = tmp>>31;
824 armr.z = (tmp == 0);
825 break;
826 case 8: /* UMULL */
827 case 9: /* UMULLS */
828 case 10: /* UMLAL */
829 case 11: /* UMLALS */
830 case 12: /* SMULL */
831 case 13: /* SMULLS */
832 case 14: /* SMLAL */
833 case 15: /* SMLALS */
834 UNIMP(ir);
835 break;
836 case 16: /* SWP */
837 tmp = arm_read_long( RN(ir) );
838 switch( RN(ir) & 0x03 ) {
839 case 1:
840 tmp = ROTATE_RIGHT_LONG(tmp, 8);
841 break;
842 case 2:
843 tmp = ROTATE_RIGHT_LONG(tmp, 16);
844 break;
845 case 3:
846 tmp = ROTATE_RIGHT_LONG(tmp, 24);
847 break;
848 }
849 arm_write_long( RN(ir), RM(ir) );
850 LRD(ir) = tmp;
851 break;
852 case 20: /* SWPB */
853 tmp = arm_read_byte( RN(ir) );
854 arm_write_byte( RN(ir), RM(ir) );
855 LRD(ir) = tmp;
856 break;
857 default:
858 UNIMP(ir);
859 }
860 break;
861 case 1:
862 if( LFLAG(ir) ) {
863 /* LDRH */
864 } else {
865 /* STRH */
866 }
867 UNIMP(ir);
868 break;
869 case 2:
870 if( LFLAG(ir) ) {
871 /* LDRSB */
872 } else {
873 }
874 UNIMP(ir);
875 break;
876 case 3:
877 if( LFLAG(ir) ) {
878 /* LDRSH */
879 } else {
880 }
881 UNIMP(ir);
882 break;
883 }
884 } else {
885 /* Data processing */
887 switch(OPCODE(ir)) {
888 case 0: /* AND Rd, Rn, operand */
889 LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
890 break;
891 case 1: /* ANDS Rd, Rn, operand */
892 operand = arm_get_shift_operand_s(ir) & RN(ir);
893 LRD(ir) = operand;
894 if( RDn(ir) == 15 ) {
895 arm_restore_cpsr();
896 } else {
897 armr.n = operand>>31;
898 armr.z = (operand == 0);
899 armr.c = armr.shift_c;
900 }
901 break;
902 case 2: /* EOR Rd, Rn, operand */
903 LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
904 break;
905 case 3: /* EORS Rd, Rn, operand */
906 operand = arm_get_shift_operand_s(ir) ^ RN(ir);
907 LRD(ir) = operand;
908 if( RDn(ir) == 15 ) {
909 arm_restore_cpsr();
910 } else {
911 armr.n = operand>>31;
912 armr.z = (operand == 0);
913 armr.c = armr.shift_c;
914 }
915 break;
916 case 4: /* SUB Rd, Rn, operand */
917 LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
918 break;
919 case 5: /* SUBS Rd, Rn, operand */
920 operand = RN(ir);
921 operand2 = arm_get_shift_operand(ir);
922 tmp = operand - operand2;
923 LRD(ir) = tmp;
924 if( RDn(ir) == 15 ) {
925 arm_restore_cpsr();
926 } else {
927 armr.n = tmp>>31;
928 armr.z = (tmp == 0);
929 armr.c = IS_NOTBORROW(tmp,operand,operand2);
930 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
931 }
932 break;
933 case 6: /* RSB Rd, operand, Rn */
934 LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
935 break;
936 case 7: /* RSBS Rd, operand, Rn */
937 operand = arm_get_shift_operand(ir);
938 operand2 = RN(ir);
939 tmp = operand - operand2;
940 LRD(ir) = tmp;
941 if( RDn(ir) == 15 ) {
942 arm_restore_cpsr();
943 } else {
944 armr.n = tmp>>31;
945 armr.z = (tmp == 0);
946 armr.c = IS_NOTBORROW(tmp,operand,operand2);
947 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
948 }
949 break;
950 case 8: /* ADD Rd, Rn, operand */
951 LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
952 break;
953 case 9: /* ADDS Rd, Rn, operand */
954 operand = arm_get_shift_operand(ir);
955 operand2 = RN(ir);
956 tmp = operand + operand2;
957 LRD(ir) = tmp;
958 if( RDn(ir) == 15 ) {
959 arm_restore_cpsr();
960 } else {
961 armr.n = tmp>>31;
962 armr.z = (tmp == 0);
963 armr.c = IS_CARRY(tmp,operand,operand2);
964 armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
965 }
966 break;
967 case 10: /* ADC */
968 LRD(ir) = RN(ir) + arm_get_shift_operand(ir) +
969 (armr.c ? 1 : 0);
970 break;
971 case 11: /* ADCS */
972 operand = arm_get_shift_operand(ir);
973 operand2 = RN(ir);
974 tmp = operand + operand2;
975 tmp2 = tmp + armr.c ? 1 : 0;
976 LRD(ir) = tmp2;
977 if( RDn(ir) == 15 ) {
978 arm_restore_cpsr();
979 } else {
980 armr.n = tmp >> 31;
981 armr.z = (tmp == 0 );
982 armr.c = IS_CARRY(tmp,operand,operand2) ||
983 (tmp2 < tmp);
984 armr.v = IS_ADDOVERFLOW(tmp,operand, operand2) ||
985 ((tmp&0x80000000) != (tmp2&0x80000000));
986 }
987 break;
988 case 12: /* SBC */
989 LRD(ir) = RN(ir) - arm_get_shift_operand(ir) -
990 (armr.c ? 0 : 1);
991 break;
992 case 13: /* SBCS */
993 operand = RN(ir);
994 operand2 = arm_get_shift_operand(ir);
995 tmp = operand - operand2;
996 tmp2 = tmp - (armr.c ? 0 : 1);
997 if( RDn(ir) == 15 ) {
998 arm_restore_cpsr();
999 } else {
1000 armr.n = tmp >> 31;
1001 armr.z = (tmp == 0 );
1002 armr.c = IS_NOTBORROW(tmp,operand,operand2) &&
1003 (tmp2<tmp);
1004 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2) ||
1005 ((tmp&0x80000000) != (tmp2&0x80000000));
1006 }
1007 break;
1008 case 14: /* RSC */
1009 LRD(ir) = arm_get_shift_operand(ir) - RN(ir) -
1010 (armr.c ? 0 : 1);
1011 break;
1012 case 15: /* RSCS */
1013 operand = arm_get_shift_operand(ir);
1014 operand2 = RN(ir);
1015 tmp = operand - operand2;
1016 tmp2 = tmp - (armr.c ? 0 : 1);
1017 if( RDn(ir) == 15 ) {
1018 arm_restore_cpsr();
1019 } else {
1020 armr.n = tmp >> 31;
1021 armr.z = (tmp == 0 );
1022 armr.c = IS_NOTBORROW(tmp,operand,operand2) &&
1023 (tmp2<tmp);
1024 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2) ||
1025 ((tmp&0x80000000) != (tmp2&0x80000000));
1026 }
1027 break;
1028 case 17: /* TST Rn, operand */
1029 operand = arm_get_shift_operand_s(ir) & RN(ir);
1030 armr.n = operand>>31;
1031 armr.z = (operand == 0);
1032 armr.c = armr.shift_c;
1033 break;
1034 case 19: /* TEQ Rn, operand */
1035 operand = arm_get_shift_operand_s(ir) ^ RN(ir);
1036 armr.n = operand>>31;
1037 armr.z = (operand == 0);
1038 armr.c = armr.shift_c;
1039 break;
1040 case 21: /* CMP Rn, operand */
1041 operand = RN(ir);
1042 operand2 = arm_get_shift_operand(ir);
1043 tmp = operand - operand2;
1044 armr.n = tmp>>31;
1045 armr.z = (tmp == 0);
1046 armr.c = IS_NOTBORROW(tmp,operand,operand2);
1047 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
1048 break;
1049 case 23: /* CMN Rn, operand */
1050 operand = RN(ir);
1051 operand2 = arm_get_shift_operand(ir);
1052 tmp = operand + operand2;
1053 armr.n = tmp>>31;
1054 armr.z = (tmp == 0);
1055 armr.c = IS_CARRY(tmp,operand,operand2);
1056 armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
1057 break;
1058 case 24: /* ORR Rd, Rn, operand */
1059 LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
1060 break;
1061 case 25: /* ORRS Rd, Rn, operand */
1062 operand = arm_get_shift_operand_s(ir) | RN(ir);
1063 LRD(ir) = operand;
1064 if( RDn(ir) == 15 ) {
1065 arm_restore_cpsr();
1066 } else {
1067 armr.n = operand>>31;
1068 armr.z = (operand == 0);
1069 armr.c = armr.shift_c;
1070 }
1071 break;
1072 case 26: /* MOV Rd, operand */
1073 LRD(ir) = arm_get_shift_operand(ir);
1074 break;
1075 case 27: /* MOVS Rd, operand */
1076 operand = arm_get_shift_operand_s(ir);
1077 LRD(ir) = operand;
1078 if( RDn(ir) == 15 ) {
1079 arm_restore_cpsr();
1080 } else {
1081 armr.n = operand>>31;
1082 armr.z = (operand == 0);
1083 armr.c = armr.shift_c;
1084 }
1085 break;
1086 case 28: /* BIC Rd, Rn, operand */
1087 LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
1088 break;
1089 case 29: /* BICS Rd, Rn, operand */
1090 operand = RN(ir) & (~arm_get_shift_operand_s(ir));
1091 LRD(ir) = operand;
1092 if( RDn(ir) == 15 ) {
1093 arm_restore_cpsr();
1094 } else {
1095 armr.n = operand>>31;
1096 armr.z = (operand == 0);
1097 armr.c = armr.shift_c;
1098 }
1099 break;
1100 case 30: /* MVN Rd, operand */
1101 LRD(ir) = ~arm_get_shift_operand(ir);
1102 break;
1103 case 31: /* MVNS Rd, operand */
1104 operand = ~arm_get_shift_operand_s(ir);
1105 LRD(ir) = operand;
1106 if( RDn(ir) == 15 ) {
1107 arm_restore_cpsr();
1108 } else {
1109 armr.n = operand>>31;
1110 armr.z = (operand == 0);
1111 armr.c = armr.shift_c;
1112 }
1113 break;
1114 default:
1115 UNIMP(ir);
1116 }
1117 }
1118 break;
1119 case 1: /* Load/store */
1120 operand = arm_get_address_operand(ir);
1121 switch( (ir>>20)&0x17 ) {
1122 case 0: case 16: case 18: /* STR Rd, address */
1123 arm_write_long( operand, RD(ir) );
1124 break;
1125 case 1: case 17: case 19: /* LDR Rd, address */
1126 LRD(ir) = arm_read_long(operand);
1127 break;
1128 case 2: /* STRT Rd, address */
1129 arm_write_long_user( operand, RD(ir) );
1130 break;
1131 case 3: /* LDRT Rd, address */
1132 LRD(ir) = arm_read_long_user( operand );
1133 break;
1134 case 4: case 20: case 22: /* STRB Rd, address */
1135 arm_write_byte( operand, RD(ir) );
1136 break;
1137 case 5: case 21: case 23: /* LDRB Rd, address */
1138 LRD(ir) = arm_read_byte( operand );
1139 break;
1140 case 6: /* STRBT Rd, address */
1141 arm_write_byte_user( operand, RD(ir) );
1142 break;
1143 case 7: /* LDRBT Rd, address */
1144 LRD(ir) = arm_read_byte_user( operand );
1145 break;
1146 }
1147 break;
1148 case 2: /* Load/store multiple, branch*/
1149 if( (ir & 0x02000000) == 0x02000000 ) { /* B[L] imm24 */
1150 operand = (SIGNEXT24(ir&0x00FFFFFF) << 2);
1151 if( (ir & 0x01000000) == 0x01000000 ) {
1152 armr.r[14] = pc; /* BL */
1153 }
1154 armr.r[15] = pc + 4 + operand;
1155 } else { /* Load/store multiple */
1156 gboolean needRestore = FALSE;
1157 operand = RN(ir);
1159 switch( (ir & 0x01D00000) >> 20 ) {
1160 case 0: /* STMDA */
1161 if( ir & 0x8000 ) {
1162 arm_write_long( operand, armr.r[15]+4 );
1163 operand -= 4;
1164 }
1165 for( i=14; i>= 0; i-- ) {
1166 if( (ir & (1<<i)) ) {
1167 arm_write_long( operand, armr.r[i] );
1168 operand -= 4;
1169 }
1170 }
1171 break;
1172 case 1: /* LDMDA */
1173 for( i=15; i>= 0; i-- ) {
1174 if( (ir & (1<<i)) ) {
1175 armr.r[i] = arm_read_long( operand );
1176 operand -= 4;
1177 }
1178 }
1179 break;
1180 case 4: /* STMDA (S) */
1181 if( ir & 0x8000 ) {
1182 arm_write_long( operand, armr.r[15]+4 );
1183 operand -= 4;
1184 }
1185 for( i=14; i>= 0; i-- ) {
1186 if( (ir & (1<<i)) ) {
1187 arm_write_long( operand, USER_R(i) );
1188 operand -= 4;
1189 }
1190 }
1191 break;
1192 case 5: /* LDMDA (S) */
1193 if( (ir&0x00008000) ) { /* Load PC */
1194 for( i=15; i>= 0; i-- ) {
1195 if( (ir & (1<<i)) ) {
1196 armr.r[i] = arm_read_long( operand );
1197 operand -= 4;
1198 }
1199 }
1200 needRestore = TRUE;
1201 } else {
1202 for( i=15; i>= 0; i-- ) {
1203 if( (ir & (1<<i)) ) {
1204 USER_R(i) = arm_read_long( operand );
1205 operand -= 4;
1206 }
1207 }
1208 }
1209 break;
1210 case 8: /* STMIA */
1211 for( i=0; i< 15; i++ ) {
1212 if( (ir & (1<<i)) ) {
1213 arm_write_long( operand, armr.r[i] );
1214 operand += 4;
1215 }
1216 }
1217 if( ir & 0x8000 ) {
1218 arm_write_long( operand, armr.r[15]+4 );
1219 operand += 4;
1220 }
1221 break;
1222 case 9: /* LDMIA */
1223 for( i=0; i< 16; i++ ) {
1224 if( (ir & (1<<i)) ) {
1225 armr.r[i] = arm_read_long( operand );
1226 operand += 4;
1227 }
1228 }
1229 break;
1230 case 12: /* STMIA (S) */
1231 for( i=0; i< 15; i++ ) {
1232 if( (ir & (1<<i)) ) {
1233 arm_write_long( operand, USER_R(i) );
1234 operand += 4;
1235 }
1236 }
1237 if( ir & 0x8000 ) {
1238 arm_write_long( operand, armr.r[15]+4 );
1239 operand += 4;
1240 }
1241 break;
1242 case 13: /* LDMIA (S) */
1243 if( (ir&0x00008000) ) { /* Load PC */
1244 for( i=0; i < 16; i++ ) {
1245 if( (ir & (1<<i)) ) {
1246 armr.r[i] = arm_read_long( operand );
1247 operand += 4;
1248 }
1249 }
1250 needRestore = TRUE;
1251 } else {
1252 for( i=0; i < 16; i++ ) {
1253 if( (ir & (1<<i)) ) {
1254 USER_R(i) = arm_read_long( operand );
1255 operand += 4;
1256 }
1257 }
1258 }
1259 break;
1260 case 16: /* STMDB */
1261 if( ir & 0x8000 ) {
1262 operand -= 4;
1263 arm_write_long( operand, armr.r[15]+4 );
1264 }
1265 for( i=14; i>= 0; i-- ) {
1266 if( (ir & (1<<i)) ) {
1267 operand -= 4;
1268 arm_write_long( operand, armr.r[i] );
1269 }
1270 }
1271 break;
1272 case 17: /* LDMDB */
1273 for( i=15; i>= 0; i-- ) {
1274 if( (ir & (1<<i)) ) {
1275 operand -= 4;
1276 armr.r[i] = arm_read_long( operand );
1277 }
1278 }
1279 break;
1280 case 20: /* STMDB (S) */
1281 if( ir & 0x8000 ) {
1282 operand -= 4;
1283 arm_write_long( operand, armr.r[15]+4 );
1284 }
1285 for( i=14; i>= 0; i-- ) {
1286 if( (ir & (1<<i)) ) {
1287 operand -= 4;
1288 arm_write_long( operand, USER_R(i) );
1289 }
1290 }
1291 break;
1292 case 21: /* LDMDB (S) */
1293 if( (ir&0x00008000) ) { /* Load PC */
1294 for( i=15; i>= 0; i-- ) {
1295 if( (ir & (1<<i)) ) {
1296 operand -= 4;
1297 armr.r[i] = arm_read_long( operand );
1298 }
1299 }
1300 needRestore = TRUE;
1301 } else {
1302 for( i=15; i>= 0; i-- ) {
1303 if( (ir & (1<<i)) ) {
1304 operand -= 4;
1305 USER_R(i) = arm_read_long( operand );
1306 }
1307 }
1308 }
1309 break;
1310 case 24: /* STMIB */
1311 for( i=0; i< 15; i++ ) {
1312 if( (ir & (1<<i)) ) {
1313 operand += 4;
1314 arm_write_long( operand, armr.r[i] );
1315 }
1316 }
1317 if( ir & 0x8000 ) {
1318 operand += 4;
1319 arm_write_long( operand, armr.r[15]+4 );
1320 }
1321 break;
1322 case 25: /* LDMIB */
1323 for( i=0; i< 16; i++ ) {
1324 if( (ir & (1<<i)) ) {
1325 operand += 4;
1326 armr.r[i] = arm_read_long( operand );
1327 }
1328 }
1329 break;
1330 case 28: /* STMIB (S) */
1331 for( i=0; i< 15; i++ ) {
1332 if( (ir & (1<<i)) ) {
1333 operand += 4;
1334 arm_write_long( operand, USER_R(i) );
1335 }
1336 }
1337 if( ir & 0x8000 ) {
1338 operand += 4;
1339 arm_write_long( operand, armr.r[15]+4 );
1340 }
1341 break;
1342 case 29: /* LDMIB (S) */
1343 if( (ir&0x00008000) ) { /* Load PC */
1344 for( i=0; i < 16; i++ ) {
1345 if( (ir & (1<<i)) ) {
1346 operand += 4;
1347 armr.r[i] = arm_read_long( operand );
1348 }
1349 }
1350 needRestore = TRUE;
1351 } else {
1352 for( i=0; i < 16; i++ ) {
1353 if( (ir & (1<<i)) ) {
1354 operand += 4;
1355 USER_R(i) = arm_read_long( operand );
1356 }
1357 }
1358 }
1359 break;
1360 }
1362 if( WFLAG(ir) )
1363 LRN(ir) = operand;
1364 if( needRestore )
1365 arm_restore_cpsr();
1366 }
1367 break;
1368 case 3: /* Copro */
1369 if( (ir & 0x0F000000) == 0x0F000000 ) { /* SWI */
1370 arm_raise_exception( EXC_SOFTWARE );
1371 } else {
1372 UNIMP(ir);
1373 }
1374 break;
1375 }
1377 }
1379 if( armr.r[15] >= 0x00200000 ) {
1380 armr.running = FALSE;
1381 ERROR( "ARM Halted: BRANCH to invalid address %08X at %08X", armr.r[15], pc );
1382 return FALSE;
1383 }
1384 return TRUE;
1385 }
.