filename | src/aica/armcore.c |
changeset | 35:21a4be098304 |
prev | 30:89b30313d757 |
next | 37:1d84f4c18816 |
author | nkeynes |
date | Mon Dec 26 03:54:55 2005 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Remove modules.h - move definitions into dream.h Add source string to output list (taken from module name) ARM Work in progress |
view | annotate | diff | log | raw |
1 /**
2 * $Id: armcore.c,v 1.6 2005-12-26 03:54:55 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 #include "aica/armcore.h"
21 struct arm_registers armr;
23 void arm_set_mode( int mode );
25 uint32_t arm_exceptions[][2] = {{ MODE_SVC, 0x00000000 },
26 { MODE_UND, 0x00000004 },
27 { MODE_SVC, 0x00000008 },
28 { MODE_ABT, 0x0000000C },
29 { MODE_ABT, 0x00000010 },
30 { MODE_IRQ, 0x00000018 },
31 { MODE_FIQ, 0x0000001C } };
33 #define EXC_RESET 0
34 #define EXC_UNDEFINED 1
35 #define EXC_SOFTWARE 2
36 #define EXC_PREFETCH_ABORT 3
37 #define EXC_DATA_ABORT 4
38 #define EXC_IRQ 5
39 #define EXC_FAST_IRQ 6
41 uint32_t arm_cpu_freq = ARM_BASE_RATE;
42 uint32_t arm_cpu_period = 1000 / ARM_BASE_RATE;
44 uint32_t arm_run_slice( uint32_t nanosecs )
45 {
46 uint32_t target = armr.icount + nanosecs / arm_cpu_period;
47 uint32_t start = armr.icount;
48 while( armr.icount < target ) {
49 armr.icount++;
50 if( !arm_execute_instruction() )
51 break;
52 }
54 if( target != armr.icount ) {
55 /* Halted - compute time actually executed */
56 nanosecs = (armr.icount - start) * arm_cpu_period;
57 }
58 return nanosecs;
59 }
61 void arm_save_state( FILE *f )
62 {
63 fwrite( &armr, sizeof(armr), 1, f );
64 }
66 int arm_load_state( FILE *f )
67 {
68 fread( &armr, sizeof(armr), 1, f );
69 return 0;
70 }
72 /* Exceptions */
73 void arm_reset( void )
74 {
75 /* Wipe all processor state */
76 memset( &armr, 0, sizeof(armr) );
78 armr.cpsr = MODE_SVC | CPSR_I | CPSR_F;
79 armr.r[15] = 0x00000000;
80 }
82 /**
83 * Raise an ARM exception (other than reset, which uses arm_reset().
84 * @param exception one of the EXC_* exception codes defined above.
85 */
86 void arm_raise_exception( int exception )
87 {
88 int mode = arm_exceptions[exception][0];
89 arm_set_mode( mode );
90 armr.spsr = armr.cpsr;
91 armr.r[14] = armr.r[15];
92 armr.cpsr = (armr.cpsr & (~CPSR_T)) | CPSR_I;
93 if( mode == MODE_FIQ )
94 armr.cpsr |= CPSR_F;
95 armr.r[15] = arm_exceptions[exception][1];
96 }
98 /**
99 * Restore CPSR from SPSR, effectively (under most circumstances) executing
100 * a return-from-exception.
101 */
102 void arm_restore_cpsr()
103 {
104 int spsr = armr.spsr;
105 int mode = spsr & CPSR_MODE;
107 arm_set_mode( mode );
108 armr.cpsr = spsr;
109 }
113 /**
114 * Change the current executing ARM mode to the requested mode.
115 * Saves any required registers to banks and restores those for the
116 * correct mode. (Note does not actually update CPSR at the moment).
117 */
118 void arm_set_mode( int targetMode )
119 {
120 int currentMode = armr.cpsr & CPSR_MODE;
121 if( currentMode == targetMode )
122 return;
124 switch( currentMode ) {
125 case MODE_USER:
126 case MODE_SYS:
127 armr.user_r[5] = armr.r[13];
128 armr.user_r[6] = armr.r[14];
129 break;
130 case MODE_SVC:
131 armr.svc_r[0] = armr.r[13];
132 armr.svc_r[1] = armr.r[14];
133 armr.svc_r[2] = armr.spsr;
134 break;
135 case MODE_ABT:
136 armr.abt_r[0] = armr.r[13];
137 armr.abt_r[1] = armr.r[14];
138 armr.abt_r[2] = armr.spsr;
139 break;
140 case MODE_UND:
141 armr.und_r[0] = armr.r[13];
142 armr.und_r[1] = armr.r[14];
143 armr.und_r[2] = armr.spsr;
144 break;
145 case MODE_IRQ:
146 armr.irq_r[0] = armr.r[13];
147 armr.irq_r[1] = armr.r[14];
148 armr.irq_r[2] = armr.spsr;
149 break;
150 case MODE_FIQ:
151 armr.fiq_r[0] = armr.r[8];
152 armr.fiq_r[1] = armr.r[9];
153 armr.fiq_r[2] = armr.r[10];
154 armr.fiq_r[3] = armr.r[11];
155 armr.fiq_r[4] = armr.r[12];
156 armr.fiq_r[5] = armr.r[13];
157 armr.fiq_r[6] = armr.r[14];
158 armr.fiq_r[7] = armr.spsr;
159 armr.r[8] = armr.user_r[0];
160 armr.r[9] = armr.user_r[1];
161 armr.r[10] = armr.user_r[2];
162 armr.r[11] = armr.user_r[3];
163 armr.r[12] = armr.user_r[4];
164 break;
165 }
167 switch( targetMode ) {
168 case MODE_USER:
169 case MODE_SYS:
170 armr.r[13] = armr.user_r[5];
171 armr.r[14] = armr.user_r[6];
172 break;
173 case MODE_SVC:
174 armr.r[13] = armr.svc_r[0];
175 armr.r[14] = armr.svc_r[1];
176 armr.spsr = armr.svc_r[2];
177 break;
178 case MODE_ABT:
179 armr.r[13] = armr.abt_r[0];
180 armr.r[14] = armr.abt_r[1];
181 armr.spsr = armr.abt_r[2];
182 break;
183 case MODE_UND:
184 armr.r[13] = armr.und_r[0];
185 armr.r[14] = armr.und_r[1];
186 armr.spsr = armr.und_r[2];
187 break;
188 case MODE_IRQ:
189 armr.r[13] = armr.irq_r[0];
190 armr.r[14] = armr.irq_r[1];
191 armr.spsr = armr.irq_r[2];
192 break;
193 case MODE_FIQ:
194 armr.user_r[0] = armr.r[8];
195 armr.user_r[1] = armr.r[9];
196 armr.user_r[2] = armr.r[10];
197 armr.user_r[3] = armr.r[11];
198 armr.user_r[4] = armr.r[12];
199 armr.r[8] = armr.fiq_r[0];
200 armr.r[9] = armr.fiq_r[1];
201 armr.r[10] = armr.fiq_r[2];
202 armr.r[11] = armr.fiq_r[3];
203 armr.r[12] = armr.fiq_r[4];
204 armr.r[13] = armr.fiq_r[5];
205 armr.r[14] = armr.fiq_r[6];
206 armr.spsr = armr.fiq_r[7];
207 break;
208 }
209 }
211 /* Page references are as per ARM DDI 0100E (June 2000) */
213 #define MEM_READ_BYTE( addr ) arm_read_byte(addr)
214 #define MEM_READ_WORD( addr ) arm_read_word(addr)
215 #define MEM_READ_LONG( addr ) arm_read_long(addr)
216 #define MEM_WRITE_BYTE( addr, val ) arm_write_byte(addr, val)
217 #define MEM_WRITE_WORD( addr, val ) arm_write_word(addr, val)
218 #define MEM_WRITE_LONG( addr, val ) arm_write_long(addr, val)
221 #define IS_NOTBORROW( result, op1, op2 ) (op2 > op1 ? 0 : 1)
222 #define IS_CARRY( result, op1, op2 ) (result < op1 ? 1 : 0)
223 #define IS_SUBOVERFLOW( result, op1, op2 ) (((op1^op2) & (result^op1)) >> 31)
224 #define IS_ADDOVERFLOW( result, op1, op2 ) (((op1&op2) & (result^op1)) >> 31)
226 #define PC armr.r[15]
228 /* Instruction fields */
229 #define COND(ir) (ir>>28)
230 #define GRP(ir) ((ir>>26)&0x03)
231 #define OPCODE(ir) ((ir>>20)&0x1F)
232 #define IFLAG(ir) (ir&0x02000000)
233 #define SFLAG(ir) (ir&0x00100000)
234 #define PFLAG(ir) (ir&0x01000000)
235 #define UFLAG(ir) (ir&0x00800000)
236 #define BFLAG(ir) (ir&0x00400000)
237 #define WFLAG(ir) (IR&0x00200000)
238 #define LFLAG(ir) SFLAG(ir)
239 #define RN(ir) (armr.r[((ir>>16)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
240 #define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
241 #define RDn(ir) ((ir>>12)&0x0F)
242 #define RS(ir) (armr.r[((ir>>8)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
243 #define RM(ir) (armr.r[(ir&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
244 #define LRN(ir) armr.r[((ir>>16)&0x0F)]
245 #define LRD(ir) armr.r[((ir>>12)&0x0F)]
246 #define LRS(ir) armr.r[((ir>>8)&0x0F)]
247 #define LRM(ir) armr.r[(ir&0x0F)]
249 #define IMM8(ir) (ir&0xFF)
250 #define IMM12(ir) (ir&0xFFF)
251 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
252 #define IMMROT(ir) ((ir>>7)&0x1E)
253 #define SHIFT(ir) ((ir>>4)&0x07)
254 #define DISP24(ir) ((ir&0x00FFFFFF))
255 #define UNDEF(ir) do{ ERROR( "Raising exception on undefined instruction at %08x, opcode = %04x", PC, ir ); return TRUE; } while(0)
256 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC, ir ); return FALSE; }while(0)
258 static uint32_t arm_get_shift_operand( uint32_t ir )
259 {
260 uint32_t operand, tmp;
261 if( IFLAG(ir) == 0 ) {
262 operand = RM(ir);
263 switch(SHIFT(ir)) {
264 case 0: /* (Rm << imm) */
265 operand = operand << SHIFTIMM(ir);
266 break;
267 case 1: /* (Rm << Rs) */
268 tmp = RS(ir)&0xFF;
269 if( tmp > 31 ) operand = 0;
270 else operand = operand << tmp;
271 break;
272 case 2: /* (Rm >> imm) */
273 operand = operand >> SHIFTIMM(ir);
274 break;
275 case 3: /* (Rm >> Rs) */
276 tmp = RS(ir) & 0xFF;
277 if( tmp > 31 ) operand = 0;
278 else operand = operand >> ir;
279 break;
280 case 4: /* (Rm >>> imm) */
281 tmp = SHIFTIMM(ir);
282 if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
283 else operand = ((int32_t)operand) >> tmp;
284 break;
285 case 5: /* (Rm >>> Rs) */
286 tmp = RS(ir) & 0xFF;
287 if( tmp > 31 ) operand = ((int32_t)operand) >> 31;
288 else operand = ((int32_t)operand) >> tmp;
289 break;
290 case 6:
291 tmp = SHIFTIMM(ir);
292 if( tmp == 0 ) /* RRX aka rotate with carry */
293 operand = (operand >> 1) | (armr.c<<31);
294 else
295 operand = ROTATE_RIGHT_LONG(operand,tmp);
296 break;
297 case 7:
298 tmp = RS(ir)&0x1F;
299 operand = ROTATE_RIGHT_LONG(operand,tmp);
300 break;
301 }
302 } else {
303 operand = IMM8(ir);
304 tmp = IMMROT(ir);
305 operand = ROTATE_RIGHT_LONG(operand, tmp);
306 }
307 return operand;
308 }
310 /**
311 * Compute the "shift operand" of the instruction for the data processing
312 * instructions. This variant also sets armr.shift_c (carry result for shifter)
313 * Reason for the variants is that most cases don't actually need the shift_c.
314 */
315 static uint32_t arm_get_shift_operand_s( uint32_t ir )
316 {
317 uint32_t operand, tmp;
318 if( IFLAG(ir) == 0 ) {
319 operand = RM(ir);
320 switch(SHIFT(ir)) {
321 case 0: /* (Rm << imm) */
322 tmp = SHIFTIMM(ir);
323 if( tmp == 0 ) { /* Rm */
324 armr.shift_c = armr.c;
325 } else { /* Rm << imm */
326 armr.shift_c = (operand >> (32-tmp)) & 0x01;
327 operand = operand << tmp;
328 }
329 break;
330 case 1: /* (Rm << Rs) */
331 tmp = RS(ir)&0xFF;
332 if( tmp == 0 ) {
333 armr.shift_c = armr.c;
334 } else {
335 if( tmp <= 32 )
336 armr.shift_c = (operand >> (32-tmp)) & 0x01;
337 else armr.shift_c = 0;
338 if( tmp < 32 )
339 operand = operand << tmp;
340 else operand = 0;
341 }
342 break;
343 case 2: /* (Rm >> imm) */
344 tmp = SHIFTIMM(ir);
345 if( tmp == 0 ) {
346 armr.shift_c = operand >> 31;
347 operand = 0;
348 } else {
349 armr.shift_c = (operand >> (tmp-1)) & 0x01;
350 operand = RM(ir) >> tmp;
351 }
352 break;
353 case 3: /* (Rm >> Rs) */
354 tmp = RS(ir) & 0xFF;
355 if( tmp == 0 ) {
356 armr.shift_c = armr.c;
357 } else {
358 if( tmp <= 32 )
359 armr.shift_c = (operand >> (tmp-1))&0x01;
360 else armr.shift_c = 0;
361 if( tmp < 32 )
362 operand = operand >> tmp;
363 else operand = 0;
364 }
365 break;
366 case 4: /* (Rm >>> imm) */
367 tmp = SHIFTIMM(ir);
368 if( tmp == 0 ) {
369 armr.shift_c = operand >> 31;
370 operand = -armr.shift_c;
371 } else {
372 armr.shift_c = (operand >> (tmp-1)) & 0x01;
373 operand = ((int32_t)operand) >> tmp;
374 }
375 break;
376 case 5: /* (Rm >>> Rs) */
377 tmp = RS(ir) & 0xFF;
378 if( tmp == 0 ) {
379 armr.shift_c = armr.c;
380 } else {
381 if( tmp < 32 ) {
382 armr.shift_c = (operand >> (tmp-1))&0x01;
383 operand = ((int32_t)operand) >> tmp;
384 } else {
385 armr.shift_c = operand >> 31;
386 operand = ((int32_t)operand) >> 31;
387 }
388 }
389 break;
390 case 6:
391 tmp = SHIFTIMM(ir);
392 if( tmp == 0 ) { /* RRX aka rotate with carry */
393 armr.shift_c = operand&0x01;
394 operand = (operand >> 1) | (armr.c<<31);
395 } else {
396 armr.shift_c = operand>>(tmp-1);
397 operand = ROTATE_RIGHT_LONG(operand,tmp);
398 }
399 break;
400 case 7:
401 tmp = RS(ir)&0xFF;
402 if( tmp == 0 ) {
403 armr.shift_c = armr.c;
404 } else {
405 tmp &= 0x1F;
406 if( tmp == 0 ) {
407 armr.shift_c = operand>>31;
408 } else {
409 armr.shift_c = (operand>>(tmp-1))&0x1;
410 operand = ROTATE_RIGHT_LONG(operand,tmp);
411 }
412 }
413 break;
414 }
415 } else {
416 operand = IMM8(ir);
417 tmp = IMMROT(ir);
418 if( tmp == 0 ) {
419 armr.shift_c = armr.c;
420 } else {
421 operand = ROTATE_RIGHT_LONG(operand, tmp);
422 armr.shift_c = operand>>31;
423 }
424 }
425 return operand;
426 }
428 /**
429 * Another variant of the shifter code for index-based memory addressing.
430 * Distinguished by the fact that it doesn't support register shifts, and
431 * ignores the I flag (WTF do the load/store instructions use the I flag to
432 * mean the _exact opposite_ of what it means for the data processing
433 * instructions ???)
434 */
435 static uint32_t arm_get_address_index( uint32_t ir )
436 {
437 uint32_t operand = RM(ir);
438 uint32_t tmp;
440 switch(SHIFT(ir)) {
441 case 0: /* (Rm << imm) */
442 operand = operand << SHIFTIMM(ir);
443 break;
444 case 2: /* (Rm >> imm) */
445 operand = operand >> SHIFTIMM(ir);
446 break;
447 case 4: /* (Rm >>> imm) */
448 tmp = SHIFTIMM(ir);
449 if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
450 else operand = ((int32_t)operand) >> tmp;
451 break;
452 case 6:
453 tmp = SHIFTIMM(ir);
454 if( tmp == 0 ) /* RRX aka rotate with carry */
455 operand = (operand >> 1) | (armr.c<<31);
456 else
457 operand = ROTATE_RIGHT_LONG(operand,tmp);
458 break;
459 default: UNIMP(ir);
460 }
461 return operand;
462 }
464 static uint32_t arm_get_address_operand( uint32_t ir )
465 {
466 uint32_t addr;
468 /* I P U . W */
469 switch( (ir>>21)&0x1D ) {
470 case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
471 case 1:
472 addr = RN(ir);
473 LRN(ir) = addr - IMM12(ir);
474 break;
475 case 4: /* Rn += imm offsett (post-indexed) [5.2.8 A5-28] */
476 case 5:
477 addr = RN(ir);
478 LRN(ir) = addr + IMM12(ir);
479 break;
480 case 8: /* Rn - imm offset [5.2.2 A5-20] */
481 addr = RN(ir) - IMM12(ir);
482 break;
483 case 9: /* Rn -= imm offset (pre-indexed) [5.2.5 A5-24] */
484 addr = RN(ir) - IMM12(ir);
485 LRN(ir) = addr;
486 break;
487 case 12: /* Rn + imm offset [5.2.2 A5-20] */
488 addr = RN(ir) + IMM12(ir);
489 break;
490 case 13: /* Rn += imm offset [5.2.5 A5-24 ] */
491 addr = RN(ir) + IMM12(ir);
492 LRN(ir) = addr;
493 break;
494 case 16: /* Rn -= Rm (post-indexed) [5.2.10 A5-32 ] */
495 case 17:
496 addr = RN(ir);
497 LRN(ir) = addr - arm_get_address_index(ir);
498 break;
499 case 20: /* Rn += Rm (post-indexed) [5.2.10 A5-32 ] */
500 case 21:
501 addr = RN(ir);
502 LRN(ir) = addr - arm_get_address_index(ir);
503 break;
504 case 24: /* Rn - Rm [5.2.4 A5-23] */
505 addr = RN(ir) - arm_get_address_index(ir);
506 break;
507 case 25: /* RN -= Rm (pre-indexed) [5.2.7 A5-26] */
508 addr = RN(ir) - arm_get_address_index(ir);
509 LRN(ir) = addr;
510 break;
511 case 28: /* Rn + Rm [5.2.4 A5-23] */
512 addr = RN(ir) + arm_get_address_index(ir);
513 break;
514 case 29: /* RN += Rm (pre-indexed) [5.2.7 A5-26] */
515 addr = RN(ir) + arm_get_address_index(ir);
516 LRN(ir) = addr;
517 break;
518 default:
519 UNIMP(ir); /* Unreachable */
520 }
521 return addr;
522 }
524 gboolean arm_execute_instruction( void )
525 {
526 uint32_t pc = PC;
527 uint32_t ir = MEM_READ_LONG(pc);
528 uint32_t operand, operand2, tmp, cond;
530 pc += 4;
531 PC = pc;
533 switch( COND(ir) ) {
534 case 0: /* EQ */
535 cond = armr.z;
536 break;
537 case 1: /* NE */
538 cond = !armr.z;
539 break;
540 case 2: /* CS/HS */
541 cond = armr.c;
542 break;
543 case 3: /* CC/LO */
544 cond = !armr.c;
545 break;
546 case 4: /* MI */
547 cond = armr.n;
548 break;
549 case 5: /* PL */
550 cond = !armr.n;
551 break;
552 case 6: /* VS */
553 cond = armr.v;
554 break;
555 case 7: /* VC */
556 cond = !armr.v;
557 break;
558 case 8: /* HI */
559 cond = armr.c && !armr.z;
560 break;
561 case 9: /* LS */
562 cond = (!armr.c) || armr.z;
563 break;
564 case 10: /* GE */
565 cond = (armr.n == armr.v);
566 break;
567 case 11: /* LT */
568 cond = (armr.n != armr.v);
569 break;
570 case 12: /* GT */
571 cond = (!armr.z) && (armr.n == armr.v);
572 break;
573 case 13: /* LE */
574 cond = armr.z || (armr.n != armr.v);
575 break;
576 case 14: /* AL */
577 cond = 1;
578 break;
579 case 15: /* (NV) */
580 cond = 0;
581 UNDEF(ir);
582 }
584 switch( GRP(ir) ) {
585 case 0:
586 if( (ir & 0x0D900000) == 0x01000000 ) {
587 /* Instructions that aren't actual data processing */
588 switch( ir & 0x0FF000F0 ) {
589 case 0x01200010: /* BX */
590 break;
591 case 0x01000000: /* MRS Rd, CPSR */
592 break;
593 case 0x01400000: /* MRS Rd, SPSR */
594 break;
595 case 0x01200000: /* MSR CPSR, Rd */
596 break;
597 case 0x01600000: /* MSR SPSR, Rd */
598 break;
599 case 0x03200000: /* MSR CPSR, imm */
600 break;
601 case 0x03600000: /* MSR SPSR, imm */
602 break;
603 default:
604 UNIMP(ir);
605 }
606 } else if( (ir & 0x0E000090) == 0x00000090 ) {
607 /* Neither are these */
608 switch( (ir>>5)&0x03 ) {
609 case 0:
610 /* Arithmetic extension area */
611 switch(OPCODE(ir)) {
612 case 0: /* MUL */
613 break;
614 case 1: /* MULS */
615 break;
616 case 2: /* MLA */
617 break;
618 case 3: /* MLAS */
619 break;
620 case 8: /* UMULL */
621 break;
622 case 9: /* UMULLS */
623 break;
624 case 10: /* UMLAL */
625 break;
626 case 11: /* UMLALS */
627 break;
628 case 12: /* SMULL */
629 break;
630 case 13: /* SMULLS */
631 break;
632 case 14: /* SMLAL */
633 break;
634 case 15: /* SMLALS */
635 break;
636 case 16: /* SWP */
637 break;
638 case 20: /* SWPB */
639 break;
640 default:
641 UNIMP(ir);
642 }
643 break;
644 case 1:
645 if( LFLAG(ir) ) {
646 /* LDRH */
647 } else {
648 /* STRH */
649 }
650 break;
651 case 2:
652 if( LFLAG(ir) ) {
653 /* LDRSB */
654 } else {
655 UNIMP(ir);
656 }
657 break;
658 case 3:
659 if( LFLAG(ir) ) {
660 /* LDRSH */
661 } else {
662 UNIMP(ir);
663 }
664 break;
665 }
666 } else {
667 /* Data processing */
669 switch(OPCODE(ir)) {
670 case 0: /* AND Rd, Rn, operand */
671 LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
672 break;
673 case 1: /* ANDS Rd, Rn, operand */
674 operand = arm_get_shift_operand_s(ir) & RN(ir);
675 LRD(ir) = operand;
676 if( RDn(ir) == 15 ) {
677 arm_restore_cpsr();
678 } else {
679 armr.n = operand>>31;
680 armr.z = (operand == 0);
681 armr.c = armr.shift_c;
682 }
683 break;
684 case 2: /* EOR Rd, Rn, operand */
685 LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
686 break;
687 case 3: /* EORS Rd, Rn, operand */
688 operand = arm_get_shift_operand_s(ir) ^ RN(ir);
689 LRD(ir) = operand;
690 if( RDn(ir) == 15 ) {
691 arm_restore_cpsr();
692 } else {
693 armr.n = operand>>31;
694 armr.z = (operand == 0);
695 armr.c = armr.shift_c;
696 }
697 break;
698 case 4: /* SUB Rd, Rn, operand */
699 LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
700 break;
701 case 5: /* SUBS Rd, Rn, operand */
702 operand = RN(ir);
703 operand2 = arm_get_shift_operand(ir);
704 tmp = operand - operand2;
705 LRD(ir) = tmp;
706 if( RDn(ir) == 15 ) {
707 arm_restore_cpsr();
708 } else {
709 armr.n = tmp>>31;
710 armr.z = (tmp == 0);
711 armr.c = IS_NOTBORROW(tmp,operand,operand2);
712 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
713 }
714 break;
715 case 6: /* RSB Rd, operand, Rn */
716 LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
717 break;
718 case 7: /* RSBS Rd, operand, Rn */
719 operand = arm_get_shift_operand(ir);
720 operand2 = RN(ir);
721 tmp = operand - operand2;
722 LRD(ir) = tmp;
723 if( RDn(ir) == 15 ) {
724 arm_restore_cpsr();
725 } else {
726 armr.n = tmp>>31;
727 armr.z = (tmp == 0);
728 armr.c = IS_NOTBORROW(tmp,operand,operand2);
729 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
730 }
731 break;
732 case 8: /* ADD Rd, Rn, operand */
733 LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
734 break;
735 case 9: /* ADDS Rd, Rn, operand */
736 operand = arm_get_shift_operand(ir);
737 operand2 = RN(ir);
738 tmp = operand + operand2;
739 LRD(ir) = tmp;
740 if( RDn(ir) == 15 ) {
741 arm_restore_cpsr();
742 } else {
743 armr.n = tmp>>31;
744 armr.z = (tmp == 0);
745 armr.c = IS_CARRY(tmp,operand,operand2);
746 armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
747 }
748 break;
749 case 10: /* ADC */
750 case 11: /* ADCS */
751 case 12: /* SBC */
752 case 13: /* SBCS */
753 case 14: /* RSC */
754 case 15: /* RSCS */
755 break;
756 case 17: /* TST Rn, operand */
757 operand = arm_get_shift_operand_s(ir) & RN(ir);
758 armr.n = operand>>31;
759 armr.z = (operand == 0);
760 armr.c = armr.shift_c;
761 break;
762 case 19: /* TEQ Rn, operand */
763 operand = arm_get_shift_operand_s(ir) ^ RN(ir);
764 armr.n = operand>>31;
765 armr.z = (operand == 0);
766 armr.c = armr.shift_c;
767 break;
768 case 21: /* CMP Rn, operand */
769 operand = RN(ir);
770 operand2 = arm_get_shift_operand(ir);
771 tmp = operand - operand2;
772 armr.n = tmp>>31;
773 armr.z = (tmp == 0);
774 armr.c = IS_NOTBORROW(tmp,operand,operand2);
775 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
776 break;
777 case 23: /* CMN Rn, operand */
778 operand = RN(ir);
779 operand2 = arm_get_shift_operand(ir);
780 tmp = operand + operand2;
781 armr.n = tmp>>31;
782 armr.z = (tmp == 0);
783 armr.c = IS_CARRY(tmp,operand,operand2);
784 armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
785 break;
786 case 24: /* ORR Rd, Rn, operand */
787 LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
788 break;
789 case 25: /* ORRS Rd, Rn, operand */
790 operand = arm_get_shift_operand_s(ir) | RN(ir);
791 LRD(ir) = operand;
792 if( RDn(ir) == 15 ) {
793 arm_restore_cpsr();
794 } else {
795 armr.n = operand>>31;
796 armr.z = (operand == 0);
797 armr.c = armr.shift_c;
798 }
799 break;
800 case 26: /* MOV Rd, operand */
801 LRD(ir) = arm_get_shift_operand(ir);
802 break;
803 case 27: /* MOVS Rd, operand */
804 operand = arm_get_shift_operand_s(ir);
805 LRD(ir) = operand;
806 if( RDn(ir) == 15 ) {
807 arm_restore_cpsr();
808 } else {
809 armr.n = operand>>31;
810 armr.z = (operand == 0);
811 armr.c = armr.shift_c;
812 }
813 break;
814 case 28: /* BIC Rd, Rn, operand */
815 LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
816 break;
817 case 29: /* BICS Rd, Rn, operand */
818 operand = RN(ir) & (~arm_get_shift_operand_s(ir));
819 LRD(ir) = operand;
820 if( RDn(ir) == 15 ) {
821 arm_restore_cpsr();
822 } else {
823 armr.n = operand>>31;
824 armr.z = (operand == 0);
825 armr.c = armr.shift_c;
826 }
827 break;
828 case 30: /* MVN Rd, operand */
829 LRD(ir) = ~arm_get_shift_operand(ir);
830 break;
831 case 31: /* MVNS Rd, operand */
832 operand = ~arm_get_shift_operand_s(ir);
833 LRD(ir) = operand;
834 if( RDn(ir) == 15 ) {
835 arm_restore_cpsr();
836 } else {
837 armr.n = operand>>31;
838 armr.z = (operand == 0);
839 armr.c = armr.shift_c;
840 }
841 break;
842 default:
843 UNIMP(ir);
844 }
845 }
846 break;
847 case 1: /* Load/store */
848 break;
849 case 2: /* Load/store multiple, branch*/
850 break;
851 case 3: /* Copro */
852 break;
853 }
854 return TRUE;
855 }
.