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