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:
Peter Maydell 2017-02-14 09:55:48 +00:00
commit 5dae13cd71
25 changed files with 922 additions and 1019 deletions

6
configure vendored
View File

@ -5843,7 +5843,7 @@ target_name=$(echo $target | cut -d '-' -f 1)
target_bigendian="no"
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
;;
esac
@ -5937,7 +5937,7 @@ case "$target_name" in
;;
nios2)
;;
or32)
or1k)
TARGET_ARCH=openrisc
TARGET_BASE_ARCH=openrisc
;;
@ -6145,7 +6145,7 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
nios2)
disas_config "NIOS2"
;;
or32)
or1k)
disas_config "OPENRISC"
;;
ppc*)

View File

@ -0,0 +1 @@
# Default configuration for or1k-linux-user

View File

@ -0,0 +1,4 @@
# Default configuration for or1k-softmmu
CONFIG_SERIAL=y
CONFIG_OPENCORES_ETH=y

View File

@ -1 +0,0 @@
# Default configuration for or32-linux-user

View File

@ -1,4 +0,0 @@
# Default configuration for or32-softmmu
CONFIG_SERIAL=y
CONFIG_OPENCORES_ETH=y

View File

@ -139,10 +139,10 @@ static void openrisc_sim_init(MachineState *machine)
static void openrisc_sim_machine_init(MachineClass *mc)
{
mc->desc = "or32 simulation";
mc->desc = "or1k simulation";
mc->init = openrisc_sim_init;
mc->max_cpus = 1;
mc->is_default = 1;
}
DEFINE_MACHINE("or32-sim", openrisc_sim_machine_init)
DEFINE_MACHINE("or1k-sim", openrisc_sim_machine_init)

View File

@ -1054,9 +1054,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
for (i = 0; i < 32; i++) {
(*regs)[i] = tswapreg(env->gpr[i]);
}
(*regs)[32] = tswapreg(env->pc);
(*regs)[33] = tswapreg(env->sr);
(*regs)[33] = tswapreg(cpu_get_sr(env));
}
#define ELF_HWCAP 0
#define ELF_PLATFORM NULL

View File

@ -2574,52 +2574,17 @@ kuser_fail:
void cpu_loop(CPUOpenRISCState *env)
{
CPUState *cs = CPU(openrisc_env_get_cpu(env));
int trapnr, gdbsig;
int trapnr;
abi_long ret;
target_siginfo_t info;
for (;;) {
cpu_exec_start(cs);
trapnr = cpu_exec(cs);
cpu_exec_end(cs);
process_queued_cpu_work(cs);
gdbsig = 0;
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:
env->pc += 4; /* 0xc00; */
ret = do_syscall(env,
@ -2636,32 +2601,54 @@ void cpu_loop(CPUOpenRISCState *env)
env->gpr[11] = ret;
}
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:
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;
case EXCP_TRAP:
qemu_log_mask(CPU_LOG_INT, "\nTrap\n");
gdbsig = TARGET_SIGTRAP;
case EXCP_INTERRUPT:
/* We processed the pending cpu work above. */
break;
case EXCP_NR:
qemu_log_mask(CPU_LOG_INT, "\nNR\n");
case EXCP_DEBUG:
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;
case EXCP_ATOMIC:
cpu_exec_step_atomic(cs);
break;
default:
EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
trapnr);
gdbsig = TARGET_SIGILL;
break;
g_assert_not_reached();
}
if (gdbsig) {
gdb_handlesig(cs, gdbsig);
if (gdbsig != TARGET_SIGTRAP) {
exit(EXIT_FAILURE);
}
}
process_pending_signals(env);
}
}
@ -4778,9 +4765,8 @@ int main(int argc, char **argv, char **envp)
for (i = 0; i < 32; i++) {
env->gpr[i] = regs->gpr[i];
}
env->sr = regs->sr;
env->pc = regs->pc;
cpu_set_sr(env, regs->sr);
}
#elif defined(TARGET_SH4)
{

View File

@ -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)
{
/* Linux kernel 3.10 does not pay any attention to CLONE_SETTLS
* in copy_thread(), so QEMU need not do so either.
*/
env->gpr[10] = newtls;
}
#endif

View File

@ -31,4 +31,6 @@ struct target_pt_regs {
#define TARGET_MLOCKALL_MCL_CURRENT 1
#define TARGET_MLOCKALL_MCL_FUTURE 2
#define MMAP_SHIFT TARGET_PAGE_BITS
#endif /* OPENRISC_TARGET_SYSCALL_H */

View File

@ -1,5 +1,5 @@
obj-$(CONFIG_SOFTMMU) += machine.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
obj-y += gdbstub.o

View File

@ -48,6 +48,7 @@ static void openrisc_cpu_reset(CPUState *s)
cpu->env.pc = 0x100;
cpu->env.sr = SR_FO | SR_SM;
cpu->env.lock_addr = -1;
s->exception_index = -1;
cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;

View File

@ -32,7 +32,7 @@ struct OpenRISCCPU;
#include "fpu/softfloat.h"
#include "qom/cpu.h"
#define TYPE_OPENRISC_CPU "or32-cpu"
#define TYPE_OPENRISC_CPU "or1k-cpu"
#define OPENRISC_CPU_CLASS(klass) \
OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU)
@ -58,6 +58,7 @@ typedef struct OpenRISCCPUClass {
} OpenRISCCPUClass;
#define NB_MMU_MODES 3
#define TARGET_INSN_START_EXTRA_WORDS 1
enum {
MMU_NOMMU_IDX = 0,
@ -82,9 +83,6 @@ enum {
/* Version Register */
#define SPR_VR 0xFFFF003F
/* Internal flags, delay slot flag */
#define D_FLAG 1
/* Interrupt */
#define NR_IRQS 32
@ -273,20 +271,18 @@ typedef struct CPUOpenRISCTLBContext {
typedef struct CPUOpenRISCState {
target_ulong gpr[32]; /* General registers */
target_ulong pc; /* Program counter */
target_ulong npc; /* Next PC */
target_ulong ppc; /* Prev PC */
target_ulong jmp_pc; /* Jump PC */
target_ulong machi; /* Multiply register MACHI */
target_ulong maclo; /* Multiply register MACLO */
target_ulong fpmaddhi; /* Multiply and add float register FPMADDHI */
target_ulong fpmaddlo; /* Multiply and add float register FPMADDLO */
uint64_t mac; /* Multiply registers MACHI:MACLO */
target_ulong epcr; /* Exception PC 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 upr; /* Unit presence register */
uint32_t cpucfgr; /* CPU configure register */
@ -296,9 +292,10 @@ typedef struct CPUOpenRISCState {
uint32_t fpcsr; /* Float register */
float_status fp_status;
uint32_t flags; /* cpu_flags, we only use it for exception
in solt so far. */
uint32_t btaken; /* the SR_F bit */
target_ulong lock_addr;
target_ulong lock_value;
uint32_t dflag; /* In delay slot (boolean) */
/* Fields up to this point are cleared by a CPU reset */
struct {} end_reset_fields;
@ -391,14 +388,19 @@ int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu,
#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,
target_ulong *pc,
target_ulong *cs_base, uint32_t *flags)
{
*pc = env->pc;
*cs_base = 0;
/* D_FLAG -- branch instruction exception */
*flags = (env->flags & D_FLAG);
*flags = (env->dflag
| (env->gpr[0] == 0 ? TB_FLAGS_R0_0 : 0)
| (env->sr & SR_OVE));
}
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;
}
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
#endif /* OPENRISC_CPU_H */

View File

@ -19,7 +19,9 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
#include "exec/exec-all.h"
#include "exception.h"
void HELPER(exception)(CPUOpenRISCState *env, uint32_t excp)
@ -28,3 +30,33 @@ void HELPER(exception)(CPUOpenRISCState *env, uint32_t 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());
}
}

View File

@ -146,52 +146,32 @@ FLOAT_CALC(div)
FLOAT_CALC(rem)
#undef FLOAT_CALC
#define FLOAT_TERNOP(name1, name2) \
uint64_t helper_float_ ## name1 ## name2 ## _d(CPUOpenRISCState *env, \
uint64_t fdt0, \
uint64_t fdt1) \
{ \
uint64_t result, temp, hi, lo; \
uint32_t val1, val2; \
OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \
hi = env->fpmaddhi; \
lo = env->fpmaddlo; \
set_float_exception_flags(0, &cpu->env.fp_status); \
result = float64_ ## name1(fdt0, fdt1, &cpu->env.fp_status); \
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; \
uint64_t helper_float_madd_d(CPUOpenRISCState *env, uint64_t a,
uint64_t b, uint64_t c)
{
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
uint64_t result;
set_float_exception_flags(0, &cpu->env.fp_status);
/* Note that or1ksim doesn't use merged operation. */
result = float64_mul(b, c, &cpu->env.fp_status);
result = float64_add(result, a, &cpu->env.fp_status);
update_fpcsr(cpu);
return result;
}
FLOAT_TERNOP(mul, add)
#undef FLOAT_TERNOP
uint32_t helper_float_madd_s(CPUOpenRISCState *env, uint32_t a,
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) \

View File

@ -34,11 +34,11 @@ int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
case 32: /* PPC */
return gdb_get_reg32(mem_buf, env->ppc);
case 33: /* NPC */
return gdb_get_reg32(mem_buf, env->npc);
case 33: /* NPC (equals PC) */
return gdb_get_reg32(mem_buf, env->pc);
case 34: /* SR */
return gdb_get_reg32(mem_buf, env->sr);
return gdb_get_reg32(mem_buf, cpu_get_sr(env));
default:
break;
@ -68,12 +68,17 @@ int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
env->ppc = tmp;
break;
case 33: /* NPC */
env->npc = tmp;
case 33: /* NPC (equals PC) */
/* If setting PC to something different,
also clear delayed branch status. */
if (env->pc != tmp) {
env->pc = tmp;
env->dflag = 0;
}
break;
case 34: /* SR */
env->sr = tmp;
cpu_set_sr(env, tmp);
break;
default:

View File

@ -18,23 +18,23 @@
*/
/* 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 */
DEF_HELPER_FLAGS_2(itofd, 0, i64, env, i64)
DEF_HELPER_FLAGS_2(itofs, 0, i32, env, i32)
DEF_HELPER_FLAGS_2(ftoid, 0, i64, env, i64)
DEF_HELPER_FLAGS_2(ftois, 0, i32, env, i32)
DEF_HELPER_FLAGS_2(itofd, TCG_CALL_NO_WG, i64, env, i64)
DEF_HELPER_FLAGS_2(itofs, TCG_CALL_NO_WG, i32, env, i32)
DEF_HELPER_FLAGS_2(ftoid, TCG_CALL_NO_WG, i64, env, i64)
DEF_HELPER_FLAGS_2(ftois, TCG_CALL_NO_WG, i32, env, i32)
#define FOP_MADD(op) \
DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \
DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
FOP_MADD(muladd)
#undef FOP_MADD
DEF_HELPER_FLAGS_4(float_madd_s, TCG_CALL_NO_WG, i32, env, i32, i32, i32)
DEF_HELPER_FLAGS_4(float_madd_d, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
#define FOP_CALC(op) \
DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \
DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \
DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_WG, i64, env, i64, i64)
FOP_CALC(add)
FOP_CALC(sub)
FOP_CALC(mul)
@ -43,8 +43,8 @@ FOP_CALC(rem)
#undef FOP_CALC
#define FOP_CMP(op) \
DEF_HELPER_FLAGS_3(float_ ## op ## _s, 0, i32, env, i32, i32) \
DEF_HELPER_FLAGS_3(float_ ## op ## _d, 0, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \
DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_WG, i64, env, i64, i64)
FOP_CMP(eq)
FOP_CMP(lt)
FOP_CMP(le)
@ -53,12 +53,9 @@ FOP_CMP(gt)
FOP_CMP(ge)
#undef FOP_CMP
/* int */
DEF_HELPER_FLAGS_3(mul32, 0, i32, env, i32, i32)
/* interrupt */
DEF_HELPER_FLAGS_1(rfe, 0, void, env)
/* sys */
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)

View File

@ -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;
}

View File

@ -34,20 +34,27 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
CPUOpenRISCState *env = &cpu->env;
env->epcr = env->pc;
if (env->flags & D_FLAG) {
env->flags &= ~D_FLAG;
if (env->dflag) {
env->dflag = 0;
env->sr |= SR_DSX;
env->epcr -= 4;
} else {
env->sr &= ~SR_DSX;
}
if (cs->exception_index == EXCP_SYSCALL) {
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,
we need flush TLB when we enter&exit EXCP. */
tlb_flush(cs);
env->esr = env->sr;
env->esr = cpu_get_sr(env);
env->sr &= ~SR_DME;
env->sr &= ~SR_IME;
env->sr |= SR_SM;
@ -55,6 +62,7 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
env->sr &= ~SR_TEE;
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->lock_addr = -1;
if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) {
env->pc = (cs->exception_index << 8);

View File

@ -32,8 +32,8 @@ void HELPER(rfe)(CPUOpenRISCState *env)
(cpu->env.esr & (SR_SM | SR_IME | SR_DME));
#endif
cpu->env.pc = cpu->env.epcr;
cpu->env.npc = cpu->env.epcr;
cpu->env.sr = cpu->env.esr;
cpu_set_sr(&cpu->env, cpu->env.esr);
cpu->env.lock_addr = -1;
#ifndef CONFIG_USER_ONLY
if (cpu->env.sr & SR_DME) {

View File

@ -24,20 +24,64 @@
#include "hw/boards.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 = {
.name = "env",
.version_id = 1,
.minimum_version_id = 1,
.version_id = 4,
.minimum_version_id = 4,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(gpr, CPUOpenRISCState, 32),
VMSTATE_UINT32(sr, CPUOpenRISCState),
VMSTATE_UINT32(epcr, CPUOpenRISCState),
VMSTATE_UINT32(eear, CPUOpenRISCState),
VMSTATE_UINTTL_ARRAY(gpr, CPUOpenRISCState, 32),
VMSTATE_UINTTL(pc, CPUOpenRISCState),
VMSTATE_UINTTL(ppc, 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(fpcsr, CPUOpenRISCState),
VMSTATE_UINT32(pc, CPUOpenRISCState),
VMSTATE_UINT32(npc, CPUOpenRISCState),
VMSTATE_UINT32(ppc, CPUOpenRISCState),
VMSTATE_UINT64(mac, CPUOpenRISCState),
VMSTATE_END_OF_LIST()
}
};

View File

@ -174,6 +174,7 @@ static void cpu_openrisc_raise_mmu_exception(OpenRISCCPU *cpu,
cs->exception_index = exception;
cpu->env.eear = address;
cpu->env.lock_addr = -1;
}
#ifndef CONFIG_USER_ONLY

View File

@ -29,11 +29,10 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
target_ulong ra, target_ulong rb, target_ulong offset)
{
#ifndef CONFIG_USER_ONLY
int spr = (ra | offset);
int idx;
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
CPUState *cs = CPU(cpu);
int spr = (ra | offset);
int idx;
switch (spr) {
case TO_SPR(0, 0): /* VR */
@ -41,7 +40,14 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
break;
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;
case TO_SPR(0, 17): /* SR */
@ -49,8 +55,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
(rb & (SR_IME | SR_DME | SR_SM))) {
tlb_flush(cs);
}
env->sr = rb;
env->sr |= SR_FO; /* FO is const equal to 1 */
cpu_set_sr(env, rb);
if (env->sr & SR_DME) {
env->tlb->cpu_openrisc_map_address_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, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
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 */
env->picmr |= rb;
break;
@ -165,7 +176,6 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
cpu_openrisc_timer_update(cpu);
break;
default:
break;
}
#endif
@ -175,11 +185,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
target_ulong rd, target_ulong ra, uint32_t offset)
{
#ifndef CONFIG_USER_ONLY
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
CPUState *cs = CPU(cpu);
int spr = (ra | offset);
int idx;
OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
switch (spr) {
case TO_SPR(0, 0): /* VR */
return env->vr & SPR_VR;
@ -196,13 +206,15 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
case TO_SPR(0, 4): /* IMMUCFGR */
return env->immucfgr;
case TO_SPR(0, 16): /* NPC */
return env->npc;
case TO_SPR(0, 16): /* NPC (equals PC) */
cpu_restore_state(cs, GETPC());
return env->pc;
case TO_SPR(0, 17): /* SR */
return env->sr;
return cpu_get_sr(env);
case TO_SPR(0, 18): /* PPC */
cpu_restore_state(cs, GETPC());
return env->ppc;
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 */
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 */
return env->picmr;
@ -264,25 +283,6 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
}
#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. */
return rd;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
-include ../../config-host.mak
CROSS = or32-linux-
CROSS = or1k-linux-
SIM = qemu-or32
SIM = qemu-or1k
CC = $(CROSS)gcc