filename | src/aica/armcore.c |
changeset | 30:89b30313d757 |
prev | 11:0a82ef380c45 |
next | 35:21a4be098304 |
author | nkeynes |
date | Sun Dec 25 05:57:00 2005 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Change timeslice to nanoseconds (was microseconds) Generize single step (now steps through active CPU) Add lots of header blocks |
view | annotate | diff | log | raw |
1 /**
2 * $Id: armcore.c,v 1.5 2005-12-25 05:57:00 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 /* NB: The arm has a different memory map, but for the meantime... */
24 /* Page references are as per ARM DDI 0100E (June 2000) */
26 #define MEM_READ_BYTE( addr ) arm_read_byte(addr)
27 #define MEM_READ_WORD( addr ) arm_read_word(addr)
28 #define MEM_READ_LONG( addr ) arm_read_long(addr)
29 #define MEM_WRITE_BYTE( addr, val ) arm_write_byte(addr, val)
30 #define MEM_WRITE_WORD( addr, val ) arm_write_word(addr, val)
31 #define MEM_WRITE_LONG( addr, val ) arm_write_long(addr, val)
34 #define IS_NOTBORROW( result, op1, op2 ) (op2 > op1 ? 0 : 1)
35 #define IS_CARRY( result, op1, op2 ) (result < op1 ? 1 : 0)
36 #define IS_SUBOVERFLOW( result, op1, op2 ) (((op1^op2) & (result^op1)) >> 31)
37 #define IS_ADDOVERFLOW( result, op1, op2 ) (((op1&op2) & (result^op1)) >> 31)
39 #define PC armr.r[15]
41 /* Instruction fields */
42 #define COND(ir) (ir>>28)
43 #define GRP(ir) ((ir>>26)&0x03)
44 #define OPCODE(ir) ((ir>>20)&0x1F)
45 #define IFLAG(ir) (ir&0x02000000)
46 #define SFLAG(ir) (ir&0x00100000)
47 #define PFLAG(ir) (ir&0x01000000)
48 #define UFLAG(ir) (ir&0x00800000)
49 #define BFLAG(ir) (ir&0x00400000)
50 #define WFLAG(ir) (IR&0x00200000)
51 #define LFLAG(ir) SFLAG(ir)
52 #define RN(ir) (armr.r[((ir>>16)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
53 #define RD(ir) (armr.r[((ir>>12)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
54 #define RDn(ir) ((ir>>12)&0x0F)
55 #define RS(ir) (armr.r[((ir>>8)&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
56 #define RM(ir) (armr.r[(ir&0x0F)] + (((ir>>16)&0x0F) == 0x0F ? 4 : 0))
57 #define LRN(ir) armr.r[((ir>>16)&0x0F)]
58 #define LRD(ir) armr.r[((ir>>12)&0x0F)]
59 #define LRS(ir) armr.r[((ir>>8)&0x0F)]
60 #define LRM(ir) armr.r[(ir&0x0F)]
62 #define IMM8(ir) (ir&0xFF)
63 #define IMM12(ir) (ir&0xFFF)
64 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
65 #define IMMROT(ir) ((ir>>7)&0x1E)
66 #define SHIFT(ir) ((ir>>4)&0x07)
67 #define DISP24(ir) ((ir&0x00FFFFFF))
68 #define UNDEF(ir) do{ ERROR( "Raising exception on undefined instruction at %08x, opcode = %04x", PC, ir ); return TRUE; } while(0)
69 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", PC, ir ); return FALSE; }while(0)
71 void arm_restore_cpsr()
72 {
74 }
76 static uint32_t arm_get_shift_operand( uint32_t ir )
77 {
78 uint32_t operand, tmp;
79 if( IFLAG(ir) == 0 ) {
80 operand = RM(ir);
81 switch(SHIFT(ir)) {
82 case 0: /* (Rm << imm) */
83 operand = operand << SHIFTIMM(ir);
84 break;
85 case 1: /* (Rm << Rs) */
86 tmp = RS(ir)&0xFF;
87 if( tmp > 31 ) operand = 0;
88 else operand = operand << tmp;
89 break;
90 case 2: /* (Rm >> imm) */
91 operand = operand >> SHIFTIMM(ir);
92 break;
93 case 3: /* (Rm >> Rs) */
94 tmp = RS(ir) & 0xFF;
95 if( tmp > 31 ) operand = 0;
96 else operand = operand >> ir;
97 break;
98 case 4: /* (Rm >>> imm) */
99 tmp = SHIFTIMM(ir);
100 if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
101 else operand = ((int32_t)operand) >> tmp;
102 break;
103 case 5: /* (Rm >>> Rs) */
104 tmp = RS(ir) & 0xFF;
105 if( tmp > 31 ) operand = ((int32_t)operand) >> 31;
106 else operand = ((int32_t)operand) >> tmp;
107 break;
108 case 6:
109 tmp = SHIFTIMM(ir);
110 if( tmp == 0 ) /* RRX aka rotate with carry */
111 operand = (operand >> 1) | (armr.c<<31);
112 else
113 operand = ROTATE_RIGHT_LONG(operand,tmp);
114 break;
115 case 7:
116 tmp = RS(ir)&0x1F;
117 operand = ROTATE_RIGHT_LONG(operand,tmp);
118 break;
119 }
120 } else {
121 operand = IMM8(ir);
122 tmp = IMMROT(ir);
123 operand = ROTATE_RIGHT_LONG(operand, tmp);
124 }
125 return operand;
126 }
128 /**
129 * Compute the "shift operand" of the instruction for the data processing
130 * instructions. This variant also sets armr.shift_c (carry result for shifter)
131 * Reason for the variants is that most cases don't actually need the shift_c.
132 */
133 static uint32_t arm_get_shift_operand_s( uint32_t ir )
134 {
135 uint32_t operand, tmp;
136 if( IFLAG(ir) == 0 ) {
137 operand = RM(ir);
138 switch(SHIFT(ir)) {
139 case 0: /* (Rm << imm) */
140 tmp = SHIFTIMM(ir);
141 if( tmp == 0 ) { /* Rm */
142 armr.shift_c = armr.c;
143 } else { /* Rm << imm */
144 armr.shift_c = (operand >> (32-tmp)) & 0x01;
145 operand = operand << tmp;
146 }
147 break;
148 case 1: /* (Rm << Rs) */
149 tmp = RS(ir)&0xFF;
150 if( tmp == 0 ) {
151 armr.shift_c = armr.c;
152 } else {
153 if( tmp <= 32 )
154 armr.shift_c = (operand >> (32-tmp)) & 0x01;
155 else armr.shift_c = 0;
156 if( tmp < 32 )
157 operand = operand << tmp;
158 else operand = 0;
159 }
160 break;
161 case 2: /* (Rm >> imm) */
162 tmp = SHIFTIMM(ir);
163 if( tmp == 0 ) {
164 armr.shift_c = operand >> 31;
165 operand = 0;
166 } else {
167 armr.shift_c = (operand >> (tmp-1)) & 0x01;
168 operand = RM(ir) >> tmp;
169 }
170 break;
171 case 3: /* (Rm >> Rs) */
172 tmp = RS(ir) & 0xFF;
173 if( tmp == 0 ) {
174 armr.shift_c = armr.c;
175 } else {
176 if( tmp <= 32 )
177 armr.shift_c = (operand >> (tmp-1))&0x01;
178 else armr.shift_c = 0;
179 if( tmp < 32 )
180 operand = operand >> tmp;
181 else operand = 0;
182 }
183 break;
184 case 4: /* (Rm >>> imm) */
185 tmp = SHIFTIMM(ir);
186 if( tmp == 0 ) {
187 armr.shift_c = operand >> 31;
188 operand = -armr.shift_c;
189 } else {
190 armr.shift_c = (operand >> (tmp-1)) & 0x01;
191 operand = ((int32_t)operand) >> tmp;
192 }
193 break;
194 case 5: /* (Rm >>> Rs) */
195 tmp = RS(ir) & 0xFF;
196 if( tmp == 0 ) {
197 armr.shift_c = armr.c;
198 } else {
199 if( tmp < 32 ) {
200 armr.shift_c = (operand >> (tmp-1))&0x01;
201 operand = ((int32_t)operand) >> tmp;
202 } else {
203 armr.shift_c = operand >> 31;
204 operand = ((int32_t)operand) >> 31;
205 }
206 }
207 break;
208 case 6:
209 tmp = SHIFTIMM(ir);
210 if( tmp == 0 ) { /* RRX aka rotate with carry */
211 armr.shift_c = operand&0x01;
212 operand = (operand >> 1) | (armr.c<<31);
213 } else {
214 armr.shift_c = operand>>(tmp-1);
215 operand = ROTATE_RIGHT_LONG(operand,tmp);
216 }
217 break;
218 case 7:
219 tmp = RS(ir)&0xFF;
220 if( tmp == 0 ) {
221 armr.shift_c = armr.c;
222 } else {
223 tmp &= 0x1F;
224 if( tmp == 0 ) {
225 armr.shift_c = operand>>31;
226 } else {
227 armr.shift_c = (operand>>(tmp-1))&0x1;
228 operand = ROTATE_RIGHT_LONG(operand,tmp);
229 }
230 }
231 break;
232 }
233 } else {
234 operand = IMM8(ir);
235 tmp = IMMROT(ir);
236 if( tmp == 0 ) {
237 armr.shift_c = armr.c;
238 } else {
239 operand = ROTATE_RIGHT_LONG(operand, tmp);
240 armr.shift_c = operand>>31;
241 }
242 }
243 return operand;
244 }
246 /**
247 * Another variant of the shifter code for index-based memory addressing.
248 * Distinguished by the fact that it doesn't support register shifts, and
249 * ignores the I flag (WTF do the load/store instructions use the I flag to
250 * mean the _exact opposite_ of what it means for the data processing
251 * instructions ???)
252 */
253 static uint32_t arm_get_address_index( uint32_t ir )
254 {
255 uint32_t operand = RM(ir);
256 uint32_t tmp;
258 switch(SHIFT(ir)) {
259 case 0: /* (Rm << imm) */
260 operand = operand << SHIFTIMM(ir);
261 break;
262 case 2: /* (Rm >> imm) */
263 operand = operand >> SHIFTIMM(ir);
264 break;
265 case 4: /* (Rm >>> imm) */
266 tmp = SHIFTIMM(ir);
267 if( tmp == 0 ) operand = ((int32_t)operand) >> 31;
268 else operand = ((int32_t)operand) >> tmp;
269 break;
270 case 6:
271 tmp = SHIFTIMM(ir);
272 if( tmp == 0 ) /* RRX aka rotate with carry */
273 operand = (operand >> 1) | (armr.c<<31);
274 else
275 operand = ROTATE_RIGHT_LONG(operand,tmp);
276 break;
277 default: UNIMP(ir);
278 }
279 return operand;
280 }
282 static uint32_t arm_get_address_operand( uint32_t ir )
283 {
284 uint32_t addr;
286 /* I P U . W */
287 switch( (ir>>21)&0x1D ) {
288 case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
289 case 1:
290 addr = RN(ir);
291 LRN(ir) = addr - IMM12(ir);
292 break;
293 case 4: /* Rn += imm offsett (post-indexed) [5.2.8 A5-28] */
294 case 5:
295 addr = RN(ir);
296 LRN(ir) = addr + IMM12(ir);
297 break;
298 case 8: /* Rn - imm offset [5.2.2 A5-20] */
299 addr = RN(ir) - IMM12(ir);
300 break;
301 case 9: /* Rn -= imm offset (pre-indexed) [5.2.5 A5-24] */
302 addr = RN(ir) - IMM12(ir);
303 LRN(ir) = addr;
304 break;
305 case 12: /* Rn + imm offset [5.2.2 A5-20] */
306 addr = RN(ir) + IMM12(ir);
307 break;
308 case 13: /* Rn += imm offset [5.2.5 A5-24 ] */
309 addr = RN(ir) + IMM12(ir);
310 LRN(ir) = addr;
311 break;
312 case 16: /* Rn -= Rm (post-indexed) [5.2.10 A5-32 ] */
313 case 17:
314 addr = RN(ir);
315 LRN(ir) = addr - arm_get_address_index(ir);
316 break;
317 case 20: /* Rn += Rm (post-indexed) [5.2.10 A5-32 ] */
318 case 21:
319 addr = RN(ir);
320 LRN(ir) = addr - arm_get_address_index(ir);
321 break;
322 case 24: /* Rn - Rm [5.2.4 A5-23] */
323 addr = RN(ir) - arm_get_address_index(ir);
324 break;
325 case 25: /* RN -= Rm (pre-indexed) [5.2.7 A5-26] */
326 addr = RN(ir) - arm_get_address_index(ir);
327 LRN(ir) = addr;
328 break;
329 case 28: /* Rn + Rm [5.2.4 A5-23] */
330 addr = RN(ir) + arm_get_address_index(ir);
331 break;
332 case 29: /* RN += Rm (pre-indexed) [5.2.7 A5-26] */
333 addr = RN(ir) + arm_get_address_index(ir);
334 LRN(ir) = addr;
335 break;
336 default:
337 UNIMP(ir); /* Unreachable */
338 }
339 return addr;
340 }
342 gboolean arm_execute_instruction( void )
343 {
344 uint32_t pc = PC;
345 uint32_t ir = MEM_READ_LONG(pc);
346 uint32_t operand, operand2, tmp, cond;
348 pc += 4;
349 PC = pc;
351 switch( COND(ir) ) {
352 case 0: /* EQ */
353 cond = armr.z;
354 break;
355 case 1: /* NE */
356 cond = !armr.z;
357 break;
358 case 2: /* CS/HS */
359 cond = armr.c;
360 break;
361 case 3: /* CC/LO */
362 cond = !armr.c;
363 break;
364 case 4: /* MI */
365 cond = armr.n;
366 break;
367 case 5: /* PL */
368 cond = !armr.n;
369 break;
370 case 6: /* VS */
371 cond = armr.v;
372 break;
373 case 7: /* VC */
374 cond = !armr.v;
375 break;
376 case 8: /* HI */
377 cond = armr.c && !armr.z;
378 break;
379 case 9: /* LS */
380 cond = (!armr.c) || armr.z;
381 break;
382 case 10: /* GE */
383 cond = (armr.n == armr.v);
384 break;
385 case 11: /* LT */
386 cond = (armr.n != armr.v);
387 break;
388 case 12: /* GT */
389 cond = (!armr.z) && (armr.n == armr.v);
390 break;
391 case 13: /* LE */
392 cond = armr.z || (armr.n != armr.v);
393 break;
394 case 14: /* AL */
395 cond = 1;
396 break;
397 case 15: /* (NV) */
398 cond = 0;
399 UNDEF(ir);
400 }
402 switch( GRP(ir) ) {
403 case 0:
404 if( (ir & 0x0D900000) == 0x01000000 ) {
405 /* Instructions that aren't actual data processing */
406 switch( ir & 0x0FF000F0 ) {
407 case 0x01200010: /* BX */
408 break;
409 case 0x01000000: /* MRS Rd, CPSR */
410 break;
411 case 0x01400000: /* MRS Rd, SPSR */
412 break;
413 case 0x01200000: /* MSR CPSR, Rd */
414 break;
415 case 0x01600000: /* MSR SPSR, Rd */
416 break;
417 case 0x03200000: /* MSR CPSR, imm */
418 break;
419 case 0x03600000: /* MSR SPSR, imm */
420 break;
421 default:
422 UNIMP(ir);
423 }
424 } else if( (ir & 0x0E000090) == 0x00000090 ) {
425 /* Neither are these */
426 switch( (ir>>5)&0x03 ) {
427 case 0:
428 /* Arithmetic extension area */
429 switch(OPCODE(ir)) {
430 case 0: /* MUL */
431 break;
432 case 1: /* MULS */
433 break;
434 case 2: /* MLA */
435 break;
436 case 3: /* MLAS */
437 break;
438 case 8: /* UMULL */
439 break;
440 case 9: /* UMULLS */
441 break;
442 case 10: /* UMLAL */
443 break;
444 case 11: /* UMLALS */
445 break;
446 case 12: /* SMULL */
447 break;
448 case 13: /* SMULLS */
449 break;
450 case 14: /* SMLAL */
451 break;
452 case 15: /* SMLALS */
453 break;
454 case 16: /* SWP */
455 break;
456 case 20: /* SWPB */
457 break;
458 default:
459 UNIMP(ir);
460 }
461 break;
462 case 1:
463 if( LFLAG(ir) ) {
464 /* LDRH */
465 } else {
466 /* STRH */
467 }
468 break;
469 case 2:
470 if( LFLAG(ir) ) {
471 /* LDRSB */
472 } else {
473 UNIMP(ir);
474 }
475 break;
476 case 3:
477 if( LFLAG(ir) ) {
478 /* LDRSH */
479 } else {
480 UNIMP(ir);
481 }
482 break;
483 }
484 } else {
485 /* Data processing */
487 switch(OPCODE(ir)) {
488 case 0: /* AND Rd, Rn, operand */
489 LRD(ir) = RN(ir) & arm_get_shift_operand(ir);
490 break;
491 case 1: /* ANDS Rd, Rn, operand */
492 operand = arm_get_shift_operand_s(ir) & RN(ir);
493 LRD(ir) = operand;
494 if( RDn(ir) == 15 ) {
495 arm_restore_cpsr();
496 } else {
497 armr.n = operand>>31;
498 armr.z = (operand == 0);
499 armr.c = armr.shift_c;
500 }
501 break;
502 case 2: /* EOR Rd, Rn, operand */
503 LRD(ir) = RN(ir) ^ arm_get_shift_operand(ir);
504 break;
505 case 3: /* EORS Rd, Rn, operand */
506 operand = arm_get_shift_operand_s(ir) ^ RN(ir);
507 LRD(ir) = operand;
508 if( RDn(ir) == 15 ) {
509 arm_restore_cpsr();
510 } else {
511 armr.n = operand>>31;
512 armr.z = (operand == 0);
513 armr.c = armr.shift_c;
514 }
515 break;
516 case 4: /* SUB Rd, Rn, operand */
517 LRD(ir) = RN(ir) - arm_get_shift_operand(ir);
518 break;
519 case 5: /* SUBS Rd, Rn, operand */
520 operand = RN(ir);
521 operand2 = arm_get_shift_operand(ir);
522 tmp = operand - operand2;
523 LRD(ir) = tmp;
524 if( RDn(ir) == 15 ) {
525 arm_restore_cpsr();
526 } else {
527 armr.n = tmp>>31;
528 armr.z = (tmp == 0);
529 armr.c = IS_NOTBORROW(tmp,operand,operand2);
530 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
531 }
532 break;
533 case 6: /* RSB Rd, operand, Rn */
534 LRD(ir) = arm_get_shift_operand(ir) - RN(ir);
535 break;
536 case 7: /* RSBS Rd, operand, Rn */
537 operand = arm_get_shift_operand(ir);
538 operand2 = RN(ir);
539 tmp = operand - operand2;
540 LRD(ir) = tmp;
541 if( RDn(ir) == 15 ) {
542 arm_restore_cpsr();
543 } else {
544 armr.n = tmp>>31;
545 armr.z = (tmp == 0);
546 armr.c = IS_NOTBORROW(tmp,operand,operand2);
547 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
548 }
549 break;
550 case 8: /* ADD Rd, Rn, operand */
551 LRD(ir) = RN(ir) + arm_get_shift_operand(ir);
552 break;
553 case 9: /* ADDS Rd, Rn, operand */
554 operand = arm_get_shift_operand(ir);
555 operand2 = RN(ir);
556 tmp = operand + operand2;
557 LRD(ir) = tmp;
558 if( RDn(ir) == 15 ) {
559 arm_restore_cpsr();
560 } else {
561 armr.n = tmp>>31;
562 armr.z = (tmp == 0);
563 armr.c = IS_CARRY(tmp,operand,operand2);
564 armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
565 }
566 break;
567 case 10: /* ADC */
568 case 11: /* ADCS */
569 case 12: /* SBC */
570 case 13: /* SBCS */
571 case 14: /* RSC */
572 case 15: /* RSCS */
573 break;
574 case 17: /* TST Rn, operand */
575 operand = arm_get_shift_operand_s(ir) & RN(ir);
576 armr.n = operand>>31;
577 armr.z = (operand == 0);
578 armr.c = armr.shift_c;
579 break;
580 case 19: /* TEQ Rn, operand */
581 operand = arm_get_shift_operand_s(ir) ^ RN(ir);
582 armr.n = operand>>31;
583 armr.z = (operand == 0);
584 armr.c = armr.shift_c;
585 break;
586 case 21: /* CMP Rn, operand */
587 operand = RN(ir);
588 operand2 = arm_get_shift_operand(ir);
589 tmp = operand - operand2;
590 armr.n = tmp>>31;
591 armr.z = (tmp == 0);
592 armr.c = IS_NOTBORROW(tmp,operand,operand2);
593 armr.v = IS_SUBOVERFLOW(tmp,operand,operand2);
594 break;
595 case 23: /* CMN Rn, operand */
596 operand = RN(ir);
597 operand2 = arm_get_shift_operand(ir);
598 tmp = operand + operand2;
599 armr.n = tmp>>31;
600 armr.z = (tmp == 0);
601 armr.c = IS_CARRY(tmp,operand,operand2);
602 armr.v = IS_ADDOVERFLOW(tmp,operand,operand2);
603 break;
604 case 24: /* ORR Rd, Rn, operand */
605 LRD(ir) = RN(ir) | arm_get_shift_operand(ir);
606 break;
607 case 25: /* ORRS Rd, Rn, operand */
608 operand = arm_get_shift_operand_s(ir) | RN(ir);
609 LRD(ir) = operand;
610 if( RDn(ir) == 15 ) {
611 arm_restore_cpsr();
612 } else {
613 armr.n = operand>>31;
614 armr.z = (operand == 0);
615 armr.c = armr.shift_c;
616 }
617 break;
618 case 26: /* MOV Rd, operand */
619 LRD(ir) = arm_get_shift_operand(ir);
620 break;
621 case 27: /* MOVS Rd, operand */
622 operand = arm_get_shift_operand_s(ir);
623 LRD(ir) = operand;
624 if( RDn(ir) == 15 ) {
625 arm_restore_cpsr();
626 } else {
627 armr.n = operand>>31;
628 armr.z = (operand == 0);
629 armr.c = armr.shift_c;
630 }
631 break;
632 case 28: /* BIC Rd, Rn, operand */
633 LRD(ir) = RN(ir) & (~arm_get_shift_operand(ir));
634 break;
635 case 29: /* BICS Rd, Rn, operand */
636 operand = RN(ir) & (~arm_get_shift_operand_s(ir));
637 LRD(ir) = operand;
638 if( RDn(ir) == 15 ) {
639 arm_restore_cpsr();
640 } else {
641 armr.n = operand>>31;
642 armr.z = (operand == 0);
643 armr.c = armr.shift_c;
644 }
645 break;
646 case 30: /* MVN Rd, operand */
647 LRD(ir) = ~arm_get_shift_operand(ir);
648 break;
649 case 31: /* MVNS Rd, operand */
650 operand = ~arm_get_shift_operand_s(ir);
651 LRD(ir) = operand;
652 if( RDn(ir) == 15 ) {
653 arm_restore_cpsr();
654 } else {
655 armr.n = operand>>31;
656 armr.z = (operand == 0);
657 armr.c = armr.shift_c;
658 }
659 break;
660 default:
661 UNIMP(ir);
662 }
663 }
664 break;
665 case 1: /* Load/store */
666 break;
667 case 2: /* Load/store multiple, branch*/
668 break;
669 case 3: /* Copro */
670 break;
671 }
672 return TRUE;
673 }
.