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