25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_arm_instr.c,v 1.60 2006/02/09 22:40:27 debug Exp $ |
* $Id: cpu_arm_instr.c,v 1.65 2006/06/23 12:49:46 debug Exp $ |
29 |
* |
* |
30 |
* ARM instructions. |
* ARM instructions. |
31 |
* |
* |
201 |
|
|
202 |
|
|
203 |
/* |
/* |
|
* nop: Do nothing. |
|
204 |
* invalid: Invalid instructions end up here. |
* invalid: Invalid instructions end up here. |
205 |
*/ |
*/ |
|
X(nop) { } |
|
206 |
X(invalid) { |
X(invalid) { |
207 |
uint32_t low_pc; |
uint32_t low_pc; |
208 |
low_pc = ((size_t)ic - (size_t) |
low_pc = ((size_t)ic - (size_t) |
211 |
<< ARM_INSTR_ALIGNMENT_SHIFT); |
<< ARM_INSTR_ALIGNMENT_SHIFT); |
212 |
cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT); |
cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT); |
213 |
|
|
214 |
fatal("Invalid ARM instruction: pc=0x%08x\n", (int)cpu->pc); |
fatal("FATAL ERROR: An internal error occured in the ARM" |
215 |
|
" dyntrans code. Please contact the author with detailed" |
216 |
|
" repro steps on how to trigger this bug. pc = 0x%08"PRIx32"\n", |
217 |
|
(uint32_t)cpu->pc); |
218 |
|
exit(1); |
219 |
|
} |
220 |
|
|
221 |
cpu->running = 0; |
|
222 |
cpu->running_translated = 0; |
/* |
223 |
cpu->n_translated_instrs --; |
* nop: Do nothing. |
224 |
cpu->cd.arm.next_ic = ¬hing_call; |
*/ |
225 |
|
X(nop) |
226 |
|
{ |
227 |
} |
} |
228 |
|
|
229 |
|
|
761 |
cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT); |
cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT); |
762 |
cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT); |
cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT); |
763 |
old_pc = cpu->pc; |
old_pc = cpu->pc; |
764 |
printf("msr_spsr: old pc = 0x%08x\n", old_pc); |
printf("msr_spsr: old pc = 0x%08"PRIx32"\n", old_pc); |
765 |
} |
} |
766 |
exit(1); |
exit(1); |
767 |
} |
} |
1325 |
|
|
1326 |
|
|
1327 |
/* Various load/store multiple instructions: */ |
/* Various load/store multiple instructions: */ |
1328 |
uint32_t *multi_opcode[256]; |
extern uint32_t *multi_opcode[256]; |
1329 |
void (**multi_opcode_f[256])(struct cpu *, struct arm_instr_call *); |
extern void (**multi_opcode_f[256])(struct cpu *, struct arm_instr_call *); |
1330 |
X(multi_0x08b15018); |
X(multi_0x08b15018); |
1331 |
X(multi_0x08ac000c__ge); |
X(multi_0x08ac000c__ge); |
1332 |
X(multi_0x08a05018); |
X(multi_0x08a05018); |
2460 |
X(to_be_translated) |
X(to_be_translated) |
2461 |
{ |
{ |
2462 |
uint32_t addr, low_pc, iword, imm = 0; |
uint32_t addr, low_pc, iword, imm = 0; |
|
#ifdef DYNTRANS_BACKEND |
|
|
int simple = 0; |
|
|
#endif |
|
2463 |
unsigned char *page; |
unsigned char *page; |
2464 |
unsigned char ib[4]; |
unsigned char ib[4]; |
2465 |
int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8; |
int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8; |
2640 |
(iword & 0x0fb0f000) == 0x0320f000) { |
(iword & 0x0fb0f000) == 0x0320f000) { |
2641 |
/* msr: move to [S|C]PSR from a register or |
/* msr: move to [S|C]PSR from a register or |
2642 |
immediate value */ |
immediate value */ |
|
if (rm == ARM_PC) { |
|
|
fatal("msr PC?\n"); |
|
|
goto bad; |
|
|
} |
|
2643 |
if (iword & 0x02000000) { |
if (iword & 0x02000000) { |
2644 |
if (iword & 0x00400000) |
if (iword & 0x00400000) |
2645 |
ic->f = cond_instr(msr_imm_spsr); |
ic->f = cond_instr(msr_imm_spsr); |
2646 |
else |
else |
2647 |
ic->f = cond_instr(msr_imm); |
ic->f = cond_instr(msr_imm); |
2648 |
} else { |
} else { |
2649 |
|
if (rm == ARM_PC) { |
2650 |
|
fatal("msr PC?\n"); |
2651 |
|
goto bad; |
2652 |
|
} |
2653 |
if (iword & 0x00400000) |
if (iword & 0x00400000) |
2654 |
ic->f = cond_instr(msr_spsr); |
ic->f = cond_instr(msr_spsr); |
2655 |
else |
else |
2747 |
/* "mov reg,#0": */ |
/* "mov reg,#0": */ |
2748 |
if ((iword & 0x0fff0fff) == 0x03a00000 && rd != ARM_PC) { |
if ((iword & 0x0fff0fff) == 0x03a00000 && rd != ARM_PC) { |
2749 |
arm_switch_clear(ic, rd, condition_code); |
arm_switch_clear(ic, rd, condition_code); |
|
#ifdef DYNTRANS_BACKEND |
|
|
simple = 1; |
|
|
#endif |
|
2750 |
break; |
break; |
2751 |
} |
} |
2752 |
|
|
2753 |
/* "mov reg,#1": */ |
/* "mov reg,#1": */ |
2754 |
if ((iword & 0x0fff0fff) == 0x03a00001 && rd != ARM_PC) { |
if ((iword & 0x0fff0fff) == 0x03a00001 && rd != ARM_PC) { |
2755 |
arm_switch_mov1(ic, rd, condition_code); |
arm_switch_mov1(ic, rd, condition_code); |
|
#ifdef DYNTRANS_BACKEND |
|
|
simple = 1; |
|
|
#endif |
|
2756 |
break; |
break; |
2757 |
} |
} |
2758 |
|
|
2760 |
if ((iword & 0x0ff00fff) == 0x02800001 && rd != ARM_PC |
if ((iword & 0x0ff00fff) == 0x02800001 && rd != ARM_PC |
2761 |
&& rn == rd) { |
&& rn == rd) { |
2762 |
arm_switch_add1(ic, rd, condition_code); |
arm_switch_add1(ic, rd, condition_code); |
|
#ifdef DYNTRANS_BACKEND |
|
|
simple = 1; |
|
|
#endif |
|
2763 |
break; |
break; |
2764 |
} |
} |
2765 |
|
|