aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-10-08 13:04:02 +0000
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-10-08 13:04:02 +0000
commit81fdc5f8d2d681da8d255baf0713144f8656bac9 (patch)
tree678e81ba4ef8b6a7cc2efe2048c3195a81d3b8b4
parent4fa551d76893dfdd976d2745a42c17ca1cedaa55 (diff)
The remainder of CRIS CPU emulation files, by Edgar E. Iglesias.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3361 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--target-cris/cpu.h256
-rw-r--r--target-cris/exec.h68
-rw-r--r--target-cris/helper.c173
-rw-r--r--target-cris/op_helper.c76
-rw-r--r--target-cris/op_mem.c59
-rw-r--r--target-cris/op_template.h48
6 files changed, 680 insertions, 0 deletions
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
new file mode 100644
index 0000000000..11652c50fb
--- /dev/null
+++ b/target-cris/cpu.h
@@ -0,0 +1,256 @@
+/*
+ * CRIS virtual CPU header
+ *
+ * Copyright (c) 2007 AXIS Communications AB
+ * Written by Edgar E. Iglesias
+ *
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef CPU_CRIS_H
+#define CPU_CRIS_H
+
+#define TARGET_LONG_BITS 32
+
+#include "cpu-defs.h"
+
+#include "softfloat.h"
+
+#define TARGET_HAS_ICE 1
+
+#define ELF_MACHINE EM_CRIS
+
+#define EXCP_MMU_EXEC 0
+#define EXCP_MMU_READ 1
+#define EXCP_MMU_WRITE 2
+#define EXCP_MMU_FLUSH 3
+#define EXCP_MMU_MISS 4
+#define EXCP_BREAK 16 /* trap. */
+
+/* CPU flags. */
+#define S_FLAG 0x200
+#define R_FLAG 0x100
+#define P_FLAG 0x80
+#define U_FLAG 0x40
+#define P_FLAG 0x80
+#define U_FLAG 0x40
+#define I_FLAG 0x20
+#define X_FLAG 0x10
+#define N_FLAG 0x08
+#define Z_FLAG 0x04
+#define V_FLAG 0x02
+#define C_FLAG 0x01
+#define ALU_FLAGS 0x1F
+
+/* Condition codes. */
+#define CC_CC 0
+#define CC_CS 1
+#define CC_NE 2
+#define CC_EQ 3
+#define CC_VC 4
+#define CC_VS 5
+#define CC_PL 6
+#define CC_MI 7
+#define CC_LS 8
+#define CC_HI 9
+#define CC_GE 10
+#define CC_LT 11
+#define CC_GT 12
+#define CC_LE 13
+#define CC_A 14
+#define CC_P 15
+
+/* Internal flags for the implementation. */
+#define F_DELAYSLOT 1
+
+typedef struct CPUCRISState {
+ uint32_t debug1;
+ uint32_t debug2;
+ uint32_t debug3;
+
+ /*
+ * We just store the stores to the tlbset here for later evaluation
+ * when the hw needs access to them.
+ *
+ * One for I and another for D.
+ */
+ struct
+ {
+ uint32_t hi;
+ uint32_t lo;
+ } tlbsets[2][4][16];
+
+ uint32_t sregs[256][16]; /* grrr why so many?? */
+ uint32_t regs[16];
+ uint32_t pregs[16];
+ uint32_t pc;
+ uint32_t sr;
+ uint32_t flag_mask; /* Per insn mask of affected flags. */
+
+ /* SSP and USP. */
+ int current_sp;
+ uint32_t sp[2];
+
+ /* These are setup up by the guest code just before transfering the
+ control back to the host. */
+ int jmp;
+ uint32_t btarget;
+ int btaken;
+
+ /* for traps. */
+ int trapnr;
+
+ /* Condition flag tracking. */
+ uint32_t cc_op;
+ uint32_t cc_mask;
+ uint32_t cc_dest;
+ uint32_t cc_src;
+ uint32_t cc_result;
+
+ /* size of the operation, 1 = byte, 2 = word, 4 = dword. */
+ int cc_size;
+
+ /* extended arithmetics. */
+ int cc_x_live;
+ int cc_x;
+
+ int features;
+
+ uint64_t pending_interrupts;
+ int interrupt_request;
+ int exception_index;
+ int user_mode_only;
+ int halted;
+
+ struct
+ {
+ int exec_insns;
+ int exec_loads;
+ int exec_stores;
+ } stats;
+
+
+ jmp_buf jmp_env;
+ CPU_COMMON
+} CPUCRISState;
+
+CPUCRISState *cpu_cris_init(void);
+int cpu_cris_exec(CPUCRISState *s);
+void cpu_cris_close(CPUCRISState *s);
+void do_interrupt(CPUCRISState *env);
+/* you can call this signal handler from your SIGBUS and SIGSEGV
+ signal handlers to inform the virtual CPU of exceptions. non zero
+ is returned if the signal was handled by the virtual CPU. */
+int cpu_cris_signal_handler(int host_signum, void *pinfo,
+ void *puc);
+void cpu_cris_flush_flags(CPUCRISState *, int);
+
+
+void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
+ int is_asi);
+
+enum {
+ CC_OP_DYNAMIC, /* Use env->cc_op */
+ CC_OP_FLAGS,
+ CC_OP_LOGIC,
+ CC_OP_CMP,
+ CC_OP_MOVE,
+ CC_OP_MOVE_PD,
+ CC_OP_MOVE_SD,
+ CC_OP_ADD,
+ CC_OP_ADDC,
+ CC_OP_MCP,
+ CC_OP_ADDU,
+ CC_OP_SUB,
+ CC_OP_SUBU,
+ CC_OP_NEG,
+ CC_OP_BTST,
+ CC_OP_MULS,
+ CC_OP_MULU,
+ CC_OP_DSTEP,
+ CC_OP_BOUND,
+
+ CC_OP_OR,
+ CC_OP_AND,
+ CC_OP_XOR,
+ CC_OP_LSL,
+ CC_OP_LSR,
+ CC_OP_ASR,
+ CC_OP_LZ
+};
+
+#define CCF_C 0x01
+#define CCF_V 0x02
+#define CCF_Z 0x04
+#define CCF_N 0x08
+#define CCF_X 0x10
+
+#define CRIS_SSP 0
+#define CRIS_USP 1
+
+typedef struct cris_def_t cris_def_t;
+
+int cpu_cris_set_model(CPUCRISState *env, const char * name);
+
+void cris_set_irq_level(CPUCRISState *env, int level, uint8_t vector);
+void cris_set_macsr(CPUCRISState *env, uint32_t val);
+void cris_switch_sp(CPUCRISState *env);
+
+void do_cris_semihosting(CPUCRISState *env, int nr);
+
+enum cris_features {
+ CRIS_FEATURE_CF_ISA_MUL,
+};
+
+static inline int cris_feature(CPUCRISState *env, int feature)
+{
+ return (env->features & (1u << feature)) != 0;
+}
+
+void register_cris_insns (CPUCRISState *env);
+
+/* CRIS uses 8k pages. */
+#define TARGET_PAGE_BITS 13
+
+#define CPUState CPUCRISState
+#define cpu_init cpu_cris_init
+#define cpu_exec cpu_cris_exec
+#define cpu_gen_code cpu_cris_gen_code
+#define cpu_signal_handler cpu_cris_signal_handler
+
+#include "cpu-all.h"
+
+/* Register aliases. */
+#define REG_SP 14
+#define REG_ACR 15
+#define REG_MOF 7
+
+/* Support regs. */
+#define SR_PID 2
+#define SR_SRS 3
+#define SR_EBP 9
+#define SR_ERP 10
+#define SR_CCS 13
+
+/* Support func regs. */
+#define SFR_RW_GC_CFG 0][0
+#define SFR_RW_MM_CFG 1][0
+#define SFR_RW_MM_KBASE_LO 1][1
+#define SFR_RW_MM_KBASE_HI 1][2
+#define SFR_R_MM_CAUSE 1][3
+#define SFR_RW_MM_TLB_SEL 1][4
+#define SFR_RW_MM_TLB_LO 1][5
+#define SFR_RW_MM_TLB_HI 1][6
+
+#endif
diff --git a/target-cris/exec.h b/target-cris/exec.h
new file mode 100644
index 0000000000..a4f555eb28
--- /dev/null
+++ b/target-cris/exec.h
@@ -0,0 +1,68 @@
+/*
+ * CRIS execution defines
+ *
+ * Copyright (c) 2007 AXIS Communications AB
+ * Written by Edgar E. Iglesias
+ *
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "dyngen-exec.h"
+
+#if 1
+register struct CPUCRISState *env asm(AREG0);
+/* This is only used for tb lookup. */
+register uint32_t T0 asm(AREG1);
+register uint32_t T1 asm(AREG2);
+#else
+struct CPUCRISState *env;
+/* This is only used for tb lookup. */
+uint32_t T0;
+uint32_t T1;
+#endif
+#include "cpu.h"
+#include "exec-all.h"
+
+#define RETURN() __asm__ __volatile__("" : : : "memory");
+
+static inline void env_to_regs(void)
+{
+}
+
+static inline void regs_to_env(void)
+{
+}
+
+int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+ int is_user, int is_softmmu);
+void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr);
+
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif
+
+void cpu_cris_flush_flags(CPUCRISState *env, int cc_op);
+void helper_movec(CPUCRISState *env, int reg, uint32_t val);
+
+void cpu_loop_exit(void);
+
+static inline int cpu_halted(CPUState *env) {
+ if (!env->halted)
+ return 0;
+ if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+ env->halted = 0;
+ return 0;
+ }
+ return EXCP_HALTED;
+}
diff --git a/target-cris/helper.c b/target-cris/helper.c
new file mode 100644
index 0000000000..3db3bea08d
--- /dev/null
+++ b/target-cris/helper.c
@@ -0,0 +1,173 @@
+/*
+ * CRIS helper routines.
+ *
+ * Copyright (c) 2007 AXIS Communications AB
+ * Written by Edgar E. Iglesias.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"
+#include "cpu.h"
+#include "mmu.h"
+#include "exec-all.h"
+
+#if defined(CONFIG_USER_ONLY)
+
+void do_interrupt (CPUState *env)
+{
+ env->exception_index = -1;
+}
+
+int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
+ int is_user, int is_softmmu)
+{
+ env->exception_index = 0xaa;
+ env->debug1 = address;
+ cpu_dump_state(env, stderr, fprintf, 0);
+ printf("%s addr=%x env->pc=%x\n", __func__, address, env->pc);
+ return 1;
+}
+
+target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
+{
+ return addr;
+}
+
+#else /* !CONFIG_USER_ONLY */
+
+int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+ int is_user, int is_softmmu)
+{
+ struct cris_mmu_result_t res;
+ int prot, miss;
+ target_ulong phy;
+
+ address &= TARGET_PAGE_MASK;
+ prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+// printf ("%s pc=%x %x w=%d smmu=%d\n", __func__, env->pc, address, rw, is_softmmu);
+ miss = cris_mmu_translate(&res, env, address, rw, is_user);
+ if (miss)
+ {
+ /* handle the miss. */
+ phy = 0;
+ env->exception_index = EXCP_MMU_MISS;
+ }
+ else
+ {
+ phy = res.phy;
+ }
+// printf ("a=%x phy=%x\n", address, phy);
+ return tlb_set_page(env, address, phy, prot, is_user, is_softmmu);
+}
+
+
+static void cris_shift_ccs(CPUState *env)
+{
+ uint32_t ccs;
+ /* Apply the ccs shift. */
+ ccs = env->pregs[SR_CCS];
+ ccs = (ccs & 0xc0000000) | ((ccs << 12) >> 2);
+// printf ("ccs=%x %x\n", env->pregs[SR_CCS], ccs);
+ env->pregs[SR_CCS] = ccs;
+}
+
+void do_interrupt(CPUState *env)
+{
+ uint32_t ebp, isr;
+ int irqnum;
+
+ fflush(NULL);
+
+#if 0
+ printf ("exception index=%d interrupt_req=%d\n",
+ env->exception_index,
+ env->interrupt_request);
+#endif
+
+ switch (env->exception_index)
+ {
+ case EXCP_BREAK:
+// printf ("BREAK! %d\n", env->trapnr);
+ irqnum = env->trapnr;
+ ebp = env->pregs[SR_EBP];
+ isr = ldl_code(ebp + irqnum * 4);
+ env->pregs[SR_ERP] = env->pc + 2;
+ env->pc = isr;
+
+ cris_shift_ccs(env);
+
+ break;
+ case EXCP_MMU_MISS:
+// printf ("MMU miss\n");
+ irqnum = 4;
+ ebp = env->pregs[SR_EBP];
+ isr = ldl_code(ebp + irqnum * 4);
+ env->pregs[SR_ERP] = env->pc;
+ env->pc = isr;
+ cris_shift_ccs(env);
+ break;
+
+ default:
+ {
+ /* Maybe the irq was acked by sw before we got a
+ change to take it. */
+ if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+ if (!env->pending_interrupts)
+ return;
+ if (!(env->pregs[SR_CCS] & I_FLAG)) {
+ return;
+ }
+
+ irqnum = 31 -
+ __builtin_clz(env->pending_interrupts);
+ irqnum += 0x30;
+ ebp = env->pregs[SR_EBP];
+ isr = ldl_code(ebp + irqnum * 4);
+ env->pregs[SR_ERP] = env->pc;
+ env->pc = isr;
+
+ cris_shift_ccs(env);
+#if 0
+ printf ("%s ebp=%x %x isr=%x %d"
+ " ir=%x pending=%x\n",
+ __func__,
+ ebp, ebp + irqnum * 4,
+ isr, env->exception_index,
+ env->interrupt_request,
+ env->pending_interrupts);
+#endif
+ }
+
+ }
+ break;
+ }
+}
+
+target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
+{
+// printf ("%s\n", __func__);
+ uint32_t phy = addr;
+ struct cris_mmu_result_t res;
+ int miss;
+ miss = cris_mmu_translate(&res, env, addr, 0, 0);
+ if (!miss)
+ phy = res.phy;
+ return phy;
+}
+#endif
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
new file mode 100644
index 0000000000..f84ceb9da0
--- /dev/null
+++ b/target-cris/op_helper.c
@@ -0,0 +1,76 @@
+/*
+ * CRIS helper routines
+ *
+ * Copyright (c) 2007 AXIS Communications
+ * Written by Edgar E. Iglesias
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <assert.h>
+#include "exec.h"
+
+#define MMUSUFFIX _mmu
+#define GETPC() (__builtin_return_address(0))
+
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
+
+/* Try to fill the TLB and return an exception if error. If retaddr is
+ NULL, it means that the function was called in C code (i.e. not
+ from generated code or from helper.c) */
+/* XXX: fix it to restore all registers */
+void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
+{
+ TranslationBlock *tb;
+ CPUState *saved_env;
+ target_phys_addr_t pc;
+ int ret;
+
+ /* XXX: hack to restore env in all cases, even if not called from
+ generated code */
+ saved_env = env;
+ env = cpu_single_env;
+ ret = cpu_cris_handle_mmu_fault(env, addr, is_write, is_user, 1);
+ if (__builtin_expect(ret, 0)) {
+ if (retaddr) {
+ /* now we have a real cpu fault */
+ pc = (target_phys_addr_t)retaddr;
+ tb = tb_find_pc(pc);
+ if (tb) {
+ /* the PC is inside the translated code. It means that we have
+ a virtual CPU fault */
+ cpu_restore_state(tb, env, pc, NULL);
+ }
+ }
+ cpu_loop_exit();
+ }
+ env = saved_env;
+}
+
+void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
+ int is_asi)
+{
+
+}
diff --git a/target-cris/op_mem.c b/target-cris/op_mem.c
new file mode 100644
index 0000000000..50ed10b57b
--- /dev/null
+++ b/target-cris/op_mem.c
@@ -0,0 +1,59 @@
+/*
+ * CRIS memory access (load and store) micro operations.
+ *
+ * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+void glue(op_ldb_T0_T0, MEMSUFFIX) (void) {
+ T0 = glue(ldsb, MEMSUFFIX) (T0);
+ RETURN();
+}
+
+void glue(op_ldub_T0_T0, MEMSUFFIX) (void) {
+ T0 = glue(ldub, MEMSUFFIX) (T0);
+ RETURN();
+}
+
+void glue(op_stb_T0_T1, MEMSUFFIX) (void) {
+ glue(stb, MEMSUFFIX) (T0, T1);
+ RETURN();
+}
+
+void glue(op_ldw_T0_T0, MEMSUFFIX) (void) {
+ T0 = glue(ldsw, MEMSUFFIX) (T0);
+ RETURN();
+}
+
+void glue(op_lduw_T0_T0, MEMSUFFIX) (void) {
+ T0 = glue(lduw, MEMSUFFIX) (T0);
+ RETURN();
+}
+
+void glue(op_stw_T0_T1, MEMSUFFIX) (void) {
+ glue(stw, MEMSUFFIX) (T0, T1);
+ RETURN();
+}
+
+void glue(op_ldl_T0_T0, MEMSUFFIX) (void) {
+ T0 = glue(ldl, MEMSUFFIX) (T0);
+ RETURN();
+}
+
+void glue(op_stl_T0_T1, MEMSUFFIX) (void) {
+ glue(stl, MEMSUFFIX) (T0, T1);
+ RETURN();
+}
diff --git a/target-cris/op_template.h b/target-cris/op_template.h
new file mode 100644
index 0000000000..370fbf3958
--- /dev/null
+++ b/target-cris/op_template.h
@@ -0,0 +1,48 @@
+/*
+ * CRIS micro operations (templates for various register related
+ * operations)
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef SET_REG
+#define SET_REG(x) REG = x
+#endif
+
+void OPPROTO glue(op_movl_T0_, REGNAME)(void)
+{
+ T0 = REG;
+}
+
+void OPPROTO glue(op_movl_T1_, REGNAME)(void)
+{
+ T1 = REG;
+}
+
+void OPPROTO glue(glue(op_movl_, REGNAME), _T0)(void)
+{
+ SET_REG (T0);
+}
+
+void OPPROTO glue(glue(op_movl_, REGNAME), _T1)(void)
+{
+ SET_REG (T1);
+}
+
+#undef REG
+#undef REGNAME
+#undef SET_REG