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