Update of /cvsroot/hppaqemu/hppaqemu/target-m68k In directory sc8-pr-cvs17.sourceforge.net:/tmp/cvs-serv24609/target-m68k Modified Files: cpu.h exec.h helper.c op-hacks.h op.c qregs.def translate.c Added Files: op_helper.c op_mem.h Log Message: Update to QEMU CVS from 2007-06-01. Index: translate.c =================================================================== RCS file: /cvsroot/hppaqemu/hppaqemu/target-m68k/translate.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- translate.c 23 Feb 2007 21:44:39 -0000 1.1.1.1 +++ translate.c 18 Feb 2008 00:13:58 -0000 1.2 @@ -1,7 +1,7 @@ /* * m68k translation * - * Copyright (c) 2005-2006 CodeSourcery + * Copyright (c) 2005-2007 CodeSourcery * Written by Paul Brook * * This library is free software; you can redistribute it and/or @@ -30,6 +30,8 @@ #include "disas.h" #include "m68k-qreg.h" [...1922 lines suppressed...] -target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) -{ - return addr; -} - -#if defined(CONFIG_USER_ONLY) - -int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw, - int is_user, int is_softmmu) -{ - env->exception_index = EXCP_ACCESS; - env->mmu.ar = address; - return 1; -} - -#else - -#error not implemented - -#endif Index: helper.c =================================================================== RCS file: /cvsroot/hppaqemu/hppaqemu/target-m68k/helper.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- helper.c 23 Feb 2007 21:44:39 -0000 1.1.1.1 +++ helper.c 18 Feb 2008 00:13:58 -0000 1.2 @@ -1,7 +1,7 @@ /* * m68k op helpers * - * Copyright (c) 2006 CodeSourcery + * Copyright (c) 2006-2007 CodeSourcery * Written by Paul Brook * * This library is free software; you can redistribute it and/or @@ -20,11 +20,74 @@ */ #include <stdio.h> +#include <string.h> #include "config.h" #include "cpu.h" #include "exec-all.h" +enum m68k_cpuid { + M68K_CPUID_M5206, + M68K_CPUID_CFV4E, + M68K_CPUID_ANY, +}; + +struct m68k_def_t { + const char * name; + enum m68k_cpuid id; +}; + +static m68k_def_t m68k_cpu_defs[] = { + {"m5206", M68K_CPUID_M5206}, + {"cfv4e", M68K_CPUID_CFV4E}, + {"any", M68K_CPUID_ANY}, + {NULL, 0}, +}; + +static void m68k_set_feature(CPUM68KState *env, int feature) +{ + env->features |= (1u << feature); +} + +int cpu_m68k_set_model(CPUM68KState *env, const char * name) +{ + m68k_def_t *def; + + for (def = m68k_cpu_defs; def->name; def++) { + if (strcmp(def->name, name) == 0) + break; + } + if (!def->name) + return 1; + + switch (def->id) { + case M68K_CPUID_M5206: + m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); + break; + case M68K_CPUID_CFV4E: + m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); + m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); + m68k_set_feature(env, M68K_FEATURE_CF_ISA_C); + m68k_set_feature(env, M68K_FEATURE_CF_FPU); + m68k_set_feature(env, M68K_FEATURE_CF_EMAC); + break; + case M68K_CPUID_ANY: + m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); + m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); + m68k_set_feature(env, M68K_FEATURE_CF_ISA_C); + m68k_set_feature(env, M68K_FEATURE_CF_FPU); + /* MAC and EMAC are mututally exclusive, so pick EMAC. + It's mostly backwards compatible. */ + m68k_set_feature(env, M68K_FEATURE_CF_EMAC); + m68k_set_feature(env, M68K_FEATURE_EXT_FULL); + break; + } + + register_m68k_insns(env); + + return 0; +} + void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op) { int flags; @@ -147,3 +210,99 @@ } return res; } + +void helper_movec(CPUM68KState *env, int reg, uint32_t val) +{ + switch (reg) { + case 0x02: /* CACR */ + /* Ignored. */ + break; + case 0x801: /* VBR */ + env->vbr = val; + break; + /* TODO: Implement control registers. */ + default: + cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n", + reg, val); + } +} + +void m68k_set_macsr(CPUM68KState *env, uint32_t val) +{ + uint32_t acc; + int8_t exthigh; + uint8_t extlow; + uint64_t regval; + int i; + if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) { + for (i = 0; i < 4; i++) { + regval = env->macc[i]; + exthigh = regval >> 40; + if (env->macsr & MACSR_FI) { + acc = regval >> 8; + extlow = regval; + } else { + acc = regval; + extlow = regval >> 32; + } + if (env->macsr & MACSR_FI) { + regval = (((uint64_t)acc) << 8) | extlow; + regval |= ((int64_t)exthigh) << 40; + } else if (env->macsr & MACSR_SU) { + regval = acc | (((int64_t)extlow) << 32); + regval |= ((int64_t)exthigh) << 40; + } else { + regval = acc | (((uint64_t)extlow) << 32); + regval |= ((uint64_t)(uint8_t)exthigh) << 40; + } + env->macc[i] = regval; + } + } + env->macsr = val; +} + +/* MMU */ + +/* TODO: This will need fixing once the MMU is implemented. */ +target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) +{ + return addr; +} + +#if defined(CONFIG_USER_ONLY) + +int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw, + int is_user, int is_softmmu) +{ + env->exception_index = EXCP_ACCESS; + env->mmu.ar = address; + return 1; +} + +#else + +int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw, + int is_user, int is_softmmu) +{ + int prot; + + address &= TARGET_PAGE_MASK; + prot = PAGE_READ | PAGE_WRITE; + return tlb_set_page(env, address, address, prot, is_user, is_softmmu); +} + +/* Notify CPU of a pending interrupt. Prioritization and vectoring should + be handled by the interrupt controller. Real hardware only requests + the vector when the interrupt is acknowledged by the CPU. For + simplicitly we calculate it when the interrupt is signalled. */ +void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector) +{ + env->pending_level = level; + env->pending_vector = vector; + if (level) + cpu_interrupt(env, CPU_INTERRUPT_HARD); + else + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); +} + +#endif Index: op.c =================================================================== RCS file: /cvsroot/hppaqemu/hppaqemu/target-m68k/op.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- op.c 23 Feb 2007 21:44:39 -0000 1.1.1.1 +++ op.c 18 Feb 2008 00:13:58 -0000 1.2 @@ -1,7 +1,7 @@ /* * m68k micro operations * - * Copyright (c) 2006 CodeSourcery + * Copyright (c) 2006-2007 CodeSourcery * Written by Paul Brook * * This library is free software; you can redistribute it and/or @@ -48,23 +48,23 @@ uint32_t get_op(int qreg) { - if (qreg == QREG_T0) { + if (qreg >= TARGET_NUM_QREGS) { + return env->qregs[qreg - TARGET_NUM_QREGS]; + } else if (qreg == QREG_T0) { return T0; - } else if (qreg < TARGET_NUM_QREGS) { - return *(uint32_t *)(((long)env) + qreg_offsets[qreg]); } else { - return env->qregs[qreg - TARGET_NUM_QREGS]; + return *(uint32_t *)(((long)env) + qreg_offsets[qreg]); } } void set_op(int qreg, uint32_t val) { - if (qreg == QREG_T0) { + if (qreg >= TARGET_NUM_QREGS) { + env->qregs[qreg - TARGET_NUM_QREGS] = val; + } else if (qreg == QREG_T0) { T0 = val; - } else if (qreg < TARGET_NUM_QREGS) { - *(uint32_t *)(((long)env) + qreg_offsets[qreg]) = val; } else { - env->qregs[qreg - TARGET_NUM_QREGS] = val; + *(uint32_t *)(((long)env) + qreg_offsets[qreg]) = val; } } @@ -86,7 +86,7 @@ } } -#define OP(name) void OPPROTO op_##name (void) +#define OP(name) void OPPROTO glue(op_,name) (void) OP(mov32) { @@ -170,7 +170,17 @@ FORCE_RET(); } -OP(addx_cc) +OP(ff1) +{ + uint32_t arg = get_op(PARAM2); + int n; + for (n = 32; arg; n--) + arg >>= 1; + set_op(PARAM1, n); + FORCE_RET(); +} + +OP(subx_cc) { uint32_t op1 = get_op(PARAM1); uint32_t op2 = get_op(PARAM2); @@ -188,7 +198,7 @@ FORCE_RET(); } -OP(subx_cc) +OP(addx_cc) { uint32_t op1 = get_op(PARAM1); uint32_t op2 = get_op(PARAM2); @@ -275,6 +285,16 @@ FORCE_RET(); } +OP(sar32) +{ + int32_t op2 = get_op(PARAM2); + uint32_t op3 = get_op(PARAM3); + uint32_t result; + result = op2 >> op3; + set_op(PARAM1, result); + FORCE_RET(); +} + OP(sar_cc) { int32_t op1 = get_op(PARAM1); @@ -316,77 +336,6 @@ FORCE_RET(); } -/* Load/store ops. */ -OP(ld8u32) -{ - uint32_t addr = get_op(PARAM2); - set_op(PARAM1, ldub(addr)); - FORCE_RET(); -} - -OP(ld8s32) -{ - uint32_t addr = get_op(PARAM2); - set_op(PARAM1, ldsb(addr)); - FORCE_RET(); -} - -OP(ld16u32) -{ - uint32_t addr = get_op(PARAM2); - set_op(PARAM1, lduw(addr)); - FORCE_RET(); -} - -OP(ld16s32) -{ - uint32_t addr = get_op(PARAM2); - set_op(PARAM1, ldsw(addr)); - FORCE_RET(); -} - -OP(ld32) -{ - uint32_t addr = get_op(PARAM2); - set_op(PARAM1, ldl(addr)); - FORCE_RET(); -} - -OP(st8) -{ - uint32_t addr = get_op(PARAM1); - stb(addr, get_op(PARAM2)); - FORCE_RET(); -} - -OP(st16) -{ - uint32_t addr = get_op(PARAM1); - stw(addr, get_op(PARAM2)); - FORCE_RET(); -} - -OP(st32) -{ - uint32_t addr = get_op(PARAM1); - stl(addr, get_op(PARAM2)); - FORCE_RET(); -} - -OP(ldf64) -{ - uint32_t addr = get_op(PARAM2); - set_opf64(PARAM1, ldfq(addr)); - FORCE_RET(); -} - -OP(stf64) -{ - uint32_t addr = get_op(PARAM1); - stfq(addr, get_opf64(PARAM2)); - FORCE_RET(); -} - OP(flush_flags) { int cc_op = PARAM1; @@ -454,6 +403,20 @@ FORCE_RET(); } +/* Halt is special because it may be a semihosting call. */ +OP(halt) +{ + RAISE_EXCEPTION(EXCP_HALT_INSN); + FORCE_RET(); +} + +OP(stop) +{ + env->halted = 1; + RAISE_EXCEPTION(EXCP_HLT); + FORCE_RET(); +} + OP(raise_exception) { RAISE_EXCEPTION(PARAM1); @@ -679,3 +642,429 @@ set_op(PARAM1, float64_compare_quiet(op0, op1, &CPU_FP_STATUS)); FORCE_RET(); } + +OP(movec) +{ + int op1 = get_op(PARAM1); + uint32_t op2 = get_op(PARAM2); + helper_movec(env, op1, op2); +} + +/* Memory access. */ + +#define MEMSUFFIX _raw +#include "op_mem.h" + +#if !defined(CONFIG_USER_ONLY) +#define MEMSUFFIX _user +#include "op_mem.h" +#define MEMSUFFIX _kernel +#include "op_mem.h" +#endif + +/* MAC unit. */ +/* TODO: The MAC instructions use 64-bit arithmetic fairly extensively. + This results in fairly large ops (and sometimes other issues) on 32-bit + hosts. Maybe move most of them into helpers. */ +OP(macmuls) +{ + uint32_t op1 = get_op(PARAM1); + uint32_t op2 = get_op(PARAM2); + int64_t product; + int64_t res; + + product = (uint64_t)op1 * op2; + res = (product << 24) >> 24; + if (res != product) { + env->macsr |= MACSR_V; + if (env->macsr & MACSR_OMC) { + /* Make sure the accumulate operation overflows. */ + if (product < 0) + res = ~(1ll << 50); + else + res = 1ll << 50; + } + } + env->mactmp = res; + FORCE_RET(); +} + +OP(macmulu) +{ + uint32_t op1 = get_op(PARAM1); + uint32_t op2 = get_op(PARAM2); + uint64_t product; + + product = (uint64_t)op1 * op2; + if (product & (0xffffffull << 40)) { + env->macsr |= MACSR_V; + if (env->macsr & MACSR_OMC) { + /* Make sure the accumulate operation overflows. */ + product = 1ll << 50; + } else { + product &= ((1ull << 40) - 1); + } + } + env->mactmp = product; + FORCE_RET(); +} + +OP(macmulf) +{ + int32_t op1 = get_op(PARAM1); + int32_t op2 = get_op(PARAM2); + uint64_t product; + uint32_t remainder; + + product = (uint64_t)op1 * op2; + if (env->macsr & MACSR_RT) { + remainder = product & 0xffffff; + product >>= 24; + if (remainder > 0x800000) + product++; + else if (remainder == 0x800000) + product += (product & 1); + } else { + product >>= 24; + } + env->mactmp = product; + FORCE_RET(); +} + +OP(macshl) +{ + env->mactmp <<= 1; +} + +OP(macshr) +{ + env->mactmp >>= 1; +} + +OP(macadd) +{ + int acc = PARAM1; + env->macc[acc] += env->mactmp; + FORCE_RET(); +} + +OP(macsub) +{ + int acc = PARAM1; + env->macc[acc] -= env->mactmp; + FORCE_RET(); +} + +OP(macsats) +{ + int acc = PARAM1; + int64_t sum; + int64_t result; + + sum = env->macc[acc]; + result = (sum << 16) >> 16; + if (result != sum) { + env->macsr |= MACSR_V; + } + if (env->macsr & MACSR_V) { + env->macsr |= MACSR_PAV0 << acc; + if (env->macsr & MACSR_OMC) { + /* The result is saturated to 32 bits, despite overflow occuring + at 48 bits. Seems weird, but that's what the hardware docs + say. */ + result = (result >> 63) ^ 0x7fffffff; + } + } + env->macc[acc] = result; + FORCE_RET(); +} + +OP(macsatu) +{ + int acc = PARAM1; + uint64_t sum; + + sum = env->macc[acc]; + if (sum & (0xffffull << 48)) { + env->macsr |= MACSR_V; + } + if (env->macsr & MACSR_V) { + env->macsr |= MACSR_PAV0 << acc; + if (env->macsr & MACSR_OMC) { + if (sum > (1ull << 53)) + sum = 0; + else + sum = (1ull << 48) - 1; + } else { + sum &= ((1ull << 48) - 1); + } + } + FORCE_RET(); +} + +OP(macsatf) +{ + int acc = PARAM1; + int64_t sum; + int64_t result; + + sum = env->macc[acc]; + result = (sum << 16) >> 16; + if (result != sum) { + env->macsr |= MACSR_V; + } + if (env->macsr & MACSR_V) { + env->macsr |= MACSR_PAV0 << acc; + if (env->macsr & MACSR_OMC) { + result = (result >> 63) ^ 0x7fffffffffffll; + } + } + env->macc[acc] = result; + FORCE_RET(); +} + +OP(mac_clear_flags) +{ + env->macsr &= ~(MACSR_V | MACSR_Z | MACSR_N | MACSR_EV); +} + +OP(mac_set_flags) +{ + int acc = PARAM1; + uint64_t val; + val = env->macc[acc]; + if (val == 0) + env->macsr |= MACSR_Z; + else if (val & (1ull << 47)); + env->macsr |= MACSR_N; + if (env->macsr & (MACSR_PAV0 << acc)) { + env->macsr |= MACSR_V; + } + if (env->macsr & MACSR_FI) { + val = ((int64_t)val) >> 40; + if (val != 0 && val != -1) + env->macsr |= MACSR_EV; + } else if (env->macsr & MACSR_SU) { + val = ((int64_t)val) >> 32; + if (val != 0 && val != -1) + env->macsr |= MACSR_EV; + } else { + if ((val >> 32) != 0) + env->macsr |= MACSR_EV; + } + FORCE_RET(); +} + +OP(get_macf) +{ + int acc = PARAM2; + int64_t val; + int rem; + uint32_t result; + + val = env->macc[acc]; + if (env->macsr & MACSR_SU) { + /* 16-bit rounding. */ + rem = val & 0xffffff; + val = (val >> 24) & 0xffffu; + if (rem > 0x800000) + val++; + else if (rem == 0x800000) + val += (val & 1); + } else if (env->macsr & MACSR_RT) { + /* 32-bit rounding. */ + rem = val & 0xff; + val >>= 8; + if (rem > 0x80) + val++; + else if (rem == 0x80) + val += (val & 1); + } else { + /* No rounding. */ + val >>= 8; + } + if (env->macsr & MACSR_OMC) { + /* Saturate. */ + if (env->macsr & MACSR_SU) { + if (val != (uint16_t) val) { + result = ((val >> 63) ^ 0x7fff) & 0xffff; + } else { + result = val & 0xffff; + } + } else { + if (val != (uint32_t)val) { + result = ((uint32_t)(val >> 63) & 0x7fffffff); + } else { + result = (uint32_t)val; + } + } + } else { + /* No saturation. */ + if (env->macsr & MACSR_SU) { + result = val & 0xffff; + } else { + result = (uint32_t)val; + } + } + set_op(PARAM1, result); + FORCE_RET(); +} + +OP(get_maci) +{ + int acc = PARAM2; + set_op(PARAM1, (uint32_t)env->macc[acc]); + FORCE_RET(); +} + +OP(get_macs) +{ + int acc = PARAM2; + int64_t val = env->macc[acc]; + uint32_t result; + if (val == (int32_t)val) { + result = (int32_t)val; + } else { + result = (val >> 61) ^ 0x7fffffff; + } + set_op(PARAM1, result); + FORCE_RET(); +} + +OP(get_macu) +{ + int acc = PARAM2; + uint64_t val = env->macc[acc]; + uint32_t result; + if ((val >> 32) == 0) { + result = (uint32_t)val; + } else { + result = 0xffffffffu; + } + set_op(PARAM1, result); + FORCE_RET(); +} + +OP(clear_mac) +{ + int acc = PARAM1; + + env->macc[acc] = 0; + env->macsr &= ~(MACSR_PAV0 << acc); + FORCE_RET(); +} + +OP(move_mac) +{ + int dest = PARAM1; + int src = PARAM2; + uint32_t mask; + env->macc[dest] = env->macc[src]; + mask = MACSR_PAV0 << dest; + if (env->macsr & (MACSR_PAV0 << src)) + env->macsr |= mask; + else + env->macsr &= ~mask; + FORCE_RET(); +} + +OP(get_mac_extf) +{ + uint32_t val; + int acc = PARAM2; + val = env->macc[acc] & 0x00ff; + val = (env->macc[acc] >> 32) & 0xff00; + val |= (env->macc[acc + 1] << 16) & 0x00ff0000; + val |= (env->macc[acc + 1] >> 16) & 0xff000000; + set_op(PARAM1, val); + FORCE_RET(); +} + +OP(get_mac_exti) +{ + uint32_t val; + int acc = PARAM2; + val = (env->macc[acc] >> 32) & 0xffff; + val |= (env->macc[acc + 1] >> 16) & 0xffff0000; + set_op(PARAM1, val); + FORCE_RET(); +} + +OP(set_macf) +{ + int acc = PARAM2; + int32_t val = get_op(PARAM1); + env->macc[acc] = ((int64_t)val) << 8; + env->macsr &= ~(MACSR_PAV0 << acc); + FORCE_RET(); +} + +OP(set_macs) +{ + int acc = PARAM2; + int32_t val = get_op(PARAM1); + env->macc[acc] = val; + env->macsr &= ~(MACSR_PAV0 << acc); + FORCE_RET(); +} + +OP(set_macu) +{ + int acc = PARAM2; + uint32_t val = get_op(PARAM1); + env->macc[acc] = val; + env->macsr &= ~(MACSR_PAV0 << acc); + FORCE_RET(); +} + +OP(set_mac_extf) +{ + int acc = PARAM2; + int32_t val = get_op(PARAM1); + int64_t res; + int32_t tmp; + res = env->macc[acc] & 0xffffffff00ull; + tmp = (int16_t)(val & 0xff00); + res |= ((int64_t)tmp) << 32; + res |= val & 0xff; + env->macc[acc] = res; + res = env->macc[acc + 1] & 0xffffffff00ull; + tmp = (val & 0xff000000); + res |= ((int64_t)tmp) << 16; + res |= (val >> 16) & 0xff; + env->macc[acc + 1] = res; +} + +OP(set_mac_exts) +{ + int acc = PARAM2; + int32_t val = get_op(PARAM1); + int64_t res; + int32_t tmp; + res = (uint32_t)env->macc[acc]; + tmp = (int16_t)val; + res |= ((int64_t)tmp) << 32; + env->macc[acc] = res; + res = (uint32_t)env->macc[acc + 1]; + tmp = val & 0xffff0000; + res |= (int64_t)tmp << 16; + env->macc[acc + 1] = res; +} + +OP(set_mac_extu) +{ + int acc = PARAM2; + int32_t val = get_op(PARAM1); + uint64_t res; + res = (uint32_t)env->macc[acc]; + res |= ((uint64_t)(val & 0xffff)) << 32; + env->macc[acc] = res; + res = (uint32_t)env->macc[acc + 1]; + res |= (uint64_t)(val & 0xffff0000) << 16; + env->macc[acc + 1] = res; +} + +OP(set_macsr) +{ + m68k_set_macsr(env, get_op(PARAM1)); +} --- NEW FILE: op_helper.c --- /* * M68K helper routines * * Copyright (c) 2007 CodeSourcery * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "exec.h" #if defined(CONFIG_USER_ONLY) void do_interrupt(int is_hw) { env->exception_index = -1; } #else extern int semihosting_enabled; #define MMUSUFFIX _mmu #define GETPC() (__builtin_return_address(0)) #define SHIFT 0 #include "softmmu_template.h" #define SHIFT 1 #include "softmmu_template.h" #define SHIFT 2 #include "softmmu_template.h" #define SHIFT 3 #include "softmmu_template.h" /* Try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ /* XXX: fix it to restore all registers */ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) { TranslationBlock *tb; CPUState *saved_env; target_phys_addr_t pc; int ret; /* XXX: hack to restore env in all cases, even if not called from generated code */ saved_env = env; env = cpu_single_env; ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, is_user, 1); if (__builtin_expect(ret, 0)) { if (retaddr) { /* now we have a real cpu fault */ pc = (target_phys_addr_t)retaddr; tb = tb_find_pc(pc); if (tb) { /* the PC is inside the translated code. It means that we have a virtual CPU fault */ cpu_restore_state(tb, env, pc, NULL); } } cpu_loop_exit(); } env = saved_env; } static void do_rte(void) { uint32_t sp; uint32_t fmt; sp = env->aregs[7]; fmt = ldl_kernel(sp); env->pc = ldl_kernel(sp + 4); sp |= (fmt >> 28) & 3; env->sr = fmt & 0xffff; env->aregs[7] = sp + 8; } void do_interrupt(int is_hw) { uint32_t sp; uint32_t fmt; uint32_t retaddr; uint32_t vector; fmt = 0; retaddr = env->pc; if (!is_hw) { switch (env->exception_index) { case EXCP_RTE: /* Return from an exception. */ do_rte(); return; case EXCP_HALT_INSN: if (semihosting_enabled && (env->sr & SR_S) != 0 && (env->pc & 3) == 0 && lduw_code(env->pc - 4) == 0x4e71 && ldl_code(env->pc) == 0x4e7bf000) { env->pc += 4; do_m68k_semihosting(env, env->dregs[0]); return; } env->halted = 1; env->exception_index = EXCP_HLT; cpu_loop_exit(); return; } if (env->exception_index >= EXCP_TRAP0 && env->exception_index <= EXCP_TRAP15) { /* Move the PC after the trap instruction. */ retaddr += 2; } } /* TODO: Implement USP. */ sp = env->aregs[7]; vector = env->exception_index << 2; fmt |= 0x40000000; fmt |= (sp & 3) << 28; fmt |= vector << 16; fmt |= env->sr; /* ??? This could cause MMU faults. */ sp &= ~3; sp -= 4; stl_kernel(sp, retaddr); sp -= 4; stl_kernel(sp, fmt); env->aregs[7] = sp; env->sr |= SR_S; if (is_hw) { env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT); } /* Jump to vector. */ env->pc = ldl_kernel(env->vbr + vector); } #endif Index: op-hacks.h =================================================================== RCS file: /cvsroot/hppaqemu/hppaqemu/target-m68k/op-hacks.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- op-hacks.h 23 Feb 2007 21:44:39 -0000 1.1.1.1 +++ op-hacks.h 18 Feb 2008 00:13:58 -0000 1.2 @@ -27,16 +27,38 @@ return qreg; } -static inline void gen_op_ldf32(int dest, int addr) +static inline void gen_op_ldf32_raw(int dest, int addr) { - gen_op_ld32(dest, addr); + gen_op_ld32_raw(dest, addr); } -static inline void gen_op_stf32(int addr, int dest) +static inline void gen_op_stf32_raw(int addr, int dest) { - gen_op_st32(addr, dest); + gen_op_st32_raw(addr, dest); +} + +#if !defined(CONFIG_USER_ONLY) +static inline void gen_op_ldf32_user(int dest, int addr) +{ + gen_op_ld32_user(dest, addr); +} + +static inline void gen_op_stf32_user(int addr, int dest) +{ + gen_op_st32_user(addr, dest); } +static inline void gen_op_ldf32_kernel(int dest, int addr) +{ + gen_op_ld32_kernel(dest, addr); +} + +static inline void gen_op_stf32_kernel(int addr, int dest) +{ + gen_op_st32_kernel(addr, dest); +} +#endif + static inline void gen_op_pack_32_f32(int dest, int src) { gen_op_mov32(dest, src); Index: qregs.def =================================================================== RCS file: /cvsroot/hppaqemu/hppaqemu/target-m68k/qregs.def,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- qregs.def 23 Feb 2007 21:44:39 -0000 1.1.1.1 +++ qregs.def 18 Feb 2008 00:13:58 -0000 1.2 @@ -24,6 +24,7 @@ DEFF64(F7, fregs[7]) DEFF64(FP_RESULT, fp_result) DEFO32(PC, pc) +DEFO32(SR, sr) DEFO32(CC_OP, cc_op) DEFR(T0, AREG1, QMODE_I32) DEFO32(CC_DEST, cc_dest) @@ -32,3 +33,5 @@ DEFO32(DIV1, div1) DEFO32(DIV2, div2) DEFO32(EXCEPTION, exception_index) +DEFO32(MACSR, macsr) +DEFO32(MAC_MASK, mac_mask) Index: cpu.h =================================================================== RCS file: /cvsroot/hppaqemu/hppaqemu/target-m68k/cpu.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- cpu.h 23 Feb 2007 21:44:39 -0000 1.1.1.1 +++ cpu.h 18 Feb 2008 00:13:58 -0000 1.2 @@ -1,7 +1,7 @@ /* * m68k virtual CPU header * - * Copyright (c) 2005-2006 CodeSourcery + * Copyright (c) 2005-2007 CodeSourcery * Written by Paul Brook * * This library is free software; you can redistribute it and/or @@ -50,6 +50,9 @@ #define EXCP_UNSUPPORTED 61 #define EXCP_ICE 13 +#define EXCP_RTE 0x100 +#define EXCP_HALT_INSN 0x101 + typedef struct CPUM68KState { uint32_t dregs[8]; uint32_t aregs[8]; @@ -68,6 +71,14 @@ uint32_t fpsr; float_status fp_status; + uint64_t mactmp; + /* EMAC Hardware deals with 48-bit values composed of one 32-bit and + two 8-bit parts. We store a single 64-bit value and + rearrange/extend this when changing modes. */ + uint64_t macc[4]; + uint32_t macsr; + uint32_t mac_mask; + /* Temporary storage for DIV helpers. */ uint32_t div1; uint32_t div2; @@ -76,6 +87,14 @@ struct { uint32_t ar; } mmu; + + /* Control registers. */ + uint32_t vbr; + uint32_t mbar; + uint32_t rambar0; + + uint32_t features; + /* ??? remove this. */ uint32_t t1; @@ -84,7 +103,10 @@ int exception_index; int interrupt_request; int user_mode_only; - uint32_t address; + int halted; + + int pending_vector; + int pending_level; uint32_t qregs[MAX_QREGS]; @@ -94,6 +116,7 @@ CPUM68KState *cpu_m68k_init(void); int cpu_m68k_exec(CPUM68KState *s); void cpu_m68k_close(CPUM68KState *s); +void do_interrupt(int is_hw); /* you can call this signal handler from your SIGBUS and SIGSEGV signal handlers to inform the virtual CPU of exceptions. non zero is returned if the signal was handled by the virtual CPU. */ @@ -120,15 +143,53 @@ #define CCF_V 0x02 #define CCF_Z 0x04 #define CCF_N 0x08 -#define CCF_X 0x01 +#define CCF_X 0x10 + +#define SR_I_SHIFT 8 +#define SR_I 0x0700 +#define SR_M 0x1000 +#define SR_S 0x2000 +#define SR_T 0x8000 + +#define MACSR_PAV0 0x100 +#define MACSR_OMC 0x080 +#define MACSR_SU 0x040 +#define MACSR_FI 0x020 +#define MACSR_RT 0x010 +#define MACSR_N 0x008 +#define MACSR_Z 0x004 +#define MACSR_V 0x002 +#define MACSR_EV 0x001 typedef struct m68k_def_t m68k_def_t; -m68k_def_t *m68k_find_by_name(const char *); -void cpu_m68k_register(CPUM68KState *, m68k_def_t *); +int cpu_m68k_set_model(CPUM68KState *env, const char * name); + +void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector); +void m68k_set_macsr(CPUM68KState *env, uint32_t val); #define M68K_FPCR_PREC (1 << 6) +void do_m68k_semihosting(CPUM68KState *env, int nr); + +enum m68k_features { + M68K_FEATURE_CF_ISA_A, + M68K_FEATURE_CF_ISA_B, + M68K_FEATURE_CF_ISA_C, + M68K_FEATURE_CF_FPU, + M68K_FEATURE_CF_MAC, + M68K_FEATURE_CF_EMAC, + M68K_FEATURE_EXT_FULL, /* 68020+ full extension word. */ + M68K_FEATURE_WORD_INDEX /* word sized address index registers. */ +}; + +static inline int m68k_feature(CPUM68KState *env, int feature) +{ + return (env->features & (1u << feature)) != 0; +} + +void register_m68k_insns (CPUM68KState *env); + #ifdef CONFIG_USER_ONLY /* Linux uses 8k pages. */ #define TARGET_PAGE_BITS 13 --- NEW FILE: op_mem.h --- /* Load/store ops. */ #define MEM_LD_OP(name,suffix) \ OP(glue(glue(ld,name),MEMSUFFIX)) \ { \ uint32_t addr = get_op(PARAM2); \ set_op(PARAM1, glue(glue(ld,suffix),MEMSUFFIX)(addr)); \ FORCE_RET(); \ } MEM_LD_OP(8u32,ub) MEM_LD_OP(8s32,sb) MEM_LD_OP(16u32,uw) MEM_LD_OP(16s32,sw) MEM_LD_OP(32,l) #undef MEM_LD_OP #define MEM_ST_OP(name,suffix) \ OP(glue(glue(st,name),MEMSUFFIX)) \ { \ uint32_t addr = get_op(PARAM1); \ glue(glue(st,suffix),MEMSUFFIX)(addr, get_op(PARAM2)); \ FORCE_RET(); \ } MEM_ST_OP(8,b) MEM_ST_OP(16,w) MEM_ST_OP(32,l) #undef MEM_ST_OP OP(glue(ldf64,MEMSUFFIX)) { uint32_t addr = get_op(PARAM2); set_opf64(PARAM1, glue(ldfq,MEMSUFFIX)(addr)); FORCE_RET(); } OP(glue(stf64,MEMSUFFIX)) { uint32_t addr = get_op(PARAM1); glue(stfq,MEMSUFFIX)(addr, get_opf64(PARAM2)); FORCE_RET(); } #undef MEMSUFFIX Index: exec.h =================================================================== RCS file: /cvsroot/hppaqemu/hppaqemu/target-m68k/exec.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -d -r1.1.1.1 -r1.2 --- exec.h 23 Feb 2007 21:44:39 -0000 1.1.1.1 +++ exec.h 18 Feb 2008 00:13:58 -0000 1.2 @@ -40,8 +40,12 @@ int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw, int is_user, int is_softmmu); +#if !defined(CONFIG_USER_ONLY) +#include "softmmu_exec.h" +#endif void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op); float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1); +void helper_movec(CPUM68KState *env, int reg, uint32_t val); void cpu_loop_exit(void); |