x49gp/main.c

435 lines
7.5 KiB
C

/* $Id: main.c,v 1.30 2008/12/11 12:18:17 ecd Exp $
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include <time.h>
#include <errno.h>
#include <gtk/gtk.h>
#include <glib.h>
#include <x49gp.h>
#include <x49gp_ui.h>
#include <memory.h>
#include <s3c2410.h>
#include <s3c2410_power.h>
#include <s3c2410_timer.h>
#include <x49gp_timer.h>
#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 <config-file>\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;
}