From 813dff13bf2c6bbf3588dfd00de75f6ed07901aa Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 1 Oct 2017 22:11:45 +0200 Subject: [PATCH 01/43] target/hppa: Skeleton support for hppa-softmmu With the addition of default-configs/hppa-softmmu.mak, this will compile. It is not enabled with this patch, however. Signed-off-by: Helge Deller Signed-off-by: Richard Henderson --- arch_init.c | 2 ++ hw/hppa/Makefile.objs | 1 + hw/hppa/machine.c | 38 +++++++++++++++++++++++++++ include/sysemu/arch_init.h | 1 + target/hppa/Makefile.objs | 2 +- target/hppa/cpu.c | 5 ++++ target/hppa/cpu.h | 1 + target/hppa/helper.c | 10 ------- target/hppa/mem_helper.c | 54 ++++++++++++++++++++++++++++++++++++++ target/hppa/op_helper.c | 13 +++++++-- 10 files changed, 114 insertions(+), 13 deletions(-) create mode 100644 hw/hppa/Makefile.objs create mode 100644 hw/hppa/machine.c create mode 100644 target/hppa/mem_helper.c diff --git a/arch_init.c b/arch_init.c index a0b8ed6167..4c36f2b076 100644 --- a/arch_init.c +++ b/arch_init.c @@ -53,6 +53,8 @@ int graphic_depth = 32; #define QEMU_ARCH QEMU_ARCH_CRIS #elif defined(TARGET_I386) #define QEMU_ARCH QEMU_ARCH_I386 +#elif defined(TARGET_HPPA) +#define QEMU_ARCH QEMU_ARCH_HPPA #elif defined(TARGET_M68K) #define QEMU_ARCH QEMU_ARCH_M68K #elif defined(TARGET_LM32) diff --git a/hw/hppa/Makefile.objs b/hw/hppa/Makefile.objs new file mode 100644 index 0000000000..46b2ae18de --- /dev/null +++ b/hw/hppa/Makefile.objs @@ -0,0 +1 @@ +obj-y += machine.o diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c new file mode 100644 index 0000000000..79958da18f --- /dev/null +++ b/hw/hppa/machine.c @@ -0,0 +1,38 @@ +/* + * QEMU HPPA hardware system emulator. + * Copyright 2018 Helge Deller + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" +#include "hw/hw.h" +#include "elf.h" +#include "hw/loader.h" +#include "hw/boards.h" +#include "qemu/error-report.h" +#include "sysemu/sysemu.h" +#include "hw/timer/mc146818rtc.h" +#include "hw/ide.h" +#include "hw/timer/i8254.h" +#include "hw/char/serial.h" +#include "qemu/cutils.h" +#include "qapi/error.h" + + +static void machine_hppa_init(MachineState *machine) +{ +} + +static void machine_hppa_machine_init(MachineClass *mc) +{ + mc->desc = "HPPA generic machine"; + mc->init = machine_hppa_init; + mc->block_default_type = IF_SCSI; + mc->max_cpus = 1; + mc->is_default = 1; + mc->default_ram_size = 512 * M_BYTE; + mc->default_boot_order = "cd"; +} + +DEFINE_MACHINE("hppa", machine_hppa_machine_init) diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h index 8751c468ed..f999bfd3be 100644 --- a/include/sysemu/arch_init.h +++ b/include/sysemu/arch_init.h @@ -24,6 +24,7 @@ enum { QEMU_ARCH_MOXIE = (1 << 15), QEMU_ARCH_TRICORE = (1 << 16), QEMU_ARCH_NIOS2 = (1 << 17), + QEMU_ARCH_HPPA = (1 << 18), }; extern const uint32_t arch_type; diff --git a/target/hppa/Makefile.objs b/target/hppa/Makefile.objs index 263446fa0b..d89285307b 100644 --- a/target/hppa/Makefile.objs +++ b/target/hppa/Makefile.objs @@ -1 +1 @@ -obj-y += translate.o helper.o cpu.o op_helper.o gdbstub.o +obj-y += translate.o helper.o cpu.o op_helper.o gdbstub.o mem_helper.o diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index 9e7b0d4ccb..f6d92de972 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -132,7 +132,12 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data) cc->synchronize_from_tb = hppa_cpu_synchronize_from_tb; cc->gdb_read_register = hppa_cpu_gdb_read_register; cc->gdb_write_register = hppa_cpu_gdb_write_register; +#ifdef CONFIG_USER_ONLY cc->handle_mmu_fault = hppa_cpu_handle_mmu_fault; +#else + cc->get_phys_page_debug = hppa_cpu_get_phys_page_debug; +#endif + cc->disas_set_info = hppa_cpu_disas_set_info; cc->tcg_initialize = hppa_translate_init; diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 1a35eae1fa..3d170c3cf7 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -134,6 +134,7 @@ void cpu_hppa_loaded_fr0(CPUHPPAState *env); int cpu_hppa_signal_handler(int host_signum, void *pinfo, void *puc); int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, int midx); +hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr); int hppa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); int hppa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); void hppa_cpu_do_interrupt(CPUState *cpu); diff --git a/target/hppa/helper.c b/target/hppa/helper.c index 23f7af7018..d6d6f06cb0 100644 --- a/target/hppa/helper.c +++ b/target/hppa/helper.c @@ -65,16 +65,6 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw) env->psw_cb = cb; } -int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, - int rw, int mmu_idx) -{ - HPPACPU *cpu = HPPA_CPU(cs); - - cs->exception_index = EXCP_SIGSEGV; - cpu->env.ior = address; - return 1; -} - void hppa_cpu_do_interrupt(CPUState *cs) { HPPACPU *cpu = HPPA_CPU(cs); diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c new file mode 100644 index 0000000000..a3e576f119 --- /dev/null +++ b/target/hppa/mem_helper.c @@ -0,0 +1,54 @@ +/* + * HPPA memory access helper routines + * + * Copyright (c) 2017 Helge Deller + * + * 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, see . + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/exec-all.h" +#include "exec/helper-proto.h" +#include "qom/cpu.h" + +#ifdef CONFIG_USER_ONLY +int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, + int size, int rw, int mmu_idx) +{ + HPPACPU *cpu = HPPA_CPU(cs); + + cs->exception_index = EXCP_SIGSEGV; + cpu->env.ior = address; + return 1; +} +#else +hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) +{ + /* Stub */ + return addr; +} + +void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType type, + int mmu_idx, uintptr_t retaddr) +{ + /* Stub */ + int prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + hwaddr phys = addr; + + /* Success! Store the translation into the QEMU TLB. */ + tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, + prot, mmu_idx, TARGET_PAGE_SIZE); +} +#endif /* CONFIG_USER_ONLY */ diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index fdbf64ae3c..9076ee998d 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -58,9 +58,9 @@ void HELPER(tcond)(CPUHPPAState *env, target_ulong cond) static void atomic_store_3(CPUHPPAState *env, target_ulong addr, uint32_t val, uint32_t mask, uintptr_t ra) { +#ifdef CONFIG_USER_ONLY uint32_t old, new, cmp; -#ifdef CONFIG_USER_ONLY uint32_t *haddr = g2h(addr - 1); old = *haddr; while (1) { @@ -72,7 +72,8 @@ static void atomic_store_3(CPUHPPAState *env, target_ulong addr, uint32_t val, old = cmp; } #else -#error "Not implemented." + /* FIXME -- we can do better. */ + cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); #endif } @@ -158,12 +159,20 @@ void HELPER(stby_e_parallel)(CPUHPPAState *env, target_ulong addr, target_ulong HELPER(probe_r)(target_ulong addr) { +#ifdef CONFIG_USER_ONLY return page_check_range(addr, 1, PAGE_READ); +#else + return 1; /* FIXME */ +#endif } target_ulong HELPER(probe_w)(target_ulong addr) { +#ifdef CONFIG_USER_ONLY return page_check_range(addr, 1, PAGE_WRITE); +#else + return 1; /* FIXME */ +#endif } void HELPER(loaded_fr0)(CPUHPPAState *env) From fa57e3274d2637138db996e4f3709b22e0726d62 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 8 Oct 2017 19:00:40 -0400 Subject: [PATCH 02/43] target/hppa: Define the rest of the PSW We don't actually do anything with most of the bits yet, but at least they have names and we have somewhere to store them. Signed-off-by: Richard Henderson --- target/hppa/cpu.h | 47 +++++++++++++++++++++++++++++++++++++++ target/hppa/helper.c | 53 ++++++++++++++++++++++++++++++++------------ 2 files changed, 86 insertions(+), 14 deletions(-) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 3d170c3cf7..d703e99bf9 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -46,6 +46,52 @@ #define EXCP_SIGILL 4 #define EXCP_SIGFPE 5 +/* Taken from Linux kernel: arch/parisc/include/asm/psw.h */ +#define PSW_I 0x00000001 +#define PSW_D 0x00000002 +#define PSW_P 0x00000004 +#define PSW_Q 0x00000008 +#define PSW_R 0x00000010 +#define PSW_F 0x00000020 +#define PSW_G 0x00000040 /* PA1.x only */ +#define PSW_O 0x00000080 /* PA2.0 only */ +#define PSW_CB 0x0000ff00 +#define PSW_M 0x00010000 +#define PSW_V 0x00020000 +#define PSW_C 0x00040000 +#define PSW_B 0x00080000 +#define PSW_X 0x00100000 +#define PSW_N 0x00200000 +#define PSW_L 0x00400000 +#define PSW_H 0x00800000 +#define PSW_T 0x01000000 +#define PSW_S 0x02000000 +#define PSW_E 0x04000000 +#ifdef TARGET_HPPA64 +#define PSW_W 0x08000000 /* PA2.0 only */ +#else +#define PSW_W 0 +#endif +#define PSW_Z 0x40000000 /* PA1.x only */ +#define PSW_Y 0x80000000 /* PA1.x only */ + +#define PSW_SM (PSW_W | PSW_E | PSW_O | PSW_G | PSW_F \ + | PSW_R | PSW_Q | PSW_P | PSW_D | PSW_I) + +/* ssm/rsm instructions number PSW_W and PSW_E differently */ +#define PSW_SM_I PSW_I /* Enable External Interrupts */ +#define PSW_SM_D PSW_D +#define PSW_SM_P PSW_P +#define PSW_SM_Q PSW_Q /* Enable Interrupt State Collection */ +#define PSW_SM_R PSW_R /* Enable Recover Counter Trap */ +#ifdef TARGET_HPPA64 +#define PSW_SM_E 0x100 +#define PSW_SM_W 0x200 /* PA2.0 only : Enable Wide Mode */ +#else +#define PSW_SM_E 0 +#define PSW_SM_W 0 +#endif + typedef struct CPUHPPAState CPUHPPAState; struct CPUHPPAState { @@ -56,6 +102,7 @@ struct CPUHPPAState { target_ulong cr26; target_ulong cr27; + target_long psw; /* All psw bits except the following: */ target_ulong psw_n; /* boolean */ target_long psw_v; /* in most significant bit */ diff --git a/target/hppa/helper.c b/target/hppa/helper.c index d6d6f06cb0..4231ef3bff 100644 --- a/target/hppa/helper.c +++ b/target/hppa/helper.c @@ -39,10 +39,11 @@ target_ulong cpu_hppa_get_psw(CPUHPPAState *env) /* .........................bcdefgh */ psw |= (psw >> 12) & 0xf; psw |= env->psw_cb_msb << 7; - psw <<= 8; + psw = (psw & 0xff) << 8; - psw |= env->psw_n << 21; - psw |= (env->psw_v < 0) << 17; + psw |= env->psw_n * PSW_N; + psw |= (env->psw_v < 0) * PSW_V; + psw |= env->psw; return psw; } @@ -51,8 +52,9 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw) { target_ulong cb = 0; - env->psw_n = (psw >> 21) & 1; - env->psw_v = -((psw >> 17) & 1); + env->psw = psw & ~(PSW_N | PSW_V | PSW_CB); + env->psw_n = (psw / PSW_N) & 1; + env->psw_v = -((psw / PSW_V) & 1); env->psw_cb_msb = (psw >> 15) & 1; cb |= ((psw >> 14) & 1) << 28; @@ -106,22 +108,45 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, { HPPACPU *cpu = HPPA_CPU(cs); CPUHPPAState *env = &cpu->env; + target_ulong psw = cpu_hppa_get_psw(env); + target_ulong psw_cb; + char psw_c[20]; int i; - cpu_fprintf(f, "IA_F " TARGET_FMT_lx - " IA_B " TARGET_FMT_lx - " PSW " TARGET_FMT_lx - " [N:" TARGET_FMT_ld " V:%d" - " CB:" TARGET_FMT_lx "]\n ", - env->iaoq_f, env->iaoq_b, cpu_hppa_get_psw(env), - env->psw_n, env->psw_v < 0, - ((env->psw_cb >> 4) & 0x01111111) | (env->psw_cb_msb << 28)); - for (i = 1; i < 32; i++) { + cpu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx "\n", + env->iaoq_f, env->iaoq_b); + + psw_c[0] = (psw & PSW_W ? 'W' : '-'); + psw_c[1] = (psw & PSW_E ? 'E' : '-'); + psw_c[2] = (psw & PSW_S ? 'S' : '-'); + psw_c[3] = (psw & PSW_T ? 'T' : '-'); + psw_c[4] = (psw & PSW_H ? 'H' : '-'); + psw_c[5] = (psw & PSW_L ? 'L' : '-'); + psw_c[6] = (psw & PSW_N ? 'N' : '-'); + psw_c[7] = (psw & PSW_X ? 'X' : '-'); + psw_c[8] = (psw & PSW_B ? 'B' : '-'); + psw_c[9] = (psw & PSW_C ? 'C' : '-'); + psw_c[10] = (psw & PSW_V ? 'V' : '-'); + psw_c[11] = (psw & PSW_M ? 'M' : '-'); + psw_c[12] = (psw & PSW_F ? 'F' : '-'); + psw_c[13] = (psw & PSW_R ? 'R' : '-'); + psw_c[14] = (psw & PSW_Q ? 'Q' : '-'); + psw_c[15] = (psw & PSW_P ? 'P' : '-'); + psw_c[16] = (psw & PSW_D ? 'D' : '-'); + psw_c[17] = (psw & PSW_I ? 'I' : '-'); + psw_c[18] = '\0'; + psw_cb = ((env->psw_cb >> 4) & 0x01111111) | (env->psw_cb_msb << 28); + + cpu_fprintf(f, "PSW " TARGET_FMT_lx " CB " TARGET_FMT_lx " %s\n", + psw, psw_cb, psw_c); + + for (i = 0; i < 32; i++) { cpu_fprintf(f, "GR%02d " TARGET_FMT_lx " ", i, env->gr[i]); if ((i % 4) == 3) { cpu_fprintf(f, "\n"); } } + cpu_fprintf(f, "\n"); /* ??? FR */ } From ba1d0b4482eaeae51ed6bc82fa8de3f12339c139 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Oct 2017 09:51:30 -0700 Subject: [PATCH 03/43] target/hppa: Disable gateway page emulation for system mode Signed-off-by: Richard Henderson --- target/hppa/translate.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 31d9a2a31b..8e357cc60c 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -1543,6 +1543,7 @@ static DisasJumpType do_ibranch(DisasContext *ctx, TCGv dest, return DISAS_NEXT; } +#ifdef CONFIG_USER_ONLY /* On Linux, page zero is normally marked execute only + gateway. Therefore normal read or write is supposed to fail, but specific offsets have kernel code mapped to raise permissions to implement @@ -1600,6 +1601,7 @@ static DisasJumpType do_page_zero(DisasContext *ctx) return DISAS_NORETURN; } } +#endif static DisasJumpType trans_nop(DisasContext *ctx, uint32_t insn, const DisasInsn *di) @@ -3787,10 +3789,13 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) int i, n; /* Execute one insn. */ +#ifdef CONFIG_USER_ONLY if (ctx->iaoq_f < TARGET_PAGE_SIZE) { ret = do_page_zero(ctx); assert(ret != DISAS_NEXT); - } else { + } else +#endif + { /* Always fetch the insn, even if nullified, so that we check the page permissions for execute. */ uint32_t insn = cpu_ldl_code(env, ctx->iaoq_f); @@ -3885,25 +3890,27 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) { TranslationBlock *tb = dcbase->tb; + target_ulong pc = tb->pc; - switch (tb->pc) { +#ifdef CONFIG_USER_ONLY + switch (pc) { case 0x00: qemu_log("IN:\n0x00000000: (null)\n"); - break; + return; case 0xb0: qemu_log("IN:\n0x000000b0: light-weight-syscall\n"); - break; + return; case 0xe0: qemu_log("IN:\n0x000000e0: set-thread-pointer-syscall\n"); - break; + return; case 0x100: qemu_log("IN:\n0x00000100: syscall\n"); - break; - default: - qemu_log("IN: %s\n", lookup_symbol(tb->pc)); - log_target_disas(cs, tb->pc, tb->size); - break; + return; } +#endif + + qemu_log("IN: %s\n", lookup_symbol(pc)); + log_target_disas(cs, pc, tb->size); } static const TranslatorOps hppa_tr_ops = { From 2986721df7d5d6528d17ddc1d25d261e720fd06d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 11 Oct 2017 10:03:02 -0700 Subject: [PATCH 04/43] target/hppa: Define hardware exception types Signed-off-by: Richard Henderson --- linux-user/main.c | 26 ++++++++++++++++-- target/hppa/cpu.h | 39 ++++++++++++++++++++++---- target/hppa/helper.c | 59 +++++++++++++++++++++++++++++----------- target/hppa/mem_helper.c | 4 ++- target/hppa/op_helper.c | 6 ++-- target/hppa/translate.c | 8 +++--- 6 files changed, 110 insertions(+), 32 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 2140465709..fee0b24ee6 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3773,21 +3773,41 @@ void cpu_loop(CPUHPPAState *env) env->iaoq_f = env->gr[31]; env->iaoq_b = env->gr[31] + 4; break; - case EXCP_SIGSEGV: + case EXCP_ITLB_MISS: + case EXCP_DTLB_MISS: + case EXCP_NA_ITLB_MISS: + case EXCP_NA_DTLB_MISS: + case EXCP_IMP: + case EXCP_DMP: + case EXCP_DMB: + case EXCP_PAGE_REF: + case EXCP_DMAR: + case EXCP_DMPI: info.si_signo = TARGET_SIGSEGV; info.si_errno = 0; info.si_code = TARGET_SEGV_ACCERR; info._sifields._sigfault._addr = env->ior; queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; - case EXCP_SIGILL: + case EXCP_UNALIGN: + info.si_signo = TARGET_SIGBUS; + info.si_errno = 0; + info.si_code = 0; + info._sifields._sigfault._addr = env->ior; + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + break; + case EXCP_ILL: + case EXCP_PRIV_OPR: + case EXCP_PRIV_REG: info.si_signo = TARGET_SIGILL; info.si_errno = 0; info.si_code = TARGET_ILL_ILLOPN; info._sifields._sigfault._addr = env->iaoq_f; queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; - case EXCP_SIGFPE: + case EXCP_OVERFLOW: + case EXCP_COND: + case EXCP_ASSIST: info.si_signo = TARGET_SIGFPE; info.si_errno = 0; info.si_code = 0; diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index d703e99bf9..4fc23fb255 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -40,11 +40,40 @@ #define MMU_USER_IDX 0 #define TARGET_INSN_START_EXTRA_WORDS 1 -#define EXCP_SYSCALL 1 -#define EXCP_SYSCALL_LWS 2 -#define EXCP_SIGSEGV 3 -#define EXCP_SIGILL 4 -#define EXCP_SIGFPE 5 +/* Hardware exceptions, interupts, faults, and traps. */ +#define EXCP_HPMC 1 /* high priority machine check */ +#define EXCP_POWER_FAIL 2 +#define EXCP_RC 3 /* recovery counter */ +#define EXCP_EXT_INTERRUPT 4 /* external interrupt */ +#define EXCP_LPMC 5 /* low priority machine check */ +#define EXCP_ITLB_MISS 6 /* itlb miss / instruction page fault */ +#define EXCP_IMP 7 /* instruction memory protection trap */ +#define EXCP_ILL 8 /* illegal instruction trap */ +#define EXCP_BREAK 9 /* break instruction */ +#define EXCP_PRIV_OPR 10 /* privileged operation trap */ +#define EXCP_PRIV_REG 11 /* privileged register trap */ +#define EXCP_OVERFLOW 12 /* signed overflow trap */ +#define EXCP_COND 13 /* trap-on-condition */ +#define EXCP_ASSIST 14 /* assist exception trap */ +#define EXCP_DTLB_MISS 15 /* dtlb miss / data page fault */ +#define EXCP_NA_ITLB_MISS 16 /* non-access itlb miss */ +#define EXCP_NA_DTLB_MISS 17 /* non-access dtlb miss */ +#define EXCP_DMP 18 /* data memory protection trap */ +#define EXCP_DMB 19 /* data memory break trap */ +#define EXCP_TLB_DIRTY 20 /* tlb dirty bit trap */ +#define EXCP_PAGE_REF 21 /* page reference trap */ +#define EXCP_ASSIST_EMU 22 /* assist emulation trap */ +#define EXCP_HPT 23 /* high-privilege transfer trap */ +#define EXCP_LPT 24 /* low-privilege transfer trap */ +#define EXCP_TB 25 /* taken branch trap */ +#define EXCP_DMAR 26 /* data memory access rights trap */ +#define EXCP_DMPI 27 /* data memory protection id trap */ +#define EXCP_UNALIGN 28 /* unaligned data reference trap */ +#define EXCP_PER_INTERRUPT 29 /* performance monitor interrupt */ + +/* Exceptions for linux-user emulation. */ +#define EXCP_SYSCALL 30 +#define EXCP_SYSCALL_LWS 31 /* Taken from Linux kernel: arch/parisc/include/asm/psw.h */ #define PSW_I 0x00000001 diff --git a/target/hppa/helper.c b/target/hppa/helper.c index 4231ef3bff..6439179a0e 100644 --- a/target/hppa/helper.c +++ b/target/hppa/helper.c @@ -74,25 +74,52 @@ void hppa_cpu_do_interrupt(CPUState *cs) int i = cs->exception_index; if (qemu_loglevel_mask(CPU_LOG_INT)) { + static const char * const names[] = { + [EXCP_HPMC] = "high priority machine check", + [EXCP_POWER_FAIL] = "power fail interrupt", + [EXCP_RC] = "recovery counter trap", + [EXCP_EXT_INTERRUPT] = "external interrupt", + [EXCP_LPMC] = "low priority machine check", + [EXCP_ITLB_MISS] = "instruction tlb miss fault", + [EXCP_IMP] = "instruction memory protection trap", + [EXCP_ILL] = "illegal instruction trap", + [EXCP_BREAK] = "break instruction trap", + [EXCP_PRIV_OPR] = "privileged operation trap", + [EXCP_PRIV_REG] = "privileged register trap", + [EXCP_OVERFLOW] = "overflow trap", + [EXCP_COND] = "conditional trap", + [EXCP_ASSIST] = "assist exception trap", + [EXCP_DTLB_MISS] = "data tlb miss fault", + [EXCP_NA_ITLB_MISS] = "non-access instruction tlb miss", + [EXCP_NA_DTLB_MISS] = "non-access data tlb miss", + [EXCP_DMP] = "data memory protection trap", + [EXCP_DMB] = "data memory break trap", + [EXCP_TLB_DIRTY] = "tlb dirty bit trap", + [EXCP_PAGE_REF] = "page reference trap", + [EXCP_ASSIST_EMU] = "assist emulation trap", + [EXCP_HPT] = "high-privilege transfer trap", + [EXCP_LPT] = "low-privilege transfer trap", + [EXCP_TB] = "taken branch trap", + [EXCP_DMAR] = "data memory access rights trap", + [EXCP_DMPI] = "data memory protection id trap", + [EXCP_UNALIGN] = "unaligned data reference trap", + [EXCP_PER_INTERRUPT] = "performance monitor interrupt", + [EXCP_SYSCALL] = "syscall", + [EXCP_SYSCALL_LWS] = "syscall-lws", + }; static int count; - const char *name = ""; + const char *name = NULL; - switch (i) { - case EXCP_SYSCALL: - name = "syscall"; - break; - case EXCP_SIGSEGV: - name = "sigsegv"; - break; - case EXCP_SIGILL: - name = "sigill"; - break; - case EXCP_SIGFPE: - name = "sigfpe"; - break; + if (i >= 0 && i < ARRAY_SIZE(names)) { + name = names[i]; + } + if (name) { + qemu_log("INT %6d: %s ia_f=" TARGET_FMT_lx "\n", + ++count, name, env->iaoq_f); + } else { + qemu_log("INT %6d: unknown %d ia_f=" TARGET_FMT_lx "\n", + ++count, i, env->iaoq_f); } - qemu_log("INT %6d: %s ia_f=" TARGET_FMT_lx "\n", - ++count, name, env->iaoq_f); } cs->exception_index = -1; } diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index a3e576f119..bd116d6bc6 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -29,7 +29,9 @@ int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, { HPPACPU *cpu = HPPA_CPU(cs); - cs->exception_index = EXCP_SIGSEGV; + /* ??? Test between data page fault and data memory protection trap, + which would affect si_code. */ + cs->exception_index = EXCP_DMP; cpu->env.ior = address; return 1; } diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 9076ee998d..ecf5824074 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -44,14 +44,14 @@ static void QEMU_NORETURN dynexcp(CPUHPPAState *env, int excp, uintptr_t ra) void HELPER(tsv)(CPUHPPAState *env, target_ulong cond) { if (unlikely((target_long)cond < 0)) { - dynexcp(env, EXCP_SIGFPE, GETPC()); + dynexcp(env, EXCP_OVERFLOW, GETPC()); } } void HELPER(tcond)(CPUHPPAState *env, target_ulong cond) { if (unlikely(cond)) { - dynexcp(env, EXCP_SIGFPE, GETPC()); + dynexcp(env, EXCP_COND, GETPC()); } } @@ -235,7 +235,7 @@ static void update_fr0_op(CPUHPPAState *env, uintptr_t ra) env->fr[0] = (uint64_t)shadow << 32; if (hard_exp & shadow) { - dynexcp(env, EXCP_SIGFPE, ra); + dynexcp(env, EXCP_ASSIST, ra); } } diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 8e357cc60c..8d85ed9df3 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -462,7 +462,7 @@ static DisasJumpType gen_excp(DisasContext *ctx, int exception) static DisasJumpType gen_illegal(DisasContext *ctx) { nullify_over(ctx); - return nullify_end(ctx, gen_excp(ctx, EXCP_SIGILL)); + return nullify_end(ctx, gen_excp(ctx, EXCP_ILL)); } static bool use_goto_tb(DisasContext *ctx, target_ulong dest) @@ -1578,7 +1578,7 @@ static DisasJumpType do_page_zero(DisasContext *ctx) switch (ctx->iaoq_f) { case 0x00: /* Null pointer call */ - gen_excp_1(EXCP_SIGSEGV); + gen_excp_1(EXCP_IMP); return DISAS_NORETURN; case 0xb0: /* LWS */ @@ -1597,7 +1597,7 @@ static DisasJumpType do_page_zero(DisasContext *ctx) default: do_sigill: - gen_excp_1(EXCP_SIGILL); + gen_excp_1(EXCP_ILL); return DISAS_NORETURN; } } @@ -1614,7 +1614,7 @@ static DisasJumpType trans_break(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { nullify_over(ctx); - return nullify_end(ctx, gen_excp(ctx, EXCP_DEBUG)); + return nullify_end(ctx, gen_excp(ctx, EXCP_BREAK)); } static DisasJumpType trans_sync(DisasContext *ctx, uint32_t insn, From eaa3783b687491bb2430951d1be1d849b6be6719 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Oct 2017 12:35:48 -0700 Subject: [PATCH 05/43] target/hppa: Split address size from register size For system mode, we will need 64-bit virtual addresses even when we have 32-bit register sizes. Since the rest of QEMU equates TARGET_LONG_BITS with the address size, redefine everything related to register size in terms of a new TARGET_REGISTER_BITS. Signed-off-by: Richard Henderson --- target/hppa/cpu.h | 48 +- target/hppa/gdbstub.c | 19 +- target/hppa/helper.c | 18 +- target/hppa/helper.h | 26 +- target/hppa/op_helper.c | 22 +- target/hppa/translate.c | 964 +++++++++++++++++++++++++--------------- 6 files changed, 683 insertions(+), 414 deletions(-) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 4fc23fb255..9fe5ea0a69 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -23,10 +23,10 @@ #include "qemu-common.h" #include "cpu-qom.h" -/* We only support hppa-linux-user at present, so 32-bit only. */ -#define TARGET_LONG_BITS 32 -#define TARGET_PHYS_ADDR_SPACE_BITS 32 -#define TARGET_VIRT_ADDR_SPACE_BITS 32 +#define TARGET_LONG_BITS 32 +#define TARGET_VIRT_ADDR_SPACE_BITS 32 +#define TARGET_REGISTER_BITS 32 +#define TARGET_PHYS_ADDR_SPACE_BITS 32 #define CPUArchState struct CPUHPPAState @@ -123,17 +123,29 @@ typedef struct CPUHPPAState CPUHPPAState; +#if TARGET_REGISTER_BITS == 32 +typedef uint32_t target_ureg; +typedef int32_t target_sreg; +#define TREG_FMT_lx "%08"PRIx32 +#define TREG_FMT_ld "%"PRId32 +#else +typedef uint64_t target_ureg; +typedef int64_t target_sreg; +#define TREG_FMT_lx "%016"PRIx64 +#define TREG_FMT_ld "%"PRId64 +#endif + struct CPUHPPAState { - target_ulong gr[32]; + target_ureg gr[32]; uint64_t fr[32]; - target_ulong sar; - target_ulong cr26; - target_ulong cr27; + target_ureg sar; + target_ureg cr26; + target_ureg cr27; - target_long psw; /* All psw bits except the following: */ - target_ulong psw_n; /* boolean */ - target_long psw_v; /* in most significant bit */ + target_ureg psw; /* All psw bits except the following: */ + target_ureg psw_n; /* boolean */ + target_sreg psw_v; /* in most significant bit */ /* Splitting the carry-borrow field into the MSB and "the rest", allows * for "the rest" to be deleted when it is unused, but the MSB is in use. @@ -142,13 +154,13 @@ struct CPUHPPAState { * host has the appropriate add-with-carry insn to compute the msb). * Therefore the carry bits are stored as: cb_msb : cb & 0x11111110. */ - target_ulong psw_cb; /* in least significant bit of next nibble */ - target_ulong psw_cb_msb; /* boolean */ + target_ureg psw_cb; /* in least significant bit of next nibble */ + target_ureg psw_cb_msb; /* boolean */ - target_ulong iaoq_f; /* front */ - target_ulong iaoq_b; /* back, aka next instruction */ + target_ureg iaoq_f; /* front */ + target_ureg iaoq_b; /* back, aka next instruction */ - target_ulong ior; /* interrupt offset register */ + target_ureg ior; /* interrupt offset register */ uint32_t fr0_shadow; /* flags, c, ca/cq, rm, d, enables */ float_status fp_status; @@ -201,8 +213,8 @@ static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, target_ulong *pc, *pflags = env->psw_n; } -target_ulong cpu_hppa_get_psw(CPUHPPAState *env); -void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong); +target_ureg cpu_hppa_get_psw(CPUHPPAState *env); +void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg); void cpu_hppa_loaded_fr0(CPUHPPAState *env); #define cpu_signal_handler cpu_hppa_signal_handler diff --git a/target/hppa/gdbstub.c b/target/hppa/gdbstub.c index c37a56f238..228d282fe9 100644 --- a/target/hppa/gdbstub.c +++ b/target/hppa/gdbstub.c @@ -26,7 +26,7 @@ int hppa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) { HPPACPU *cpu = HPPA_CPU(cs); CPUHPPAState *env = &cpu->env; - target_ulong val; + target_ureg val; switch (n) { case 0: @@ -61,14 +61,25 @@ int hppa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) } break; } - return gdb_get_regl(mem_buf, val); + + if (TARGET_REGISTER_BITS == 64) { + return gdb_get_reg64(mem_buf, val); + } else { + return gdb_get_reg32(mem_buf, val); + } } int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { HPPACPU *cpu = HPPA_CPU(cs); CPUHPPAState *env = &cpu->env; - target_ulong val = ldtul_p(mem_buf); + target_ureg val; + + if (TARGET_REGISTER_BITS == 64) { + val = ldq_p(mem_buf); + } else { + val = ldl_p(mem_buf); + } switch (n) { case 0: @@ -108,5 +119,5 @@ int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) } break; } - return sizeof(target_ulong); + return sizeof(target_ureg); } diff --git a/target/hppa/helper.c b/target/hppa/helper.c index 6439179a0e..b6521f61fc 100644 --- a/target/hppa/helper.c +++ b/target/hppa/helper.c @@ -24,9 +24,9 @@ #include "fpu/softfloat.h" #include "exec/helper-proto.h" -target_ulong cpu_hppa_get_psw(CPUHPPAState *env) +target_ureg cpu_hppa_get_psw(CPUHPPAState *env) { - target_ulong psw; + target_ureg psw; /* Fold carry bits down to 8 consecutive bits. */ /* ??? Needs tweaking for hppa64. */ @@ -48,9 +48,9 @@ target_ulong cpu_hppa_get_psw(CPUHPPAState *env) return psw; } -void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw) +void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg psw) { - target_ulong cb = 0; + target_ureg cb = 0; env->psw = psw & ~(PSW_N | PSW_V | PSW_CB); env->psw_n = (psw / PSW_N) & 1; @@ -135,13 +135,13 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, { HPPACPU *cpu = HPPA_CPU(cs); CPUHPPAState *env = &cpu->env; - target_ulong psw = cpu_hppa_get_psw(env); - target_ulong psw_cb; + target_ureg psw = cpu_hppa_get_psw(env); + target_ureg psw_cb; char psw_c[20]; int i; cpu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx "\n", - env->iaoq_f, env->iaoq_b); + (target_ulong)env->iaoq_f, (target_ulong)env->iaoq_b); psw_c[0] = (psw & PSW_W ? 'W' : '-'); psw_c[1] = (psw & PSW_E ? 'E' : '-'); @@ -164,11 +164,11 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, psw_c[18] = '\0'; psw_cb = ((env->psw_cb >> 4) & 0x01111111) | (env->psw_cb_msb << 28); - cpu_fprintf(f, "PSW " TARGET_FMT_lx " CB " TARGET_FMT_lx " %s\n", + cpu_fprintf(f, "PSW " TREG_FMT_lx " CB " TREG_FMT_lx " %s\n", psw, psw_cb, psw_c); for (i = 0; i < 32; i++) { - cpu_fprintf(f, "GR%02d " TARGET_FMT_lx " ", i, env->gr[i]); + cpu_fprintf(f, "GR%02d " TREG_FMT_lx " ", i, env->gr[i]); if ((i % 4) == 3) { cpu_fprintf(f, "\n"); } diff --git a/target/hppa/helper.h b/target/hppa/helper.h index 0a6b900555..c720de523b 100644 --- a/target/hppa/helper.h +++ b/target/hppa/helper.h @@ -1,14 +1,24 @@ +#if TARGET_REGISTER_BITS == 64 +# define dh_alias_tr i64 +# define dh_is_64bit_tr 1 +#else +# define dh_alias_tr i32 +# define dh_is_64bit_tr 0 +#endif +#define dh_ctype_tr target_ureg +#define dh_is_signed_tr 0 + DEF_HELPER_2(excp, noreturn, env, int) -DEF_HELPER_FLAGS_2(tsv, TCG_CALL_NO_WG, void, env, tl) -DEF_HELPER_FLAGS_2(tcond, TCG_CALL_NO_WG, void, env, tl) +DEF_HELPER_FLAGS_2(tsv, TCG_CALL_NO_WG, void, env, tr) +DEF_HELPER_FLAGS_2(tcond, TCG_CALL_NO_WG, void, env, tr) -DEF_HELPER_FLAGS_3(stby_b, TCG_CALL_NO_WG, void, env, tl, tl) -DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, env, tl, tl) -DEF_HELPER_FLAGS_3(stby_e, TCG_CALL_NO_WG, void, env, tl, tl) -DEF_HELPER_FLAGS_3(stby_e_parallel, TCG_CALL_NO_WG, void, env, tl, tl) +DEF_HELPER_FLAGS_3(stby_b, TCG_CALL_NO_WG, void, env, tl, tr) +DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, env, tl, tr) +DEF_HELPER_FLAGS_3(stby_e, TCG_CALL_NO_WG, void, env, tl, tr) +DEF_HELPER_FLAGS_3(stby_e_parallel, TCG_CALL_NO_WG, void, env, tl, tr) -DEF_HELPER_FLAGS_1(probe_r, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_FLAGS_1(probe_w, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(probe_r, TCG_CALL_NO_RWG_SE, tr, tl) +DEF_HELPER_FLAGS_1(probe_w, TCG_CALL_NO_RWG_SE, tr, tl) DEF_HELPER_FLAGS_1(loaded_fr0, TCG_CALL_NO_RWG, void, env) diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index ecf5824074..4ab4ee8a77 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -41,14 +41,14 @@ static void QEMU_NORETURN dynexcp(CPUHPPAState *env, int excp, uintptr_t ra) cpu_loop_exit_restore(cs, ra); } -void HELPER(tsv)(CPUHPPAState *env, target_ulong cond) +void HELPER(tsv)(CPUHPPAState *env, target_ureg cond) { - if (unlikely((target_long)cond < 0)) { + if (unlikely((target_sreg)cond < 0)) { dynexcp(env, EXCP_OVERFLOW, GETPC()); } } -void HELPER(tcond)(CPUHPPAState *env, target_ulong cond) +void HELPER(tcond)(CPUHPPAState *env, target_ureg cond) { if (unlikely(cond)) { dynexcp(env, EXCP_COND, GETPC()); @@ -77,7 +77,7 @@ static void atomic_store_3(CPUHPPAState *env, target_ulong addr, uint32_t val, #endif } -static void do_stby_b(CPUHPPAState *env, target_ulong addr, target_ulong val, +static void do_stby_b(CPUHPPAState *env, target_ulong addr, target_ureg val, bool parallel) { uintptr_t ra = GETPC(); @@ -104,18 +104,18 @@ static void do_stby_b(CPUHPPAState *env, target_ulong addr, target_ulong val, } } -void HELPER(stby_b)(CPUHPPAState *env, target_ulong addr, target_ulong val) +void HELPER(stby_b)(CPUHPPAState *env, target_ulong addr, target_ureg val) { do_stby_b(env, addr, val, false); } void HELPER(stby_b_parallel)(CPUHPPAState *env, target_ulong addr, - target_ulong val) + target_ureg val) { do_stby_b(env, addr, val, true); } -static void do_stby_e(CPUHPPAState *env, target_ulong addr, target_ulong val, +static void do_stby_e(CPUHPPAState *env, target_ulong addr, target_ureg val, bool parallel) { uintptr_t ra = GETPC(); @@ -146,18 +146,18 @@ static void do_stby_e(CPUHPPAState *env, target_ulong addr, target_ulong val, } } -void HELPER(stby_e)(CPUHPPAState *env, target_ulong addr, target_ulong val) +void HELPER(stby_e)(CPUHPPAState *env, target_ulong addr, target_ureg val) { do_stby_e(env, addr, val, false); } void HELPER(stby_e_parallel)(CPUHPPAState *env, target_ulong addr, - target_ulong val) + target_ureg val) { do_stby_e(env, addr, val, true); } -target_ulong HELPER(probe_r)(target_ulong addr) +target_ureg HELPER(probe_r)(target_ulong addr) { #ifdef CONFIG_USER_ONLY return page_check_range(addr, 1, PAGE_READ); @@ -166,7 +166,7 @@ target_ulong HELPER(probe_r)(target_ulong addr) #endif } -target_ulong HELPER(probe_w)(target_ulong addr) +target_ureg HELPER(probe_w)(target_ulong addr) { #ifdef CONFIG_USER_ONLY return page_check_range(addr, 1, PAGE_WRITE); diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 8d85ed9df3..dd96147bf1 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -30,9 +30,239 @@ #include "trace-tcg.h" #include "exec/log.h" +/* Since we have a distinction between register size and address size, + we need to redefine all of these. */ + +#undef TCGv +#undef tcg_temp_new +#undef tcg_global_reg_new +#undef tcg_global_mem_new +#undef tcg_temp_local_new +#undef tcg_temp_free + +#if TARGET_LONG_BITS == 64 +#define TCGv_tl TCGv_i64 +#define tcg_temp_new_tl tcg_temp_new_i64 +#define tcg_temp_free_tl tcg_temp_free_i64 +#if TARGET_REGISTER_BITS == 64 +#define tcg_gen_extu_reg_tl tcg_gen_mov_i64 +#else +#define tcg_gen_extu_reg_tl tcg_gen_extu_i32_i64 +#endif +#else +#define TCGv_tl TCGv_i32 +#define tcg_temp_new_tl tcg_temp_new_i32 +#define tcg_temp_free_tl tcg_temp_free_i32 +#define tcg_gen_extu_reg_tl tcg_gen_mov_i32 +#endif + +#if TARGET_REGISTER_BITS == 64 +#define TCGv_reg TCGv_i64 + +#define tcg_temp_new tcg_temp_new_i64 +#define tcg_global_reg_new tcg_global_reg_new_i64 +#define tcg_global_mem_new tcg_global_mem_new_i64 +#define tcg_temp_local_new tcg_temp_local_new_i64 +#define tcg_temp_free tcg_temp_free_i64 + +#define tcg_gen_movi_reg tcg_gen_movi_i64 +#define tcg_gen_mov_reg tcg_gen_mov_i64 +#define tcg_gen_ld8u_reg tcg_gen_ld8u_i64 +#define tcg_gen_ld8s_reg tcg_gen_ld8s_i64 +#define tcg_gen_ld16u_reg tcg_gen_ld16u_i64 +#define tcg_gen_ld16s_reg tcg_gen_ld16s_i64 +#define tcg_gen_ld32u_reg tcg_gen_ld32u_i64 +#define tcg_gen_ld32s_reg tcg_gen_ld32s_i64 +#define tcg_gen_ld_reg tcg_gen_ld_i64 +#define tcg_gen_st8_reg tcg_gen_st8_i64 +#define tcg_gen_st16_reg tcg_gen_st16_i64 +#define tcg_gen_st32_reg tcg_gen_st32_i64 +#define tcg_gen_st_reg tcg_gen_st_i64 +#define tcg_gen_add_reg tcg_gen_add_i64 +#define tcg_gen_addi_reg tcg_gen_addi_i64 +#define tcg_gen_sub_reg tcg_gen_sub_i64 +#define tcg_gen_neg_reg tcg_gen_neg_i64 +#define tcg_gen_subfi_reg tcg_gen_subfi_i64 +#define tcg_gen_subi_reg tcg_gen_subi_i64 +#define tcg_gen_and_reg tcg_gen_and_i64 +#define tcg_gen_andi_reg tcg_gen_andi_i64 +#define tcg_gen_or_reg tcg_gen_or_i64 +#define tcg_gen_ori_reg tcg_gen_ori_i64 +#define tcg_gen_xor_reg tcg_gen_xor_i64 +#define tcg_gen_xori_reg tcg_gen_xori_i64 +#define tcg_gen_not_reg tcg_gen_not_i64 +#define tcg_gen_shl_reg tcg_gen_shl_i64 +#define tcg_gen_shli_reg tcg_gen_shli_i64 +#define tcg_gen_shr_reg tcg_gen_shr_i64 +#define tcg_gen_shri_reg tcg_gen_shri_i64 +#define tcg_gen_sar_reg tcg_gen_sar_i64 +#define tcg_gen_sari_reg tcg_gen_sari_i64 +#define tcg_gen_brcond_reg tcg_gen_brcond_i64 +#define tcg_gen_brcondi_reg tcg_gen_brcondi_i64 +#define tcg_gen_setcond_reg tcg_gen_setcond_i64 +#define tcg_gen_setcondi_reg tcg_gen_setcondi_i64 +#define tcg_gen_mul_reg tcg_gen_mul_i64 +#define tcg_gen_muli_reg tcg_gen_muli_i64 +#define tcg_gen_div_reg tcg_gen_div_i64 +#define tcg_gen_rem_reg tcg_gen_rem_i64 +#define tcg_gen_divu_reg tcg_gen_divu_i64 +#define tcg_gen_remu_reg tcg_gen_remu_i64 +#define tcg_gen_discard_reg tcg_gen_discard_i64 +#define tcg_gen_trunc_reg_i32 tcg_gen_extrl_i64_i32 +#define tcg_gen_trunc_i64_reg tcg_gen_mov_i64 +#define tcg_gen_extu_i32_reg tcg_gen_extu_i32_i64 +#define tcg_gen_ext_i32_reg tcg_gen_ext_i32_i64 +#define tcg_gen_extu_reg_i64 tcg_gen_mov_i64 +#define tcg_gen_ext_reg_i64 tcg_gen_mov_i64 +#define tcg_gen_ext8u_reg tcg_gen_ext8u_i64 +#define tcg_gen_ext8s_reg tcg_gen_ext8s_i64 +#define tcg_gen_ext16u_reg tcg_gen_ext16u_i64 +#define tcg_gen_ext16s_reg tcg_gen_ext16s_i64 +#define tcg_gen_ext32u_reg tcg_gen_ext32u_i64 +#define tcg_gen_ext32s_reg tcg_gen_ext32s_i64 +#define tcg_gen_bswap16_reg tcg_gen_bswap16_i64 +#define tcg_gen_bswap32_reg tcg_gen_bswap32_i64 +#define tcg_gen_bswap64_reg tcg_gen_bswap64_i64 +#define tcg_gen_concat_reg_i64 tcg_gen_concat32_i64 +#define tcg_gen_andc_reg tcg_gen_andc_i64 +#define tcg_gen_eqv_reg tcg_gen_eqv_i64 +#define tcg_gen_nand_reg tcg_gen_nand_i64 +#define tcg_gen_nor_reg tcg_gen_nor_i64 +#define tcg_gen_orc_reg tcg_gen_orc_i64 +#define tcg_gen_clz_reg tcg_gen_clz_i64 +#define tcg_gen_ctz_reg tcg_gen_ctz_i64 +#define tcg_gen_clzi_reg tcg_gen_clzi_i64 +#define tcg_gen_ctzi_reg tcg_gen_ctzi_i64 +#define tcg_gen_clrsb_reg tcg_gen_clrsb_i64 +#define tcg_gen_ctpop_reg tcg_gen_ctpop_i64 +#define tcg_gen_rotl_reg tcg_gen_rotl_i64 +#define tcg_gen_rotli_reg tcg_gen_rotli_i64 +#define tcg_gen_rotr_reg tcg_gen_rotr_i64 +#define tcg_gen_rotri_reg tcg_gen_rotri_i64 +#define tcg_gen_deposit_reg tcg_gen_deposit_i64 +#define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i64 +#define tcg_gen_extract_reg tcg_gen_extract_i64 +#define tcg_gen_sextract_reg tcg_gen_sextract_i64 +#define tcg_const_reg tcg_const_i64 +#define tcg_const_local_reg tcg_const_local_i64 +#define tcg_gen_movcond_reg tcg_gen_movcond_i64 +#define tcg_gen_add2_reg tcg_gen_add2_i64 +#define tcg_gen_sub2_reg tcg_gen_sub2_i64 +#define tcg_gen_qemu_ld_reg tcg_gen_qemu_ld_i64 +#define tcg_gen_qemu_st_reg tcg_gen_qemu_st_i64 +#define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i64 +#if UINTPTR_MAX == UINT32_MAX +# define tcg_gen_trunc_reg_ptr(p, r) \ + tcg_gen_trunc_i64_i32(TCGV_PTR_TO_NAT(p), r) +#else +# define tcg_gen_trunc_reg_ptr(p, r) \ + tcg_gen_mov_i64(TCGV_PTR_TO_NAT(p), r) +#endif +#else +#define TCGv_reg TCGv_i32 +#define tcg_temp_new tcg_temp_new_i32 +#define tcg_global_reg_new tcg_global_reg_new_i32 +#define tcg_global_mem_new tcg_global_mem_new_i32 +#define tcg_temp_local_new tcg_temp_local_new_i32 +#define tcg_temp_free tcg_temp_free_i32 + +#define tcg_gen_movi_reg tcg_gen_movi_i32 +#define tcg_gen_mov_reg tcg_gen_mov_i32 +#define tcg_gen_ld8u_reg tcg_gen_ld8u_i32 +#define tcg_gen_ld8s_reg tcg_gen_ld8s_i32 +#define tcg_gen_ld16u_reg tcg_gen_ld16u_i32 +#define tcg_gen_ld16s_reg tcg_gen_ld16s_i32 +#define tcg_gen_ld32u_reg tcg_gen_ld_i32 +#define tcg_gen_ld32s_reg tcg_gen_ld_i32 +#define tcg_gen_ld_reg tcg_gen_ld_i32 +#define tcg_gen_st8_reg tcg_gen_st8_i32 +#define tcg_gen_st16_reg tcg_gen_st16_i32 +#define tcg_gen_st32_reg tcg_gen_st32_i32 +#define tcg_gen_st_reg tcg_gen_st_i32 +#define tcg_gen_add_reg tcg_gen_add_i32 +#define tcg_gen_addi_reg tcg_gen_addi_i32 +#define tcg_gen_sub_reg tcg_gen_sub_i32 +#define tcg_gen_neg_reg tcg_gen_neg_i32 +#define tcg_gen_subfi_reg tcg_gen_subfi_i32 +#define tcg_gen_subi_reg tcg_gen_subi_i32 +#define tcg_gen_and_reg tcg_gen_and_i32 +#define tcg_gen_andi_reg tcg_gen_andi_i32 +#define tcg_gen_or_reg tcg_gen_or_i32 +#define tcg_gen_ori_reg tcg_gen_ori_i32 +#define tcg_gen_xor_reg tcg_gen_xor_i32 +#define tcg_gen_xori_reg tcg_gen_xori_i32 +#define tcg_gen_not_reg tcg_gen_not_i32 +#define tcg_gen_shl_reg tcg_gen_shl_i32 +#define tcg_gen_shli_reg tcg_gen_shli_i32 +#define tcg_gen_shr_reg tcg_gen_shr_i32 +#define tcg_gen_shri_reg tcg_gen_shri_i32 +#define tcg_gen_sar_reg tcg_gen_sar_i32 +#define tcg_gen_sari_reg tcg_gen_sari_i32 +#define tcg_gen_brcond_reg tcg_gen_brcond_i32 +#define tcg_gen_brcondi_reg tcg_gen_brcondi_i32 +#define tcg_gen_setcond_reg tcg_gen_setcond_i32 +#define tcg_gen_setcondi_reg tcg_gen_setcondi_i32 +#define tcg_gen_mul_reg tcg_gen_mul_i32 +#define tcg_gen_muli_reg tcg_gen_muli_i32 +#define tcg_gen_div_reg tcg_gen_div_i32 +#define tcg_gen_rem_reg tcg_gen_rem_i32 +#define tcg_gen_divu_reg tcg_gen_divu_i32 +#define tcg_gen_remu_reg tcg_gen_remu_i32 +#define tcg_gen_discard_reg tcg_gen_discard_i32 +#define tcg_gen_trunc_reg_i32 tcg_gen_mov_i32 +#define tcg_gen_trunc_i64_reg tcg_gen_extrl_i64_i32 +#define tcg_gen_extu_i32_reg tcg_gen_mov_i32 +#define tcg_gen_ext_i32_reg tcg_gen_mov_i32 +#define tcg_gen_extu_reg_i64 tcg_gen_extu_i32_i64 +#define tcg_gen_ext_reg_i64 tcg_gen_ext_i32_i64 +#define tcg_gen_ext8u_reg tcg_gen_ext8u_i32 +#define tcg_gen_ext8s_reg tcg_gen_ext8s_i32 +#define tcg_gen_ext16u_reg tcg_gen_ext16u_i32 +#define tcg_gen_ext16s_reg tcg_gen_ext16s_i32 +#define tcg_gen_ext32u_reg tcg_gen_mov_i32 +#define tcg_gen_ext32s_reg tcg_gen_mov_i32 +#define tcg_gen_bswap16_reg tcg_gen_bswap16_i32 +#define tcg_gen_bswap32_reg tcg_gen_bswap32_i32 +#define tcg_gen_concat_reg_i64 tcg_gen_concat_i32_i64 +#define tcg_gen_andc_reg tcg_gen_andc_i32 +#define tcg_gen_eqv_reg tcg_gen_eqv_i32 +#define tcg_gen_nand_reg tcg_gen_nand_i32 +#define tcg_gen_nor_reg tcg_gen_nor_i32 +#define tcg_gen_orc_reg tcg_gen_orc_i32 +#define tcg_gen_clz_reg tcg_gen_clz_i32 +#define tcg_gen_ctz_reg tcg_gen_ctz_i32 +#define tcg_gen_clzi_reg tcg_gen_clzi_i32 +#define tcg_gen_ctzi_reg tcg_gen_ctzi_i32 +#define tcg_gen_clrsb_reg tcg_gen_clrsb_i32 +#define tcg_gen_ctpop_reg tcg_gen_ctpop_i32 +#define tcg_gen_rotl_reg tcg_gen_rotl_i32 +#define tcg_gen_rotli_reg tcg_gen_rotli_i32 +#define tcg_gen_rotr_reg tcg_gen_rotr_i32 +#define tcg_gen_rotri_reg tcg_gen_rotri_i32 +#define tcg_gen_deposit_reg tcg_gen_deposit_i32 +#define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i32 +#define tcg_gen_extract_reg tcg_gen_extract_i32 +#define tcg_gen_sextract_reg tcg_gen_sextract_i32 +#define tcg_const_reg tcg_const_i32 +#define tcg_const_local_reg tcg_const_local_i32 +#define tcg_gen_movcond_reg tcg_gen_movcond_i32 +#define tcg_gen_add2_reg tcg_gen_add2_i32 +#define tcg_gen_sub2_reg tcg_gen_sub2_i32 +#define tcg_gen_qemu_ld_reg tcg_gen_qemu_ld_i32 +#define tcg_gen_qemu_st_reg tcg_gen_qemu_st_i32 +#define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i32 +#if UINTPTR_MAX == UINT32_MAX +# define tcg_gen_trunc_reg_ptr(p, r) \ + tcg_gen_mov_i32(TCGV_PTR_TO_NAT(p), r) +#else +# define tcg_gen_trunc_reg_ptr(p, r) \ + tcg_gen_extu_i32_i64(TCGV_PTR_TO_NAT(p), r) +#endif +#endif /* TARGET_REGISTER_BITS */ + typedef struct DisasCond { TCGCond c; - TCGv a0, a1; + TCGv_reg a0, a1; bool a0_is_n; bool a1_is_0; } DisasCond; @@ -41,13 +271,13 @@ typedef struct DisasContext { DisasContextBase base; CPUState *cs; - target_ulong iaoq_f; - target_ulong iaoq_b; - target_ulong iaoq_n; - TCGv iaoq_n_var; + target_ureg iaoq_f; + target_ureg iaoq_b; + target_ureg iaoq_n; + TCGv_reg iaoq_n_var; int ntemps; - TCGv temps[8]; + TCGv_reg temps[8]; DisasCond null_cond; TCGLabel *null_lab; @@ -72,7 +302,7 @@ typedef struct DisasInsn { DisasJumpType (*trans)(DisasContext *ctx, uint32_t insn, const struct DisasInsn *f); union { - void (*ttt)(TCGv, TCGv, TCGv); + void (*ttt)(TCGv_reg, TCGv_reg, TCGv_reg); void (*weww)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32); void (*dedd)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64); void (*wew)(TCGv_i32, TCGv_env, TCGv_i32); @@ -83,16 +313,16 @@ typedef struct DisasInsn { } DisasInsn; /* global register indexes */ -static TCGv cpu_gr[32]; -static TCGv cpu_iaoq_f; -static TCGv cpu_iaoq_b; -static TCGv cpu_sar; -static TCGv cpu_psw_n; -static TCGv cpu_psw_v; -static TCGv cpu_psw_cb; -static TCGv cpu_psw_cb_msb; -static TCGv cpu_cr26; -static TCGv cpu_cr27; +static TCGv_reg cpu_gr[32]; +static TCGv_reg cpu_iaoq_f; +static TCGv_reg cpu_iaoq_b; +static TCGv_reg cpu_sar; +static TCGv_reg cpu_psw_n; +static TCGv_reg cpu_psw_v; +static TCGv_reg cpu_psw_cb; +static TCGv_reg cpu_psw_cb_msb; +static TCGv_reg cpu_cr26; +static TCGv_reg cpu_cr27; #include "exec/gen-icount.h" @@ -100,7 +330,7 @@ void hppa_translate_init(void) { #define DEF_VAR(V) { &cpu_##V, #V, offsetof(CPUHPPAState, V) } - typedef struct { TCGv *var; const char *name; int ofs; } GlobalVar; + typedef struct { TCGv_reg *var; const char *name; int ofs; } GlobalVar; static const GlobalVar vars[] = { DEF_VAR(sar), DEF_VAR(cr26), @@ -158,26 +388,26 @@ static DisasCond cond_make_n(void) }; } -static DisasCond cond_make_0(TCGCond c, TCGv a0) +static DisasCond cond_make_0(TCGCond c, TCGv_reg a0) { DisasCond r = { .c = c, .a1 = NULL, .a1_is_0 = true }; assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS); r.a0 = tcg_temp_new(); - tcg_gen_mov_tl(r.a0, a0); + tcg_gen_mov_reg(r.a0, a0); return r; } -static DisasCond cond_make(TCGCond c, TCGv a0, TCGv a1) +static DisasCond cond_make(TCGCond c, TCGv_reg a0, TCGv_reg a1) { DisasCond r = { .c = c }; assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS); r.a0 = tcg_temp_new(); - tcg_gen_mov_tl(r.a0, a0); + tcg_gen_mov_reg(r.a0, a0); r.a1 = tcg_temp_new(); - tcg_gen_mov_tl(r.a1, a1); + tcg_gen_mov_reg(r.a1, a1); return r; } @@ -186,7 +416,7 @@ static void cond_prep(DisasCond *cond) { if (cond->a1_is_0) { cond->a1_is_0 = false; - cond->a1 = tcg_const_tl(0); + cond->a1 = tcg_const_reg(0); } } @@ -213,32 +443,32 @@ static void cond_free(DisasCond *cond) } } -static TCGv get_temp(DisasContext *ctx) +static TCGv_reg get_temp(DisasContext *ctx) { unsigned i = ctx->ntemps++; g_assert(i < ARRAY_SIZE(ctx->temps)); return ctx->temps[i] = tcg_temp_new(); } -static TCGv load_const(DisasContext *ctx, target_long v) +static TCGv_reg load_const(DisasContext *ctx, target_sreg v) { - TCGv t = get_temp(ctx); - tcg_gen_movi_tl(t, v); + TCGv_reg t = get_temp(ctx); + tcg_gen_movi_reg(t, v); return t; } -static TCGv load_gpr(DisasContext *ctx, unsigned reg) +static TCGv_reg load_gpr(DisasContext *ctx, unsigned reg) { if (reg == 0) { - TCGv t = get_temp(ctx); - tcg_gen_movi_tl(t, 0); + TCGv_reg t = get_temp(ctx); + tcg_gen_movi_reg(t, 0); return t; } else { return cpu_gr[reg]; } } -static TCGv dest_gpr(DisasContext *ctx, unsigned reg) +static TCGv_reg dest_gpr(DisasContext *ctx, unsigned reg) { if (reg == 0 || ctx->null_cond.c != TCG_COND_NEVER) { return get_temp(ctx); @@ -247,18 +477,18 @@ static TCGv dest_gpr(DisasContext *ctx, unsigned reg) } } -static void save_or_nullify(DisasContext *ctx, TCGv dest, TCGv t) +static void save_or_nullify(DisasContext *ctx, TCGv_reg dest, TCGv_reg t) { if (ctx->null_cond.c != TCG_COND_NEVER) { cond_prep(&ctx->null_cond); - tcg_gen_movcond_tl(ctx->null_cond.c, dest, ctx->null_cond.a0, + tcg_gen_movcond_reg(ctx->null_cond.c, dest, ctx->null_cond.a0, ctx->null_cond.a1, dest, t); } else { - tcg_gen_mov_tl(dest, t); + tcg_gen_mov_reg(dest, t); } } -static void save_gpr(DisasContext *ctx, unsigned reg, TCGv t) +static void save_gpr(DisasContext *ctx, unsigned reg, TCGv_reg t) { if (reg != 0) { save_or_nullify(ctx, cpu_gr[reg], t); @@ -350,17 +580,17 @@ static void nullify_over(DisasContext *ctx) if (ctx->null_cond.a0_is_n) { ctx->null_cond.a0_is_n = false; ctx->null_cond.a0 = tcg_temp_new(); - tcg_gen_mov_tl(ctx->null_cond.a0, cpu_psw_n); + tcg_gen_mov_reg(ctx->null_cond.a0, cpu_psw_n); } /* ... we clear it before branching over the implementation, so that (1) it's clear after nullifying this insn and (2) if this insn nullifies the next, PSW[N] is valid. */ if (ctx->psw_n_nonzero) { ctx->psw_n_nonzero = false; - tcg_gen_movi_tl(cpu_psw_n, 0); + tcg_gen_movi_reg(cpu_psw_n, 0); } - tcg_gen_brcond_tl(ctx->null_cond.c, ctx->null_cond.a0, + tcg_gen_brcond_reg(ctx->null_cond.c, ctx->null_cond.a0, ctx->null_cond.a1, ctx->null_lab); cond_free(&ctx->null_cond); } @@ -371,13 +601,13 @@ static void nullify_save(DisasContext *ctx) { if (ctx->null_cond.c == TCG_COND_NEVER) { if (ctx->psw_n_nonzero) { - tcg_gen_movi_tl(cpu_psw_n, 0); + tcg_gen_movi_reg(cpu_psw_n, 0); } return; } if (!ctx->null_cond.a0_is_n) { cond_prep(&ctx->null_cond); - tcg_gen_setcond_tl(ctx->null_cond.c, cpu_psw_n, + tcg_gen_setcond_reg(ctx->null_cond.c, cpu_psw_n, ctx->null_cond.a0, ctx->null_cond.a1); ctx->psw_n_nonzero = true; } @@ -390,7 +620,7 @@ static void nullify_save(DisasContext *ctx) static void nullify_set(DisasContext *ctx, bool x) { if (ctx->psw_n_nonzero || x) { - tcg_gen_movi_tl(cpu_psw_n, x); + tcg_gen_movi_reg(cpu_psw_n, x); } } @@ -429,16 +659,16 @@ static DisasJumpType nullify_end(DisasContext *ctx, DisasJumpType status) return status; } -static void copy_iaoq_entry(TCGv dest, target_ulong ival, TCGv vval) +static void copy_iaoq_entry(TCGv_reg dest, target_ureg ival, TCGv_reg vval) { if (unlikely(ival == -1)) { - tcg_gen_mov_tl(dest, vval); + tcg_gen_mov_reg(dest, vval); } else { - tcg_gen_movi_tl(dest, ival); + tcg_gen_movi_reg(dest, ival); } } -static inline target_ulong iaoq_dest(DisasContext *ctx, target_long disp) +static inline target_ureg iaoq_dest(DisasContext *ctx, target_sreg disp) { return ctx->iaoq_f + disp + 8; } @@ -465,7 +695,7 @@ static DisasJumpType gen_illegal(DisasContext *ctx) return nullify_end(ctx, gen_excp(ctx, EXCP_ILL)); } -static bool use_goto_tb(DisasContext *ctx, target_ulong dest) +static bool use_goto_tb(DisasContext *ctx, target_ureg dest) { /* Suppress goto_tb in the case of single-steping and IO. */ if ((tb_cflags(ctx->base.tb) & CF_LAST_IO) || ctx->base.singlestep_enabled) { @@ -485,12 +715,12 @@ static bool use_nullify_skip(DisasContext *ctx) } static void gen_goto_tb(DisasContext *ctx, int which, - target_ulong f, target_ulong b) + target_ureg f, target_ureg b) { if (f != -1 && b != -1 && use_goto_tb(ctx, f)) { tcg_gen_goto_tb(which); - tcg_gen_movi_tl(cpu_iaoq_f, f); - tcg_gen_movi_tl(cpu_iaoq_b, b); + tcg_gen_movi_reg(cpu_iaoq_f, f); + tcg_gen_movi_reg(cpu_iaoq_b, b); tcg_gen_exit_tb((uintptr_t)ctx->base.tb + which); } else { copy_iaoq_entry(cpu_iaoq_f, f, cpu_iaoq_b); @@ -505,9 +735,9 @@ static void gen_goto_tb(DisasContext *ctx, int which, /* PA has a habit of taking the LSB of a field and using that as the sign, with the rest of the field becoming the least significant bits. */ -static target_long low_sextract(uint32_t val, int pos, int len) +static target_sreg low_sextract(uint32_t val, int pos, int len) { - target_ulong x = -(target_ulong)extract32(val, pos, 1); + target_ureg x = -(target_ureg)extract32(val, pos, 1); x = (x << (len - 1)) | extract32(val, pos + 1, len - 1); return x; } @@ -541,15 +771,15 @@ static unsigned assemble_rc64(uint32_t insn) return r2 * 32 + r1 * 4 + r0; } -static target_long assemble_12(uint32_t insn) +static target_sreg assemble_12(uint32_t insn) { - target_ulong x = -(target_ulong)(insn & 1); + target_ureg x = -(target_ureg)(insn & 1); x = (x << 1) | extract32(insn, 2, 1); x = (x << 10) | extract32(insn, 3, 10); return x; } -static target_long assemble_16(uint32_t insn) +static target_sreg assemble_16(uint32_t insn) { /* Take the name from PA2.0, which produces a 16-bit number only with wide mode; otherwise a 14-bit number. Since we don't @@ -557,28 +787,28 @@ static target_long assemble_16(uint32_t insn) return low_sextract(insn, 0, 14); } -static target_long assemble_16a(uint32_t insn) +static target_sreg assemble_16a(uint32_t insn) { /* Take the name from PA2.0, which produces a 14-bit shifted number only with wide mode; otherwise a 12-bit shifted number. Since we don't implement wide mode, this is always the 12-bit number. */ - target_ulong x = -(target_ulong)(insn & 1); + target_ureg x = -(target_ureg)(insn & 1); x = (x << 11) | extract32(insn, 2, 11); return x << 2; } -static target_long assemble_17(uint32_t insn) +static target_sreg assemble_17(uint32_t insn) { - target_ulong x = -(target_ulong)(insn & 1); + target_ureg x = -(target_ureg)(insn & 1); x = (x << 5) | extract32(insn, 16, 5); x = (x << 1) | extract32(insn, 2, 1); x = (x << 10) | extract32(insn, 3, 10); return x << 2; } -static target_long assemble_21(uint32_t insn) +static target_sreg assemble_21(uint32_t insn) { - target_ulong x = -(target_ulong)(insn & 1); + target_ureg x = -(target_ureg)(insn & 1); x = (x << 11) | extract32(insn, 1, 11); x = (x << 2) | extract32(insn, 14, 2); x = (x << 5) | extract32(insn, 16, 5); @@ -586,9 +816,9 @@ static target_long assemble_21(uint32_t insn) return x << 11; } -static target_long assemble_22(uint32_t insn) +static target_sreg assemble_22(uint32_t insn) { - target_ulong x = -(target_ulong)(insn & 1); + target_ureg x = -(target_ureg)(insn & 1); x = (x << 10) | extract32(insn, 16, 10); x = (x << 1) | extract32(insn, 2, 1); x = (x << 10) | extract32(insn, 3, 10); @@ -602,10 +832,11 @@ static target_long assemble_22(uint32_t insn) as a whole it would appear that these relations are similar to what a traditional NZCV set of flags would produce. */ -static DisasCond do_cond(unsigned cf, TCGv res, TCGv cb_msb, TCGv sv) +static DisasCond do_cond(unsigned cf, TCGv_reg res, + TCGv_reg cb_msb, TCGv_reg sv) { DisasCond cond; - TCGv tmp; + TCGv_reg tmp; switch (cf >> 1) { case 0: /* Never / TR */ @@ -625,8 +856,8 @@ static DisasCond do_cond(unsigned cf, TCGv res, TCGv cb_msb, TCGv sv) break; case 5: /* ZNV / VNZ (!C | Z / C & !Z) */ tmp = tcg_temp_new(); - tcg_gen_neg_tl(tmp, cb_msb); - tcg_gen_and_tl(tmp, tmp, res); + tcg_gen_neg_reg(tmp, cb_msb); + tcg_gen_and_reg(tmp, tmp, res); cond = cond_make_0(TCG_COND_EQ, tmp); tcg_temp_free(tmp); break; @@ -635,7 +866,7 @@ static DisasCond do_cond(unsigned cf, TCGv res, TCGv cb_msb, TCGv sv) break; case 7: /* OD / EV */ tmp = tcg_temp_new(); - tcg_gen_andi_tl(tmp, res, 1); + tcg_gen_andi_reg(tmp, res, 1); cond = cond_make_0(TCG_COND_NE, tmp); tcg_temp_free(tmp); break; @@ -653,7 +884,8 @@ static DisasCond do_cond(unsigned cf, TCGv res, TCGv cb_msb, TCGv sv) can use the inputs directly. This can allow other computation to be deleted as unused. */ -static DisasCond do_sub_cond(unsigned cf, TCGv res, TCGv in1, TCGv in2, TCGv sv) +static DisasCond do_sub_cond(unsigned cf, TCGv_reg res, + TCGv_reg in1, TCGv_reg in2, TCGv_reg sv) { DisasCond cond; @@ -686,7 +918,7 @@ static DisasCond do_sub_cond(unsigned cf, TCGv res, TCGv in1, TCGv in2, TCGv sv) /* Similar, but for logicals, where the carry and overflow bits are not computed, and use of them is undefined. */ -static DisasCond do_log_cond(unsigned cf, TCGv res) +static DisasCond do_log_cond(unsigned cf, TCGv_reg res) { switch (cf >> 1) { case 4: case 5: case 6: @@ -698,7 +930,7 @@ static DisasCond do_log_cond(unsigned cf, TCGv res) /* Similar, but for shift/extract/deposit conditions. */ -static DisasCond do_sed_cond(unsigned orig, TCGv res) +static DisasCond do_sed_cond(unsigned orig, TCGv_reg res) { unsigned c, f; @@ -716,10 +948,11 @@ static DisasCond do_sed_cond(unsigned orig, TCGv res) /* Similar, but for unit conditions. */ -static DisasCond do_unit_cond(unsigned cf, TCGv res, TCGv in1, TCGv in2) +static DisasCond do_unit_cond(unsigned cf, TCGv_reg res, + TCGv_reg in1, TCGv_reg in2) { DisasCond cond; - TCGv tmp, cb = NULL; + TCGv_reg tmp, cb = NULL; if (cf & 8) { /* Since we want to test lots of carry-out bits all at once, do not @@ -728,10 +961,10 @@ static DisasCond do_unit_cond(unsigned cf, TCGv res, TCGv in1, TCGv in2) */ cb = tcg_temp_new(); tmp = tcg_temp_new(); - tcg_gen_or_tl(cb, in1, in2); - tcg_gen_and_tl(tmp, in1, in2); - tcg_gen_andc_tl(cb, cb, res); - tcg_gen_or_tl(cb, cb, tmp); + tcg_gen_or_reg(cb, in1, in2); + tcg_gen_and_reg(tmp, in1, in2); + tcg_gen_andc_reg(cb, cb, res); + tcg_gen_or_reg(cb, cb, tmp); tcg_temp_free(tmp); } @@ -747,34 +980,34 @@ static DisasCond do_unit_cond(unsigned cf, TCGv res, TCGv in1, TCGv in2) * https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord */ tmp = tcg_temp_new(); - tcg_gen_subi_tl(tmp, res, 0x01010101u); - tcg_gen_andc_tl(tmp, tmp, res); - tcg_gen_andi_tl(tmp, tmp, 0x80808080u); + tcg_gen_subi_reg(tmp, res, 0x01010101u); + tcg_gen_andc_reg(tmp, tmp, res); + tcg_gen_andi_reg(tmp, tmp, 0x80808080u); cond = cond_make_0(TCG_COND_NE, tmp); tcg_temp_free(tmp); break; case 3: /* SHZ / NHZ */ tmp = tcg_temp_new(); - tcg_gen_subi_tl(tmp, res, 0x00010001u); - tcg_gen_andc_tl(tmp, tmp, res); - tcg_gen_andi_tl(tmp, tmp, 0x80008000u); + tcg_gen_subi_reg(tmp, res, 0x00010001u); + tcg_gen_andc_reg(tmp, tmp, res); + tcg_gen_andi_reg(tmp, tmp, 0x80008000u); cond = cond_make_0(TCG_COND_NE, tmp); tcg_temp_free(tmp); break; case 4: /* SDC / NDC */ - tcg_gen_andi_tl(cb, cb, 0x88888888u); + tcg_gen_andi_reg(cb, cb, 0x88888888u); cond = cond_make_0(TCG_COND_NE, cb); break; case 6: /* SBC / NBC */ - tcg_gen_andi_tl(cb, cb, 0x80808080u); + tcg_gen_andi_reg(cb, cb, 0x80808080u); cond = cond_make_0(TCG_COND_NE, cb); break; case 7: /* SHC / NHC */ - tcg_gen_andi_tl(cb, cb, 0x80008000u); + tcg_gen_andi_reg(cb, cb, 0x80008000u); cond = cond_make_0(TCG_COND_NE, cb); break; @@ -792,38 +1025,40 @@ static DisasCond do_unit_cond(unsigned cf, TCGv res, TCGv in1, TCGv in2) } /* Compute signed overflow for addition. */ -static TCGv do_add_sv(DisasContext *ctx, TCGv res, TCGv in1, TCGv in2) +static TCGv_reg do_add_sv(DisasContext *ctx, TCGv_reg res, + TCGv_reg in1, TCGv_reg in2) { - TCGv sv = get_temp(ctx); - TCGv tmp = tcg_temp_new(); + TCGv_reg sv = get_temp(ctx); + TCGv_reg tmp = tcg_temp_new(); - tcg_gen_xor_tl(sv, res, in1); - tcg_gen_xor_tl(tmp, in1, in2); - tcg_gen_andc_tl(sv, sv, tmp); + tcg_gen_xor_reg(sv, res, in1); + tcg_gen_xor_reg(tmp, in1, in2); + tcg_gen_andc_reg(sv, sv, tmp); tcg_temp_free(tmp); return sv; } /* Compute signed overflow for subtraction. */ -static TCGv do_sub_sv(DisasContext *ctx, TCGv res, TCGv in1, TCGv in2) +static TCGv_reg do_sub_sv(DisasContext *ctx, TCGv_reg res, + TCGv_reg in1, TCGv_reg in2) { - TCGv sv = get_temp(ctx); - TCGv tmp = tcg_temp_new(); + TCGv_reg sv = get_temp(ctx); + TCGv_reg tmp = tcg_temp_new(); - tcg_gen_xor_tl(sv, res, in1); - tcg_gen_xor_tl(tmp, in1, in2); - tcg_gen_and_tl(sv, sv, tmp); + tcg_gen_xor_reg(sv, res, in1); + tcg_gen_xor_reg(tmp, in1, in2); + tcg_gen_and_reg(sv, sv, tmp); tcg_temp_free(tmp); return sv; } -static DisasJumpType do_add(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2, - unsigned shift, bool is_l, bool is_tsv, bool is_tc, - bool is_c, unsigned cf) +static DisasJumpType do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1, + TCGv_reg in2, unsigned shift, bool is_l, + bool is_tsv, bool is_tc, bool is_c, unsigned cf) { - TCGv dest, cb, cb_msb, sv, tmp; + TCGv_reg dest, cb, cb_msb, sv, tmp; unsigned c = cf >> 1; DisasCond cond; @@ -833,27 +1068,27 @@ static DisasJumpType do_add(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2, if (shift) { tmp = get_temp(ctx); - tcg_gen_shli_tl(tmp, in1, shift); + tcg_gen_shli_reg(tmp, in1, shift); in1 = tmp; } if (!is_l || c == 4 || c == 5) { - TCGv zero = tcg_const_tl(0); + TCGv_reg zero = tcg_const_reg(0); cb_msb = get_temp(ctx); - tcg_gen_add2_tl(dest, cb_msb, in1, zero, in2, zero); + tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero); if (is_c) { - tcg_gen_add2_tl(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero); + tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero); } tcg_temp_free(zero); if (!is_l) { cb = get_temp(ctx); - tcg_gen_xor_tl(cb, in1, in2); - tcg_gen_xor_tl(cb, cb, dest); + tcg_gen_xor_reg(cb, in1, in2); + tcg_gen_xor_reg(cb, cb, dest); } } else { - tcg_gen_add_tl(dest, in1, in2); + tcg_gen_add_reg(dest, in1, in2); if (is_c) { - tcg_gen_add_tl(dest, dest, cpu_psw_cb_msb); + tcg_gen_add_reg(dest, dest, cpu_psw_cb_msb); } } @@ -872,7 +1107,7 @@ static DisasJumpType do_add(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2, if (is_tc) { cond_prep(&cond); tmp = tcg_temp_new(); - tcg_gen_setcond_tl(cond.c, tmp, cond.a0, cond.a1); + tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1); gen_helper_tcond(cpu_env, tmp); tcg_temp_free(tmp); } @@ -891,10 +1126,11 @@ static DisasJumpType do_add(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2, return DISAS_NEXT; } -static DisasJumpType do_sub(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2, - bool is_tsv, bool is_b, bool is_tc, unsigned cf) +static DisasJumpType do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1, + TCGv_reg in2, bool is_tsv, bool is_b, + bool is_tc, unsigned cf) { - TCGv dest, sv, cb, cb_msb, zero, tmp; + TCGv_reg dest, sv, cb, cb_msb, zero, tmp; unsigned c = cf >> 1; DisasCond cond; @@ -902,21 +1138,21 @@ static DisasJumpType do_sub(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2, cb = tcg_temp_new(); cb_msb = tcg_temp_new(); - zero = tcg_const_tl(0); + zero = tcg_const_reg(0); if (is_b) { /* DEST,C = IN1 + ~IN2 + C. */ - tcg_gen_not_tl(cb, in2); - tcg_gen_add2_tl(dest, cb_msb, in1, zero, cpu_psw_cb_msb, zero); - tcg_gen_add2_tl(dest, cb_msb, dest, cb_msb, cb, zero); - tcg_gen_xor_tl(cb, cb, in1); - tcg_gen_xor_tl(cb, cb, dest); + tcg_gen_not_reg(cb, in2); + tcg_gen_add2_reg(dest, cb_msb, in1, zero, cpu_psw_cb_msb, zero); + tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cb, zero); + tcg_gen_xor_reg(cb, cb, in1); + tcg_gen_xor_reg(cb, cb, dest); } else { /* DEST,C = IN1 + ~IN2 + 1. We can produce the same result in fewer operations by seeding the high word with 1 and subtracting. */ - tcg_gen_movi_tl(cb_msb, 1); - tcg_gen_sub2_tl(dest, cb_msb, in1, cb_msb, in2, zero); - tcg_gen_eqv_tl(cb, in1, in2); - tcg_gen_xor_tl(cb, cb, dest); + tcg_gen_movi_reg(cb_msb, 1); + tcg_gen_sub2_reg(dest, cb_msb, in1, cb_msb, in2, zero); + tcg_gen_eqv_reg(cb, in1, in2); + tcg_gen_xor_reg(cb, cb, dest); } tcg_temp_free(zero); @@ -940,7 +1176,7 @@ static DisasJumpType do_sub(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2, if (is_tc) { cond_prep(&cond); tmp = tcg_temp_new(); - tcg_gen_setcond_tl(cond.c, tmp, cond.a0, cond.a1); + tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1); gen_helper_tcond(cpu_env, tmp); tcg_temp_free(tmp); } @@ -957,14 +1193,14 @@ static DisasJumpType do_sub(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2, return DISAS_NEXT; } -static DisasJumpType do_cmpclr(DisasContext *ctx, unsigned rt, TCGv in1, - TCGv in2, unsigned cf) +static DisasJumpType do_cmpclr(DisasContext *ctx, unsigned rt, TCGv_reg in1, + TCGv_reg in2, unsigned cf) { - TCGv dest, sv; + TCGv_reg dest, sv; DisasCond cond; dest = tcg_temp_new(); - tcg_gen_sub_tl(dest, in1, in2); + tcg_gen_sub_reg(dest, in1, in2); /* Compute signed overflow if required. */ sv = NULL; @@ -976,7 +1212,7 @@ static DisasJumpType do_cmpclr(DisasContext *ctx, unsigned rt, TCGv in1, cond = do_sub_cond(cf, dest, in1, in2, sv); /* Clear. */ - tcg_gen_movi_tl(dest, 0); + tcg_gen_movi_reg(dest, 0); save_gpr(ctx, rt, dest); tcg_temp_free(dest); @@ -986,10 +1222,11 @@ static DisasJumpType do_cmpclr(DisasContext *ctx, unsigned rt, TCGv in1, return DISAS_NEXT; } -static DisasJumpType do_log(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2, - unsigned cf, void (*fn)(TCGv, TCGv, TCGv)) +static DisasJumpType do_log(DisasContext *ctx, unsigned rt, TCGv_reg in1, + TCGv_reg in2, unsigned cf, + void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg)) { - TCGv dest = dest_gpr(ctx, rt); + TCGv_reg dest = dest_gpr(ctx, rt); /* Perform the operation, and writeback. */ fn(dest, in1, in2); @@ -1003,11 +1240,11 @@ static DisasJumpType do_log(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2, return DISAS_NEXT; } -static DisasJumpType do_unit(DisasContext *ctx, unsigned rt, TCGv in1, - TCGv in2, unsigned cf, bool is_tc, - void (*fn)(TCGv, TCGv, TCGv)) +static DisasJumpType do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1, + TCGv_reg in2, unsigned cf, bool is_tc, + void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg)) { - TCGv dest; + TCGv_reg dest; DisasCond cond; if (cf == 0) { @@ -1022,9 +1259,9 @@ static DisasJumpType do_unit(DisasContext *ctx, unsigned rt, TCGv in1, cond = do_unit_cond(cf, dest, in1, in2); if (is_tc) { - TCGv tmp = tcg_temp_new(); + TCGv_reg tmp = tcg_temp_new(); cond_prep(&cond); - tcg_gen_setcond_tl(cond.c, tmp, cond.a0, cond.a1); + tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1); gen_helper_tcond(cpu_env, tmp); tcg_temp_free(tmp); } @@ -1042,10 +1279,10 @@ static DisasJumpType do_unit(DisasContext *ctx, unsigned rt, TCGv in1, * = 0 for no base register update. */ static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb, - unsigned rx, int scale, target_long disp, + unsigned rx, int scale, target_sreg disp, int modify, TCGMemOp mop) { - TCGv addr, base; + TCGv_reg addr, base; /* Caller uses nullify_over/nullify_end. */ assert(ctx->null_cond.c == TCG_COND_NEVER); @@ -1055,10 +1292,10 @@ static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb, /* Note that RX is mutually exclusive with DISP. */ if (rx) { - tcg_gen_shli_tl(addr, cpu_gr[rx], scale); - tcg_gen_add_tl(addr, addr, base); + tcg_gen_shli_reg(addr, cpu_gr[rx], scale); + tcg_gen_add_reg(addr, addr, base); } else { - tcg_gen_addi_tl(addr, base, disp); + tcg_gen_addi_reg(addr, base, disp); } if (modify == 0) { @@ -1072,10 +1309,10 @@ static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb, } static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb, - unsigned rx, int scale, target_long disp, + unsigned rx, int scale, target_sreg disp, int modify, TCGMemOp mop) { - TCGv addr, base; + TCGv_reg addr, base; /* Caller uses nullify_over/nullify_end. */ assert(ctx->null_cond.c == TCG_COND_NEVER); @@ -1085,10 +1322,10 @@ static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb, /* Note that RX is mutually exclusive with DISP. */ if (rx) { - tcg_gen_shli_tl(addr, cpu_gr[rx], scale); - tcg_gen_add_tl(addr, addr, base); + tcg_gen_shli_reg(addr, cpu_gr[rx], scale); + tcg_gen_add_reg(addr, addr, base); } else { - tcg_gen_addi_tl(addr, base, disp); + tcg_gen_addi_reg(addr, base, disp); } if (modify == 0) { @@ -1102,10 +1339,10 @@ static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb, } static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb, - unsigned rx, int scale, target_long disp, + unsigned rx, int scale, target_sreg disp, int modify, TCGMemOp mop) { - TCGv addr, base; + TCGv_reg addr, base; /* Caller uses nullify_over/nullify_end. */ assert(ctx->null_cond.c == TCG_COND_NEVER); @@ -1115,10 +1352,10 @@ static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb, /* Note that RX is mutually exclusive with DISP. */ if (rx) { - tcg_gen_shli_tl(addr, cpu_gr[rx], scale); - tcg_gen_add_tl(addr, addr, base); + tcg_gen_shli_reg(addr, cpu_gr[rx], scale); + tcg_gen_add_reg(addr, addr, base); } else { - tcg_gen_addi_tl(addr, base, disp); + tcg_gen_addi_reg(addr, base, disp); } tcg_gen_qemu_st_i32(src, (modify <= 0 ? addr : base), MMU_USER_IDX, mop); @@ -1130,10 +1367,10 @@ static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb, } static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb, - unsigned rx, int scale, target_long disp, + unsigned rx, int scale, target_sreg disp, int modify, TCGMemOp mop) { - TCGv addr, base; + TCGv_reg addr, base; /* Caller uses nullify_over/nullify_end. */ assert(ctx->null_cond.c == TCG_COND_NEVER); @@ -1143,10 +1380,10 @@ static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb, /* Note that RX is mutually exclusive with DISP. */ if (rx) { - tcg_gen_shli_tl(addr, cpu_gr[rx], scale); - tcg_gen_add_tl(addr, addr, base); + tcg_gen_shli_reg(addr, cpu_gr[rx], scale); + tcg_gen_add_reg(addr, addr, base); } else { - tcg_gen_addi_tl(addr, base, disp); + tcg_gen_addi_reg(addr, base, disp); } tcg_gen_qemu_st_i64(src, (modify <= 0 ? addr : base), MMU_USER_IDX, mop); @@ -1157,19 +1394,19 @@ static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb, tcg_temp_free(addr); } -#if TARGET_LONG_BITS == 64 -#define do_load_tl do_load_64 -#define do_store_tl do_store_64 +#if TARGET_REGISTER_BITS == 64 +#define do_load_reg do_load_64 +#define do_store_reg do_store_64 #else -#define do_load_tl do_load_32 -#define do_store_tl do_store_32 +#define do_load_reg do_load_32 +#define do_store_reg do_store_32 #endif static DisasJumpType do_load(DisasContext *ctx, unsigned rt, unsigned rb, - unsigned rx, int scale, target_long disp, + unsigned rx, int scale, target_sreg disp, int modify, TCGMemOp mop) { - TCGv dest; + TCGv_reg dest; nullify_over(ctx); @@ -1180,14 +1417,14 @@ static DisasJumpType do_load(DisasContext *ctx, unsigned rt, unsigned rb, /* Make sure if RT == RB, we see the result of the load. */ dest = get_temp(ctx); } - do_load_tl(ctx, dest, rb, rx, scale, disp, modify, mop); + do_load_reg(ctx, dest, rb, rx, scale, disp, modify, mop); save_gpr(ctx, rt, dest); return nullify_end(ctx, DISAS_NEXT); } static DisasJumpType do_floadw(DisasContext *ctx, unsigned rt, unsigned rb, - unsigned rx, int scale, target_long disp, + unsigned rx, int scale, target_sreg disp, int modify) { TCGv_i32 tmp; @@ -1207,7 +1444,7 @@ static DisasJumpType do_floadw(DisasContext *ctx, unsigned rt, unsigned rb, } static DisasJumpType do_floadd(DisasContext *ctx, unsigned rt, unsigned rb, - unsigned rx, int scale, target_long disp, + unsigned rx, int scale, target_sreg disp, int modify) { TCGv_i64 tmp; @@ -1227,15 +1464,15 @@ static DisasJumpType do_floadd(DisasContext *ctx, unsigned rt, unsigned rb, } static DisasJumpType do_store(DisasContext *ctx, unsigned rt, unsigned rb, - target_long disp, int modify, TCGMemOp mop) + target_sreg disp, int modify, TCGMemOp mop) { nullify_over(ctx); - do_store_tl(ctx, load_gpr(ctx, rt), rb, 0, 0, disp, modify, mop); + do_store_reg(ctx, load_gpr(ctx, rt), rb, 0, 0, disp, modify, mop); return nullify_end(ctx, DISAS_NEXT); } static DisasJumpType do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb, - unsigned rx, int scale, target_long disp, + unsigned rx, int scale, target_sreg disp, int modify) { TCGv_i32 tmp; @@ -1250,7 +1487,7 @@ static DisasJumpType do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb, } static DisasJumpType do_fstored(DisasContext *ctx, unsigned rt, unsigned rb, - unsigned rx, int scale, target_long disp, + unsigned rx, int scale, target_sreg disp, int modify) { TCGv_i64 tmp; @@ -1370,7 +1607,7 @@ static DisasJumpType do_fop_dedd(DisasContext *ctx, unsigned rt, /* Emit an unconditional branch to a direct target, which may or may not have already had nullification handled. */ -static DisasJumpType do_dbranch(DisasContext *ctx, target_ulong dest, +static DisasJumpType do_dbranch(DisasContext *ctx, target_ureg dest, unsigned link, bool is_n) { if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) { @@ -1407,10 +1644,10 @@ static DisasJumpType do_dbranch(DisasContext *ctx, target_ulong dest, /* Emit a conditional branch to a direct target. If the branch itself is nullified, we should have already used nullify_over. */ -static DisasJumpType do_cbranch(DisasContext *ctx, target_long disp, bool is_n, +static DisasJumpType do_cbranch(DisasContext *ctx, target_sreg disp, bool is_n, DisasCond *cond) { - target_ulong dest = iaoq_dest(ctx, disp); + target_ureg dest = iaoq_dest(ctx, disp); TCGLabel *taken = NULL; TCGCond c = cond->c; bool n; @@ -1427,7 +1664,7 @@ static DisasJumpType do_cbranch(DisasContext *ctx, target_long disp, bool is_n, taken = gen_new_label(); cond_prep(cond); - tcg_gen_brcond_tl(c, cond->a0, cond->a1, taken); + tcg_gen_brcond_reg(c, cond->a0, cond->a1, taken); cond_free(cond); /* Not taken: Condition not satisfied; nullify on backward branches. */ @@ -1468,10 +1705,10 @@ static DisasJumpType do_cbranch(DisasContext *ctx, target_long disp, bool is_n, /* Emit an unconditional branch to an indirect target. This handles nullification of the branch itself. */ -static DisasJumpType do_ibranch(DisasContext *ctx, TCGv dest, +static DisasJumpType do_ibranch(DisasContext *ctx, TCGv_reg dest, unsigned link, bool is_n) { - TCGv a0, a1, next, tmp; + TCGv_reg a0, a1, next, tmp; TCGCond c; assert(ctx->null_lab == NULL); @@ -1481,7 +1718,7 @@ static DisasJumpType do_ibranch(DisasContext *ctx, TCGv dest, copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var); } next = get_temp(ctx); - tcg_gen_mov_tl(next, dest); + tcg_gen_mov_reg(next, dest); ctx->iaoq_n = -1; ctx->iaoq_n_var = next; if (is_n) { @@ -1500,12 +1737,12 @@ static DisasJumpType do_ibranch(DisasContext *ctx, TCGv dest, /* We do have to handle the non-local temporary, DEST, before branching. Since IOAQ_F is not really live at this point, we can simply store DEST optimistically. Similarly with IAOQ_B. */ - tcg_gen_mov_tl(cpu_iaoq_f, dest); - tcg_gen_addi_tl(cpu_iaoq_b, dest, 4); + tcg_gen_mov_reg(cpu_iaoq_f, dest); + tcg_gen_addi_reg(cpu_iaoq_b, dest, 4); nullify_over(ctx); if (link != 0) { - tcg_gen_movi_tl(cpu_gr[link], ctx->iaoq_n); + tcg_gen_movi_reg(cpu_gr[link], ctx->iaoq_n); } tcg_gen_lookup_and_goto_ptr(); return nullify_end(ctx, DISAS_NEXT); @@ -1519,19 +1756,19 @@ static DisasJumpType do_ibranch(DisasContext *ctx, TCGv dest, next = get_temp(ctx); copy_iaoq_entry(tmp, ctx->iaoq_n, ctx->iaoq_n_var); - tcg_gen_movcond_tl(c, next, a0, a1, tmp, dest); + tcg_gen_movcond_reg(c, next, a0, a1, tmp, dest); ctx->iaoq_n = -1; ctx->iaoq_n_var = next; if (link != 0) { - tcg_gen_movcond_tl(c, cpu_gr[link], a0, a1, cpu_gr[link], tmp); + tcg_gen_movcond_reg(c, cpu_gr[link], a0, a1, cpu_gr[link], tmp); } if (is_n) { /* The branch nullifies the next insn, which means the state of N after the branch is the inverse of the state of N that applied to the branch. */ - tcg_gen_setcond_tl(tcg_invert_cond(c), cpu_psw_n, a0, a1); + tcg_gen_setcond_reg(tcg_invert_cond(c), cpu_psw_n, a0, a1); cond_free(&ctx->null_cond); ctx->null_cond = cond_make_n(); ctx->psw_n_nonzero = true; @@ -1560,7 +1797,7 @@ static DisasJumpType do_page_zero(DisasContext *ctx) case TCG_COND_NEVER: break; case TCG_COND_ALWAYS: - tcg_gen_movi_tl(cpu_psw_n, 0); + tcg_gen_movi_reg(cpu_psw_n, 0); goto do_sigill; default: /* Since this is always the first (and only) insn within the @@ -1586,9 +1823,9 @@ static DisasJumpType do_page_zero(DisasContext *ctx) return DISAS_NORETURN; case 0xe0: /* SET_THREAD_POINTER */ - tcg_gen_mov_tl(cpu_cr27, cpu_gr[26]); - tcg_gen_mov_tl(cpu_iaoq_f, cpu_gr[31]); - tcg_gen_addi_tl(cpu_iaoq_b, cpu_iaoq_f, 4); + tcg_gen_mov_reg(cpu_cr27, cpu_gr[26]); + tcg_gen_mov_reg(cpu_iaoq_f, cpu_gr[31]); + tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4); return DISAS_IAQ_N_UPDATED; case 0x100: /* SYSCALL */ @@ -1631,8 +1868,8 @@ static DisasJumpType trans_mfia(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { unsigned rt = extract32(insn, 0, 5); - TCGv tmp = dest_gpr(ctx, rt); - tcg_gen_movi_tl(tmp, ctx->iaoq_f); + TCGv_reg tmp = dest_gpr(ctx, rt); + tcg_gen_movi_reg(tmp, ctx->iaoq_f); save_gpr(ctx, rt, tmp); cond_free(&ctx->null_cond); @@ -1643,10 +1880,10 @@ static DisasJumpType trans_mfsp(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { unsigned rt = extract32(insn, 0, 5); - TCGv tmp = dest_gpr(ctx, rt); + TCGv_reg tmp = dest_gpr(ctx, rt); /* ??? We don't implement space registers. */ - tcg_gen_movi_tl(tmp, 0); + tcg_gen_movi_reg(tmp, 0); save_gpr(ctx, rt, tmp); cond_free(&ctx->null_cond); @@ -1658,7 +1895,7 @@ static DisasJumpType trans_mfctl(DisasContext *ctx, uint32_t insn, { unsigned rt = extract32(insn, 0, 5); unsigned ctl = extract32(insn, 21, 5); - TCGv tmp; + TCGv_reg tmp; switch (ctl) { case 11: /* SAR */ @@ -1666,7 +1903,7 @@ static DisasJumpType trans_mfctl(DisasContext *ctx, uint32_t insn, if (extract32(insn, 14, 1) == 0) { /* MFSAR without ,W masks low 5 bits. */ tmp = dest_gpr(ctx, rt); - tcg_gen_andi_tl(tmp, cpu_sar, 31); + tcg_gen_andi_reg(tmp, cpu_sar, 31); save_gpr(ctx, rt, tmp); break; } @@ -1698,11 +1935,11 @@ static DisasJumpType trans_mtctl(DisasContext *ctx, uint32_t insn, { unsigned rin = extract32(insn, 16, 5); unsigned ctl = extract32(insn, 21, 5); - TCGv tmp; + TCGv_reg tmp; if (ctl == 11) { /* SAR */ tmp = tcg_temp_new(); - tcg_gen_andi_tl(tmp, load_gpr(ctx, rin), TARGET_LONG_BITS - 1); + tcg_gen_andi_reg(tmp, load_gpr(ctx, rin), TARGET_REGISTER_BITS - 1); save_or_nullify(ctx, cpu_sar, tmp); tcg_temp_free(tmp); } else { @@ -1718,10 +1955,10 @@ static DisasJumpType trans_mtsarcm(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { unsigned rin = extract32(insn, 16, 5); - TCGv tmp = tcg_temp_new(); + TCGv_reg tmp = tcg_temp_new(); - tcg_gen_not_tl(tmp, load_gpr(ctx, rin)); - tcg_gen_andi_tl(tmp, tmp, TARGET_LONG_BITS - 1); + tcg_gen_not_reg(tmp, load_gpr(ctx, rin)); + tcg_gen_andi_reg(tmp, tmp, TARGET_REGISTER_BITS - 1); save_or_nullify(ctx, cpu_sar, tmp); tcg_temp_free(tmp); @@ -1733,10 +1970,10 @@ static DisasJumpType trans_ldsid(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { unsigned rt = extract32(insn, 0, 5); - TCGv dest = dest_gpr(ctx, rt); + TCGv_reg dest = dest_gpr(ctx, rt); /* Since we don't implement space registers, this returns zero. */ - tcg_gen_movi_tl(dest, 0); + tcg_gen_movi_reg(dest, 0); save_gpr(ctx, rt, dest); cond_free(&ctx->null_cond); @@ -1761,12 +1998,12 @@ static DisasJumpType trans_base_idx_mod(DisasContext *ctx, uint32_t insn, { unsigned rb = extract32(insn, 21, 5); unsigned rx = extract32(insn, 16, 5); - TCGv dest = dest_gpr(ctx, rb); - TCGv src1 = load_gpr(ctx, rb); - TCGv src2 = load_gpr(ctx, rx); + TCGv_reg dest = dest_gpr(ctx, rb); + TCGv_reg src1 = load_gpr(ctx, rb); + TCGv_reg src2 = load_gpr(ctx, rx); /* The only thing we need to do is the base register modification. */ - tcg_gen_add_tl(dest, src1, src2); + tcg_gen_add_reg(dest, src1, src2); save_gpr(ctx, rb, dest); cond_free(&ctx->null_cond); @@ -1779,7 +2016,7 @@ static DisasJumpType trans_probe(DisasContext *ctx, uint32_t insn, unsigned rt = extract32(insn, 0, 5); unsigned rb = extract32(insn, 21, 5); unsigned is_write = extract32(insn, 6, 1); - TCGv dest; + TCGv_reg dest; nullify_over(ctx); @@ -1821,7 +2058,7 @@ static DisasJumpType trans_add(DisasContext *ctx, uint32_t insn, unsigned ext = extract32(insn, 8, 4); unsigned shift = extract32(insn, 6, 2); unsigned rt = extract32(insn, 0, 5); - TCGv tcg_r1, tcg_r2; + TCGv_reg tcg_r1, tcg_r2; bool is_c = false; bool is_l = false; bool is_tc = false; @@ -1864,7 +2101,7 @@ static DisasJumpType trans_sub(DisasContext *ctx, uint32_t insn, unsigned cf = extract32(insn, 12, 4); unsigned ext = extract32(insn, 6, 6); unsigned rt = extract32(insn, 0, 5); - TCGv tcg_r1, tcg_r2; + TCGv_reg tcg_r1, tcg_r2; bool is_b = false; bool is_tc = false; bool is_tsv = false; @@ -1908,7 +2145,7 @@ static DisasJumpType trans_log(DisasContext *ctx, uint32_t insn, unsigned r1 = extract32(insn, 16, 5); unsigned cf = extract32(insn, 12, 4); unsigned rt = extract32(insn, 0, 5); - TCGv tcg_r1, tcg_r2; + TCGv_reg tcg_r1, tcg_r2; DisasJumpType ret; if (cf) { @@ -1928,8 +2165,8 @@ static DisasJumpType trans_copy(DisasContext *ctx, uint32_t insn, unsigned rt = extract32(insn, 0, 5); if (r1 == 0) { - TCGv dest = dest_gpr(ctx, rt); - tcg_gen_movi_tl(dest, 0); + TCGv_reg dest = dest_gpr(ctx, rt); + tcg_gen_movi_reg(dest, 0); save_gpr(ctx, rt, dest); } else { save_gpr(ctx, rt, cpu_gr[r1]); @@ -1945,7 +2182,7 @@ static DisasJumpType trans_cmpclr(DisasContext *ctx, uint32_t insn, unsigned r1 = extract32(insn, 16, 5); unsigned cf = extract32(insn, 12, 4); unsigned rt = extract32(insn, 0, 5); - TCGv tcg_r1, tcg_r2; + TCGv_reg tcg_r1, tcg_r2; DisasJumpType ret; if (cf) { @@ -1964,7 +2201,7 @@ static DisasJumpType trans_uxor(DisasContext *ctx, uint32_t insn, unsigned r1 = extract32(insn, 16, 5); unsigned cf = extract32(insn, 12, 4); unsigned rt = extract32(insn, 0, 5); - TCGv tcg_r1, tcg_r2; + TCGv_reg tcg_r1, tcg_r2; DisasJumpType ret; if (cf) { @@ -1972,7 +2209,7 @@ static DisasJumpType trans_uxor(DisasContext *ctx, uint32_t insn, } tcg_r1 = load_gpr(ctx, r1); tcg_r2 = load_gpr(ctx, r2); - ret = do_unit(ctx, rt, tcg_r1, tcg_r2, cf, false, tcg_gen_xor_tl); + ret = do_unit(ctx, rt, tcg_r1, tcg_r2, cf, false, tcg_gen_xor_reg); return nullify_end(ctx, ret); } @@ -1984,7 +2221,7 @@ static DisasJumpType trans_uaddcm(DisasContext *ctx, uint32_t insn, unsigned cf = extract32(insn, 12, 4); unsigned is_tc = extract32(insn, 6, 1); unsigned rt = extract32(insn, 0, 5); - TCGv tcg_r1, tcg_r2, tmp; + TCGv_reg tcg_r1, tcg_r2, tmp; DisasJumpType ret; if (cf) { @@ -1993,8 +2230,8 @@ static DisasJumpType trans_uaddcm(DisasContext *ctx, uint32_t insn, tcg_r1 = load_gpr(ctx, r1); tcg_r2 = load_gpr(ctx, r2); tmp = get_temp(ctx); - tcg_gen_not_tl(tmp, tcg_r2); - ret = do_unit(ctx, rt, tcg_r1, tmp, cf, is_tc, tcg_gen_add_tl); + tcg_gen_not_reg(tmp, tcg_r2); + ret = do_unit(ctx, rt, tcg_r1, tmp, cf, is_tc, tcg_gen_add_reg); return nullify_end(ctx, ret); } @@ -2005,20 +2242,20 @@ static DisasJumpType trans_dcor(DisasContext *ctx, uint32_t insn, unsigned cf = extract32(insn, 12, 4); unsigned is_i = extract32(insn, 6, 1); unsigned rt = extract32(insn, 0, 5); - TCGv tmp; + TCGv_reg tmp; DisasJumpType ret; nullify_over(ctx); tmp = get_temp(ctx); - tcg_gen_shri_tl(tmp, cpu_psw_cb, 3); + tcg_gen_shri_reg(tmp, cpu_psw_cb, 3); if (!is_i) { - tcg_gen_not_tl(tmp, tmp); + tcg_gen_not_reg(tmp, tmp); } - tcg_gen_andi_tl(tmp, tmp, 0x11111111); - tcg_gen_muli_tl(tmp, tmp, 6); + tcg_gen_andi_reg(tmp, tmp, 0x11111111); + tcg_gen_muli_reg(tmp, tmp, 6); ret = do_unit(ctx, rt, tmp, load_gpr(ctx, r2), cf, false, - is_i ? tcg_gen_add_tl : tcg_gen_sub_tl); + is_i ? tcg_gen_add_reg : tcg_gen_sub_reg); return nullify_end(ctx, ret); } @@ -2030,7 +2267,7 @@ static DisasJumpType trans_ds(DisasContext *ctx, uint32_t insn, unsigned r1 = extract32(insn, 16, 5); unsigned cf = extract32(insn, 12, 4); unsigned rt = extract32(insn, 0, 5); - TCGv dest, add1, add2, addc, zero, in1, in2; + TCGv_reg dest, add1, add2, addc, zero, in1, in2; nullify_over(ctx); @@ -2041,19 +2278,19 @@ static DisasJumpType trans_ds(DisasContext *ctx, uint32_t insn, add2 = tcg_temp_new(); addc = tcg_temp_new(); dest = tcg_temp_new(); - zero = tcg_const_tl(0); + zero = tcg_const_reg(0); /* Form R1 << 1 | PSW[CB]{8}. */ - tcg_gen_add_tl(add1, in1, in1); - tcg_gen_add_tl(add1, add1, cpu_psw_cb_msb); + tcg_gen_add_reg(add1, in1, in1); + tcg_gen_add_reg(add1, add1, cpu_psw_cb_msb); /* Add or subtract R2, depending on PSW[V]. Proper computation of carry{8} requires that we subtract via + ~R2 + 1, as described in the manual. By extracting and masking V, we can produce the proper inputs to the addition without movcond. */ - tcg_gen_sari_tl(addc, cpu_psw_v, TARGET_LONG_BITS - 1); - tcg_gen_xor_tl(add2, in2, addc); - tcg_gen_andi_tl(addc, addc, 1); + tcg_gen_sari_reg(addc, cpu_psw_v, TARGET_REGISTER_BITS - 1); + tcg_gen_xor_reg(add2, in2, addc); + tcg_gen_andi_reg(addc, addc, 1); /* ??? This is only correct for 32-bit. */ tcg_gen_add2_i32(dest, cpu_psw_cb_msb, add1, zero, add2, zero); tcg_gen_add2_i32(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb, addc, zero); @@ -2065,16 +2302,16 @@ static DisasJumpType trans_ds(DisasContext *ctx, uint32_t insn, save_gpr(ctx, rt, dest); /* Write back PSW[CB]. */ - tcg_gen_xor_tl(cpu_psw_cb, add1, add2); - tcg_gen_xor_tl(cpu_psw_cb, cpu_psw_cb, dest); + tcg_gen_xor_reg(cpu_psw_cb, add1, add2); + tcg_gen_xor_reg(cpu_psw_cb, cpu_psw_cb, dest); /* Write back PSW[V] for the division step. */ - tcg_gen_neg_tl(cpu_psw_v, cpu_psw_cb_msb); - tcg_gen_xor_tl(cpu_psw_v, cpu_psw_v, in2); + tcg_gen_neg_reg(cpu_psw_v, cpu_psw_cb_msb); + tcg_gen_xor_reg(cpu_psw_v, cpu_psw_v, in2); /* Install the new nullification. */ if (cf) { - TCGv sv = NULL; + TCGv_reg sv = NULL; if (cf >> 1 == 6) { /* ??? The lshift is supposed to contribute to overflow. */ sv = do_add_sv(ctx, dest, add1, add2); @@ -2092,10 +2329,10 @@ static DisasJumpType trans_ds(DisasContext *ctx, uint32_t insn, static const DisasInsn table_arith_log[] = { { 0x08000240u, 0xfc00ffffu, trans_nop }, /* or x,y,0 */ { 0x08000240u, 0xffe0ffe0u, trans_copy }, /* or x,0,t */ - { 0x08000000u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_andc_tl }, - { 0x08000200u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_and_tl }, - { 0x08000240u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_or_tl }, - { 0x08000280u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_xor_tl }, + { 0x08000000u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_andc_reg }, + { 0x08000200u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_and_reg }, + { 0x08000240u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_or_reg }, + { 0x08000280u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_xor_reg }, { 0x08000880u, 0xfc000fe0u, trans_cmpclr }, { 0x08000380u, 0xfc000fe0u, trans_uxor }, { 0x08000980u, 0xfc000fa0u, trans_uaddcm }, @@ -2109,13 +2346,13 @@ static const DisasInsn table_arith_log[] = { static DisasJumpType trans_addi(DisasContext *ctx, uint32_t insn) { - target_long im = low_sextract(insn, 0, 11); + target_sreg im = low_sextract(insn, 0, 11); unsigned e1 = extract32(insn, 11, 1); unsigned cf = extract32(insn, 12, 4); unsigned rt = extract32(insn, 16, 5); unsigned r2 = extract32(insn, 21, 5); unsigned o1 = extract32(insn, 26, 1); - TCGv tcg_im, tcg_r2; + TCGv_reg tcg_im, tcg_r2; DisasJumpType ret; if (cf) { @@ -2131,12 +2368,12 @@ static DisasJumpType trans_addi(DisasContext *ctx, uint32_t insn) static DisasJumpType trans_subi(DisasContext *ctx, uint32_t insn) { - target_long im = low_sextract(insn, 0, 11); + target_sreg im = low_sextract(insn, 0, 11); unsigned e1 = extract32(insn, 11, 1); unsigned cf = extract32(insn, 12, 4); unsigned rt = extract32(insn, 16, 5); unsigned r2 = extract32(insn, 21, 5); - TCGv tcg_im, tcg_r2; + TCGv_reg tcg_im, tcg_r2; DisasJumpType ret; if (cf) { @@ -2152,11 +2389,11 @@ static DisasJumpType trans_subi(DisasContext *ctx, uint32_t insn) static DisasJumpType trans_cmpiclr(DisasContext *ctx, uint32_t insn) { - target_long im = low_sextract(insn, 0, 11); + target_sreg im = low_sextract(insn, 0, 11); unsigned cf = extract32(insn, 12, 4); unsigned rt = extract32(insn, 16, 5); unsigned r2 = extract32(insn, 21, 5); - TCGv tcg_im, tcg_r2; + TCGv_reg tcg_im, tcg_r2; DisasJumpType ret; if (cf) { @@ -2224,7 +2461,7 @@ static DisasJumpType trans_ldcw(DisasContext *ctx, uint32_t insn, unsigned rx = extract32(insn, 16, 5); unsigned rb = extract32(insn, 21, 5); TCGMemOp mop = MO_TEUL | MO_ALIGN_16; - TCGv zero, addr, base, dest; + TCGv_reg zero, addr, base, dest; int modify, disp = 0, scale = 0; nullify_over(ctx); @@ -2252,15 +2489,15 @@ static DisasJumpType trans_ldcw(DisasContext *ctx, uint32_t insn, addr = tcg_temp_new(); base = load_gpr(ctx, rb); if (rx) { - tcg_gen_shli_tl(addr, cpu_gr[rx], scale); - tcg_gen_add_tl(addr, addr, base); + tcg_gen_shli_reg(addr, cpu_gr[rx], scale); + tcg_gen_add_reg(addr, addr, base); } else { - tcg_gen_addi_tl(addr, base, disp); + tcg_gen_addi_reg(addr, base, disp); } - zero = tcg_const_tl(0); - tcg_gen_atomic_xchg_tl(dest, (modify <= 0 ? addr : base), - zero, MMU_USER_IDX, mop); + zero = tcg_const_reg(0); + tcg_gen_atomic_xchg_reg(dest, (modify <= 0 ? addr : base), + zero, MMU_USER_IDX, mop); if (modify) { save_gpr(ctx, rb, addr); } @@ -2272,20 +2509,20 @@ static DisasJumpType trans_ldcw(DisasContext *ctx, uint32_t insn, static DisasJumpType trans_stby(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { - target_long disp = low_sextract(insn, 0, 5); + target_sreg disp = low_sextract(insn, 0, 5); unsigned m = extract32(insn, 5, 1); unsigned a = extract32(insn, 13, 1); unsigned rt = extract32(insn, 16, 5); unsigned rb = extract32(insn, 21, 5); - TCGv addr, val; + TCGv_reg addr, val; nullify_over(ctx); addr = tcg_temp_new(); if (m || disp == 0) { - tcg_gen_mov_tl(addr, load_gpr(ctx, rb)); + tcg_gen_mov_reg(addr, load_gpr(ctx, rb)); } else { - tcg_gen_addi_tl(addr, load_gpr(ctx, rb), disp); + tcg_gen_addi_reg(addr, load_gpr(ctx, rb), disp); } val = load_gpr(ctx, rt); @@ -2304,8 +2541,8 @@ static DisasJumpType trans_stby(DisasContext *ctx, uint32_t insn, } if (m) { - tcg_gen_addi_tl(addr, addr, disp); - tcg_gen_andi_tl(addr, addr, ~3); + tcg_gen_addi_reg(addr, addr, disp); + tcg_gen_andi_reg(addr, addr, ~3); save_gpr(ctx, rb, addr); } tcg_temp_free(addr); @@ -2324,10 +2561,10 @@ static const DisasInsn table_index_mem[] = { static DisasJumpType trans_ldil(DisasContext *ctx, uint32_t insn) { unsigned rt = extract32(insn, 21, 5); - target_long i = assemble_21(insn); - TCGv tcg_rt = dest_gpr(ctx, rt); + target_sreg i = assemble_21(insn); + TCGv_reg tcg_rt = dest_gpr(ctx, rt); - tcg_gen_movi_tl(tcg_rt, i); + tcg_gen_movi_reg(tcg_rt, i); save_gpr(ctx, rt, tcg_rt); cond_free(&ctx->null_cond); @@ -2337,11 +2574,11 @@ static DisasJumpType trans_ldil(DisasContext *ctx, uint32_t insn) static DisasJumpType trans_addil(DisasContext *ctx, uint32_t insn) { unsigned rt = extract32(insn, 21, 5); - target_long i = assemble_21(insn); - TCGv tcg_rt = load_gpr(ctx, rt); - TCGv tcg_r1 = dest_gpr(ctx, 1); + target_sreg i = assemble_21(insn); + TCGv_reg tcg_rt = load_gpr(ctx, rt); + TCGv_reg tcg_r1 = dest_gpr(ctx, 1); - tcg_gen_addi_tl(tcg_r1, tcg_rt, i); + tcg_gen_addi_reg(tcg_r1, tcg_rt, i); save_gpr(ctx, 1, tcg_r1); cond_free(&ctx->null_cond); @@ -2352,15 +2589,15 @@ static DisasJumpType trans_ldo(DisasContext *ctx, uint32_t insn) { unsigned rb = extract32(insn, 21, 5); unsigned rt = extract32(insn, 16, 5); - target_long i = assemble_16(insn); - TCGv tcg_rt = dest_gpr(ctx, rt); + target_sreg i = assemble_16(insn); + TCGv_reg tcg_rt = dest_gpr(ctx, rt); /* Special case rb == 0, for the LDI pseudo-op. The COPY pseudo-op is handled for free within tcg_gen_addi_tl. */ if (rb == 0) { - tcg_gen_movi_tl(tcg_rt, i); + tcg_gen_movi_reg(tcg_rt, i); } else { - tcg_gen_addi_tl(tcg_rt, cpu_gr[rb], i); + tcg_gen_addi_reg(tcg_rt, cpu_gr[rb], i); } save_gpr(ctx, rt, tcg_rt); cond_free(&ctx->null_cond); @@ -2373,7 +2610,7 @@ static DisasJumpType trans_load(DisasContext *ctx, uint32_t insn, { unsigned rb = extract32(insn, 21, 5); unsigned rt = extract32(insn, 16, 5); - target_long i = assemble_16(insn); + target_sreg i = assemble_16(insn); return do_load(ctx, rt, rb, 0, 0, i, is_mod ? (i < 0 ? -1 : 1) : 0, mop); } @@ -2382,7 +2619,7 @@ static DisasJumpType trans_load_w(DisasContext *ctx, uint32_t insn) { unsigned rb = extract32(insn, 21, 5); unsigned rt = extract32(insn, 16, 5); - target_long i = assemble_16a(insn); + target_sreg i = assemble_16a(insn); unsigned ext2 = extract32(insn, 1, 2); switch (ext2) { @@ -2401,7 +2638,7 @@ static DisasJumpType trans_load_w(DisasContext *ctx, uint32_t insn) static DisasJumpType trans_fload_mod(DisasContext *ctx, uint32_t insn) { - target_long i = assemble_16a(insn); + target_sreg i = assemble_16a(insn); unsigned t1 = extract32(insn, 1, 1); unsigned a = extract32(insn, 2, 1); unsigned t0 = extract32(insn, 16, 5); @@ -2416,7 +2653,7 @@ static DisasJumpType trans_store(DisasContext *ctx, uint32_t insn, { unsigned rb = extract32(insn, 21, 5); unsigned rt = extract32(insn, 16, 5); - target_long i = assemble_16(insn); + target_sreg i = assemble_16(insn); return do_store(ctx, rt, rb, i, is_mod ? (i < 0 ? -1 : 1) : 0, mop); } @@ -2425,7 +2662,7 @@ static DisasJumpType trans_store_w(DisasContext *ctx, uint32_t insn) { unsigned rb = extract32(insn, 21, 5); unsigned rt = extract32(insn, 16, 5); - target_long i = assemble_16a(insn); + target_sreg i = assemble_16a(insn); unsigned ext2 = extract32(insn, 1, 2); switch (ext2) { @@ -2443,7 +2680,7 @@ static DisasJumpType trans_store_w(DisasContext *ctx, uint32_t insn) static DisasJumpType trans_fstore_mod(DisasContext *ctx, uint32_t insn) { - target_long i = assemble_16a(insn); + target_sreg i = assemble_16a(insn); unsigned t1 = extract32(insn, 1, 1); unsigned a = extract32(insn, 2, 1); unsigned t0 = extract32(insn, 16, 5); @@ -2525,12 +2762,12 @@ static DisasJumpType trans_copr_dw(DisasContext *ctx, uint32_t insn) static DisasJumpType trans_cmpb(DisasContext *ctx, uint32_t insn, bool is_true, bool is_imm, bool is_dw) { - target_long disp = assemble_12(insn) * 4; + target_sreg disp = assemble_12(insn) * 4; unsigned n = extract32(insn, 1, 1); unsigned c = extract32(insn, 13, 3); unsigned r = extract32(insn, 21, 5); unsigned cf = c * 2 + !is_true; - TCGv dest, in1, in2, sv; + TCGv_reg dest, in1, in2, sv; DisasCond cond; nullify_over(ctx); @@ -2543,7 +2780,7 @@ static DisasJumpType trans_cmpb(DisasContext *ctx, uint32_t insn, in2 = load_gpr(ctx, r); dest = get_temp(ctx); - tcg_gen_sub_tl(dest, in1, in2); + tcg_gen_sub_reg(dest, in1, in2); sv = NULL; if (c == 6) { @@ -2557,12 +2794,12 @@ static DisasJumpType trans_cmpb(DisasContext *ctx, uint32_t insn, static DisasJumpType trans_addb(DisasContext *ctx, uint32_t insn, bool is_true, bool is_imm) { - target_long disp = assemble_12(insn) * 4; + target_sreg disp = assemble_12(insn) * 4; unsigned n = extract32(insn, 1, 1); unsigned c = extract32(insn, 13, 3); unsigned r = extract32(insn, 21, 5); unsigned cf = c * 2 + !is_true; - TCGv dest, in1, in2, sv, cb_msb; + TCGv_reg dest, in1, in2, sv, cb_msb; DisasCond cond; nullify_over(ctx); @@ -2579,15 +2816,15 @@ static DisasJumpType trans_addb(DisasContext *ctx, uint32_t insn, switch (c) { default: - tcg_gen_add_tl(dest, in1, in2); + tcg_gen_add_reg(dest, in1, in2); break; case 4: case 5: cb_msb = get_temp(ctx); - tcg_gen_movi_tl(cb_msb, 0); - tcg_gen_add2_tl(dest, cb_msb, in1, cb_msb, in2, cb_msb); + tcg_gen_movi_reg(cb_msb, 0); + tcg_gen_add2_reg(dest, cb_msb, in1, cb_msb, in2, cb_msb); break; case 6: - tcg_gen_add_tl(dest, in1, in2); + tcg_gen_add_reg(dest, in1, in2); sv = do_add_sv(ctx, dest, in1, in2); break; } @@ -2598,13 +2835,13 @@ static DisasJumpType trans_addb(DisasContext *ctx, uint32_t insn, static DisasJumpType trans_bb(DisasContext *ctx, uint32_t insn) { - target_long disp = assemble_12(insn) * 4; + target_sreg disp = assemble_12(insn) * 4; unsigned n = extract32(insn, 1, 1); unsigned c = extract32(insn, 15, 1); unsigned r = extract32(insn, 16, 5); unsigned p = extract32(insn, 21, 5); unsigned i = extract32(insn, 26, 1); - TCGv tmp, tcg_r; + TCGv_reg tmp, tcg_r; DisasCond cond; nullify_over(ctx); @@ -2612,9 +2849,9 @@ static DisasJumpType trans_bb(DisasContext *ctx, uint32_t insn) tmp = tcg_temp_new(); tcg_r = load_gpr(ctx, r); if (i) { - tcg_gen_shli_tl(tmp, tcg_r, p); + tcg_gen_shli_reg(tmp, tcg_r, p); } else { - tcg_gen_shl_tl(tmp, tcg_r, cpu_sar); + tcg_gen_shl_reg(tmp, tcg_r, cpu_sar); } cond = cond_make_0(c ? TCG_COND_GE : TCG_COND_LT, tmp); @@ -2624,23 +2861,23 @@ static DisasJumpType trans_bb(DisasContext *ctx, uint32_t insn) static DisasJumpType trans_movb(DisasContext *ctx, uint32_t insn, bool is_imm) { - target_long disp = assemble_12(insn) * 4; + target_sreg disp = assemble_12(insn) * 4; unsigned n = extract32(insn, 1, 1); unsigned c = extract32(insn, 13, 3); unsigned t = extract32(insn, 16, 5); unsigned r = extract32(insn, 21, 5); - TCGv dest; + TCGv_reg dest; DisasCond cond; nullify_over(ctx); dest = dest_gpr(ctx, r); if (is_imm) { - tcg_gen_movi_tl(dest, low_sextract(t, 0, 5)); + tcg_gen_movi_reg(dest, low_sextract(t, 0, 5)); } else if (t == 0) { - tcg_gen_movi_tl(dest, 0); + tcg_gen_movi_reg(dest, 0); } else { - tcg_gen_mov_tl(dest, cpu_gr[t]); + tcg_gen_mov_reg(dest, cpu_gr[t]); } cond = do_sed_cond(c, dest); @@ -2654,7 +2891,7 @@ static DisasJumpType trans_shrpw_sar(DisasContext *ctx, uint32_t insn, unsigned c = extract32(insn, 13, 3); unsigned r1 = extract32(insn, 16, 5); unsigned r2 = extract32(insn, 21, 5); - TCGv dest; + TCGv_reg dest; if (c) { nullify_over(ctx); @@ -2662,22 +2899,22 @@ static DisasJumpType trans_shrpw_sar(DisasContext *ctx, uint32_t insn, dest = dest_gpr(ctx, rt); if (r1 == 0) { - tcg_gen_ext32u_tl(dest, load_gpr(ctx, r2)); - tcg_gen_shr_tl(dest, dest, cpu_sar); + tcg_gen_ext32u_reg(dest, load_gpr(ctx, r2)); + tcg_gen_shr_reg(dest, dest, cpu_sar); } else if (r1 == r2) { TCGv_i32 t32 = tcg_temp_new_i32(); - tcg_gen_trunc_tl_i32(t32, load_gpr(ctx, r2)); + tcg_gen_trunc_reg_i32(t32, load_gpr(ctx, r2)); tcg_gen_rotr_i32(t32, t32, cpu_sar); - tcg_gen_extu_i32_tl(dest, t32); + tcg_gen_extu_i32_reg(dest, t32); tcg_temp_free_i32(t32); } else { TCGv_i64 t = tcg_temp_new_i64(); TCGv_i64 s = tcg_temp_new_i64(); - tcg_gen_concat_tl_i64(t, load_gpr(ctx, r2), load_gpr(ctx, r1)); - tcg_gen_extu_tl_i64(s, cpu_sar); + tcg_gen_concat_reg_i64(t, load_gpr(ctx, r2), load_gpr(ctx, r1)); + tcg_gen_extu_reg_i64(s, cpu_sar); tcg_gen_shr_i64(t, t, s); - tcg_gen_trunc_i64_tl(dest, t); + tcg_gen_trunc_i64_reg(dest, t); tcg_temp_free_i64(t); tcg_temp_free_i64(s); @@ -2701,7 +2938,7 @@ static DisasJumpType trans_shrpw_imm(DisasContext *ctx, uint32_t insn, unsigned r1 = extract32(insn, 16, 5); unsigned r2 = extract32(insn, 21, 5); unsigned sa = 31 - cpos; - TCGv dest, t2; + TCGv_reg dest, t2; if (c) { nullify_over(ctx); @@ -2711,16 +2948,16 @@ static DisasJumpType trans_shrpw_imm(DisasContext *ctx, uint32_t insn, t2 = load_gpr(ctx, r2); if (r1 == r2) { TCGv_i32 t32 = tcg_temp_new_i32(); - tcg_gen_trunc_tl_i32(t32, t2); + tcg_gen_trunc_reg_i32(t32, t2); tcg_gen_rotri_i32(t32, t32, sa); - tcg_gen_extu_i32_tl(dest, t32); + tcg_gen_extu_i32_reg(dest, t32); tcg_temp_free_i32(t32); } else if (r1 == 0) { - tcg_gen_extract_tl(dest, t2, sa, 32 - sa); + tcg_gen_extract_reg(dest, t2, sa, 32 - sa); } else { - TCGv t0 = tcg_temp_new(); - tcg_gen_extract_tl(t0, t2, sa, 32 - sa); - tcg_gen_deposit_tl(dest, t0, cpu_gr[r1], 32 - sa, sa); + TCGv_reg t0 = tcg_temp_new(); + tcg_gen_extract_reg(t0, t2, sa, 32 - sa); + tcg_gen_deposit_reg(dest, t0, cpu_gr[r1], 32 - sa, sa); tcg_temp_free(t0); } save_gpr(ctx, rt, dest); @@ -2742,7 +2979,7 @@ static DisasJumpType trans_extrw_sar(DisasContext *ctx, uint32_t insn, unsigned rt = extract32(insn, 16, 5); unsigned rr = extract32(insn, 21, 5); unsigned len = 32 - clen; - TCGv dest, src, tmp; + TCGv_reg dest, src, tmp; if (c) { nullify_over(ctx); @@ -2753,13 +2990,13 @@ static DisasJumpType trans_extrw_sar(DisasContext *ctx, uint32_t insn, tmp = tcg_temp_new(); /* Recall that SAR is using big-endian bit numbering. */ - tcg_gen_xori_tl(tmp, cpu_sar, TARGET_LONG_BITS - 1); + tcg_gen_xori_reg(tmp, cpu_sar, TARGET_REGISTER_BITS - 1); if (is_se) { - tcg_gen_sar_tl(dest, src, tmp); - tcg_gen_sextract_tl(dest, dest, 0, len); + tcg_gen_sar_reg(dest, src, tmp); + tcg_gen_sextract_reg(dest, dest, 0, len); } else { - tcg_gen_shr_tl(dest, src, tmp); - tcg_gen_extract_tl(dest, dest, 0, len); + tcg_gen_shr_reg(dest, src, tmp); + tcg_gen_extract_reg(dest, dest, 0, len); } tcg_temp_free(tmp); save_gpr(ctx, rt, dest); @@ -2783,7 +3020,7 @@ static DisasJumpType trans_extrw_imm(DisasContext *ctx, uint32_t insn, unsigned rr = extract32(insn, 21, 5); unsigned len = 32 - clen; unsigned cpos = 31 - pos; - TCGv dest, src; + TCGv_reg dest, src; if (c) { nullify_over(ctx); @@ -2792,9 +3029,9 @@ static DisasJumpType trans_extrw_imm(DisasContext *ctx, uint32_t insn, dest = dest_gpr(ctx, rt); src = load_gpr(ctx, rr); if (is_se) { - tcg_gen_sextract_tl(dest, src, cpos, len); + tcg_gen_sextract_reg(dest, src, cpos, len); } else { - tcg_gen_extract_tl(dest, src, cpos, len); + tcg_gen_extract_reg(dest, src, cpos, len); } save_gpr(ctx, rt, dest); @@ -2820,11 +3057,11 @@ static DisasJumpType trans_depw_imm_c(DisasContext *ctx, uint32_t insn, unsigned cpos = extract32(insn, 5, 5); unsigned nz = extract32(insn, 10, 1); unsigned c = extract32(insn, 13, 3); - target_long val = low_sextract(insn, 16, 5); + target_sreg val = low_sextract(insn, 16, 5); unsigned rt = extract32(insn, 21, 5); unsigned len = 32 - clen; - target_long mask0, mask1; - TCGv dest; + target_sreg mask0, mask1; + TCGv_reg dest; if (c) { nullify_over(ctx); @@ -2838,14 +3075,14 @@ static DisasJumpType trans_depw_imm_c(DisasContext *ctx, uint32_t insn, mask1 = deposit64(-1, cpos, len, val); if (nz) { - TCGv src = load_gpr(ctx, rt); + TCGv_reg src = load_gpr(ctx, rt); if (mask1 != -1) { - tcg_gen_andi_tl(dest, src, mask1); + tcg_gen_andi_reg(dest, src, mask1); src = dest; } - tcg_gen_ori_tl(dest, src, mask0); + tcg_gen_ori_reg(dest, src, mask0); } else { - tcg_gen_movi_tl(dest, mask0); + tcg_gen_movi_reg(dest, mask0); } save_gpr(ctx, rt, dest); @@ -2868,7 +3105,7 @@ static DisasJumpType trans_depw_imm(DisasContext *ctx, uint32_t insn, unsigned rt = extract32(insn, 21, 5); unsigned rs = nz ? rt : 0; unsigned len = 32 - clen; - TCGv dest, val; + TCGv_reg dest, val; if (c) { nullify_over(ctx); @@ -2880,9 +3117,9 @@ static DisasJumpType trans_depw_imm(DisasContext *ctx, uint32_t insn, dest = dest_gpr(ctx, rt); val = load_gpr(ctx, rr); if (rs == 0) { - tcg_gen_deposit_z_tl(dest, val, cpos, len); + tcg_gen_deposit_z_reg(dest, val, cpos, len); } else { - tcg_gen_deposit_tl(dest, cpu_gr[rs], val, cpos, len); + tcg_gen_deposit_reg(dest, cpu_gr[rs], val, cpos, len); } save_gpr(ctx, rt, dest); @@ -2904,7 +3141,7 @@ static DisasJumpType trans_depw_sar(DisasContext *ctx, uint32_t insn, unsigned rt = extract32(insn, 21, 5); unsigned rs = nz ? rt : 0; unsigned len = 32 - clen; - TCGv val, mask, tmp, shift, dest; + TCGv_reg val, mask, tmp, shift, dest; unsigned msb = 1U << (len - 1); if (c) { @@ -2921,17 +3158,17 @@ static DisasJumpType trans_depw_sar(DisasContext *ctx, uint32_t insn, tmp = tcg_temp_new(); /* Convert big-endian bit numbering in SAR to left-shift. */ - tcg_gen_xori_tl(shift, cpu_sar, TARGET_LONG_BITS - 1); + tcg_gen_xori_reg(shift, cpu_sar, TARGET_REGISTER_BITS - 1); - mask = tcg_const_tl(msb + (msb - 1)); - tcg_gen_and_tl(tmp, val, mask); + mask = tcg_const_reg(msb + (msb - 1)); + tcg_gen_and_reg(tmp, val, mask); if (rs) { - tcg_gen_shl_tl(mask, mask, shift); - tcg_gen_shl_tl(tmp, tmp, shift); - tcg_gen_andc_tl(dest, cpu_gr[rs], mask); - tcg_gen_or_tl(dest, dest, tmp); + tcg_gen_shl_reg(mask, mask, shift); + tcg_gen_shl_reg(tmp, tmp, shift); + tcg_gen_andc_reg(dest, cpu_gr[rs], mask); + tcg_gen_or_reg(dest, dest, tmp); } else { - tcg_gen_shl_tl(dest, tmp, shift); + tcg_gen_shl_reg(dest, tmp, shift); } tcg_temp_free(shift); tcg_temp_free(mask); @@ -2956,7 +3193,7 @@ static DisasJumpType trans_be(DisasContext *ctx, uint32_t insn, bool is_l) { unsigned n = extract32(insn, 1, 1); unsigned b = extract32(insn, 21, 5); - target_long disp = assemble_17(insn); + target_sreg disp = assemble_17(insn); /* unsigned s = low_uextract(insn, 13, 3); */ /* ??? It seems like there should be a good way of using @@ -2971,8 +3208,8 @@ static DisasJumpType trans_be(DisasContext *ctx, uint32_t insn, bool is_l) if (b == 0) { return do_dbranch(ctx, disp, is_l ? 31 : 0, n); } else { - TCGv tmp = get_temp(ctx); - tcg_gen_addi_tl(tmp, load_gpr(ctx, b), disp); + TCGv_reg tmp = get_temp(ctx); + tcg_gen_addi_reg(tmp, load_gpr(ctx, b), disp); return do_ibranch(ctx, tmp, is_l ? 31 : 0, n); } } @@ -2982,7 +3219,7 @@ static DisasJumpType trans_bl(DisasContext *ctx, uint32_t insn, { unsigned n = extract32(insn, 1, 1); unsigned link = extract32(insn, 21, 5); - target_long disp = assemble_17(insn); + target_sreg disp = assemble_17(insn); return do_dbranch(ctx, iaoq_dest(ctx, disp), link, n); } @@ -2991,7 +3228,7 @@ static DisasJumpType trans_bl_long(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { unsigned n = extract32(insn, 1, 1); - target_long disp = assemble_22(insn); + target_sreg disp = assemble_22(insn); return do_dbranch(ctx, iaoq_dest(ctx, disp), 2, n); } @@ -3002,10 +3239,10 @@ static DisasJumpType trans_blr(DisasContext *ctx, uint32_t insn, unsigned n = extract32(insn, 1, 1); unsigned rx = extract32(insn, 16, 5); unsigned link = extract32(insn, 21, 5); - TCGv tmp = get_temp(ctx); + TCGv_reg tmp = get_temp(ctx); - tcg_gen_shli_tl(tmp, load_gpr(ctx, rx), 3); - tcg_gen_addi_tl(tmp, tmp, ctx->iaoq_f + 8); + tcg_gen_shli_reg(tmp, load_gpr(ctx, rx), 3); + tcg_gen_addi_reg(tmp, tmp, ctx->iaoq_f + 8); return do_ibranch(ctx, tmp, link, n); } @@ -3015,14 +3252,14 @@ static DisasJumpType trans_bv(DisasContext *ctx, uint32_t insn, unsigned n = extract32(insn, 1, 1); unsigned rx = extract32(insn, 16, 5); unsigned rb = extract32(insn, 21, 5); - TCGv dest; + TCGv_reg dest; if (rx == 0) { dest = load_gpr(ctx, rb); } else { dest = get_temp(ctx); - tcg_gen_shli_tl(dest, load_gpr(ctx, rx), 3); - tcg_gen_add_tl(dest, dest, load_gpr(ctx, rb)); + tcg_gen_shli_reg(dest, load_gpr(ctx, rx), 3); + tcg_gen_add_reg(dest, dest, load_gpr(ctx, rb)); } return do_ibranch(ctx, dest, 0, n); } @@ -3242,13 +3479,13 @@ static DisasJumpType trans_ftest_t(DisasContext *ctx, uint32_t insn, { unsigned y = extract32(insn, 13, 3); unsigned cbit = (y ^ 1) - 1; - TCGv t; + TCGv_reg t; nullify_over(ctx); t = tcg_temp_new(); - tcg_gen_ld32u_tl(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow)); - tcg_gen_extract_tl(t, t, 21 - cbit, 1); + tcg_gen_ld32u_reg(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow)); + tcg_gen_extract_reg(t, t, 21 - cbit, 1); ctx->null_cond = cond_make_0(TCG_COND_NE, t); tcg_temp_free(t); @@ -3261,16 +3498,16 @@ static DisasJumpType trans_ftest_q(DisasContext *ctx, uint32_t insn, unsigned c = extract32(insn, 0, 5); int mask; bool inv = false; - TCGv t; + TCGv_reg t; nullify_over(ctx); t = tcg_temp_new(); - tcg_gen_ld32u_tl(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow)); + tcg_gen_ld32u_reg(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow)); switch (c) { case 0: /* simple */ - tcg_gen_andi_tl(t, t, 0x4000000); + tcg_gen_andi_reg(t, t, 0x4000000); ctx->null_cond = cond_make_0(TCG_COND_NE, t); goto done; case 2: /* rej */ @@ -3298,11 +3535,11 @@ static DisasJumpType trans_ftest_q(DisasContext *ctx, uint32_t insn, return gen_illegal(ctx); } if (inv) { - TCGv c = load_const(ctx, mask); - tcg_gen_or_tl(t, t, c); + TCGv_reg c = load_const(ctx, mask); + tcg_gen_or_reg(t, t, c); ctx->null_cond = cond_make(TCG_COND_EQ, t, c); } else { - tcg_gen_andi_tl(t, t, mask); + tcg_gen_andi_reg(t, t, mask); ctx->null_cond = cond_make_0(TCG_COND_EQ, t); } done: @@ -3805,7 +4042,7 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) if (ctx->iaoq_b == -1) { ctx->iaoq_n = -1; ctx->iaoq_n_var = get_temp(ctx); - tcg_gen_addi_tl(ctx->iaoq_n_var, cpu_iaoq_b, 4); + tcg_gen_addi_reg(ctx->iaoq_n_var, cpu_iaoq_b, 4); } else { ctx->iaoq_n = ctx->iaoq_b + 4; ctx->iaoq_n_var = NULL; @@ -3849,12 +4086,12 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) return; } if (ctx->iaoq_f == -1) { - tcg_gen_mov_tl(cpu_iaoq_f, cpu_iaoq_b); + tcg_gen_mov_reg(cpu_iaoq_f, cpu_iaoq_b); copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var); nullify_save(ctx); ctx->base.is_jmp = DISAS_IAQ_N_UPDATED; } else if (ctx->iaoq_b == -1) { - tcg_gen_mov_tl(cpu_iaoq_b, ctx->iaoq_n_var); + tcg_gen_mov_reg(cpu_iaoq_b, ctx->iaoq_n_var); } } @@ -3889,8 +4126,7 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) { - TranslationBlock *tb = dcbase->tb; - target_ulong pc = tb->pc; + target_ureg pc = dcbase->pc_first; #ifdef CONFIG_USER_ONLY switch (pc) { @@ -3910,7 +4146,7 @@ static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) #endif qemu_log("IN: %s\n", lookup_symbol(pc)); - log_target_disas(cs, pc, tb->size); + log_target_disas(cs, pc, dcbase->tb->size); } static const TranslatorOps hppa_tr_ops = { From 3d68ee7bbe34278d5792f5341ba0246069c6191c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Oct 2017 10:17:24 -0700 Subject: [PATCH 06/43] target/hppa: Implement mmu_idx from IA privilege level Most aspects of privilege are not yet handled. But this gives us the start from which to begin checking. Signed-off-by: Richard Henderson --- target/hppa/cpu.c | 2 +- target/hppa/cpu.h | 19 +++++++++++--- target/hppa/translate.c | 55 +++++++++++++++++++++++++---------------- 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index f6d92de972..9962ab71ee 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -39,7 +39,7 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) cpu->env.iaoq_f = tb->pc; cpu->env.iaoq_b = tb->cs_base; - cpu->env.psw_n = tb->flags & 1; + cpu->env.psw_n = (tb->flags & PSW_N) != 0; } static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 9fe5ea0a69..f60435b9ec 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -36,8 +36,10 @@ #define TARGET_PAGE_BITS 12 #define ALIGNED_ONLY -#define NB_MMU_MODES 1 -#define MMU_USER_IDX 0 +#define NB_MMU_MODES 5 +#define MMU_KERNEL_IDX 0 +#define MMU_USER_IDX 3 +#define MMU_PHYS_IDX 4 #define TARGET_INSN_START_EXTRA_WORDS 1 /* Hardware exceptions, interupts, faults, and traps. */ @@ -195,7 +197,14 @@ static inline HPPACPU *hppa_env_get_cpu(CPUHPPAState *env) static inline int cpu_mmu_index(CPUHPPAState *env, bool ifetch) { - return 0; +#ifdef CONFIG_USER_ONLY + return MMU_USER_IDX; +#else + if (env->psw & (ifetch ? PSW_C : PSW_D)) { + return env->iaoq_f & 3; + } + return MMU_PHYS_IDX; /* mmu disabled */ +#endif } void hppa_translate_init(void); @@ -210,7 +219,9 @@ static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, target_ulong *pc, { *pc = env->iaoq_f; *cs_base = env->iaoq_b; - *pflags = env->psw_n; + /* ??? E, T, H, L, B, P bits need to be here, when implemented. */ + *pflags = (env->psw & (PSW_W | PSW_C | PSW_D)) + | env->psw_n * PSW_N; } target_ureg cpu_hppa_get_psw(CPUHPPAState *env); diff --git a/target/hppa/translate.c b/target/hppa/translate.c index dd96147bf1..33605a2d15 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -282,6 +282,8 @@ typedef struct DisasContext { DisasCond null_cond; TCGLabel *null_lab; + int mmu_idx; + int privilege; bool psw_n_nonzero; } DisasContext; @@ -1299,10 +1301,10 @@ static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb, } if (modify == 0) { - tcg_gen_qemu_ld_i32(dest, addr, MMU_USER_IDX, mop); + tcg_gen_qemu_ld_i32(dest, addr, ctx->mmu_idx, mop); } else { tcg_gen_qemu_ld_i32(dest, (modify < 0 ? addr : base), - MMU_USER_IDX, mop); + ctx->mmu_idx, mop); save_gpr(ctx, rb, addr); } tcg_temp_free(addr); @@ -1329,10 +1331,10 @@ static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb, } if (modify == 0) { - tcg_gen_qemu_ld_i64(dest, addr, MMU_USER_IDX, mop); + tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop); } else { tcg_gen_qemu_ld_i64(dest, (modify < 0 ? addr : base), - MMU_USER_IDX, mop); + ctx->mmu_idx, mop); save_gpr(ctx, rb, addr); } tcg_temp_free(addr); @@ -1358,7 +1360,7 @@ static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb, tcg_gen_addi_reg(addr, base, disp); } - tcg_gen_qemu_st_i32(src, (modify <= 0 ? addr : base), MMU_USER_IDX, mop); + tcg_gen_qemu_st_i32(src, (modify <= 0 ? addr : base), ctx->mmu_idx, mop); if (modify != 0) { save_gpr(ctx, rb, addr); @@ -1386,7 +1388,7 @@ static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb, tcg_gen_addi_reg(addr, base, disp); } - tcg_gen_qemu_st_i64(src, (modify <= 0 ? addr : base), MMU_USER_IDX, mop); + tcg_gen_qemu_st_i64(src, (modify <= 0 ? addr : base), ctx->mmu_idx, mop); if (modify != 0) { save_gpr(ctx, rb, addr); @@ -2497,7 +2499,7 @@ static DisasJumpType trans_ldcw(DisasContext *ctx, uint32_t insn, zero = tcg_const_reg(0); tcg_gen_atomic_xchg_reg(dest, (modify <= 0 ? addr : base), - zero, MMU_USER_IDX, mop); + zero, ctx->mmu_idx, mop); if (modify) { save_gpr(ctx, rb, addr); } @@ -3971,30 +3973,43 @@ static int hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs, int max_insns) { DisasContext *ctx = container_of(dcbase, DisasContext, base); - TranslationBlock *tb = ctx->base.tb; int bound; ctx->cs = cs; - ctx->iaoq_f = tb->pc; - ctx->iaoq_b = tb->cs_base; + +#ifdef CONFIG_USER_ONLY + ctx->privilege = MMU_USER_IDX; + ctx->mmu_idx = MMU_USER_IDX; +#else + ctx->privilege = ctx->base.pc_first & 3; + ctx->mmu_idx = (ctx->base.tb->flags & PSW_D + ? ctx->privilege : MMU_PHYS_IDX); +#endif + ctx->iaoq_f = ctx->base.pc_first; + ctx->iaoq_b = ctx->base.tb->cs_base; + ctx->base.pc_first &= -4; + ctx->iaoq_n = -1; ctx->iaoq_n_var = NULL; + /* Bound the number of instructions by those left on the page. */ + bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4; + bound = MIN(max_insns, bound); + ctx->ntemps = 0; memset(ctx->temps, 0, sizeof(ctx->temps)); - bound = -(tb->pc | TARGET_PAGE_MASK) / 4; - return MIN(max_insns, bound); + return bound; } static void hppa_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) { DisasContext *ctx = container_of(dcbase, DisasContext, base); - /* Seed the nullification status from PSW[N], as shown in TB->FLAGS. */ + /* Seed the nullification status from PSW[N], as saved in TB->FLAGS. */ ctx->null_cond = cond_make_f(); ctx->psw_n_nonzero = false; - if (ctx->base.tb->flags & 1) { + if (ctx->base.tb->flags & PSW_N) { ctx->null_cond.c = TCG_COND_ALWAYS; ctx->psw_n_nonzero = true; } @@ -4014,7 +4029,7 @@ static bool hppa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, DisasContext *ctx = container_of(dcbase, DisasContext, base); ctx->base.is_jmp = gen_excp(ctx, EXCP_DEBUG); - ctx->base.pc_next = ctx->iaoq_f + 4; + ctx->base.pc_next = (ctx->iaoq_f & -4) + 4; return true; } @@ -4035,7 +4050,7 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { /* Always fetch the insn, even if nullified, so that we check the page permissions for execute. */ - uint32_t insn = cpu_ldl_code(env, ctx->iaoq_f); + uint32_t insn = cpu_ldl_code(env, ctx->iaoq_f & -4); /* Set up the IA queue for the next insn. This will be overwritten by a branch. */ @@ -4064,10 +4079,8 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) } ctx->ntemps = 0; - /* Advance the insn queue. */ - /* ??? The non-linear instruction restriction is purely due to - the debugging dump. Otherwise we *could* follow unconditional - branches within the same page. */ + /* Advance the insn queue. Note that this check also detects + a priority change within the instruction queue. */ if (ret == DISAS_NEXT && ctx->iaoq_b != ctx->iaoq_f + 4) { if (ctx->null_cond.c == TCG_COND_NEVER || ctx->null_cond.c == TCG_COND_ALWAYS) { @@ -4121,7 +4134,7 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) /* We don't actually use this during normal translation, but we should interact with the generic main loop. */ - ctx->base.pc_next = ctx->base.tb->pc + 4 * ctx->base.num_insns; + ctx->base.pc_next = ctx->base.pc_first + 4 * ctx->base.num_insns; } static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) From e1b5a5ed6f817515e9328561ad0230f8a7af440a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Oct 2017 07:44:30 -0700 Subject: [PATCH 07/43] target/hppa: Implement the system mask instructions Signed-off-by: Richard Henderson --- target/hppa/helper.h | 4 ++ target/hppa/op_helper.c | 14 ++++++ target/hppa/translate.c | 96 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 113 insertions(+), 1 deletion(-) diff --git a/target/hppa/helper.h b/target/hppa/helper.h index c720de523b..254a4da133 100644 --- a/target/hppa/helper.h +++ b/target/hppa/helper.h @@ -76,3 +76,7 @@ DEF_HELPER_FLAGS_4(fmpyfadd_s, TCG_CALL_NO_RWG, i32, env, i32, i32, i32) DEF_HELPER_FLAGS_4(fmpynfadd_s, TCG_CALL_NO_RWG, i32, env, i32, i32, i32) DEF_HELPER_FLAGS_4(fmpyfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_4(fmpynfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) + +#ifndef CONFIG_USER_ONLY +DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr) +#endif diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 4ab4ee8a77..1d56ba497b 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -601,3 +601,17 @@ float64 HELPER(fmpynfadd_d)(CPUHPPAState *env, float64 a, float64 b, float64 c) update_fr0_op(env, GETPC()); return ret; } + +#ifndef CONFIG_USER_ONLY +target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm) +{ + target_ulong psw = env->psw; + /* ??? On second reading this condition simply seems + to be undefined rather than a diagnosed trap. */ + if (nsm & ~psw & PSW_Q) { + dynexcp(env, EXCP_ILL, GETPC()); + } + env->psw = (psw & ~PSW_SM) | (nsm & PSW_SM); + return psw & PSW_SM; +} +#endif diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 33605a2d15..088031e7f3 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -299,6 +299,10 @@ typedef struct DisasContext { updated the iaq for the next instruction to be executed. */ #define DISAS_IAQ_N_STALE DISAS_TARGET_1 +/* Similarly, but we want to return to the main loop immediately + to recognize unmasked interrupts. */ +#define DISAS_IAQ_N_STALE_EXIT DISAS_TARGET_2 + typedef struct DisasInsn { uint32_t insn, mask; DisasJumpType (*trans)(DisasContext *ctx, uint32_t insn, @@ -697,6 +701,14 @@ static DisasJumpType gen_illegal(DisasContext *ctx) return nullify_end(ctx, gen_excp(ctx, EXCP_ILL)); } +#define CHECK_MOST_PRIVILEGED(EXCP) \ + do { \ + if (ctx->privilege != 0) { \ + nullify_over(ctx); \ + return nullify_end(ctx, gen_excp(ctx, EXCP)); \ + } \ + } while (0) + static bool use_goto_tb(DisasContext *ctx, target_ureg dest) { /* Suppress goto_tb in the case of single-steping and IO. */ @@ -1982,6 +1994,79 @@ static DisasJumpType trans_ldsid(DisasContext *ctx, uint32_t insn, return DISAS_NEXT; } +#ifndef CONFIG_USER_ONLY +/* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */ +static target_ureg extract_sm_imm(uint32_t insn) +{ + target_ureg val = extract32(insn, 16, 10); + + if (val & PSW_SM_E) { + val = (val & ~PSW_SM_E) | PSW_E; + } + if (val & PSW_SM_W) { + val = (val & ~PSW_SM_W) | PSW_W; + } + return val; +} + +static DisasJumpType trans_rsm(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + unsigned rt = extract32(insn, 0, 5); + target_ureg sm = extract_sm_imm(insn); + TCGv_reg tmp; + + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + nullify_over(ctx); + + tmp = get_temp(ctx); + tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw)); + tcg_gen_andi_reg(tmp, tmp, ~sm); + gen_helper_swap_system_mask(tmp, cpu_env, tmp); + save_gpr(ctx, rt, tmp); + + /* Exit the TB to recognize new interrupts, e.g. PSW_M. */ + return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT); +} + +static DisasJumpType trans_ssm(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + unsigned rt = extract32(insn, 0, 5); + target_ureg sm = extract_sm_imm(insn); + TCGv_reg tmp; + + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + nullify_over(ctx); + + tmp = get_temp(ctx); + tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw)); + tcg_gen_ori_reg(tmp, tmp, sm); + gen_helper_swap_system_mask(tmp, cpu_env, tmp); + save_gpr(ctx, rt, tmp); + + /* Exit the TB to recognize new interrupts, e.g. PSW_I. */ + return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT); +} + +static DisasJumpType trans_mtsm(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + unsigned rr = extract32(insn, 16, 5); + TCGv_reg tmp, reg; + + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + nullify_over(ctx); + + reg = load_gpr(ctx, rr); + tmp = get_temp(ctx); + gen_helper_swap_system_mask(tmp, cpu_env, reg); + + /* Exit the TB to recognize new interrupts. */ + return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT); +} +#endif /* !CONFIG_USER_ONLY */ + static const DisasInsn table_system[] = { { 0x00000000u, 0xfc001fe0u, trans_break }, /* We don't implement space register, so MTSP is a nop. */ @@ -1993,6 +2078,11 @@ static const DisasInsn table_system[] = { { 0x000008a0u, 0xfc1fffe0u, trans_mfctl }, { 0x00000400u, 0xffffffffu, trans_sync }, { 0x000010a0u, 0xfc1f3fe0u, trans_ldsid }, +#ifndef CONFIG_USER_ONLY + { 0x00000e60u, 0xfc00ffe0u, trans_rsm }, + { 0x00000d60u, 0xfc00ffe0u, trans_ssm }, + { 0x00001860u, 0xffe0ffffu, trans_mtsm }, +#endif }; static DisasJumpType trans_base_idx_mod(DisasContext *ctx, uint32_t insn, @@ -4111,12 +4201,14 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) { DisasContext *ctx = container_of(dcbase, DisasContext, base); + DisasJumpType is_jmp = ctx->base.is_jmp; - switch (ctx->base.is_jmp) { + switch (is_jmp) { case DISAS_NORETURN: break; case DISAS_TOO_MANY: case DISAS_IAQ_N_STALE: + case DISAS_IAQ_N_STALE_EXIT: copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f); copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b); nullify_save(ctx); @@ -4124,6 +4216,8 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) case DISAS_IAQ_N_UPDATED: if (ctx->base.singlestep_enabled) { gen_excp_1(EXCP_DEBUG); + } else if (is_jmp == DISAS_IAQ_N_STALE_EXIT) { + tcg_gen_exit_tb(0); } else { tcg_gen_lookup_and_goto_ptr(); } From 33423472f03c7693324ee86cbd76fe34346837ed Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Oct 2017 22:54:12 -0700 Subject: [PATCH 08/43] target/hppa: Add space registers Not used where they should be yet, but we can copy them. Signed-off-by: Richard Henderson --- target/hppa/cpu.h | 1 + target/hppa/helper.c | 14 +++++--- target/hppa/translate.c | 73 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 77 insertions(+), 11 deletions(-) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index f60435b9ec..e3da05e5d3 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -140,6 +140,7 @@ typedef int64_t target_sreg; struct CPUHPPAState { target_ureg gr[32]; uint64_t fr[32]; + uint64_t sr[8]; /* stored shifted into place for gva */ target_ureg sar; target_ureg cr26; diff --git a/target/hppa/helper.c b/target/hppa/helper.c index b6521f61fc..48ac80cb2d 100644 --- a/target/hppa/helper.c +++ b/target/hppa/helper.c @@ -168,12 +168,16 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, psw, psw_cb, psw_c); for (i = 0; i < 32; i++) { - cpu_fprintf(f, "GR%02d " TREG_FMT_lx " ", i, env->gr[i]); - if ((i % 4) == 3) { - cpu_fprintf(f, "\n"); - } + cpu_fprintf(f, "GR%02d " TREG_FMT_lx "%c", i, env->gr[i], + (i & 3) == 3 ? '\n' : ' '); } - cpu_fprintf(f, "\n"); +#ifndef CONFIG_USER_ONLY + for (i = 0; i < 8; i++) { + cpu_fprintf(f, "SR%02d %08x%c", i, (uint32_t)(env->sr[i] >> 32), + (i & 3) == 3 ? '\n' : ' '); + } +#endif + cpu_fprintf(f, "\n"); /* ??? FR */ } diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 088031e7f3..50d41b0c63 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -320,6 +320,7 @@ typedef struct DisasInsn { /* global register indexes */ static TCGv_reg cpu_gr[32]; +static TCGv_i64 cpu_sr[4]; static TCGv_reg cpu_iaoq_f; static TCGv_reg cpu_iaoq_b; static TCGv_reg cpu_sar; @@ -358,6 +359,10 @@ void hppa_translate_init(void) "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" }; + /* SR[4-7] are not global registers so that we can index them. */ + static const char sr_names[4][4] = { + "sr0", "sr1", "sr2", "sr3" + }; int i; @@ -367,6 +372,11 @@ void hppa_translate_init(void) offsetof(CPUHPPAState, gr[i]), gr_names[i]); } + for (i = 0; i < 4; i++) { + cpu_sr[i] = tcg_global_mem_new_i64(cpu_env, + offsetof(CPUHPPAState, sr[i]), + sr_names[i]); + } for (i = 0; i < ARRAY_SIZE(vars); ++i) { const GlobalVar *v = &vars[i]; @@ -571,6 +581,19 @@ static void save_frd(unsigned rt, TCGv_i64 val) tcg_gen_st_i64(val, cpu_env, offsetof(CPUHPPAState, fr[rt])); } +static void load_spr(DisasContext *ctx, TCGv_i64 dest, unsigned reg) +{ +#ifdef CONFIG_USER_ONLY + tcg_gen_movi_i64(dest, 0); +#else + if (reg < 4) { + tcg_gen_mov_i64(dest, cpu_sr[reg]); + } else { + tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUHPPAState, sr[reg])); + } +#endif +} + /* Skip over the implementation of an insn that has been nullified. Use this when the insn is too complex for a conditional move. */ static void nullify_over(DisasContext *ctx) @@ -785,6 +808,13 @@ static unsigned assemble_rc64(uint32_t insn) return r2 * 32 + r1 * 4 + r0; } +static unsigned assemble_sr3(uint32_t insn) +{ + unsigned s2 = extract32(insn, 13, 1); + unsigned s0 = extract32(insn, 14, 2); + return s2 * 4 + s0; +} + static target_sreg assemble_12(uint32_t insn) { target_ureg x = -(target_ureg)(insn & 1); @@ -1894,11 +1924,17 @@ static DisasJumpType trans_mfsp(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { unsigned rt = extract32(insn, 0, 5); - TCGv_reg tmp = dest_gpr(ctx, rt); + unsigned rs = assemble_sr3(insn); + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_reg t1 = tcg_temp_new(); - /* ??? We don't implement space registers. */ - tcg_gen_movi_reg(tmp, 0); - save_gpr(ctx, rt, tmp); + load_spr(ctx, t0, rs); + tcg_gen_shri_i64(t0, t0, 32); + tcg_gen_trunc_i64_reg(t1, t0); + + save_gpr(ctx, rt, t1); + tcg_temp_free(t1); + tcg_temp_free_i64(t0); cond_free(&ctx->null_cond); return DISAS_NEXT; @@ -1944,6 +1980,32 @@ static DisasJumpType trans_mfctl(DisasContext *ctx, uint32_t insn, return DISAS_NEXT; } +static DisasJumpType trans_mtsp(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + unsigned rr = extract32(insn, 16, 5); + unsigned rs = assemble_sr3(insn); + TCGv_i64 t64; + + if (rs >= 5) { + CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG); + } + nullify_over(ctx); + + t64 = tcg_temp_new_i64(); + tcg_gen_extu_reg_i64(t64, load_gpr(ctx, rr)); + tcg_gen_shli_i64(t64, t64, 32); + + if (rs >= 4) { + tcg_gen_st_i64(t64, cpu_env, offsetof(CPUHPPAState, sr[rs])); + } else { + tcg_gen_mov_i64(cpu_sr[rs], t64); + } + tcg_temp_free_i64(t64); + + return nullify_end(ctx, DISAS_NEXT); +} + static DisasJumpType trans_mtctl(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { @@ -2069,8 +2131,7 @@ static DisasJumpType trans_mtsm(DisasContext *ctx, uint32_t insn, static const DisasInsn table_system[] = { { 0x00000000u, 0xfc001fe0u, trans_break }, - /* We don't implement space register, so MTSP is a nop. */ - { 0x00001820u, 0xffe01fffu, trans_nop }, + { 0x00001820u, 0xffe01fffu, trans_mtsp }, { 0x00001840u, 0xfc00ffffu, trans_mtctl }, { 0x016018c0u, 0xffe0ffffu, trans_mtsarcm }, { 0x000014a0u, 0xffffffe0u, trans_mfia }, From 35136a77cb6570ffcf91820e95e58f1185e39986 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 10 Oct 2017 21:19:34 -0700 Subject: [PATCH 09/43] target/hppa: Add control registers Signed-off-by: Richard Henderson --- linux-user/hppa/target_cpu.h | 2 +- linux-user/main.c | 4 +-- linux-user/signal.c | 4 +-- target/hppa/cpu.h | 23 ++++++++---- target/hppa/gdbstub.c | 12 +++---- target/hppa/mem_helper.c | 2 +- target/hppa/translate.c | 70 ++++++++++++++++++++++++------------ 7 files changed, 77 insertions(+), 40 deletions(-) diff --git a/linux-user/hppa/target_cpu.h b/linux-user/hppa/target_cpu.h index e50522eae9..7b78bbea80 100644 --- a/linux-user/hppa/target_cpu.h +++ b/linux-user/hppa/target_cpu.h @@ -33,7 +33,7 @@ static inline void cpu_clone_regs(CPUHPPAState *env, target_ulong newsp) static inline void cpu_set_tls(CPUHPPAState *env, target_ulong newtls) { - env->cr27 = newtls; + env->cr[27] = newtls; } #endif diff --git a/linux-user/main.c b/linux-user/main.c index fee0b24ee6..7de0e02487 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3786,14 +3786,14 @@ void cpu_loop(CPUHPPAState *env) info.si_signo = TARGET_SIGSEGV; info.si_errno = 0; info.si_code = TARGET_SEGV_ACCERR; - info._sifields._sigfault._addr = env->ior; + info._sifields._sigfault._addr = env->cr[CR_IOR]; queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; case EXCP_UNALIGN: info.si_signo = TARGET_SIGBUS; info.si_errno = 0; info.si_code = 0; - info._sifields._sigfault._addr = env->ior; + info._sifields._sigfault._addr = env->cr[CR_IOR]; queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; case EXCP_ILL: diff --git a/linux-user/signal.c b/linux-user/signal.c index 2db4507083..9a380b9e31 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -6442,7 +6442,7 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env) __put_user(env->fr[i], &sc->sc_fr[i]); } - __put_user(env->sar, &sc->sc_sar); + __put_user(env->cr[CR_SAR], &sc->sc_sar); } static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc) @@ -6463,7 +6463,7 @@ static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc) __get_user(env->iaoq_f, &sc->sc_iaoq[0]); __get_user(env->iaoq_b, &sc->sc_iaoq[1]); - __get_user(env->sar, &sc->sc_sar); + __get_user(env->cr[CR_SAR], &sc->sc_sar); } /* No, this doesn't look right, but it's copied straight from the kernel. */ diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index e3da05e5d3..7524cf8aa6 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -123,6 +123,20 @@ #define PSW_SM_W 0 #endif +#define CR_RC 0 +#define CR_SCRCCR 10 +#define CR_SAR 11 +#define CR_IVA 14 +#define CR_EIEM 15 +#define CR_IT 16 +#define CR_IIASQ 17 +#define CR_IIAOQ 18 +#define CR_IIR 19 +#define CR_ISR 20 +#define CR_IOR 21 +#define CR_IPSW 22 +#define CR_EIRR 23 + typedef struct CPUHPPAState CPUHPPAState; #if TARGET_REGISTER_BITS == 32 @@ -142,10 +156,6 @@ struct CPUHPPAState { uint64_t fr[32]; uint64_t sr[8]; /* stored shifted into place for gva */ - target_ureg sar; - target_ureg cr26; - target_ureg cr27; - target_ureg psw; /* All psw bits except the following: */ target_ureg psw_n; /* boolean */ target_sreg psw_v; /* in most significant bit */ @@ -163,11 +173,12 @@ struct CPUHPPAState { target_ureg iaoq_f; /* front */ target_ureg iaoq_b; /* back, aka next instruction */ - target_ureg ior; /* interrupt offset register */ - uint32_t fr0_shadow; /* flags, c, ca/cq, rm, d, enables */ float_status fp_status; + target_ureg cr[32]; /* control registers */ + target_ureg cr_back[2]; /* back of cr17/cr18 */ + /* Those resources are used only in QEMU core */ CPU_COMMON }; diff --git a/target/hppa/gdbstub.c b/target/hppa/gdbstub.c index 228d282fe9..fc27aec073 100644 --- a/target/hppa/gdbstub.c +++ b/target/hppa/gdbstub.c @@ -36,7 +36,7 @@ int hppa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) val = env->gr[n]; break; case 32: - val = env->sar; + val = env->cr[CR_SAR]; break; case 33: val = env->iaoq_f; @@ -45,10 +45,10 @@ int hppa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) val = env->iaoq_b; break; case 59: - val = env->cr26; + val = env->cr[26]; break; case 60: - val = env->cr27; + val = env->cr[27]; break; case 64 ... 127: val = extract64(env->fr[(n - 64) / 2], (n & 1 ? 0 : 32), 32); @@ -89,7 +89,7 @@ int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) env->gr[n] = val; break; case 32: - env->sar = val; + env->cr[CR_SAR] = val; break; case 33: env->iaoq_f = val; @@ -98,10 +98,10 @@ int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) env->iaoq_b = val; break; case 59: - env->cr26 = val; + env->cr[26] = val; break; case 60: - env->cr27 = val; + env->cr[27] = val; break; case 64: env->fr[0] = deposit64(env->fr[0], 32, 32, val); diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index bd116d6bc6..65e2c95b78 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -32,7 +32,7 @@ int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, /* ??? Test between data page fault and data memory protection trap, which would affect si_code. */ cs->exception_index = EXCP_DMP; - cpu->env.ior = address; + cpu->env.cr[CR_IOR] = address; return 1; } #else diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 50d41b0c63..89b336c2c4 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -328,8 +328,6 @@ static TCGv_reg cpu_psw_n; static TCGv_reg cpu_psw_v; static TCGv_reg cpu_psw_cb; static TCGv_reg cpu_psw_cb_msb; -static TCGv_reg cpu_cr26; -static TCGv_reg cpu_cr27; #include "exec/gen-icount.h" @@ -339,9 +337,7 @@ void hppa_translate_init(void) typedef struct { TCGv_reg *var; const char *name; int ofs; } GlobalVar; static const GlobalVar vars[] = { - DEF_VAR(sar), - DEF_VAR(cr26), - DEF_VAR(cr27), + { &cpu_sar, "sar", offsetof(CPUHPPAState, cr[CR_SAR]) }, DEF_VAR(psw_n), DEF_VAR(psw_v), DEF_VAR(psw_cb), @@ -1867,7 +1863,7 @@ static DisasJumpType do_page_zero(DisasContext *ctx) return DISAS_NORETURN; case 0xe0: /* SET_THREAD_POINTER */ - tcg_gen_mov_reg(cpu_cr27, cpu_gr[26]); + tcg_gen_st_reg(cpu_gr[26], cpu_env, offsetof(CPUHPPAState, cr[27])); tcg_gen_mov_reg(cpu_iaoq_f, cpu_gr[31]); tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4); return DISAS_IAQ_N_UPDATED; @@ -1948,34 +1944,39 @@ static DisasJumpType trans_mfctl(DisasContext *ctx, uint32_t insn, TCGv_reg tmp; switch (ctl) { - case 11: /* SAR */ + case CR_SAR: #ifdef TARGET_HPPA64 if (extract32(insn, 14, 1) == 0) { /* MFSAR without ,W masks low 5 bits. */ tmp = dest_gpr(ctx, rt); tcg_gen_andi_reg(tmp, cpu_sar, 31); save_gpr(ctx, rt, tmp); - break; + goto done; } #endif save_gpr(ctx, rt, cpu_sar); - break; - case 16: /* Interval Timer */ + goto done; + case CR_IT: /* Interval Timer */ + /* FIXME: Respect PSW_S bit. */ + nullify_over(ctx); tmp = dest_gpr(ctx, rt); - tcg_gen_movi_tl(tmp, 0); /* FIXME */ + tcg_gen_movi_reg(tmp, 0); /* FIXME */ save_gpr(ctx, rt, tmp); break; case 26: - save_gpr(ctx, rt, cpu_cr26); - break; case 27: - save_gpr(ctx, rt, cpu_cr27); break; default: /* All other control registers are privileged. */ - return gen_illegal(ctx); + CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG); + break; } + tmp = get_temp(ctx); + tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[ctl])); + save_gpr(ctx, rt, tmp); + + done: cond_free(&ctx->null_cond); return DISAS_NEXT; } @@ -2011,20 +2012,45 @@ static DisasJumpType trans_mtctl(DisasContext *ctx, uint32_t insn, { unsigned rin = extract32(insn, 16, 5); unsigned ctl = extract32(insn, 21, 5); + TCGv_reg reg = load_gpr(ctx, rin); TCGv_reg tmp; - if (ctl == 11) { /* SAR */ + if (ctl == CR_SAR) { tmp = tcg_temp_new(); - tcg_gen_andi_reg(tmp, load_gpr(ctx, rin), TARGET_REGISTER_BITS - 1); + tcg_gen_andi_reg(tmp, reg, TARGET_REGISTER_BITS - 1); save_or_nullify(ctx, cpu_sar, tmp); tcg_temp_free(tmp); - } else { - /* All other control registers are privileged or read-only. */ - return gen_illegal(ctx); + + cond_free(&ctx->null_cond); + return DISAS_NEXT; } - cond_free(&ctx->null_cond); - return DISAS_NEXT; + /* All other control registers are privileged or read-only. */ + CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG); + + nullify_over(ctx); + switch (ctl) { + case CR_IT: + /* ??? modify interval timer offset */ + break; + + case CR_IIASQ: + case CR_IIAOQ: + /* FIXME: Respect PSW_Q bit */ + /* The write advances the queue and stores to the back element. */ + tmp = get_temp(ctx); + tcg_gen_ld_reg(tmp, cpu_env, + offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ])); + tcg_gen_st_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[ctl])); + tcg_gen_st_reg(reg, cpu_env, + offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ])); + break; + + default: + tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl])); + break; + } + return nullify_end(ctx, DISAS_NEXT); } static DisasJumpType trans_mtsarcm(DisasContext *ctx, uint32_t insn, From 7f221b0706f7ab8359cb9008650dc7370238839c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 11 Oct 2017 07:48:05 -0700 Subject: [PATCH 10/43] target/hppa: Adjust insn mask for mfctl,w While the E bit is only used for pa2.0 mfctl,w from sar, the otherwise reserved bit does not appear to be decoded. Signed-off-by: Richard Henderson --- target/hppa/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 89b336c2c4..8ca58f3df3 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2162,7 +2162,7 @@ static const DisasInsn table_system[] = { { 0x016018c0u, 0xffe0ffffu, trans_mtsarcm }, { 0x000014a0u, 0xffffffe0u, trans_mfia }, { 0x000004a0u, 0xffff1fe0u, trans_mfsp }, - { 0x000008a0u, 0xfc1fffe0u, trans_mfctl }, + { 0x000008a0u, 0xfc1fbfe0u, trans_mfctl }, { 0x00000400u, 0xffffffffu, trans_sync }, { 0x000010a0u, 0xfc1f3fe0u, trans_ldsid }, #ifndef CONFIG_USER_ONLY From f49b3537cb28b98284f6ce893ef7240a3cacded3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 11 Oct 2017 08:54:49 -0700 Subject: [PATCH 11/43] target/hppa: Implement rfi Signed-off-by: Richard Henderson --- target/hppa/cpu.h | 1 + target/hppa/helper.h | 2 ++ target/hppa/op_helper.c | 24 ++++++++++++++++++++++++ target/hppa/translate.c | 30 ++++++++++++++++++++++++++++-- 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 7524cf8aa6..ef36826f54 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -178,6 +178,7 @@ struct CPUHPPAState { target_ureg cr[32]; /* control registers */ target_ureg cr_back[2]; /* back of cr17/cr18 */ + target_ureg shadow[7]; /* shadow registers */ /* Those resources are used only in QEMU core */ CPU_COMMON diff --git a/target/hppa/helper.h b/target/hppa/helper.h index 254a4da133..79d22ae486 100644 --- a/target/hppa/helper.h +++ b/target/hppa/helper.h @@ -78,5 +78,7 @@ DEF_HELPER_FLAGS_4(fmpyfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_4(fmpynfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) #ifndef CONFIG_USER_ONLY +DEF_HELPER_1(rfi, void, env) +DEF_HELPER_1(rfi_r, void, env) DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr) #endif diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 1d56ba497b..cf9fe46942 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -614,4 +614,28 @@ target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm) env->psw = (psw & ~PSW_SM) | (nsm & PSW_SM); return psw & PSW_SM; } + +void HELPER(rfi)(CPUHPPAState *env) +{ + /* ??? On second reading this condition simply seems + to be undefined rather than a diagnosed trap. */ + if (env->psw & (PSW_I | PSW_R | PSW_Q)) { + helper_excp(env, EXCP_ILL); + } + env->iaoq_f = env->cr[CR_IIAOQ]; + env->iaoq_b = env->cr_back[1]; + cpu_hppa_put_psw(env, env->cr[CR_IPSW]); +} + +void HELPER(rfi_r)(CPUHPPAState *env) +{ + env->gr[1] = env->shadow[0]; + env->gr[8] = env->shadow[1]; + env->gr[9] = env->shadow[2]; + env->gr[16] = env->shadow[3]; + env->gr[17] = env->shadow[4]; + env->gr[24] = env->shadow[5]; + env->gr[25] = env->shadow[6]; + helper_rfi(env); +} #endif diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 8ca58f3df3..df0bb04907 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -655,6 +655,10 @@ static DisasJumpType nullify_end(DisasContext *ctx, DisasJumpType status) { TCGLabel *null_lab = ctx->null_lab; + /* For NEXT, NORETURN, STALE, we can easily continue (or exit). + For UPDATED, we cannot update on the nullified path. */ + assert(status != DISAS_IAQ_N_UPDATED); + if (likely(null_lab == NULL)) { /* The current insn wasn't conditional or handled the condition applied to it without a branch, so the (new) setting of @@ -676,8 +680,6 @@ static DisasJumpType nullify_end(DisasContext *ctx, DisasJumpType status) gen_set_label(null_lab); ctx->null_cond = cond_make_n(); } - - assert(status != DISAS_NORETURN && status != DISAS_IAQ_N_UPDATED); if (status == DISAS_NORETURN) { status = DISAS_NEXT; } @@ -2153,6 +2155,29 @@ static DisasJumpType trans_mtsm(DisasContext *ctx, uint32_t insn, /* Exit the TB to recognize new interrupts. */ return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT); } + +static DisasJumpType trans_rfi(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + unsigned comp = extract32(insn, 5, 4); + + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + nullify_over(ctx); + + if (comp == 5) { + gen_helper_rfi_r(cpu_env); + } else { + gen_helper_rfi(cpu_env); + } + if (ctx->base.singlestep_enabled) { + gen_excp_1(EXCP_DEBUG); + } else { + tcg_gen_exit_tb(0); + } + + /* Exit the TB to recognize new interrupts. */ + return nullify_end(ctx, DISAS_NORETURN); +} #endif /* !CONFIG_USER_ONLY */ static const DisasInsn table_system[] = { @@ -2169,6 +2194,7 @@ static const DisasInsn table_system[] = { { 0x00000e60u, 0xfc00ffe0u, trans_rsm }, { 0x00000d60u, 0xfc00ffe0u, trans_ssm }, { 0x00001860u, 0xffe0ffffu, trans_mtsm }, + { 0x00000c00u, 0xfffffe1fu, trans_rfi }, #endif }; From 1a19da0da44430581bf48b595d75ad6e9fc7e428 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 11 Oct 2017 13:19:11 -0700 Subject: [PATCH 12/43] target/hppa: Fill in hppa_cpu_do_interrupt/hppa_cpu_exec_interrupt Signed-off-by: Richard Henderson --- target/hppa/Makefile.objs | 1 + target/hppa/cpu.c | 2 + target/hppa/helper.c | 63 -------------- target/hppa/int_helper.c | 176 ++++++++++++++++++++++++++++++++++++++ target/hppa/translate.c | 16 +++- 5 files changed, 192 insertions(+), 66 deletions(-) create mode 100644 target/hppa/int_helper.c diff --git a/target/hppa/Makefile.objs b/target/hppa/Makefile.objs index d89285307b..dcd60a6839 100644 --- a/target/hppa/Makefile.objs +++ b/target/hppa/Makefile.objs @@ -1 +1,2 @@ obj-y += translate.o helper.o cpu.o op_helper.o gdbstub.o mem_helper.o +obj-y += int_helper.o diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index 9962ab71ee..ca619578dd 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -106,8 +106,10 @@ static void hppa_cpu_initfn(Object *obj) CPUHPPAState *env = &cpu->env; cs->env_ptr = env; + cs->exception_index = -1; cpu_hppa_loaded_fr0(env); set_snan_bit_is_one(true, &env->fp_status); + cpu_hppa_put_psw(env, PSW_W); } static ObjectClass *hppa_cpu_class_by_name(const char *cpu_model) diff --git a/target/hppa/helper.c b/target/hppa/helper.c index 48ac80cb2d..6e8758f82c 100644 --- a/target/hppa/helper.c +++ b/target/hppa/helper.c @@ -67,69 +67,6 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg psw) env->psw_cb = cb; } -void hppa_cpu_do_interrupt(CPUState *cs) -{ - HPPACPU *cpu = HPPA_CPU(cs); - CPUHPPAState *env = &cpu->env; - int i = cs->exception_index; - - if (qemu_loglevel_mask(CPU_LOG_INT)) { - static const char * const names[] = { - [EXCP_HPMC] = "high priority machine check", - [EXCP_POWER_FAIL] = "power fail interrupt", - [EXCP_RC] = "recovery counter trap", - [EXCP_EXT_INTERRUPT] = "external interrupt", - [EXCP_LPMC] = "low priority machine check", - [EXCP_ITLB_MISS] = "instruction tlb miss fault", - [EXCP_IMP] = "instruction memory protection trap", - [EXCP_ILL] = "illegal instruction trap", - [EXCP_BREAK] = "break instruction trap", - [EXCP_PRIV_OPR] = "privileged operation trap", - [EXCP_PRIV_REG] = "privileged register trap", - [EXCP_OVERFLOW] = "overflow trap", - [EXCP_COND] = "conditional trap", - [EXCP_ASSIST] = "assist exception trap", - [EXCP_DTLB_MISS] = "data tlb miss fault", - [EXCP_NA_ITLB_MISS] = "non-access instruction tlb miss", - [EXCP_NA_DTLB_MISS] = "non-access data tlb miss", - [EXCP_DMP] = "data memory protection trap", - [EXCP_DMB] = "data memory break trap", - [EXCP_TLB_DIRTY] = "tlb dirty bit trap", - [EXCP_PAGE_REF] = "page reference trap", - [EXCP_ASSIST_EMU] = "assist emulation trap", - [EXCP_HPT] = "high-privilege transfer trap", - [EXCP_LPT] = "low-privilege transfer trap", - [EXCP_TB] = "taken branch trap", - [EXCP_DMAR] = "data memory access rights trap", - [EXCP_DMPI] = "data memory protection id trap", - [EXCP_UNALIGN] = "unaligned data reference trap", - [EXCP_PER_INTERRUPT] = "performance monitor interrupt", - [EXCP_SYSCALL] = "syscall", - [EXCP_SYSCALL_LWS] = "syscall-lws", - }; - static int count; - const char *name = NULL; - - if (i >= 0 && i < ARRAY_SIZE(names)) { - name = names[i]; - } - if (name) { - qemu_log("INT %6d: %s ia_f=" TARGET_FMT_lx "\n", - ++count, name, env->iaoq_f); - } else { - qemu_log("INT %6d: unknown %d ia_f=" TARGET_FMT_lx "\n", - ++count, i, env->iaoq_f); - } - } - cs->exception_index = -1; -} - -bool hppa_cpu_exec_interrupt(CPUState *cs, int interrupt_request) -{ - abort(); - return false; -} - void hppa_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int flags) { diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c new file mode 100644 index 0000000000..a59aae1189 --- /dev/null +++ b/target/hppa/int_helper.c @@ -0,0 +1,176 @@ +/* + * HPPA interrupt helper routines + * + * Copyright (c) 2017 Richard Henderson + * + * 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, see . + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "cpu.h" +#include "exec/exec-all.h" +#include "exec/helper-proto.h" +#include "qom/cpu.h" + + +void hppa_cpu_do_interrupt(CPUState *cs) +{ + HPPACPU *cpu = HPPA_CPU(cs); + CPUHPPAState *env = &cpu->env; + int i = cs->exception_index; + target_ureg iaoq_f = env->iaoq_f; + target_ureg iaoq_b = env->iaoq_b; + +#ifndef CONFIG_USER_ONLY + target_ureg old_psw; + + /* As documented in pa2.0 -- interruption handling. */ + /* step 1 */ + env->cr[CR_IPSW] = old_psw = cpu_hppa_get_psw(env); + + /* step 2 -- note PSW_W == 0 for !HPPA64. */ + cpu_hppa_put_psw(env, PSW_W | (i == EXCP_HPMC ? PSW_M : 0)); + + /* step 3 */ + env->cr[CR_IIAOQ] = iaoq_f; + env->cr_back[1] = iaoq_b; + + if (old_psw & PSW_Q) { + /* step 5 */ + /* ISR and IOR will be set elsewhere. */ + switch (i) { + case EXCP_ILL: + case EXCP_BREAK: + case EXCP_PRIV_REG: + case EXCP_PRIV_OPR: + /* IIR set via translate.c. */ + break; + + case EXCP_OVERFLOW: + case EXCP_COND: + case EXCP_ASSIST: + case EXCP_DTLB_MISS: + case EXCP_NA_ITLB_MISS: + case EXCP_NA_DTLB_MISS: + case EXCP_DMAR: + case EXCP_DMPI: + case EXCP_UNALIGN: + case EXCP_DMP: + case EXCP_DMB: + case EXCP_TLB_DIRTY: + case EXCP_PAGE_REF: + case EXCP_ASSIST_EMU: + { + /* Avoid reading directly from the virtual address, lest we + raise another exception from some sort of TLB issue. */ + vaddr vaddr; + hwaddr paddr; + + paddr = vaddr = iaoq_f & -4; + env->cr[CR_IIR] = ldl_phys(cs->as, paddr); + } + break; + + default: + /* Other exceptions do not set IIR. */ + break; + } + + /* step 6 */ + env->shadow[0] = env->gr[1]; + env->shadow[1] = env->gr[8]; + env->shadow[2] = env->gr[9]; + env->shadow[3] = env->gr[16]; + env->shadow[4] = env->gr[17]; + env->shadow[5] = env->gr[24]; + env->shadow[6] = env->gr[25]; + } + + /* step 7 */ + env->iaoq_f = env->cr[CR_IVA] + 32 * i; + env->iaoq_b = env->iaoq_f + 4; +#endif + + if (qemu_loglevel_mask(CPU_LOG_INT)) { + static const char * const names[] = { + [EXCP_HPMC] = "high priority machine check", + [EXCP_POWER_FAIL] = "power fail interrupt", + [EXCP_RC] = "recovery counter trap", + [EXCP_EXT_INTERRUPT] = "external interrupt", + [EXCP_LPMC] = "low priority machine check", + [EXCP_ITLB_MISS] = "instruction tlb miss fault", + [EXCP_IMP] = "instruction memory protection trap", + [EXCP_ILL] = "illegal instruction trap", + [EXCP_BREAK] = "break instruction trap", + [EXCP_PRIV_OPR] = "privileged operation trap", + [EXCP_PRIV_REG] = "privileged register trap", + [EXCP_OVERFLOW] = "overflow trap", + [EXCP_COND] = "conditional trap", + [EXCP_ASSIST] = "assist exception trap", + [EXCP_DTLB_MISS] = "data tlb miss fault", + [EXCP_NA_ITLB_MISS] = "non-access instruction tlb miss", + [EXCP_NA_DTLB_MISS] = "non-access data tlb miss", + [EXCP_DMP] = "data memory protection trap", + [EXCP_DMB] = "data memory break trap", + [EXCP_TLB_DIRTY] = "tlb dirty bit trap", + [EXCP_PAGE_REF] = "page reference trap", + [EXCP_ASSIST_EMU] = "assist emulation trap", + [EXCP_HPT] = "high-privilege transfer trap", + [EXCP_LPT] = "low-privilege transfer trap", + [EXCP_TB] = "taken branch trap", + [EXCP_DMAR] = "data memory access rights trap", + [EXCP_DMPI] = "data memory protection id trap", + [EXCP_UNALIGN] = "unaligned data reference trap", + [EXCP_PER_INTERRUPT] = "performance monitor interrupt", + [EXCP_SYSCALL] = "syscall", + [EXCP_SYSCALL_LWS] = "syscall-lws", + }; + static int count; + const char *name = NULL; + char unknown[16]; + + if (i >= 0 && i < ARRAY_SIZE(names)) { + name = names[i]; + } + if (!name) { + snprintf(unknown, sizeof(unknown), "unknown %d", i); + name = unknown; + } + qemu_log("INT %6d: %s @ " TARGET_FMT_lx "," TARGET_FMT_lx + " -> " TREG_FMT_lx " " TARGET_FMT_lx "\n", + ++count, name, + (target_ulong)iaoq_f, + (target_ulong)iaoq_b, + env->iaoq_f, + (target_ulong)env->cr[CR_IOR]); + } + cs->exception_index = -1; +} + +bool hppa_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ +#ifndef CONFIG_USER_ONLY + HPPACPU *cpu = HPPA_CPU(cs); + CPUHPPAState *env = &cpu->env; + + /* If interrupts are requested and enabled, raise them. */ + if ((env->psw & PSW_I) && (interrupt_request & CPU_INTERRUPT_HARD)) { + cs->exception_index = EXCP_EXT_INTERRUPT; + hppa_cpu_do_interrupt(cs); + return true; + } +#endif + return false; +} diff --git a/target/hppa/translate.c b/target/hppa/translate.c index df0bb04907..34b999fb2c 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -282,6 +282,7 @@ typedef struct DisasContext { DisasCond null_cond; TCGLabel *null_lab; + uint32_t insn; int mmu_idx; int privilege; bool psw_n_nonzero; @@ -716,17 +717,25 @@ static DisasJumpType gen_excp(DisasContext *ctx, int exception) return DISAS_NORETURN; } +static DisasJumpType gen_excp_iir(DisasContext *ctx, int exc) +{ + TCGv_reg tmp = tcg_const_reg(ctx->insn); + tcg_gen_st_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[CR_IIR])); + tcg_temp_free(tmp); + return gen_excp(ctx, exc); +} + static DisasJumpType gen_illegal(DisasContext *ctx) { nullify_over(ctx); - return nullify_end(ctx, gen_excp(ctx, EXCP_ILL)); + return nullify_end(ctx, gen_excp_iir(ctx, EXCP_ILL)); } #define CHECK_MOST_PRIVILEGED(EXCP) \ do { \ if (ctx->privilege != 0) { \ nullify_over(ctx); \ - return nullify_end(ctx, gen_excp(ctx, EXCP)); \ + return nullify_end(ctx, gen_excp_iir(ctx, EXCP)); \ } \ } while (0) @@ -1893,7 +1902,7 @@ static DisasJumpType trans_break(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { nullify_over(ctx); - return nullify_end(ctx, gen_excp(ctx, EXCP_BREAK)); + return nullify_end(ctx, gen_excp_iir(ctx, EXCP_BREAK)); } static DisasJumpType trans_sync(DisasContext *ctx, uint32_t insn, @@ -4270,6 +4279,7 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) ctx->null_cond.c = TCG_COND_NEVER; ret = DISAS_NEXT; } else { + ctx->insn = insn; ret = translate_one(ctx, insn); assert(ctx->null_lab == NULL); } From 08aec8b53c76b90f935b96ba2f466331a8a3b8ae Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 29 Oct 2017 16:31:08 +0100 Subject: [PATCH 13/43] target/hppa: Implement unaligned access trap Signed-off-by: Richard Henderson --- target/hppa/cpu.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index ca619578dd..4d0b760baa 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -48,6 +48,23 @@ static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info) info->print_insn = print_insn_hppa; } +static void hppa_cpu_do_unaligned_access(CPUState *cs, vaddr addr, + MMUAccessType access_type, + int mmu_idx, uintptr_t retaddr) +{ + HPPACPU *cpu = HPPA_CPU(cs); + CPUHPPAState *env = &cpu->env; + + cs->exception_index = EXCP_UNALIGN; + if (env->psw & PSW_Q) { + /* ??? Needs tweaking for hppa64. */ + env->cr[CR_IOR] = addr; + env->cr[CR_ISR] = addr >> 32; + } + + cpu_loop_exit_restore(cs, retaddr); +} + static void hppa_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); @@ -139,7 +156,7 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data) #else cc->get_phys_page_debug = hppa_cpu_get_phys_page_debug; #endif - + cc->do_unaligned_access = hppa_cpu_do_unaligned_access; cc->disas_set_info = hppa_cpu_disas_set_info; cc->tcg_initialize = hppa_translate_init; From 86f8d05fc0bd077811c11c603b4263df2192e8e0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 28 Dec 2017 12:38:46 -0800 Subject: [PATCH 14/43] target/hppa: Use space registers in data operations This changes the system virtual address width to 64-bit and incorporates the space registers into load/store operations. Signed-off-by: Richard Henderson --- target/hppa/cpu.h | 14 ++ target/hppa/translate.c | 334 ++++++++++++++++++++++------------------ 2 files changed, 201 insertions(+), 147 deletions(-) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index ef36826f54..49f95a0b77 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -23,10 +23,24 @@ #include "qemu-common.h" #include "cpu-qom.h" +#ifdef TARGET_HPPA64 +#define TARGET_LONG_BITS 64 +#define TARGET_VIRT_ADDR_SPACE_BITS 64 +#define TARGET_REGISTER_BITS 64 +#define TARGET_PHYS_ADDR_SPACE_BITS 64 +#elif defined(CONFIG_USER_ONLY) #define TARGET_LONG_BITS 32 #define TARGET_VIRT_ADDR_SPACE_BITS 32 #define TARGET_REGISTER_BITS 32 #define TARGET_PHYS_ADDR_SPACE_BITS 32 +#else +/* In order to form the GVA from space:offset, + we need a 64-bit virtual address space. */ +#define TARGET_LONG_BITS 64 +#define TARGET_VIRT_ADDR_SPACE_BITS 64 +#define TARGET_REGISTER_BITS 32 +#define TARGET_PHYS_ADDR_SPACE_BITS 32 +#endif #define CPUArchState struct CPUHPPAState diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 34b999fb2c..6be9e0c3ff 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -276,8 +276,9 @@ typedef struct DisasContext { target_ureg iaoq_n; TCGv_reg iaoq_n_var; - int ntemps; - TCGv_reg temps[8]; + int ntempr, ntempl; + TCGv_reg tempr[4]; + TCGv_tl templ[4]; DisasCond null_cond; TCGLabel *null_lab; @@ -458,11 +459,20 @@ static void cond_free(DisasCond *cond) static TCGv_reg get_temp(DisasContext *ctx) { - unsigned i = ctx->ntemps++; - g_assert(i < ARRAY_SIZE(ctx->temps)); - return ctx->temps[i] = tcg_temp_new(); + unsigned i = ctx->ntempr++; + g_assert(i < ARRAY_SIZE(ctx->tempr)); + return ctx->tempr[i] = tcg_temp_new(); } +#ifndef CONFIG_USER_ONLY +static TCGv_tl get_temp_tl(DisasContext *ctx) +{ + unsigned i = ctx->ntempl++; + g_assert(i < ARRAY_SIZE(ctx->templ)); + return ctx->templ[i] = tcg_temp_new_tl(); +} +#endif + static TCGv_reg load_const(DisasContext *ctx, target_sreg v) { TCGv_reg t = get_temp(ctx); @@ -1324,6 +1334,70 @@ static DisasJumpType do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1, return DISAS_NEXT; } +#ifndef CONFIG_USER_ONLY +/* Top 2 bits of the base register select sp[4-7]. */ +static TCGv_i64 space_select(DisasContext *ctx, int sp, TCGv_reg base) +{ + TCGv_ptr ptr; + TCGv_reg tmp; + TCGv_i64 spc; + + if (sp != 0) { + return cpu_sr[sp]; + } + + ptr = tcg_temp_new_ptr(); + tmp = tcg_temp_new(); + spc = get_temp_tl(ctx); + + tcg_gen_shri_reg(tmp, base, TARGET_REGISTER_BITS - 5); + tcg_gen_andi_reg(tmp, tmp, 030); + tcg_gen_trunc_reg_ptr(ptr, tmp); + tcg_temp_free(tmp); + + tcg_gen_add_ptr(ptr, ptr, cpu_env); + tcg_gen_ld_i64(spc, ptr, offsetof(CPUHPPAState, sr[4])); + tcg_temp_free_ptr(ptr); + + return spc; +} +#endif + +static void form_gva(DisasContext *ctx, TCGv_tl *pgva, TCGv_reg *pofs, + unsigned rb, unsigned rx, int scale, target_sreg disp, + unsigned sp, int modify, bool is_phys) +{ + TCGv_reg base = load_gpr(ctx, rb); + TCGv_reg ofs; + + /* Note that RX is mutually exclusive with DISP. */ + if (rx) { + ofs = get_temp(ctx); + tcg_gen_shli_reg(ofs, cpu_gr[rx], scale); + tcg_gen_add_reg(ofs, ofs, base); + } else if (disp || modify) { + ofs = get_temp(ctx); + tcg_gen_addi_reg(ofs, base, disp); + } else { + ofs = base; + } + + *pofs = ofs; +#ifdef CONFIG_USER_ONLY + *pgva = (modify <= 0 ? ofs : base); +#else + TCGv_tl addr = get_temp_tl(ctx); + tcg_gen_extu_reg_tl(addr, modify <= 0 ? ofs : base); + if (ctx->base.tb->flags & PSW_W) { + tcg_gen_andi_tl(addr, addr, 0x3fffffffffffffffull); + } + if (!is_phys) { + tcg_gen_or_tl(addr, addr, space_select(ctx, sp, base)); + } + *pgva = addr; +#endif +} + /* Emit a memory load. The modify parameter should be * < 0 for pre-modify, * > 0 for post-modify, @@ -1331,118 +1405,74 @@ static DisasJumpType do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1, */ static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb, unsigned rx, int scale, target_sreg disp, - int modify, TCGMemOp mop) + unsigned sp, int modify, TCGMemOp mop) { - TCGv_reg addr, base; + TCGv_reg ofs; + TCGv_tl addr; /* Caller uses nullify_over/nullify_end. */ assert(ctx->null_cond.c == TCG_COND_NEVER); - addr = tcg_temp_new(); - base = load_gpr(ctx, rb); - - /* Note that RX is mutually exclusive with DISP. */ - if (rx) { - tcg_gen_shli_reg(addr, cpu_gr[rx], scale); - tcg_gen_add_reg(addr, addr, base); - } else { - tcg_gen_addi_reg(addr, base, disp); + form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify, + ctx->mmu_idx == MMU_PHYS_IDX); + tcg_gen_qemu_ld_reg(dest, addr, ctx->mmu_idx, mop); + if (modify) { + save_gpr(ctx, rb, ofs); } - - if (modify == 0) { - tcg_gen_qemu_ld_i32(dest, addr, ctx->mmu_idx, mop); - } else { - tcg_gen_qemu_ld_i32(dest, (modify < 0 ? addr : base), - ctx->mmu_idx, mop); - save_gpr(ctx, rb, addr); - } - tcg_temp_free(addr); } static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb, unsigned rx, int scale, target_sreg disp, - int modify, TCGMemOp mop) + unsigned sp, int modify, TCGMemOp mop) { - TCGv_reg addr, base; + TCGv_reg ofs; + TCGv_tl addr; /* Caller uses nullify_over/nullify_end. */ assert(ctx->null_cond.c == TCG_COND_NEVER); - addr = tcg_temp_new(); - base = load_gpr(ctx, rb); - - /* Note that RX is mutually exclusive with DISP. */ - if (rx) { - tcg_gen_shli_reg(addr, cpu_gr[rx], scale); - tcg_gen_add_reg(addr, addr, base); - } else { - tcg_gen_addi_reg(addr, base, disp); + form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify, + ctx->mmu_idx == MMU_PHYS_IDX); + tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop); + if (modify) { + save_gpr(ctx, rb, ofs); } - - if (modify == 0) { - tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop); - } else { - tcg_gen_qemu_ld_i64(dest, (modify < 0 ? addr : base), - ctx->mmu_idx, mop); - save_gpr(ctx, rb, addr); - } - tcg_temp_free(addr); } static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb, unsigned rx, int scale, target_sreg disp, - int modify, TCGMemOp mop) + unsigned sp, int modify, TCGMemOp mop) { - TCGv_reg addr, base; + TCGv_reg ofs; + TCGv_tl addr; /* Caller uses nullify_over/nullify_end. */ assert(ctx->null_cond.c == TCG_COND_NEVER); - addr = tcg_temp_new(); - base = load_gpr(ctx, rb); - - /* Note that RX is mutually exclusive with DISP. */ - if (rx) { - tcg_gen_shli_reg(addr, cpu_gr[rx], scale); - tcg_gen_add_reg(addr, addr, base); - } else { - tcg_gen_addi_reg(addr, base, disp); + form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify, + ctx->mmu_idx == MMU_PHYS_IDX); + tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop); + if (modify) { + save_gpr(ctx, rb, ofs); } - - tcg_gen_qemu_st_i32(src, (modify <= 0 ? addr : base), ctx->mmu_idx, mop); - - if (modify != 0) { - save_gpr(ctx, rb, addr); - } - tcg_temp_free(addr); } static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb, unsigned rx, int scale, target_sreg disp, - int modify, TCGMemOp mop) + unsigned sp, int modify, TCGMemOp mop) { - TCGv_reg addr, base; + TCGv_reg ofs; + TCGv_tl addr; /* Caller uses nullify_over/nullify_end. */ assert(ctx->null_cond.c == TCG_COND_NEVER); - addr = tcg_temp_new(); - base = load_gpr(ctx, rb); - - /* Note that RX is mutually exclusive with DISP. */ - if (rx) { - tcg_gen_shli_reg(addr, cpu_gr[rx], scale); - tcg_gen_add_reg(addr, addr, base); - } else { - tcg_gen_addi_reg(addr, base, disp); + form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify, + ctx->mmu_idx == MMU_PHYS_IDX); + tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop); + if (modify) { + save_gpr(ctx, rb, ofs); } - - tcg_gen_qemu_st_i64(src, (modify <= 0 ? addr : base), ctx->mmu_idx, mop); - - if (modify != 0) { - save_gpr(ctx, rb, addr); - } - tcg_temp_free(addr); } #if TARGET_REGISTER_BITS == 64 @@ -1455,7 +1485,7 @@ static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb, static DisasJumpType do_load(DisasContext *ctx, unsigned rt, unsigned rb, unsigned rx, int scale, target_sreg disp, - int modify, TCGMemOp mop) + unsigned sp, int modify, TCGMemOp mop) { TCGv_reg dest; @@ -1468,7 +1498,7 @@ static DisasJumpType do_load(DisasContext *ctx, unsigned rt, unsigned rb, /* Make sure if RT == RB, we see the result of the load. */ dest = get_temp(ctx); } - do_load_reg(ctx, dest, rb, rx, scale, disp, modify, mop); + do_load_reg(ctx, dest, rb, rx, scale, disp, sp, modify, mop); save_gpr(ctx, rt, dest); return nullify_end(ctx, DISAS_NEXT); @@ -1476,14 +1506,14 @@ static DisasJumpType do_load(DisasContext *ctx, unsigned rt, unsigned rb, static DisasJumpType do_floadw(DisasContext *ctx, unsigned rt, unsigned rb, unsigned rx, int scale, target_sreg disp, - int modify) + unsigned sp, int modify) { TCGv_i32 tmp; nullify_over(ctx); tmp = tcg_temp_new_i32(); - do_load_32(ctx, tmp, rb, rx, scale, disp, modify, MO_TEUL); + do_load_32(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUL); save_frw_i32(rt, tmp); tcg_temp_free_i32(tmp); @@ -1496,14 +1526,14 @@ static DisasJumpType do_floadw(DisasContext *ctx, unsigned rt, unsigned rb, static DisasJumpType do_floadd(DisasContext *ctx, unsigned rt, unsigned rb, unsigned rx, int scale, target_sreg disp, - int modify) + unsigned sp, int modify) { TCGv_i64 tmp; nullify_over(ctx); tmp = tcg_temp_new_i64(); - do_load_64(ctx, tmp, rb, rx, scale, disp, modify, MO_TEQ); + do_load_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ); save_frd(rt, tmp); tcg_temp_free_i64(tmp); @@ -1515,23 +1545,24 @@ static DisasJumpType do_floadd(DisasContext *ctx, unsigned rt, unsigned rb, } static DisasJumpType do_store(DisasContext *ctx, unsigned rt, unsigned rb, - target_sreg disp, int modify, TCGMemOp mop) + target_sreg disp, unsigned sp, + int modify, TCGMemOp mop) { nullify_over(ctx); - do_store_reg(ctx, load_gpr(ctx, rt), rb, 0, 0, disp, modify, mop); + do_store_reg(ctx, load_gpr(ctx, rt), rb, 0, 0, disp, sp, modify, mop); return nullify_end(ctx, DISAS_NEXT); } static DisasJumpType do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb, unsigned rx, int scale, target_sreg disp, - int modify) + unsigned sp, int modify) { TCGv_i32 tmp; nullify_over(ctx); tmp = load_frw_i32(rt); - do_store_32(ctx, tmp, rb, rx, scale, disp, modify, MO_TEUL); + do_store_32(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUL); tcg_temp_free_i32(tmp); return nullify_end(ctx, DISAS_NEXT); @@ -1539,14 +1570,14 @@ static DisasJumpType do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb, static DisasJumpType do_fstored(DisasContext *ctx, unsigned rt, unsigned rb, unsigned rx, int scale, target_sreg disp, - int modify) + unsigned sp, int modify) { TCGv_i64 tmp; nullify_over(ctx); tmp = load_frd(rt); - do_store_64(ctx, tmp, rb, rx, scale, disp, modify, MO_TEQ); + do_store_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ); tcg_temp_free_i64(tmp); return nullify_end(ctx, DISAS_NEXT); @@ -2228,18 +2259,21 @@ static DisasJumpType trans_probe(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { unsigned rt = extract32(insn, 0, 5); + unsigned sp = extract32(insn, 14, 2); unsigned rb = extract32(insn, 21, 5); unsigned is_write = extract32(insn, 6, 1); - TCGv_reg dest; + TCGv_reg dest, ofs; + TCGv_tl addr; nullify_over(ctx); /* ??? Do something with priv level operand. */ dest = dest_gpr(ctx, rt); + form_gva(ctx, &addr, &ofs, rb, 0, 0, 0, sp, 0, false); if (is_write) { - gen_helper_probe_w(dest, load_gpr(ctx, rb)); + gen_helper_probe_w(dest, addr); } else { - gen_helper_probe_r(dest, load_gpr(ctx, rb)); + gen_helper_probe_r(dest, addr); } save_gpr(ctx, rt, dest); return nullify_end(ctx, DISAS_NEXT); @@ -2628,12 +2662,13 @@ static DisasJumpType trans_ld_idx_i(DisasContext *ctx, uint32_t insn, unsigned m = extract32(insn, 5, 1); unsigned sz = extract32(insn, 6, 2); unsigned a = extract32(insn, 13, 1); + unsigned sp = extract32(insn, 14, 2); int disp = low_sextract(insn, 16, 5); unsigned rb = extract32(insn, 21, 5); int modify = (m ? (a ? -1 : 1) : 0); TCGMemOp mop = MO_TE | sz; - return do_load(ctx, rt, rb, 0, 0, disp, modify, mop); + return do_load(ctx, rt, rb, 0, 0, disp, sp, modify, mop); } static DisasJumpType trans_ld_idx_x(DisasContext *ctx, uint32_t insn, @@ -2643,11 +2678,12 @@ static DisasJumpType trans_ld_idx_x(DisasContext *ctx, uint32_t insn, unsigned m = extract32(insn, 5, 1); unsigned sz = extract32(insn, 6, 2); unsigned u = extract32(insn, 13, 1); + unsigned sp = extract32(insn, 14, 2); unsigned rx = extract32(insn, 16, 5); unsigned rb = extract32(insn, 21, 5); TCGMemOp mop = MO_TE | sz; - return do_load(ctx, rt, rb, rx, u ? sz : 0, 0, m, mop); + return do_load(ctx, rt, rb, rx, u ? sz : 0, 0, sp, m, mop); } static DisasJumpType trans_st_idx_i(DisasContext *ctx, uint32_t insn, @@ -2657,12 +2693,13 @@ static DisasJumpType trans_st_idx_i(DisasContext *ctx, uint32_t insn, unsigned m = extract32(insn, 5, 1); unsigned sz = extract32(insn, 6, 2); unsigned a = extract32(insn, 13, 1); + unsigned sp = extract32(insn, 14, 2); unsigned rr = extract32(insn, 16, 5); unsigned rb = extract32(insn, 21, 5); int modify = (m ? (a ? -1 : 1) : 0); TCGMemOp mop = MO_TE | sz; - return do_store(ctx, rr, rb, disp, modify, mop); + return do_store(ctx, rr, rb, disp, sp, modify, mop); } static DisasJumpType trans_ldcw(DisasContext *ctx, uint32_t insn, @@ -2672,16 +2709,16 @@ static DisasJumpType trans_ldcw(DisasContext *ctx, uint32_t insn, unsigned m = extract32(insn, 5, 1); unsigned i = extract32(insn, 12, 1); unsigned au = extract32(insn, 13, 1); + unsigned sp = extract32(insn, 14, 2); unsigned rx = extract32(insn, 16, 5); unsigned rb = extract32(insn, 21, 5); TCGMemOp mop = MO_TEUL | MO_ALIGN_16; - TCGv_reg zero, addr, base, dest; + TCGv_reg zero, dest, ofs; + TCGv_tl addr; int modify, disp = 0, scale = 0; nullify_over(ctx); - /* ??? Share more code with do_load and do_load_{32,64}. */ - if (i) { modify = (m ? (au ? -1 : 1) : 0); disp = low_sextract(rx, 0, 5); @@ -2693,27 +2730,19 @@ static DisasJumpType trans_ldcw(DisasContext *ctx, uint32_t insn, } } if (modify) { - /* Base register modification. Make sure if RT == RB, we see - the result of the load. */ + /* Base register modification. Make sure if RT == RB, + we see the result of the load. */ dest = get_temp(ctx); } else { dest = dest_gpr(ctx, rt); } - addr = tcg_temp_new(); - base = load_gpr(ctx, rb); - if (rx) { - tcg_gen_shli_reg(addr, cpu_gr[rx], scale); - tcg_gen_add_reg(addr, addr, base); - } else { - tcg_gen_addi_reg(addr, base, disp); - } - + form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify, + ctx->mmu_idx == MMU_PHYS_IDX); zero = tcg_const_reg(0); - tcg_gen_atomic_xchg_reg(dest, (modify <= 0 ? addr : base), - zero, ctx->mmu_idx, mop); + tcg_gen_atomic_xchg_reg(dest, addr, zero, ctx->mmu_idx, mop); if (modify) { - save_gpr(ctx, rb, addr); + save_gpr(ctx, rb, ofs); } save_gpr(ctx, rt, dest); @@ -2726,20 +2755,17 @@ static DisasJumpType trans_stby(DisasContext *ctx, uint32_t insn, target_sreg disp = low_sextract(insn, 0, 5); unsigned m = extract32(insn, 5, 1); unsigned a = extract32(insn, 13, 1); + unsigned sp = extract32(insn, 14, 2); unsigned rt = extract32(insn, 16, 5); unsigned rb = extract32(insn, 21, 5); - TCGv_reg addr, val; + TCGv_reg ofs, val; + TCGv_tl addr; nullify_over(ctx); - addr = tcg_temp_new(); - if (m || disp == 0) { - tcg_gen_mov_reg(addr, load_gpr(ctx, rb)); - } else { - tcg_gen_addi_reg(addr, load_gpr(ctx, rb), disp); - } + form_gva(ctx, &addr, &ofs, rb, 0, 0, disp, sp, m, + ctx->mmu_idx == MMU_PHYS_IDX); val = load_gpr(ctx, rt); - if (a) { if (tb_cflags(ctx->base.tb) & CF_PARALLEL) { gen_helper_stby_e_parallel(cpu_env, addr, val); @@ -2755,11 +2781,9 @@ static DisasJumpType trans_stby(DisasContext *ctx, uint32_t insn, } if (m) { - tcg_gen_addi_reg(addr, addr, disp); - tcg_gen_andi_reg(addr, addr, ~3); - save_gpr(ctx, rb, addr); + tcg_gen_andi_reg(ofs, ofs, ~3); + save_gpr(ctx, rb, ofs); } - tcg_temp_free(addr); return nullify_end(ctx, DISAS_NEXT); } @@ -2824,15 +2848,18 @@ static DisasJumpType trans_load(DisasContext *ctx, uint32_t insn, { unsigned rb = extract32(insn, 21, 5); unsigned rt = extract32(insn, 16, 5); + unsigned sp = extract32(insn, 14, 2); target_sreg i = assemble_16(insn); - return do_load(ctx, rt, rb, 0, 0, i, is_mod ? (i < 0 ? -1 : 1) : 0, mop); + return do_load(ctx, rt, rb, 0, 0, i, sp, + is_mod ? (i < 0 ? -1 : 1) : 0, mop); } static DisasJumpType trans_load_w(DisasContext *ctx, uint32_t insn) { unsigned rb = extract32(insn, 21, 5); unsigned rt = extract32(insn, 16, 5); + unsigned sp = extract32(insn, 14, 2); target_sreg i = assemble_16a(insn); unsigned ext2 = extract32(insn, 1, 2); @@ -2840,11 +2867,11 @@ static DisasJumpType trans_load_w(DisasContext *ctx, uint32_t insn) case 0: case 1: /* FLDW without modification. */ - return do_floadw(ctx, ext2 * 32 + rt, rb, 0, 0, i, 0); + return do_floadw(ctx, ext2 * 32 + rt, rb, 0, 0, i, sp, 0); case 2: /* LDW with modification. Note that the sign of I selects post-dec vs pre-inc. */ - return do_load(ctx, rt, rb, 0, 0, i, (i < 0 ? 1 : -1), MO_TEUL); + return do_load(ctx, rt, rb, 0, 0, i, sp, (i < 0 ? 1 : -1), MO_TEUL); default: return gen_illegal(ctx); } @@ -2855,11 +2882,12 @@ static DisasJumpType trans_fload_mod(DisasContext *ctx, uint32_t insn) target_sreg i = assemble_16a(insn); unsigned t1 = extract32(insn, 1, 1); unsigned a = extract32(insn, 2, 1); + unsigned sp = extract32(insn, 14, 2); unsigned t0 = extract32(insn, 16, 5); unsigned rb = extract32(insn, 21, 5); /* FLDW with modification. */ - return do_floadw(ctx, t1 * 32 + t0, rb, 0, 0, i, (a ? -1 : 1)); + return do_floadw(ctx, t1 * 32 + t0, rb, 0, 0, i, sp, (a ? -1 : 1)); } static DisasJumpType trans_store(DisasContext *ctx, uint32_t insn, @@ -2867,15 +2895,17 @@ static DisasJumpType trans_store(DisasContext *ctx, uint32_t insn, { unsigned rb = extract32(insn, 21, 5); unsigned rt = extract32(insn, 16, 5); + unsigned sp = extract32(insn, 14, 2); target_sreg i = assemble_16(insn); - return do_store(ctx, rt, rb, i, is_mod ? (i < 0 ? -1 : 1) : 0, mop); + return do_store(ctx, rt, rb, i, sp, is_mod ? (i < 0 ? -1 : 1) : 0, mop); } static DisasJumpType trans_store_w(DisasContext *ctx, uint32_t insn) { unsigned rb = extract32(insn, 21, 5); unsigned rt = extract32(insn, 16, 5); + unsigned sp = extract32(insn, 14, 2); target_sreg i = assemble_16a(insn); unsigned ext2 = extract32(insn, 1, 2); @@ -2883,10 +2913,10 @@ static DisasJumpType trans_store_w(DisasContext *ctx, uint32_t insn) case 0: case 1: /* FSTW without modification. */ - return do_fstorew(ctx, ext2 * 32 + rt, rb, 0, 0, i, 0); + return do_fstorew(ctx, ext2 * 32 + rt, rb, 0, 0, i, sp, 0); case 2: /* LDW with modification. */ - return do_store(ctx, rt, rb, i, (i < 0 ? 1 : -1), MO_TEUL); + return do_store(ctx, rt, rb, i, sp, (i < 0 ? 1 : -1), MO_TEUL); default: return gen_illegal(ctx); } @@ -2897,11 +2927,12 @@ static DisasJumpType trans_fstore_mod(DisasContext *ctx, uint32_t insn) target_sreg i = assemble_16a(insn); unsigned t1 = extract32(insn, 1, 1); unsigned a = extract32(insn, 2, 1); + unsigned sp = extract32(insn, 14, 2); unsigned t0 = extract32(insn, 16, 5); unsigned rb = extract32(insn, 21, 5); /* FSTW with modification. */ - return do_fstorew(ctx, t1 * 32 + t0, rb, 0, 0, i, (a ? -1 : 1)); + return do_fstorew(ctx, t1 * 32 + t0, rb, 0, 0, i, sp, (a ? -1 : 1)); } static DisasJumpType trans_copr_w(DisasContext *ctx, uint32_t insn) @@ -2913,6 +2944,7 @@ static DisasJumpType trans_copr_w(DisasContext *ctx, uint32_t insn) /* unsigned cc = extract32(insn, 10, 2); */ unsigned i = extract32(insn, 12, 1); unsigned ua = extract32(insn, 13, 1); + unsigned sp = extract32(insn, 14, 2); unsigned rx = extract32(insn, 16, 5); unsigned rb = extract32(insn, 21, 5); unsigned rt = t1 * 32 + t0; @@ -2932,9 +2964,9 @@ static DisasJumpType trans_copr_w(DisasContext *ctx, uint32_t insn) switch (ext3) { case 0: /* FLDW */ - return do_floadw(ctx, rt, rb, rx, scale, disp, modify); + return do_floadw(ctx, rt, rb, rx, scale, disp, sp, modify); case 4: /* FSTW */ - return do_fstorew(ctx, rt, rb, rx, scale, disp, modify); + return do_fstorew(ctx, rt, rb, rx, scale, disp, sp, modify); } return gen_illegal(ctx); } @@ -2947,6 +2979,7 @@ static DisasJumpType trans_copr_dw(DisasContext *ctx, uint32_t insn) /* unsigned cc = extract32(insn, 10, 2); */ unsigned i = extract32(insn, 12, 1); unsigned ua = extract32(insn, 13, 1); + unsigned sp = extract32(insn, 14, 2); unsigned rx = extract32(insn, 16, 5); unsigned rb = extract32(insn, 21, 5); int modify = (m ? (ua ? -1 : 1) : 0); @@ -2965,9 +2998,9 @@ static DisasJumpType trans_copr_dw(DisasContext *ctx, uint32_t insn) switch (ext4) { case 0: /* FLDD */ - return do_floadd(ctx, rt, rb, rx, scale, disp, modify); + return do_floadd(ctx, rt, rb, rx, scale, disp, sp, modify); case 8: /* FSTD */ - return do_fstored(ctx, rt, rb, rx, scale, disp, modify); + return do_fstored(ctx, rt, rb, rx, scale, disp, sp, modify); default: return gen_illegal(ctx); } @@ -4208,8 +4241,10 @@ static int hppa_tr_init_disas_context(DisasContextBase *dcbase, bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4; bound = MIN(max_insns, bound); - ctx->ntemps = 0; - memset(ctx->temps, 0, sizeof(ctx->temps)); + ctx->ntempr = 0; + ctx->ntempl = 0; + memset(ctx->tempr, 0, sizeof(ctx->tempr)); + memset(ctx->templ, 0, sizeof(ctx->templ)); return bound; } @@ -4286,11 +4321,16 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) } /* Free any temporaries allocated. */ - for (i = 0, n = ctx->ntemps; i < n; ++i) { - tcg_temp_free(ctx->temps[i]); - ctx->temps[i] = NULL; + for (i = 0, n = ctx->ntempr; i < n; ++i) { + tcg_temp_free(ctx->tempr[i]); + ctx->tempr[i] = NULL; } - ctx->ntemps = 0; + for (i = 0, n = ctx->ntempl; i < n; ++i) { + tcg_temp_free_tl(ctx->templ[i]); + ctx->templ[i] = NULL; + } + ctx->ntempr = 0; + ctx->ntempl = 0; /* Advance the insn queue. Note that this check also detects a priority change within the instruction queue. */ @@ -4400,7 +4440,7 @@ void restore_state_to_opc(CPUHPPAState *env, TranslationBlock *tb, target_ulong *data) { env->iaoq_f = data[0]; - if (data[1] != -1) { + if (data[1] != (target_ureg)-1) { env->iaoq_b = data[1]; } /* Since we were executing the instruction at IAOQ_F, and took some From 660eefe1ca20ac118191bffcd23e721afec94142 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Oct 2017 11:25:12 -0700 Subject: [PATCH 15/43] target/hppa: Avoid privilege level decrease during branches These instructions force the destination privilege level of the branch destination to be no higher than current. Signed-off-by: Richard Henderson --- target/hppa/translate.c | 52 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 6be9e0c3ff..4a69f05a91 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -1862,6 +1862,40 @@ static DisasJumpType do_ibranch(DisasContext *ctx, TCGv_reg dest, return DISAS_NEXT; } +/* Implement + * if (IAOQ_Front{30..31} < GR[b]{30..31}) + * IAOQ_Next{30..31} ← GR[b]{30..31}; + * else + * IAOQ_Next{30..31} ← IAOQ_Front{30..31}; + * which keeps the privilege level from being increased. + */ +static TCGv_reg do_ibranch_priv(DisasContext *ctx, TCGv_reg offset) +{ +#ifdef CONFIG_USER_ONLY + return offset; +#else + TCGv_reg dest; + switch (ctx->privilege) { + case 0: + /* Privilege 0 is maximum and is allowed to decrease. */ + return offset; + case 3: + /* Privilege 3 is minimum and is never allowed increase. */ + dest = get_temp(ctx); + tcg_gen_ori_reg(dest, offset, 3); + break; + default: + dest = tcg_temp_new(); + tcg_gen_andi_reg(dest, offset, -4); + tcg_gen_ori_reg(dest, dest, ctx->privilege); + tcg_gen_movcond_reg(TCG_COND_GTU, dest, dest, offset, dest, offset); + tcg_temp_free(dest); + break; + } + return dest; +#endif +} + #ifdef CONFIG_USER_ONLY /* On Linux, page zero is normally marked execute only + gateway. Therefore normal read or write is supposed to fail, but specific @@ -3441,6 +3475,7 @@ static DisasJumpType trans_be(DisasContext *ctx, uint32_t insn, bool is_l) unsigned n = extract32(insn, 1, 1); unsigned b = extract32(insn, 21, 5); target_sreg disp = assemble_17(insn); + TCGv_reg tmp; /* unsigned s = low_uextract(insn, 13, 3); */ /* ??? It seems like there should be a good way of using @@ -3449,16 +3484,19 @@ static DisasJumpType trans_be(DisasContext *ctx, uint32_t insn, bool is_l) manage along side branch delay slots. Therefore we handle entry into the gateway page via absolute address. */ +#ifdef CONFIG_USER_ONLY /* Since we don't implement spaces, just branch. Do notice the special case of "be disp(*,r0)" using a direct branch to disp, so that we can goto_tb to the TB containing the syscall. */ if (b == 0) { return do_dbranch(ctx, disp, is_l ? 31 : 0, n); - } else { - TCGv_reg tmp = get_temp(ctx); - tcg_gen_addi_reg(tmp, load_gpr(ctx, b), disp); - return do_ibranch(ctx, tmp, is_l ? 31 : 0, n); } +#endif + + tmp = get_temp(ctx); + tcg_gen_addi_reg(tmp, load_gpr(ctx, b), disp); + tmp = do_ibranch_priv(ctx, tmp); + return do_ibranch(ctx, tmp, is_l ? 31 : 0, n); } static DisasJumpType trans_bl(DisasContext *ctx, uint32_t insn, @@ -3490,6 +3528,7 @@ static DisasJumpType trans_blr(DisasContext *ctx, uint32_t insn, tcg_gen_shli_reg(tmp, load_gpr(ctx, rx), 3); tcg_gen_addi_reg(tmp, tmp, ctx->iaoq_f + 8); + /* The computation here never changes privilege level. */ return do_ibranch(ctx, tmp, link, n); } @@ -3508,6 +3547,7 @@ static DisasJumpType trans_bv(DisasContext *ctx, uint32_t insn, tcg_gen_shli_reg(dest, load_gpr(ctx, rx), 3); tcg_gen_add_reg(dest, dest, load_gpr(ctx, rb)); } + dest = do_ibranch_priv(ctx, dest); return do_ibranch(ctx, dest, 0, n); } @@ -3517,8 +3557,10 @@ static DisasJumpType trans_bve(DisasContext *ctx, uint32_t insn, unsigned n = extract32(insn, 1, 1); unsigned rb = extract32(insn, 21, 5); unsigned link = extract32(insn, 13, 1) ? 2 : 0; + TCGv_reg dest; - return do_ibranch(ctx, load_gpr(ctx, rb), link, n); + dest = do_ibranch_priv(ctx, load_gpr(ctx, rb)); + return do_ibranch(ctx, dest, link, n); } static const DisasInsn table_branch[] = { From c301f34e798e2921cc4c4d1983512f1499e80996 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 21 Oct 2017 22:53:35 -0700 Subject: [PATCH 16/43] target/hppa: Implement IASQ Any one TB will have only one space value. If we change spaces, we change TBs. Thus BE and BEV must exit the TB immediately. Signed-off-by: Richard Henderson --- target/hppa/cpu.c | 15 +++++ target/hppa/cpu.h | 53 ++++++++++++++++- target/hppa/helper.c | 3 +- target/hppa/int_helper.c | 16 +++++- target/hppa/op_helper.c | 2 + target/hppa/translate.c | 119 +++++++++++++++++++++++++++++++-------- 6 files changed, 180 insertions(+), 28 deletions(-) diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index 4d0b760baa..2970afd58d 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -37,8 +37,23 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) { HPPACPU *cpu = HPPA_CPU(cs); +#ifdef CONFIG_USER_ONLY cpu->env.iaoq_f = tb->pc; cpu->env.iaoq_b = tb->cs_base; +#else + /* Recover the IAOQ values from the GVA + PRIV. */ + uint32_t priv = (tb->flags >> TB_FLAG_PRIV_SHIFT) & 3; + target_ulong cs_base = tb->cs_base; + target_ulong iasq_f = cs_base & ~0xffffffffull; + int32_t diff = cs_base; + + cpu->env.iasq_f = iasq_f; + cpu->env.iaoq_f = (tb->pc & ~iasq_f) + priv; + if (diff) { + cpu->env.iaoq_b = cpu->env.iaoq_f + diff; + } +#endif + cpu->env.psw_n = (tb->flags & PSW_N) != 0; } diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 49f95a0b77..27cd5f03d8 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -186,6 +186,8 @@ struct CPUHPPAState { target_ureg iaoq_f; /* front */ target_ureg iaoq_b; /* back, aka next instruction */ + uint64_t iasq_f; + uint64_t iasq_b; uint32_t fr0_shadow; /* flags, c, ca/cq, rm, d, enables */ float_status fp_status; @@ -240,15 +242,62 @@ void hppa_translate_init(void); void hppa_cpu_list(FILE *f, fprintf_function cpu_fprintf); +static inline target_ulong hppa_form_gva_psw(target_ureg psw, uint64_t spc, + target_ureg off) +{ +#ifdef CONFIG_USER_ONLY + return off; +#else + off &= (psw & PSW_W ? 0x3fffffffffffffffull : 0xffffffffull); + return spc | off; +#endif +} + +static inline target_ulong hppa_form_gva(CPUHPPAState *env, uint64_t spc, + target_ureg off) +{ + return hppa_form_gva_psw(env->psw, spc, off); +} + +/* Since PSW_CB will never need to be in tb->flags, reuse them. */ +#define TB_FLAG_PRIV_SHIFT 8 + static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags) { + uint32_t flags = env->psw_n * PSW_N; + + /* TB lookup assumes that PC contains the complete virtual address. + If we leave space+offset separate, we'll get ITLB misses to an + incomplete virtual address. This also means that we must separate + out current cpu priviledge from the low bits of IAOQ_F. */ +#ifdef CONFIG_USER_ONLY *pc = env->iaoq_f; *cs_base = env->iaoq_b; +#else /* ??? E, T, H, L, B, P bits need to be here, when implemented. */ - *pflags = (env->psw & (PSW_W | PSW_C | PSW_D)) - | env->psw_n * PSW_N; + flags |= env->psw & (PSW_W | PSW_C | PSW_D); + flags |= (env->iaoq_f & 3) << TB_FLAG_PRIV_SHIFT; + + *pc = (env->psw & PSW_C + ? hppa_form_gva_psw(env->psw, env->iasq_f, env->iaoq_f & -4) + : env->iaoq_f & -4); + *cs_base = env->iasq_f; + + /* Insert a difference between IAOQ_B and IAOQ_F within the otherwise zero + low 32-bits of CS_BASE. This will succeed for all direct branches, + which is the primary case we care about -- using goto_tb within a page. + Failure is indicated by a zero difference. */ + if (env->iasq_f == env->iasq_b) { + target_sreg diff = env->iaoq_b - env->iaoq_f; + if (TARGET_REGISTER_BITS == 32 || diff == (int32_t)diff) { + *cs_base |= (uint32_t)diff; + } + } +#endif + + *pflags = flags; } target_ureg cpu_hppa_get_psw(CPUHPPAState *env); diff --git a/target/hppa/helper.c b/target/hppa/helper.c index 6e8758f82c..858ec205b6 100644 --- a/target/hppa/helper.c +++ b/target/hppa/helper.c @@ -78,7 +78,8 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, int i; cpu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx "\n", - (target_ulong)env->iaoq_f, (target_ulong)env->iaoq_b); + hppa_form_gva_psw(psw, env->iasq_f, env->iaoq_f), + hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b)); psw_c[0] = (psw & PSW_W ? 'W' : '-'); psw_c[1] = (psw & PSW_E ? 'E' : '-'); diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c index a59aae1189..02963b80c6 100644 --- a/target/hppa/int_helper.c +++ b/target/hppa/int_helper.c @@ -32,6 +32,8 @@ void hppa_cpu_do_interrupt(CPUState *cs) int i = cs->exception_index; target_ureg iaoq_f = env->iaoq_f; target_ureg iaoq_b = env->iaoq_b; + uint64_t iasq_f = env->iasq_f; + uint64_t iasq_b = env->iasq_b; #ifndef CONFIG_USER_ONLY target_ureg old_psw; @@ -44,6 +46,8 @@ void hppa_cpu_do_interrupt(CPUState *cs) cpu_hppa_put_psw(env, PSW_W | (i == EXCP_HPMC ? PSW_M : 0)); /* step 3 */ + env->cr[CR_IIASQ] = iasq_f >> 32; + env->cr_back[0] = iasq_b >> 32; env->cr[CR_IIAOQ] = iaoq_f; env->cr_back[1] = iaoq_b; @@ -79,6 +83,9 @@ void hppa_cpu_do_interrupt(CPUState *cs) hwaddr paddr; paddr = vaddr = iaoq_f & -4; + if (old_psw & PSW_C) { + vaddr = hppa_form_gva_psw(old_psw, iasq_f, iaoq_f & -4); + } env->cr[CR_IIR] = ldl_phys(cs->as, paddr); } break; @@ -101,6 +108,8 @@ void hppa_cpu_do_interrupt(CPUState *cs) /* step 7 */ env->iaoq_f = env->cr[CR_IVA] + 32 * i; env->iaoq_b = env->iaoq_f + 4; + env->iasq_f = 0; + env->iasq_b = 0; #endif if (qemu_loglevel_mask(CPU_LOG_INT)) { @@ -151,10 +160,11 @@ void hppa_cpu_do_interrupt(CPUState *cs) qemu_log("INT %6d: %s @ " TARGET_FMT_lx "," TARGET_FMT_lx " -> " TREG_FMT_lx " " TARGET_FMT_lx "\n", ++count, name, - (target_ulong)iaoq_f, - (target_ulong)iaoq_b, + hppa_form_gva(env, iasq_f, iaoq_f), + hppa_form_gva(env, iasq_b, iaoq_b), env->iaoq_f, - (target_ulong)env->cr[CR_IOR]); + hppa_form_gva(env, (uint64_t)env->cr[CR_ISR] << 32, + env->cr[CR_IOR])); } cs->exception_index = -1; } diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index cf9fe46942..917d8de540 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -622,6 +622,8 @@ void HELPER(rfi)(CPUHPPAState *env) if (env->psw & (PSW_I | PSW_R | PSW_Q)) { helper_excp(env, EXCP_ILL); } + env->iasq_f = (uint64_t)env->cr[CR_IIASQ] << 32; + env->iasq_b = (uint64_t)env->cr_back[0] << 32; env->iaoq_f = env->cr[CR_IIAOQ]; env->iaoq_b = env->cr_back[1]; cpu_hppa_put_psw(env, env->cr[CR_IPSW]); diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 4a69f05a91..44abc9006b 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -325,6 +325,8 @@ static TCGv_reg cpu_gr[32]; static TCGv_i64 cpu_sr[4]; static TCGv_reg cpu_iaoq_f; static TCGv_reg cpu_iaoq_b; +static TCGv_i64 cpu_iasq_f; +static TCGv_i64 cpu_iasq_b; static TCGv_reg cpu_sar; static TCGv_reg cpu_psw_n; static TCGv_reg cpu_psw_v; @@ -380,6 +382,13 @@ void hppa_translate_init(void) const GlobalVar *v = &vars[i]; *v->var = tcg_global_mem_new(cpu_env, v->ofs, v->name); } + + cpu_iasq_f = tcg_global_mem_new_i64(cpu_env, + offsetof(CPUHPPAState, iasq_f), + "iasq_f"); + cpu_iasq_b = tcg_global_mem_new_i64(cpu_env, + offsetof(CPUHPPAState, iasq_b), + "iasq_b"); } static DisasCond cond_make_f(void) @@ -1760,6 +1769,11 @@ static DisasJumpType do_cbranch(DisasContext *ctx, target_sreg disp, bool is_n, ctx->null_lab = NULL; } nullify_set(ctx, n); + if (ctx->iaoq_n == -1) { + /* The temporary iaoq_n_var died at the branch above. + Regenerate it here instead of saving it. */ + tcg_gen_addi_reg(ctx->iaoq_n_var, cpu_iaoq_b, 4); + } gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n); } @@ -1801,11 +1815,17 @@ static DisasJumpType do_ibranch(DisasContext *ctx, TCGv_reg dest, } next = get_temp(ctx); tcg_gen_mov_reg(next, dest); - ctx->iaoq_n = -1; - ctx->iaoq_n_var = next; if (is_n) { + if (use_nullify_skip(ctx)) { + tcg_gen_mov_reg(cpu_iaoq_f, next); + tcg_gen_addi_reg(cpu_iaoq_b, next, 4); + nullify_set(ctx, 0); + return DISAS_IAQ_N_UPDATED; + } ctx->null_cond.c = TCG_COND_ALWAYS; } + ctx->iaoq_n = -1; + ctx->iaoq_n_var = next; } else if (is_n && use_nullify_skip(ctx)) { /* The (conditional) branch, B, nullifies the next insn, N, and we're allowed to skip execution N (no single-step or @@ -3477,26 +3497,55 @@ static DisasJumpType trans_be(DisasContext *ctx, uint32_t insn, bool is_l) target_sreg disp = assemble_17(insn); TCGv_reg tmp; - /* unsigned s = low_uextract(insn, 13, 3); */ +#ifdef CONFIG_USER_ONLY /* ??? It seems like there should be a good way of using "be disp(sr2, r0)", the canonical gateway entry mechanism to our advantage. But that appears to be inconvenient to manage along side branch delay slots. Therefore we handle entry into the gateway page via absolute address. */ - -#ifdef CONFIG_USER_ONLY /* Since we don't implement spaces, just branch. Do notice the special case of "be disp(*,r0)" using a direct branch to disp, so that we can goto_tb to the TB containing the syscall. */ if (b == 0) { return do_dbranch(ctx, disp, is_l ? 31 : 0, n); } +#else + int sp = assemble_sr3(insn); + nullify_over(ctx); #endif tmp = get_temp(ctx); tcg_gen_addi_reg(tmp, load_gpr(ctx, b), disp); tmp = do_ibranch_priv(ctx, tmp); + +#ifdef CONFIG_USER_ONLY return do_ibranch(ctx, tmp, is_l ? 31 : 0, n); +#else + TCGv_i64 new_spc = tcg_temp_new_i64(); + + load_spr(ctx, new_spc, sp); + if (is_l) { + copy_iaoq_entry(cpu_gr[31], ctx->iaoq_n, ctx->iaoq_n_var); + tcg_gen_mov_i64(cpu_sr[0], cpu_iasq_f); + } + if (n && use_nullify_skip(ctx)) { + tcg_gen_mov_reg(cpu_iaoq_f, tmp); + tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4); + tcg_gen_mov_i64(cpu_iasq_f, new_spc); + tcg_gen_mov_i64(cpu_iasq_b, cpu_iasq_f); + } else { + copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b); + if (ctx->iaoq_b == -1) { + tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b); + } + tcg_gen_mov_reg(cpu_iaoq_b, tmp); + tcg_gen_mov_i64(cpu_iasq_b, new_spc); + nullify_set(ctx, n); + } + tcg_temp_free_i64(new_spc); + tcg_gen_lookup_and_goto_ptr(); + return nullify_end(ctx, DISAS_NORETURN); +#endif } static DisasJumpType trans_bl(DisasContext *ctx, uint32_t insn, @@ -3559,8 +3608,26 @@ static DisasJumpType trans_bve(DisasContext *ctx, uint32_t insn, unsigned link = extract32(insn, 13, 1) ? 2 : 0; TCGv_reg dest; +#ifdef CONFIG_USER_ONLY dest = do_ibranch_priv(ctx, load_gpr(ctx, rb)); return do_ibranch(ctx, dest, link, n); +#else + nullify_over(ctx); + dest = do_ibranch_priv(ctx, load_gpr(ctx, rb)); + + copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b); + if (ctx->iaoq_b == -1) { + tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b); + } + copy_iaoq_entry(cpu_iaoq_b, -1, dest); + tcg_gen_mov_i64(cpu_iasq_b, space_select(ctx, 0, dest)); + if (link) { + copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var); + } + nullify_set(ctx, n); + tcg_gen_lookup_and_goto_ptr(); + return nullify_end(ctx, DISAS_NORETURN); +#endif } static const DisasInsn table_branch[] = { @@ -4267,15 +4334,21 @@ static int hppa_tr_init_disas_context(DisasContextBase *dcbase, #ifdef CONFIG_USER_ONLY ctx->privilege = MMU_USER_IDX; ctx->mmu_idx = MMU_USER_IDX; -#else - ctx->privilege = ctx->base.pc_first & 3; - ctx->mmu_idx = (ctx->base.tb->flags & PSW_D - ? ctx->privilege : MMU_PHYS_IDX); -#endif ctx->iaoq_f = ctx->base.pc_first; ctx->iaoq_b = ctx->base.tb->cs_base; - ctx->base.pc_first &= -4; +#else + ctx->privilege = (ctx->base.tb->flags >> TB_FLAG_PRIV_SHIFT) & 3; + ctx->mmu_idx = (ctx->base.tb->flags & PSW_D + ? ctx->privilege : MMU_PHYS_IDX); + /* Recover the IAOQ values from the GVA + PRIV. */ + uint64_t cs_base = ctx->base.tb->cs_base; + uint64_t iasq_f = cs_base & ~0xffffffffull; + int32_t diff = cs_base; + + ctx->iaoq_f = (ctx->base.pc_first & ~iasq_f) + ctx->privilege; + ctx->iaoq_b = (diff ? ctx->iaoq_f + diff : -1); +#endif ctx->iaoq_n = -1; ctx->iaoq_n_var = NULL; @@ -4318,7 +4391,7 @@ static bool hppa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, DisasContext *ctx = container_of(dcbase, DisasContext, base); ctx->base.is_jmp = gen_excp(ctx, EXCP_DEBUG); - ctx->base.pc_next = (ctx->iaoq_f & -4) + 4; + ctx->base.pc_next += 4; return true; } @@ -4331,7 +4404,7 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) /* Execute one insn. */ #ifdef CONFIG_USER_ONLY - if (ctx->iaoq_f < TARGET_PAGE_SIZE) { + if (ctx->base.pc_next < TARGET_PAGE_SIZE) { ret = do_page_zero(ctx); assert(ret != DISAS_NEXT); } else @@ -4339,7 +4412,7 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { /* Always fetch the insn, even if nullified, so that we check the page permissions for execute. */ - uint32_t insn = cpu_ldl_code(env, ctx->iaoq_f & -4); + uint32_t insn = cpu_ldl_code(env, ctx->base.pc_next); /* Set up the IA queue for the next insn. This will be overwritten by a branch. */ @@ -4377,18 +4450,21 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) /* Advance the insn queue. Note that this check also detects a priority change within the instruction queue. */ if (ret == DISAS_NEXT && ctx->iaoq_b != ctx->iaoq_f + 4) { - if (ctx->null_cond.c == TCG_COND_NEVER - || ctx->null_cond.c == TCG_COND_ALWAYS) { + if (ctx->iaoq_b != -1 && ctx->iaoq_n != -1 + && use_goto_tb(ctx, ctx->iaoq_b) + && (ctx->null_cond.c == TCG_COND_NEVER + || ctx->null_cond.c == TCG_COND_ALWAYS)) { nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS); gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n); ret = DISAS_NORETURN; } else { ret = DISAS_IAQ_N_STALE; - } + } } ctx->iaoq_f = ctx->iaoq_b; ctx->iaoq_b = ctx->iaoq_n; ctx->base.is_jmp = ret; + ctx->base.pc_next += 4; if (ret == DISAS_NORETURN || ret == DISAS_IAQ_N_UPDATED) { return; @@ -4396,6 +4472,9 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) if (ctx->iaoq_f == -1) { tcg_gen_mov_reg(cpu_iaoq_f, cpu_iaoq_b); copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var); +#ifndef CONFIG_USER_ONLY + tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b); +#endif nullify_save(ctx); ctx->base.is_jmp = DISAS_IAQ_N_UPDATED; } else if (ctx->iaoq_b == -1) { @@ -4430,15 +4509,11 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) default: g_assert_not_reached(); } - - /* We don't actually use this during normal translation, - but we should interact with the generic main loop. */ - ctx->base.pc_next = ctx->base.pc_first + 4 * ctx->base.num_insns; } static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) { - target_ureg pc = dcbase->pc_first; + target_ulong pc = dcbase->pc_first; #ifdef CONFIG_USER_ONLY switch (pc) { From 650cdb2a2e4936fb66c13793278f4bacf0e5a6f7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 27 Oct 2017 10:17:12 +0200 Subject: [PATCH 17/43] target/hppa: Implement tlb_fill However since HPPA has a software-managed TLB, and the relevant TLB manipulation instructions are not implemented, this does not actually do anything. Signed-off-by: Richard Henderson --- target/hppa/cpu.h | 31 +++++++- target/hppa/int_helper.c | 14 +++- target/hppa/mem_helper.c | 164 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 198 insertions(+), 11 deletions(-) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 27cd5f03d8..bd8fe6af78 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -165,6 +165,22 @@ typedef int64_t target_sreg; #define TREG_FMT_ld "%"PRId64 #endif +typedef struct { + uint64_t va_b; + uint64_t va_e; + target_ureg pa; + unsigned u : 1; + unsigned t : 1; + unsigned d : 1; + unsigned b : 1; + unsigned page_size : 4; + unsigned ar_type : 3; + unsigned ar_pl1 : 2; + unsigned ar_pl2 : 2; + unsigned entry_valid : 1; + unsigned access_id : 16; +} hppa_tlb_entry; + struct CPUHPPAState { target_ureg gr[32]; uint64_t fr[32]; @@ -198,6 +214,12 @@ struct CPUHPPAState { /* Those resources are used only in QEMU core */ CPU_COMMON + + /* ??? The number of entries isn't specified by the architecture. */ + /* ??? Implement a unified itlb/dtlb for the moment. */ + /* ??? We should use a more intelligent data structure. */ + hppa_tlb_entry tlb[256]; + uint32_t tlb_last; }; /** @@ -307,13 +329,18 @@ void cpu_hppa_loaded_fr0(CPUHPPAState *env); #define cpu_signal_handler cpu_hppa_signal_handler int cpu_hppa_signal_handler(int host_signum, void *pinfo, void *puc); -int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, - int rw, int midx); hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr); int hppa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); int hppa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); void hppa_cpu_do_interrupt(CPUState *cpu); bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req); void hppa_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function, int); +#ifdef CONFIG_USER_ONLY +int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, + int rw, int midx); +#else +int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, + int type, hwaddr *pphys, int *pprot); +#endif #endif /* HPPA_CPU_H */ diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c index 02963b80c6..3d668a3a4f 100644 --- a/target/hppa/int_helper.c +++ b/target/hppa/int_helper.c @@ -79,12 +79,24 @@ void hppa_cpu_do_interrupt(CPUState *cs) { /* Avoid reading directly from the virtual address, lest we raise another exception from some sort of TLB issue. */ + /* ??? An alternate fool-proof method would be to store the + instruction data into the unwind info. That's probably + a bit too much in the way of extra storage required. */ vaddr vaddr; hwaddr paddr; paddr = vaddr = iaoq_f & -4; if (old_psw & PSW_C) { - vaddr = hppa_form_gva_psw(old_psw, iasq_f, iaoq_f & -4); + int prot, t; + + vaddr = hppa_form_gva_psw(old_psw, iasq_f, vaddr); + t = hppa_get_physical_address(env, vaddr, MMU_KERNEL_IDX, + 0, &paddr, &prot); + if (t >= 0) { + /* We can't re-load the instruction. */ + env->cr[CR_IIR] = 0; + break; + } } env->cr[CR_IIR] = ldl_phys(cs->as, paddr); } diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index 65e2c95b78..334ef98a32 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -36,18 +36,166 @@ int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, return 1; } #else -hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) +static hppa_tlb_entry *hppa_find_tlb(CPUHPPAState *env, vaddr addr) { - /* Stub */ - return addr; + int i; + + for (i = 0; i < ARRAY_SIZE(env->tlb); ++i) { + hppa_tlb_entry *ent = &env->tlb[i]; + if (ent->va_b <= addr && addr <= ent->va_e && ent->entry_valid) { + return ent; + } + } + return NULL; } -void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType type, - int mmu_idx, uintptr_t retaddr) +int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, + int type, hwaddr *pphys, int *pprot) { - /* Stub */ - int prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; - hwaddr phys = addr; + hwaddr phys; + int prot, r_prot, w_prot, x_prot; + hppa_tlb_entry *ent; + int ret = -1; + + /* Virtual translation disabled. Direct map virtual to physical. */ + if (mmu_idx == MMU_PHYS_IDX) { + phys = addr; + prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + goto egress; + } + + /* Find a valid tlb entry that matches the virtual address. */ + ent = hppa_find_tlb(env, addr); + if (ent == NULL) { + phys = 0; + prot = 0; + ret = (type & PAGE_EXEC ? EXCP_ITLB_MISS : EXCP_DTLB_MISS); + goto egress; + } + + /* We now know the physical address. */ + phys = ent->pa + (addr & ~TARGET_PAGE_MASK); + + /* Map TLB access_rights field to QEMU protection. */ + r_prot = (mmu_idx <= ent->ar_pl1) * PAGE_READ; + w_prot = (mmu_idx <= ent->ar_pl2) * PAGE_WRITE; + x_prot = (ent->ar_pl2 <= mmu_idx && mmu_idx <= ent->ar_pl1) * PAGE_EXEC; + switch (ent->ar_type) { + case 0: /* read-only: data page */ + prot = r_prot; + break; + case 1: /* read/write: dynamic data page */ + prot = r_prot | w_prot; + break; + case 2: /* read/execute: normal code page */ + prot = r_prot | x_prot; + break; + case 3: /* read/write/execute: dynamic code page */ + prot = r_prot | w_prot | x_prot; + break; + default: /* execute: promote to privilege level type & 3 */ + prot = x_prot; + } + + /* ??? Check PSW_P and ent->access_prot. This can remove PAGE_WRITE. */ + + /* No guest access type indicates a non-architectural access from + within QEMU. Bypass checks for access, D, B and T bits. */ + if (type == 0) { + goto egress; + } + + if (unlikely(!(prot & type))) { + /* The access isn't allowed -- Inst/Data Memory Protection Fault. */ + ret = (type & PAGE_EXEC ? EXCP_IMP : EXCP_DMP); + goto egress; + } + + /* In reverse priority order, check for conditions which raise faults. + As we go, remove PROT bits that cover the condition we want to check. + In this way, the resulting PROT will force a re-check of the + architectural TLB entry for the next access. */ + if (unlikely(!ent->d)) { + if (type & PAGE_WRITE) { + /* The D bit is not set -- TLB Dirty Bit Fault. */ + ret = EXCP_TLB_DIRTY; + } + prot &= PAGE_READ | PAGE_EXEC; + } + if (unlikely(ent->b)) { + if (type & PAGE_WRITE) { + /* The B bit is set -- Data Memory Break Fault. */ + ret = EXCP_DMB; + } + prot &= PAGE_READ | PAGE_EXEC; + } + if (unlikely(ent->t)) { + if (!(type & PAGE_EXEC)) { + /* The T bit is set -- Page Reference Fault. */ + ret = EXCP_PAGE_REF; + } + prot &= PAGE_EXEC; + } + + egress: + *pphys = phys; + *pprot = prot; + return ret; +} + +hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) +{ + HPPACPU *cpu = HPPA_CPU(cs); + hwaddr phys; + int prot, excp; + + /* If the (data) mmu is disabled, bypass translation. */ + /* ??? We really ought to know if the code mmu is disabled too, + in order to get the correct debugging dumps. */ + if (!(cpu->env.psw & PSW_D)) { + return addr; + } + + excp = hppa_get_physical_address(&cpu->env, addr, MMU_KERNEL_IDX, 0, + &phys, &prot); + + /* Since we're translating for debugging, the only error that is a + hard error is no translation at all. Otherwise, while a real cpu + access might not have permission, the debugger does. */ + return excp == EXCP_DTLB_MISS ? -1 : phys; +} + +void tlb_fill(CPUState *cs, target_ulong addr, int size, + MMUAccessType type, int mmu_idx, uintptr_t retaddr) +{ + HPPACPU *cpu = HPPA_CPU(cs); + int prot, excp, a_prot; + hwaddr phys; + + switch (type) { + case MMU_INST_FETCH: + a_prot = PAGE_EXEC; + break; + case MMU_DATA_STORE: + a_prot = PAGE_WRITE; + break; + default: + a_prot = PAGE_READ; + break; + } + + excp = hppa_get_physical_address(&cpu->env, addr, mmu_idx, + a_prot, &phys, &prot); + if (unlikely(excp >= 0)) { + /* Failure. Raise the indicated exception. */ + cs->exception_index = excp; + if (cpu->env.psw & PSW_Q) { + /* ??? Needs tweaking for hppa64. */ + cpu->env.cr[CR_IOR] = addr; + cpu->env.cr[CR_ISR] = addr >> 32; + } + cpu_loop_exit_restore(cs, retaddr); + } /* Success! Store the translation into the QEMU TLB. */ tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, From 4f5f254808e1e317b407275724df7794a270c5c1 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 28 Dec 2017 17:36:45 -0800 Subject: [PATCH 18/43] target/hppa: Implement external interrupts Signed-off-by: Richard Henderson --- target/hppa/cpu.c | 6 ++++ target/hppa/cpu.h | 1 + target/hppa/helper.h | 2 ++ target/hppa/int_helper.c | 59 ++++++++++++++++++++++++++++++++++++++++ target/hppa/translate.c | 16 ++++++++++- 5 files changed, 83 insertions(+), 1 deletion(-) diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index 2970afd58d..888a48f16d 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -57,6 +57,11 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) cpu->env.psw_n = (tb->flags & PSW_N) != 0; } +static bool hppa_cpu_has_work(CPUState *cs) +{ + return cs->interrupt_request & CPU_INTERRUPT_HARD; +} + static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info) { info->mach = bfd_mach_hppa20; @@ -159,6 +164,7 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data) dc->realize = hppa_cpu_realizefn; cc->class_by_name = hppa_cpu_class_by_name; + cc->has_work = hppa_cpu_has_work; cc->do_interrupt = hppa_cpu_do_interrupt; cc->cpu_exec_interrupt = hppa_cpu_exec_interrupt; cc->dump_state = hppa_cpu_dump_state; diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index bd8fe6af78..586ea1e555 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -341,6 +341,7 @@ int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, #else int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, int type, hwaddr *pphys, int *pprot); +extern const MemoryRegionOps hppa_io_eir_ops; #endif #endif /* HPPA_CPU_H */ diff --git a/target/hppa/helper.h b/target/hppa/helper.h index 79d22ae486..535f086ab4 100644 --- a/target/hppa/helper.h +++ b/target/hppa/helper.h @@ -80,5 +80,7 @@ DEF_HELPER_FLAGS_4(fmpynfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) #ifndef CONFIG_USER_ONLY DEF_HELPER_1(rfi, void, env) DEF_HELPER_1(rfi_r, void, env) +DEF_HELPER_FLAGS_2(write_eirr, TCG_CALL_NO_RWG, void, env, tr) +DEF_HELPER_FLAGS_2(write_eiem, TCG_CALL_NO_RWG, void, env, tr) DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr) #endif diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c index 3d668a3a4f..c468b12e73 100644 --- a/target/hppa/int_helper.c +++ b/target/hppa/int_helper.c @@ -24,6 +24,65 @@ #include "exec/helper-proto.h" #include "qom/cpu.h" +#ifndef CONFIG_USER_ONLY +static void eval_interrupt(HPPACPU *cpu) +{ + CPUState *cs = CPU(cpu); + if (cpu->env.cr[CR_EIRR] & cpu->env.cr[CR_EIEM]) { + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + } else { + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + } +} + +/* Each CPU has a word mapped into the GSC bus. Anything on the GSC bus + * can write to this word to raise an external interrupt on the target CPU. + * This includes the system controler (DINO) for regular devices, or + * another CPU for SMP interprocessor interrupts. + */ +static uint64_t io_eir_read(void *opaque, hwaddr addr, unsigned size) +{ + HPPACPU *cpu = opaque; + + /* ??? What does a read of this register over the GSC bus do? */ + return cpu->env.cr[CR_EIRR]; +} + +static void io_eir_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ + HPPACPU *cpu = opaque; + int le_bit = ~data & (TARGET_REGISTER_BITS - 1); + + cpu->env.cr[CR_EIRR] |= (target_ureg)1 << le_bit; + eval_interrupt(cpu); +} + +const MemoryRegionOps hppa_io_eir_ops = { + .read = io_eir_read, + .write = io_eir_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .impl.min_access_size = 4, + .impl.max_access_size = 4, +}; + +void HELPER(write_eirr)(CPUHPPAState *env, target_ureg val) +{ + env->cr[CR_EIRR] &= ~val; + qemu_mutex_lock_iothread(); + eval_interrupt(hppa_env_get_cpu(env)); + qemu_mutex_unlock_iothread(); +} + +void HELPER(write_eiem)(CPUHPPAState *env, target_ureg val) +{ + env->cr[CR_EIEM] = val; + qemu_mutex_lock_iothread(); + eval_interrupt(hppa_env_get_cpu(env)); + qemu_mutex_unlock_iothread(); +} +#endif /* !CONFIG_USER_ONLY */ void hppa_cpu_do_interrupt(CPUState *cs) { diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 44abc9006b..d6c65f314b 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2124,12 +2124,25 @@ static DisasJumpType trans_mtctl(DisasContext *ctx, uint32_t insn, /* All other control registers are privileged or read-only. */ CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG); +#ifdef CONFIG_USER_ONLY + g_assert_not_reached(); +#else + DisasJumpType ret = DISAS_NEXT; + nullify_over(ctx); switch (ctl) { case CR_IT: /* ??? modify interval timer offset */ break; + case CR_EIRR: + gen_helper_write_eirr(cpu_env, reg); + break; + case CR_EIEM: + gen_helper_write_eiem(cpu_env, reg); + ret = DISAS_IAQ_N_STALE_EXIT; + break; + case CR_IIASQ: case CR_IIAOQ: /* FIXME: Respect PSW_Q bit */ @@ -2146,7 +2159,8 @@ static DisasJumpType trans_mtctl(DisasContext *ctx, uint32_t insn, tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl])); break; } - return nullify_end(ctx, DISAS_NEXT); + return nullify_end(ctx, ret); +#endif } static DisasJumpType trans_mtsarcm(DisasContext *ctx, uint32_t insn, From 49c29d6c2e8ce2d3cddf9a92452d1ccb78051517 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 28 Dec 2017 17:50:14 -0800 Subject: [PATCH 19/43] target/hppa: Implement the interval timer Signed-off-by: Richard Henderson --- target/hppa/cpu.c | 8 ++++++++ target/hppa/cpu.h | 2 ++ target/hppa/helper.h | 3 +++ target/hppa/int_helper.c | 6 ++++++ target/hppa/op_helper.c | 36 ++++++++++++++++++++++++++++++++++++ target/hppa/translate.c | 16 ++++++++++++---- 6 files changed, 67 insertions(+), 4 deletions(-) diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index 888a48f16d..6be6eb0a7b 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -99,6 +99,14 @@ static void hppa_cpu_realizefn(DeviceState *dev, Error **errp) qemu_init_vcpu(cs); acc->parent_realize(dev, errp); + +#ifndef CONFIG_USER_ONLY + { + HPPACPU *cpu = HPPA_CPU(cs); + cpu->alarm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + hppa_cpu_alarm_timer, cpu); + } +#endif } /* Sort hppabetically by type name. */ diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 586ea1e555..3782e1d834 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -234,6 +234,7 @@ struct HPPACPU { /*< public >*/ CPUHPPAState env; + QEMUTimer *alarm_timer; }; static inline HPPACPU *hppa_env_get_cpu(CPUHPPAState *env) @@ -342,6 +343,7 @@ int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, int type, hwaddr *pphys, int *pprot); extern const MemoryRegionOps hppa_io_eir_ops; +void hppa_cpu_alarm_timer(void *); #endif #endif /* HPPA_CPU_H */ diff --git a/target/hppa/helper.h b/target/hppa/helper.h index 535f086ab4..744b11cb66 100644 --- a/target/hppa/helper.h +++ b/target/hppa/helper.h @@ -77,9 +77,12 @@ DEF_HELPER_FLAGS_4(fmpynfadd_s, TCG_CALL_NO_RWG, i32, env, i32, i32, i32) DEF_HELPER_FLAGS_4(fmpyfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_4(fmpynfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) +DEF_HELPER_FLAGS_0(read_interval_timer, TCG_CALL_NO_RWG, tr) + #ifndef CONFIG_USER_ONLY DEF_HELPER_1(rfi, void, env) DEF_HELPER_1(rfi_r, void, env) +DEF_HELPER_FLAGS_2(write_interval_timer, TCG_CALL_NO_RWG, void, env, tr) DEF_HELPER_FLAGS_2(write_eirr, TCG_CALL_NO_RWG, void, env, tr) DEF_HELPER_FLAGS_2(write_eiem, TCG_CALL_NO_RWG, void, env, tr) DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr) diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c index c468b12e73..787f3d6357 100644 --- a/target/hppa/int_helper.c +++ b/target/hppa/int_helper.c @@ -67,6 +67,12 @@ const MemoryRegionOps hppa_io_eir_ops = { .impl.max_access_size = 4, }; +void hppa_cpu_alarm_timer(void *opaque) +{ + /* Raise interrupt 0. */ + io_eir_write(opaque, 0, 0, 4); +} + void HELPER(write_eirr)(CPUHPPAState *env, target_ureg val) { env->cr[CR_EIRR] &= ~val; diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 917d8de540..8c546f4882 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -22,6 +22,8 @@ #include "exec/exec-all.h" #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" +#include "qemu/timer.h" + void QEMU_NORETURN HELPER(excp)(CPUHPPAState *env, int excp) { @@ -602,7 +604,41 @@ float64 HELPER(fmpynfadd_d)(CPUHPPAState *env, float64 a, float64 b, float64 c) return ret; } +target_ureg HELPER(read_interval_timer)(void) +{ +#ifdef CONFIG_USER_ONLY + /* In user-mode, QEMU_CLOCK_VIRTUAL doesn't exist. + Just pass through the host cpu clock ticks. */ + return cpu_get_host_ticks(); +#else + /* In system mode we have access to a decent high-resolution clock. + In order to make OS-level time accounting work with the cr16, + present it with a well-timed clock fixed at 250MHz. */ + return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >> 2; +#endif +} + #ifndef CONFIG_USER_ONLY +void HELPER(write_interval_timer)(CPUHPPAState *env, target_ureg val) +{ + HPPACPU *cpu = hppa_env_get_cpu(env); + uint64_t current = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t timeout; + + /* Even in 64-bit mode, the comparator is always 32-bit. But the + value we expose to the guest is 1/4 of the speed of the clock, + so moosh in 34 bits. */ + timeout = deposit64(current, 0, 34, (uint64_t)val << 2); + + /* If the mooshing puts the clock in the past, advance to next round. */ + if (timeout < current + 1000) { + timeout += 1ULL << 34; + } + + cpu->env.cr[CR_IT] = timeout; + timer_mod(cpu->alarm_timer, timeout); +} + target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm) { target_ulong psw = env->psw; diff --git a/target/hppa/translate.c b/target/hppa/translate.c index d6c65f314b..1cd57f5a90 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2038,6 +2038,7 @@ static DisasJumpType trans_mfctl(DisasContext *ctx, uint32_t insn, unsigned rt = extract32(insn, 0, 5); unsigned ctl = extract32(insn, 21, 5); TCGv_reg tmp; + DisasJumpType ret; switch (ctl) { case CR_SAR: @@ -2056,9 +2057,17 @@ static DisasJumpType trans_mfctl(DisasContext *ctx, uint32_t insn, /* FIXME: Respect PSW_S bit. */ nullify_over(ctx); tmp = dest_gpr(ctx, rt); - tcg_gen_movi_reg(tmp, 0); /* FIXME */ + if (ctx->base.tb->cflags & CF_USE_ICOUNT) { + gen_io_start(); + gen_helper_read_interval_timer(tmp); + gen_io_end(); + ret = DISAS_IAQ_N_STALE; + } else { + gen_helper_read_interval_timer(tmp); + ret = DISAS_NEXT; + } save_gpr(ctx, rt, tmp); - break; + return nullify_end(ctx, ret); case 26: case 27: break; @@ -2132,9 +2141,8 @@ static DisasJumpType trans_mtctl(DisasContext *ctx, uint32_t insn, nullify_over(ctx); switch (ctl) { case CR_IT: - /* ??? modify interval timer offset */ + gen_helper_write_interval_timer(cpu_env, reg); break; - case CR_EIRR: gen_helper_write_eirr(cpu_env, reg); break; From b36942a6981da534cda31b79f2b35319902389a0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 27 Oct 2017 16:26:59 +0200 Subject: [PATCH 20/43] target/hppa: Log unimplemented instructions Signed-off-by: Richard Henderson --- target/hppa/translate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 1cd57f5a90..6288bb9f67 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -4218,6 +4218,8 @@ static DisasJumpType translate_table_int(DisasContext *ctx, uint32_t insn, return table[i].trans(ctx, insn, &table[i]); } } + qemu_log_mask(LOG_UNIMP, "UNIMP insn %08x @ " TARGET_FMT_lx "\n", + insn, ctx->base.pc_next); return gen_illegal(ctx); } From 8d6ae7fb3a9c4369979bcc7188966fa725eed033 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 27 Oct 2017 16:26:36 +0200 Subject: [PATCH 21/43] target/hppa: Implement I*TLBA and I*TLBP insns The TLB can now be populated, but it cannot yet be cleared. Signed-off-by: Richard Henderson --- target/hppa/helper.h | 2 + target/hppa/mem_helper.c | 80 +++++++++++++++++++++++++++++++++++++++- target/hppa/translate.c | 54 ++++++++++++++++++++++++++- 3 files changed, 132 insertions(+), 4 deletions(-) diff --git a/target/hppa/helper.h b/target/hppa/helper.h index 744b11cb66..d412093914 100644 --- a/target/hppa/helper.h +++ b/target/hppa/helper.h @@ -86,4 +86,6 @@ DEF_HELPER_FLAGS_2(write_interval_timer, TCG_CALL_NO_RWG, void, env, tr) DEF_HELPER_FLAGS_2(write_eirr, TCG_CALL_NO_RWG, void, env, tr) DEF_HELPER_FLAGS_2(write_eiem, TCG_CALL_NO_RWG, void, env, tr) DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr) +DEF_HELPER_FLAGS_3(itlba, TCG_CALL_NO_RWG, void, env, tl, tr) +DEF_HELPER_FLAGS_3(itlbp, TCG_CALL_NO_RWG, void, env, tl, tr) #endif diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index 334ef98a32..59619e9ba8 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -42,13 +42,40 @@ static hppa_tlb_entry *hppa_find_tlb(CPUHPPAState *env, vaddr addr) for (i = 0; i < ARRAY_SIZE(env->tlb); ++i) { hppa_tlb_entry *ent = &env->tlb[i]; - if (ent->va_b <= addr && addr <= ent->va_e && ent->entry_valid) { + if (ent->va_b <= addr && addr <= ent->va_e) { return ent; } } return NULL; } +static void hppa_flush_tlb_ent(CPUHPPAState *env, hppa_tlb_entry *ent) +{ + CPUState *cs = CPU(hppa_env_get_cpu(env)); + unsigned i, n = 1 << (2 * ent->page_size); + uint64_t addr = ent->va_b; + + for (i = 0; i < n; ++i, addr += TARGET_PAGE_SIZE) { + /* Do not flush MMU_PHYS_IDX. */ + tlb_flush_page_by_mmuidx(cs, addr, 0xf); + } + + memset(ent, 0, sizeof(*ent)); + ent->va_b = -1; +} + +static hppa_tlb_entry *hppa_alloc_tlb_ent(CPUHPPAState *env) +{ + hppa_tlb_entry *ent; + uint32_t i = env->tlb_last; + + env->tlb_last = (i == ARRAY_SIZE(env->tlb) - 1 ? 0 : i + 1); + ent = &env->tlb[i]; + + hppa_flush_tlb_ent(env, ent); + return ent; +} + int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, int type, hwaddr *pphys, int *pprot) { @@ -66,7 +93,7 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, /* Find a valid tlb entry that matches the virtual address. */ ent = hppa_find_tlb(env, addr); - if (ent == NULL) { + if (ent == NULL || !ent->entry_valid) { phys = 0; prot = 0; ret = (type & PAGE_EXEC ? EXCP_ITLB_MISS : EXCP_DTLB_MISS); @@ -201,4 +228,53 @@ void tlb_fill(CPUState *cs, target_ulong addr, int size, tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, prot, mmu_idx, TARGET_PAGE_SIZE); } + +/* Insert (Insn/Data) TLB Address. Note this is PA 1.1 only. */ +void HELPER(itlba)(CPUHPPAState *env, target_ulong addr, target_ureg reg) +{ + hppa_tlb_entry *empty = NULL; + int i; + + /* Zap any old entries covering ADDR; notice empty entries on the way. */ + for (i = 0; i < ARRAY_SIZE(env->tlb); ++i) { + hppa_tlb_entry *ent = &env->tlb[i]; + if (!ent->entry_valid) { + empty = ent; + } else if (ent->va_b <= addr && addr <= ent->va_e) { + hppa_flush_tlb_ent(env, ent); + empty = ent; + } + } + + /* If we didn't see an empty entry, evict one. */ + if (empty == NULL) { + empty = hppa_alloc_tlb_ent(env); + } + + /* Note that empty->entry_valid == 0 already. */ + empty->va_b = addr & TARGET_PAGE_MASK; + empty->va_e = empty->va_b + TARGET_PAGE_SIZE - 1; + empty->pa = extract32(reg, 5, 20) << TARGET_PAGE_BITS; +} + +/* Insert (Insn/Data) TLB Protection. Note this is PA 1.1 only. */ +void HELPER(itlbp)(CPUHPPAState *env, target_ulong addr, target_ureg reg) +{ + hppa_tlb_entry *ent = hppa_find_tlb(env, addr); + + if (unlikely(ent == NULL || ent->entry_valid)) { + qemu_log_mask(LOG_GUEST_ERROR, "ITLBP not following ITLBA\n"); + return; + } + + ent->access_id = extract32(reg, 1, 18); + ent->u = extract32(reg, 19, 1); + ent->ar_pl2 = extract32(reg, 20, 2); + ent->ar_pl1 = extract32(reg, 22, 2); + ent->ar_type = extract32(reg, 24, 3); + ent->b = extract32(reg, 27, 1); + ent->d = extract32(reg, 28, 1); + ent->t = extract32(reg, 29, 1); + ent->entry_valid = 1; +} #endif /* CONFIG_USER_ONLY */ diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 6288bb9f67..c02d107041 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -1344,7 +1344,10 @@ static DisasJumpType do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1, } #ifndef CONFIG_USER_ONLY -/* Top 2 bits of the base register select sp[4-7]. */ +/* The "normal" usage is SP >= 0, wherein SP == 0 selects the space + from the top 2 bits of the base register. There are a few system + instructions that have a 3-bit space specifier, for which SR0 is + not special. To handle this, pass ~SP. */ static TCGv_i64 space_select(DisasContext *ctx, int sp, TCGv_reg base) { TCGv_ptr ptr; @@ -1352,7 +1355,12 @@ static TCGv_i64 space_select(DisasContext *ctx, int sp, TCGv_reg base) TCGv_i64 spc; if (sp != 0) { - return cpu_sr[sp]; + if (sp < 0) { + sp = ~sp; + } + spc = get_temp_tl(ctx); + load_spr(ctx, spc, sp); + return spc; } ptr = tcg_temp_new_ptr(); @@ -2355,6 +2363,42 @@ static DisasJumpType trans_probe(DisasContext *ctx, uint32_t insn, return nullify_end(ctx, DISAS_NEXT); } +#ifndef CONFIG_USER_ONLY +static DisasJumpType trans_ixtlbx(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + unsigned sp; + unsigned rr = extract32(insn, 16, 5); + unsigned rb = extract32(insn, 21, 5); + unsigned is_data = insn & 0x1000; + unsigned is_addr = insn & 0x40; + TCGv_tl addr; + TCGv_reg ofs, reg; + + if (is_data) { + sp = extract32(insn, 14, 2); + } else { + sp = ~assemble_sr3(insn); + } + + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + nullify_over(ctx); + + form_gva(ctx, &addr, &ofs, rb, 0, 0, 0, sp, 0, false); + reg = load_gpr(ctx, rr); + if (is_addr) { + gen_helper_itlba(cpu_env, addr, reg); + } else { + gen_helper_itlbp(cpu_env, addr, reg); + } + + /* Exit TB for ITLB change if mmu is enabled. This *should* not be + the case, since the OS TLB fill handler runs with mmu disabled. */ + return nullify_end(ctx, !is_data && (ctx->base.tb->flags & PSW_C) + ? DISAS_IAQ_N_STALE : DISAS_NEXT); +} +#endif /* !CONFIG_USER_ONLY */ + static const DisasInsn table_mem_mgmt[] = { { 0x04003280u, 0xfc003fffu, trans_nop }, /* fdc, disp */ { 0x04001280u, 0xfc003fffu, trans_nop }, /* fdc, index */ @@ -2371,6 +2415,12 @@ static const DisasInsn table_mem_mgmt[] = { { 0x04002720u, 0xfc003fffu, trans_base_idx_mod }, /* pdc, base mod */ { 0x04001180u, 0xfc003fa0u, trans_probe }, /* probe */ { 0x04003180u, 0xfc003fa0u, trans_probe }, /* probei */ +#ifndef CONFIG_USER_ONLY + { 0x04000000u, 0xfc001fffu, trans_ixtlbx }, /* iitlbp */ + { 0x04000040u, 0xfc001fffu, trans_ixtlbx }, /* iitlba */ + { 0x04001000u, 0xfc001fffu, trans_ixtlbx }, /* idtlbp */ + { 0x04001040u, 0xfc001fffu, trans_ixtlbx }, /* idtlba */ +#endif }; static DisasJumpType trans_add(DisasContext *ctx, uint32_t insn, From 63300a00ab52c770f8a76218d4a3a75e0db8a6d0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 27 Oct 2017 18:33:23 +0200 Subject: [PATCH 22/43] target/hppa: Implement P*TLB and P*TLBE insns We now have all of the TLB manipulation instructions. Signed-off-by: Richard Henderson --- target/hppa/helper.h | 2 ++ target/hppa/mem_helper.c | 37 +++++++++++++++++++++++++++++++++++++ target/hppa/translate.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/target/hppa/helper.h b/target/hppa/helper.h index d412093914..f059ddf3b9 100644 --- a/target/hppa/helper.h +++ b/target/hppa/helper.h @@ -88,4 +88,6 @@ DEF_HELPER_FLAGS_2(write_eiem, TCG_CALL_NO_RWG, void, env, tr) DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr) DEF_HELPER_FLAGS_3(itlba, TCG_CALL_NO_RWG, void, env, tl, tr) DEF_HELPER_FLAGS_3(itlbp, TCG_CALL_NO_RWG, void, env, tl, tr) +DEF_HELPER_FLAGS_2(ptlb, TCG_CALL_NO_RWG, void, env, tl) +DEF_HELPER_FLAGS_1(ptlbe, TCG_CALL_NO_RWG, void, env) #endif diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index 59619e9ba8..995b1937f6 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -277,4 +277,41 @@ void HELPER(itlbp)(CPUHPPAState *env, target_ulong addr, target_ureg reg) ent->t = extract32(reg, 29, 1); ent->entry_valid = 1; } + +/* Purge (Insn/Data) TLB. This is explicitly page-based, and is + synchronous across all processors. */ +static void ptlb_work(CPUState *cpu, run_on_cpu_data data) +{ + CPUHPPAState *env = cpu->env_ptr; + target_ulong addr = (target_ulong) data.target_ptr; + hppa_tlb_entry *ent = hppa_find_tlb(env, addr); + + if (ent && ent->entry_valid) { + hppa_flush_tlb_ent(env, ent); + } +} + +void HELPER(ptlb)(CPUHPPAState *env, target_ulong addr) +{ + CPUState *src = CPU(hppa_env_get_cpu(env)); + CPUState *cpu; + run_on_cpu_data data = RUN_ON_CPU_TARGET_PTR(addr); + + CPU_FOREACH(cpu) { + if (cpu != src) { + async_run_on_cpu(cpu, ptlb_work, data); + } + } + async_safe_run_on_cpu(src, ptlb_work, data); +} + +/* Purge (Insn/Data) TLB entry. This affects an implementation-defined + number of pages/entries (we choose all), and is local to the cpu. */ +void HELPER(ptlbe)(CPUHPPAState *env) +{ + CPUState *src = CPU(hppa_env_get_cpu(env)); + + memset(env->tlb, 0, sizeof(env->tlb)); + tlb_flush_by_mmuidx(src, 0xf); +} #endif /* CONFIG_USER_ONLY */ diff --git a/target/hppa/translate.c b/target/hppa/translate.c index c02d107041..5b77688fc0 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2397,6 +2397,42 @@ static DisasJumpType trans_ixtlbx(DisasContext *ctx, uint32_t insn, return nullify_end(ctx, !is_data && (ctx->base.tb->flags & PSW_C) ? DISAS_IAQ_N_STALE : DISAS_NEXT); } + +static DisasJumpType trans_pxtlbx(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + unsigned m = extract32(insn, 5, 1); + unsigned sp; + unsigned rx = extract32(insn, 16, 5); + unsigned rb = extract32(insn, 21, 5); + unsigned is_data = insn & 0x1000; + unsigned is_local = insn & 0x40; + TCGv_tl addr; + TCGv_reg ofs; + + if (is_data) { + sp = extract32(insn, 14, 2); + } else { + sp = ~assemble_sr3(insn); + } + + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + nullify_over(ctx); + + form_gva(ctx, &addr, &ofs, rb, rx, 0, 0, sp, m, false); + if (m) { + save_gpr(ctx, rb, ofs); + } + if (is_local) { + gen_helper_ptlbe(cpu_env); + } else { + gen_helper_ptlb(cpu_env, addr); + } + + /* Exit TB for TLB change if mmu is enabled. */ + return nullify_end(ctx, !is_data && (ctx->base.tb->flags & PSW_C) + ? DISAS_IAQ_N_STALE : DISAS_NEXT); +} #endif /* !CONFIG_USER_ONLY */ static const DisasInsn table_mem_mgmt[] = { @@ -2420,6 +2456,10 @@ static const DisasInsn table_mem_mgmt[] = { { 0x04000040u, 0xfc001fffu, trans_ixtlbx }, /* iitlba */ { 0x04001000u, 0xfc001fffu, trans_ixtlbx }, /* idtlbp */ { 0x04001040u, 0xfc001fffu, trans_ixtlbx }, /* idtlba */ + { 0x04000200u, 0xfc001fdfu, trans_pxtlbx }, /* pitlb */ + { 0x04000240u, 0xfc001fdfu, trans_pxtlbx }, /* pitlbe */ + { 0x04001200u, 0xfc001fdfu, trans_pxtlbx }, /* pdtlb */ + { 0x04001240u, 0xfc001fdfu, trans_pxtlbx }, /* pdtlbe */ #endif }; From d0a851cc508b355a4d63e905e4f69a466f0d7f89 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 5 Nov 2017 10:23:48 +0100 Subject: [PATCH 23/43] target/hppa: Implement LDWA Signed-off-by: Richard Henderson --- target/hppa/translate.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 5b77688fc0..3d441ef4ac 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2954,12 +2954,50 @@ static DisasJumpType trans_stby(DisasContext *ctx, uint32_t insn, return nullify_end(ctx, DISAS_NEXT); } +#ifndef CONFIG_USER_ONLY +static DisasJumpType trans_ldwa_idx_i(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + int hold_mmu_idx = ctx->mmu_idx; + DisasJumpType ret; + + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + + /* ??? needs fixing for hppa64 -- ldda does not follow the same + format wrt the sub-opcode in bits 6:9. */ + ctx->mmu_idx = MMU_PHYS_IDX; + ret = trans_ld_idx_i(ctx, insn, di); + ctx->mmu_idx = hold_mmu_idx; + return ret; +} + +static DisasJumpType trans_ldwa_idx_x(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + int hold_mmu_idx = ctx->mmu_idx; + DisasJumpType ret; + + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + + /* ??? needs fixing for hppa64 -- ldda does not follow the same + format wrt the sub-opcode in bits 6:9. */ + ctx->mmu_idx = MMU_PHYS_IDX; + ret = trans_ld_idx_x(ctx, insn, di); + ctx->mmu_idx = hold_mmu_idx; + return ret; +} +#endif + static const DisasInsn table_index_mem[] = { { 0x0c001000u, 0xfc001300, trans_ld_idx_i }, /* LD[BHWD], im */ { 0x0c000000u, 0xfc001300, trans_ld_idx_x }, /* LD[BHWD], rx */ { 0x0c001200u, 0xfc001300, trans_st_idx_i }, /* ST[BHWD] */ { 0x0c0001c0u, 0xfc0003c0, trans_ldcw }, { 0x0c001300u, 0xfc0013c0, trans_stby }, +#ifndef CONFIG_USER_ONLY + { 0x0c001180u, 0xfc00d3c0, trans_ldwa_idx_i }, /* LDWA, im */ + { 0x0c000180u, 0xfc00d3c0, trans_ldwa_idx_x }, /* LDWA, rx */ +#endif }; static DisasJumpType trans_ldil(DisasContext *ctx, uint32_t insn) From 2dfcca9ffc0131f0d740dea27ebff04be01f871b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 5 Nov 2017 10:50:47 +0100 Subject: [PATCH 24/43] target/hppa: Implement LPA Signed-off-by: Richard Henderson --- target/hppa/cpu.h | 1 + target/hppa/helper.h | 1 + target/hppa/mem_helper.c | 21 +++++++++++++++++++++ target/hppa/op_helper.c | 10 +++++----- target/hppa/translate.c | 30 ++++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 5 deletions(-) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 3782e1d834..54f11d4e18 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -345,5 +345,6 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, extern const MemoryRegionOps hppa_io_eir_ops; void hppa_cpu_alarm_timer(void *); #endif +void QEMU_NORETURN hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra); #endif /* HPPA_CPU_H */ diff --git a/target/hppa/helper.h b/target/hppa/helper.h index f059ddf3b9..1e733b7926 100644 --- a/target/hppa/helper.h +++ b/target/hppa/helper.h @@ -90,4 +90,5 @@ DEF_HELPER_FLAGS_3(itlba, TCG_CALL_NO_RWG, void, env, tl, tr) DEF_HELPER_FLAGS_3(itlbp, TCG_CALL_NO_RWG, void, env, tl, tr) DEF_HELPER_FLAGS_2(ptlb, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_1(ptlbe, TCG_CALL_NO_RWG, void, env) +DEF_HELPER_FLAGS_2(lpa, TCG_CALL_NO_WG, tr, env, tl) #endif diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index 995b1937f6..ecd964d779 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -314,4 +314,25 @@ void HELPER(ptlbe)(CPUHPPAState *env) memset(env->tlb, 0, sizeof(env->tlb)); tlb_flush_by_mmuidx(src, 0xf); } + +target_ureg HELPER(lpa)(CPUHPPAState *env, target_ulong addr) +{ + hwaddr phys; + int prot, excp; + + excp = hppa_get_physical_address(env, addr, MMU_KERNEL_IDX, 0, + &phys, &prot); + if (excp >= 0) { + if (env->psw & PSW_Q) { + /* ??? Needs tweaking for hppa64. */ + env->cr[CR_IOR] = addr; + env->cr[CR_ISR] = addr >> 32; + } + if (excp == EXCP_DTLB_MISS) { + excp = EXCP_NA_DTLB_MISS; + } + hppa_dynamic_excp(env, excp, GETPC()); + } + return phys; +} #endif /* CONFIG_USER_ONLY */ diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 8c546f4882..ef2951386c 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -34,7 +34,7 @@ void QEMU_NORETURN HELPER(excp)(CPUHPPAState *env, int excp) cpu_loop_exit(cs); } -static void QEMU_NORETURN dynexcp(CPUHPPAState *env, int excp, uintptr_t ra) +void QEMU_NORETURN hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra) { HPPACPU *cpu = hppa_env_get_cpu(env); CPUState *cs = CPU(cpu); @@ -46,14 +46,14 @@ static void QEMU_NORETURN dynexcp(CPUHPPAState *env, int excp, uintptr_t ra) void HELPER(tsv)(CPUHPPAState *env, target_ureg cond) { if (unlikely((target_sreg)cond < 0)) { - dynexcp(env, EXCP_OVERFLOW, GETPC()); + hppa_dynamic_excp(env, EXCP_OVERFLOW, GETPC()); } } void HELPER(tcond)(CPUHPPAState *env, target_ureg cond) { if (unlikely(cond)) { - dynexcp(env, EXCP_COND, GETPC()); + hppa_dynamic_excp(env, EXCP_COND, GETPC()); } } @@ -237,7 +237,7 @@ static void update_fr0_op(CPUHPPAState *env, uintptr_t ra) env->fr[0] = (uint64_t)shadow << 32; if (hard_exp & shadow) { - dynexcp(env, EXCP_ASSIST, ra); + hppa_dynamic_excp(env, EXCP_ASSIST, ra); } } @@ -645,7 +645,7 @@ target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm) /* ??? On second reading this condition simply seems to be undefined rather than a diagnosed trap. */ if (nsm & ~psw & PSW_Q) { - dynexcp(env, EXCP_ILL, GETPC()); + hppa_dynamic_excp(env, EXCP_ILL, GETPC()); } env->psw = (psw & ~PSW_SM) | (nsm & PSW_SM); return psw & PSW_SM; diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 3d441ef4ac..082221f450 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2433,6 +2433,35 @@ static DisasJumpType trans_pxtlbx(DisasContext *ctx, uint32_t insn, return nullify_end(ctx, !is_data && (ctx->base.tb->flags & PSW_C) ? DISAS_IAQ_N_STALE : DISAS_NEXT); } + +static DisasJumpType trans_lpa(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + unsigned rt = extract32(insn, 0, 5); + unsigned m = extract32(insn, 5, 1); + unsigned sp = extract32(insn, 14, 2); + unsigned rx = extract32(insn, 16, 5); + unsigned rb = extract32(insn, 21, 5); + TCGv_tl vaddr; + TCGv_reg ofs, paddr; + + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + nullify_over(ctx); + + form_gva(ctx, &vaddr, &ofs, rb, rx, 0, 0, sp, m, false); + + paddr = tcg_temp_new(); + gen_helper_lpa(paddr, cpu_env, vaddr); + + /* Note that physical address result overrides base modification. */ + if (m) { + save_gpr(ctx, rb, ofs); + } + save_gpr(ctx, rt, paddr); + tcg_temp_free(paddr); + + return nullify_end(ctx, DISAS_NEXT); +} #endif /* !CONFIG_USER_ONLY */ static const DisasInsn table_mem_mgmt[] = { @@ -2460,6 +2489,7 @@ static const DisasInsn table_mem_mgmt[] = { { 0x04000240u, 0xfc001fdfu, trans_pxtlbx }, /* pitlbe */ { 0x04001200u, 0xfc001fdfu, trans_pxtlbx }, /* pdtlb */ { 0x04001240u, 0xfc001fdfu, trans_pxtlbx }, /* pdtlbe */ + { 0x04001340u, 0xfc003fc0u, trans_lpa }, #endif }; From 43a97b81b5ae791bfdb2470b9be749155a968604 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 5 Nov 2017 11:02:40 +0100 Subject: [PATCH 25/43] target/hppa: Implement LCI Signed-off-by: Richard Henderson --- target/hppa/translate.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 082221f450..41e28ff64c 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2462,6 +2462,25 @@ static DisasJumpType trans_lpa(DisasContext *ctx, uint32_t insn, return nullify_end(ctx, DISAS_NEXT); } + +static DisasJumpType trans_lci(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + unsigned rt = extract32(insn, 0, 5); + TCGv_reg ci; + + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + + /* The Coherence Index is an implementation-defined function of the + physical address. Two addresses with the same CI have a coherent + view of the cache. Our implementation is to return 0 for all, + since the entire address space is coherent. */ + ci = tcg_const_reg(0); + save_gpr(ctx, rt, ci); + tcg_temp_free(ci); + + return DISAS_NEXT; +} #endif /* !CONFIG_USER_ONLY */ static const DisasInsn table_mem_mgmt[] = { @@ -2490,6 +2509,7 @@ static const DisasInsn table_mem_mgmt[] = { { 0x04001200u, 0xfc001fdfu, trans_pxtlbx }, /* pdtlb */ { 0x04001240u, 0xfc001fdfu, trans_pxtlbx }, /* pdtlbe */ { 0x04001340u, 0xfc003fc0u, trans_lpa }, + { 0x04001300u, 0xfc003fe0u, trans_lci }, #endif }; From e216a77e3b2e7ba3d5662f216915eb81497f673a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 29 Oct 2017 15:57:51 +0100 Subject: [PATCH 26/43] target/hppa: Implement SYNCDMA insn Signed-off-by: Richard Henderson --- target/hppa/translate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 41e28ff64c..f3942b1baf 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2312,7 +2312,8 @@ static const DisasInsn table_system[] = { { 0x000014a0u, 0xffffffe0u, trans_mfia }, { 0x000004a0u, 0xffff1fe0u, trans_mfsp }, { 0x000008a0u, 0xfc1fbfe0u, trans_mfctl }, - { 0x00000400u, 0xffffffffu, trans_sync }, + { 0x00000400u, 0xffffffffu, trans_sync }, /* sync */ + { 0x00100400u, 0xffffffffu, trans_sync }, /* syncdma */ { 0x000010a0u, 0xfc1f3fe0u, trans_ldsid }, #ifndef CONFIG_USER_ONLY { 0x00000e60u, 0xfc00ffe0u, trans_rsm }, From 6210db057a6f255f8d5caff1507f14185526df7a Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 28 Dec 2017 22:04:57 -0800 Subject: [PATCH 27/43] target/hppa: Implement halt and reset instructions Real hardware would use an external device to control the power. But for the moment let's invent instructions in reserved space, to be used by our custom firmware. Signed-off-by: Helge Deller Signed-off-by: Richard Henderson --- target/hppa/helper.h | 2 ++ target/hppa/op_helper.c | 13 +++++++++++++ target/hppa/translate.c | 25 ++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/target/hppa/helper.h b/target/hppa/helper.h index 1e733b7926..0e569cba31 100644 --- a/target/hppa/helper.h +++ b/target/hppa/helper.h @@ -80,6 +80,8 @@ DEF_HELPER_FLAGS_4(fmpynfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) DEF_HELPER_FLAGS_0(read_interval_timer, TCG_CALL_NO_RWG, tr) #ifndef CONFIG_USER_ONLY +DEF_HELPER_1(halt, noreturn, env) +DEF_HELPER_1(reset, noreturn, env) DEF_HELPER_1(rfi, void, env) DEF_HELPER_1(rfi_r, void, env) DEF_HELPER_FLAGS_2(write_interval_timer, TCG_CALL_NO_RWG, void, env, tr) diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index ef2951386c..0daa7511f4 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -22,6 +22,7 @@ #include "exec/exec-all.h" #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" +#include "sysemu/sysemu.h" #include "qemu/timer.h" @@ -639,6 +640,18 @@ void HELPER(write_interval_timer)(CPUHPPAState *env, target_ureg val) timer_mod(cpu->alarm_timer, timeout); } +void HELPER(halt)(CPUHPPAState *env) +{ + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + helper_excp(env, EXCP_HLT); +} + +void HELPER(reset)(CPUHPPAState *env) +{ + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + helper_excp(env, EXCP_HLT); +} + target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm) { target_ulong psw = env->psw; diff --git a/target/hppa/translate.c b/target/hppa/translate.c index f3942b1baf..b410583af5 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2302,6 +2302,18 @@ static DisasJumpType trans_rfi(DisasContext *ctx, uint32_t insn, /* Exit the TB to recognize new interrupts. */ return nullify_end(ctx, DISAS_NORETURN); } + +static DisasJumpType gen_hlt(DisasContext *ctx, int reset) +{ + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + nullify_over(ctx); + if (reset) { + gen_helper_reset(cpu_env); + } else { + gen_helper_halt(cpu_env); + } + return nullify_end(ctx, DISAS_NORETURN); +} #endif /* !CONFIG_USER_ONLY */ static const DisasInsn table_system[] = { @@ -4519,7 +4531,18 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) case 0x15: /* unassigned */ case 0x1D: /* unassigned */ case 0x37: /* unassigned */ - case 0x3F: /* unassigned */ + break; + case 0x3F: +#ifndef CONFIG_USER_ONLY + /* Unassigned, but use as system-halt. */ + if (insn == 0xfffdead0) { + return gen_hlt(ctx, 0); /* halt system */ + } + if (insn == 0xfffdead1) { + return gen_hlt(ctx, 1); /* reset system */ + } +#endif + break; default: break; } From 494737b7a24b39f3a2d537180af2a2880a0817fb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 6 Nov 2017 21:10:33 +0100 Subject: [PATCH 28/43] target/hppa: Optimize for flat addressing space Linux sets sr4-sr7 all to the same value, which means that we need not do any runtime computation to find out what space to use in forming the GVA. Signed-off-by: Richard Henderson --- target/hppa/cpu.h | 11 ++++++++++- target/hppa/translate.c | 29 ++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 54f11d4e18..40700f8425 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -282,7 +282,11 @@ static inline target_ulong hppa_form_gva(CPUHPPAState *env, uint64_t spc, return hppa_form_gva_psw(env->psw, spc, off); } -/* Since PSW_CB will never need to be in tb->flags, reuse them. */ +/* Since PSW_{I,CB} will never need to be in tb->flags, reuse them. + * TB_FLAG_SR_SAME indicates that SR4 through SR7 all contain the + * same value. + */ +#define TB_FLAG_SR_SAME PSW_I #define TB_FLAG_PRIV_SHIFT 8 static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, target_ulong *pc, @@ -318,6 +322,11 @@ static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, target_ulong *pc, *cs_base |= (uint32_t)diff; } } + if ((env->sr[4] == env->sr[5]) + & (env->sr[4] == env->sr[6]) + & (env->sr[4] == env->sr[7])) { + flags |= TB_FLAG_SR_SAME; + } #endif *pflags = flags; diff --git a/target/hppa/translate.c b/target/hppa/translate.c index b410583af5..0f0d5333f3 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -284,6 +284,7 @@ typedef struct DisasContext { TCGLabel *null_lab; uint32_t insn; + uint32_t tb_flags; int mmu_idx; int privilege; bool psw_n_nonzero; @@ -323,6 +324,7 @@ typedef struct DisasInsn { /* global register indexes */ static TCGv_reg cpu_gr[32]; static TCGv_i64 cpu_sr[4]; +static TCGv_i64 cpu_srH; static TCGv_reg cpu_iaoq_f; static TCGv_reg cpu_iaoq_b; static TCGv_i64 cpu_iasq_f; @@ -360,8 +362,8 @@ void hppa_translate_init(void) "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" }; /* SR[4-7] are not global registers so that we can index them. */ - static const char sr_names[4][4] = { - "sr0", "sr1", "sr2", "sr3" + static const char sr_names[5][4] = { + "sr0", "sr1", "sr2", "sr3", "srH" }; int i; @@ -377,6 +379,9 @@ void hppa_translate_init(void) offsetof(CPUHPPAState, sr[i]), sr_names[i]); } + cpu_srH = tcg_global_mem_new_i64(cpu_env, + offsetof(CPUHPPAState, sr[4]), + sr_names[4]); for (i = 0; i < ARRAY_SIZE(vars); ++i) { const GlobalVar *v = &vars[i]; @@ -604,6 +609,8 @@ static void load_spr(DisasContext *ctx, TCGv_i64 dest, unsigned reg) #else if (reg < 4) { tcg_gen_mov_i64(dest, cpu_sr[reg]); + } else if (ctx->tb_flags & TB_FLAG_SR_SAME) { + tcg_gen_mov_i64(dest, cpu_srH); } else { tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUHPPAState, sr[reg])); } @@ -1362,6 +1369,9 @@ static TCGv_i64 space_select(DisasContext *ctx, int sp, TCGv_reg base) load_spr(ctx, spc, sp); return spc; } + if (ctx->tb_flags & TB_FLAG_SR_SAME) { + return cpu_srH; + } ptr = tcg_temp_new_ptr(); tmp = tcg_temp_new(); @@ -1405,7 +1415,7 @@ static void form_gva(DisasContext *ctx, TCGv_tl *pgva, TCGv_reg *pofs, #else TCGv_tl addr = get_temp_tl(ctx); tcg_gen_extu_reg_tl(addr, modify <= 0 ? ofs : base); - if (ctx->base.tb->flags & PSW_W) { + if (ctx->tb_flags & PSW_W) { tcg_gen_andi_tl(addr, addr, 0x3fffffffffffffffull); } if (!is_phys) { @@ -2112,6 +2122,7 @@ static DisasJumpType trans_mtsp(DisasContext *ctx, uint32_t insn, if (rs >= 4) { tcg_gen_st_i64(t64, cpu_env, offsetof(CPUHPPAState, sr[rs])); + ctx->tb_flags &= ~TB_FLAG_SR_SAME; } else { tcg_gen_mov_i64(cpu_sr[rs], t64); } @@ -2407,7 +2418,7 @@ static DisasJumpType trans_ixtlbx(DisasContext *ctx, uint32_t insn, /* Exit TB for ITLB change if mmu is enabled. This *should* not be the case, since the OS TLB fill handler runs with mmu disabled. */ - return nullify_end(ctx, !is_data && (ctx->base.tb->flags & PSW_C) + return nullify_end(ctx, !is_data && (ctx->tb_flags & PSW_C) ? DISAS_IAQ_N_STALE : DISAS_NEXT); } @@ -2443,7 +2454,7 @@ static DisasJumpType trans_pxtlbx(DisasContext *ctx, uint32_t insn, } /* Exit TB for TLB change if mmu is enabled. */ - return nullify_end(ctx, !is_data && (ctx->base.tb->flags & PSW_C) + return nullify_end(ctx, !is_data && (ctx->tb_flags & PSW_C) ? DISAS_IAQ_N_STALE : DISAS_NEXT); } @@ -4556,6 +4567,7 @@ static int hppa_tr_init_disas_context(DisasContextBase *dcbase, int bound; ctx->cs = cs; + ctx->tb_flags = ctx->base.tb->flags; #ifdef CONFIG_USER_ONLY ctx->privilege = MMU_USER_IDX; @@ -4563,9 +4575,8 @@ static int hppa_tr_init_disas_context(DisasContextBase *dcbase, ctx->iaoq_f = ctx->base.pc_first; ctx->iaoq_b = ctx->base.tb->cs_base; #else - ctx->privilege = (ctx->base.tb->flags >> TB_FLAG_PRIV_SHIFT) & 3; - ctx->mmu_idx = (ctx->base.tb->flags & PSW_D - ? ctx->privilege : MMU_PHYS_IDX); + ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3; + ctx->mmu_idx = (ctx->tb_flags & PSW_D ? ctx->privilege : MMU_PHYS_IDX); /* Recover the IAOQ values from the GVA + PRIV. */ uint64_t cs_base = ctx->base.tb->cs_base; @@ -4597,7 +4608,7 @@ static void hppa_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) /* Seed the nullification status from PSW[N], as saved in TB->FLAGS. */ ctx->null_cond = cond_make_f(); ctx->psw_n_nonzero = false; - if (ctx->base.tb->flags & PSW_N) { + if (ctx->tb_flags & PSW_N) { ctx->null_cond.c = TCG_COND_ALWAYS; ctx->psw_n_nonzero = true; } From e33348a635462d33d6383b532100bbe2e1fa4097 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 7 Nov 2017 05:42:14 +0100 Subject: [PATCH 29/43] target/hppa: Add system registers to gdbstub Signed-off-by: Richard Henderson --- target/hppa/gdbstub.c | 156 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/target/hppa/gdbstub.c b/target/hppa/gdbstub.c index fc27aec073..e2e9c4d77f 100644 --- a/target/hppa/gdbstub.c +++ b/target/hppa/gdbstub.c @@ -41,15 +41,93 @@ int hppa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) case 33: val = env->iaoq_f; break; + case 34: + val = env->iasq_f >> 32; + break; case 35: val = env->iaoq_b; break; + case 36: + val = env->iasq_b >> 32; + break; + case 37: + val = env->cr[CR_EIEM]; + break; + case 38: + val = env->cr[CR_IIR]; + break; + case 39: + val = env->cr[CR_ISR]; + break; + case 40: + val = env->cr[CR_IOR]; + break; + case 41: + val = env->cr[CR_IPSW]; + break; + case 43: + val = env->sr[4] >> 32; + break; + case 44: + val = env->sr[0] >> 32; + break; + case 45: + val = env->sr[1] >> 32; + break; + case 46: + val = env->sr[2] >> 32; + break; + case 47: + val = env->sr[3] >> 32; + break; + case 48: + val = env->sr[5] >> 32; + break; + case 49: + val = env->sr[6] >> 32; + break; + case 50: + val = env->sr[7] >> 32; + break; + case 51: + val = env->cr[CR_RC]; + break; + case 52: + val = env->cr[8]; + break; + case 53: + val = env->cr[9]; + break; + case 54: + val = env->cr[CR_SCRCCR]; + break; + case 55: + val = env->cr[12]; + break; + case 56: + val = env->cr[13]; + break; + case 57: + val = env->cr[24]; + break; + case 58: + val = env->cr[25]; + break; case 59: val = env->cr[26]; break; case 60: val = env->cr[27]; break; + case 61: + val = env->cr[28]; + break; + case 62: + val = env->cr[29]; + break; + case 63: + val = env->cr[30]; + break; case 64 ... 127: val = extract64(env->fr[(n - 64) / 2], (n & 1 ? 0 : 32), 32); break; @@ -94,15 +172,93 @@ int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) case 33: env->iaoq_f = val; break; + case 34: + env->iasq_f = (uint64_t)val << 32; + break; case 35: env->iaoq_b = val; break; + case 36: + env->iasq_b = (uint64_t)val << 32; + break; + case 37: + env->cr[CR_EIEM] = val; + break; + case 38: + env->cr[CR_IIR] = val; + break; + case 39: + env->cr[CR_ISR] = val; + break; + case 40: + env->cr[CR_IOR] = val; + break; + case 41: + env->cr[CR_IPSW] = val; + break; + case 43: + env->sr[4] = (uint64_t)val << 32; + break; + case 44: + env->sr[0] = (uint64_t)val << 32; + break; + case 45: + env->sr[1] = (uint64_t)val << 32; + break; + case 46: + env->sr[2] = (uint64_t)val << 32; + break; + case 47: + env->sr[3] = (uint64_t)val << 32; + break; + case 48: + env->sr[5] = (uint64_t)val << 32; + break; + case 49: + env->sr[6] = (uint64_t)val << 32; + break; + case 50: + env->sr[7] = (uint64_t)val << 32; + break; + case 51: + env->cr[CR_RC] = val; + break; + case 52: + env->cr[8] = val; + break; + case 53: + env->cr[9] = val; + break; + case 54: + env->cr[CR_SCRCCR] = val; + break; + case 55: + env->cr[12] = val; + break; + case 56: + env->cr[13] = val; + break; + case 57: + env->cr[24] = val; + break; + case 58: + env->cr[25] = val; + break; case 59: env->cr[26] = val; break; case 60: env->cr[27] = val; break; + case 61: + env->cr[28] = val; + break; + case 62: + env->cr[29] = val; + break; + case 63: + env->cr[30] = val; + break; case 64: env->fr[0] = deposit64(env->fr[0], 32, 32, val); cpu_hppa_loaded_fr0(env); From c643603a85fc27e2a899ec99b44a61ab1f631e21 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Nov 2017 11:06:04 +0100 Subject: [PATCH 30/43] target/hppa: Add migration for the cpu Signed-off-by: Richard Henderson --- target/hppa/Makefile.objs | 1 + target/hppa/cpu.c | 1 + target/hppa/cpu.h | 1 + target/hppa/machine.c | 181 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 184 insertions(+) create mode 100644 target/hppa/machine.c diff --git a/target/hppa/Makefile.objs b/target/hppa/Makefile.objs index dcd60a6839..3359da5341 100644 --- a/target/hppa/Makefile.objs +++ b/target/hppa/Makefile.objs @@ -1,2 +1,3 @@ obj-y += translate.o helper.o cpu.o op_helper.o gdbstub.o mem_helper.o obj-y += int_helper.o +obj-$(CONFIG_SOFTMMU) += machine.o diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index 6be6eb0a7b..5213347720 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -184,6 +184,7 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data) cc->handle_mmu_fault = hppa_cpu_handle_mmu_fault; #else cc->get_phys_page_debug = hppa_cpu_get_phys_page_debug; + dc->vmsd = &vmstate_hppa_cpu; #endif cc->do_unaligned_access = hppa_cpu_do_unaligned_access; cc->disas_set_info = hppa_cpu_disas_set_info; diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 40700f8425..5fab9e1394 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -352,6 +352,7 @@ int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, int type, hwaddr *pphys, int *pprot); extern const MemoryRegionOps hppa_io_eir_ops; +extern const struct VMStateDescription vmstate_hppa_cpu; void hppa_cpu_alarm_timer(void *); #endif void QEMU_NORETURN hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra); diff --git a/target/hppa/machine.c b/target/hppa/machine.c new file mode 100644 index 0000000000..8e077788c3 --- /dev/null +++ b/target/hppa/machine.c @@ -0,0 +1,181 @@ +/* + * HPPA interrupt helper routines + * + * Copyright (c) 2017 Richard Henderson + * + * 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, see . + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" +#include "hw/hw.h" +#include "hw/boards.h" +#include "migration/cpu.h" + +#if TARGET_REGISTER_BITS == 64 +#define qemu_put_betr qemu_put_be64 +#define qemu_get_betr qemu_get_be64 +#define VMSTATE_UINTTL_V(_f, _s, _v) \ + VMSTATE_UINT64_V(_f, _s, _v) +#define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \ + VMSTATE_UINT64_ARRAY_V(_f, _s, _n, _v) +#else +#define qemu_put_betr qemu_put_be32 +#define qemu_get_betr qemu_get_be32 +#define VMSTATE_UINTTR_V(_f, _s, _v) \ + VMSTATE_UINT32_V(_f, _s, _v) +#define VMSTATE_UINTTR_ARRAY_V(_f, _s, _n, _v) \ + VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v) +#endif + +#define VMSTATE_UINTTR(_f, _s) \ + VMSTATE_UINTTR_V(_f, _s, 0) +#define VMSTATE_UINTTR_ARRAY(_f, _s, _n) \ + VMSTATE_UINTTR_ARRAY_V(_f, _s, _n, 0) + + +static int get_psw(QEMUFile *f, void *opaque, size_t size, VMStateField *field) +{ + CPUHPPAState *env = opaque; + cpu_hppa_put_psw(env, qemu_get_betr(f)); + return 0; +} + +static int put_psw(QEMUFile *f, void *opaque, size_t size, + VMStateField *field, QJSON *vmdesc) +{ + CPUHPPAState *env = opaque; + qemu_put_betr(f, cpu_hppa_get_psw(env)); + return 0; +} + +static const VMStateInfo vmstate_psw = { + .name = "psw", + .get = get_psw, + .put = put_psw, +}; + +/* FIXME: Use the PA2.0 format, which is a superset of the PA1.1 format. */ +static int get_tlb(QEMUFile *f, void *opaque, size_t size, VMStateField *field) +{ + hppa_tlb_entry *ent = opaque; + uint32_t val; + + memset(ent, 0, sizeof(*ent)); + + ent->va_b = qemu_get_be64(f); + ent->pa = qemu_get_betr(f); + val = qemu_get_be32(f); + + ent->entry_valid = extract32(val, 0, 1); + ent->access_id = extract32(val, 1, 18); + ent->u = extract32(val, 19, 1); + ent->ar_pl2 = extract32(val, 20, 2); + ent->ar_pl1 = extract32(val, 22, 2); + ent->ar_type = extract32(val, 24, 3); + ent->b = extract32(val, 27, 1); + ent->d = extract32(val, 28, 1); + ent->t = extract32(val, 29, 1); + + ent->va_e = ent->va_b + TARGET_PAGE_SIZE - 1; + return 0; +} + +static int put_tlb(QEMUFile *f, void *opaque, size_t size, + VMStateField *field, QJSON *vmdesc) +{ + hppa_tlb_entry *ent = opaque; + uint32_t val = 0; + + if (ent->entry_valid) { + val = 1; + val = deposit32(val, 1, 18, ent->access_id); + val = deposit32(val, 19, 1, ent->u); + val = deposit32(val, 20, 2, ent->ar_pl2); + val = deposit32(val, 22, 2, ent->ar_pl1); + val = deposit32(val, 24, 3, ent->ar_type); + val = deposit32(val, 27, 1, ent->b); + val = deposit32(val, 28, 1, ent->d); + val = deposit32(val, 29, 1, ent->t); + } + + qemu_put_be64(f, ent->va_b); + qemu_put_betr(f, ent->pa); + qemu_put_be32(f, val); + return 0; +} + +static const VMStateInfo vmstate_tlb = { + .name = "tlb entry", + .get = get_tlb, + .put = put_tlb, +}; + +static VMStateField vmstate_env_fields[] = { + VMSTATE_UINTTR_ARRAY(gr, CPUHPPAState, 32), + VMSTATE_UINT64_ARRAY(fr, CPUHPPAState, 32), + VMSTATE_UINT64_ARRAY(sr, CPUHPPAState, 8), + VMSTATE_UINTTR_ARRAY(cr, CPUHPPAState, 32), + VMSTATE_UINTTR_ARRAY(cr_back, CPUHPPAState, 2), + VMSTATE_UINTTR_ARRAY(shadow, CPUHPPAState, 7), + + /* Save the architecture value of the psw, not the internally + expanded version. Since this architecture value does not + exist in memory to be stored, this requires a but of hoop + jumping. We want OFFSET=0 so that we effectively pass ENV + to the helper functions, and we need to fill in the name by + hand since there's no field of that name. */ + { + .name = "psw", + .version_id = 0, + .size = sizeof(uint64_t), + .info = &vmstate_psw, + .flags = VMS_SINGLE, + .offset = 0 + }, + + VMSTATE_UINTTR(iaoq_f, CPUHPPAState), + VMSTATE_UINTTR(iaoq_b, CPUHPPAState), + VMSTATE_UINT64(iasq_f, CPUHPPAState), + VMSTATE_UINT64(iasq_b, CPUHPPAState), + + VMSTATE_UINT32(fr0_shadow, CPUHPPAState), + + VMSTATE_ARRAY(tlb, CPUHPPAState, ARRAY_SIZE(((CPUHPPAState *)0)->tlb), + 0, vmstate_tlb, hppa_tlb_entry), + VMSTATE_UINT32(tlb_last, CPUHPPAState), + + VMSTATE_END_OF_LIST() +}; + +static const VMStateDescription vmstate_env = { + .name = "env", + .version_id = 1, + .minimum_version_id = 1, + .fields = vmstate_env_fields, +}; + +static VMStateField vmstate_cpu_fields[] = { + VMSTATE_CPU(), + VMSTATE_STRUCT(env, HPPACPU, 1, vmstate_env, CPUHPPAState), + VMSTATE_END_OF_LIST() +}; + +const VMStateDescription vmstate_hppa_cpu = { + .name = "cpu", + .version_id = 1, + .minimum_version_id = 1, + .fields = vmstate_cpu_fields, +}; From 43e056522f3e653d0d7e412b4e4d54eb7bcae8b1 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 15 Dec 2017 14:37:26 -0600 Subject: [PATCH 31/43] target/hppa: Implement B,GATE insn Signed-off-by: Richard Henderson --- target/hppa/cpu.h | 1 + target/hppa/mem_helper.c | 8 +++++++ target/hppa/translate.c | 48 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 5fab9e1394..70af823a15 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -354,6 +354,7 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, extern const MemoryRegionOps hppa_io_eir_ops; extern const struct VMStateDescription vmstate_hppa_cpu; void hppa_cpu_alarm_timer(void *); +int hppa_artype_for_page(CPUHPPAState *env, target_ulong vaddr); #endif void QEMU_NORETURN hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra); diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index ecd964d779..bf7559ba9e 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -122,6 +122,7 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, break; default: /* execute: promote to privilege level type & 3 */ prot = x_prot; + break; } /* ??? Check PSW_P and ent->access_prot. This can remove PAGE_WRITE. */ @@ -335,4 +336,11 @@ target_ureg HELPER(lpa)(CPUHPPAState *env, target_ulong addr) } return phys; } + +/* Return the ar_type of the TLB at VADDR, or -1. */ +int hppa_artype_for_page(CPUHPPAState *env, target_ulong vaddr) +{ + hppa_tlb_entry *ent = hppa_find_tlb(env, vaddr); + return ent ? ent->ar_type : -1; +} #endif /* CONFIG_USER_ONLY */ diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 0f0d5333f3..b6b7262e53 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -3782,6 +3782,53 @@ static DisasJumpType trans_bl(DisasContext *ctx, uint32_t insn, return do_dbranch(ctx, iaoq_dest(ctx, disp), link, n); } +static DisasJumpType trans_b_gate(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + unsigned n = extract32(insn, 1, 1); + unsigned link = extract32(insn, 21, 5); + target_sreg disp = assemble_17(insn); + target_ureg dest = iaoq_dest(ctx, disp); + + /* Make sure the caller hasn't done something weird with the queue. + * ??? This is not quite the same as the PSW[B] bit, which would be + * expensive to track. Real hardware will trap for + * b gateway + * b gateway+4 (in delay slot of first branch) + * However, checking for a non-sequential instruction queue *will* + * diagnose the security hole + * b gateway + * b evil + * in which instructions at evil would run with increased privs. + */ + if (ctx->iaoq_b == -1 || ctx->iaoq_b != ctx->iaoq_f + 4) { + return gen_illegal(ctx); + } + +#ifndef CONFIG_USER_ONLY + if (ctx->tb_flags & PSW_C) { + CPUHPPAState *env = ctx->cs->env_ptr; + int type = hppa_artype_for_page(env, ctx->base.pc_next); + /* If we could not find a TLB entry, then we need to generate an + ITLB miss exception so the kernel will provide it. + The resulting TLB fill operation will invalidate this TB and + we will re-translate, at which point we *will* be able to find + the TLB entry and determine if this is in fact a gateway page. */ + if (type < 0) { + return gen_excp(ctx, EXCP_ITLB_MISS); + } + /* No change for non-gateway pages or for priv decrease. */ + if (type >= 4 && type - 4 < ctx->privilege) { + dest = deposit32(dest, 0, 2, type - 4); + } + } else { + dest &= -4; /* priv = 0 */ + } +#endif + + return do_dbranch(ctx, dest, link, n); +} + static DisasJumpType trans_bl_long(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { @@ -3860,6 +3907,7 @@ static const DisasInsn table_branch[] = { { 0xe8004000u, 0xfc00fffdu, trans_blr }, { 0xe800c000u, 0xfc00fffdu, trans_bv }, { 0xe800d000u, 0xfc00dffcu, trans_bve }, + { 0xe8002000u, 0xfc00e000u, trans_b_gate }, }; static DisasJumpType trans_fop_wew_0c(DisasContext *ctx, uint32_t insn, From 46559e8184b23e539912bb78764e662b5eabb537 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 28 Dec 2017 19:26:52 -0800 Subject: [PATCH 32/43] target/hppa: Only use EXCP_DTLB_MISS Unknown why this works, but if we return EXCP_ITLB_MISS we will triple-fault the first userland instruction fetch. Is it something to do with having a combined I/DTLB? Signed-off-by: Richard Henderson --- target/hppa/mem_helper.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index bf7559ba9e..ab160c2a74 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -96,7 +96,9 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, if (ent == NULL || !ent->entry_valid) { phys = 0; prot = 0; - ret = (type & PAGE_EXEC ? EXCP_ITLB_MISS : EXCP_DTLB_MISS); + /* ??? Unconditionally report data tlb miss, + even if this is an instruction fetch. */ + ret = EXCP_DTLB_MISS; goto egress; } From 5eecd37a931e04b229fe6b695781932161a38c0a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 1 Nov 2017 05:03:09 -0700 Subject: [PATCH 33/43] target/hppa: Increase number of temp regs HP-UX 10.20 CD contains "add r0, r0, r27" in a delay slot, which uses at least 5 temps. Signed-off-by: Richard Henderson --- target/hppa/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index b6b7262e53..6ff82d3e9c 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -277,7 +277,7 @@ typedef struct DisasContext { TCGv_reg iaoq_n_var; int ntempr, ntempl; - TCGv_reg tempr[4]; + TCGv_reg tempr[8]; TCGv_tl templ[4]; DisasCond null_cond; From 3f7367e2ccc33aefd962c9459624ce40efa7e7ad Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 12 Dec 2017 22:23:19 +0100 Subject: [PATCH 34/43] target/hppa: Fix comment Signed-off-by: Helge Deller Message-Id: <20171212212319.GA31494@ls3530.fritz.box> Signed-off-by: Richard Henderson --- target/hppa/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 6ff82d3e9c..b773b0ef09 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -3193,7 +3193,7 @@ static DisasJumpType trans_store_w(DisasContext *ctx, uint32_t insn) /* FSTW without modification. */ return do_fstorew(ctx, ext2 * 32 + rt, rb, 0, 0, i, sp, 0); case 2: - /* LDW with modification. */ + /* STW with modification. */ return do_store(ctx, rt, rb, i, sp, (i < 0 ? 1 : -1), MO_TEUL); default: return gen_illegal(ctx); From 2330504ceec94e2cfa1138e5b256b5e1b4a1b444 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 2 Jan 2018 21:31:45 +0100 Subject: [PATCH 35/43] target/hppa: Implement LDSID for system mode Signed-off-by: Helge Deller Message-Id: <20180102203145.GA17059@ls3530.fritz.box> Signed-off-by: Richard Henderson --- target/hppa/translate.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index b773b0ef09..2f8e87bba9 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2211,8 +2211,20 @@ static DisasJumpType trans_ldsid(DisasContext *ctx, uint32_t insn, unsigned rt = extract32(insn, 0, 5); TCGv_reg dest = dest_gpr(ctx, rt); - /* Since we don't implement space registers, this returns zero. */ +#ifdef CONFIG_USER_ONLY + /* We don't implement space registers in user mode. */ tcg_gen_movi_reg(dest, 0); +#else + unsigned rb = extract32(insn, 21, 5); + unsigned sp = extract32(insn, 14, 2); + TCGv_i64 t0 = tcg_temp_new_i64(); + + tcg_gen_mov_i64(t0, space_select(ctx, sp, load_gpr(ctx, rb))); + tcg_gen_shri_i64(t0, t0, 32); + tcg_gen_trunc_i64_reg(dest, t0); + + tcg_temp_free_i64(t0); +#endif save_gpr(ctx, rt, dest); cond_free(&ctx->null_cond); From b49572d3736bebcf0420178e8b694bb6f1a1a3d8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 4 Jan 2018 16:49:29 -0800 Subject: [PATCH 36/43] target/hppa: Implement a pause instruction This is an extension to the base ISA, but we can use this in the kernel idle loop to reduce the host cpu time consumed. Signed-off-by: Richard Henderson --- target/hppa/translate.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 2f8e87bba9..96cbd29d4d 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2826,9 +2826,45 @@ static DisasJumpType trans_ds(DisasContext *ctx, uint32_t insn, return nullify_end(ctx, DISAS_NEXT); } +#ifndef CONFIG_USER_ONLY +/* These are QEMU extensions and are nops in the real architecture: + * + * or %r10,%r10,%r10 -- idle loop; wait for interrupt + * or %r31,%r31,%r31 -- death loop; offline cpu + * currently implemented as idle. + */ +static DisasJumpType trans_pause(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + TCGv_i32 tmp; + + /* No need to check for supervisor, as userland can only pause + until the next timer interrupt. */ + nullify_over(ctx); + + /* Advance the instruction queue. */ + copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b); + copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var); + nullify_set(ctx, 0); + + /* Tell the qemu main loop to halt until this cpu has work. */ + tmp = tcg_const_i32(1); + tcg_gen_st_i32(tmp, cpu_env, -offsetof(HPPACPU, env) + + offsetof(CPUState, halted)); + tcg_temp_free_i32(tmp); + gen_excp_1(EXCP_HALTED); + + return nullify_end(ctx, DISAS_NORETURN); +} +#endif + static const DisasInsn table_arith_log[] = { { 0x08000240u, 0xfc00ffffu, trans_nop }, /* or x,y,0 */ { 0x08000240u, 0xffe0ffe0u, trans_copy }, /* or x,0,t */ +#ifndef CONFIG_USER_ONLY + { 0x094a024au, 0xffffffffu, trans_pause }, /* or r10,r10,r10 */ + { 0x0bff025fu, 0xffffffffu, trans_pause }, /* or r31,r31,r31 */ +#endif { 0x08000000u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_andc_reg }, { 0x08000200u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_and_reg }, { 0x08000240u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_or_reg }, From 95412a612867ea200b8f5285a4de3c059b873a55 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 6 Jan 2018 15:30:45 -0800 Subject: [PATCH 37/43] target/hppa: Implement STWA Signed-off-by: Richard Henderson --- target/hppa/translate.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 96cbd29d4d..276ddfaa7d 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -3108,6 +3108,22 @@ static DisasJumpType trans_ldwa_idx_x(DisasContext *ctx, uint32_t insn, ctx->mmu_idx = hold_mmu_idx; return ret; } + +static DisasJumpType trans_stwa_idx_i(DisasContext *ctx, uint32_t insn, + const DisasInsn *di) +{ + int hold_mmu_idx = ctx->mmu_idx; + DisasJumpType ret; + + CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); + + /* ??? needs fixing for hppa64 -- ldda does not follow the same + format wrt the sub-opcode in bits 6:9. */ + ctx->mmu_idx = MMU_PHYS_IDX; + ret = trans_st_idx_i(ctx, insn, di); + ctx->mmu_idx = hold_mmu_idx; + return ret; +} #endif static const DisasInsn table_index_mem[] = { @@ -3117,8 +3133,9 @@ static const DisasInsn table_index_mem[] = { { 0x0c0001c0u, 0xfc0003c0, trans_ldcw }, { 0x0c001300u, 0xfc0013c0, trans_stby }, #ifndef CONFIG_USER_ONLY - { 0x0c001180u, 0xfc00d3c0, trans_ldwa_idx_i }, /* LDWA, im */ { 0x0c000180u, 0xfc00d3c0, trans_ldwa_idx_x }, /* LDWA, rx */ + { 0x0c001180u, 0xfc00d3c0, trans_ldwa_idx_i }, /* LDWA, im */ + { 0x0c001380u, 0xfc00d3c0, trans_stwa_idx_i }, /* STWA, im */ #endif }; From 7b93dab51e929d7c2878cb5ad92b4419e3318e73 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 6 Jan 2018 16:02:27 -0800 Subject: [PATCH 38/43] target/hppa: Enable MTTCG Signed-off-by: Richard Henderson --- configure | 1 + target/hppa/cpu.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/configure b/configure index 96dee6572c..302fdc92ff 100755 --- a/configure +++ b/configure @@ -6555,6 +6555,7 @@ case "$target_name" in cris) ;; hppa) + mttcg="yes" ;; lm32) ;; diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 70af823a15..7640c81221 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -42,6 +42,12 @@ #define TARGET_PHYS_ADDR_SPACE_BITS 32 #endif +/* PA-RISC 1.x processors have a strong memory model. */ +/* ??? While we do not yet implement PA-RISC 2.0, those processors have + a weak memory model, but with TLB bits that force ordering on a per-page + basis. It's probably easier to fall back to a strong memory model. */ +#define TCG_GUEST_DEFAULT_MO TCG_MO_ALL + #define CPUArchState struct CPUHPPAState #include "exec/cpu-defs.h" From a72bd606ca9754e2d2aecf75acd3c27564ad4fe0 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 8 Oct 2017 16:47:27 -0400 Subject: [PATCH 39/43] hw/hppa: Implement DINO system board Now that we have the prerequisites in target/hppa/, implement the hardware for a PA7100LC. This also enables build for hppa-softmmu. Signed-off-by: Helge Deller [rth: Since it is all new code, squashed all branch development withing hw/hppa/ to a single patch.] Signed-off-by: Richard Henderson --- Makefile.objs | 1 + default-configs/hppa-softmmu.mak | 14 + hw/hppa/Makefile.objs | 2 +- hw/hppa/dino.c | 518 +++++++++++++++++++++++++++++++ hw/hppa/hppa_hardware.h | 40 +++ hw/hppa/hppa_sys.h | 24 ++ hw/hppa/machine.c | 247 ++++++++++++++- hw/hppa/pci.c | 90 ++++++ hw/hppa/trace-events | 4 + 9 files changed, 938 insertions(+), 2 deletions(-) create mode 100644 default-configs/hppa-softmmu.mak create mode 100644 hw/hppa/dino.c create mode 100644 hw/hppa/hppa_hardware.h create mode 100644 hw/hppa/hppa_sys.h create mode 100644 hw/hppa/pci.c create mode 100644 hw/hppa/trace-events diff --git a/Makefile.objs b/Makefile.objs index 323ef12384..2efba6d768 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -156,6 +156,7 @@ trace-events-subdirs += hw/vfio trace-events-subdirs += hw/acpi trace-events-subdirs += hw/arm trace-events-subdirs += hw/alpha +trace-events-subdirs += hw/hppa trace-events-subdirs += hw/xen trace-events-subdirs += hw/ide trace-events-subdirs += ui diff --git a/default-configs/hppa-softmmu.mak b/default-configs/hppa-softmmu.mak new file mode 100644 index 0000000000..013e5f046f --- /dev/null +++ b/default-configs/hppa-softmmu.mak @@ -0,0 +1,14 @@ +include pci.mak +include usb.mak +CONFIG_SERIAL=y +CONFIG_SERIAL_ISA=y +CONFIG_ISA_BUS=y +CONFIG_I8259=y +CONFIG_VIRTIO_PCI=$(CONFIG_PCI) +CONFIG_VIRTIO=y +CONFIG_E1000_PCI=y +CONFIG_IDE_ISA=y +CONFIG_IDE_CMD646=y +# CONFIG_IDE_MMIO=y +CONFIG_VIRTIO_VGA=y +CONFIG_MC146818RTC=y diff --git a/hw/hppa/Makefile.objs b/hw/hppa/Makefile.objs index 46b2ae18de..bef241ed25 100644 --- a/hw/hppa/Makefile.objs +++ b/hw/hppa/Makefile.objs @@ -1 +1 @@ -obj-y += machine.o +obj-y += machine.o pci.o dino.o diff --git a/hw/hppa/dino.c b/hw/hppa/dino.c new file mode 100644 index 0000000000..15aefde09c --- /dev/null +++ b/hw/hppa/dino.c @@ -0,0 +1,518 @@ +/* + * HP-PARISC Dino PCI chipset emulation. + * + * (C) 2017 by Helge Deller + * + * This work is licensed under the GNU GPL license version 2 or later. + * + * Documentation available at: + * https://parisc.wiki.kernel.org/images-parisc/9/91/Dino_ers.pdf + * https://parisc.wiki.kernel.org/images-parisc/7/70/Dino_3_1_Errata.pdf + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "cpu.h" +#include "hw/hw.h" +#include "hw/devices.h" +#include "sysemu/sysemu.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_bus.h" +#include "hppa_sys.h" +#include "exec/address-spaces.h" + + +#define TYPE_DINO_PCI_HOST_BRIDGE "dino-pcihost" + +#define DINO_IAR0 0x004 +#define DINO_IODC 0x008 +#define DINO_IRR0 0x00C /* RO */ +#define DINO_IAR1 0x010 +#define DINO_IRR1 0x014 /* RO */ +#define DINO_IMR 0x018 +#define DINO_IPR 0x01C +#define DINO_TOC_ADDR 0x020 +#define DINO_ICR 0x024 +#define DINO_ILR 0x028 /* RO */ +#define DINO_IO_COMMAND 0x030 /* WO */ +#define DINO_IO_STATUS 0x034 /* RO */ +#define DINO_IO_CONTROL 0x038 +#define DINO_IO_GSC_ERR_RESP 0x040 /* RO */ +#define DINO_IO_ERR_INFO 0x044 /* RO */ +#define DINO_IO_PCI_ERR_RESP 0x048 /* RO */ +#define DINO_IO_FBB_EN 0x05c +#define DINO_IO_ADDR_EN 0x060 +#define DINO_PCI_CONFIG_ADDR 0x064 +#define DINO_PCI_CONFIG_DATA 0x068 +#define DINO_PCI_IO_DATA 0x06c +#define DINO_PCI_MEM_DATA 0x070 /* Dino 3.x only */ +#define DINO_GSC2X_CONFIG 0x7b4 /* RO */ +#define DINO_GMASK 0x800 +#define DINO_PAMR 0x804 +#define DINO_PAPR 0x808 +#define DINO_DAMODE 0x80c +#define DINO_PCICMD 0x810 +#define DINO_PCISTS 0x814 /* R/WC */ +#define DINO_MLTIM 0x81c +#define DINO_BRDG_FEAT 0x820 +#define DINO_PCIROR 0x824 +#define DINO_PCIWOR 0x828 +#define DINO_TLTIM 0x830 + +#define DINO_IRQS 11 /* bits 0-10 are architected */ +#define DINO_IRR_MASK 0x5ff /* only 10 bits are implemented */ +#define DINO_LOCAL_IRQS (DINO_IRQS + 1) +#define DINO_MASK_IRQ(x) (1 << (x)) + +#define PCIINTA 0x001 +#define PCIINTB 0x002 +#define PCIINTC 0x004 +#define PCIINTD 0x008 +#define PCIINTE 0x010 +#define PCIINTF 0x020 +#define GSCEXTINT 0x040 +/* #define xxx 0x080 - bit 7 is "default" */ +/* #define xxx 0x100 - bit 8 not used */ +/* #define xxx 0x200 - bit 9 not used */ +#define RS232INT 0x400 + +#define DINO_MEM_CHUNK_SIZE (8 * 1024 * 1024) /* 8MB */ + +#define DINO_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(DinoState, (obj), TYPE_DINO_PCI_HOST_BRIDGE) + +typedef struct DinoState { + PCIHostState parent_obj; + + /* PCI_CONFIG_ADDR is parent_obj.config_reg, via pci_host_conf_be_ops, + so that we can map PCI_CONFIG_DATA to pci_host_data_be_ops. */ + + uint32_t iar0; + uint32_t iar1; + uint32_t imr; + uint32_t ipr; + uint32_t icr; + uint32_t ilr; + uint32_t io_addr_en; + uint32_t io_control; + + MemoryRegion this_mem; + MemoryRegion pci_mem; + MemoryRegion pci_mem_alias[32]; + + AddressSpace bm_as; + MemoryRegion bm; + MemoryRegion bm_ram_alias; + MemoryRegion bm_pci_alias; + + MemoryRegion cpu0_eir_mem; +} DinoState; + +/* + * Dino can forward memory accesses from the CPU in the range between + * 0xf0800000 and 0xff000000 to the PCI bus. + */ +static void gsc_to_pci_forwarding(DinoState *s) +{ + uint32_t io_addr_en, tmp; + int enabled, i; + + tmp = extract32(s->io_control, 7, 2); + enabled = (tmp == 0x01); + io_addr_en = s->io_addr_en; + + memory_region_transaction_begin(); + for (i = 1; i < 31; i++) { + MemoryRegion *mem = &s->pci_mem_alias[i]; + if (enabled && (io_addr_en & (1U << i))) { + if (!memory_region_is_mapped(mem)) { + uint32_t addr = 0xf0000000 + i * DINO_MEM_CHUNK_SIZE; + memory_region_add_subregion(get_system_memory(), addr, mem); + } + } else if (memory_region_is_mapped(mem)) { + memory_region_del_subregion(get_system_memory(), mem); + } + } + memory_region_transaction_commit(); +} + +static bool dino_chip_mem_valid(void *opaque, hwaddr addr, + unsigned size, bool is_write) +{ + switch (addr) { + case DINO_IAR0: + case DINO_IAR1: + case DINO_IRR0: + case DINO_IRR1: + case DINO_IMR: + case DINO_IPR: + case DINO_ICR: + case DINO_ILR: + case DINO_IO_CONTROL: + case DINO_IO_ADDR_EN: + case DINO_PCI_IO_DATA: + return true; + case DINO_PCI_IO_DATA + 2: + return size <= 2; + case DINO_PCI_IO_DATA + 1: + case DINO_PCI_IO_DATA + 3: + return size == 1; + } + return false; +} + +static MemTxResult dino_chip_read_with_attrs(void *opaque, hwaddr addr, + uint64_t *data, unsigned size, + MemTxAttrs attrs) +{ + DinoState *s = opaque; + MemTxResult ret = MEMTX_OK; + AddressSpace *io; + uint16_t ioaddr; + uint32_t val; + + switch (addr) { + case DINO_PCI_IO_DATA ... DINO_PCI_IO_DATA + 3: + /* Read from PCI IO space. */ + io = &address_space_io; + ioaddr = s->parent_obj.config_reg; + switch (size) { + case 1: + val = address_space_ldub(io, ioaddr, attrs, &ret); + break; + case 2: + val = address_space_lduw_be(io, ioaddr, attrs, &ret); + break; + case 4: + val = address_space_ldl_be(io, ioaddr, attrs, &ret); + break; + default: + g_assert_not_reached(); + } + break; + + case DINO_IO_ADDR_EN: + val = s->io_addr_en; + break; + case DINO_IO_CONTROL: + val = s->io_control; + break; + + case DINO_IAR0: + val = s->iar0; + break; + case DINO_IAR1: + val = s->iar1; + break; + case DINO_IMR: + val = s->imr; + break; + case DINO_ICR: + val = s->icr; + break; + case DINO_IPR: + val = s->ipr; + /* Any read to IPR clears the register. */ + s->ipr = 0; + break; + case DINO_ILR: + val = s->ilr; + break; + case DINO_IRR0: + val = s->ilr & s->imr & ~s->icr; + break; + case DINO_IRR1: + val = s->ilr & s->imr & s->icr; + break; + + default: + /* Controlled by dino_chip_mem_valid above. */ + g_assert_not_reached(); + } + + *data = val; + return ret; +} + +static MemTxResult dino_chip_write_with_attrs(void *opaque, hwaddr addr, + uint64_t val, unsigned size, + MemTxAttrs attrs) +{ + DinoState *s = opaque; + AddressSpace *io; + MemTxResult ret; + uint16_t ioaddr; + + switch (addr) { + case DINO_IO_DATA ... DINO_PCI_IO_DATA + 3: + /* Write into PCI IO space. */ + io = &address_space_io; + ioaddr = s->parent_obj.config_reg; + switch (size) { + case 1: + address_space_stb(io, ioaddr, val, attrs, &ret); + break; + case 2: + address_space_stw_be(io, ioaddr, val, attrs, &ret); + break; + case 4: + address_space_stl_be(io, ioaddr, val, attrs, &ret); + break; + default: + g_assert_not_reached(); + } + return ret; + + case DINO_IO_ADDR_EN: + /* Never allow first (=firmware) and last (=Dino) areas. */ + s->io_addr_en = val & 0x7ffffffe; + gsc_to_pci_forwarding(s); + break; + case DINO_IO_CONTROL: + s->io_control = val; + gsc_to_pci_forwarding(s); + break; + + case DINO_IAR0: + s->iar0 = val; + break; + case DINO_IAR1: + s->iar1 = val; + break; + case DINO_IMR: + s->imr = val; + break; + case DINO_ICR: + s->icr = val; + break; + case DINO_IPR: + /* Any write to IPR clears the register. */ + s->ipr = 0; + break; + + case DINO_ILR: + case DINO_IRR0: + case DINO_IRR1: + /* These registers are read-only. */ + break; + + default: + /* Controlled by dino_chip_mem_valid above. */ + g_assert_not_reached(); + } + return MEMTX_OK; +} + +static const MemoryRegionOps dino_chip_ops = { + .read_with_attrs = dino_chip_read_with_attrs, + .write_with_attrs = dino_chip_write_with_attrs, + .endianness = DEVICE_BIG_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + .accepts = dino_chip_mem_valid, + }, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, +}; + +static const VMStateDescription vmstate_dino = { + .name = "Dino", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(iar0, DinoState), + VMSTATE_UINT32(iar1, DinoState), + VMSTATE_UINT32(imr, DinoState), + VMSTATE_UINT32(ipr, DinoState), + VMSTATE_UINT32(icr, DinoState), + VMSTATE_UINT32(ilr, DinoState), + VMSTATE_UINT32(io_addr_en, DinoState), + VMSTATE_UINT32(io_control, DinoState), + VMSTATE_END_OF_LIST() + } +}; + + +/* Unlike pci_config_data_le_ops, no check of high bit set in config_reg. */ + +static uint64_t dino_config_data_read(void *opaque, hwaddr addr, unsigned len) +{ + PCIHostState *s = opaque; + return pci_data_read(s->bus, s->config_reg | (addr & 3), len); +} + +static void dino_config_data_write(void *opaque, hwaddr addr, + uint64_t val, unsigned len) +{ + PCIHostState *s = opaque; + pci_data_write(s->bus, s->config_reg | (addr & 3), val, len); +} + +static const MemoryRegionOps dino_config_data_ops = { + .read = dino_config_data_read, + .write = dino_config_data_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static AddressSpace *dino_pcihost_set_iommu(PCIBus *bus, void *opaque, + int devfn) +{ + DinoState *s = opaque; + + return &s->bm_as; +} + +/* + * Dino interrupts are connected as shown on Page 78, Table 23 + * (Little-endian bit numbers) + * 0 PCI INTA + * 1 PCI INTB + * 2 PCI INTC + * 3 PCI INTD + * 4 PCI INTE + * 5 PCI INTF + * 6 GSC External Interrupt + * 7 Bus Error for "less than fatal" mode + * 8 PS2 + * 9 Unused + * 10 RS232 + */ + +static void dino_set_irq(void *opaque, int irq, int level) +{ + DinoState *s = opaque; + uint32_t bit = 1u << irq; + uint32_t old_ilr = s->ilr; + + if (level) { + uint32_t ena = bit & ~old_ilr; + s->ipr |= ena; + s->ilr = old_ilr | bit; + if (ena & s->imr) { + uint32_t iar = (ena & s->icr ? s->iar1 : s->iar0); + stl_be_phys(&address_space_memory, iar & -32, iar & 31); + } + } else { + s->ilr = old_ilr & ~bit; + } +} + +static int dino_pci_map_irq(PCIDevice *d, int irq_num) +{ + int slot = d->devfn >> 3; + int local_irq; + + assert(irq_num >= 0 && irq_num <= 3); + + local_irq = slot & 0x03; + + return local_irq; +} + +static void dino_set_timer_irq(void *opaque, int irq, int level) +{ + /* ??? Not connected. */ +} + +static void dino_set_serial_irq(void *opaque, int irq, int level) +{ + dino_set_irq(opaque, 10, level); +} + +PCIBus *dino_init(MemoryRegion *addr_space, + qemu_irq *p_rtc_irq, qemu_irq *p_ser_irq) +{ + DeviceState *dev; + DinoState *s; + PCIBus *b; + int i; + + dev = qdev_create(NULL, TYPE_DINO_PCI_HOST_BRIDGE); + s = DINO_PCI_HOST_BRIDGE(dev); + + /* Dino PCI access from main memory. */ + memory_region_init_io(&s->this_mem, OBJECT(s), &dino_chip_ops, + s, "dino", 4096); + memory_region_add_subregion(addr_space, DINO_HPA, &s->this_mem); + + /* Dino PCI config. */ + memory_region_init_io(&s->parent_obj.conf_mem, OBJECT(&s->parent_obj), + &pci_host_conf_be_ops, dev, "pci-conf-idx", 4); + memory_region_init_io(&s->parent_obj.data_mem, OBJECT(&s->parent_obj), + &dino_config_data_ops, dev, "pci-conf-data", 4); + memory_region_add_subregion(&s->this_mem, DINO_PCI_CONFIG_ADDR, + &s->parent_obj.conf_mem); + memory_region_add_subregion(&s->this_mem, DINO_CONFIG_DATA, + &s->parent_obj.data_mem); + + /* Dino PCI bus memory. */ + memory_region_init(&s->pci_mem, OBJECT(s), "pci-memory", 1ull << 32); + + b = pci_register_root_bus(dev, "pci", dino_set_irq, dino_pci_map_irq, s, + &s->pci_mem, get_system_io(), + PCI_DEVFN(0, 0), 32, TYPE_PCI_BUS); + s->parent_obj.bus = b; + qdev_init_nofail(dev); + + /* Set up windows into PCI bus memory. */ + for (i = 1; i < 31; i++) { + uint32_t addr = 0xf0000000 + i * DINO_MEM_CHUNK_SIZE; + char *name = g_strdup_printf("PCI Outbound Window %d", i); + memory_region_init_alias(&s->pci_mem_alias[i], OBJECT(s), + name, &s->pci_mem, addr, + DINO_MEM_CHUNK_SIZE); + } + + /* Set up PCI view of memory: Bus master address space. */ + memory_region_init(&s->bm, OBJECT(s), "bm-dino", 1ull << 32); + memory_region_init_alias(&s->bm_ram_alias, OBJECT(s), + "bm-system", addr_space, 0, + 0xf0000000 + DINO_MEM_CHUNK_SIZE); + memory_region_init_alias(&s->bm_pci_alias, OBJECT(s), + "bm-pci", &s->pci_mem, + 0xf0000000 + DINO_MEM_CHUNK_SIZE, + 31 * DINO_MEM_CHUNK_SIZE); + memory_region_add_subregion(&s->bm, 0, + &s->bm_ram_alias); + memory_region_add_subregion(&s->bm, + 0xf0000000 + DINO_MEM_CHUNK_SIZE, + &s->bm_pci_alias); + address_space_init(&s->bm_as, &s->bm, "pci-bm"); + pci_setup_iommu(b, dino_pcihost_set_iommu, s); + + *p_rtc_irq = qemu_allocate_irq(dino_set_timer_irq, s, 0); + *p_ser_irq = qemu_allocate_irq(dino_set_serial_irq, s, 0); + + return b; +} + +static int dino_pcihost_init(SysBusDevice *dev) +{ + return 0; +} + +static void dino_pcihost_class_init(ObjectClass *klass, void *data) +{ + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = dino_pcihost_init; + dc->vmsd = &vmstate_dino; +} + +static const TypeInfo dino_pcihost_info = { + .name = TYPE_DINO_PCI_HOST_BRIDGE, + .parent = TYPE_PCI_HOST_BRIDGE, + .instance_size = sizeof(DinoState), + .class_init = dino_pcihost_class_init, +}; + +static void dino_register_types(void) +{ + type_register_static(&dino_pcihost_info); +} + +type_init(dino_register_types) diff --git a/hw/hppa/hppa_hardware.h b/hw/hppa/hppa_hardware.h new file mode 100644 index 0000000000..2c61b1f77c --- /dev/null +++ b/hw/hppa/hppa_hardware.h @@ -0,0 +1,40 @@ +/* HPPA cores and system support chips. */ + +#define FIRMWARE_START 0xf0000000 +#define FIRMWARE_END 0xf0800000 + +#define DEVICE_HPA_LEN 0x00100000 + +#define GSC_HPA 0xffc00000 +#define DINO_HPA 0xfff80000 +#define DINO_UART_HPA 0xfff83000 +#define DINO_UART_BASE 0xfff83800 +#define DINO_SCSI_HPA 0xfff8c000 +#define LASI_HPA 0xffd00000 +#define LASI_UART_HPA 0xffd05000 +#define LASI_SCSI_HPA 0xffd06000 +#define LASI_LAN_HPA 0xffd07000 +#define LASI_LPT_HPA 0xffd02000 +#define LASI_AUDIO_HPA 0xffd04000 +#define LASI_PS2KBD_HPA 0xffd08000 +#define LASI_PS2MOU_HPA 0xffd08100 +#define LASI_GFX_HPA 0xf8000000 +#define CPU_HPA 0xfff10000 +#define MEMORY_HPA 0xfffbf000 + +#define PCI_HPA DINO_HPA /* PCI bus */ +#define IDE_HPA 0xf9000000 /* Boot disc controller */ + +/* offsets to DINO HPA: */ +#define DINO_PCI_ADDR 0x064 +#define DINO_CONFIG_DATA 0x068 +#define DINO_IO_DATA 0x06c + +#define PORT_PCI_CMD (PCI_HPA + DINO_PCI_ADDR) +#define PORT_PCI_DATA (PCI_HPA + DINO_CONFIG_DATA) + +#define PORT_SERIAL1 (DINO_UART_HPA + 0x800) +#define PORT_SERIAL2 (LASI_UART_HPA + 0x800) + +#define HPPA_MAX_CPUS 32 /* max. number of SMP CPUs */ +#define CPU_CLOCK_MHZ 250 /* emulate a 250 MHz CPU */ diff --git a/hw/hppa/hppa_sys.h b/hw/hppa/hppa_sys.h new file mode 100644 index 0000000000..a182d1f34e --- /dev/null +++ b/hw/hppa/hppa_sys.h @@ -0,0 +1,24 @@ +/* HPPA cores and system support chips. */ + +#ifndef HW_HPPA_SYS_H +#define HW_HPPA_SYS_H + +#include "target/hppa/cpu-qom.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_host.h" +#include "hw/ide.h" +#include "hw/i386/pc.h" +#include "hw/irq.h" + +#include "hw/hppa/hppa_hardware.h" + +PCIBus *dino_init(MemoryRegion *, qemu_irq *, qemu_irq *); + +#define TYPE_DINO_PCI_HOST_BRIDGE "dino-pcihost" + +/* hppa_pci.c. */ +extern const MemoryRegionOps hppa_pci_ignore_ops; +extern const MemoryRegionOps hppa_pci_conf1_ops; +extern const MemoryRegionOps hppa_pci_iack_ops; + +#endif diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 79958da18f..afd3867313 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -16,20 +16,265 @@ #include "hw/ide.h" #include "hw/timer/i8254.h" #include "hw/char/serial.h" +#include "hw/hppa/hppa_sys.h" #include "qemu/cutils.h" #include "qapi/error.h" +#define MAX_IDE_BUS 2 + +static ISABus *hppa_isa_bus(void) +{ + ISABus *isa_bus; + qemu_irq *isa_irqs; + MemoryRegion *isa_region; + + isa_region = g_new(MemoryRegion, 1); + memory_region_init_io(isa_region, NULL, &hppa_pci_ignore_ops, + NULL, "isa-io", 0x800); + memory_region_add_subregion(get_system_memory(), IDE_HPA, + isa_region); + + isa_bus = isa_bus_new(NULL, get_system_memory(), isa_region, + &error_abort); + isa_irqs = i8259_init(isa_bus, + /* qemu_allocate_irq(dino_set_isa_irq, s, 0)); */ + NULL); + isa_bus_irqs(isa_bus, isa_irqs); + + return isa_bus; +} + +static uint64_t cpu_hppa_to_phys(void *opaque, uint64_t addr) +{ + addr &= (0x10000000 - 1); + return addr; +} + +static HPPACPU *cpu[HPPA_MAX_CPUS]; +static uint64_t firmware_entry; static void machine_hppa_init(MachineState *machine) { + const char *kernel_filename = machine->kernel_filename; + const char *kernel_cmdline = machine->kernel_cmdline; + const char *initrd_filename = machine->initrd_filename; + PCIBus *pci_bus; + ISABus *isa_bus; + qemu_irq rtc_irq, serial_irq; + char *firmware_filename; + uint64_t firmware_low, firmware_high; + long size; + uint64_t kernel_entry = 0, kernel_low, kernel_high; + MemoryRegion *addr_space = get_system_memory(); + MemoryRegion *rom_region; + MemoryRegion *ram_region; + MemoryRegion *cpu_region; + long i; + + ram_size = machine->ram_size; + + /* Create CPUs. */ + for (i = 0; i < smp_cpus; i++) { + cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type)); + + cpu_region = g_new(MemoryRegion, 1); + memory_region_init_io(cpu_region, OBJECT(cpu[i]), &hppa_io_eir_ops, + cpu[i], g_strdup_printf("cpu%ld-io-eir", i), 4); + memory_region_add_subregion(addr_space, CPU_HPA + i * 0x1000, + cpu_region); + } + + /* Limit main memory. */ + if (ram_size > FIRMWARE_START) { + machine->ram_size = ram_size = FIRMWARE_START; + } + + /* Main memory region. */ + ram_region = g_new(MemoryRegion, 1); + memory_region_allocate_system_memory(ram_region, OBJECT(machine), + "ram", ram_size); + memory_region_add_subregion(addr_space, 0, ram_region); + + /* Init Dino (PCI host bus chip). */ + pci_bus = dino_init(addr_space, &rtc_irq, &serial_irq); + assert(pci_bus); + + /* Create ISA bus. */ + isa_bus = hppa_isa_bus(); + assert(isa_bus); + + /* Realtime clock, used by firmware for PDC_TOD call. */ + mc146818_rtc_init(isa_bus, 2000, rtc_irq); + + /* Serial code setup. */ + if (serial_hds[0]) { + uint32_t addr = DINO_UART_HPA + 0x800; + serial_mm_init(addr_space, addr, 0, serial_irq, + 115200, serial_hds[0], DEVICE_BIG_ENDIAN); + fprintf(stderr, "Serial port created at 0x%x\n", addr); + } + + /* SCSI disk setup. */ + lsi53c895a_create(pci_bus); + + /* Network setup. e1000 is good enough, failing Tulip support. */ + for (i = 0; i < nb_nics; i++) { + pci_nic_init_nofail(&nd_table[i], pci_bus, "e1000", NULL); + } + + /* Load firmware. Given that this is not "real" firmware, + but one explicitly written for the emulation, we might as + well load it directly from an ELF image. */ + firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, + bios_name ? bios_name : + "hppa-firmware.img"); + if (firmware_filename == NULL) { + error_report("no firmware provided"); + exit(1); + } + + size = load_elf(firmware_filename, NULL, + NULL, &firmware_entry, &firmware_low, &firmware_high, + true, EM_PARISC, 0, 0); + + /* Unfortunately, load_elf sign-extends reading elf32. */ + firmware_entry = (target_ureg)firmware_entry; + firmware_low = (target_ureg)firmware_low; + firmware_high = (target_ureg)firmware_high; + + if (size < 0) { + error_report("could not load firmware '%s'", firmware_filename); + exit(1); + } + fprintf(stderr, "Firmware loaded at 0x%08" PRIx64 "-0x%08" PRIx64 + ", entry at 0x%08" PRIx64 ".\n", + firmware_low, firmware_high, firmware_entry); + if (firmware_low < ram_size || firmware_high >= FIRMWARE_END) { + error_report("Firmware overlaps with memory or IO space"); + exit(1); + } + g_free(firmware_filename); + + rom_region = g_new(MemoryRegion, 1); + memory_region_allocate_system_memory(rom_region, OBJECT(machine), + "firmware", + (FIRMWARE_END - FIRMWARE_START)); + memory_region_add_subregion(addr_space, FIRMWARE_START, rom_region); + + /* Load kernel */ + if (kernel_filename) { + fprintf(stderr, "LOADING kernel '%s'\n", kernel_filename); + size = load_elf(kernel_filename, &cpu_hppa_to_phys, + NULL, &kernel_entry, &kernel_low, &kernel_high, + true, EM_PARISC, 0, 0); + + /* Unfortunately, load_elf sign-extends reading elf32. */ + kernel_entry = (target_ureg) cpu_hppa_to_phys(NULL, kernel_entry); + kernel_low = (target_ureg)kernel_low; + kernel_high = (target_ureg)kernel_high; + + if (size < 0) { + error_report("could not load kernel '%s'", kernel_filename); + exit(1); + } + + fprintf(stderr, "Kernel loaded at 0x%08" PRIx64 "-0x%08" PRIx64 + ", entry at 0x%08" PRIx64 ", size %ld kB.\n", + kernel_low, kernel_high, kernel_entry, size / 1024); + + if (kernel_cmdline) { + cpu[0]->env.gr[24] = 0x4000; + pstrcpy_targphys("cmdline", cpu[0]->env.gr[24], + TARGET_PAGE_SIZE, kernel_cmdline); + } + + if (initrd_filename) { + ram_addr_t initrd_base; + long initrd_size; + + initrd_size = get_image_size(initrd_filename); + if (initrd_size < 0) { + error_report("could not load initial ram disk '%s'", + initrd_filename); + exit(1); + } + + /* Load the initrd image high in memory. + Mirror the algorithm used by palo: + (1) Due to sign-extension problems and PDC, + put the initrd no higher than 1G. + (2) Reserve 64k for stack. */ + initrd_base = MIN(ram_size, 1024 * 1024 * 1024); + initrd_base = initrd_base - 64 * 1024; + initrd_base = (initrd_base - initrd_size) & TARGET_PAGE_MASK; + + if (initrd_base < kernel_high) { + error_report("kernel and initial ram disk too large!"); + exit(1); + } + + load_image_targphys(initrd_filename, initrd_base, initrd_size); + cpu[0]->env.gr[23] = initrd_base; + cpu[0]->env.gr[22] = initrd_base + initrd_size; + } + } + + if (!kernel_entry) { + /* When booting via firmware, tell firmware if we want interactive + * mode (kernel_entry=1), and to boot from CD (gr[24]='d') + * or hard disc * (gr[24]='c'). + */ + kernel_entry = boot_menu ? 1 : 0; + cpu[0]->env.gr[24] = machine->boot_order[0]; + } + + /* We jump to the firmware entry routine and pass the + * various parameters in registers. After firmware initialization, + * firmware will start the Linux kernel with ramdisk and cmdline. + */ + cpu[0]->env.gr[26] = ram_size; + cpu[0]->env.gr[25] = kernel_entry; + + /* tell firmware how many SMP CPUs to present in inventory table */ + cpu[0]->env.gr[21] = smp_cpus; } +static void hppa_machine_reset(void) +{ + int i; + + qemu_devices_reset(); + + /* Start all CPUs at the firmware entry point. + * Monarch CPU will initialize firmware, secondary CPUs + * will enter a small idle look and wait for rendevouz. */ + for (i = 0; i < smp_cpus; i++) { + cpu_set_pc(CPU(cpu[i]), firmware_entry); + cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000; + } + + /* already initialized by machine_hppa_init()? */ + if (cpu[0]->env.gr[26] == ram_size) { + return; + } + + cpu[0]->env.gr[26] = ram_size; + cpu[0]->env.gr[25] = 0; /* no firmware boot menu */ + cpu[0]->env.gr[24] = 'c'; + /* gr22/gr23 unused, no initrd while reboot. */ + cpu[0]->env.gr[21] = smp_cpus; +} + + static void machine_hppa_machine_init(MachineClass *mc) { mc->desc = "HPPA generic machine"; + mc->default_cpu_type = TYPE_HPPA_CPU; mc->init = machine_hppa_init; + mc->reset = hppa_machine_reset; mc->block_default_type = IF_SCSI; - mc->max_cpus = 1; + mc->max_cpus = HPPA_MAX_CPUS; + mc->default_cpus = 1; mc->is_default = 1; mc->default_ram_size = 512 * M_BYTE; mc->default_boot_order = "cd"; diff --git a/hw/hppa/pci.c b/hw/hppa/pci.c new file mode 100644 index 0000000000..766420254e --- /dev/null +++ b/hw/hppa/pci.c @@ -0,0 +1,90 @@ +/* + * QEMU HP-PARISC PCI support functions. + * + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "hppa_sys.h" +#include "qemu/log.h" +#include "sysemu/sysemu.h" +#include "trace.h" + + +/* Fallback for unassigned PCI I/O operations. Avoids MCHK. */ + +static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size) +{ + return 0; +} + +static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size) +{ +} + +const MemoryRegionOps hppa_pci_ignore_ops = { + .read = ignore_read, + .write = ignore_write, + .endianness = DEVICE_BIG_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 1, + .max_access_size = 8, + }, +}; + + +/* PCI config space reads/writes, to byte-word addressable memory. */ +static uint64_t bw_conf1_read(void *opaque, hwaddr addr, + unsigned size) +{ + PCIBus *b = opaque; + return pci_data_read(b, addr, size); +} + +static void bw_conf1_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + PCIBus *b = opaque; + pci_data_write(b, addr, val, size); +} + +const MemoryRegionOps hppa_pci_conf1_ops = { + .read = bw_conf1_read, + .write = bw_conf1_write, + .endianness = DEVICE_BIG_ENDIAN, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, +}; + +/* PCI/EISA Interrupt Acknowledge Cycle. */ + +static uint64_t iack_read(void *opaque, hwaddr addr, unsigned size) +{ + return pic_read_irq(isa_pic); +} + +static void special_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + trace_hppa_pci_iack_write(); +} + +const MemoryRegionOps hppa_pci_iack_ops = { + .read = iack_read, + .write = special_write, + .endianness = DEVICE_BIG_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; diff --git a/hw/hppa/trace-events b/hw/hppa/trace-events new file mode 100644 index 0000000000..14c67937e1 --- /dev/null +++ b/hw/hppa/trace-events @@ -0,0 +1,4 @@ +# See docs/devel/tracing.txt for syntax documentation. + +# hw/hppa/pci.c +hppa_pci_iack_write(void) "" From 43ad25643a0656a5a44b146abd72744e41ffe143 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 21 Jan 2018 13:04:45 -0800 Subject: [PATCH 40/43] pc-bios: Add hppa-firmware.img and git submodule Signed-off-by: Richard Henderson --- .gitmodules | 3 +++ Makefile | 3 ++- pc-bios/hppa-firmware.img | Bin 0 -> 461352 bytes roms/seabios-hppa | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) create mode 100755 pc-bios/hppa-firmware.img create mode 160000 roms/seabios-hppa diff --git a/.gitmodules b/.gitmodules index 1500579638..7a8282df46 100644 --- a/.gitmodules +++ b/.gitmodules @@ -40,3 +40,6 @@ [submodule "capstone"] path = capstone url = git://git.qemu.org/capstone.git +[submodule "roms/seabios-hppa"] + path = roms/seabios-hppa + url = git://github.com/hdeller/seabios-hppa.git diff --git a/Makefile b/Makefile index 7073b3d842..7d35ea1a06 100644 --- a/Makefile +++ b/Makefile @@ -661,7 +661,8 @@ s390-ccw.img s390-netboot.img \ spapr-rtas.bin slof.bin skiboot.lid \ palcode-clipper \ u-boot.e500 \ -qemu_vga.ndrv +qemu_vga.ndrv \ +hppa-firmware.img else BLOBS= endif diff --git a/pc-bios/hppa-firmware.img b/pc-bios/hppa-firmware.img new file mode 100755 index 0000000000000000000000000000000000000000..ae833437a73cb0955491b95f03cd42132d8d2e9c GIT binary patch literal 461352 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 z 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 S^VmU`127x{vmpe?J_Z0sO;TF` literal 0 HcmV?d00001 diff --git a/roms/seabios-hppa b/roms/seabios-hppa new file mode 160000 index 0000000000..8fa4ca9935 --- /dev/null +++ b/roms/seabios-hppa @@ -0,0 +1 @@ +Subproject commit 8fa4ca9935669414a824ecda24f6e70c36e8dc94 From 61461802bb535f7a004d85c181bf2061121924bf Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 21 Jan 2018 14:05:03 -0800 Subject: [PATCH 41/43] hw/hppa: Add MAINTAINERS entry Signed-off-by: Richard Henderson --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index fe39b30450..f8deaf638c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -133,6 +133,7 @@ HPPA (PA-RISC) M: Richard Henderson S: Maintained F: target/hppa/ +F: hw/hppa/ F: disas/hppa.c LM32 From fe0a69cca56e115f7dc2800a91ef0c8be69828b6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 24 Jan 2018 14:24:53 -0800 Subject: [PATCH 42/43] target/hppa: Fix 32-bit operand masks for 0E FCVT We masked the wrong bits, which prevented some of the 32-bit R registers. E.g. "fcnvxf,sgl,sgl fr22R,fr6R". Signed-off-by: Richard Henderson --- target/hppa/translate.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 276ddfaa7d..842f74ea5b 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -4381,34 +4381,34 @@ static const DisasInsn table_float_0e[] = { /* floating point class one */ /* float/float */ { 0x38000a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_s }, - { 0x38002200, 0xfc1fffc0, FOP_DEW = gen_helper_fcnv_s_d }, + { 0x38002200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_d }, /* int/float */ - { 0x38008200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_w_s }, + { 0x38008200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_w_s }, { 0x38008a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_dw_s }, { 0x3800a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_w_d }, { 0x3800aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_dw_d }, /* float/int */ - { 0x38010200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_s_w }, + { 0x38010200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_s_w }, { 0x38010a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_w }, { 0x38012200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_dw }, { 0x38012a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_dw }, /* float/int truncate */ - { 0x38018200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_t_s_w }, + { 0x38018200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_t_s_w }, { 0x38018a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_w }, { 0x3801a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_dw }, { 0x3801aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_dw }, /* uint/float */ - { 0x38028200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_uw_s }, + { 0x38028200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_uw_s }, { 0x38028a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_udw_s }, { 0x3802a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_uw_d }, { 0x3802aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_udw_d }, /* float/uint */ - { 0x38030200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_s_uw }, + { 0x38030200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_s_uw }, { 0x38030a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_uw }, { 0x38032200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_udw }, { 0x38032a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_udw }, /* float/uint truncate */ - { 0x38038200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_t_s_uw }, + { 0x38038200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_t_s_uw }, { 0x38038a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_uw }, { 0x3803a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_udw }, { 0x3803aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_udw }, From eed142195c95a6c50545fa7a28e725d780ab9636 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 24 Jan 2018 15:03:25 -0800 Subject: [PATCH 43/43] target/hppa: Implement PROBE for system mode Signed-off-by: Richard Henderson --- target/hppa/helper.h | 3 +-- target/hppa/op_helper.c | 34 +++++++++++++++++++++++----------- target/hppa/translate.c | 20 ++++++++++++++++---- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/target/hppa/helper.h b/target/hppa/helper.h index 0e569cba31..bfe0dd1db1 100644 --- a/target/hppa/helper.h +++ b/target/hppa/helper.h @@ -17,8 +17,7 @@ DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, env, tl, tr) DEF_HELPER_FLAGS_3(stby_e, TCG_CALL_NO_WG, void, env, tl, tr) DEF_HELPER_FLAGS_3(stby_e_parallel, TCG_CALL_NO_WG, void, env, tl, tr) -DEF_HELPER_FLAGS_1(probe_r, TCG_CALL_NO_RWG_SE, tr, tl) -DEF_HELPER_FLAGS_1(probe_w, TCG_CALL_NO_RWG_SE, tr, tl) +DEF_HELPER_FLAGS_4(probe, TCG_CALL_NO_WG, tr, env, tl, i32, i32) DEF_HELPER_FLAGS_1(loaded_fr0, TCG_CALL_NO_RWG, void, env) diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 0daa7511f4..4ee936bf86 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -160,21 +160,33 @@ void HELPER(stby_e_parallel)(CPUHPPAState *env, target_ulong addr, do_stby_e(env, addr, val, true); } -target_ureg HELPER(probe_r)(target_ulong addr) +target_ureg HELPER(probe)(CPUHPPAState *env, target_ulong addr, + uint32_t level, uint32_t want) { #ifdef CONFIG_USER_ONLY - return page_check_range(addr, 1, PAGE_READ); + return page_check_range(addr, 1, want); #else - return 1; /* FIXME */ -#endif -} + int prot, excp; + hwaddr phys; -target_ureg HELPER(probe_w)(target_ulong addr) -{ -#ifdef CONFIG_USER_ONLY - return page_check_range(addr, 1, PAGE_WRITE); -#else - return 1; /* FIXME */ + /* Fail if the requested privilege level is higher than current. */ + if (level < (env->iaoq_f & 3)) { + return 0; + } + + excp = hppa_get_physical_address(env, addr, level, 0, &phys, &prot); + if (excp >= 0) { + if (env->psw & PSW_Q) { + /* ??? Needs tweaking for hppa64. */ + env->cr[CR_IOR] = addr; + env->cr[CR_ISR] = addr >> 32; + } + if (excp == EXCP_DTLB_MISS) { + excp = EXCP_NA_DTLB_MISS; + } + hppa_dynamic_excp(env, excp, GETPC()); + } + return (want & prot) != 0; #endif } diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 842f74ea5b..6499b392f9 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -2380,21 +2380,33 @@ static DisasJumpType trans_probe(DisasContext *ctx, uint32_t insn, { unsigned rt = extract32(insn, 0, 5); unsigned sp = extract32(insn, 14, 2); + unsigned rr = extract32(insn, 16, 5); unsigned rb = extract32(insn, 21, 5); unsigned is_write = extract32(insn, 6, 1); + unsigned is_imm = extract32(insn, 13, 1); TCGv_reg dest, ofs; + TCGv_i32 level, want; TCGv_tl addr; nullify_over(ctx); - /* ??? Do something with priv level operand. */ dest = dest_gpr(ctx, rt); form_gva(ctx, &addr, &ofs, rb, 0, 0, 0, sp, 0, false); - if (is_write) { - gen_helper_probe_w(dest, addr); + + if (is_imm) { + level = tcg_const_i32(extract32(insn, 16, 2)); } else { - gen_helper_probe_r(dest, addr); + level = tcg_temp_new_i32(); + tcg_gen_trunc_reg_i32(level, load_gpr(ctx, rr)); + tcg_gen_andi_i32(level, level, 3); } + want = tcg_const_i32(is_write ? PAGE_WRITE : PAGE_READ); + + gen_helper_probe(dest, cpu_env, addr, level, want); + + tcg_temp_free_i32(want); + tcg_temp_free_i32(level); + save_gpr(ctx, rt, dest); return nullify_end(ctx, DISAS_NEXT); }