--- trunk/src/cpus/cpu_arm_instr.c 2007/10/08 16:18:56 15 +++ trunk/src/cpus/cpu_arm_instr.c 2007/10/08 16:19:01 16 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: cpu_arm_instr.c,v 1.26 2005/10/07 22:10:51 debug Exp $ + * $Id: cpu_arm_instr.c,v 1.29 2005/10/11 03:31:28 debug Exp $ * * ARM instructions. * @@ -133,141 +133,6 @@ /*****************************************************************************/ -/* - * update_c is set if the C flag should be updated with the last shifted/ - * rotated bit. - */ -uint32_t R(struct cpu *cpu, struct arm_instr_call *ic, - uint32_t iword, int update_c) -{ - int rm = iword & 15, lastbit, t, c; - uint32_t tmp = cpu->cd.arm.r[rm]; - - if ((iword & 0xff0)==0 && rm != ARM_PC) - return tmp; - - t = (iword >> 4) & 7; - c = (iword >> 7) & 31; - lastbit = 0; - - if (rm == ARM_PC) { - /* Calculate tmp from this instruction's PC + 8 */ - uint32_t low_pc = ((size_t)ic - (size_t) - cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call); - tmp &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << - ARM_INSTR_ALIGNMENT_SHIFT); - tmp += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT); - tmp += 8; - } - - if ((iword & 0xff0)==0 && rm == ARM_PC) - return tmp; - - if ((t & 1) && (c >> 1) == ARM_PC) { - fatal("TODO: R: rc = PC\n"); - exit(1); - } - - switch (t) { - case 0: /* lsl #c (c = 0..31) */ - if (update_c) { - if (c == 0) - update_c = 0; - else - lastbit = (tmp << (c-1)) & 0x80000000; - } - tmp <<= c; - break; - case 1: /* lsl Rc */ - c = cpu->cd.arm.r[c >> 1] & 255; - if (c >= 32) - c = 33; - if (update_c) { - if (c == 0) - update_c = 0; - else - lastbit = ((uint64_t)tmp << (c-1)) & 0x80000000; - } - tmp = (uint64_t)tmp << c; - break; - case 2: /* lsr #c (c = 1..32) */ - if (c == 0) - c = 32; - if (update_c) { - lastbit = ((uint64_t)tmp >> (c-1)) & 1; - } - tmp = (uint64_t)tmp >> c; - break; - case 3: /* lsr Rc */ - c = cpu->cd.arm.r[c >> 1] & 255; - if (c >= 32) - c = 33; - if (update_c) { - if (c == 0) - update_c = 0; - else - lastbit = ((uint64_t)tmp >> (c-1)) & 1; - } - tmp = (uint64_t)tmp >> c; - break; - case 4: /* asr #c (c = 1..32) */ - if (c == 0) - c = 32; - if (update_c) { - lastbit = ((int64_t)(int32_t)tmp >> (c-1)) & 1; - } - tmp = (int64_t)(int32_t)tmp >> c; - break; - case 5: /* asr Rc */ - c = cpu->cd.arm.r[c >> 1] & 255; - if (c >= 32) - c = 33; - if (update_c) { - if (c == 0) - update_c = 0; - else - lastbit = ((int64_t)(int32_t)tmp >> (c-1)) & 1; - } - tmp = (int64_t)(int32_t)tmp >> c; - break; - case 6: /* ror 1..31 */ - if (c == 0) { - fatal("TODO: rrx\n"); - exit(1); - } - if (update_c) - lastbit = ((int64_t)(int32_t)tmp >> (c-1)) & 1; - tmp = (uint64_t)(((uint64_t)tmp << 32) | tmp) >> c; - break; - case 7: /* ror Rc */ - c = cpu->cd.arm.r[c >> 1] & 255; - if (update_c) { - if (c == 0) - update_c = 0; - else { - c &= 31; - if (c == 0) - lastbit = tmp & 0x80000000; - else - lastbit = ((int64_t)(int32_t)tmp - >> (c-1)) & 1; - tmp = (uint64_t)(((uint64_t)tmp << 32) - | tmp) >> c; - } - } - break; - } - if (update_c) { - cpu->cd.arm.cpsr &= ~ARM_FLAG_C; - if (lastbit) - cpu->cd.arm.cpsr |= ARM_FLAG_C; - } - return tmp; -} - - -/*****************************************************************************/ - /* * nop: Do nothing. @@ -937,6 +802,8 @@ extern void (*arm_load_store_instr_3_pc[2048])(struct cpu *, struct arm_instr_call *); +extern uint32_t (*arm_r[8192])(struct cpu *, struct arm_instr_call *); + extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *, struct arm_instr_call *); X(cmps); @@ -962,7 +829,7 @@ int u_bit = iw & 0x00800000; int s_bit = iw & 0x00400000; int w_bit = iw & 0x00200000; - int i, return_flag = 0, saved_mode = 0; + int i, return_flag = 0; uint32_t new_values[16]; /* Synchronize the program counter: */ @@ -974,32 +841,14 @@ cpu->pc = cpu->cd.arm.r[ARM_PC]; if (s_bit) { - /* Load USR registers: */ + /* Load to USR registers: */ if ((cpu->cd.arm.cpsr & ARM_FLAG_MODE) == ARM_MODE_USR32) { fatal("[ bdt_load: s-bit: in usermode? ]\n"); s_bit = 0; - } else if (iw & 0x8000) { + } + if (iw & 0x8000) { s_bit = 0; return_flag = 1; - } else { - /* Which saved mode to restore to: */ - uint32_t spsr; - switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) { - case ARM_MODE_FIQ32: - spsr = cpu->cd.arm.spsr_fiq; break; - case ARM_MODE_ABT32: - spsr = cpu->cd.arm.spsr_abt; break; - case ARM_MODE_UND32: - spsr = cpu->cd.arm.spsr_und; break; - case ARM_MODE_IRQ32: - spsr = cpu->cd.arm.spsr_irq; break; - case ARM_MODE_SVC32: - spsr = cpu->cd.arm.spsr_svc; break; - default:fatal("bdt_load (1): unimplemented mode %i\n", - cpu->cd.arm.cpsr & ARM_FLAG_MODE); - exit(1); - } - saved_mode = spsr & ARM_FLAG_MODE; } } @@ -1069,46 +918,24 @@ if (!s_bit) { cpu->cd.arm.r[i] = new_values[i]; } else { - switch (saved_mode) { + switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) { case ARM_MODE_USR32: case ARM_MODE_SYS32: - if (i >= 8 && i <= 14) - cpu->cd.arm.default_r8_r14[i-8] = - new_values[i]; - else - cpu->cd.arm.r[i] = new_values[i]; + cpu->cd.arm.r[i] = new_values[i]; break; case ARM_MODE_FIQ32: if (i >= 8 && i <= 14) - cpu->cd.arm.fiq_r8_r14[i-8] = - new_values[i]; - else - cpu->cd.arm.r[i] = new_values[i]; - break; - case ARM_MODE_IRQ32: - if (i >= 13 && i <= 14) - cpu->cd.arm.irq_r13_r14[i-13] = + cpu->cd.arm.default_r8_r14[i-8] = new_values[i]; else cpu->cd.arm.r[i] = new_values[i]; break; case ARM_MODE_SVC32: - if (i >= 13 && i <= 14) - cpu->cd.arm.svc_r13_r14[i-13] = - new_values[i]; - else - cpu->cd.arm.r[i] = new_values[i]; - break; case ARM_MODE_ABT32: - if (i >= 13 && i <= 14) - cpu->cd.arm.abt_r13_r14[i-13] = - new_values[i]; - else - cpu->cd.arm.r[i] = new_values[i]; - break; case ARM_MODE_UND32: + case ARM_MODE_IRQ32: if (i >= 13 && i <= 14) - cpu->cd.arm.und_r13_r14[i-13] = + cpu->cd.arm.default_r8_r14[i-8] = new_values[i]; else cpu->cd.arm.r[i] = new_values[i]; @@ -1186,28 +1013,7 @@ int u_bit = iw & 0x00800000; int s_bit = iw & 0x00400000; int w_bit = iw & 0x00200000; - int i, saved_mode = 0; - - if (s_bit) { - /* Store USR (or saved) registers: */ - uint32_t spsr; - switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) { - case ARM_MODE_FIQ32: - spsr = cpu->cd.arm.spsr_fiq; break; - case ARM_MODE_ABT32: - spsr = cpu->cd.arm.spsr_abt; break; - case ARM_MODE_UND32: - spsr = cpu->cd.arm.spsr_und; break; - case ARM_MODE_IRQ32: - spsr = cpu->cd.arm.spsr_irq; break; - case ARM_MODE_SVC32: - spsr = cpu->cd.arm.spsr_svc; break; - default:fatal("bdt_store: unimplemented mode %i\n", - cpu->cd.arm.cpsr & ARM_FLAG_MODE); - exit(1); - } - saved_mode = spsr & ARM_FLAG_MODE; - } + int i; /* Synchronize the program counter: */ low_pc = ((size_t)ic - (size_t) @@ -1226,31 +1032,20 @@ value = cpu->cd.arm.r[i]; if (s_bit) { - switch (saved_mode) { + switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) { case ARM_MODE_FIQ32: if (i >= 8 && i <= 14) - value = cpu->cd.arm.fiq_r8_r14[i-8]; + value = cpu->cd.arm.default_r8_r14[i-8]; break; case ARM_MODE_ABT32: - if (i >= 13 && i <= 14) - value = cpu->cd.arm.abt_r13_r14[i-13]; - break; case ARM_MODE_UND32: - if (i >= 13 && i <= 14) - value = cpu->cd.arm.und_r13_r14[i-13]; - break; case ARM_MODE_IRQ32: - if (i >= 13 && i <= 14) - value = cpu->cd.arm.irq_r13_r14[i-13]; - break; case ARM_MODE_SVC32: if (i >= 13 && i <= 14) - value = cpu->cd.arm.svc_r13_r14[i-13]; + value = cpu->cd.arm.default_r8_r14[i-8]; break; case ARM_MODE_USR32: case ARM_MODE_SYS32: - if (i >= 8 && i <= 14) - value = cpu->cd.arm.default_r8_r14[i-8]; break; } } @@ -1755,7 +1550,7 @@ + (u_bit? 256 : 0) + (p_bit? 512 : 0) + (regform? 1024 : 0)]; if (regform) - ic->arg[1] = iword & 0xf; + ic->arg[1] = (size_t)(void *)arm_r[iword & 0xf]; else ic->arg[1] = imm; break; @@ -1790,9 +1585,19 @@ else regform = 0; - if (regform) - ic->arg[1] = iword; - else { + if (regform) { + /* 0x1000 signifies Carry bit update on rotation, + which is not necessary for add,adc,sub,sbc, + rsb,rsc,cmp, or cmn, because they update the + Carry bit manually anyway. */ + int q = 0x1000; + if (s_bit == 0) + q = 0; + if ((secondary_opcode >= 2 && secondary_opcode <= 7) + || secondary_opcode==0xa || secondary_opcode==0xb) + q = 0; + ic->arg[1] = (size_t)(void *)arm_r[(iword & 0xfff) + q]; + } else { imm = iword & 0xff; while (r8-- > 0) imm = (imm >> 2) | ((imm & 3) << 30); @@ -1831,7 +1636,7 @@ if (main_opcode < 6) ic->arg[1] = imm; else - ic->arg[1] = iword; + ic->arg[1] = (size_t)(void *)arm_r[iword & 0xfff]; if ((iword & 0x0e000010) == 0x06000010) { fatal("Not a Load/store TODO\n"); goto bad;