filename | src/aica/armcore.c |
changeset | 44:8da2cbcffe24 |
prev | 43:0cf3e339cc59 |
next | 46:30d123047e16 |
author | nkeynes |
date | Mon Dec 26 11:52:56 2005 +0000 (18 years ago) |
permissions | -rw-r--r-- |
last change | Default ARM to not-running for sanity's sake Stop machine on UNIMP abort |
view | annotate | diff | log | raw |
1 /**
2 * $Id: armcore.c,v 1.9 2005-12-26 11:52:56 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 "aica/armcore.h"
22 #include "mem.h"
24 struct arm_registers armr;
26 void arm_set_mode( int mode );
28 uint32_t arm_exceptions[][2] = {{ MODE_SVC, 0x00000000 },
29 { MODE_UND, 0x00000004 },
30 { MODE_SVC, 0x00000008 },
31 { MODE_ABT, 0x0000000C },
32 { MODE_ABT, 0x00000010 },
33 { MODE_IRQ, 0x00000018 },
34 { MODE_FIQ, 0x0000001C } };
36 #define EXC_RESET 0
37 #define EXC_UNDEFINED 1
38 #define EXC_SOFTWARE 2
39 #define EXC_PREFETCH_ABORT 3
40 #define EXC_DATA_ABORT 4
41 #define EXC_IRQ 5
42 #define EXC_FAST_IRQ 6
44 uint32_t arm_cpu_freq = ARM_BASE_RATE;
45 uint32_t arm_cpu_period = 1000 / ARM_BASE_RATE;
48 static struct breakpoint_struct arm_breakpoints[MAX_BREAKPOINTS];
49 static int arm_breakpoint_count = 0;
51 void arm_set_breakpoint( uint32_t pc, int type )
52 {
53 arm_breakpoints[arm_breakpoint_count].address = pc;
54 arm_breakpoints[arm_breakpoint_count].type = type;
55 arm_breakpoint_count++;
56 }
58 gboolean arm_clear_breakpoint( uint32_t pc, int type )
59 {
60 int i;
62 for( i=0; i<arm_breakpoint_count; i++ ) {
63 if( arm_breakpoints[i].address == pc &&
64 arm_breakpoints[i].type == type ) {
65 while( ++i < arm_breakpoint_count ) {
66 arm_breakpoints[i-1].address = arm_breakpoints[i].address;
67 arm_breakpoints[i-1].type = arm_breakpoints[i].type;
68 }
69 arm_breakpoint_count--;
70 return TRUE;
71 }
72 }
73 return FALSE;
74 }
76 int arm_get_breakpoint( uint32_t pc )
77 {
78 int i;
79 for( i=0; i<arm_breakpoint_count; i++ ) {
80 if( arm_breakpoints[i].address == pc )
81 return arm_breakpoints[i].type;
82 }
83 return 0;
84 }
86 uint32_t arm_run_slice( uint32_t nanosecs )
87 {
88 int i;
89 uint32_t target = armr.icount + nanosecs / arm_cpu_period;
90 uint32_t start = armr.icount;
91 while( armr.icount < target ) {
92 armr.icount++;
93 if( !arm_execute_instruction() )
94 break;
95 #ifdef ENABLE_DEBUG_MODE
96 for( i=0; i<arm_breakpoint_count; i++ ) {
97 if( arm_breakpoints[i].address == armr.r[15] ) {
98 break;
99 }
100 }
101 if( i != arm_breakpoint_count ) {
102 dreamcast_stop();
103 if( arm_breakpoints[i].type == BREAK_ONESHOT )
104 arm_clear_breakpoint( armr.r[15], BREAK_ONESHOT );
105 break;
106 }
107 #endif
108 }
110 if( target != armr.icount ) {
111 /* Halted - compute time actually executed */
112 nanosecs = (armr.icount - start) * arm_cpu_period;
113 }
114 return nanosecs;
115 }
117 void arm_save_state( FILE *f )
118 {
119 fwrite( &armr, sizeof(armr), 1, f );
120 }
122 int arm_load_state( FILE *f )
123 {
124 fread( &armr, sizeof(armr), 1, f );
125 return 0;
126 }
128 /* Exceptions */
129 void arm_reset( void )
130 {
131 /* Wipe all processor state */
132 memset( &armr, 0, sizeof(armr) );
134 armr.cpsr = MODE_SVC | CPSR_I | CPSR_F;
135 armr.r[15] = 0x00000000;
136 }
138 #define SET_CPSR_CONTROL 0x00010000
139 #define SET_CPSR_EXTENSION 0x00020000
140 #define SET_CPSR_STATUS 0x00040000
141 #define SET_CPSR_FLAGS 0x00080000
143 uint32_t arm_get_cpsr( void )
144 {
145 /* write back all flags to the cpsr */
146 armr.cpsr = armr.cpsr & CPSR_COMPACT_MASK;
147 if( armr.n ) armr.cpsr |= CPSR_N;
148 if( armr.z ) armr.cpsr |= CPSR_Z;
149 if( armr.c ) armr.cpsr |= CPSR_C;
150 if( armr.v ) armr.cpsr |= CPSR_V;
151 if( armr.t ) armr.cpsr |= CPSR_T;
152 return armr.cpsr;
153 }
155 /**
156 * Set the CPSR to the specified value.
157 *
158 * @param value values to set in CPSR
159 * @param fields set of mask values to define which sections of the
160 * CPSR to set (one of the SET_CPSR_* values above)
161 */
162 void arm_set_cpsr( uint32_t value, uint32_t fields )
163 {
164 if( IS_PRIVILEGED_MODE() ) {
165 if( fields & SET_CPSR_CONTROL ) {
166 int mode = value & CPSR_MODE;
167 arm_set_mode( mode );
168 armr.t = ( value & CPSR_T ); /* Technically illegal to change */
169 armr.cpsr = (armr.cpsr & 0xFFFFFF00) | (value & 0x000000FF);
170 }
172 /* Middle 16 bits not currently defined */
173 }
174 if( fields & SET_CPSR_FLAGS ) {
175 /* Break flags directly out of given value - don't bother writing
176 * back to CPSR
177 */
178 armr.n = ( value & CPSR_N );
179 armr.z = ( value & CPSR_Z );
180 armr.c = ( value & CPSR_C );
181 armr.v = ( value & CPSR_V );
182 }
183 }
185 void arm_set_spsr( uint32_t value, uint32_t fields )
186 {
187 /* Only defined if we actually have an SPSR register */
188 if( IS_EXCEPTION_MODE() ) {
189 if( fields & SET_CPSR_CONTROL ) {
190 armr.spsr = (armr.spsr & 0xFFFFFF00) | (value & 0x000000FF);
191 }
193 /* Middle 16 bits not currently defined */
195 if( fields & SET_CPSR_FLAGS ) {
196 armr.spsr = (armr.spsr & 0x00FFFFFF) | (value & 0xFF000000);
197 }
198 }
199 }
201 /**
202 * Raise an ARM exception (other than reset, which uses arm_reset().
203 * @param exception one of the EXC_* exception codes defined above.
204 */
205 void arm_raise_exception( int exception )
206 {
207 int mode = arm_exceptions[exception][0];
208 uint32_t spsr = arm_get_cpsr();
209 arm_set_mode( mode );
210 armr.spsr = spsr;
211 armr.r[14] = armr.r[15];
212 armr.cpsr = (spsr & (~CPSR_T)) | CPSR_I;
213 if( mode == MODE_FIQ )
214 armr.cpsr |= CPSR_F;
215 armr.r[15] = arm_exceptions[exception][1];
216 }
218 void arm_restore_cpsr( void )
219 {
220 int spsr = armr.spsr;
221 int mode = spsr & CPSR_MODE;
222 arm_set_mode( mode );
223 armr.cpsr = spsr;
224 armr.n = ( spsr & CPSR_N );
225 armr.z = ( spsr & CPSR_Z );
226 armr.c = ( spsr & CPSR_C );
227 armr.v = ( spsr & CPSR_V );
228 armr.t = ( spsr & CPSR_T );
229 }
233 /**
234 * Change the current executing ARM mode to the requested mode.
235 * Saves any required registers to banks and restores those for the
236 * correct mode. (Note does not actually update CPSR at the moment).
237 */
238 void arm_set_mode( int targetMode )
239 {
240 int currentMode = armr.cpsr & CPSR_MODE;
241 if( currentMode == targetMode )
242 return;
244 switch( currentMode ) {
245 case MODE_USER:
246 case MODE_SYS:
247 armr.user_r[5] = armr.r[13];
248 armr.user_r[6] = armr.r[14];
249 break;
250 case MODE_SVC:
251 armr.svc_r[0] = armr.r[13];
252 armr.svc_r[1] = armr.r[14];
253 armr.svc_r[2] = armr.spsr;
254 break;
255 case MODE_ABT:
256 armr.abt_r[0] = armr.r[13];
257 armr.abt_r[1] = armr.r[14];
258 armr.abt_r[2] = armr.spsr;
259 break;
260 case MODE_UND:
261 armr.und_r[0] = armr.r[13];
262 armr.und_r[1] = armr.r[14];
263 armr.und_r[2] = armr.spsr;
264 break;
265 case MODE_IRQ:
266 armr.irq_r[0] = armr.r[13];
267 armr.irq_r[1] = armr.r[14];
268 armr.irq_r[2] = armr.spsr;
269 break;
270 case MODE_FIQ:
271 armr.fiq_r[0] = armr.r[8];
272 armr.fiq_r[1] = armr.r[9];
273 armr.fiq_r[2] = armr.r[10];
274 armr.fiq_r[3] = armr.r[11];
275 armr.fiq_r[4] = armr.r[12];
276 armr.fiq_r[5] = armr.r[13];
277 armr.fiq_r[6] = armr.r[14];
278 armr.fiq_r[7] = armr.spsr;
279 armr.r[8] = armr.user_r[0];
280 armr.r[9] = armr.user_r[1];
281 armr.r[10] = armr.user_r[2];
282 armr.r[11] = armr.user_r[3];
283 armr.r[12] = armr.user_r[4];
284 break;
285 }
287 switch( targetMode ) {
288 case MODE_USER:
289 case MODE_SYS:
290 armr.r[13] = armr.user_r[5];
291 armr.r[14] = armr.user_r[6];
292 break;
293 case MODE_SVC:
294 armr.r[13] = armr.svc_r[0];
295 armr.r[14] = armr.svc_r[1];
296 armr.spsr = armr.svc_r[2];
297 break;
298 case MODE_ABT:
299 armr.r[13] = armr.abt_r[0];
300 armr.r[14] = armr.abt_r[1];
301 armr.spsr = armr.abt_r[2];
302 break;
303 case MODE_UND:
304 armr.r[13] = armr.und_r[0];
305 armr.r[14] = armr.und_r[1];
306 armr.spsr = armr.und_r[2];
307 break;
308 case MODE_IRQ:
309 armr.r[13] = armr.irq_r[0];
310 armr.r[14] = armr.irq_r[1];
311 armr.spsr = armr.irq_r[2];
312 break;
313 case MODE_FIQ:
314 armr.user_r[0] = armr.r[8];
315 armr.user_r[1] = armr.r[9];
316 armr.user_r[2] = armr.r[10];
317 armr.user_r[3] = armr.r[11];
318 armr.user_r[4] = armr.r[12];
319 armr.r[8] = armr.fiq_r[0];
320 armr.r[9] = armr.fiq_r[1];
321 armr.r[10] = armr.fiq_r[2];
322 armr.r[11] = armr.fiq_r[3];
323 armr.r[12] = armr.fiq_r[4];
324 armr.r[13] = armr.fiq_r[5];
325 armr.r[14] = armr.fiq_r[6];
326 armr.spsr = armr.fiq_r[7];
327 break;
328 }
329 }
331 /* Page references are as per ARM DDI 0100E (June 2000) */
333 #define MEM_READ_BYTE( addr ) arm_read_byte(addr)
334 #define MEM_READ_WORD( addr ) arm_read_word(addr)
335 #define MEM_READ_LONG( addr ) arm_read_long(addr)
336 #define MEM_WRITE_BYTE( addr, val ) arm_write_byte(addr, val)
337 #define MEM_WRITE_WORD( addr, val ) arm_write_word(addr, val)
338 #define MEM_WRITE_LONG( addr, val ) arm_write_long(addr, val)
341 #define IS_NOTBORROW( result, op1, op2 ) (op2 > op1 ? 0 : 1)
342 #define IS_CARRY( result, op1, op2 ) (result < op1 ? 1 : 0)
343 #define IS_SUBOVERFLOW( result, op1, op2 ) (((op1^op2) & (result^op1)) >> 31)
344 #define IS_ADDOVERFLOW( result, op1, op2 ) (((op1&op2) & (result^op1)) >> 31)
346 #define PC armr.r[15]
348 /* Instruction fields */
349 #define COND(ir) (ir>>28)
350 #define GRP(ir) ((ir>>26)&0x03)
351 #define OPCODE(ir) ((ir>>20)&0x1F)
352 #define IFLAG(ir) (ir&0x02000000)
353 #define SFLAG(ir) (ir&0x00100000)
354 #define PFLAG(ir) (ir&0x01000000)
355 #define UFLAG(ir) (ir&0x00800000)
356 #define BFLAG(ir) (ir&0x00400000)
357 #define WFLAG(ir) (IR&0x00200000)
358 #define LFLAG(ir) SFLAG(ir)
359 #define RN(ir) (armr.r[((ir>>16)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
360 #define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>12)&0x0F) == 0x0F ? 4 : 0))
361 #define RDn(ir) ((ir>>12)&0x0F)
362 #define RS(ir) (armr.r[((ir>>8)&0x0F)] + (((ir>>8)&0x0F) == 0x0F ? 4 : 0))
363 #define RM(ir) (armr.r[(ir&0x0F)] + (((ir&0x0F) == 0x0F ? 4 : 0)) )
364 #define LRN(ir) armr.r[((ir>>16)&0x0F)]
365 #define LRD(ir) armr.r[((ir>>12)&0x0F)]
366 #define LRS(ir) armr.r[((ir>>8)&0x0F)]
367 #define LRM(ir) armr.r[(ir&0x0F)]
369 #define IMM8(ir) (ir&0xFF)
370 #define IMM12(ir) (ir&0xFFF)
371 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
372 #define IMMROT(ir) ((ir>>7)&0x1E)
373 #define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
374 #define SIGNEXT24(n) ((n&0x00800000) ? (n|0xFF000000) : (n&0x00FFFFFF))
375 #define SHIFT(ir) ((ir>>4)&0x07)
376 #define DISP24(ir) ((ir&0x00FFFFFF))
377 #define UNDEF(ir) do{ arm_raise_exception( EXC_UNDEFINED ); return TRUE; } while(0)
378 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC-4, ir ); dreamcast_stop(); return FALSE; }while(0)
380 /**
381 * Determine the value of the shift-operand for a data processing instruction,
382 * without determing a value for shift_C (optimized form for instructions that
383 * don't require shift_C ).
384 * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
385 */
386 static uint32_t arm_get_shift_operand( uint32_t ir )
387 {
388 uint32_t operand, tmp;
389 if( IFLAG(ir) == 0 ) {
390 operand = RM(ir);
391 switch(SHIFT(ir)) {
392 case 0: /* (Rm << imm) */
393 operand = operand << SHIFTIMM(ir);
394 break;
395 case 1: /* (Rm << Rs) */
396 tmp = RS(ir)&0xFF;
397 if( tmp > 31 ) operand = 0;
398 else operand = operand << tmp;
399 break;
400 case 2: /* (Rm >> imm) */
401 operand = operand >> SHIFTIMM(ir);
402 break;
403 case 3: /* (Rm >> Rs) */
404 tmp = RS(ir) & 0xFF;
405 if( tmp > 31 ) operand = 0;
406 else operand = operand >> ir;
407 break;
408 case 4: /* (Rm >>> imm) */
409 tmp = SHIFTIMM(ir);
410 if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
411 else operand = ((int32_t)operand) >> tmp;
412 break;
413 case 5: /* (Rm >>> Rs) */
414 tmp = RS(ir) & 0xFF;
415 if( tmp > 31 ) operand = ((int32_t)operand) >> 31;
416 else operand = ((int32_t)operand) >> tmp;
417 break;
418 case 6:
419 tmp = SHIFTIMM(ir);
420 if( tmp == 0 ) /* RRX aka rotate with carry */
421 operand = (operand >> 1) | (armr.c<<31);
422 else
423 operand = ROTATE_RIGHT_LONG(operand,tmp);
424 break;
425 case 7:
426 tmp = RS(ir)&0x1F;
427 operand = ROTATE_RIGHT_LONG(operand,tmp);
428 break;
429 }
430 } else {
431 operand = IMM8(ir);
432 tmp = IMMROT(ir);
433 operand = ROTATE_RIGHT_LONG(operand, tmp);
434 }
435 return operand;
436 }
438 /**
439 * Determine the value of the shift-operand for a data processing instruction,
440 * and set armr.shift_c accordingly.
441 * @see s5.1 Addressing Mode 1 - Data-processing operands (p A5-2, 218)
442 */
443 static uint32_t arm_get_shift_operand_s( uint32_t ir )
444 {
445 uint32_t operand, tmp;
446 if( IFLAG(ir) == 0 ) {
447 operand = RM(ir);
448 switch(SHIFT(ir)) {
449 case 0: /* (Rm << imm) */
450 tmp = SHIFTIMM(ir);
451 if( tmp == 0 ) { /* Rm */
452 armr.shift_c = armr.c;
453 } else { /* Rm << imm */
454 armr.shift_c = (operand >> (32-tmp)) & 0x01;
455 operand = operand << tmp;
456 }
457 break;
458 case 1: /* (Rm << Rs) */
459 tmp = RS(ir)&0xFF;
460 if( tmp == 0 ) {
461 armr.shift_c = armr.c;
462 } else {
463 if( tmp <= 32 )
464 armr.shift_c = (operand >> (32-tmp)) & 0x01;
465 else armr.shift_c = 0;
466 if( tmp < 32 )
467 operand = operand << tmp;
468 else operand = 0;
469 }
470 break;
471 case 2: /* (Rm >> imm) */
472 tmp = SHIFTIMM(ir);
473 if( tmp == 0 ) {
474 armr.shift_c = operand >> 31;
475 operand = 0;
476 } else {
477 armr.shift_c = (operand >> (tmp-1)) & 0x01;
478 operand = RM(ir) >> tmp;
479 }
480 break;
481 case 3: /* (Rm >> Rs) */
482 tmp = RS(ir) & 0xFF;
483 if( tmp == 0 ) {
484 armr.shift_c = armr.c;
485 } else {
486 if( tmp <= 32 )
487 armr.shift_c = (operand >> (tmp-1))&0x01;
488 else armr.shift_c = 0;
489 if( tmp < 32 )
490 operand = operand >> tmp;
491 else operand = 0;
492 }
493 break;
494 case 4: /* (Rm >>> imm) */
495 tmp = SHIFTIMM(ir);
496 if( tmp == 0 ) {
497 armr.shift_c = operand >> 31;
498 operand = -armr.shift_c;
499 } else {
500 armr.shift_c = (operand >> (tmp-1)) & 0x01;
501 operand = ((int32_t)operand) >> tmp;
502 }
503 break;
504 case 5: /* (Rm >>> Rs) */
505 tmp = RS(ir) & 0xFF;
506 if( tmp == 0 ) {
507 armr.shift_c = armr.c;
508 } else {
509 if( tmp < 32 ) {
510 armr.shift_c = (operand >> (tmp-1))&0x01;
511 operand = ((int32_t)operand) >> tmp;
512 } else {
513 armr.shift_c = operand >> 31;
514 operand = ((int32_t)operand) >> 31;
515 }
516 }
517 break;
518 case 6:
519 tmp = SHIFTIMM(ir);
520 if( tmp == 0 ) { /* RRX aka rotate with carry */
521 armr.shift_c = operand&0x01;
522 operand = (operand >> 1) | (armr.c<<31);
523 } else {
524 armr.shift_c = operand>>(tmp-1);
525 operand = ROTATE_RIGHT_LONG(operand,tmp);
526 }
527 break;
528 case 7:
529 tmp = RS(ir)&0xFF;
530 if( tmp == 0 ) {
531 armr.shift_c = armr.c;
532 } else {
533 tmp &= 0x1F;
534 if( tmp == 0 ) {
535 armr.shift_c = operand>>31;
536 } else {
537 armr.shift_c = (operand>>(tmp-1))&0x1;
538 operand = ROTATE_RIGHT_LONG(operand,tmp);
539 }
540 }
541 break;
542 }
543 } else {
544 operand = IMM8(ir);
545 tmp = IMMROT(ir);
546 if( tmp == 0 ) {
547 armr.shift_c = armr.c;
548 } else {
549 operand = ROTATE_RIGHT_LONG(operand, tmp);
550 armr.shift_c = operand>>31;
551 }
552 }
553 return operand;
554 }
556 /**
557 * Another variant of the shifter code for index-based memory addressing.
558 * Distinguished by the fact that it doesn't support register shifts, and
559 * ignores the I flag (WTF do the load/store instructions use the I flag to
560 * mean the _exact opposite_ of what it means for the data processing
561 * instructions ???)
562 */
563 static uint32_t arm_get_address_index( uint32_t ir )
564 {
565 uint32_t operand = RM(ir);
566 uint32_t tmp;
568 switch(SHIFT(ir)) {
569 case 0: /* (Rm << imm) */
570 operand = operand << SHIFTIMM(ir);
571 break;
572 case 2: /* (Rm >> imm) */
573 operand = operand >> SHIFTIMM(ir);
574 break;
575 case 4: /* (Rm >>> imm) */
576 tmp = SHIFTIMM(ir);
577 if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
578 else operand = ((int32_t)operand) >> tmp;
579 break;
580 case 6:
581 tmp = SHIFTIMM(ir);
582 if( tmp == 0 ) /* RRX aka rotate with carry */
583 operand = (operand >> 1) | (armr.c<<31);
584 else
585 operand = ROTATE_RIGHT_LONG(operand,tmp);
586 break;
587 default: UNIMP(ir);
588 }
589 return operand;
590 }
592 /**
593 * Determine the address operand of a load/store instruction, including
594 * applying any pre/post adjustments to the address registers.
595 * @see s5.2 Addressing Mode 2 - Load and Store Word or Unsigned Byte
596 * @param The instruction word.
597 * @return The calculated address
598 */
599 static uint32_t arm_get_address_operand( uint32_t ir )
600 {
601 uint32_t addr;
603 /* I P U . W */
604 switch( (ir>>21)&0x1D ) {
605 case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
606 case 1:
607 addr = RN(ir);
608 LRN(ir) = addr - IMM12(ir);
609 break;
610 case 4: /* Rn += imm offsett (post-indexed) [5.2.8 A5-28] */
611 case 5:
612 addr = RN(ir);
613 LRN(ir) = addr + IMM12(ir);
614 break;
615 case 8: /* Rn - imm offset [5.2.2 A5-20] */
616 addr = RN(ir) - IMM12(ir);
617 break;
618 case 9: /* Rn -= imm offset (pre-indexed) [5.2.5 A5-24] */
619 addr = RN(ir) - IMM12(ir);
620 LRN(ir) = addr;
621 break;
622 case 12: /* Rn + imm offset [5.2.2 A5-20] */
623 addr = RN(ir) + IMM12(ir);
624 break;
625 case 13: /* Rn += imm offset [5.2.5 A5-24 ] */
626 addr = RN(ir) + IMM12(ir);
627 LRN(ir) = addr;
628 break;
629 case 16: /* Rn -= Rm (post-indexed) [5.2.10 A5-32 ] */
630 case 17:
631 addr = RN(ir);
632 LRN(ir) = addr - arm_get_address_index(ir);
633 break;
634 case 20: /* Rn += Rm (post-indexed) [5.2.10 A5-32 ] */
635 case 21:
636 addr = RN(ir);
637 LRN(ir) = addr - arm_get_address_index(ir);
638 break;
639 case 24: /* Rn - Rm [5.2.4 A5-23] */
640 addr = RN(ir) - arm_get_address_index(ir);
641 break;
642 case 25: /* RN -= Rm (pre-indexed) [5.2.7 A5-26] */
643 addr = RN(ir) - arm_get_address_index(ir);
644 LRN(ir) = addr;
645 break;
646 case 28: /* Rn + Rm [5.2.4 A5-23] */
647 addr = RN(ir) + arm_get_address_index(ir);
648 break;
649 case 29: /* RN += Rm (pre-indexed) [5.2.7 A5-26] */
650 addr = RN(ir) + arm_get_address_index(ir);
651 LRN(ir) = addr;
652 break;
653 }
654 return addr;
655 }
657 gboolean arm_execute_instruction( void )
658 {
659 uint32_t pc = PC;
660 uint32_t ir = MEM_READ_LONG(pc);
661 uint32_t operand, operand2, tmp, cond;
663 pc += 4;
664 PC = pc;
666 /**
667 * Check the condition bits first - if the condition fails return
668 * immediately without actually looking at the rest of the instruction.
669 */
670 switch( COND(ir) ) {
671 case 0: /* EQ */
672 cond = armr.z;
673 break;
674 case 1: /* NE */
675 cond = !armr.z;
676 break;
677 case 2: /* CS/HS */
678 cond = armr.c;
679 break;
680 case 3: /* CC/LO */
681 cond = !armr.c;
682 break;
683 case 4: /* MI */
684 cond = armr.n;
685 break;
686 case 5: /* PL */
687 cond = !armr.n;
688 break;
689 case 6: /* VS */
690 cond = armr.v;
691 break;
692 case 7: /* VC */
693 cond = !armr.v;
694 break;
695 case 8: /* HI */
696 cond = armr.c && !armr.z;
697 break;
698 case 9: /* LS */
699 cond = (!armr.c) || armr.z;
700 break;
701 case 10: /* GE */
702 cond = (armr.n == armr.v);
703 break;
704 case 11: /* LT */
705 cond = (armr.n != armr.v);
706 break;
707 case 12: /* GT */
708 cond = (!armr.z) && (armr.n == armr.v);
709 break;
710 case 13: /* LE */
711 cond = armr.z || (armr.n != armr.v);
712 break;
713 case 14: /* AL */
714 cond = 1;
715 break;
716 case 15: /* (NV) */
717 cond = 0;
718 UNDEF(ir);
719 }
720 if( !cond )
721 return TRUE;
723 /**
724 * Condition passed, now for the actual instructions...
725 */
726 switch( GRP(ir) ) {
727 case 0:
728 if( (ir & 0x0D900000) == 0x01000000 ) {
729 /* Instructions that aren't actual data processing even though
730 * they sit in the DP instruction block.
731 */
732 switch( ir & 0x0FF000F0 ) {
733 case 0x01200010: /* BX Rd */
734 armr.t = ir & 0x01;
735 armr.r[15] = RM(ir) & 0xFFFFFFFE;
736 break;
737 case 0x01000000: /* MRS Rd, CPSR */
738 LRD(ir) = arm_get_cpsr();
739 break;
740 case 0x01400000: /* MRS Rd, SPSR */
741 LRD(ir) = armr.spsr;
742 break;
743 case 0x01200000: /* MSR CPSR, Rd */
744 arm_set_cpsr( RM(ir), ir );
745 break;
746 case 0x01600000: /* MSR SPSR, Rd */
747 arm_set_spsr( RM(ir), ir );
748 break;
749 case 0x03200000: /* MSR CPSR, imm */
750 arm_set_cpsr( ROTIMM12(ir), ir );
751 break;
752 case 0x03600000: /* MSR SPSR, imm */
753 arm_set_spsr( ROTIMM12(ir), ir );
754 break;
755 default:
756 UNIMP(ir);
757 }
758 } else if( (ir & 0x0E000090) == 0x00000090 ) {
759 /* Neither are these */
760 switch( (ir>>5)&0x03 ) {
761 case 0:
762 /* Arithmetic extension area */
763 switch(OPCODE(ir)) {
764 case 0: /* MUL */
765 break;
766 case 1: /* MULS */
767 break;
768 case 2: /* MLA */
769 break;
770 case 3: /* MLAS */
771 break;
772 case 8: /* UMULL */
773 break;
774 case 9: /* UMULLS */
775 break;
776 case 10: /* UMLAL */
777 break;
778 case 11: /* UMLALS */
779 break;
780 case 12: /* SMULL */
781 break;
782 case 13: /* SMULLS */
783 break;
784 case 14: /* SMLAL */
785 break;
786 case 15: /* SMLALS */
787 break;
788 case 16: /* SWP */
789 break;
790 case 20: /* SWPB */
791 break;
792 default:
793 UNIMP(ir);
794 }
795 break;
796 case 1:
797 if( LFLAG(ir) ) {
798 /* LDRH */
799 } else {
800 /* STRH */
801 }
802 break;
803 case 2:
804 if( LFLAG(ir) ) {
805 /* LDRSB */
806 } else {
807 UNIMP(ir);
808 }
809 break;
810 case 3:
811 if( LFLAG(ir) ) {
812 /* LDRSH */
813 } else {
814 UNIMP(ir);
815 }
816 break;
817 }
818 } else {
819 /* Data processing */
821 switch(OPCODE(ir)) {
822 case 0: /* AND Rd, Rn, operand */
823 LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
824 break;
825 case 1: /* ANDS Rd, Rn, operand */
826 operand = arm_get_shift_operand_s(ir) & RN(ir);
827 LRD(ir) = operand;
828 if( RDn(ir) == 15 ) {
829 arm_restore_cpsr();
830 } else {
831 armr.n = operand>>31;
832 armr.z = (operand == 0);
833 armr.c = armr.shift_c;
834 }
835 break;
836 case 2: /* EOR Rd, Rn, operand */
837 LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
838 break;
839 case 3: /* EORS Rd, Rn, operand */
840 operand = arm_get_shift_operand_s(ir) ^ RN(ir);
841 LRD(ir) = operand;
842 if( RDn(ir) == 15 ) {
843 arm_restore_cpsr();
844 } else {
845 armr.n = operand>>31;
846 armr.z = (operand == 0);
847 armr.c = armr.shift_c;
848 }
849 break;
850 case 4: /* SUB Rd, Rn, operand */
851 LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
852 break;
853 case 5: /* SUBS Rd, Rn, operand */
854 operand = RN(ir);
855 operand2 = arm_get_shift_operand(ir);
856 tmp = operand - operand2;
857 LRD(ir) = tmp;
858 if( RDn(ir) == 15 ) {
859 arm_restore_cpsr();
860 } else {
861 armr.n = tmp>>31;
862 armr.z = (tmp == 0);
863 armr.c = IS_NOTBORROW(tmp,operand,operand2);
864 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
865 }
866 break;
867 case 6: /* RSB Rd, operand, Rn */
868 LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
869 break;
870 case 7: /* RSBS Rd, operand, Rn */
871 operand = arm_get_shift_operand(ir);
872 operand2 = RN(ir);
873 tmp = operand - operand2;
874 LRD(ir) = tmp;
875 if( RDn(ir) == 15 ) {
876 arm_restore_cpsr();
877 } else {
878 armr.n = tmp>>31;
879 armr.z = (tmp == 0);
880 armr.c = IS_NOTBORROW(tmp,operand,operand2);
881 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
882 }
883 break;
884 case 8: /* ADD Rd, Rn, operand */
885 LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
886 break;
887 case 9: /* ADDS Rd, Rn, operand */
888 operand = arm_get_shift_operand(ir);
889 operand2 = RN(ir);
890 tmp = operand + operand2;
891 LRD(ir) = tmp;
892 if( RDn(ir) == 15 ) {
893 arm_restore_cpsr();
894 } else {
895 armr.n = tmp>>31;
896 armr.z = (tmp == 0);
897 armr.c = IS_CARRY(tmp,operand,operand2);
898 armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
899 }
900 break;
901 case 10: /* ADC */
902 case 11: /* ADCS */
903 case 12: /* SBC */
904 case 13: /* SBCS */
905 case 14: /* RSC */
906 case 15: /* RSCS */
907 break;
908 case 17: /* TST Rn, operand */
909 operand = arm_get_shift_operand_s(ir) & RN(ir);
910 armr.n = operand>>31;
911 armr.z = (operand == 0);
912 armr.c = armr.shift_c;
913 break;
914 case 19: /* TEQ Rn, operand */
915 operand = arm_get_shift_operand_s(ir) ^ RN(ir);
916 armr.n = operand>>31;
917 armr.z = (operand == 0);
918 armr.c = armr.shift_c;
919 break;
920 case 21: /* CMP Rn, operand */
921 operand = RN(ir);
922 operand2 = arm_get_shift_operand(ir);
923 tmp = operand - operand2;
924 armr.n = tmp>>31;
925 armr.z = (tmp == 0);
926 armr.c = IS_NOTBORROW(tmp,operand,operand2);
927 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
928 break;
929 case 23: /* CMN Rn, operand */
930 operand = RN(ir);
931 operand2 = arm_get_shift_operand(ir);
932 tmp = operand + operand2;
933 armr.n = tmp>>31;
934 armr.z = (tmp == 0);
935 armr.c = IS_CARRY(tmp,operand,operand2);
936 armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
937 break;
938 case 24: /* ORR Rd, Rn, operand */
939 LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
940 break;
941 case 25: /* ORRS Rd, Rn, operand */
942 operand = arm_get_shift_operand_s(ir) | RN(ir);
943 LRD(ir) = operand;
944 if( RDn(ir) == 15 ) {
945 arm_restore_cpsr();
946 } else {
947 armr.n = operand>>31;
948 armr.z = (operand == 0);
949 armr.c = armr.shift_c;
950 }
951 break;
952 case 26: /* MOV Rd, operand */
953 LRD(ir) = arm_get_shift_operand(ir);
954 break;
955 case 27: /* MOVS Rd, operand */
956 operand = arm_get_shift_operand_s(ir);
957 LRD(ir) = operand;
958 if( RDn(ir) == 15 ) {
959 arm_restore_cpsr();
960 } else {
961 armr.n = operand>>31;
962 armr.z = (operand == 0);
963 armr.c = armr.shift_c;
964 }
965 break;
966 case 28: /* BIC Rd, Rn, operand */
967 LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
968 break;
969 case 29: /* BICS Rd, Rn, operand */
970 operand = RN(ir) & (~arm_get_shift_operand_s(ir));
971 LRD(ir) = operand;
972 if( RDn(ir) == 15 ) {
973 arm_restore_cpsr();
974 } else {
975 armr.n = operand>>31;
976 armr.z = (operand == 0);
977 armr.c = armr.shift_c;
978 }
979 break;
980 case 30: /* MVN Rd, operand */
981 LRD(ir) = ~arm_get_shift_operand(ir);
982 break;
983 case 31: /* MVNS Rd, operand */
984 operand = ~arm_get_shift_operand_s(ir);
985 LRD(ir) = operand;
986 if( RDn(ir) == 15 ) {
987 arm_restore_cpsr();
988 } else {
989 armr.n = operand>>31;
990 armr.z = (operand == 0);
991 armr.c = armr.shift_c;
992 }
993 break;
994 default:
995 UNIMP(ir);
996 }
997 }
998 break;
999 case 1: /* Load/store */
1000 operand = arm_get_address_operand(ir);
1001 switch( (ir>>20)&0x17 ) {
1002 case 0: case 16: case 18: /* STR Rd, address */
1003 arm_write_long( operand, RD(ir) );
1004 break;
1005 case 1: case 17: case 19: /* LDR Rd, address */
1006 LRD(ir) = arm_read_long(operand);
1007 break;
1008 case 2: /* STRT Rd, address */
1009 arm_write_long_user( operand, RD(ir) );
1010 break;
1011 case 3: /* LDRT Rd, address */
1012 LRD(ir) = arm_read_long_user( operand );
1013 break;
1014 case 4: case 20: case 22: /* STRB Rd, address */
1015 arm_write_byte( operand, RD(ir) );
1016 break;
1017 case 5: case 21: case 23: /* LDRB Rd, address */
1018 LRD(ir) = arm_read_byte( operand );
1019 break;
1020 case 6: /* STRBT Rd, address */
1021 arm_write_byte_user( operand, RD(ir) );
1022 break;
1023 case 7: /* LDRBT Rd, address */
1024 LRD(ir) = arm_read_byte_user( operand );
1025 break;
1026 }
1027 break;
1028 case 2: /* Load/store multiple, branch*/
1029 if( (ir & 0x02000000) == 0x02000000 ) { /* B[L] imm24 */
1030 operand = (SIGNEXT24(ir&0x00FFFFFF) << 2);
1031 if( (ir & 0x01000000) == 0x01000000 ) {
1032 armr.r[14] = pc; /* BL */
1033 }
1034 armr.r[15] = pc + 4 + operand;
1035 } else { /* Load/store multiple */
1036 UNIMP(ir);
1037 }
1038 break;
1039 case 3: /* Copro */
1040 UNIMP(ir);
1041 break;
1042 }
1043 return TRUE;
1044 }
.