/* $Id: main.c,v 1.30 2008/12/11 12:18:17 ecd Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gdbstub.h" static x49gp_t *x49gp; #ifdef QEMU_OLD // LD TEMPO HACK extern #endif CPUState *__GLOBAL_env; int semihosting_enabled = 1; /* LD TEMPO HACK */ #ifndef QEMU_OLD uint8_t *phys_ram_base; int phys_ram_size; ram_addr_t ram_size = 0x80000; // LD ??? /* vl.c */ int singlestep; void *qemu_memalign(size_t alignment, size_t size) { #if defined(__APPLE__) || defined(_POSIX_C_SOURCE) && !defined(__sun__) int ret; void *ptr; ret = posix_memalign(&ptr, alignment, size); if (ret != 0) abort(); return ptr; #elif defined(CONFIG_BSD) return oom_check(valloc(size)); #else return oom_check(memalign(alignment, size)); #endif } void qemu_init_vcpu(void *_env) { CPUState *env = _env; env->nr_cores = 1; env->nr_threads = 1; } int qemu_cpu_self(void *env) { return 1; } void qemu_cpu_kick(void *env) { } void armv7m_nvic_set_pending(void *opaque, int irq) { abort(); } int armv7m_nvic_acknowledge_irq(void *opaque) { abort(); } void armv7m_nvic_complete_irq(void *opaque, int irq) { abort(); } void gdb_register_coprocessor(CPUState * env, void * get_reg, void * set_reg, int num_regs, const char *xml, int g_pos) { fprintf(stderr, "TODO: %s\n", __FUNCTION__); } #endif /* !QEMU_OLD */ void * qemu_malloc(size_t size) { return malloc(size); } void * qemu_mallocz(size_t size) { void *ptr; ptr = qemu_malloc(size); if (NULL == ptr) return NULL; memset(ptr, 0, size); return ptr; } void qemu_free(void *ptr) { free(ptr); } void * qemu_vmalloc(size_t size) { #if defined(__linux__) void *mem; if (0 == posix_memalign(&mem, sysconf(_SC_PAGE_SIZE), size)) return mem; return NULL; #else return valloc(size); #endif } #ifdef QEMU_OLD int term_vprintf(const char *fmt, va_list ap) { return vprintf(fmt, ap); } int term_printf(const char *fmt, ...) { va_list ap; int n; va_start(ap, fmt); n = vprintf(fmt, ap); va_end(ap); return n; } #endif #define SWI_Breakpoint 0x180000 #ifdef QEMU_OLD int do_arm_semihosting(CPUState *env, uint32_t number) #else uint32_t do_arm_semihosting(CPUState *env) #endif { #ifndef QEMU_OLD uint32_t number; if (env->thumb) { number = lduw_code(env->regs[15] - 2) & 0xff; } else { number = ldl_code(env->regs[15] - 4) & 0xffffff; } #endif switch (number) { case SWI_Breakpoint: break; case 0: #ifdef DEBUG_X49GP_SYSCALL printf("%s: SWI LR %08x: syscall %u: args %08x %08x %08x %08x %08x %08x %08x\n", __FUNCTION__, env->regs[14], env->regs[0], env->regs[1], env->regs[2], env->regs[3], env->regs[4], env->regs[5], env->regs[6], env->regs[7]); #endif #if 1 switch (env->regs[0]) { case 305: /* Beep */ printf("%s: BEEP: frequency %u, time %u, override %u\n", __FUNCTION__, env->regs[1], env->regs[2], env->regs[3]); gdk_beep(); env->regs[0] = 0; return 1; case 28: /* CheckBeepEnd */ env->regs[0] = 0; return 1; case 29: /* StopBeep */ env->regs[0] = 0; return 1; default: break; } #endif break; default: break; } return 0; } void x49gp_set_idle(x49gp_t *x49gp, x49gp_arm_idle_t idle) { #ifdef DEBUG_X49GP_ARM_IDLE if (idle != x49gp->arm_idle) { printf("%s: arm_idle %u, idle %u\n", __FUNCTION__, x49gp->arm_idle, idle); } #endif x49gp->arm_idle = idle; if (x49gp->arm_idle == X49GP_ARM_RUN) { x49gp->env->halted = 0; } else { x49gp->env->halted = 1; #ifdef QEMU_OLD cpu_interrupt(x49gp->env, CPU_INTERRUPT_EXIT); #else cpu_exit(x49gp->env); #endif } } static void arm_sighnd(int sig) { switch (sig) { case SIGUSR1: // stop_simulator = 1; // x49gp->arm->CallDebug ^= 1; break; default: fprintf(stderr, "%s: sig %u\n", __FUNCTION__, sig); break; } } void x49gp_gtk_timer(void *data) { while (gtk_events_pending()) { // printf("%s: gtk_main_iteration_do()\n", __FUNCTION__); gtk_main_iteration_do(FALSE); } x49gp_mod_timer(x49gp->gtk_timer, x49gp_get_clock() + X49GP_GTK_REFRESH_INTERVAL); } void x49gp_lcd_timer(void *data) { x49gp_t *x49gp = data; int64_t now, expires; // printf("%s: lcd_update\n", __FUNCTION__); x49gp_lcd_update(x49gp); gdk_flush(); now = x49gp_get_clock(); expires = now + X49GP_LCD_REFRESH_INTERVAL; // printf("%s: now: %lld, next update: %lld\n", __FUNCTION__, now, expires); x49gp_mod_timer(x49gp->lcd_timer, expires); } static void usage(const char *progname) { fprintf(stderr, "usage: %s \n", progname); exit(1); } void ui_sighnd(int sig) { switch (sig) { case SIGINT: case SIGQUIT: case SIGTERM: x49gp->arm_exit = 1; #ifdef QEMU_OLD cpu_interrupt(x49gp->env, CPU_INTERRUPT_EXIT); #else cpu_exit(x49gp->env); #endif break; } } int main(int argc, char **argv) { char *progname; int error; progname = strrchr(argv[0], '/'); if (progname) progname++; else progname = argv[0]; gtk_init(&argc, &argv); if (argc < 2) usage(progname); x49gp = malloc(sizeof(x49gp_t)); if (NULL == x49gp) { fprintf(stderr, "%s: %s:%u: Out of memory\n", progname, __FUNCTION__, __LINE__); exit(1); } memset(x49gp, 0, sizeof(x49gp_t)); fprintf(stderr, "_SC_PAGE_SIZE: %08lx\n", sysconf(_SC_PAGE_SIZE)); printf("%s:%u: x49gp: %p\n", __FUNCTION__, __LINE__, x49gp); INIT_LIST_HEAD(&x49gp->modules); x49gp->progname = progname; x49gp->clk_tck = sysconf(_SC_CLK_TCK); x49gp->emulator_fclk = 75000000; x49gp->PCLK_ratio = 4; x49gp->PCLK = 75000000 / 4; #ifdef QEMU_OLD x49gp->env = cpu_init(); #else //cpu_set_log(0xffffffff); cpu_exec_init_all(0); x49gp->env = cpu_init("arm926"); #endif __GLOBAL_env = x49gp->env; // cpu_set_log(cpu_str_to_log_mask("all")); x49gp_timer_init(x49gp); x49gp->gtk_timer = x49gp_new_timer(X49GP_TIMER_REALTIME, x49gp_gtk_timer, x49gp); x49gp->lcd_timer = x49gp_new_timer(X49GP_TIMER_VIRTUAL, x49gp_lcd_timer, x49gp); x49gp_ui_init(x49gp); x49gp_s3c2410_arm_init(x49gp); x49gp_flash_init(x49gp); x49gp_sram_init(x49gp); x49gp_s3c2410_init(x49gp); if (x49gp_modules_init(x49gp)) { exit(1); } error = x49gp_modules_load(x49gp, argv[1]); if (error) { if (error != -EAGAIN) { exit(1); } x49gp_modules_reset(x49gp, X49GP_RESET_POWER_ON); } // x49gp_modules_reset(x49gp, X49GP_RESET_POWER_ON); signal(SIGINT, ui_sighnd); signal(SIGTERM, ui_sighnd); signal(SIGQUIT, ui_sighnd); signal(SIGUSR1, arm_sighnd); x49gp_set_idle(x49gp, 0); // stl_phys(0x08000a1c, 0x55555555); x49gp_mod_timer(x49gp->gtk_timer, x49gp_get_clock()); x49gp_mod_timer(x49gp->lcd_timer, x49gp_get_clock()); #if 0 gdbserver_start(1234); gdb_handlesig(x49gp->env, 0); #endif x49gp_main_loop(x49gp); x49gp_modules_save(x49gp, argv[1]); x49gp_modules_exit(x49gp); #if 0 printf("ClkTicks: %lu\n", ARMul_Time(x49gp->arm)); printf("D TLB: hit0 %lu, hit1 %lu, search %lu (%lu), walk %lu\n", x49gp->mmu->dTLB.hit0, x49gp->mmu->dTLB.hit1, x49gp->mmu->dTLB.search, x49gp->mmu->dTLB.nsearch, x49gp->mmu->dTLB.walk); printf("I TLB: hit0 %lu, hit1 %lu, search %lu (%lu), walk %lu\n", x49gp->mmu->iTLB.hit0, x49gp->mmu->iTLB.hit1, x49gp->mmu->iTLB.search, x49gp->mmu->iTLB.nsearch, x49gp->mmu->iTLB.walk); #endif return 0; }