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 308 endif
309 309  
310 310 ifeq ($(TARGET_BASE_ARCH), m68k)
311   -LIBOBJS+= helper.o
  311 +LIBOBJS+= op_helper.o helper.o
312 312 endif
313 313  
314 314 ifeq ($(TARGET_BASE_ARCH), alpha)
... ... @@ -466,6 +466,9 @@ endif
466 466 ifeq ($(TARGET_BASE_ARCH), sh4)
467 467 VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
468 468 endif
  469 +ifeq ($(TARGET_BASE_ARCH), m68k)
  470 +VL_OBJS+= an5206.o mcf5206.o ptimer.o
  471 +endif
469 472 ifdef CONFIG_GDBSTUB
470 473 VL_OBJS+=gdbstub.o
471 474 endif
... ...
configure
... ... @@ -467,7 +467,7 @@ fi
467 467 if test -z "$target_list" ; then
468 468 # these targets are portable
469 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 471 fi
472 472 # the following are Linux specific
473 473 if [ "$linux_user" = "yes" ] ; then
... ...
cpu-exec.c
... ... @@ -196,7 +196,7 @@ static inline TranslationBlock *tb_find_fast(void)
196 196 cs_base = 0;
197 197 pc = env->PC;
198 198 #elif defined(TARGET_M68K)
199   - flags = env->fpcr & M68K_FPCR_PREC;
  199 + flags = (env->fpcr & M68K_FPCR_PREC) | (env->sr & SR_S);
200 200 cs_base = 0;
201 201 pc = env->pc;
202 202 #elif defined(TARGET_SH4)
... ... @@ -297,7 +297,7 @@ int cpu_exec(CPUState *env1)
297 297 return EXCP_HALTED;
298 298 }
299 299 }
300   -#elif defined(TARGET_ALPHA)
  300 +#elif defined(TARGET_ALPHA) || defined(TARGET_M68K)
301 301 if (env1->halted) {
302 302 if (env1->interrupt_request & CPU_INTERRUPT_HARD) {
303 303 env1->halted = 0;
... ... @@ -390,6 +390,8 @@ int cpu_exec(CPUState *env1)
390 390 do_interrupt(env);
391 391 #elif defined(TARGET_ALPHA)
392 392 do_interrupt(env);
  393 +#elif defined(TARGET_M68K)
  394 + do_interrupt(0);
393 395 #endif
394 396 }
395 397 env->exception_index = -1;
... ... @@ -542,6 +544,18 @@ int cpu_exec(CPUState *env1)
542 544 if (interrupt_request & CPU_INTERRUPT_HARD) {
543 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 559 #endif
546 560 /* Don't use the cached interupt_request value,
547 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 584 is_user = ((env->sr & SR_MD) == 0);
585 585 #elif defined (TARGET_ALPHA)
586 586 is_user = ((env->ps >> 3) & 3);
  587 +#elif defined (TARGET_M68K)
  588 + is_user = ((env->sr & SR_S) == 0);
587 589 #else
588 590 #error unimplemented CPU
589 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 1977 }
1978 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 1983 cpu_abort(cpu_single_env,
1984 1984 "Unable to find m68k CPU definition\n");
1985 1985 }
1986   - cpu_m68k_register(cpu_single_env, def);
1987 1986 env->pc = regs->pc;
1988 1987 env->dregs[0] = regs->d0;
1989 1988 env->dregs[1] = regs->d1;
... ...
softmmu_header.h
... ... @@ -65,6 +65,8 @@
65 65 #define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
66 66 #elif defined (TARGET_ALPHA)
67 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 70 #else
69 71 #error unsupported CPU
70 72 #endif
... ... @@ -86,6 +88,8 @@
86 88 #define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
87 89 #elif defined (TARGET_ALPHA)
88 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 93 #else
90 94 #error unsupported CPU
91 95 #endif
... ...
target-m68k/cpu.h
1 1 /*
2 2 * m68k virtual CPU header
3 3 *
4   - * Copyright (c) 2005-2006 CodeSourcery
  4 + * Copyright (c) 2005-2007 CodeSourcery
5 5 * Written by Paul Brook
6 6 *
7 7 * This library is free software; you can redistribute it and/or
... ... @@ -50,6 +50,8 @@
50 50 #define EXCP_UNSUPPORTED 61
51 51 #define EXCP_ICE 13
52 52  
  53 +#define EXCP_RTE 0x100
  54 +
53 55 typedef struct CPUM68KState {
54 56 uint32_t dregs[8];
55 57 uint32_t aregs[8];
... ... @@ -76,6 +78,12 @@ typedef struct CPUM68KState {
76 78 struct {
77 79 uint32_t ar;
78 80 } mmu;
  81 +
  82 + /* Control registers. */
  83 + uint32_t vbr;
  84 + uint32_t mbar;
  85 + uint32_t rambar0;
  86 +
79 87 /* ??? remove this. */
80 88 uint32_t t1;
81 89  
... ... @@ -84,7 +92,10 @@ typedef struct CPUM68KState {
84 92 int exception_index;
85 93 int interrupt_request;
86 94 int user_mode_only;
87   - uint32_t address;
  95 + int halted;
  96 +
  97 + int pending_vector;
  98 + int pending_level;
88 99  
89 100 uint32_t qregs[MAX_QREGS];
90 101  
... ... @@ -94,6 +105,7 @@ typedef struct CPUM68KState {
94 105 CPUM68KState *cpu_m68k_init(void);
95 106 int cpu_m68k_exec(CPUM68KState *s);
96 107 void cpu_m68k_close(CPUM68KState *s);
  108 +void do_interrupt(int is_hw);
97 109 /* you can call this signal handler from your SIGBUS and SIGSEGV
98 110 signal handlers to inform the virtual CPU of exceptions. non zero
99 111 is returned if the signal was handled by the virtual CPU. */
... ... @@ -120,12 +132,19 @@ enum {
120 132 #define CCF_V 0x02
121 133 #define CCF_Z 0x04
122 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 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 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 40 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
41 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 47 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op);
45 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 51 void cpu_loop_exit(void);
... ...
target-m68k/helper.c
1 1 /*
2 2 * m68k op helpers
3 3 *
4   - * Copyright (c) 2006 CodeSourcery
  4 + * Copyright (c) 2006-2007 CodeSourcery
5 5 * Written by Paul Brook
6 6 *
7 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 147 }
148 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 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 62 static inline void gen_op_pack_32_f32(int dest, int src)
41 63 {
42 64 gen_op_mov32(dest, src);
... ...
target-m68k/op.c
1 1 /*
2 2 * m68k micro operations
3 3 *
4   - * Copyright (c) 2006 CodeSourcery
  4 + * Copyright (c) 2006-2007 CodeSourcery
5 5 * Written by Paul Brook
6 6 *
7 7 * This library is free software; you can redistribute it and/or
... ... @@ -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 91 OP(mov32)
92 92 {
... ... @@ -316,77 +316,6 @@ OP(ext16s32)
316 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 319 OP(flush_flags)
391 320 {
392 321 int cc_op = PARAM1;
... ... @@ -454,6 +383,13 @@ OP(divs)
454 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 393 OP(raise_exception)
458 394 {
459 395 RAISE_EXCEPTION(PARAM1);
... ... @@ -679,3 +615,22 @@ OP(compare_quietf64)
679 615 set_op(PARAM1, float64_compare_quiet(op0, op1, &CPU_FP_STATUS));
680 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 24 DEFF64(F7, fregs[7])
25 25 DEFF64(FP_RESULT, fp_result)
26 26 DEFO32(PC, pc)
  27 +DEFO32(SR, sr)
27 28 DEFO32(CC_OP, cc_op)
28 29 DEFR(T0, AREG1, QMODE_I32)
29 30 DEFO32(CC_DEST, cc_dest)
... ...
target-m68k/translate.c
1 1 /*
2 2 * m68k translation
3 3 *
4   - * Copyright (c) 2005-2006 CodeSourcery
  4 + * Copyright (c) 2005-2007 CodeSourcery
5 5 * Written by Paul Brook
6 6 *
7 7 * This library is free software; you can redistribute it and/or
... ... @@ -30,6 +30,8 @@
30 30 #include "disas.h"
31 31 #include "m68k-qreg.h"
32 32  
  33 +//#define DEBUG_DISPATCH 1
  34 +
33 35 static inline void qemu_assert(int cond, const char *msg)
34 36 {
35 37 if (!cond) {
... ... @@ -43,6 +45,7 @@ typedef struct DisasContext {
43 45 target_ulong pc;
44 46 int is_jmp;
45 47 int cc_op;
  48 + int user;
46 49 uint32_t fpcr;
47 50 struct TranslationBlock *tb;
48 51 int singlestep_enabled;
... ... @@ -50,6 +53,12 @@ typedef struct DisasContext {
50 53  
51 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 62 /* XXX: move that elsewhere */
54 63 /* ??? Fix exceptions. */
55 64 static void *gen_throws_exception;
... ... @@ -68,6 +77,25 @@ enum {
68 77 };
69 78  
70 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 99 #include "op-hacks.h"
72 100  
73 101 #define OS_BYTE 0
... ... @@ -101,40 +129,49 @@ static m68k_def_t m68k_cpu_defs[] = {
101 129  
102 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 140 #define DISAS_INSN(name) \
105 141 static void disas_##name (DisasContext *s, uint16_t insn)
  142 +#endif
106 143  
107 144 /* Generate a load from the specified address. Narrow values are
108 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 148 int tmp;
112 149 switch(opsize) {
113 150 case OS_BYTE:
114 151 tmp = gen_new_qreg(QMODE_I32);
115 152 if (sign)
116   - gen_op_ld8s32(tmp, addr);
  153 + gen_ld(s, 8s32, tmp, addr);
117 154 else
118   - gen_op_ld8u32(tmp, addr);
  155 + gen_ld(s, 8u32, tmp, addr);
119 156 break;
120 157 case OS_WORD:
121 158 tmp = gen_new_qreg(QMODE_I32);
122 159 if (sign)
123   - gen_op_ld16s32(tmp, addr);
  160 + gen_ld(s, 16s32, tmp, addr);
124 161 else
125   - gen_op_ld16u32(tmp, addr);
  162 + gen_ld(s, 16u32, tmp, addr);
126 163 break;
127 164 case OS_LONG:
128 165 tmp = gen_new_qreg(QMODE_I32);
129   - gen_op_ld32(tmp, addr);
  166 + gen_ld(s, 32, tmp, addr);
130 167 break;
131 168 case OS_SINGLE:
132 169 tmp = gen_new_qreg(QMODE_F32);
133   - gen_op_ldf32(tmp, addr);
  170 + gen_ld(s, f32, tmp, addr);
134 171 break;
135 172 case OS_DOUBLE:
136 173 tmp = gen_new_qreg(QMODE_F64);
137   - gen_op_ldf64(tmp, addr);
  174 + gen_ld(s, f64, tmp, addr);
138 175 break;
139 176 default:
140 177 qemu_assert(0, "bad load size");
... ... @@ -144,23 +181,23 @@ static inline int gen_load(int opsize, int addr, int sign)
144 181 }
145 182  
146 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 186 switch(opsize) {
150 187 case OS_BYTE:
151   - gen_op_st8(addr, val);
  188 + gen_st(s, 8, addr, val);
152 189 break;
153 190 case OS_WORD:
154   - gen_op_st16(addr, val);
  191 + gen_st(s, 16, addr, val);
155 192 break;
156 193 case OS_LONG:
157   - gen_op_st32(addr, val);
  194 + gen_st(s, 32, addr, val);
158 195 break;
159 196 case OS_SINGLE:
160   - gen_op_stf32(addr, val);
  197 + gen_st(s, f32, addr, val);
161 198 break;
162 199 case OS_DOUBLE:
163   - gen_op_stf64(addr, val);
  200 + gen_st(s, f64, addr, val);
164 201 break;
165 202 default:
166 203 qemu_assert(0, "bad store size");
... ... @@ -170,13 +207,13 @@ static inline void gen_store(int opsize, int addr, int val)
170 207  
171 208 /* Generate an unsigned load if VAL is 0 a signed load if val is -1,
172 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 212 if (val > 0) {
176   - gen_store(opsize, addr, val);
  213 + gen_store(s, opsize, addr, val);
177 214 return 0;
178 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 228 int tmp;
192 229  
193 230 offset = s->pc;
194   - ext = lduw(s->pc);
  231 + ext = lduw_code(s->pc);
195 232 s->pc += 2;
196 233 tmp = ((ext >> 12) & 7) + ((ext & 0x8000) ? QREG_A0 : QREG_D0);
197 234 /* ??? Check W/L bit. */
... ... @@ -216,9 +253,9 @@ static int gen_lea_indexed(DisasContext *s, int opsize, int base)
216 253 static inline uint32_t read_im32(DisasContext *s)
217 254 {
218 255 uint32_t im;
219   - im = ((uint32_t)lduw(s->pc)) << 16;
  256 + im = ((uint32_t)lduw_code(s->pc)) << 16;
220 257 s->pc += 2;
221   - im |= lduw(s->pc);
  258 + im |= lduw_code(s->pc);
222 259 s->pc += 2;
223 260 return im;
224 261 }
... ... @@ -343,7 +380,7 @@ static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
343 380 case 5: /* Indirect displacement. */
344 381 reg += QREG_A0;
345 382 tmp = gen_new_qreg(QMODE_I32);
346   - ext = lduw(s->pc);
  383 + ext = lduw_code(s->pc);
347 384 s->pc += 2;
348 385 gen_op_add32(tmp, reg, gen_im32((int16_t)ext));
349 386 return tmp;
... ... @@ -353,7 +390,7 @@ static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
353 390 case 7: /* Other */
354 391 switch (reg) {
355 392 case 0: /* Absolute short. */
356   - offset = ldsw(s->pc);
  393 + offset = ldsw_code(s->pc);
357 394 s->pc += 2;
358 395 return gen_im32(offset);
359 396 case 1: /* Absolute long. */
... ... @@ -362,7 +399,7 @@ static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
362 399 case 2: /* pc displacement */
363 400 tmp = gen_new_qreg(QMODE_I32);
364 401 offset = s->pc;
365   - offset += ldsw(s->pc);
  402 + offset += ldsw_code(s->pc);
366 403 s->pc += 2;
367 404 return gen_im32(offset);
368 405 case 3: /* pc index+displacement. */
... ... @@ -391,7 +428,7 @@ static inline int gen_ea_once(DisasContext *s, uint16_t insn, int opsize,
391 428 if (addrp)
392 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 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 461 }
425 462 case 2: /* Indirect register */
426 463 reg += QREG_A0;
427   - return gen_ldst(opsize, reg, val);
  464 + return gen_ldst(s, opsize, reg, val);
428 465 case 3: /* Indirect postincrement. */
429 466 reg += QREG_A0;
430   - result = gen_ldst(opsize, reg, val);
  467 + result = gen_ldst(s, opsize, reg, val);
431 468 /* ??? This is not exception safe. The instruction may still
432 469 fault after this point. */
433 470 if (val > 0 || !addrp)
... ... @@ -443,7 +480,7 @@ static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,
443 480 if (addrp)
444 481 *addrp = tmp;
445 482 }
446   - result = gen_ldst(opsize, tmp, val);
  483 + result = gen_ldst(s, opsize, tmp, val);
447 484 /* ??? This is not exception safe. The instruction may still
448 485 fault after this point. */
449 486 if (val > 0 || !addrp) {
... ... @@ -467,16 +504,16 @@ static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,
467 504 switch (opsize) {
468 505 case OS_BYTE:
469 506 if (val)
470   - offset = ldsb(s->pc + 1);
  507 + offset = ldsb_code(s->pc + 1);
471 508 else
472   - offset = ldub(s->pc + 1);
  509 + offset = ldub_code(s->pc + 1);
473 510 s->pc += 2;
474 511 break;
475 512 case OS_WORD:
476 513 if (val)
477   - offset = ldsw(s->pc);
  514 + offset = ldsw_code(s->pc);
478 515 else
479   - offset = lduw(s->pc);
  516 + offset = lduw_code(s->pc);
480 517 s->pc += 2;
481 518 break;
482 519 case OS_LONG:
... ... @@ -622,6 +659,14 @@ DISAS_INSN(scc)
622 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 670 /* Generate a jump to to the address in qreg DEST. */
626 671 static void gen_jmp(DisasContext *s, int dest)
627 672 {
... ... @@ -735,7 +780,7 @@ DISAS_INSN(divl)
735 780 int reg;
736 781 uint16_t ext;
737 782  
738   - ext = lduw(s->pc);
  783 + ext = lduw_code(s->pc);
739 784 s->pc += 2;
740 785 if (ext & 0x87f8) {
741 786 gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
... ... @@ -903,13 +948,13 @@ DISAS_INSN(sats)
903 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 953 int tmp;
909 954  
910 955 tmp = gen_new_qreg(QMODE_I32);
911 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 958 gen_op_mov32(QREG_SP, tmp);
914 959 }
915 960  
... ... @@ -922,7 +967,7 @@ DISAS_INSN(movem)
922 967 int tmp;
923 968 int is_load;
924 969  
925   - mask = lduw(s->pc);
  970 + mask = lduw_code(s->pc);
926 971 s->pc += 2;
927 972 tmp = gen_lea(s, insn, OS_LONG);
928 973 addr = gen_new_qreg(QMODE_I32);
... ... @@ -935,10 +980,10 @@ DISAS_INSN(movem)
935 980 else
936 981 reg = AREG(i, 0);
937 982 if (is_load) {
938   - tmp = gen_load(OS_LONG, addr, 0);
  983 + tmp = gen_load(s, OS_LONG, addr, 0);
939 984 gen_op_mov32(reg, tmp);
940 985 } else {
941   - gen_store(OS_LONG, addr, reg);
  986 + gen_store(s, OS_LONG, addr, reg);
942 987 }
943 988 if (mask != 1)
944 989 gen_op_add32(addr, addr, gen_im32(4));
... ... @@ -963,7 +1008,7 @@ DISAS_INSN(bitop_im)
963 1008 opsize = OS_LONG;
964 1009 op = (insn >> 6) & 3;
965 1010  
966   - bitnum = lduw(s->pc);
  1011 + bitnum = lduw_code(s->pc);
967 1012 s->pc += 2;
968 1013 if (bitnum & 0xff00) {
969 1014 disas_undef(s, insn);
... ... @@ -1155,9 +1200,8 @@ DISAS_INSN(clr)
1155 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 1205 int dest;
1162 1206  
1163 1207 gen_flush_flags(s);
... ... @@ -1165,8 +1209,17 @@ DISAS_INSN(move_from_ccr)
1165 1209 gen_op_get_xflag(dest);
1166 1210 gen_op_shl32(dest, dest, gen_im32(4));
1167 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 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 1225 DISAS_INSN(neg)
... ... @@ -1184,7 +1237,16 @@ DISAS_INSN(neg)
1184 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 1251 int src1;
1190 1252 int reg;
... ... @@ -1199,19 +1261,26 @@ DISAS_INSN(move_to_ccr)
1199 1261 gen_op_shr32(src1, reg, gen_im32(4));
1200 1262 gen_op_and32(src1, src1, gen_im32(1));
1201 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 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 1275 else
1212 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 1284 DISAS_INSN(not)
1216 1285 {
1217 1286 int reg;
... ... @@ -1244,7 +1313,7 @@ DISAS_INSN(pea)
1244 1313 int tmp;
1245 1314  
1246 1315 tmp = gen_lea(s, insn, OS_LONG);
1247   - gen_push(tmp);
  1316 + gen_push(s, tmp);
1248 1317 }
1249 1318  
1250 1319 DISAS_INSN(ext)
... ... @@ -1322,7 +1391,7 @@ DISAS_INSN(mull)
1322 1391  
1323 1392 /* The upper 32 bits of the product are discarded, so
1324 1393 muls.l and mulu.l are functionally equivalent. */
1325   - ext = lduw(s->pc);
  1394 + ext = lduw_code(s->pc);
1326 1395 s->pc += 2;
1327 1396 if (ext & 0x87ff) {
1328 1397 gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
... ... @@ -1343,12 +1412,12 @@ DISAS_INSN(link)
1343 1412 int reg;
1344 1413 int tmp;
1345 1414  
1346   - offset = ldsw(s->pc);
  1415 + offset = ldsw_code(s->pc);
1347 1416 s->pc += 2;
1348 1417 reg = AREG(insn, 0);
1349 1418 tmp = gen_new_qreg(QMODE_I32);
1350 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 1421 if (reg != QREG_SP)
1353 1422 gen_op_mov32(reg, tmp);
1354 1423 gen_op_add32(QREG_SP, tmp, gen_im32(offset));
... ... @@ -1363,7 +1432,7 @@ DISAS_INSN(unlk)
1363 1432 src = gen_new_qreg(QMODE_I32);
1364 1433 reg = AREG(insn, 0);
1365 1434 gen_op_mov32(src, reg);
1366   - tmp = gen_load(OS_LONG, src, 0);
  1435 + tmp = gen_load(s, OS_LONG, src, 0);
1367 1436 gen_op_mov32(reg, tmp);
1368 1437 gen_op_add32(QREG_SP, src, gen_im32(4));
1369 1438 }
... ... @@ -1376,7 +1445,7 @@ DISAS_INSN(rts)
1376 1445 {
1377 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 1449 gen_op_add32(QREG_SP, QREG_SP, gen_im32(4));
1381 1450 gen_jmp(s, tmp);
1382 1451 }
... ... @@ -1390,7 +1459,7 @@ DISAS_INSN(jump)
1390 1459 tmp = gen_lea(s, insn, OS_LONG);
1391 1460 if ((insn & 0x40) == 0) {
1392 1461 /* jsr */
1393   - gen_push(gen_im32(s->pc));
  1462 + gen_push(s, gen_im32(s->pc));
1394 1463 }
1395 1464 gen_jmp(s, tmp);
1396 1465 }
... ... @@ -1460,14 +1529,14 @@ DISAS_INSN(branch)
1460 1529 op = (insn >> 8) & 0xf;
1461 1530 offset = (int8_t)insn;
1462 1531 if (offset == 0) {
1463   - offset = ldsw(s->pc);
  1532 + offset = ldsw_code(s->pc);
1464 1533 s->pc += 2;
1465 1534 } else if (offset == -1) {
1466 1535 offset = read_im32(s);
1467 1536 }
1468 1537 if (op == 1) {
1469 1538 /* bsr */
1470   - gen_push(gen_im32(s->pc));
  1539 + gen_push(s, gen_im32(s->pc));
1471 1540 }
1472 1541 gen_flush_cc_op(s);
1473 1542 if (op > 1) {
... ... @@ -1752,68 +1821,154 @@ DISAS_INSN(ff1)
1752 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 1836 DISAS_INSN(strldsr)
1756 1837 {
1757 1838 uint16_t ext;
1758 1839 uint32_t addr;
1759 1840  
1760 1841 addr = s->pc - 2;
1761   - ext = lduw(s->pc);
  1842 + ext = lduw_code(s->pc);
1762 1843 s->pc += 2;
1763   - if (ext != 0x46FC)
  1844 + if (ext != 0x46FC) {
1764 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 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 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 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 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 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 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 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 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 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 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 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 1974 DISAS_INSN(wddata)
... ... @@ -1823,7 +1978,12 @@ DISAS_INSN(wddata)
1823 1978  
1824 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 1989 DISAS_INSN(trap)
... ... @@ -1843,7 +2003,7 @@ DISAS_INSN(fpu)
1843 2003 int round;
1844 2004 int opsize;
1845 2005  
1846   - ext = lduw(s->pc);
  2006 + ext = lduw_code(s->pc);
1847 2007 s->pc += 2;
1848 2008 opmode = ext & 0x7f;
1849 2009 switch ((ext >> 13) & 7) {
... ... @@ -1928,10 +2088,10 @@ DISAS_INSN(fpu)
1928 2088 if (ext & mask) {
1929 2089 if (ext & (1 << 13)) {
1930 2090 /* store */
1931   - gen_op_stf64(addr, dest);
  2091 + gen_st(s, f64, addr, dest);
1932 2092 } else {
1933 2093 /* load */
1934   - gen_op_ldf64(dest, addr);
  2094 + gen_ld(s, f64, dest, addr);
1935 2095 }
1936 2096 if (ext & (mask - 1))
1937 2097 gen_op_add32(addr, addr, gen_im32(8));
... ... @@ -2060,10 +2220,10 @@ DISAS_INSN(fbcc)
2060 2220 int l1;
2061 2221  
2062 2222 addr = s->pc;
2063   - offset = ldsw(s->pc);
  2223 + offset = ldsw_code(s->pc);
2064 2224 s->pc += 2;
2065 2225 if (insn & (1 << 6)) {
2066   - offset = (offset << 16) | lduw(s->pc);
  2226 + offset = (offset << 16) | lduw_code(s->pc);
2067 2227 s->pc += 2;
2068 2228 }
2069 2229  
... ... @@ -2143,6 +2303,18 @@ DISAS_INSN(fbcc)
2143 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 2318 static disas_proc opcode_table[65536];
2147 2319  
2148 2320 static void
... ... @@ -2168,11 +2340,10 @@ register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
2168 2340 i <<= 1;
2169 2341 from = opcode & ~(i - 1);
2170 2342 to = from + i;
2171   - for (i = from; i < to; i++)
2172   - {
  2343 + for (i = from; i < to; i++) {
2173 2344 if ((i & mask) == opcode)
2174 2345 opcode_table[i] = proc;
2175   - }
  2346 + }
2176 2347 }
2177 2348  
2178 2349 /* Register m68k opcode handlers. Order is important.
... ... @@ -2274,6 +2445,8 @@ register_m68k_insns (m68k_def_t *def)
2274 2445 INSN(undef_fpu, f000, f000, CF_A);
2275 2446 INSN(fpu, f200, ffc0, CF_FPU);
2276 2447 INSN(fbcc, f280, ffc0, CF_FPU);
  2448 + INSN(frestore, f340, ffc0, CF_FPU);
  2449 + INSN(fsave, f340, ffc0, CF_FPU);
2277 2450 INSN(intouch, f340, ffc0, CF_A);
2278 2451 INSN(cpushl, f428, ff38, CF_A);
2279 2452 INSN(wddata, fb00, ff00, CF_A);
... ... @@ -2287,7 +2460,7 @@ static void disas_m68k_insn(CPUState * env, DisasContext *s)
2287 2460 {
2288 2461 uint16_t insn;
2289 2462  
2290   - insn = lduw(s->pc);
  2463 + insn = lduw_code(s->pc);
2291 2464 s->pc += 2;
2292 2465  
2293 2466 opcode_table[insn](s, insn);
... ... @@ -2576,6 +2749,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2576 2749 dc->cc_op = CC_OP_DYNAMIC;
2577 2750 dc->singlestep_enabled = env->singlestep_enabled;
2578 2751 dc->fpcr = env->fpcr;
  2752 + dc->user = (env->sr & SR_S) == 0;
2579 2753 nb_gen_labels = 0;
2580 2754 lj = -1;
2581 2755 do {
... ... @@ -2675,6 +2849,19 @@ int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2675 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 2865 CPUM68KState *cpu_m68k_init(void)
2679 2866 {
2680 2867 CPUM68KState *env;
... ... @@ -2684,10 +2871,7 @@ CPUM68KState *cpu_m68k_init(void)
2684 2871 return NULL;
2685 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 2875 return env;
2692 2876 }
2693 2877  
... ... @@ -2696,23 +2880,20 @@ void cpu_m68k_close(CPUM68KState *env)
2696 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 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 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 2894 register_m68k_insns(def);
  2895 +
  2896 + return 0;
2716 2897 }
2717 2898  
2718 2899 void cpu_dump_state(CPUState *env, FILE *f,
... ... @@ -2737,24 +2918,3 @@ void cpu_dump_state(CPUState *env, FILE *f,
2737 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 6833 qemu_register_machine(&shix_machine);
6834 6834 #elif defined(TARGET_ALPHA)
6835 6835 /* XXX: TODO */
  6836 +#elif defined(TARGET_M68K)
  6837 + qemu_register_machine(&an5206_machine);
6836 6838 #else
6837 6839 #error unsupported CPU
6838 6840 #endif
... ...
... ... @@ -1597,6 +1597,12 @@ void ptimer_stop(ptimer_state *s);
1597 1597  
1598 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 1606 #include "gdbstub.h"
1601 1607  
1602 1608 #endif /* defined(QEMU_TOOL) */
... ...