Queued openrisc patches
-----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJYoiM/AAoJEK0ScMxN0CebYVwIAIGCLck2AG7mgY377NerD7zj Z8PZ/0Rpx75Hin2JVx/E6haXjBZMYdGhi55RtffmLCVr52kFap8hfwpISPEo0V3Y XGg13lYlsDq+nzOx/YQvsYZg7JKFhu9m3w39ZoFL4YSMPoDgOBMx8dOZ/Oa7i6AQ n006YXVs5rDZhcm36Uwy3e0+gz5Cuzy4u3KsCdRWX5poSWuR0NXV/Apbhgq7i70l 7c+R3Y+vlv7weWFr2svuIiX7hXt/2pCHH0KLWJoxH2fj/bo9A2DzGSnYhGxNYKu6 cvqpsvolmBdv+yyXyeF3Yj7yldUv7wcTQVviOLbqZgIf7GweNurvUFf64HJs4tU= =wDfr -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/rth/tags/pull-or-20170214' into staging Queued openrisc patches # gpg: Signature made Mon 13 Feb 2017 21:21:03 GMT # gpg: using RSA key 0xAD1270CC4DD0279B # gpg: Good signature from "Richard Henderson <rth7680@gmail.com>" # gpg: aka "Richard Henderson <rth@redhat.com>" # gpg: aka "Richard Henderson <rth@twiddle.net>" # Primary key fingerprint: 9CB1 8DDA F8E8 49AD 2AFC 16A4 AD12 70CC 4DD0 279B * remotes/rth/tags/pull-or-20170214: (24 commits) target/openrisc: Optimize for r0 being zero target/openrisc: Tidy handling of delayed branches target/openrisc: Tidy ppc/npc implementation target/openrisc: Optimize l.jal to next target/openrisc: Fix madd target/openrisc: Implement muld, muldu, macu, msbu target/openrisc: Represent MACHI:MACLO as a single unit target/openrisc: Implement msync target/openrisc: Enable trap, csync, msync, psync for user mode target/openrisc: Set flags on helpers target/openrisc: Use movcond where appropriate target/openrisc: Keep SR_CY and SR_OV in a separate variables target/openrisc: Keep SR_F in a separate variable target/openrisc: Invert the decoding in dec_calc target/openrisc: Put SR[OVE] in TB flags target/openrisc: Streamline arithmetic and OVE target/openrisc: Rationalize immediate extraction target/openrisc: Tidy insn dumping target/openrisc: Implement lwa, swa target/openrisc: Fix exception handling status registers ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
5dae13cd71
6
configure
vendored
6
configure
vendored
@ -5843,7 +5843,7 @@ target_name=$(echo $target | cut -d '-' -f 1)
|
|||||||
target_bigendian="no"
|
target_bigendian="no"
|
||||||
|
|
||||||
case "$target_name" in
|
case "$target_name" in
|
||||||
armeb|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or32|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
|
armeb|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or1k|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
|
||||||
target_bigendian=yes
|
target_bigendian=yes
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@ -5937,7 +5937,7 @@ case "$target_name" in
|
|||||||
;;
|
;;
|
||||||
nios2)
|
nios2)
|
||||||
;;
|
;;
|
||||||
or32)
|
or1k)
|
||||||
TARGET_ARCH=openrisc
|
TARGET_ARCH=openrisc
|
||||||
TARGET_BASE_ARCH=openrisc
|
TARGET_BASE_ARCH=openrisc
|
||||||
;;
|
;;
|
||||||
@ -6145,7 +6145,7 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
|
|||||||
nios2)
|
nios2)
|
||||||
disas_config "NIOS2"
|
disas_config "NIOS2"
|
||||||
;;
|
;;
|
||||||
or32)
|
or1k)
|
||||||
disas_config "OPENRISC"
|
disas_config "OPENRISC"
|
||||||
;;
|
;;
|
||||||
ppc*)
|
ppc*)
|
||||||
|
1
default-configs/or1k-linux-user.mak
Normal file
1
default-configs/or1k-linux-user.mak
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Default configuration for or1k-linux-user
|
4
default-configs/or1k-softmmu.mak
Normal file
4
default-configs/or1k-softmmu.mak
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# Default configuration for or1k-softmmu
|
||||||
|
|
||||||
|
CONFIG_SERIAL=y
|
||||||
|
CONFIG_OPENCORES_ETH=y
|
@ -1 +0,0 @@
|
|||||||
# Default configuration for or32-linux-user
|
|
@ -1,4 +0,0 @@
|
|||||||
# Default configuration for or32-softmmu
|
|
||||||
|
|
||||||
CONFIG_SERIAL=y
|
|
||||||
CONFIG_OPENCORES_ETH=y
|
|
@ -139,10 +139,10 @@ static void openrisc_sim_init(MachineState *machine)
|
|||||||
|
|
||||||
static void openrisc_sim_machine_init(MachineClass *mc)
|
static void openrisc_sim_machine_init(MachineClass *mc)
|
||||||
{
|
{
|
||||||
mc->desc = "or32 simulation";
|
mc->desc = "or1k simulation";
|
||||||
mc->init = openrisc_sim_init;
|
mc->init = openrisc_sim_init;
|
||||||
mc->max_cpus = 1;
|
mc->max_cpus = 1;
|
||||||
mc->is_default = 1;
|
mc->is_default = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_MACHINE("or32-sim", openrisc_sim_machine_init)
|
DEFINE_MACHINE("or1k-sim", openrisc_sim_machine_init)
|
||||||
|
@ -1054,9 +1054,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
|
|||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
(*regs)[i] = tswapreg(env->gpr[i]);
|
(*regs)[i] = tswapreg(env->gpr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
(*regs)[32] = tswapreg(env->pc);
|
(*regs)[32] = tswapreg(env->pc);
|
||||||
(*regs)[33] = tswapreg(env->sr);
|
(*regs)[33] = tswapreg(cpu_get_sr(env));
|
||||||
}
|
}
|
||||||
#define ELF_HWCAP 0
|
#define ELF_HWCAP 0
|
||||||
#define ELF_PLATFORM NULL
|
#define ELF_PLATFORM NULL
|
||||||
|
@ -2574,52 +2574,17 @@ kuser_fail:
|
|||||||
void cpu_loop(CPUOpenRISCState *env)
|
void cpu_loop(CPUOpenRISCState *env)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(openrisc_env_get_cpu(env));
|
CPUState *cs = CPU(openrisc_env_get_cpu(env));
|
||||||
int trapnr, gdbsig;
|
int trapnr;
|
||||||
abi_long ret;
|
abi_long ret;
|
||||||
|
target_siginfo_t info;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
cpu_exec_start(cs);
|
cpu_exec_start(cs);
|
||||||
trapnr = cpu_exec(cs);
|
trapnr = cpu_exec(cs);
|
||||||
cpu_exec_end(cs);
|
cpu_exec_end(cs);
|
||||||
process_queued_cpu_work(cs);
|
process_queued_cpu_work(cs);
|
||||||
gdbsig = 0;
|
|
||||||
|
|
||||||
switch (trapnr) {
|
switch (trapnr) {
|
||||||
case EXCP_RESET:
|
|
||||||
qemu_log_mask(CPU_LOG_INT, "\nReset request, exit, pc is %#x\n", env->pc);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
break;
|
|
||||||
case EXCP_BUSERR:
|
|
||||||
qemu_log_mask(CPU_LOG_INT, "\nBus error, exit, pc is %#x\n", env->pc);
|
|
||||||
gdbsig = TARGET_SIGBUS;
|
|
||||||
break;
|
|
||||||
case EXCP_DPF:
|
|
||||||
case EXCP_IPF:
|
|
||||||
cpu_dump_state(cs, stderr, fprintf, 0);
|
|
||||||
gdbsig = TARGET_SIGSEGV;
|
|
||||||
break;
|
|
||||||
case EXCP_TICK:
|
|
||||||
qemu_log_mask(CPU_LOG_INT, "\nTick time interrupt pc is %#x\n", env->pc);
|
|
||||||
break;
|
|
||||||
case EXCP_ALIGN:
|
|
||||||
qemu_log_mask(CPU_LOG_INT, "\nAlignment pc is %#x\n", env->pc);
|
|
||||||
gdbsig = TARGET_SIGBUS;
|
|
||||||
break;
|
|
||||||
case EXCP_ILLEGAL:
|
|
||||||
qemu_log_mask(CPU_LOG_INT, "\nIllegal instructionpc is %#x\n", env->pc);
|
|
||||||
gdbsig = TARGET_SIGILL;
|
|
||||||
break;
|
|
||||||
case EXCP_INT:
|
|
||||||
qemu_log_mask(CPU_LOG_INT, "\nExternal interruptpc is %#x\n", env->pc);
|
|
||||||
break;
|
|
||||||
case EXCP_DTLBMISS:
|
|
||||||
case EXCP_ITLBMISS:
|
|
||||||
qemu_log_mask(CPU_LOG_INT, "\nTLB miss\n");
|
|
||||||
break;
|
|
||||||
case EXCP_RANGE:
|
|
||||||
qemu_log_mask(CPU_LOG_INT, "\nRange\n");
|
|
||||||
gdbsig = TARGET_SIGSEGV;
|
|
||||||
break;
|
|
||||||
case EXCP_SYSCALL:
|
case EXCP_SYSCALL:
|
||||||
env->pc += 4; /* 0xc00; */
|
env->pc += 4; /* 0xc00; */
|
||||||
ret = do_syscall(env,
|
ret = do_syscall(env,
|
||||||
@ -2636,32 +2601,54 @@ void cpu_loop(CPUOpenRISCState *env)
|
|||||||
env->gpr[11] = ret;
|
env->gpr[11] = ret;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EXCP_DPF:
|
||||||
|
case EXCP_IPF:
|
||||||
|
case EXCP_RANGE:
|
||||||
|
info.si_signo = TARGET_SIGSEGV;
|
||||||
|
info.si_errno = 0;
|
||||||
|
info.si_code = TARGET_SEGV_MAPERR;
|
||||||
|
info._sifields._sigfault._addr = env->pc;
|
||||||
|
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||||
|
break;
|
||||||
|
case EXCP_ALIGN:
|
||||||
|
info.si_signo = TARGET_SIGBUS;
|
||||||
|
info.si_errno = 0;
|
||||||
|
info.si_code = TARGET_BUS_ADRALN;
|
||||||
|
info._sifields._sigfault._addr = env->pc;
|
||||||
|
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||||
|
break;
|
||||||
|
case EXCP_ILLEGAL:
|
||||||
|
info.si_signo = TARGET_SIGILL;
|
||||||
|
info.si_errno = 0;
|
||||||
|
info.si_code = TARGET_ILL_ILLOPC;
|
||||||
|
info._sifields._sigfault._addr = env->pc;
|
||||||
|
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||||
|
break;
|
||||||
case EXCP_FPE:
|
case EXCP_FPE:
|
||||||
qemu_log_mask(CPU_LOG_INT, "\nFloating point error\n");
|
info.si_signo = TARGET_SIGFPE;
|
||||||
|
info.si_errno = 0;
|
||||||
|
info.si_code = 0;
|
||||||
|
info._sifields._sigfault._addr = env->pc;
|
||||||
|
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||||
break;
|
break;
|
||||||
case EXCP_TRAP:
|
case EXCP_INTERRUPT:
|
||||||
qemu_log_mask(CPU_LOG_INT, "\nTrap\n");
|
/* We processed the pending cpu work above. */
|
||||||
gdbsig = TARGET_SIGTRAP;
|
|
||||||
break;
|
break;
|
||||||
case EXCP_NR:
|
case EXCP_DEBUG:
|
||||||
qemu_log_mask(CPU_LOG_INT, "\nNR\n");
|
trapnr = gdb_handlesig(cs, TARGET_SIGTRAP);
|
||||||
|
if (trapnr) {
|
||||||
|
info.si_signo = trapnr;
|
||||||
|
info.si_errno = 0;
|
||||||
|
info.si_code = TARGET_TRAP_BRKPT;
|
||||||
|
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EXCP_ATOMIC:
|
case EXCP_ATOMIC:
|
||||||
cpu_exec_step_atomic(cs);
|
cpu_exec_step_atomic(cs);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
|
g_assert_not_reached();
|
||||||
trapnr);
|
|
||||||
gdbsig = TARGET_SIGILL;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (gdbsig) {
|
|
||||||
gdb_handlesig(cs, gdbsig);
|
|
||||||
if (gdbsig != TARGET_SIGTRAP) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
process_pending_signals(env);
|
process_pending_signals(env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4778,9 +4765,8 @@ int main(int argc, char **argv, char **envp)
|
|||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
env->gpr[i] = regs->gpr[i];
|
env->gpr[i] = regs->gpr[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
env->sr = regs->sr;
|
|
||||||
env->pc = regs->pc;
|
env->pc = regs->pc;
|
||||||
|
cpu_set_sr(env, regs->sr);
|
||||||
}
|
}
|
||||||
#elif defined(TARGET_SH4)
|
#elif defined(TARGET_SH4)
|
||||||
{
|
{
|
||||||
|
@ -30,9 +30,7 @@ static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp)
|
|||||||
|
|
||||||
static inline void cpu_set_tls(CPUOpenRISCState *env, target_ulong newtls)
|
static inline void cpu_set_tls(CPUOpenRISCState *env, target_ulong newtls)
|
||||||
{
|
{
|
||||||
/* Linux kernel 3.10 does not pay any attention to CLONE_SETTLS
|
env->gpr[10] = newtls;
|
||||||
* in copy_thread(), so QEMU need not do so either.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,4 +31,6 @@ struct target_pt_regs {
|
|||||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||||
|
|
||||||
|
#define MMAP_SHIFT TARGET_PAGE_BITS
|
||||||
|
|
||||||
#endif /* OPENRISC_TARGET_SYSCALL_H */
|
#endif /* OPENRISC_TARGET_SYSCALL_H */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
obj-$(CONFIG_SOFTMMU) += machine.o
|
obj-$(CONFIG_SOFTMMU) += machine.o
|
||||||
obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
|
obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
|
||||||
obj-y += exception_helper.o fpu_helper.o int_helper.o \
|
obj-y += exception_helper.o fpu_helper.o \
|
||||||
interrupt_helper.o mmu_helper.o sys_helper.o
|
interrupt_helper.o mmu_helper.o sys_helper.o
|
||||||
obj-y += gdbstub.o
|
obj-y += gdbstub.o
|
||||||
|
@ -48,6 +48,7 @@ static void openrisc_cpu_reset(CPUState *s)
|
|||||||
|
|
||||||
cpu->env.pc = 0x100;
|
cpu->env.pc = 0x100;
|
||||||
cpu->env.sr = SR_FO | SR_SM;
|
cpu->env.sr = SR_FO | SR_SM;
|
||||||
|
cpu->env.lock_addr = -1;
|
||||||
s->exception_index = -1;
|
s->exception_index = -1;
|
||||||
|
|
||||||
cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;
|
cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;
|
||||||
|
@ -32,7 +32,7 @@ struct OpenRISCCPU;
|
|||||||
#include "fpu/softfloat.h"
|
#include "fpu/softfloat.h"
|
||||||
#include "qom/cpu.h"
|
#include "qom/cpu.h"
|
||||||
|
|
||||||
#define TYPE_OPENRISC_CPU "or32-cpu"
|
#define TYPE_OPENRISC_CPU "or1k-cpu"
|
||||||
|
|
||||||
#define OPENRISC_CPU_CLASS(klass) \
|
#define OPENRISC_CPU_CLASS(klass) \
|
||||||
OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU)
|
OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU)
|
||||||
@ -58,6 +58,7 @@ typedef struct OpenRISCCPUClass {
|
|||||||
} OpenRISCCPUClass;
|
} OpenRISCCPUClass;
|
||||||
|
|
||||||
#define NB_MMU_MODES 3
|
#define NB_MMU_MODES 3
|
||||||
|
#define TARGET_INSN_START_EXTRA_WORDS 1
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MMU_NOMMU_IDX = 0,
|
MMU_NOMMU_IDX = 0,
|
||||||
@ -82,9 +83,6 @@ enum {
|
|||||||
/* Version Register */
|
/* Version Register */
|
||||||
#define SPR_VR 0xFFFF003F
|
#define SPR_VR 0xFFFF003F
|
||||||
|
|
||||||
/* Internal flags, delay slot flag */
|
|
||||||
#define D_FLAG 1
|
|
||||||
|
|
||||||
/* Interrupt */
|
/* Interrupt */
|
||||||
#define NR_IRQS 32
|
#define NR_IRQS 32
|
||||||
|
|
||||||
@ -273,20 +271,18 @@ typedef struct CPUOpenRISCTLBContext {
|
|||||||
typedef struct CPUOpenRISCState {
|
typedef struct CPUOpenRISCState {
|
||||||
target_ulong gpr[32]; /* General registers */
|
target_ulong gpr[32]; /* General registers */
|
||||||
target_ulong pc; /* Program counter */
|
target_ulong pc; /* Program counter */
|
||||||
target_ulong npc; /* Next PC */
|
|
||||||
target_ulong ppc; /* Prev PC */
|
target_ulong ppc; /* Prev PC */
|
||||||
target_ulong jmp_pc; /* Jump PC */
|
target_ulong jmp_pc; /* Jump PC */
|
||||||
|
|
||||||
target_ulong machi; /* Multiply register MACHI */
|
uint64_t mac; /* Multiply registers MACHI:MACLO */
|
||||||
target_ulong maclo; /* Multiply register MACLO */
|
|
||||||
|
|
||||||
target_ulong fpmaddhi; /* Multiply and add float register FPMADDHI */
|
|
||||||
target_ulong fpmaddlo; /* Multiply and add float register FPMADDLO */
|
|
||||||
|
|
||||||
target_ulong epcr; /* Exception PC register */
|
target_ulong epcr; /* Exception PC register */
|
||||||
target_ulong eear; /* Exception EA register */
|
target_ulong eear; /* Exception EA register */
|
||||||
|
|
||||||
uint32_t sr; /* Supervisor register */
|
target_ulong sr_f; /* the SR_F bit, values 0, 1. */
|
||||||
|
target_ulong sr_cy; /* the SR_CY bit, values 0, 1. */
|
||||||
|
target_long sr_ov; /* the SR_OV bit (in the sign bit only) */
|
||||||
|
uint32_t sr; /* Supervisor register, without SR_{F,CY,OV} */
|
||||||
uint32_t vr; /* Version register */
|
uint32_t vr; /* Version register */
|
||||||
uint32_t upr; /* Unit presence register */
|
uint32_t upr; /* Unit presence register */
|
||||||
uint32_t cpucfgr; /* CPU configure register */
|
uint32_t cpucfgr; /* CPU configure register */
|
||||||
@ -296,9 +292,10 @@ typedef struct CPUOpenRISCState {
|
|||||||
uint32_t fpcsr; /* Float register */
|
uint32_t fpcsr; /* Float register */
|
||||||
float_status fp_status;
|
float_status fp_status;
|
||||||
|
|
||||||
uint32_t flags; /* cpu_flags, we only use it for exception
|
target_ulong lock_addr;
|
||||||
in solt so far. */
|
target_ulong lock_value;
|
||||||
uint32_t btaken; /* the SR_F bit */
|
|
||||||
|
uint32_t dflag; /* In delay slot (boolean) */
|
||||||
|
|
||||||
/* Fields up to this point are cleared by a CPU reset */
|
/* Fields up to this point are cleared by a CPU reset */
|
||||||
struct {} end_reset_fields;
|
struct {} end_reset_fields;
|
||||||
@ -391,14 +388,19 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu,
|
|||||||
|
|
||||||
#include "exec/cpu-all.h"
|
#include "exec/cpu-all.h"
|
||||||
|
|
||||||
|
#define TB_FLAGS_DFLAG 1
|
||||||
|
#define TB_FLAGS_R0_0 2
|
||||||
|
#define TB_FLAGS_OVE SR_OVE
|
||||||
|
|
||||||
static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
|
static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
|
||||||
target_ulong *pc,
|
target_ulong *pc,
|
||||||
target_ulong *cs_base, uint32_t *flags)
|
target_ulong *cs_base, uint32_t *flags)
|
||||||
{
|
{
|
||||||
*pc = env->pc;
|
*pc = env->pc;
|
||||||
*cs_base = 0;
|
*cs_base = 0;
|
||||||
/* D_FLAG -- branch instruction exception */
|
*flags = (env->dflag
|
||||||
*flags = (env->flags & D_FLAG);
|
| (env->gpr[0] == 0 ? TB_FLAGS_R0_0 : 0)
|
||||||
|
| (env->sr & SR_OVE));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch)
|
static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch)
|
||||||
@ -409,6 +411,22 @@ static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch)
|
|||||||
return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX;
|
return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint32_t cpu_get_sr(const CPUOpenRISCState *env)
|
||||||
|
{
|
||||||
|
return (env->sr
|
||||||
|
+ env->sr_f * SR_F
|
||||||
|
+ env->sr_cy * SR_CY
|
||||||
|
+ (env->sr_ov < 0) * SR_OV);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cpu_set_sr(CPUOpenRISCState *env, uint32_t val)
|
||||||
|
{
|
||||||
|
env->sr_f = (val & SR_F) != 0;
|
||||||
|
env->sr_cy = (val & SR_CY) != 0;
|
||||||
|
env->sr_ov = (val & SR_OV ? -1 : 0);
|
||||||
|
env->sr = (val & ~(SR_F | SR_CY | SR_OV)) | SR_FO;
|
||||||
|
}
|
||||||
|
|
||||||
#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_INT_0
|
#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_INT_0
|
||||||
|
|
||||||
#endif /* OPENRISC_CPU_H */
|
#endif /* OPENRISC_CPU_H */
|
||||||
|
@ -19,7 +19,9 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "exec/exec-all.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
|
#include "exec/exec-all.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
|
|
||||||
void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp)
|
void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp)
|
||||||
@ -28,3 +30,33 @@ void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp)
|
|||||||
|
|
||||||
raise_exception(cpu, excp);
|
raise_exception(cpu, excp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void QEMU_NORETURN do_range(CPUOpenRISCState *env, uintptr_t pc)
|
||||||
|
{
|
||||||
|
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
|
||||||
|
CPUState *cs = CPU(cpu);
|
||||||
|
|
||||||
|
cs->exception_index = EXCP_RANGE;
|
||||||
|
cpu_loop_exit_restore(cs, pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HELPER(ove_cy)(CPUOpenRISCState *env)
|
||||||
|
{
|
||||||
|
if (env->sr_cy) {
|
||||||
|
do_range(env, GETPC());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HELPER(ove_ov)(CPUOpenRISCState *env)
|
||||||
|
{
|
||||||
|
if (env->sr_ov < 0) {
|
||||||
|
do_range(env, GETPC());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HELPER(ove_cyov)(CPUOpenRISCState *env)
|
||||||
|
{
|
||||||
|
if (env->sr_cy || env->sr_ov < 0) {
|
||||||
|
do_range(env, GETPC());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -146,52 +146,32 @@ FLOAT_CALC(div)
|
|||||||
FLOAT_CALC(rem)
|
FLOAT_CALC(rem)
|
||||||
#undef FLOAT_CALC
|
#undef FLOAT_CALC
|
||||||
|
|
||||||
#define FLOAT_TERNOP(name1, name2) \
|
|
||||||
uint64_t helper_float_ ## name1 ## name2 ## _d(CPUOpenRISCState *env, \
|
uint64_t helper_float_madd_d(CPUOpenRISCState *env, uint64_t a,
|
||||||
uint64_t fdt0, \
|
uint64_t b, uint64_t c)
|
||||||
uint64_t fdt1) \
|
{
|
||||||
{ \
|
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
|
||||||
uint64_t result, temp, hi, lo; \
|
uint64_t result;
|
||||||
uint32_t val1, val2; \
|
set_float_exception_flags(0, &cpu->env.fp_status);
|
||||||
OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \
|
/* Note that or1ksim doesn't use merged operation. */
|
||||||
hi = env->fpmaddhi; \
|
result = float64_mul(b, c, &cpu->env.fp_status);
|
||||||
lo = env->fpmaddlo; \
|
result = float64_add(result, a, &cpu->env.fp_status);
|
||||||
set_float_exception_flags(0, &cpu->env.fp_status); \
|
update_fpcsr(cpu);
|
||||||
result = float64_ ## name1(fdt0, fdt1, &cpu->env.fp_status); \
|
return result;
|
||||||
lo &= 0xffffffff; \
|
|
||||||
hi &= 0xffffffff; \
|
|
||||||
temp = (hi << 32) | lo; \
|
|
||||||
result = float64_ ## name2(result, temp, &cpu->env.fp_status); \
|
|
||||||
val1 = result >> 32; \
|
|
||||||
val2 = (uint32_t) (result & 0xffffffff); \
|
|
||||||
update_fpcsr(cpu); \
|
|
||||||
cpu->env.fpmaddlo = val2; \
|
|
||||||
cpu->env.fpmaddhi = val1; \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
uint32_t helper_float_ ## name1 ## name2 ## _s(CPUOpenRISCState *env, \
|
|
||||||
uint32_t fdt0, uint32_t fdt1) \
|
|
||||||
{ \
|
|
||||||
uint64_t result, temp, hi, lo; \
|
|
||||||
uint32_t val1, val2; \
|
|
||||||
OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \
|
|
||||||
hi = cpu->env.fpmaddhi; \
|
|
||||||
lo = cpu->env.fpmaddlo; \
|
|
||||||
set_float_exception_flags(0, &cpu->env.fp_status); \
|
|
||||||
result = float64_ ## name1(fdt0, fdt1, &cpu->env.fp_status); \
|
|
||||||
temp = (hi << 32) | lo; \
|
|
||||||
result = float64_ ## name2(result, temp, &cpu->env.fp_status); \
|
|
||||||
val1 = result >> 32; \
|
|
||||||
val2 = (uint32_t) (result & 0xffffffff); \
|
|
||||||
update_fpcsr(cpu); \
|
|
||||||
cpu->env.fpmaddlo = val2; \
|
|
||||||
cpu->env.fpmaddhi = val1; \
|
|
||||||
return 0; \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FLOAT_TERNOP(mul, add)
|
uint32_t helper_float_madd_s(CPUOpenRISCState *env, uint32_t a,
|
||||||
#undef FLOAT_TERNOP
|
uint32_t b, uint32_t c)
|
||||||
|
{
|
||||||
|
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
|
||||||
|
uint32_t result;
|
||||||
|
set_float_exception_flags(0, &cpu->env.fp_status);
|
||||||
|
/* Note that or1ksim doesn't use merged operation. */
|
||||||
|
result = float32_mul(b, c, &cpu->env.fp_status);
|
||||||
|
result = float32_add(result, a, &cpu->env.fp_status);
|
||||||
|
update_fpcsr(cpu);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define FLOAT_CMP(name) \
|
#define FLOAT_CMP(name) \
|
||||||
|
@ -34,11 +34,11 @@ int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
|||||||
case 32: /* PPC */
|
case 32: /* PPC */
|
||||||
return gdb_get_reg32(mem_buf, env->ppc);
|
return gdb_get_reg32(mem_buf, env->ppc);
|
||||||
|
|
||||||
case 33: /* NPC */
|
case 33: /* NPC (equals PC) */
|
||||||
return gdb_get_reg32(mem_buf, env->npc);
|
return gdb_get_reg32(mem_buf, env->pc);
|
||||||
|
|
||||||
case 34: /* SR */
|
case 34: /* SR */
|
||||||
return gdb_get_reg32(mem_buf, env->sr);
|
return gdb_get_reg32(mem_buf, cpu_get_sr(env));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -68,12 +68,17 @@ int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
|||||||
env->ppc = tmp;
|
env->ppc = tmp;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 33: /* NPC */
|
case 33: /* NPC (equals PC) */
|
||||||
env->npc = tmp;
|
/* If setting PC to something different,
|
||||||
|
also clear delayed branch status. */
|
||||||
|
if (env->pc != tmp) {
|
||||||
|
env->pc = tmp;
|
||||||
|
env->dflag = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 34: /* SR */
|
case 34: /* SR */
|
||||||
env->sr = tmp;
|
cpu_set_sr(env, tmp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -18,23 +18,23 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* exception */
|
/* exception */
|
||||||
DEF_HELPER_FLAGS_2(exception, 0, void, env, i32)
|
DEF_HELPER_FLAGS_2(exception, TCG_CALL_NO_WG, void, env, i32)
|
||||||
|
DEF_HELPER_FLAGS_1(ove_cy, TCG_CALL_NO_WG, void, env)
|
||||||
|
DEF_HELPER_FLAGS_1(ove_ov, TCG_CALL_NO_WG, void, env)
|
||||||
|
DEF_HELPER_FLAGS_1(ove_cyov, TCG_CALL_NO_WG, void, env)
|
||||||
|
|
||||||
/* float */
|
/* float */
|
||||||
DEF_HELPER_FLAGS_2(itofd, 0, i64, env, i64)
|
DEF_HELPER_FLAGS_2(itofd, TCG_CALL_NO_WG, i64, env, i64)
|
||||||
DEF_HELPER_FLAGS_2(itofs, 0, i32, env, i32)
|
DEF_HELPER_FLAGS_2(itofs, TCG_CALL_NO_WG, i32, env, i32)
|
||||||
DEF_HELPER_FLAGS_2(ftoid, 0, i64, env, i64)
|
DEF_HELPER_FLAGS_2(ftoid, TCG_CALL_NO_WG, i64, env, i64)
|
||||||
DEF_HELPER_FLAGS_2(ftois, 0, i32, env, i32)
|
DEF_HELPER_FLAGS_2(ftois, TCG_CALL_NO_WG, i32, env, i32)
|
||||||
|
|
||||||
#define FOP_MADD(op) \
|
DEF_HELPER_FLAGS_4(float_madd_s, TCG_CALL_NO_WG, i32, env, i32, i32, i32)
|
||||||
DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \
|
DEF_HELPER_FLAGS_4(float_madd_d, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
|
||||||
DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
|
|
||||||
FOP_MADD(muladd)
|
|
||||||
#undef FOP_MADD
|
|
||||||
|
|
||||||
#define FOP_CALC(op) \
|
#define FOP_CALC(op) \
|
||||||
DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \
|
DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \
|
||||||
DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
|
DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_WG, i64, env, i64, i64)
|
||||||
FOP_CALC(add)
|
FOP_CALC(add)
|
||||||
FOP_CALC(sub)
|
FOP_CALC(sub)
|
||||||
FOP_CALC(mul)
|
FOP_CALC(mul)
|
||||||
@ -43,8 +43,8 @@ FOP_CALC(rem)
|
|||||||
#undef FOP_CALC
|
#undef FOP_CALC
|
||||||
|
|
||||||
#define FOP_CMP(op) \
|
#define FOP_CMP(op) \
|
||||||
DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \
|
DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \
|
||||||
DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
|
DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_WG, i64, env, i64, i64)
|
||||||
FOP_CMP(eq)
|
FOP_CMP(eq)
|
||||||
FOP_CMP(lt)
|
FOP_CMP(lt)
|
||||||
FOP_CMP(le)
|
FOP_CMP(le)
|
||||||
@ -53,12 +53,9 @@ FOP_CMP(gt)
|
|||||||
FOP_CMP(ge)
|
FOP_CMP(ge)
|
||||||
#undef FOP_CMP
|
#undef FOP_CMP
|
||||||
|
|
||||||
/* int */
|
|
||||||
DEF_HELPER_FLAGS_3(mul32, 0, i32, env, i32, i32)
|
|
||||||
|
|
||||||
/* interrupt */
|
/* interrupt */
|
||||||
DEF_HELPER_FLAGS_1(rfe, 0, void, env)
|
DEF_HELPER_FLAGS_1(rfe, 0, void, env)
|
||||||
|
|
||||||
/* sys */
|
/* sys */
|
||||||
DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl)
|
DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl)
|
||||||
DEF_HELPER_FLAGS_4(mfspr, 0, tl, env, tl, tl, tl)
|
DEF_HELPER_FLAGS_4(mfspr, TCG_CALL_NO_WG, tl, env, tl, tl, tl)
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* OpenRISC int helper routines
|
|
||||||
*
|
|
||||||
* Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
|
|
||||||
* Feng Gao <gf91597@gmail.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "exec/helper-proto.h"
|
|
||||||
#include "exception.h"
|
|
||||||
#include "qemu/host-utils.h"
|
|
||||||
|
|
||||||
uint32_t HELPER(mul32)(CPUOpenRISCState *env,
|
|
||||||
uint32_t ra, uint32_t rb)
|
|
||||||
{
|
|
||||||
uint64_t result;
|
|
||||||
uint32_t high, cy;
|
|
||||||
|
|
||||||
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
|
|
||||||
|
|
||||||
result = (uint64_t)ra * rb;
|
|
||||||
/* regisiers in or32 is 32bit, so 32 is NOT a magic number.
|
|
||||||
or64 is not handled in this function, and not implement yet,
|
|
||||||
TARGET_LONG_BITS for or64 is 64, it will break this function,
|
|
||||||
so, we didn't use TARGET_LONG_BITS here. */
|
|
||||||
high = result >> 32;
|
|
||||||
cy = result >> (32 - 1);
|
|
||||||
|
|
||||||
if ((cy & 0x1) == 0x0) {
|
|
||||||
if (high == 0x0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((cy & 0x1) == 0x1) {
|
|
||||||
if (high == 0xffffffff) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu->env.sr |= (SR_OV | SR_CY);
|
|
||||||
if (cpu->env.sr & SR_OVE) {
|
|
||||||
raise_exception(cpu, EXCP_RANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
@ -34,20 +34,27 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
|
|||||||
CPUOpenRISCState *env = &cpu->env;
|
CPUOpenRISCState *env = &cpu->env;
|
||||||
|
|
||||||
env->epcr = env->pc;
|
env->epcr = env->pc;
|
||||||
if (env->flags & D_FLAG) {
|
if (env->dflag) {
|
||||||
env->flags &= ~D_FLAG;
|
env->dflag = 0;
|
||||||
env->sr |= SR_DSX;
|
env->sr |= SR_DSX;
|
||||||
env->epcr -= 4;
|
env->epcr -= 4;
|
||||||
|
} else {
|
||||||
|
env->sr &= ~SR_DSX;
|
||||||
}
|
}
|
||||||
if (cs->exception_index == EXCP_SYSCALL) {
|
if (cs->exception_index == EXCP_SYSCALL) {
|
||||||
env->epcr += 4;
|
env->epcr += 4;
|
||||||
}
|
}
|
||||||
|
/* When we have an illegal instruction the error effective address
|
||||||
|
shall be set to the illegal instruction address. */
|
||||||
|
if (cs->exception_index == EXCP_ILLEGAL) {
|
||||||
|
env->eear = env->pc;
|
||||||
|
}
|
||||||
|
|
||||||
/* For machine-state changed between user-mode and supervisor mode,
|
/* For machine-state changed between user-mode and supervisor mode,
|
||||||
we need flush TLB when we enter&exit EXCP. */
|
we need flush TLB when we enter&exit EXCP. */
|
||||||
tlb_flush(cs);
|
tlb_flush(cs);
|
||||||
|
|
||||||
env->esr = env->sr;
|
env->esr = cpu_get_sr(env);
|
||||||
env->sr &= ~SR_DME;
|
env->sr &= ~SR_DME;
|
||||||
env->sr &= ~SR_IME;
|
env->sr &= ~SR_IME;
|
||||||
env->sr |= SR_SM;
|
env->sr |= SR_SM;
|
||||||
@ -55,6 +62,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
|
|||||||
env->sr &= ~SR_TEE;
|
env->sr &= ~SR_TEE;
|
||||||
env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu;
|
env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu;
|
||||||
env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu;
|
env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu;
|
||||||
|
env->lock_addr = -1;
|
||||||
|
|
||||||
if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) {
|
if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) {
|
||||||
env->pc = (cs->exception_index << 8);
|
env->pc = (cs->exception_index << 8);
|
||||||
|
@ -32,8 +32,8 @@ void HELPER(rfe)(CPUOpenRISCState *env)
|
|||||||
(cpu->env.esr & (SR_SM | SR_IME | SR_DME));
|
(cpu->env.esr & (SR_SM | SR_IME | SR_DME));
|
||||||
#endif
|
#endif
|
||||||
cpu->env.pc = cpu->env.epcr;
|
cpu->env.pc = cpu->env.epcr;
|
||||||
cpu->env.npc = cpu->env.epcr;
|
cpu_set_sr(&cpu->env, cpu->env.esr);
|
||||||
cpu->env.sr = cpu->env.esr;
|
cpu->env.lock_addr = -1;
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
if (cpu->env.sr & SR_DME) {
|
if (cpu->env.sr & SR_DME) {
|
||||||
|
@ -24,20 +24,64 @@
|
|||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "migration/cpu.h"
|
#include "migration/cpu.h"
|
||||||
|
|
||||||
|
static int get_sr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
|
||||||
|
{
|
||||||
|
CPUOpenRISCState *env = opaque;
|
||||||
|
cpu_set_sr(env, qemu_get_be32(f));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int put_sr(QEMUFile *f, void *opaque, size_t size,
|
||||||
|
VMStateField *field, QJSON *vmdesc)
|
||||||
|
{
|
||||||
|
CPUOpenRISCState *env = opaque;
|
||||||
|
qemu_put_be32(f, cpu_get_sr(env));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const VMStateInfo vmstate_sr = {
|
||||||
|
.name = "sr",
|
||||||
|
.get = get_sr,
|
||||||
|
.put = put_sr,
|
||||||
|
};
|
||||||
|
|
||||||
static const VMStateDescription vmstate_env = {
|
static const VMStateDescription vmstate_env = {
|
||||||
.name = "env",
|
.name = "env",
|
||||||
.version_id = 1,
|
.version_id = 4,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 4,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32_ARRAY(gpr, CPUOpenRISCState, 32),
|
VMSTATE_UINTTL_ARRAY(gpr, CPUOpenRISCState, 32),
|
||||||
VMSTATE_UINT32(sr, CPUOpenRISCState),
|
VMSTATE_UINTTL(pc, CPUOpenRISCState),
|
||||||
VMSTATE_UINT32(epcr, CPUOpenRISCState),
|
VMSTATE_UINTTL(ppc, CPUOpenRISCState),
|
||||||
VMSTATE_UINT32(eear, CPUOpenRISCState),
|
VMSTATE_UINTTL(jmp_pc, CPUOpenRISCState),
|
||||||
|
VMSTATE_UINTTL(lock_addr, CPUOpenRISCState),
|
||||||
|
VMSTATE_UINTTL(lock_value, CPUOpenRISCState),
|
||||||
|
VMSTATE_UINTTL(epcr, CPUOpenRISCState),
|
||||||
|
VMSTATE_UINTTL(eear, CPUOpenRISCState),
|
||||||
|
|
||||||
|
/* Save the architecture value of the SR, 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 = "sr",
|
||||||
|
.version_id = 0,
|
||||||
|
.size = sizeof(uint32_t),
|
||||||
|
.info = &vmstate_sr,
|
||||||
|
.flags = VMS_SINGLE,
|
||||||
|
.offset = 0
|
||||||
|
},
|
||||||
|
|
||||||
|
VMSTATE_UINT32(vr, CPUOpenRISCState),
|
||||||
|
VMSTATE_UINT32(upr, CPUOpenRISCState),
|
||||||
|
VMSTATE_UINT32(cpucfgr, CPUOpenRISCState),
|
||||||
|
VMSTATE_UINT32(dmmucfgr, CPUOpenRISCState),
|
||||||
|
VMSTATE_UINT32(immucfgr, CPUOpenRISCState),
|
||||||
VMSTATE_UINT32(esr, CPUOpenRISCState),
|
VMSTATE_UINT32(esr, CPUOpenRISCState),
|
||||||
VMSTATE_UINT32(fpcsr, CPUOpenRISCState),
|
VMSTATE_UINT32(fpcsr, CPUOpenRISCState),
|
||||||
VMSTATE_UINT32(pc, CPUOpenRISCState),
|
VMSTATE_UINT64(mac, CPUOpenRISCState),
|
||||||
VMSTATE_UINT32(npc, CPUOpenRISCState),
|
|
||||||
VMSTATE_UINT32(ppc, CPUOpenRISCState),
|
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -174,6 +174,7 @@ static void cpu_openrisc_raise_mmu_exception(OpenRISCCPU *cpu,
|
|||||||
|
|
||||||
cs->exception_index = exception;
|
cs->exception_index = exception;
|
||||||
cpu->env.eear = address;
|
cpu->env.eear = address;
|
||||||
|
cpu->env.lock_addr = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
@ -29,11 +29,10 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
|||||||
target_ulong ra, target_ulong rb, target_ulong offset)
|
target_ulong ra, target_ulong rb, target_ulong offset)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
int spr = (ra | offset);
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
|
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
|
||||||
CPUState *cs = CPU(cpu);
|
CPUState *cs = CPU(cpu);
|
||||||
|
int spr = (ra | offset);
|
||||||
|
int idx;
|
||||||
|
|
||||||
switch (spr) {
|
switch (spr) {
|
||||||
case TO_SPR(0, 0): /* VR */
|
case TO_SPR(0, 0): /* VR */
|
||||||
@ -41,7 +40,14 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TO_SPR(0, 16): /* NPC */
|
case TO_SPR(0, 16): /* NPC */
|
||||||
env->npc = rb;
|
cpu_restore_state(cs, GETPC());
|
||||||
|
/* ??? Mirror or1ksim in not trashing delayed branch state
|
||||||
|
when "jumping" to the current instruction. */
|
||||||
|
if (env->pc != rb) {
|
||||||
|
env->pc = rb;
|
||||||
|
env->dflag = 0;
|
||||||
|
cpu_loop_exit(cs);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TO_SPR(0, 17): /* SR */
|
case TO_SPR(0, 17): /* SR */
|
||||||
@ -49,8 +55,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
|||||||
(rb & (SR_IME | SR_DME | SR_SM))) {
|
(rb & (SR_IME | SR_DME | SR_SM))) {
|
||||||
tlb_flush(cs);
|
tlb_flush(cs);
|
||||||
}
|
}
|
||||||
env->sr = rb;
|
cpu_set_sr(env, rb);
|
||||||
env->sr |= SR_FO; /* FO is const equal to 1 */
|
|
||||||
if (env->sr & SR_DME) {
|
if (env->sr & SR_DME) {
|
||||||
env->tlb->cpu_openrisc_map_address_data =
|
env->tlb->cpu_openrisc_map_address_data =
|
||||||
&cpu_openrisc_get_phys_data;
|
&cpu_openrisc_get_phys_data;
|
||||||
@ -121,6 +126,12 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
|||||||
case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */
|
case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */
|
||||||
case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
|
case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
|
||||||
break;
|
break;
|
||||||
|
case TO_SPR(5, 1): /* MACLO */
|
||||||
|
env->mac = deposit64(env->mac, 0, 32, rb);
|
||||||
|
break;
|
||||||
|
case TO_SPR(5, 2): /* MACHI */
|
||||||
|
env->mac = deposit64(env->mac, 32, 32, rb);
|
||||||
|
break;
|
||||||
case TO_SPR(9, 0): /* PICMR */
|
case TO_SPR(9, 0): /* PICMR */
|
||||||
env->picmr |= rb;
|
env->picmr |= rb;
|
||||||
break;
|
break;
|
||||||
@ -165,7 +176,6 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
|||||||
cpu_openrisc_timer_update(cpu);
|
cpu_openrisc_timer_update(cpu);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -175,11 +185,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
|
|||||||
target_ulong rd, target_ulong ra, uint32_t offset)
|
target_ulong rd, target_ulong ra, uint32_t offset)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
|
||||||
|
CPUState *cs = CPU(cpu);
|
||||||
int spr = (ra | offset);
|
int spr = (ra | offset);
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
|
|
||||||
|
|
||||||
switch (spr) {
|
switch (spr) {
|
||||||
case TO_SPR(0, 0): /* VR */
|
case TO_SPR(0, 0): /* VR */
|
||||||
return env->vr & SPR_VR;
|
return env->vr & SPR_VR;
|
||||||
@ -196,13 +206,15 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
|
|||||||
case TO_SPR(0, 4): /* IMMUCFGR */
|
case TO_SPR(0, 4): /* IMMUCFGR */
|
||||||
return env->immucfgr;
|
return env->immucfgr;
|
||||||
|
|
||||||
case TO_SPR(0, 16): /* NPC */
|
case TO_SPR(0, 16): /* NPC (equals PC) */
|
||||||
return env->npc;
|
cpu_restore_state(cs, GETPC());
|
||||||
|
return env->pc;
|
||||||
|
|
||||||
case TO_SPR(0, 17): /* SR */
|
case TO_SPR(0, 17): /* SR */
|
||||||
return env->sr;
|
return cpu_get_sr(env);
|
||||||
|
|
||||||
case TO_SPR(0, 18): /* PPC */
|
case TO_SPR(0, 18): /* PPC */
|
||||||
|
cpu_restore_state(cs, GETPC());
|
||||||
return env->ppc;
|
return env->ppc;
|
||||||
|
|
||||||
case TO_SPR(0, 32): /* EPCR */
|
case TO_SPR(0, 32): /* EPCR */
|
||||||
@ -246,6 +258,13 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
|
|||||||
case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
|
case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TO_SPR(5, 1): /* MACLO */
|
||||||
|
return (uint32_t)env->mac;
|
||||||
|
break;
|
||||||
|
case TO_SPR(5, 2): /* MACHI */
|
||||||
|
return env->mac >> 32;
|
||||||
|
break;
|
||||||
|
|
||||||
case TO_SPR(9, 0): /* PICMR */
|
case TO_SPR(9, 0): /* PICMR */
|
||||||
return env->picmr;
|
return env->picmr;
|
||||||
|
|
||||||
@ -264,25 +283,6 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*If we later need to add tracepoints (or debug printfs) for the return
|
|
||||||
value, it may be useful to structure the code like this:
|
|
||||||
|
|
||||||
target_ulong ret = 0;
|
|
||||||
|
|
||||||
switch() {
|
|
||||||
case x:
|
|
||||||
ret = y;
|
|
||||||
break;
|
|
||||||
case z:
|
|
||||||
ret = 42;
|
|
||||||
break;
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
later something like trace_spr_read(ret);
|
|
||||||
|
|
||||||
return ret;*/
|
|
||||||
|
|
||||||
/* for rd is passed in, if rd unchanged, just keep it back. */
|
/* for rd is passed in, if rd unchanged, just keep it back. */
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
|||||||
-include ../../config-host.mak
|
-include ../../config-host.mak
|
||||||
|
|
||||||
CROSS = or32-linux-
|
CROSS = or1k-linux-
|
||||||
|
|
||||||
SIM = qemu-or32
|
SIM = qemu-or1k
|
||||||
|
|
||||||
CC = $(CROSS)gcc
|
CC = $(CROSS)gcc
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user