/* From emu to GDB. Returns regbuf. */ static unsigned long *get_registers(unsigned long regbuf[NUMREGS]) { // GDB's format in arm-tdep.c/arm_register_names memset(regbuf, 0, sizeof(unsigned long) * NUMREGS); memcpy(regbuf, arm.reg, sizeof(unsigned long) * 16); regbuf[NUMREGS-1] = (unsigned long)get_cpsr(); return regbuf; }
cpu_t restore_fiq(cpu_t old_cpsr) { cpu_t cpsr; cpsr = get_cpsr(); set_cpsr( (cpsr & ~FIQ_MASK) | (old_cpsr & FIQ_MASK) ); return cpsr; }
cpu_t disable_fiq(void) { cpu_t cpsr; cpsr = get_cpsr(); set_cpsr(cpsr | FIQ_MASK); return cpsr; }
cpu_t enable_fiq(void) { cpu_t cpsr; cpsr = get_cpsr(); set_cpsr(cpsr & ~FIQ_MASK); return cpsr; }
cpu_t enable_irq(void) { cpu_t cpsr; cpsr = get_cpsr(); set_cpsr(cpsr & ~IRQ_MASK); return cpsr; }
cpu_t restore_irq(cpu_t old_cpsr) { cpu_t cpsr; cpsr = get_cpsr(); set_cpsr( (cpsr & ~IRQ_MASK) | (old_cpsr & IRQ_MASK) ); return cpsr; }
cpu_t disable_irq(void) { cpu_t cpsr; cpsr = get_cpsr(); set_cpsr(cpsr | IRQ_MASK); return cpsr; }
void exc_handler(u32 type, u32 spsr, u32 *regs) { if (type > 8) type = 8; debug_printf("\nException %d (%s):\n", type, exceptions[type]); u32 pc, fsr; switch(type) { case 1: // UND case 2: // SWI case 3: // INSTR ABORT case 7: // FIQ pc = regs[15] - 4; break; case 4: // DATA ABORT pc = regs[15] - 8; break; default: pc = regs[15]; break; } debug_printf("Registers (%p):\n", regs); debug_printf(" R0-R3: %08x %08x %08x %08x\n", regs[0], regs[1], regs[2], regs[3]); debug_printf(" R4-R7: %08x %08x %08x %08x\n", regs[4], regs[5], regs[6], regs[7]); debug_printf(" R8-R11: %08x %08x %08x %08x\n", regs[8], regs[9], regs[10], regs[11]); debug_printf("R12-R15: %08x %08x %08x %08x\n", regs[12], regs[13], regs[14], pc); debug_printf("SPSR: %08x\n", spsr); debug_printf("CPSR: %08x\n", get_cpsr()); debug_printf("CR: %08x\n", get_cr()); debug_printf("TTBR: %08x\n", get_ttbr()); debug_printf("DACR: %08x\n", get_dacr()); switch (type) { case 3: // INSTR ABORT case 4: // DATA ABORT if(type == 3) fsr = get_ifsr(); else fsr = get_dfsr(); debug_printf("Abort type: %s\n", aborts[fsr&0xf]); if(domvalid[fsr&0xf]) debug_printf("Domain: %d\n", (fsr>>4)&0xf); if(type == 4) debug_printf("Address: 0x%08x\n", get_far()); break; default: break; } if(type != 3) { debug_printf("Code dump:\n"); debug_printf("%08x: %08x %08x %08x %08x\n", pc-16, read32(pc-16), read32(pc-12), read32(pc-8), read32(pc-4)); debug_printf("%08x: *%08x %08x %08x %08x\n", pc, read32(pc), read32(pc+4), read32(pc+8), read32(pc+12)); debug_printf("%08x: %08x %08x %08x %08x\n", pc+16, read32(pc+16), read32(pc+20), read32(pc+24), read32(pc+28)); } panic2(0, PANIC_EXCEPTION); }
void /* TODO: __attribute__((fastcall)) */ set_cpsr(u32 cpsr, u32 mask) { if (!(arm.cpsr_low28 & 0x0F)) { /* User mode. Don't change privileged or execution state bits */ mask &= ~0x010000FF; } cpsr = (cpsr & mask) | (get_cpsr() & ~mask); if (cpsr & 0x20) error("Cannot set T bit with MSR instruction"); set_cpsr_full(cpsr); }
// Read a bunch of registers to see what happens, for initial debugging void test_registers() { u_long id; id = idcode(id); id = get_cpsr(); id = 0x87654321; ice_set(watchpoint0_adr, id); id = idcode(); id = ice_get(watchpoint0_adr); set_register(5, 0xaa5533cc); set_register(12, 0x1234fedc); id = get_register(5); id = get_register(12); }
int start_kernel(int argc, char *argv[]) { int i; int rc; int reg[16]; int cpsr; const int timer_irq = 49; cpsr = get_cpsr(); cpsr &= ~(1<<6 | 1<<7); /* enable irq & fiq */ cpsr = set_cpsr(cpsr); printk("starting kernel...\n"); printk("starting timer1...\n"); avic_init_irq((void *)0x80000000, 128); mxs_enable_fiq_functionality(1); icoll_unmask_irq(timer_irq); start_timer(0, 0, 0, 0); waitMsec(1000); printk("CPSR: [%08X]\n", getcpsr()); getr(reg); for(i=0; i<16; i++){ printk("register [%d]: [%X]\n", i, reg[i]); } printk("Hello World!\n"); while(1) { printk("E"); waitMsec(1000); } return 0; }
int cycle(ARMSIM_CTX *ctx){ as_log(ctx, "Entering cycle\n",0); if(ctx->irq != 0 && can_irq(ctx->registers)){ unsigned int irq_ret = get_effective_pc(ctx) + 4; if(ctx->log_hook_defined != 0){ as_log(ctx, "----------------------------------------------------------------------------------------", 0); char * string1 = (char*)malloc(sizeof(char)*LOG_STRING_LENGTH); sprintf(string1, "!!!! IRQ: ePC=%#010x, tPC=%#010x !!!!", get_effective_pc(ctx), get_register(ctx->registers, AR_r15)); as_log(ctx, string1, 0); free(string1); char * string2 = (char*)malloc(sizeof(char)*LOG_STRING_LENGTH); char * instruction_string = instruction_to_string(master_decode(irq_ret - 4, get_word_from_memory(ctx, irq_ret - 4))); sprintf(string2, "???? Effective IRQ return: %s ????", instruction_string); as_log(ctx, string2, 0); free(string2); } set_mode(ctx->registers, AM_IRQ); set_cpsr(ctx->registers, get_cpsr(ctx->registers) | 0xC0); set_register(ctx->registers, AR_r14, irq_ret); branch_cpu(ctx, 0x00000018); ctx->irq = 0; } ctx-> per = as_execute_instruction(ctx, ctx->pdr); ctx->pdr = as_decode_instruction(ctx, ctx->pfr_address, ctx->pfr_instruction); ARM_ADDRESS * address = (ARM_ADDRESS*)malloc(sizeof(ARM_ADDRESS)); ctx->pfr_instruction = fetch_instruction(ctx, address); ctx->pfr_address = *address; free(address); if(ctx->per != 0) { ctx->steps += 1; if (ctx->trace_hook_defined != 0) { cpu_trace(ctx, ctx->per); } } as_log(ctx, "Leaving cycle\n",0); return (ctx->per != 0); }
ARMSIM_INSTRUCTION * as_execute_instruction(ARMSIM_CTX *ctx, ARMSIM_INSTRUCTION * cooked_instruction){ as_log(ctx, "Entering as_execute_instruction\n",0); if(cooked_instruction == 0){ as_log(ctx, "Leaving as_execute_instruction\n",0); return 0; } char * string = (char*)malloc(sizeof(char) * LOG_STRING_LENGTH); char * instruction_string = instruction_to_string(cooked_instruction); if(cond_test(cooked_instruction->condition, get_cpsr(ctx->registers)) != 0){ sprintf(string, "EXECUTING([%s] %x)", instruction_string, get_mode(ctx->registers)); actually_execute_instruction(cooked_instruction); } else{ sprintf(string, "SKIPPING([%s] %x)", instruction_string, get_mode(ctx->registers)); } as_log(ctx, string, 0); free(string); free(instruction_string); as_log(ctx, "Leaving as_execute_instruction\n",0); return cooked_instruction; }
void cpu_trace(ARMSIM_CTX *ctx, ARMSIM_INSTRUCTION * instruction){ as_log(ctx, "Entering cpu_trace\n",0); ARM_WORD *r = (*ctx->registers); if(instruction != 0){ char *traceString1 = (char*)malloc(sizeof(char)*LOG_STRING_LENGTH); sprintf(traceString1, "%06d %08x %08x", ctx->steps, instruction->address, get_cpsr(ctx->registers)); as_trace(ctx, traceString1, 0); free(traceString1); char *traceString2 = (char*)malloc(sizeof(char)*LOG_STRING_LENGTH); sprintf(traceString2, "\\t 0=%08x 1=%08x 2=%08x 3=%08x 4=%08x 5=%08x 6=%08x 7=%08x", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); as_trace(ctx, traceString2, 0); free(traceString2); char *traceString3 = (char*)malloc(sizeof(char)*LOG_STRING_LENGTH); sprintf(traceString3, "\\t 8=%08x 9=%08x 10=%08x 11=%08x 12=%08x 13=%08x 14=%08x", r[8], r[9], r[10], r[11], r[12], r[13], r[14]); as_trace(ctx, traceString3,0); free(traceString3); } as_log(ctx, "Leaving cpu_trace\n",0); }
// return 1: break (should stop being feed with debugger commands), 0: continue (can be feed with other debugger commands) int process_debug_cmd(char *cmdline) { char *cmd = strtok(cmdline, " \n\r"); if (!cmd) return 0; if (!strcasecmp(cmd, "?") || !strcasecmp(cmd, "h")) { gui_debug_printf( "Debugger commands:\n" "b - stack backtrace\n" "c - continue\n" "d <address> - dump memory\n" "k <address> <+r|+w|+x|-r|-w|-x> - add/remove breakpoint\n" "k - show breakpoints\n" "ln c - connect\n" "ln s <file> - send a file\n" "ln st <dir> - set target directory\n" "mmu - dump memory mappings\n" "n - continue until next instruction\n" "pr <address> - port or memory read\n" "pw <address> <value> - port or memory write\n" "r - show registers\n" "rs <regnum> <value> - change register value\n" "ss <address> <length> <string> - search a string\n" "s - step instruction\n" "t+ - enable instruction translation\n" "t- - disable instruction translation\n" "u[a|t] [address] - disassemble memory\n" "wm <file> <start> <size> - write memory to file\n" "wf <file> <start> [size] - write file to memory\n" "stop - stop the emulation\n" "exec <path> - exec file with ndless\n"); } else if (!strcasecmp(cmd, "b")) { char *fp = strtok(NULL, " \n\r"); backtrace(fp ? parse_expr(fp) : arm.reg[11]); } else if (!strcasecmp(cmd, "mmu")) { mmu_dump_tables(); } else if (!strcasecmp(cmd, "r")) { int i, show_spsr; uint32_t cpsr = get_cpsr(); const char *mode; for (i = 0; i < 16; i++) { int newline = ((1 << 5) | (1 << 11) | (1 << 15)) & (1 << i); gui_debug_printf("%3s=%08x%c", reg_name[i], arm.reg[i], newline ? '\n' : ' '); } switch (cpsr & 0x1F) { case MODE_USR: mode = "usr"; show_spsr = 0; break; case MODE_SYS: mode = "sys"; show_spsr = 0; break; case MODE_FIQ: mode = "fiq"; show_spsr = 1; break; case MODE_IRQ: mode = "irq"; show_spsr = 1; break; case MODE_SVC: mode = "svc"; show_spsr = 1; break; case MODE_ABT: mode = "abt"; show_spsr = 1; break; case MODE_UND: mode = "und"; show_spsr = 1; break; default: mode = "???"; show_spsr = 0; break; } gui_debug_printf("cpsr=%08x (N=%d Z=%d C=%d V=%d Q=%d IRQ=%s FIQ=%s T=%d Mode=%s)", cpsr, arm.cpsr_n, arm.cpsr_z, arm.cpsr_c, arm.cpsr_v, cpsr >> 27 & 1, (cpsr & 0x80) ? "off" : "on ", (cpsr & 0x40) ? "off" : "on ", cpsr >> 5 & 1, mode); if (show_spsr) gui_debug_printf(" spsr=%08x", get_spsr()); gui_debug_printf("\n"); } else if (!strcasecmp(cmd, "rs")) {
void console_put_cpsr(void) { int cpsr_value = get_cpsr(); console_put_hex(cpsr_value); }