Commit 0633879f1ac38b18d84c46dda506300cc8329723

Authored by pbrook
1 parent 9daea906

m68k/ColdFire system emulation.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2851 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
@@ -308,7 +308,7 @@ LIBOBJS+= op_helper.o helper.o @@ -308,7 +308,7 @@ LIBOBJS+= op_helper.o helper.o
308 endif 308 endif
309 309
310 ifeq ($(TARGET_BASE_ARCH), m68k) 310 ifeq ($(TARGET_BASE_ARCH), m68k)
311 -LIBOBJS+= helper.o 311 +LIBOBJS+= op_helper.o helper.o
312 endif 312 endif
313 313
314 ifeq ($(TARGET_BASE_ARCH), alpha) 314 ifeq ($(TARGET_BASE_ARCH), alpha)
@@ -466,6 +466,9 @@ endif @@ -466,6 +466,9 @@ endif
466 ifeq ($(TARGET_BASE_ARCH), sh4) 466 ifeq ($(TARGET_BASE_ARCH), sh4)
467 VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o 467 VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
468 endif 468 endif
  469 +ifeq ($(TARGET_BASE_ARCH), m68k)
  470 +VL_OBJS+= an5206.o mcf5206.o ptimer.o
  471 +endif
469 ifdef CONFIG_GDBSTUB 472 ifdef CONFIG_GDBSTUB
470 VL_OBJS+=gdbstub.o 473 VL_OBJS+=gdbstub.o
471 endif 474 endif
configure
@@ -467,7 +467,7 @@ fi @@ -467,7 +467,7 @@ fi
467 if test -z "$target_list" ; then 467 if test -z "$target_list" ; then
468 # these targets are portable 468 # these targets are portable
469 if [ "$softmmu" = "yes" ] ; then 469 if [ "$softmmu" = "yes" ] ; then
470 - target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc64-softmmu ppcemb-softmmu " 470 + target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc64-softmmu ppcemb-softmmu m68k-softmmu"
471 fi 471 fi
472 # the following are Linux specific 472 # the following are Linux specific
473 if [ "$linux_user" = "yes" ] ; then 473 if [ "$linux_user" = "yes" ] ; then
cpu-exec.c
@@ -196,7 +196,7 @@ static inline TranslationBlock *tb_find_fast(void) @@ -196,7 +196,7 @@ static inline TranslationBlock *tb_find_fast(void)
196 cs_base = 0; 196 cs_base = 0;
197 pc = env->PC; 197 pc = env->PC;
198 #elif defined(TARGET_M68K) 198 #elif defined(TARGET_M68K)
199 - flags = env->fpcr & M68K_FPCR_PREC; 199 + flags = (env->fpcr & M68K_FPCR_PREC) | (env->sr & SR_S);
200 cs_base = 0; 200 cs_base = 0;
201 pc = env->pc; 201 pc = env->pc;
202 #elif defined(TARGET_SH4) 202 #elif defined(TARGET_SH4)
@@ -297,7 +297,7 @@ int cpu_exec(CPUState *env1) @@ -297,7 +297,7 @@ int cpu_exec(CPUState *env1)
297 return EXCP_HALTED; 297 return EXCP_HALTED;
298 } 298 }
299 } 299 }
300 -#elif defined(TARGET_ALPHA) 300 +#elif defined(TARGET_ALPHA) || defined(TARGET_M68K)
301 if (env1->halted) { 301 if (env1->halted) {
302 if (env1->interrupt_request & CPU_INTERRUPT_HARD) { 302 if (env1->interrupt_request & CPU_INTERRUPT_HARD) {
303 env1->halted = 0; 303 env1->halted = 0;
@@ -390,6 +390,8 @@ int cpu_exec(CPUState *env1) @@ -390,6 +390,8 @@ int cpu_exec(CPUState *env1)
390 do_interrupt(env); 390 do_interrupt(env);
391 #elif defined(TARGET_ALPHA) 391 #elif defined(TARGET_ALPHA)
392 do_interrupt(env); 392 do_interrupt(env);
  393 +#elif defined(TARGET_M68K)
  394 + do_interrupt(0);
393 #endif 395 #endif
394 } 396 }
395 env->exception_index = -1; 397 env->exception_index = -1;
@@ -542,6 +544,18 @@ int cpu_exec(CPUState *env1) @@ -542,6 +544,18 @@ int cpu_exec(CPUState *env1)
542 if (interrupt_request & CPU_INTERRUPT_HARD) { 544 if (interrupt_request & CPU_INTERRUPT_HARD) {
543 do_interrupt(env); 545 do_interrupt(env);
544 } 546 }
  547 +#elif defined(TARGET_M68K)
  548 + if (interrupt_request & CPU_INTERRUPT_HARD
  549 + && ((env->sr & SR_I) >> SR_I_SHIFT)
  550 + < env->pending_level) {
  551 + /* Real hardware gets the interrupt vector via an
  552 + IACK cycle at this point. Current emulated
  553 + hardware doesn't rely on this, so we
  554 + provide/save the vector when the interrupt is
  555 + first signalled. */
  556 + env->exception_index = env->pending_vector;
  557 + do_interrupt(1);
  558 + }
545 #endif 559 #endif
546 /* Don't use the cached interupt_request value, 560 /* Don't use the cached interupt_request value,
547 do_interrupt may have updated the EXITTB flag. */ 561 do_interrupt may have updated the EXITTB flag. */
exec-all.h
@@ -584,6 +584,8 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) @@ -584,6 +584,8 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
584 is_user = ((env->sr & SR_MD) == 0); 584 is_user = ((env->sr & SR_MD) == 0);
585 #elif defined (TARGET_ALPHA) 585 #elif defined (TARGET_ALPHA)
586 is_user = ((env->ps >> 3) & 3); 586 is_user = ((env->ps >> 3) & 3);
  587 +#elif defined (TARGET_M68K)
  588 + is_user = ((env->sr & SR_S) == 0);
587 #else 589 #else
588 #error unimplemented CPU 590 #error unimplemented CPU
589 #endif 591 #endif
hw/an5206.c 0 โ†’ 100644
  1 +/*
  2 + * Arnewsh 5206 ColdFire system emulation.
  3 + *
  4 + * Copyright (c) 2007 CodeSourcery.
  5 + *
  6 + * This code is licenced under the GPL
  7 + */
  8 +
  9 +#include "vl.h"
  10 +
  11 +#define KERNEL_LOAD_ADDR 0x10000
  12 +#define AN5206_MBAR_ADDR 0x10000000
  13 +#define AN5206_RAMBAR_ADDR 0x20000000
  14 +
  15 +/* Stub functions for hardware that doesn't exist. */
  16 +void pic_info(void)
  17 +{
  18 +}
  19 +
  20 +void irq_info(void)
  21 +{
  22 +}
  23 +
  24 +void DMA_run (void)
  25 +{
  26 +}
  27 +
  28 +/* Board init. */
  29 +
  30 +static void an5206_init(int ram_size, int vga_ram_size, int boot_device,
  31 + DisplayState *ds, const char **fd_filename, int snapshot,
  32 + const char *kernel_filename, const char *kernel_cmdline,
  33 + const char *initrd_filename, const char *cpu_model)
  34 +{
  35 + CPUState *env;
  36 + int kernel_size;
  37 + uint64_t elf_entry;
  38 + target_ulong entry;
  39 +
  40 + env = cpu_init();
  41 + if (!cpu_model)
  42 + cpu_model = "m5206";
  43 + cpu_m68k_set_model(env, cpu_model);
  44 +
  45 + /* Initialize CPU registers. */
  46 + env->vbr = 0;
  47 + /* TODO: allow changing MBAR and RAMBAR. */
  48 + env->mbar = AN5206_MBAR_ADDR | 1;
  49 + env->rambar0 = AN5206_RAMBAR_ADDR | 1;
  50 +
  51 + /* DRAM at address zero */
  52 + cpu_register_physical_memory(0, ram_size,
  53 + qemu_ram_alloc(ram_size) | IO_MEM_RAM);
  54 +
  55 + /* Internal SRAM. */
  56 + cpu_register_physical_memory(AN5206_RAMBAR_ADDR, 512,
  57 + qemu_ram_alloc(512) | IO_MEM_RAM);
  58 +
  59 + mcf5206_init(AN5206_MBAR_ADDR, env);
  60 +
  61 + /* Load kernel. */
  62 + if (!kernel_filename) {
  63 + fprintf(stderr, "Kernel image must be specified\n");
  64 + exit(1);
  65 + }
  66 +
  67 + kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
  68 + entry = elf_entry;
  69 + if (kernel_size < 0) {
  70 + kernel_size = load_uboot(kernel_filename, &entry, NULL);
  71 + }
  72 + if (kernel_size < 0) {
  73 + kernel_size = load_image(kernel_filename,
  74 + phys_ram_base + KERNEL_LOAD_ADDR);
  75 + entry = KERNEL_LOAD_ADDR;
  76 + }
  77 + if (kernel_size < 0) {
  78 + fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
  79 + exit(1);
  80 + }
  81 +
  82 + env->pc = entry;
  83 +}
  84 +
  85 +QEMUMachine an5206_machine = {
  86 + "an5206",
  87 + "Arnewsh 5206",
  88 + an5206_init,
  89 +};
hw/mcf5206.c 0 โ†’ 100644
  1 +/*
  2 + * Motorola ColdFire MCF5206 SoC embedded peripheral emulation.
  3 + *
  4 + * Copyright (c) 2007 CodeSourcery.
  5 + *
  6 + * This code is licenced under the GPL
  7 + */
  8 +#include "vl.h"
  9 +
  10 +/* General purpose timer module. */
  11 +typedef struct {
  12 + uint16_t tmr;
  13 + uint16_t trr;
  14 + uint16_t tcr;
  15 + uint16_t ter;
  16 + ptimer_state *timer;
  17 + qemu_irq irq;
  18 + int irq_state;
  19 +} m5206_timer_state;
  20 +
  21 +#define TMR_RST 0x01
  22 +#define TMR_CLK 0x06
  23 +#define TMR_FRR 0x08
  24 +#define TMR_ORI 0x10
  25 +#define TMR_OM 0x20
  26 +#define TMR_CE 0xc0
  27 +
  28 +#define TER_CAP 0x01
  29 +#define TER_REF 0x02
  30 +
  31 +static void m5206_timer_update(m5206_timer_state *s)
  32 +{
  33 + if ((s->tmr & TMR_ORI) != 0 && (s->ter & TER_REF))
  34 + qemu_irq_raise(s->irq);
  35 + else
  36 + qemu_irq_lower(s->irq);
  37 +}
  38 +
  39 +static void m5206_timer_reset(m5206_timer_state *s)
  40 +{
  41 + s->tmr = 0;
  42 + s->trr = 0;
  43 +}
  44 +
  45 +static void m5206_timer_recalibrate(m5206_timer_state *s)
  46 +{
  47 + int prescale;
  48 + int mode;
  49 +
  50 + ptimer_stop(s->timer);
  51 +
  52 + if ((s->tmr & TMR_RST) == 0)
  53 + return;
  54 +
  55 + prescale = (s->tmr >> 8) + 1;
  56 + mode = (s->tmr >> 1) & 3;
  57 + if (mode == 2)
  58 + prescale *= 16;
  59 +
  60 + if (mode == 3 || mode == 0)
  61 + cpu_abort(cpu_single_env,
  62 + "m5206_timer: mode %d not implemented\n", mode);
  63 + if ((s->tmr & TMR_FRR) == 0)
  64 + cpu_abort(cpu_single_env,
  65 + "m5206_timer: free running mode not implemented\n");
  66 +
  67 + /* Assume 66MHz system clock. */
  68 + ptimer_set_freq(s->timer, 66000000 / prescale);
  69 +
  70 + ptimer_set_limit(s->timer, s->trr, 0);
  71 +
  72 + ptimer_run(s->timer, 0);
  73 +}
  74 +
  75 +static void m5206_timer_trigger(void *opaque)
  76 +{
  77 + m5206_timer_state *s = (m5206_timer_state *)opaque;
  78 + s->ter |= TER_REF;
  79 + m5206_timer_update(s);
  80 +}
  81 +
  82 +static uint32_t m5206_timer_read(m5206_timer_state *s, uint32_t addr)
  83 +{
  84 + switch (addr) {
  85 + case 0:
  86 + return s->tmr;
  87 + case 4:
  88 + return s->trr;
  89 + case 8:
  90 + return s->tcr;
  91 + case 0xc:
  92 + return s->trr - ptimer_get_count(s->timer);
  93 + case 0x11:
  94 + return s->ter;
  95 + default:
  96 + return 0;
  97 + }
  98 +}
  99 +
  100 +static void m5206_timer_write(m5206_timer_state *s, uint32_t addr, uint32_t val)
  101 +{
  102 + switch (addr) {
  103 + case 0:
  104 + if ((s->tmr & TMR_RST) != 0 && (val & TMR_RST) == 0) {
  105 + m5206_timer_reset(s);
  106 + }
  107 + s->tmr = val;
  108 + m5206_timer_recalibrate(s);
  109 + break;
  110 + case 4:
  111 + s->trr = val;
  112 + m5206_timer_recalibrate(s);
  113 + break;
  114 + case 8:
  115 + s->tcr = val;
  116 + break;
  117 + case 0xc:
  118 + ptimer_set_count(s->timer, val);
  119 + break;
  120 + case 0x11:
  121 + s->ter &= ~val;
  122 + break;
  123 + default:
  124 + break;
  125 + }
  126 + m5206_timer_update(s);
  127 +}
  128 +
  129 +static m5206_timer_state *m5206_timer_init(qemu_irq irq)
  130 +{
  131 + m5206_timer_state *s;
  132 + QEMUBH *bh;
  133 +
  134 + s = (m5206_timer_state *)qemu_mallocz(sizeof(m5206_timer_state));
  135 + bh = qemu_bh_new(m5206_timer_trigger, s);
  136 + s->timer = ptimer_init(bh);
  137 + s->irq = irq;
  138 + m5206_timer_reset(s);
  139 + return s;
  140 +}
  141 +
  142 +/* UART */
  143 +
  144 +typedef struct {
  145 + uint8_t mr[2];
  146 + uint8_t sr;
  147 + uint8_t isr;
  148 + uint8_t imr;
  149 + uint8_t bg1;
  150 + uint8_t bg2;
  151 + uint8_t fifo[4];
  152 + uint8_t tb;
  153 + int current_mr;
  154 + int fifo_len;
  155 + int tx_enabled;
  156 + int rx_enabled;
  157 + qemu_irq irq;
  158 + CharDriverState *chr;
  159 +} m5206_uart_state;
  160 +
  161 +/* UART Status Register bits. */
  162 +#define M5206_UART_RxRDY 0x01
  163 +#define M5206_UART_FFULL 0x02
  164 +#define M5206_UART_TxRDY 0x04
  165 +#define M5206_UART_TxEMP 0x08
  166 +#define M5206_UART_OE 0x10
  167 +#define M5206_UART_PE 0x20
  168 +#define M5206_UART_FE 0x40
  169 +#define M5206_UART_RB 0x80
  170 +
  171 +/* Interrupt flags. */
  172 +#define M5206_UART_TxINT 0x01
  173 +#define M5206_UART_RxINT 0x02
  174 +#define M5206_UART_DBINT 0x04
  175 +#define M5206_UART_COSINT 0x80
  176 +
  177 +/* UMR1 flags. */
  178 +#define M5206_UART_BC0 0x01
  179 +#define M5206_UART_BC1 0x02
  180 +#define M5206_UART_PT 0x04
  181 +#define M5206_UART_PM0 0x08
  182 +#define M5206_UART_PM1 0x10
  183 +#define M5206_UART_ERR 0x20
  184 +#define M5206_UART_RxIRQ 0x40
  185 +#define M5206_UART_RxRTS 0x80
  186 +
  187 +static void m5206_uart_update(m5206_uart_state *s)
  188 +{
  189 + s->isr &= ~(M5206_UART_TxINT | M5206_UART_RxINT);
  190 + if (s->sr & M5206_UART_TxRDY)
  191 + s->isr |= M5206_UART_TxINT;
  192 + if ((s->sr & ((s->mr[0] & M5206_UART_RxIRQ)
  193 + ? M5206_UART_FFULL : M5206_UART_RxRDY)) != 0)
  194 + s->isr |= M5206_UART_RxINT;
  195 +
  196 + qemu_set_irq(s->irq, (s->isr & s->imr) != 0);
  197 +}
  198 +
  199 +static uint32_t m5206_uart_read(m5206_uart_state *s, uint32_t addr)
  200 +{
  201 + switch (addr) {
  202 + case 0x00:
  203 + return s->mr[s->current_mr];
  204 + case 0x04:
  205 + return s->sr;
  206 + case 0x0c:
  207 + {
  208 + uint8_t val;
  209 + int i;
  210 +
  211 + if (s->fifo_len == 0)
  212 + return 0;
  213 +
  214 + val = s->fifo[0];
  215 + s->fifo_len--;
  216 + for (i = 0; i < s->fifo_len; i++)
  217 + s->fifo[i] = s->fifo[i + 1];
  218 + s->sr &= ~M5206_UART_FFULL;
  219 + if (s->fifo_len == 0)
  220 + s->sr &= ~M5206_UART_RxRDY;
  221 + m5206_uart_update(s);
  222 + return val;
  223 + }
  224 + case 0x10:
  225 + /* TODO: Implement IPCR. */
  226 + return 0;
  227 + case 0x14:
  228 + return s->isr;
  229 + case 0x18:
  230 + return s->bg1;
  231 + case 0x1c:
  232 + return s->bg2;
  233 + default:
  234 + return 0;
  235 + }
  236 +}
  237 +
  238 +/* Update TxRDY flag and set data if present and enabled. */
  239 +static void m5206_uart_do_tx(m5206_uart_state *s)
  240 +{
  241 + if (s->tx_enabled && (s->sr & M5206_UART_TxEMP) == 0) {
  242 + if (s->chr)
  243 + qemu_chr_write(s->chr, (unsigned char *)&s->tb, 1);
  244 + s->sr |= M5206_UART_TxEMP;
  245 + }
  246 + if (s->tx_enabled) {
  247 + s->sr |= M5206_UART_TxRDY;
  248 + } else {
  249 + s->sr &= ~M5206_UART_TxRDY;
  250 + }
  251 +}
  252 +
  253 +static void m5206_do_command(m5206_uart_state *s, uint8_t cmd)
  254 +{
  255 + /* Misc command. */
  256 + switch ((cmd >> 4) & 3) {
  257 + case 0: /* No-op. */
  258 + break;
  259 + case 1: /* Reset mode register pointer. */
  260 + s->current_mr = 0;
  261 + break;
  262 + case 2: /* Reset receiver. */
  263 + s->rx_enabled = 0;
  264 + s->fifo_len = 0;
  265 + s->sr &= ~(M5206_UART_RxRDY | M5206_UART_FFULL);
  266 + break;
  267 + case 3: /* Reset transmitter. */
  268 + s->tx_enabled = 0;
  269 + s->sr |= M5206_UART_TxEMP;
  270 + s->sr &= ~M5206_UART_TxRDY;
  271 + break;
  272 + case 4: /* Reset error status. */
  273 + break;
  274 + case 5: /* Reset break-change interrupt. */
  275 + s->isr &= ~M5206_UART_DBINT;
  276 + break;
  277 + case 6: /* Start break. */
  278 + case 7: /* Stop break. */
  279 + break;
  280 + }
  281 +
  282 + /* Transmitter command. */
  283 + switch ((cmd >> 2) & 3) {
  284 + case 0: /* No-op. */
  285 + break;
  286 + case 1: /* Enable. */
  287 + s->tx_enabled = 1;
  288 + m5206_uart_do_tx(s);
  289 + break;
  290 + case 2: /* Disable. */
  291 + s->tx_enabled = 0;
  292 + m5206_uart_do_tx(s);
  293 + break;
  294 + case 3: /* Reserved. */
  295 + fprintf(stderr, "m5206_uart: Bad TX command\n");
  296 + break;
  297 + }
  298 +
  299 + /* Receiver command. */
  300 + switch (cmd & 3) {
  301 + case 0: /* No-op. */
  302 + break;
  303 + case 1: /* Enable. */
  304 + s->rx_enabled = 1;
  305 + break;
  306 + case 2:
  307 + s->rx_enabled = 0;
  308 + break;
  309 + case 3: /* Reserved. */
  310 + fprintf(stderr, "m5206_uart: Bad RX command\n");
  311 + break;
  312 + }
  313 +}
  314 +
  315 +static void m5206_uart_write(m5206_uart_state *s, uint32_t addr, uint32_t val)
  316 +{
  317 + switch (addr) {
  318 + case 0x00:
  319 + s->mr[s->current_mr] = val;
  320 + s->current_mr = 1;
  321 + break;
  322 + case 0x04:
  323 + /* CSR is ignored. */
  324 + break;
  325 + case 0x08: /* Command Register. */
  326 + m5206_do_command(s, val);
  327 + break;
  328 + case 0x0c: /* Transmit Buffer. */
  329 + s->sr &= ~M5206_UART_TxEMP;
  330 + s->tb = val;
  331 + m5206_uart_do_tx(s);
  332 + break;
  333 + case 0x10:
  334 + /* ACR is ignored. */
  335 + break;
  336 + case 0x14:
  337 + s->imr = val;
  338 + break;
  339 + default:
  340 + break;
  341 + }
  342 + m5206_uart_update(s);
  343 +}
  344 +
  345 +static void m5206_uart_reset(m5206_uart_state *s)
  346 +{
  347 + s->fifo_len = 0;
  348 + s->mr[0] = 0;
  349 + s->mr[1] = 0;
  350 + s->sr = M5206_UART_TxEMP;
  351 + s->tx_enabled = 0;
  352 + s->rx_enabled = 0;
  353 + s->isr = 0;
  354 + s->imr = 0;
  355 +}
  356 +
  357 +static void m5206_uart_push_byte(m5206_uart_state *s, uint8_t data)
  358 +{
  359 + /* Break events overwrite the last byte if the fifo is full. */
  360 + if (s->fifo_len == 4)
  361 + s->fifo_len--;
  362 +
  363 + s->fifo[s->fifo_len] = data;
  364 + s->fifo_len++;
  365 + s->sr |= M5206_UART_RxRDY;
  366 + if (s->fifo_len == 4)
  367 + s->sr |= M5206_UART_FFULL;
  368 +
  369 + m5206_uart_update(s);
  370 +}
  371 +
  372 +static void m5206_uart_event(void *opaque, int event)
  373 +{
  374 + m5206_uart_state *s = (m5206_uart_state *)opaque;
  375 +
  376 + switch (event) {
  377 + case CHR_EVENT_BREAK:
  378 + s->isr |= M5206_UART_DBINT;
  379 + m5206_uart_push_byte(s, 0);
  380 + break;
  381 + default:
  382 + break;
  383 + }
  384 +}
  385 +
  386 +static int m5206_uart_can_receive(void *opaque)
  387 +{
  388 + m5206_uart_state *s = (m5206_uart_state *)opaque;
  389 +
  390 + return s->rx_enabled && (s->sr & M5206_UART_FFULL) == 0;
  391 +}
  392 +
  393 +static void m5206_uart_receive(void *opaque, const uint8_t *buf, int size)
  394 +{
  395 + m5206_uart_state *s = (m5206_uart_state *)opaque;
  396 +
  397 + m5206_uart_push_byte(s, buf[0]);
  398 +}
  399 +
  400 +static m5206_uart_state *m5206_uart_init(qemu_irq irq, CharDriverState *chr)
  401 +{
  402 + m5206_uart_state *s;
  403 +
  404 + s = qemu_mallocz(sizeof(m5206_uart_state));
  405 + s->chr = chr;
  406 + s->irq = irq;
  407 + if (chr) {
  408 + qemu_chr_add_handlers(chr, m5206_uart_can_receive, m5206_uart_receive,
  409 + m5206_uart_event, s);
  410 + }
  411 + m5206_uart_reset(s);
  412 + return s;
  413 +}
  414 +
  415 +/* System Integration Module. */
  416 +
  417 +typedef struct {
  418 + CPUState *env;
  419 + m5206_timer_state *timer[2];
  420 + m5206_uart_state *uart[2];
  421 + uint8_t scr;
  422 + uint8_t icr[14];
  423 + uint16_t imr; /* 1 == interrupt is masked. */
  424 + uint16_t ipr;
  425 + uint8_t rsr;
  426 + uint8_t swivr;
  427 + uint8_t par;
  428 + /* Include the UART vector registers here. */
  429 + uint8_t uivr[2];
  430 +} m5206_mbar_state;
  431 +
  432 +/* Interrupt controller. */
  433 +
  434 +static int m5206_find_pending_irq(m5206_mbar_state *s)
  435 +{
  436 + int level;
  437 + int vector;
  438 + uint16_t active;
  439 + int i;
  440 +
  441 + level = 0;
  442 + vector = 0;
  443 + active = s->ipr & ~s->imr;
  444 + if (!active)
  445 + return 0;
  446 +
  447 + for (i = 1; i < 14; i++) {
  448 + if (active & (1 << i)) {
  449 + if ((s->icr[i] & 0x1f) > level) {
  450 + level = s->icr[i] & 0x1f;
  451 + vector = i;
  452 + }
  453 + }
  454 + }
  455 +
  456 + if (level < 4)
  457 + vector = 0;
  458 +
  459 + return vector;
  460 +}
  461 +
  462 +static void m5206_mbar_update(m5206_mbar_state *s)
  463 +{
  464 + int irq;
  465 + int vector;
  466 + int level;
  467 +
  468 + irq = m5206_find_pending_irq(s);
  469 + if (irq) {
  470 + int tmp;
  471 + tmp = s->icr[irq];
  472 + level = (tmp >> 2) & 7;
  473 + if (tmp & 0x80) {
  474 + /* Autovector. */
  475 + vector = 24 + level;
  476 + } else {
  477 + switch (irq) {
  478 + case 8: /* SWT */
  479 + vector = s->swivr;
  480 + break;
  481 + case 12: /* UART1 */
  482 + vector = s->uivr[0];
  483 + break;
  484 + case 13: /* UART2 */
  485 + vector = s->uivr[1];
  486 + break;
  487 + default:
  488 + /* Unknown vector. */
  489 + fprintf(stderr, "Unhandled vector for IRQ %d\n", irq);
  490 + vector = 0xf;
  491 + break;
  492 + }
  493 + }
  494 + } else {
  495 + level = 0;
  496 + vector = 0;
  497 + }
  498 + m68k_set_irq_level(s->env, level, vector);
  499 +}
  500 +
  501 +static void m5206_mbar_set_irq(void *opaque, int irq, int level)
  502 +{
  503 + m5206_mbar_state *s = (m5206_mbar_state *)opaque;
  504 + if (level) {
  505 + s->ipr |= 1 << irq;
  506 + } else {
  507 + s->ipr &= ~(1 << irq);
  508 + }
  509 + m5206_mbar_update(s);
  510 +}
  511 +
  512 +/* System Integration Module. */
  513 +
  514 +static void m5206_mbar_reset(m5206_mbar_state *s)
  515 +{
  516 + s->scr = 0xc0;
  517 + s->icr[1] = 0x04;
  518 + s->icr[2] = 0x08;
  519 + s->icr[3] = 0x0c;
  520 + s->icr[4] = 0x10;
  521 + s->icr[5] = 0x14;
  522 + s->icr[6] = 0x18;
  523 + s->icr[7] = 0x1c;
  524 + s->icr[8] = 0x1c;
  525 + s->icr[9] = 0x80;
  526 + s->icr[10] = 0x80;
  527 + s->icr[11] = 0x80;
  528 + s->icr[12] = 0x00;
  529 + s->icr[13] = 0x00;
  530 + s->imr = 0x3ffe;
  531 + s->rsr = 0x80;
  532 + s->swivr = 0x0f;
  533 + s->par = 0;
  534 +}
  535 +
  536 +static uint32_t m5206_mbar_read(m5206_mbar_state *s, uint32_t offset)
  537 +{
  538 + if (offset >= 0x100 && offset < 0x120) {
  539 + return m5206_timer_read(s->timer[0], offset - 0x100);
  540 + } else if (offset >= 0x120 && offset < 0x140) {
  541 + return m5206_timer_read(s->timer[1], offset - 0x120);
  542 + } else if (offset >= 0x140 && offset < 0x160) {
  543 + return m5206_uart_read(s->uart[0], offset - 0x140);
  544 + } else if (offset >= 0x180 && offset < 0x1a0) {
  545 + return m5206_uart_read(s->uart[1], offset - 0x180);
  546 + }
  547 + switch (offset) {
  548 + case 0x03: return s->scr;
  549 + case 0x14 ... 0x20: return s->icr[offset - 0x13];
  550 + case 0x36: return s->imr;
  551 + case 0x3a: return s->ipr;
  552 + case 0x40: return s->rsr;
  553 + case 0x41: return 0;
  554 + case 0x42: return s->swivr;
  555 + case 0x50:
  556 + /* DRAM mask register. */
  557 + /* FIXME: currently hardcoded to 128Mb. */
  558 + {
  559 + uint32_t mask = ~0;
  560 + while (mask > ram_size)
  561 + mask >>= 1;
  562 + return mask & 0x0ffe0000;
  563 + }
  564 + case 0x5c: return 1; /* DRAM bank 1 empty. */
  565 + case 0xcb: return s->par;
  566 + case 0x170: return s->uivr[0];
  567 + case 0x1b0: return s->uivr[1];
  568 + }
  569 + cpu_abort(cpu_single_env, "Bad MBAR read offset 0x%x", (int)offset);
  570 + return 0;
  571 +}
  572 +
  573 +static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset,
  574 + uint32_t value)
  575 +{
  576 + if (offset >= 0x100 && offset < 0x120) {
  577 + m5206_timer_write(s->timer[0], offset - 0x100, value);
  578 + return;
  579 + } else if (offset >= 0x120 && offset < 0x140) {
  580 + m5206_timer_write(s->timer[1], offset - 0x120, value);
  581 + return;
  582 + } else if (offset >= 0x140 && offset < 0x160) {
  583 + m5206_uart_write(s->uart[0], offset - 0x140, value);
  584 + return;
  585 + } else if (offset >= 0x180 && offset < 0x1a0) {
  586 + m5206_uart_write(s->uart[1], offset - 0x180, value);
  587 + return;
  588 + }
  589 + switch (offset) {
  590 + case 0x03:
  591 + s->scr = value;
  592 + break;
  593 + case 0x14 ... 0x20:
  594 + s->icr[offset - 0x13] = value;
  595 + m5206_mbar_update(s);
  596 + break;
  597 + case 0x36:
  598 + s->imr = value;
  599 + m5206_mbar_update(s);
  600 + break;
  601 + case 0x40:
  602 + s->rsr &= ~value;
  603 + break;
  604 + case 0x41:
  605 + /* TODO: implement watchdog. */
  606 + break;
  607 + case 0x42:
  608 + s->swivr = value;
  609 + break;
  610 + case 0xcb:
  611 + s->par = value;
  612 + break;
  613 + case 0x170:
  614 + s->uivr[0] = value;
  615 + break;
  616 + case 0x178: case 0x17c: case 0x1c8: case 0x1bc:
  617 + /* Not implemented: UART Output port bits. */
  618 + break;
  619 + case 0x1b0:
  620 + s->uivr[1] = value;
  621 + break;
  622 + default:
  623 + cpu_abort(cpu_single_env, "Bad MBAR write offset 0x%x", (int)offset);
  624 + break;
  625 + }
  626 +}
  627 +
  628 +/* Internal peripherals use a variety of register widths.
  629 + This lookup table allows a single routine to handle all of them. */
  630 +static const int m5206_mbar_width[] =
  631 +{
  632 + /* 000-040 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
  633 + /* 040-080 */ 1, 2, 2, 2, 4, 1, 2, 4, 1, 2, 4, 2, 2, 4, 2, 2,
  634 + /* 080-0c0 */ 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4,
  635 + /* 0c0-100 */ 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  636 + /* 100-140 */ 2, 2, 2, 2, 1, 0, 0, 0, 2, 2, 2, 2, 1, 0, 0, 0,
  637 + /* 140-180 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  638 + /* 180-1c0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  639 + /* 1c0-200 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  640 +};
  641 +
  642 +static uint32_t m5206_mbar_readw(void *opaque, target_phys_addr_t offset);
  643 +static uint32_t m5206_mbar_readl(void *opaque, target_phys_addr_t offset);
  644 +
  645 +static uint32_t m5206_mbar_readb(void *opaque, target_phys_addr_t offset)
  646 +{
  647 + m5206_mbar_state *s = (m5206_mbar_state *)opaque;
  648 + offset &= 0x3ff;
  649 + if (offset > 0x200) {
  650 + cpu_abort(cpu_single_env, "Bad MBAR read offset 0x%x", (int)offset);
  651 + }
  652 + if (m5206_mbar_width[offset >> 2] > 1) {
  653 + uint16_t val;
  654 + val = m5206_mbar_readw(opaque, offset & ~1);
  655 + if ((offset & 1) == 0) {
  656 + val >>= 8;
  657 + }
  658 + return val & 0xff;
  659 + }
  660 + return m5206_mbar_read(s, offset);
  661 +}
  662 +
  663 +static uint32_t m5206_mbar_readw(void *opaque, target_phys_addr_t offset)
  664 +{
  665 + m5206_mbar_state *s = (m5206_mbar_state *)opaque;
  666 + int width;
  667 + offset &= 0x3ff;
  668 + if (offset > 0x200) {
  669 + cpu_abort(cpu_single_env, "Bad MBAR read offset 0x%x", (int)offset);
  670 + }
  671 + width = m5206_mbar_width[offset >> 2];
  672 + if (width > 2) {
  673 + uint32_t val;
  674 + val = m5206_mbar_readl(opaque, offset & ~3);
  675 + if ((offset & 3) == 0)
  676 + val >>= 16;
  677 + return val & 0xffff;
  678 + } else if (width < 2) {
  679 + uint16_t val;
  680 + val = m5206_mbar_readb(opaque, offset) << 8;
  681 + val |= m5206_mbar_readb(opaque, offset + 1);
  682 + return val;
  683 + }
  684 + return m5206_mbar_read(s, offset);
  685 +}
  686 +
  687 +static uint32_t m5206_mbar_readl(void *opaque, target_phys_addr_t offset)
  688 +{
  689 + m5206_mbar_state *s = (m5206_mbar_state *)opaque;
  690 + int width;
  691 + offset &= 0x3ff;
  692 + if (offset > 0x200) {
  693 + cpu_abort(cpu_single_env, "Bad MBAR read offset 0x%x", (int)offset);
  694 + }
  695 + width = m5206_mbar_width[offset >> 2];
  696 + if (width < 4) {
  697 + uint32_t val;
  698 + val = m5206_mbar_readw(opaque, offset) << 16;
  699 + val |= m5206_mbar_readw(opaque, offset + 2);
  700 + return val;
  701 + }
  702 + return m5206_mbar_read(s, offset);
  703 +}
  704 +
  705 +static void m5206_mbar_writew(void *opaque, target_phys_addr_t offset,
  706 + uint32_t value);
  707 +static void m5206_mbar_writel(void *opaque, target_phys_addr_t offset,
  708 + uint32_t value);
  709 +
  710 +static void m5206_mbar_writeb(void *opaque, target_phys_addr_t offset,
  711 + uint32_t value)
  712 +{
  713 + m5206_mbar_state *s = (m5206_mbar_state *)opaque;
  714 + int width;
  715 + offset &= 0x3ff;
  716 + if (offset > 0x200) {
  717 + cpu_abort(cpu_single_env, "Bad MBAR write offset 0x%x", (int)offset);
  718 + }
  719 + width = m5206_mbar_width[offset >> 2];
  720 + if (width > 1) {
  721 + uint32_t tmp;
  722 + tmp = m5206_mbar_readw(opaque, offset & ~1);
  723 + if (offset & 1) {
  724 + tmp = (tmp & 0xff00) | value;
  725 + } else {
  726 + tmp = (tmp & 0x00ff) | (value << 8);
  727 + }
  728 + m5206_mbar_writew(opaque, offset & ~1, tmp);
  729 + return;
  730 + }
  731 + m5206_mbar_write(s, offset, value);
  732 +}
  733 +
  734 +static void m5206_mbar_writew(void *opaque, target_phys_addr_t offset,
  735 + uint32_t value)
  736 +{
  737 + m5206_mbar_state *s = (m5206_mbar_state *)opaque;
  738 + int width;
  739 + offset &= 0x3ff;
  740 + if (offset > 0x200) {
  741 + cpu_abort(cpu_single_env, "Bad MBAR write offset 0x%x", (int)offset);
  742 + }
  743 + width = m5206_mbar_width[offset >> 2];
  744 + if (width > 2) {
  745 + uint32_t tmp;
  746 + tmp = m5206_mbar_readl(opaque, offset & ~3);
  747 + if (offset & 3) {
  748 + tmp = (tmp & 0xffff0000) | value;
  749 + } else {
  750 + tmp = (tmp & 0x0000ffff) | (value << 16);
  751 + }
  752 + m5206_mbar_writel(opaque, offset & ~3, tmp);
  753 + return;
  754 + } else if (width < 2) {
  755 + m5206_mbar_writeb(opaque, offset, value >> 8);
  756 + m5206_mbar_writeb(opaque, offset + 1, value & 0xff);
  757 + return;
  758 + }
  759 + m5206_mbar_write(s, offset, value);
  760 +}
  761 +
  762 +static void m5206_mbar_writel(void *opaque, target_phys_addr_t offset,
  763 + uint32_t value)
  764 +{
  765 + m5206_mbar_state *s = (m5206_mbar_state *)opaque;
  766 + int width;
  767 + offset &= 0x3ff;
  768 + if (offset > 0x200) {
  769 + cpu_abort(cpu_single_env, "Bad MBAR write offset 0x%x", (int)offset);
  770 + }
  771 + width = m5206_mbar_width[offset >> 2];
  772 + if (width < 4) {
  773 + m5206_mbar_writew(opaque, offset, value >> 16);
  774 + m5206_mbar_writew(opaque, offset + 2, value & 0xffff);
  775 + return;
  776 + }
  777 + m5206_mbar_write(s, offset, value);
  778 +}
  779 +
  780 +static CPUReadMemoryFunc *m5206_mbar_readfn[] = {
  781 + m5206_mbar_readb,
  782 + m5206_mbar_readw,
  783 + m5206_mbar_readl
  784 +};
  785 +
  786 +static CPUWriteMemoryFunc *m5206_mbar_writefn[] = {
  787 + m5206_mbar_writeb,
  788 + m5206_mbar_writew,
  789 + m5206_mbar_writel
  790 +};
  791 +
  792 +qemu_irq *mcf5206_init(uint32_t base, CPUState *env)
  793 +{
  794 + m5206_mbar_state *s;
  795 + qemu_irq *pic;
  796 + int iomemtype;
  797 +
  798 + s = (m5206_mbar_state *)qemu_mallocz(sizeof(m5206_mbar_state));
  799 + iomemtype = cpu_register_io_memory(0, m5206_mbar_readfn,
  800 + m5206_mbar_writefn, s);
  801 + cpu_register_physical_memory(base, 0x00000fff, iomemtype);
  802 +
  803 + pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14);
  804 + s->timer[0] = m5206_timer_init(pic[9]);
  805 + s->timer[1] = m5206_timer_init(pic[10]);
  806 + s->uart[0] = m5206_uart_init(pic[12], serial_hds[0]);
  807 + s->uart[1] = m5206_uart_init(pic[13], serial_hds[1]);
  808 + s->env = env;
  809 +
  810 + m5206_mbar_reset(s);
  811 + return pic;
  812 +}
  813 +
linux-user/main.c
@@ -1977,13 +1977,12 @@ int main(int argc, char **argv) @@ -1977,13 +1977,12 @@ int main(int argc, char **argv)
1977 } 1977 }
1978 #elif defined(TARGET_M68K) 1978 #elif defined(TARGET_M68K)
1979 { 1979 {
1980 - m68k_def_t *def;  
1981 - def = m68k_find_by_name("cfv4e");  
1982 - if (def == NULL) { 1980 + if (cpu_model == NULL)
  1981 + cpu_model = "cfv4e";
  1982 + if (cpu_m68k_set_model(env, cpu_model)) {
1983 cpu_abort(cpu_single_env, 1983 cpu_abort(cpu_single_env,
1984 "Unable to find m68k CPU definition\n"); 1984 "Unable to find m68k CPU definition\n");
1985 } 1985 }
1986 - cpu_m68k_register(cpu_single_env, def);  
1987 env->pc = regs->pc; 1986 env->pc = regs->pc;
1988 env->dregs[0] = regs->d0; 1987 env->dregs[0] = regs->d0;
1989 env->dregs[1] = regs->d1; 1988 env->dregs[1] = regs->d1;
softmmu_header.h
@@ -65,6 +65,8 @@ @@ -65,6 +65,8 @@
65 #define CPU_MEM_INDEX ((env->sr & SR_MD) == 0) 65 #define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
66 #elif defined (TARGET_ALPHA) 66 #elif defined (TARGET_ALPHA)
67 #define CPU_MEM_INDEX ((env->ps >> 3) & 3) 67 #define CPU_MEM_INDEX ((env->ps >> 3) & 3)
  68 +#elif defined (TARGET_M68K)
  69 +#define CPU_MEM_INDEX ((env->sr & SR_S) == 0)
68 #else 70 #else
69 #error unsupported CPU 71 #error unsupported CPU
70 #endif 72 #endif
@@ -86,6 +88,8 @@ @@ -86,6 +88,8 @@
86 #define CPU_MEM_INDEX ((env->sr & SR_MD) == 0) 88 #define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
87 #elif defined (TARGET_ALPHA) 89 #elif defined (TARGET_ALPHA)
88 #define CPU_MEM_INDEX ((env->ps >> 3) & 3) 90 #define CPU_MEM_INDEX ((env->ps >> 3) & 3)
  91 +#elif defined (TARGET_M68K)
  92 +#define CPU_MEM_INDEX ((env->sr & SR_S) == 0)
89 #else 93 #else
90 #error unsupported CPU 94 #error unsupported CPU
91 #endif 95 #endif
target-m68k/cpu.h
1 /* 1 /*
2 * m68k virtual CPU header 2 * m68k virtual CPU header
3 * 3 *
4 - * Copyright (c) 2005-2006 CodeSourcery 4 + * Copyright (c) 2005-2007 CodeSourcery
5 * Written by Paul Brook 5 * Written by Paul Brook
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
@@ -50,6 +50,8 @@ @@ -50,6 +50,8 @@
50 #define EXCP_UNSUPPORTED 61 50 #define EXCP_UNSUPPORTED 61
51 #define EXCP_ICE 13 51 #define EXCP_ICE 13
52 52
  53 +#define EXCP_RTE 0x100
  54 +
53 typedef struct CPUM68KState { 55 typedef struct CPUM68KState {
54 uint32_t dregs[8]; 56 uint32_t dregs[8];
55 uint32_t aregs[8]; 57 uint32_t aregs[8];
@@ -76,6 +78,12 @@ typedef struct CPUM68KState { @@ -76,6 +78,12 @@ typedef struct CPUM68KState {
76 struct { 78 struct {
77 uint32_t ar; 79 uint32_t ar;
78 } mmu; 80 } mmu;
  81 +
  82 + /* Control registers. */
  83 + uint32_t vbr;
  84 + uint32_t mbar;
  85 + uint32_t rambar0;
  86 +
79 /* ??? remove this. */ 87 /* ??? remove this. */
80 uint32_t t1; 88 uint32_t t1;
81 89
@@ -84,7 +92,10 @@ typedef struct CPUM68KState { @@ -84,7 +92,10 @@ typedef struct CPUM68KState {
84 int exception_index; 92 int exception_index;
85 int interrupt_request; 93 int interrupt_request;
86 int user_mode_only; 94 int user_mode_only;
87 - uint32_t address; 95 + int halted;
  96 +
  97 + int pending_vector;
  98 + int pending_level;
88 99
89 uint32_t qregs[MAX_QREGS]; 100 uint32_t qregs[MAX_QREGS];
90 101
@@ -94,6 +105,7 @@ typedef struct CPUM68KState { @@ -94,6 +105,7 @@ typedef struct CPUM68KState {
94 CPUM68KState *cpu_m68k_init(void); 105 CPUM68KState *cpu_m68k_init(void);
95 int cpu_m68k_exec(CPUM68KState *s); 106 int cpu_m68k_exec(CPUM68KState *s);
96 void cpu_m68k_close(CPUM68KState *s); 107 void cpu_m68k_close(CPUM68KState *s);
  108 +void do_interrupt(int is_hw);
97 /* you can call this signal handler from your SIGBUS and SIGSEGV 109 /* you can call this signal handler from your SIGBUS and SIGSEGV
98 signal handlers to inform the virtual CPU of exceptions. non zero 110 signal handlers to inform the virtual CPU of exceptions. non zero
99 is returned if the signal was handled by the virtual CPU. */ 111 is returned if the signal was handled by the virtual CPU. */
@@ -120,12 +132,19 @@ enum { @@ -120,12 +132,19 @@ enum {
120 #define CCF_V 0x02 132 #define CCF_V 0x02
121 #define CCF_Z 0x04 133 #define CCF_Z 0x04
122 #define CCF_N 0x08 134 #define CCF_N 0x08
123 -#define CCF_X 0x01 135 +#define CCF_X 0x10
  136 +
  137 +#define SR_I_SHIFT 8
  138 +#define SR_I 0x0700
  139 +#define SR_M 0x1000
  140 +#define SR_S 0x2000
  141 +#define SR_T 0x8000
124 142
125 typedef struct m68k_def_t m68k_def_t; 143 typedef struct m68k_def_t m68k_def_t;
126 144
127 -m68k_def_t *m68k_find_by_name(const char *);  
128 -void cpu_m68k_register(CPUM68KState *, m68k_def_t *); 145 +int cpu_m68k_set_model(CPUM68KState *env, const char * name);
  146 +
  147 +void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector);
129 148
130 #define M68K_FPCR_PREC (1 << 6) 149 #define M68K_FPCR_PREC (1 << 6)
131 150
target-m68k/exec.h
@@ -40,8 +40,12 @@ static inline void regs_to_env(void) @@ -40,8 +40,12 @@ static inline void regs_to_env(void)
40 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw, 40 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
41 int is_user, int is_softmmu); 41 int is_user, int is_softmmu);
42 42
  43 +#if !defined(CONFIG_USER_ONLY)
  44 +#include "softmmu_exec.h"
  45 +#endif
43 46
44 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op); 47 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op);
45 float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1); 48 float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1);
  49 +void helper_movec(CPUM68KState *env, int reg, uint32_t val);
46 50
47 void cpu_loop_exit(void); 51 void cpu_loop_exit(void);
target-m68k/helper.c
1 /* 1 /*
2 * m68k op helpers 2 * m68k op helpers
3 * 3 *
4 - * Copyright (c) 2006 CodeSourcery 4 + * Copyright (c) 2006-2007 CodeSourcery
5 * Written by Paul Brook 5 * Written by Paul Brook
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
@@ -147,3 +147,65 @@ float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1) @@ -147,3 +147,65 @@ float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1)
147 } 147 }
148 return res; 148 return res;
149 } 149 }
  150 +
  151 +void helper_movec(CPUM68KState *env, int reg, uint32_t val)
  152 +{
  153 + switch (reg) {
  154 + case 0x02: /* CACR */
  155 + /* Ignored. */
  156 + break;
  157 + case 0x801: /* VBR */
  158 + env->vbr = val;
  159 + break;
  160 + /* TODO: Implement control registers. */
  161 + default:
  162 + cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
  163 + reg, val);
  164 + }
  165 +}
  166 +
  167 +/* MMU */
  168 +
  169 +/* TODO: This will need fixing once the MMU is implemented. */
  170 +target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
  171 +{
  172 + return addr;
  173 +}
  174 +
  175 +#if defined(CONFIG_USER_ONLY)
  176 +
  177 +int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
  178 + int is_user, int is_softmmu)
  179 +{
  180 + env->exception_index = EXCP_ACCESS;
  181 + env->mmu.ar = address;
  182 + return 1;
  183 +}
  184 +
  185 +#else
  186 +
  187 +int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
  188 + int is_user, int is_softmmu)
  189 +{
  190 + int prot;
  191 +
  192 + address &= TARGET_PAGE_MASK;
  193 + prot = PAGE_READ | PAGE_WRITE;
  194 + return tlb_set_page(env, address, address, prot, is_user, is_softmmu);
  195 +}
  196 +
  197 +/* Notify CPU of a pending interrupt. Prioritization and vectoring should
  198 + be handled by the interrupt controller. Real hardware only requests
  199 + the vector when the interrupt is acknowledged by the CPU. For
  200 + simplicitly we calculate it when the interrupt is signalled. */
  201 +void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
  202 +{
  203 + env->pending_level = level;
  204 + env->pending_vector = vector;
  205 + if (level)
  206 + cpu_interrupt(env, CPU_INTERRUPT_HARD);
  207 + else
  208 + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
  209 +}
  210 +
  211 +#endif
target-m68k/op-hacks.h
@@ -27,16 +27,38 @@ static inline int gen_im32(uint32_t i) @@ -27,16 +27,38 @@ static inline int gen_im32(uint32_t i)
27 return qreg; 27 return qreg;
28 } 28 }
29 29
30 -static inline void gen_op_ldf32(int dest, int addr) 30 +static inline void gen_op_ldf32_raw(int dest, int addr)
31 { 31 {
32 - gen_op_ld32(dest, addr); 32 + gen_op_ld32_raw(dest, addr);
33 } 33 }
34 34
35 -static inline void gen_op_stf32(int addr, int dest) 35 +static inline void gen_op_stf32_raw(int addr, int dest)
36 { 36 {
37 - gen_op_st32(addr, dest); 37 + gen_op_st32_raw(addr, dest);
38 } 38 }
39 39
  40 +#if !defined(CONFIG_USER_ONLY)
  41 +static inline void gen_op_ldf32_user(int dest, int addr)
  42 +{
  43 + gen_op_ld32_user(dest, addr);
  44 +}
  45 +
  46 +static inline void gen_op_stf32_user(int addr, int dest)
  47 +{
  48 + gen_op_st32_user(addr, dest);
  49 +}
  50 +
  51 +static inline void gen_op_ldf32_kernel(int dest, int addr)
  52 +{
  53 + gen_op_ld32_kernel(dest, addr);
  54 +}
  55 +
  56 +static inline void gen_op_stf32_kernel(int addr, int dest)
  57 +{
  58 + gen_op_st32_kernel(addr, dest);
  59 +}
  60 +#endif
  61 +
40 static inline void gen_op_pack_32_f32(int dest, int src) 62 static inline void gen_op_pack_32_f32(int dest, int src)
41 { 63 {
42 gen_op_mov32(dest, src); 64 gen_op_mov32(dest, src);
target-m68k/op.c
1 /* 1 /*
2 * m68k micro operations 2 * m68k micro operations
3 * 3 *
4 - * Copyright (c) 2006 CodeSourcery 4 + * Copyright (c) 2006-2007 CodeSourcery
5 * Written by Paul Brook 5 * Written by Paul Brook
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
@@ -86,7 +86,7 @@ void set_opf64(int qreg, float64 val) @@ -86,7 +86,7 @@ void set_opf64(int qreg, float64 val)
86 } 86 }
87 } 87 }
88 88
89 -#define OP(name) void OPPROTO op_##name (void) 89 +#define OP(name) void OPPROTO glue(op_,name) (void)
90 90
91 OP(mov32) 91 OP(mov32)
92 { 92 {
@@ -316,77 +316,6 @@ OP(ext16s32) @@ -316,77 +316,6 @@ OP(ext16s32)
316 FORCE_RET(); 316 FORCE_RET();
317 } 317 }
318 318
319 -/* Load/store ops. */  
320 -OP(ld8u32)  
321 -{  
322 - uint32_t addr = get_op(PARAM2);  
323 - set_op(PARAM1, ldub(addr));  
324 - FORCE_RET();  
325 -}  
326 -  
327 -OP(ld8s32)  
328 -{  
329 - uint32_t addr = get_op(PARAM2);  
330 - set_op(PARAM1, ldsb(addr));  
331 - FORCE_RET();  
332 -}  
333 -  
334 -OP(ld16u32)  
335 -{  
336 - uint32_t addr = get_op(PARAM2);  
337 - set_op(PARAM1, lduw(addr));  
338 - FORCE_RET();  
339 -}  
340 -  
341 -OP(ld16s32)  
342 -{  
343 - uint32_t addr = get_op(PARAM2);  
344 - set_op(PARAM1, ldsw(addr));  
345 - FORCE_RET();  
346 -}  
347 -  
348 -OP(ld32)  
349 -{  
350 - uint32_t addr = get_op(PARAM2);  
351 - set_op(PARAM1, ldl(addr));  
352 - FORCE_RET();  
353 -}  
354 -  
355 -OP(st8)  
356 -{  
357 - uint32_t addr = get_op(PARAM1);  
358 - stb(addr, get_op(PARAM2));  
359 - FORCE_RET();  
360 -}  
361 -  
362 -OP(st16)  
363 -{  
364 - uint32_t addr = get_op(PARAM1);  
365 - stw(addr, get_op(PARAM2));  
366 - FORCE_RET();  
367 -}  
368 -  
369 -OP(st32)  
370 -{  
371 - uint32_t addr = get_op(PARAM1);  
372 - stl(addr, get_op(PARAM2));  
373 - FORCE_RET();  
374 -}  
375 -  
376 -OP(ldf64)  
377 -{  
378 - uint32_t addr = get_op(PARAM2);  
379 - set_opf64(PARAM1, ldfq(addr));  
380 - FORCE_RET();  
381 -}  
382 -  
383 -OP(stf64)  
384 -{  
385 - uint32_t addr = get_op(PARAM1);  
386 - stfq(addr, get_opf64(PARAM2));  
387 - FORCE_RET();  
388 -}  
389 -  
390 OP(flush_flags) 319 OP(flush_flags)
391 { 320 {
392 int cc_op = PARAM1; 321 int cc_op = PARAM1;
@@ -454,6 +383,13 @@ OP(divs) @@ -454,6 +383,13 @@ OP(divs)
454 FORCE_RET(); 383 FORCE_RET();
455 } 384 }
456 385
  386 +OP(halt)
  387 +{
  388 + env->halted = 1;
  389 + RAISE_EXCEPTION(EXCP_HLT);
  390 + FORCE_RET();
  391 +}
  392 +
457 OP(raise_exception) 393 OP(raise_exception)
458 { 394 {
459 RAISE_EXCEPTION(PARAM1); 395 RAISE_EXCEPTION(PARAM1);
@@ -679,3 +615,22 @@ OP(compare_quietf64) @@ -679,3 +615,22 @@ OP(compare_quietf64)
679 set_op(PARAM1, float64_compare_quiet(op0, op1, &CPU_FP_STATUS)); 615 set_op(PARAM1, float64_compare_quiet(op0, op1, &CPU_FP_STATUS));
680 FORCE_RET(); 616 FORCE_RET();
681 } 617 }
  618 +
  619 +OP(movec)
  620 +{
  621 + int op1 = get_op(PARAM1);
  622 + uint32_t op2 = get_op(PARAM2);
  623 + helper_movec(env, op1, op2);
  624 +}
  625 +
  626 +/* Memory access. */
  627 +
  628 +#define MEMSUFFIX _raw
  629 +#include "op_mem.h"
  630 +
  631 +#if !defined(CONFIG_USER_ONLY)
  632 +#define MEMSUFFIX _user
  633 +#include "op_mem.h"
  634 +#define MEMSUFFIX _kernel
  635 +#include "op_mem.h"
  636 +#endif
target-m68k/op_helper.c 0 โ†’ 100644
  1 +/*
  2 + * M68K helper routines
  3 + *
  4 + * Copyright (c) 2007 CodeSourcery
  5 + *
  6 + * This library is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU Lesser General Public
  8 + * License as published by the Free Software Foundation; either
  9 + * version 2 of the License, or (at your option) any later version.
  10 + *
  11 + * This library is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 + * Lesser General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU Lesser General Public
  17 + * License along with this library; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 + */
  20 +#include "exec.h"
  21 +
  22 +#if defined(CONFIG_USER_ONLY)
  23 +
  24 +void do_interrupt(int is_hw)
  25 +{
  26 + env->exception_index = -1;
  27 +}
  28 +
  29 +#else
  30 +
  31 +#define MMUSUFFIX _mmu
  32 +#define GETPC() (__builtin_return_address(0))
  33 +
  34 +#define SHIFT 0
  35 +#include "softmmu_template.h"
  36 +
  37 +#define SHIFT 1
  38 +#include "softmmu_template.h"
  39 +
  40 +#define SHIFT 2
  41 +#include "softmmu_template.h"
  42 +
  43 +#define SHIFT 3
  44 +#include "softmmu_template.h"
  45 +
  46 +/* Try to fill the TLB and return an exception if error. If retaddr is
  47 + NULL, it means that the function was called in C code (i.e. not
  48 + from generated code or from helper.c) */
  49 +/* XXX: fix it to restore all registers */
  50 +void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
  51 +{
  52 + TranslationBlock *tb;
  53 + CPUState *saved_env;
  54 + target_phys_addr_t pc;
  55 + int ret;
  56 +
  57 + /* XXX: hack to restore env in all cases, even if not called from
  58 + generated code */
  59 + saved_env = env;
  60 + env = cpu_single_env;
  61 + ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, is_user, 1);
  62 + if (__builtin_expect(ret, 0)) {
  63 + if (retaddr) {
  64 + /* now we have a real cpu fault */
  65 + pc = (target_phys_addr_t)retaddr;
  66 + tb = tb_find_pc(pc);
  67 + if (tb) {
  68 + /* the PC is inside the translated code. It means that we have
  69 + a virtual CPU fault */
  70 + cpu_restore_state(tb, env, pc, NULL);
  71 + }
  72 + }
  73 + cpu_loop_exit();
  74 + }
  75 + env = saved_env;
  76 +}
  77 +
  78 +static void do_rte(void)
  79 +{
  80 + uint32_t sp;
  81 + uint32_t fmt;
  82 +
  83 + sp = env->aregs[7];
  84 + fmt = ldl_kernel(sp);
  85 + env->pc = ldl_kernel(sp + 4);
  86 + sp |= (fmt >> 28) & 3;
  87 + env->sr = fmt & 0xffff;
  88 + env->aregs[7] = sp + 8;
  89 +}
  90 +
  91 +void do_interrupt(int is_hw)
  92 +{
  93 + uint32_t sp;
  94 + uint32_t fmt;
  95 + uint32_t retaddr;
  96 + uint32_t vector;
  97 +
  98 + fmt = 0;
  99 + retaddr = env->pc;
  100 +
  101 + if (!is_hw) {
  102 + switch (env->exception_index) {
  103 + case EXCP_RTE:
  104 + /* Return from an exception. */
  105 + do_rte();
  106 + return;
  107 + }
  108 + if (env->exception_index >= EXCP_TRAP0
  109 + && env->exception_index <= EXCP_TRAP15) {
  110 + /* Move the PC after the trap instruction. */
  111 + retaddr += 2;
  112 + }
  113 + }
  114 +
  115 + /* TODO: Implement USP. */
  116 + sp = env->aregs[7];
  117 +
  118 + vector = env->exception_index << 2;
  119 +
  120 + fmt |= 0x40000000;
  121 + fmt |= (sp & 3) << 28;
  122 + fmt |= vector << 16;
  123 + fmt |= env->sr;
  124 +
  125 + /* ??? This could cause MMU faults. */
  126 + sp &= ~3;
  127 + sp -= 4;
  128 + stl_kernel(sp, retaddr);
  129 + sp -= 4;
  130 + stl_kernel(sp, fmt);
  131 + env->aregs[7] = sp;
  132 + env->sr |= SR_S;
  133 + if (is_hw) {
  134 + env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT);
  135 + }
  136 + /* Jump to vector. */
  137 + env->pc = ldl_kernel(env->vbr + vector);
  138 +}
  139 +
  140 +#endif
target-m68k/op_mem.h 0 โ†’ 100644
  1 +/* Load/store ops. */
  2 +#define MEM_LD_OP(name,suffix) \
  3 +OP(glue(glue(ld,name),MEMSUFFIX)) \
  4 +{ \
  5 + uint32_t addr = get_op(PARAM2); \
  6 + set_op(PARAM1, glue(glue(ld,suffix),MEMSUFFIX)(addr)); \
  7 + FORCE_RET(); \
  8 +}
  9 +
  10 +MEM_LD_OP(8u32,ub)
  11 +MEM_LD_OP(8s32,sb)
  12 +MEM_LD_OP(16u32,uw)
  13 +MEM_LD_OP(16s32,sw)
  14 +MEM_LD_OP(32,l)
  15 +
  16 +#undef MEM_LD_OP
  17 +
  18 +#define MEM_ST_OP(name,suffix) \
  19 +OP(glue(glue(st,name),MEMSUFFIX)) \
  20 +{ \
  21 + uint32_t addr = get_op(PARAM1); \
  22 + glue(glue(st,suffix),MEMSUFFIX)(addr, get_op(PARAM2)); \
  23 + FORCE_RET(); \
  24 +}
  25 +
  26 +MEM_ST_OP(8,b)
  27 +MEM_ST_OP(16,w)
  28 +MEM_ST_OP(32,l)
  29 +
  30 +#undef MEM_ST_OP
  31 +
  32 +OP(glue(ldf64,MEMSUFFIX))
  33 +{
  34 + uint32_t addr = get_op(PARAM2);
  35 + set_opf64(PARAM1, glue(ldfq,MEMSUFFIX)(addr));
  36 + FORCE_RET();
  37 +}
  38 +
  39 +OP(glue(stf64,MEMSUFFIX))
  40 +{
  41 + uint32_t addr = get_op(PARAM1);
  42 + glue(stfq,MEMSUFFIX)(addr, get_opf64(PARAM2));
  43 + FORCE_RET();
  44 +}
  45 +
  46 +#undef MEMSUFFIX
target-m68k/qregs.def
@@ -24,6 +24,7 @@ DEFF64(F6, fregs[6]) @@ -24,6 +24,7 @@ DEFF64(F6, fregs[6])
24 DEFF64(F7, fregs[7]) 24 DEFF64(F7, fregs[7])
25 DEFF64(FP_RESULT, fp_result) 25 DEFF64(FP_RESULT, fp_result)
26 DEFO32(PC, pc) 26 DEFO32(PC, pc)
  27 +DEFO32(SR, sr)
27 DEFO32(CC_OP, cc_op) 28 DEFO32(CC_OP, cc_op)
28 DEFR(T0, AREG1, QMODE_I32) 29 DEFR(T0, AREG1, QMODE_I32)
29 DEFO32(CC_DEST, cc_dest) 30 DEFO32(CC_DEST, cc_dest)
target-m68k/translate.c
1 /* 1 /*
2 * m68k translation 2 * m68k translation
3 * 3 *
4 - * Copyright (c) 2005-2006 CodeSourcery 4 + * Copyright (c) 2005-2007 CodeSourcery
5 * Written by Paul Brook 5 * Written by Paul Brook
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
@@ -30,6 +30,8 @@ @@ -30,6 +30,8 @@
30 #include "disas.h" 30 #include "disas.h"
31 #include "m68k-qreg.h" 31 #include "m68k-qreg.h"
32 32
  33 +//#define DEBUG_DISPATCH 1
  34 +
33 static inline void qemu_assert(int cond, const char *msg) 35 static inline void qemu_assert(int cond, const char *msg)
34 { 36 {
35 if (!cond) { 37 if (!cond) {
@@ -43,6 +45,7 @@ typedef struct DisasContext { @@ -43,6 +45,7 @@ typedef struct DisasContext {
43 target_ulong pc; 45 target_ulong pc;
44 int is_jmp; 46 int is_jmp;
45 int cc_op; 47 int cc_op;
  48 + int user;
46 uint32_t fpcr; 49 uint32_t fpcr;
47 struct TranslationBlock *tb; 50 struct TranslationBlock *tb;
48 int singlestep_enabled; 51 int singlestep_enabled;
@@ -50,6 +53,12 @@ typedef struct DisasContext { @@ -50,6 +53,12 @@ typedef struct DisasContext {
50 53
51 #define DISAS_JUMP_NEXT 4 54 #define DISAS_JUMP_NEXT 4
52 55
  56 +#if defined(CONFIG_USER_ONLY)
  57 +#define IS_USER(s) 1
  58 +#else
  59 +#define IS_USER(s) s->user
  60 +#endif
  61 +
53 /* XXX: move that elsewhere */ 62 /* XXX: move that elsewhere */
54 /* ??? Fix exceptions. */ 63 /* ??? Fix exceptions. */
55 static void *gen_throws_exception; 64 static void *gen_throws_exception;
@@ -68,6 +77,25 @@ enum { @@ -68,6 +77,25 @@ enum {
68 }; 77 };
69 78
70 #include "gen-op.h" 79 #include "gen-op.h"
  80 +
  81 +#if defined(CONFIG_USER_ONLY)
  82 +#define gen_st(s, name, addr, val) gen_op_st##name##_raw(addr, val)
  83 +#define gen_ld(s, name, val, addr) gen_op_ld##name##_raw(val, addr)
  84 +#else
  85 +#define gen_st(s, name, addr, val) do { \
  86 + if (IS_USER(s)) \
  87 + gen_op_st##name##_user(addr, val); \
  88 + else \
  89 + gen_op_st##name##_kernel(addr, val); \
  90 + } while (0)
  91 +#define gen_ld(s, name, val, addr) do { \
  92 + if (IS_USER(s)) \
  93 + gen_op_ld##name##_user(val, addr); \
  94 + else \
  95 + gen_op_ld##name##_kernel(val, addr); \
  96 + } while (0)
  97 +#endif
  98 +
71 #include "op-hacks.h" 99 #include "op-hacks.h"
72 100
73 #define OS_BYTE 0 101 #define OS_BYTE 0
@@ -101,40 +129,49 @@ static m68k_def_t m68k_cpu_defs[] = { @@ -101,40 +129,49 @@ static m68k_def_t m68k_cpu_defs[] = {
101 129
102 typedef void (*disas_proc)(DisasContext *, uint16_t); 130 typedef void (*disas_proc)(DisasContext *, uint16_t);
103 131
  132 +#ifdef DEBUG_DISPATCH
  133 +#define DISAS_INSN(name) \
  134 + static void real_disas_##name (DisasContext *s, uint16_t insn); \
  135 + static void disas_##name (DisasContext *s, uint16_t insn) { \
  136 + if (logfile) fprintf(logfile, "Dispatch " #name "\n"); \
  137 + real_disas_##name(s, insn); } \
  138 + static void real_disas_##name (DisasContext *s, uint16_t insn)
  139 +#else
104 #define DISAS_INSN(name) \ 140 #define DISAS_INSN(name) \
105 static void disas_##name (DisasContext *s, uint16_t insn) 141 static void disas_##name (DisasContext *s, uint16_t insn)
  142 +#endif
106 143
107 /* Generate a load from the specified address. Narrow values are 144 /* Generate a load from the specified address. Narrow values are
108 sign extended to full register width. */ 145 sign extended to full register width. */
109 -static inline int gen_load(int opsize, int addr, int sign) 146 +static inline int gen_load(DisasContext * s, int opsize, int addr, int sign)
110 { 147 {
111 int tmp; 148 int tmp;
112 switch(opsize) { 149 switch(opsize) {
113 case OS_BYTE: 150 case OS_BYTE:
114 tmp = gen_new_qreg(QMODE_I32); 151 tmp = gen_new_qreg(QMODE_I32);
115 if (sign) 152 if (sign)
116 - gen_op_ld8s32(tmp, addr); 153 + gen_ld(s, 8s32, tmp, addr);
117 else 154 else
118 - gen_op_ld8u32(tmp, addr); 155 + gen_ld(s, 8u32, tmp, addr);
119 break; 156 break;
120 case OS_WORD: 157 case OS_WORD:
121 tmp = gen_new_qreg(QMODE_I32); 158 tmp = gen_new_qreg(QMODE_I32);
122 if (sign) 159 if (sign)
123 - gen_op_ld16s32(tmp, addr); 160 + gen_ld(s, 16s32, tmp, addr);
124 else 161 else
125 - gen_op_ld16u32(tmp, addr); 162 + gen_ld(s, 16u32, tmp, addr);
126 break; 163 break;
127 case OS_LONG: 164 case OS_LONG:
128 tmp = gen_new_qreg(QMODE_I32); 165 tmp = gen_new_qreg(QMODE_I32);
129 - gen_op_ld32(tmp, addr); 166 + gen_ld(s, 32, tmp, addr);
130 break; 167 break;
131 case OS_SINGLE: 168 case OS_SINGLE:
132 tmp = gen_new_qreg(QMODE_F32); 169 tmp = gen_new_qreg(QMODE_F32);
133 - gen_op_ldf32(tmp, addr); 170 + gen_ld(s, f32, tmp, addr);
134 break; 171 break;
135 case OS_DOUBLE: 172 case OS_DOUBLE:
136 tmp = gen_new_qreg(QMODE_F64); 173 tmp = gen_new_qreg(QMODE_F64);
137 - gen_op_ldf64(tmp, addr); 174 + gen_ld(s, f64, tmp, addr);
138 break; 175 break;
139 default: 176 default:
140 qemu_assert(0, "bad load size"); 177 qemu_assert(0, "bad load size");
@@ -144,23 +181,23 @@ static inline int gen_load(int opsize, int addr, int sign) @@ -144,23 +181,23 @@ static inline int gen_load(int opsize, int addr, int sign)
144 } 181 }
145 182
146 /* Generate a store. */ 183 /* Generate a store. */
147 -static inline void gen_store(int opsize, int addr, int val) 184 +static inline void gen_store(DisasContext *s, int opsize, int addr, int val)
148 { 185 {
149 switch(opsize) { 186 switch(opsize) {
150 case OS_BYTE: 187 case OS_BYTE:
151 - gen_op_st8(addr, val); 188 + gen_st(s, 8, addr, val);
152 break; 189 break;
153 case OS_WORD: 190 case OS_WORD:
154 - gen_op_st16(addr, val); 191 + gen_st(s, 16, addr, val);
155 break; 192 break;
156 case OS_LONG: 193 case OS_LONG:
157 - gen_op_st32(addr, val); 194 + gen_st(s, 32, addr, val);
158 break; 195 break;
159 case OS_SINGLE: 196 case OS_SINGLE:
160 - gen_op_stf32(addr, val); 197 + gen_st(s, f32, addr, val);
161 break; 198 break;
162 case OS_DOUBLE: 199 case OS_DOUBLE:
163 - gen_op_stf64(addr, val); 200 + gen_st(s, f64, addr, val);
164 break; 201 break;
165 default: 202 default:
166 qemu_assert(0, "bad store size"); 203 qemu_assert(0, "bad store size");
@@ -170,13 +207,13 @@ static inline void gen_store(int opsize, int addr, int val) @@ -170,13 +207,13 @@ static inline void gen_store(int opsize, int addr, int val)
170 207
171 /* Generate an unsigned load if VAL is 0 a signed load if val is -1, 208 /* Generate an unsigned load if VAL is 0 a signed load if val is -1,
172 otherwise generate a store. */ 209 otherwise generate a store. */
173 -static int gen_ldst(int opsize, int addr, int val) 210 +static int gen_ldst(DisasContext *s, int opsize, int addr, int val)
174 { 211 {
175 if (val > 0) { 212 if (val > 0) {
176 - gen_store(opsize, addr, val); 213 + gen_store(s, opsize, addr, val);
177 return 0; 214 return 0;
178 } else { 215 } else {
179 - return gen_load(opsize, addr, val != 0); 216 + return gen_load(s, opsize, addr, val != 0);
180 } 217 }
181 } 218 }
182 219
@@ -191,7 +228,7 @@ static int gen_lea_indexed(DisasContext *s, int opsize, int base) @@ -191,7 +228,7 @@ static int gen_lea_indexed(DisasContext *s, int opsize, int base)
191 int tmp; 228 int tmp;
192 229
193 offset = s->pc; 230 offset = s->pc;
194 - ext = lduw(s->pc); 231 + ext = lduw_code(s->pc);
195 s->pc += 2; 232 s->pc += 2;
196 tmp = ((ext >> 12) & 7) + ((ext & 0x8000) ? QREG_A0 : QREG_D0); 233 tmp = ((ext >> 12) & 7) + ((ext & 0x8000) ? QREG_A0 : QREG_D0);
197 /* ??? Check W/L bit. */ 234 /* ??? Check W/L bit. */
@@ -216,9 +253,9 @@ static int gen_lea_indexed(DisasContext *s, int opsize, int base) @@ -216,9 +253,9 @@ static int gen_lea_indexed(DisasContext *s, int opsize, int base)
216 static inline uint32_t read_im32(DisasContext *s) 253 static inline uint32_t read_im32(DisasContext *s)
217 { 254 {
218 uint32_t im; 255 uint32_t im;
219 - im = ((uint32_t)lduw(s->pc)) << 16; 256 + im = ((uint32_t)lduw_code(s->pc)) << 16;
220 s->pc += 2; 257 s->pc += 2;
221 - im |= lduw(s->pc); 258 + im |= lduw_code(s->pc);
222 s->pc += 2; 259 s->pc += 2;
223 return im; 260 return im;
224 } 261 }
@@ -343,7 +380,7 @@ static int gen_lea(DisasContext *s, uint16_t insn, int opsize) @@ -343,7 +380,7 @@ static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
343 case 5: /* Indirect displacement. */ 380 case 5: /* Indirect displacement. */
344 reg += QREG_A0; 381 reg += QREG_A0;
345 tmp = gen_new_qreg(QMODE_I32); 382 tmp = gen_new_qreg(QMODE_I32);
346 - ext = lduw(s->pc); 383 + ext = lduw_code(s->pc);
347 s->pc += 2; 384 s->pc += 2;
348 gen_op_add32(tmp, reg, gen_im32((int16_t)ext)); 385 gen_op_add32(tmp, reg, gen_im32((int16_t)ext));
349 return tmp; 386 return tmp;
@@ -353,7 +390,7 @@ static int gen_lea(DisasContext *s, uint16_t insn, int opsize) @@ -353,7 +390,7 @@ static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
353 case 7: /* Other */ 390 case 7: /* Other */
354 switch (reg) { 391 switch (reg) {
355 case 0: /* Absolute short. */ 392 case 0: /* Absolute short. */
356 - offset = ldsw(s->pc); 393 + offset = ldsw_code(s->pc);
357 s->pc += 2; 394 s->pc += 2;
358 return gen_im32(offset); 395 return gen_im32(offset);
359 case 1: /* Absolute long. */ 396 case 1: /* Absolute long. */
@@ -362,7 +399,7 @@ static int gen_lea(DisasContext *s, uint16_t insn, int opsize) @@ -362,7 +399,7 @@ static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
362 case 2: /* pc displacement */ 399 case 2: /* pc displacement */
363 tmp = gen_new_qreg(QMODE_I32); 400 tmp = gen_new_qreg(QMODE_I32);
364 offset = s->pc; 401 offset = s->pc;
365 - offset += ldsw(s->pc); 402 + offset += ldsw_code(s->pc);
366 s->pc += 2; 403 s->pc += 2;
367 return gen_im32(offset); 404 return gen_im32(offset);
368 case 3: /* pc index+displacement. */ 405 case 3: /* pc index+displacement. */
@@ -391,7 +428,7 @@ static inline int gen_ea_once(DisasContext *s, uint16_t insn, int opsize, @@ -391,7 +428,7 @@ static inline int gen_ea_once(DisasContext *s, uint16_t insn, int opsize,
391 if (addrp) 428 if (addrp)
392 *addrp = tmp; 429 *addrp = tmp;
393 } 430 }
394 - return gen_ldst(opsize, tmp, val); 431 + return gen_ldst(s, opsize, tmp, val);
395 } 432 }
396 433
397 /* Generate code to load/store a value ito/from an EA. If VAL > 0 this is 434 /* Generate code to load/store a value ito/from an EA. If VAL > 0 this is
@@ -424,10 +461,10 @@ static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val, @@ -424,10 +461,10 @@ static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,
424 } 461 }
425 case 2: /* Indirect register */ 462 case 2: /* Indirect register */
426 reg += QREG_A0; 463 reg += QREG_A0;
427 - return gen_ldst(opsize, reg, val); 464 + return gen_ldst(s, opsize, reg, val);
428 case 3: /* Indirect postincrement. */ 465 case 3: /* Indirect postincrement. */
429 reg += QREG_A0; 466 reg += QREG_A0;
430 - result = gen_ldst(opsize, reg, val); 467 + result = gen_ldst(s, opsize, reg, val);
431 /* ??? This is not exception safe. The instruction may still 468 /* ??? This is not exception safe. The instruction may still
432 fault after this point. */ 469 fault after this point. */
433 if (val > 0 || !addrp) 470 if (val > 0 || !addrp)
@@ -443,7 +480,7 @@ static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val, @@ -443,7 +480,7 @@ static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,
443 if (addrp) 480 if (addrp)
444 *addrp = tmp; 481 *addrp = tmp;
445 } 482 }
446 - result = gen_ldst(opsize, tmp, val); 483 + result = gen_ldst(s, opsize, tmp, val);
447 /* ??? This is not exception safe. The instruction may still 484 /* ??? This is not exception safe. The instruction may still
448 fault after this point. */ 485 fault after this point. */
449 if (val > 0 || !addrp) { 486 if (val > 0 || !addrp) {
@@ -467,16 +504,16 @@ static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val, @@ -467,16 +504,16 @@ static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,
467 switch (opsize) { 504 switch (opsize) {
468 case OS_BYTE: 505 case OS_BYTE:
469 if (val) 506 if (val)
470 - offset = ldsb(s->pc + 1); 507 + offset = ldsb_code(s->pc + 1);
471 else 508 else
472 - offset = ldub(s->pc + 1); 509 + offset = ldub_code(s->pc + 1);
473 s->pc += 2; 510 s->pc += 2;
474 break; 511 break;
475 case OS_WORD: 512 case OS_WORD:
476 if (val) 513 if (val)
477 - offset = ldsw(s->pc); 514 + offset = ldsw_code(s->pc);
478 else 515 else
479 - offset = lduw(s->pc); 516 + offset = lduw_code(s->pc);
480 s->pc += 2; 517 s->pc += 2;
481 break; 518 break;
482 case OS_LONG: 519 case OS_LONG:
@@ -622,6 +659,14 @@ DISAS_INSN(scc) @@ -622,6 +659,14 @@ DISAS_INSN(scc)
622 gen_set_label(l1); 659 gen_set_label(l1);
623 } 660 }
624 661
  662 +/* Force a TB lookup after an instruction that changes the CPU state. */
  663 +static void gen_lookup_tb(DisasContext *s)
  664 +{
  665 + gen_flush_cc_op(s);
  666 + gen_op_mov32(QREG_PC, gen_im32(s->pc));
  667 + s->is_jmp = DISAS_UPDATE;
  668 +}
  669 +
625 /* Generate a jump to to the address in qreg DEST. */ 670 /* Generate a jump to to the address in qreg DEST. */
626 static void gen_jmp(DisasContext *s, int dest) 671 static void gen_jmp(DisasContext *s, int dest)
627 { 672 {
@@ -735,7 +780,7 @@ DISAS_INSN(divl) @@ -735,7 +780,7 @@ DISAS_INSN(divl)
735 int reg; 780 int reg;
736 uint16_t ext; 781 uint16_t ext;
737 782
738 - ext = lduw(s->pc); 783 + ext = lduw_code(s->pc);
739 s->pc += 2; 784 s->pc += 2;
740 if (ext & 0x87f8) { 785 if (ext & 0x87f8) {
741 gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); 786 gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
@@ -903,13 +948,13 @@ DISAS_INSN(sats) @@ -903,13 +948,13 @@ DISAS_INSN(sats)
903 gen_logic_cc(s, tmp); 948 gen_logic_cc(s, tmp);
904 } 949 }
905 950
906 -static void gen_push(int val) 951 +static void gen_push(DisasContext *s, int val)
907 { 952 {
908 int tmp; 953 int tmp;
909 954
910 tmp = gen_new_qreg(QMODE_I32); 955 tmp = gen_new_qreg(QMODE_I32);
911 gen_op_sub32(tmp, QREG_SP, gen_im32(4)); 956 gen_op_sub32(tmp, QREG_SP, gen_im32(4));
912 - gen_store(OS_LONG, tmp, val); 957 + gen_store(s, OS_LONG, tmp, val);
913 gen_op_mov32(QREG_SP, tmp); 958 gen_op_mov32(QREG_SP, tmp);
914 } 959 }
915 960
@@ -922,7 +967,7 @@ DISAS_INSN(movem) @@ -922,7 +967,7 @@ DISAS_INSN(movem)
922 int tmp; 967 int tmp;
923 int is_load; 968 int is_load;
924 969
925 - mask = lduw(s->pc); 970 + mask = lduw_code(s->pc);
926 s->pc += 2; 971 s->pc += 2;
927 tmp = gen_lea(s, insn, OS_LONG); 972 tmp = gen_lea(s, insn, OS_LONG);
928 addr = gen_new_qreg(QMODE_I32); 973 addr = gen_new_qreg(QMODE_I32);
@@ -935,10 +980,10 @@ DISAS_INSN(movem) @@ -935,10 +980,10 @@ DISAS_INSN(movem)
935 else 980 else
936 reg = AREG(i, 0); 981 reg = AREG(i, 0);
937 if (is_load) { 982 if (is_load) {
938 - tmp = gen_load(OS_LONG, addr, 0); 983 + tmp = gen_load(s, OS_LONG, addr, 0);
939 gen_op_mov32(reg, tmp); 984 gen_op_mov32(reg, tmp);
940 } else { 985 } else {
941 - gen_store(OS_LONG, addr, reg); 986 + gen_store(s, OS_LONG, addr, reg);
942 } 987 }
943 if (mask != 1) 988 if (mask != 1)
944 gen_op_add32(addr, addr, gen_im32(4)); 989 gen_op_add32(addr, addr, gen_im32(4));
@@ -963,7 +1008,7 @@ DISAS_INSN(bitop_im) @@ -963,7 +1008,7 @@ DISAS_INSN(bitop_im)
963 opsize = OS_LONG; 1008 opsize = OS_LONG;
964 op = (insn >> 6) & 3; 1009 op = (insn >> 6) & 3;
965 1010
966 - bitnum = lduw(s->pc); 1011 + bitnum = lduw_code(s->pc);
967 s->pc += 2; 1012 s->pc += 2;
968 if (bitnum & 0xff00) { 1013 if (bitnum & 0xff00) {
969 disas_undef(s, insn); 1014 disas_undef(s, insn);
@@ -1155,9 +1200,8 @@ DISAS_INSN(clr) @@ -1155,9 +1200,8 @@ DISAS_INSN(clr)
1155 gen_logic_cc(s, gen_im32(0)); 1200 gen_logic_cc(s, gen_im32(0));
1156 } 1201 }
1157 1202
1158 -DISAS_INSN(move_from_ccr) 1203 +static int gen_get_ccr(DisasContext *s)
1159 { 1204 {
1160 - int reg;  
1161 int dest; 1205 int dest;
1162 1206
1163 gen_flush_flags(s); 1207 gen_flush_flags(s);
@@ -1165,8 +1209,17 @@ DISAS_INSN(move_from_ccr) @@ -1165,8 +1209,17 @@ DISAS_INSN(move_from_ccr)
1165 gen_op_get_xflag(dest); 1209 gen_op_get_xflag(dest);
1166 gen_op_shl32(dest, dest, gen_im32(4)); 1210 gen_op_shl32(dest, dest, gen_im32(4));
1167 gen_op_or32(dest, dest, QREG_CC_DEST); 1211 gen_op_or32(dest, dest, QREG_CC_DEST);
  1212 + return dest;
  1213 +}
  1214 +
  1215 +DISAS_INSN(move_from_ccr)
  1216 +{
  1217 + int reg;
  1218 + int ccr;
  1219 +
  1220 + ccr = gen_get_ccr(s);
1168 reg = DREG(insn, 0); 1221 reg = DREG(insn, 0);
1169 - gen_partset_reg(OS_WORD, reg, dest); 1222 + gen_partset_reg(OS_WORD, reg, ccr);
1170 } 1223 }
1171 1224
1172 DISAS_INSN(neg) 1225 DISAS_INSN(neg)
@@ -1184,7 +1237,16 @@ DISAS_INSN(neg) @@ -1184,7 +1237,16 @@ DISAS_INSN(neg)
1184 s->cc_op = CC_OP_SUB; 1237 s->cc_op = CC_OP_SUB;
1185 } 1238 }
1186 1239
1187 -DISAS_INSN(move_to_ccr) 1240 +static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
  1241 +{
  1242 + gen_op_logic_cc(gen_im32(val & 0xf));
  1243 + gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4));
  1244 + if (!ccr_only) {
  1245 + gen_op_mov32(QREG_SR, gen_im32(val & 0xff00));
  1246 + }
  1247 +}
  1248 +
  1249 +static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only)
1188 { 1250 {
1189 int src1; 1251 int src1;
1190 int reg; 1252 int reg;
@@ -1199,19 +1261,26 @@ DISAS_INSN(move_to_ccr) @@ -1199,19 +1261,26 @@ DISAS_INSN(move_to_ccr)
1199 gen_op_shr32(src1, reg, gen_im32(4)); 1261 gen_op_shr32(src1, reg, gen_im32(4));
1200 gen_op_and32(src1, src1, gen_im32(1)); 1262 gen_op_and32(src1, src1, gen_im32(1));
1201 gen_op_update_xflag_tst(src1); 1263 gen_op_update_xflag_tst(src1);
  1264 + if (!ccr_only) {
  1265 + gen_op_and32(QREG_SR, reg, gen_im32(0xff00));
  1266 + }
1202 } 1267 }
1203 - else if ((insn & 0x3f) != 0x3c) 1268 + else if ((insn & 0x3f) == 0x3c)
1204 { 1269 {
1205 - uint8_t val;  
1206 - val = ldsb(s->pc); 1270 + uint16_t val;
  1271 + val = lduw_code(s->pc);
1207 s->pc += 2; 1272 s->pc += 2;
1208 - gen_op_logic_cc(gen_im32(val & 0xf));  
1209 - gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4)); 1273 + gen_set_sr_im(s, val, ccr_only);
1210 } 1274 }
1211 else 1275 else
1212 disas_undef(s, insn); 1276 disas_undef(s, insn);
1213 } 1277 }
1214 1278
  1279 +DISAS_INSN(move_to_ccr)
  1280 +{
  1281 + gen_set_sr(s, insn, 1);
  1282 +}
  1283 +
1215 DISAS_INSN(not) 1284 DISAS_INSN(not)
1216 { 1285 {
1217 int reg; 1286 int reg;
@@ -1244,7 +1313,7 @@ DISAS_INSN(pea) @@ -1244,7 +1313,7 @@ DISAS_INSN(pea)
1244 int tmp; 1313 int tmp;
1245 1314
1246 tmp = gen_lea(s, insn, OS_LONG); 1315 tmp = gen_lea(s, insn, OS_LONG);
1247 - gen_push(tmp); 1316 + gen_push(s, tmp);
1248 } 1317 }
1249 1318
1250 DISAS_INSN(ext) 1319 DISAS_INSN(ext)
@@ -1322,7 +1391,7 @@ DISAS_INSN(mull) @@ -1322,7 +1391,7 @@ DISAS_INSN(mull)
1322 1391
1323 /* The upper 32 bits of the product are discarded, so 1392 /* The upper 32 bits of the product are discarded, so
1324 muls.l and mulu.l are functionally equivalent. */ 1393 muls.l and mulu.l are functionally equivalent. */
1325 - ext = lduw(s->pc); 1394 + ext = lduw_code(s->pc);
1326 s->pc += 2; 1395 s->pc += 2;
1327 if (ext & 0x87ff) { 1396 if (ext & 0x87ff) {
1328 gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED); 1397 gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
@@ -1343,12 +1412,12 @@ DISAS_INSN(link) @@ -1343,12 +1412,12 @@ DISAS_INSN(link)
1343 int reg; 1412 int reg;
1344 int tmp; 1413 int tmp;
1345 1414
1346 - offset = ldsw(s->pc); 1415 + offset = ldsw_code(s->pc);
1347 s->pc += 2; 1416 s->pc += 2;
1348 reg = AREG(insn, 0); 1417 reg = AREG(insn, 0);
1349 tmp = gen_new_qreg(QMODE_I32); 1418 tmp = gen_new_qreg(QMODE_I32);
1350 gen_op_sub32(tmp, QREG_SP, gen_im32(4)); 1419 gen_op_sub32(tmp, QREG_SP, gen_im32(4));
1351 - gen_store(OS_LONG, tmp, reg); 1420 + gen_store(s, OS_LONG, tmp, reg);
1352 if (reg != QREG_SP) 1421 if (reg != QREG_SP)
1353 gen_op_mov32(reg, tmp); 1422 gen_op_mov32(reg, tmp);
1354 gen_op_add32(QREG_SP, tmp, gen_im32(offset)); 1423 gen_op_add32(QREG_SP, tmp, gen_im32(offset));
@@ -1363,7 +1432,7 @@ DISAS_INSN(unlk) @@ -1363,7 +1432,7 @@ DISAS_INSN(unlk)
1363 src = gen_new_qreg(QMODE_I32); 1432 src = gen_new_qreg(QMODE_I32);
1364 reg = AREG(insn, 0); 1433 reg = AREG(insn, 0);
1365 gen_op_mov32(src, reg); 1434 gen_op_mov32(src, reg);
1366 - tmp = gen_load(OS_LONG, src, 0); 1435 + tmp = gen_load(s, OS_LONG, src, 0);
1367 gen_op_mov32(reg, tmp); 1436 gen_op_mov32(reg, tmp);
1368 gen_op_add32(QREG_SP, src, gen_im32(4)); 1437 gen_op_add32(QREG_SP, src, gen_im32(4));
1369 } 1438 }
@@ -1376,7 +1445,7 @@ DISAS_INSN(rts) @@ -1376,7 +1445,7 @@ DISAS_INSN(rts)
1376 { 1445 {
1377 int tmp; 1446 int tmp;
1378 1447
1379 - tmp = gen_load(OS_LONG, QREG_SP, 0); 1448 + tmp = gen_load(s, OS_LONG, QREG_SP, 0);
1380 gen_op_add32(QREG_SP, QREG_SP, gen_im32(4)); 1449 gen_op_add32(QREG_SP, QREG_SP, gen_im32(4));
1381 gen_jmp(s, tmp); 1450 gen_jmp(s, tmp);
1382 } 1451 }
@@ -1390,7 +1459,7 @@ DISAS_INSN(jump) @@ -1390,7 +1459,7 @@ DISAS_INSN(jump)
1390 tmp = gen_lea(s, insn, OS_LONG); 1459 tmp = gen_lea(s, insn, OS_LONG);
1391 if ((insn & 0x40) == 0) { 1460 if ((insn & 0x40) == 0) {
1392 /* jsr */ 1461 /* jsr */
1393 - gen_push(gen_im32(s->pc)); 1462 + gen_push(s, gen_im32(s->pc));
1394 } 1463 }
1395 gen_jmp(s, tmp); 1464 gen_jmp(s, tmp);
1396 } 1465 }
@@ -1460,14 +1529,14 @@ DISAS_INSN(branch) @@ -1460,14 +1529,14 @@ DISAS_INSN(branch)
1460 op = (insn >> 8) & 0xf; 1529 op = (insn >> 8) & 0xf;
1461 offset = (int8_t)insn; 1530 offset = (int8_t)insn;
1462 if (offset == 0) { 1531 if (offset == 0) {
1463 - offset = ldsw(s->pc); 1532 + offset = ldsw_code(s->pc);
1464 s->pc += 2; 1533 s->pc += 2;
1465 } else if (offset == -1) { 1534 } else if (offset == -1) {
1466 offset = read_im32(s); 1535 offset = read_im32(s);
1467 } 1536 }
1468 if (op == 1) { 1537 if (op == 1) {
1469 /* bsr */ 1538 /* bsr */
1470 - gen_push(gen_im32(s->pc)); 1539 + gen_push(s, gen_im32(s->pc));
1471 } 1540 }
1472 gen_flush_cc_op(s); 1541 gen_flush_cc_op(s);
1473 if (op > 1) { 1542 if (op > 1) {
@@ -1752,68 +1821,154 @@ DISAS_INSN(ff1) @@ -1752,68 +1821,154 @@ DISAS_INSN(ff1)
1752 cpu_abort(NULL, "Unimplemented insn: ff1"); 1821 cpu_abort(NULL, "Unimplemented insn: ff1");
1753 } 1822 }
1754 1823
  1824 +static int gen_get_sr(DisasContext *s)
  1825 +{
  1826 + int ccr;
  1827 + int sr;
  1828 +
  1829 + ccr = gen_get_ccr(s);
  1830 + sr = gen_new_qreg(QMODE_I32);
  1831 + gen_op_and32(sr, QREG_SR, gen_im32(0xffe0));
  1832 + gen_op_or32(sr, sr, ccr);
  1833 + return sr;
  1834 +}
  1835 +
1755 DISAS_INSN(strldsr) 1836 DISAS_INSN(strldsr)
1756 { 1837 {
1757 uint16_t ext; 1838 uint16_t ext;
1758 uint32_t addr; 1839 uint32_t addr;
1759 1840
1760 addr = s->pc - 2; 1841 addr = s->pc - 2;
1761 - ext = lduw(s->pc); 1842 + ext = lduw_code(s->pc);
1762 s->pc += 2; 1843 s->pc += 2;
1763 - if (ext != 0x46FC) 1844 + if (ext != 0x46FC) {
1764 gen_exception(s, addr, EXCP_UNSUPPORTED); 1845 gen_exception(s, addr, EXCP_UNSUPPORTED);
1765 - else 1846 + return;
  1847 + }
  1848 + ext = lduw_code(s->pc);
  1849 + s->pc += 2;
  1850 + if (IS_USER(s) || (ext & SR_S) == 0) {
1766 gen_exception(s, addr, EXCP_PRIVILEGE); 1851 gen_exception(s, addr, EXCP_PRIVILEGE);
  1852 + return;
  1853 + }
  1854 + gen_push(s, gen_get_sr(s));
  1855 + gen_set_sr_im(s, ext, 0);
1767 } 1856 }
1768 1857
1769 DISAS_INSN(move_from_sr) 1858 DISAS_INSN(move_from_sr)
1770 { 1859 {
1771 - gen_exception(s, s->pc - 2, EXCP_PRIVILEGE); 1860 + int reg;
  1861 + int sr;
  1862 +
  1863 + if (IS_USER(s)) {
  1864 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1865 + return;
  1866 + }
  1867 + sr = gen_get_sr(s);
  1868 + reg = DREG(insn, 0);
  1869 + gen_partset_reg(OS_WORD, reg, sr);
1772 } 1870 }
1773 1871
1774 DISAS_INSN(move_to_sr) 1872 DISAS_INSN(move_to_sr)
1775 { 1873 {
1776 - gen_exception(s, s->pc - 2, EXCP_PRIVILEGE); 1874 + if (IS_USER(s)) {
  1875 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1876 + return;
  1877 + }
  1878 + gen_set_sr(s, insn, 0);
  1879 + gen_lookup_tb(s);
1777 } 1880 }
1778 1881
1779 DISAS_INSN(move_from_usp) 1882 DISAS_INSN(move_from_usp)
1780 { 1883 {
1781 - gen_exception(s, s->pc - 2, EXCP_PRIVILEGE); 1884 + if (IS_USER(s)) {
  1885 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1886 + return;
  1887 + }
  1888 + /* TODO: Implement USP. */
  1889 + gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1782 } 1890 }
1783 1891
1784 DISAS_INSN(move_to_usp) 1892 DISAS_INSN(move_to_usp)
1785 { 1893 {
1786 - gen_exception(s, s->pc - 2, EXCP_PRIVILEGE); 1894 + if (IS_USER(s)) {
  1895 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1896 + return;
  1897 + }
  1898 + /* TODO: Implement USP. */
  1899 + gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1787 } 1900 }
1788 1901
1789 DISAS_INSN(halt) 1902 DISAS_INSN(halt)
1790 { 1903 {
1791 - gen_exception(s, s->pc, EXCP_HLT); 1904 + gen_flush_cc_op(s);
  1905 + gen_jmp(s, gen_im32(s->pc));
  1906 + gen_op_halt();
1792 } 1907 }
1793 1908
1794 DISAS_INSN(stop) 1909 DISAS_INSN(stop)
1795 { 1910 {
1796 - gen_exception(s, s->pc - 2, EXCP_PRIVILEGE); 1911 + uint16_t ext;
  1912 +
  1913 + if (IS_USER(s)) {
  1914 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1915 + return;
  1916 + }
  1917 +
  1918 + ext = lduw_code(s->pc);
  1919 + s->pc += 2;
  1920 +
  1921 + gen_set_sr_im(s, ext, 0);
  1922 + disas_halt(s, insn);
1797 } 1923 }
1798 1924
1799 DISAS_INSN(rte) 1925 DISAS_INSN(rte)
1800 { 1926 {
1801 - gen_exception(s, s->pc - 2, EXCP_PRIVILEGE); 1927 + if (IS_USER(s)) {
  1928 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1929 + return;
  1930 + }
  1931 + gen_exception(s, s->pc - 2, EXCP_RTE);
1802 } 1932 }
1803 1933
1804 DISAS_INSN(movec) 1934 DISAS_INSN(movec)
1805 { 1935 {
1806 - gen_exception(s, s->pc - 2, EXCP_PRIVILEGE); 1936 + uint16_t ext;
  1937 + int reg;
  1938 +
  1939 + if (IS_USER(s)) {
  1940 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1941 + return;
  1942 + }
  1943 +
  1944 + ext = lduw_code(s->pc);
  1945 + s->pc += 2;
  1946 +
  1947 + if (ext & 0x8000) {
  1948 + reg = AREG(ext, 12);
  1949 + } else {
  1950 + reg = DREG(ext, 12);
  1951 + }
  1952 + gen_op_movec(gen_im32(ext & 0xfff), reg);
  1953 + gen_lookup_tb(s);
1807 } 1954 }
1808 1955
1809 DISAS_INSN(intouch) 1956 DISAS_INSN(intouch)
1810 { 1957 {
1811 - gen_exception(s, s->pc - 2, EXCP_PRIVILEGE); 1958 + if (IS_USER(s)) {
  1959 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1960 + return;
  1961 + }
  1962 + /* ICache fetch. Implement as no-op. */
1812 } 1963 }
1813 1964
1814 DISAS_INSN(cpushl) 1965 DISAS_INSN(cpushl)
1815 { 1966 {
1816 - gen_exception(s, s->pc - 2, EXCP_PRIVILEGE); 1967 + if (IS_USER(s)) {
  1968 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1969 + return;
  1970 + }
  1971 + /* Cache push/invalidate. Implement as no-op. */
1817 } 1972 }
1818 1973
1819 DISAS_INSN(wddata) 1974 DISAS_INSN(wddata)
@@ -1823,7 +1978,12 @@ DISAS_INSN(wddata) @@ -1823,7 +1978,12 @@ DISAS_INSN(wddata)
1823 1978
1824 DISAS_INSN(wdebug) 1979 DISAS_INSN(wdebug)
1825 { 1980 {
1826 - gen_exception(s, s->pc - 2, EXCP_PRIVILEGE); 1981 + if (IS_USER(s)) {
  1982 + gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
  1983 + return;
  1984 + }
  1985 + /* TODO: Implement wdebug. */
  1986 + qemu_assert(0, "WDEBUG not implemented");
1827 } 1987 }
1828 1988
1829 DISAS_INSN(trap) 1989 DISAS_INSN(trap)
@@ -1843,7 +2003,7 @@ DISAS_INSN(fpu) @@ -1843,7 +2003,7 @@ DISAS_INSN(fpu)
1843 int round; 2003 int round;
1844 int opsize; 2004 int opsize;
1845 2005
1846 - ext = lduw(s->pc); 2006 + ext = lduw_code(s->pc);
1847 s->pc += 2; 2007 s->pc += 2;
1848 opmode = ext & 0x7f; 2008 opmode = ext & 0x7f;
1849 switch ((ext >> 13) & 7) { 2009 switch ((ext >> 13) & 7) {
@@ -1928,10 +2088,10 @@ DISAS_INSN(fpu) @@ -1928,10 +2088,10 @@ DISAS_INSN(fpu)
1928 if (ext & mask) { 2088 if (ext & mask) {
1929 if (ext & (1 << 13)) { 2089 if (ext & (1 << 13)) {
1930 /* store */ 2090 /* store */
1931 - gen_op_stf64(addr, dest); 2091 + gen_st(s, f64, addr, dest);
1932 } else { 2092 } else {
1933 /* load */ 2093 /* load */
1934 - gen_op_ldf64(dest, addr); 2094 + gen_ld(s, f64, dest, addr);
1935 } 2095 }
1936 if (ext & (mask - 1)) 2096 if (ext & (mask - 1))
1937 gen_op_add32(addr, addr, gen_im32(8)); 2097 gen_op_add32(addr, addr, gen_im32(8));
@@ -2060,10 +2220,10 @@ DISAS_INSN(fbcc) @@ -2060,10 +2220,10 @@ DISAS_INSN(fbcc)
2060 int l1; 2220 int l1;
2061 2221
2062 addr = s->pc; 2222 addr = s->pc;
2063 - offset = ldsw(s->pc); 2223 + offset = ldsw_code(s->pc);
2064 s->pc += 2; 2224 s->pc += 2;
2065 if (insn & (1 << 6)) { 2225 if (insn & (1 << 6)) {
2066 - offset = (offset << 16) | lduw(s->pc); 2226 + offset = (offset << 16) | lduw_code(s->pc);
2067 s->pc += 2; 2227 s->pc += 2;
2068 } 2228 }
2069 2229
@@ -2143,6 +2303,18 @@ DISAS_INSN(fbcc) @@ -2143,6 +2303,18 @@ DISAS_INSN(fbcc)
2143 gen_jmp_tb(s, 1, addr + offset); 2303 gen_jmp_tb(s, 1, addr + offset);
2144 } 2304 }
2145 2305
  2306 +DISAS_INSN(frestore)
  2307 +{
  2308 + /* TODO: Implement frestore. */
  2309 + qemu_assert(0, "FRESTORE not implemented");
  2310 +}
  2311 +
  2312 +DISAS_INSN(fsave)
  2313 +{
  2314 + /* TODO: Implement fsave. */
  2315 + qemu_assert(0, "FSAVE not implemented");
  2316 +}
  2317 +
2146 static disas_proc opcode_table[65536]; 2318 static disas_proc opcode_table[65536];
2147 2319
2148 static void 2320 static void
@@ -2168,11 +2340,10 @@ register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask) @@ -2168,11 +2340,10 @@ register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
2168 i <<= 1; 2340 i <<= 1;
2169 from = opcode & ~(i - 1); 2341 from = opcode & ~(i - 1);
2170 to = from + i; 2342 to = from + i;
2171 - for (i = from; i < to; i++)  
2172 - { 2343 + for (i = from; i < to; i++) {
2173 if ((i & mask) == opcode) 2344 if ((i & mask) == opcode)
2174 opcode_table[i] = proc; 2345 opcode_table[i] = proc;
2175 - } 2346 + }
2176 } 2347 }
2177 2348
2178 /* Register m68k opcode handlers. Order is important. 2349 /* Register m68k opcode handlers. Order is important.
@@ -2274,6 +2445,8 @@ register_m68k_insns (m68k_def_t *def) @@ -2274,6 +2445,8 @@ register_m68k_insns (m68k_def_t *def)
2274 INSN(undef_fpu, f000, f000, CF_A); 2445 INSN(undef_fpu, f000, f000, CF_A);
2275 INSN(fpu, f200, ffc0, CF_FPU); 2446 INSN(fpu, f200, ffc0, CF_FPU);
2276 INSN(fbcc, f280, ffc0, CF_FPU); 2447 INSN(fbcc, f280, ffc0, CF_FPU);
  2448 + INSN(frestore, f340, ffc0, CF_FPU);
  2449 + INSN(fsave, f340, ffc0, CF_FPU);
2277 INSN(intouch, f340, ffc0, CF_A); 2450 INSN(intouch, f340, ffc0, CF_A);
2278 INSN(cpushl, f428, ff38, CF_A); 2451 INSN(cpushl, f428, ff38, CF_A);
2279 INSN(wddata, fb00, ff00, CF_A); 2452 INSN(wddata, fb00, ff00, CF_A);
@@ -2287,7 +2460,7 @@ static void disas_m68k_insn(CPUState * env, DisasContext *s) @@ -2287,7 +2460,7 @@ static void disas_m68k_insn(CPUState * env, DisasContext *s)
2287 { 2460 {
2288 uint16_t insn; 2461 uint16_t insn;
2289 2462
2290 - insn = lduw(s->pc); 2463 + insn = lduw_code(s->pc);
2291 s->pc += 2; 2464 s->pc += 2;
2292 2465
2293 opcode_table[insn](s, insn); 2466 opcode_table[insn](s, insn);
@@ -2576,6 +2749,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, @@ -2576,6 +2749,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2576 dc->cc_op = CC_OP_DYNAMIC; 2749 dc->cc_op = CC_OP_DYNAMIC;
2577 dc->singlestep_enabled = env->singlestep_enabled; 2750 dc->singlestep_enabled = env->singlestep_enabled;
2578 dc->fpcr = env->fpcr; 2751 dc->fpcr = env->fpcr;
  2752 + dc->user = (env->sr & SR_S) == 0;
2579 nb_gen_labels = 0; 2753 nb_gen_labels = 0;
2580 lj = -1; 2754 lj = -1;
2581 do { 2755 do {
@@ -2675,6 +2849,19 @@ int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) @@ -2675,6 +2849,19 @@ int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2675 return gen_intermediate_code_internal(env, tb, 1); 2849 return gen_intermediate_code_internal(env, tb, 1);
2676 } 2850 }
2677 2851
  2852 +void cpu_reset(CPUM68KState *env)
  2853 +{
  2854 + memset(env, 0, offsetof(CPUM68KState, breakpoints));
  2855 +#if !defined (CONFIG_USER_ONLY)
  2856 + env->sr = 0x2700;
  2857 +#endif
  2858 + /* ??? FP regs should be initialized to NaN. */
  2859 + env->cc_op = CC_OP_FLAGS;
  2860 + /* TODO: We should set PC from the interrupt vector. */
  2861 + env->pc = 0;
  2862 + tlb_flush(env, 1);
  2863 +}
  2864 +
2678 CPUM68KState *cpu_m68k_init(void) 2865 CPUM68KState *cpu_m68k_init(void)
2679 { 2866 {
2680 CPUM68KState *env; 2867 CPUM68KState *env;
@@ -2684,10 +2871,7 @@ CPUM68KState *cpu_m68k_init(void) @@ -2684,10 +2871,7 @@ CPUM68KState *cpu_m68k_init(void)
2684 return NULL; 2871 return NULL;
2685 cpu_exec_init(env); 2872 cpu_exec_init(env);
2686 2873
2687 - memset(env, 0, sizeof(CPUM68KState));  
2688 - /* ??? FP regs should be initialized to NaN. */  
2689 - cpu_single_env = env;  
2690 - env->cc_op = CC_OP_FLAGS; 2874 + cpu_reset(env);
2691 return env; 2875 return env;
2692 } 2876 }
2693 2877
@@ -2696,23 +2880,20 @@ void cpu_m68k_close(CPUM68KState *env) @@ -2696,23 +2880,20 @@ void cpu_m68k_close(CPUM68KState *env)
2696 free(env); 2880 free(env);
2697 } 2881 }
2698 2882
2699 -m68k_def_t *m68k_find_by_name(const char *name) 2883 +int cpu_m68k_set_model(CPUM68KState *env, const char * name)
2700 { 2884 {
2701 m68k_def_t *def; 2885 m68k_def_t *def;
2702 2886
2703 - def = m68k_cpu_defs;  
2704 - while (def->name)  
2705 - { 2887 + for (def = m68k_cpu_defs; def->name; def++) {
2706 if (strcmp(def->name, name) == 0) 2888 if (strcmp(def->name, name) == 0)
2707 - return def;  
2708 - def++;  
2709 - }  
2710 - return NULL;  
2711 -} 2889 + break;
  2890 + }
  2891 + if (!def->name)
  2892 + return 1;
2712 2893
2713 -void cpu_m68k_register(CPUM68KState *env, m68k_def_t *def)  
2714 -{  
2715 register_m68k_insns(def); 2894 register_m68k_insns(def);
  2895 +
  2896 + return 0;
2716 } 2897 }
2717 2898
2718 void cpu_dump_state(CPUState *env, FILE *f, 2899 void cpu_dump_state(CPUState *env, FILE *f,
@@ -2737,24 +2918,3 @@ void cpu_dump_state(CPUState *env, FILE *f, @@ -2737,24 +2918,3 @@ void cpu_dump_state(CPUState *env, FILE *f,
2737 cpu_fprintf (f, "FPRESULT = %12g\n", env->fp_result); 2918 cpu_fprintf (f, "FPRESULT = %12g\n", env->fp_result);
2738 } 2919 }
2739 2920
2740 -/* ??? */  
2741 -target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)  
2742 -{  
2743 - return addr;  
2744 -}  
2745 -  
2746 -#if defined(CONFIG_USER_ONLY)  
2747 -  
2748 -int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,  
2749 - int is_user, int is_softmmu)  
2750 -{  
2751 - env->exception_index = EXCP_ACCESS;  
2752 - env->mmu.ar = address;  
2753 - return 1;  
2754 -}  
2755 -  
2756 -#else  
2757 -  
2758 -#error not implemented  
2759 -  
2760 -#endif  
@@ -6833,6 +6833,8 @@ void register_machines(void) @@ -6833,6 +6833,8 @@ void register_machines(void)
6833 qemu_register_machine(&shix_machine); 6833 qemu_register_machine(&shix_machine);
6834 #elif defined(TARGET_ALPHA) 6834 #elif defined(TARGET_ALPHA)
6835 /* XXX: TODO */ 6835 /* XXX: TODO */
  6836 +#elif defined(TARGET_M68K)
  6837 + qemu_register_machine(&an5206_machine);
6836 #else 6838 #else
6837 #error unsupported CPU 6839 #error unsupported CPU
6838 #endif 6840 #endif
@@ -1597,6 +1597,12 @@ void ptimer_stop(ptimer_state *s); @@ -1597,6 +1597,12 @@ void ptimer_stop(ptimer_state *s);
1597 1597
1598 #include "hw/pxa.h" 1598 #include "hw/pxa.h"
1599 1599
  1600 +/* mcf5206.c */
  1601 +qemu_irq *mcf5206_init(uint32_t base, CPUState *env);
  1602 +
  1603 +/* an5206.c */
  1604 +extern QEMUMachine an5206_machine;
  1605 +
1600 #include "gdbstub.h" 1606 #include "gdbstub.h"
1601 1607
1602 #endif /* defined(QEMU_TOOL) */ 1608 #endif /* defined(QEMU_TOOL) */