Browse Source
The CRIS target is deprecated since v9.0 (commit c7bbef4023
"docs: mark CRIS support as deprecated").
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Acked-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
Message-ID: <20240904143603.52934-14-philmd@linaro.org>
pull/273/head
29 changed files with 9 additions and 7306 deletions
@ -1,2 +0,0 @@ |
|||
config CRIS |
|||
bool |
|||
@ -1,16 +0,0 @@ |
|||
/*
|
|||
* CRIS cpu parameters for qemu. |
|||
* |
|||
* Copyright (c) 2007 AXIS Communications AB |
|||
* SPDX-License-Identifier: LGPL-2.0+ |
|||
*/ |
|||
|
|||
#ifndef CRIS_CPU_PARAM_H |
|||
#define CRIS_CPU_PARAM_H |
|||
|
|||
#define TARGET_LONG_BITS 32 |
|||
#define TARGET_PAGE_BITS 13 |
|||
#define TARGET_PHYS_ADDR_SPACE_BITS 32 |
|||
#define TARGET_VIRT_ADDR_SPACE_BITS 32 |
|||
|
|||
#endif |
|||
@ -1,32 +0,0 @@ |
|||
/*
|
|||
* QEMU CRIS CPU QOM header (target agnostic) |
|||
* |
|||
* Copyright (c) 2012 SUSE LINUX Products GmbH |
|||
* |
|||
* 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.1 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/lgpl-2.1.html>
|
|||
*/ |
|||
#ifndef QEMU_CRIS_CPU_QOM_H |
|||
#define QEMU_CRIS_CPU_QOM_H |
|||
|
|||
#include "hw/core/cpu.h" |
|||
|
|||
#define TYPE_CRIS_CPU "cris-cpu" |
|||
|
|||
OBJECT_DECLARE_CPU_TYPE(CRISCPU, CRISCPUClass, CRIS_CPU) |
|||
|
|||
#define CRIS_CPU_TYPE_SUFFIX "-" TYPE_CRIS_CPU |
|||
#define CRIS_CPU_TYPE_NAME(name) (name CRIS_CPU_TYPE_SUFFIX) |
|||
|
|||
#endif |
|||
@ -1,323 +0,0 @@ |
|||
/*
|
|||
* QEMU CRIS CPU |
|||
* |
|||
* Copyright (c) 2008 AXIS Communications AB |
|||
* Written by Edgar E. Iglesias. |
|||
* |
|||
* Copyright (c) 2012 SUSE LINUX Products GmbH |
|||
* |
|||
* 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.1 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/lgpl-2.1.html>
|
|||
*/ |
|||
|
|||
#include "qemu/osdep.h" |
|||
#include "qapi/error.h" |
|||
#include "qemu/qemu-print.h" |
|||
#include "cpu.h" |
|||
#include "mmu.h" |
|||
|
|||
|
|||
static void cris_cpu_set_pc(CPUState *cs, vaddr value) |
|||
{ |
|||
CRISCPU *cpu = CRIS_CPU(cs); |
|||
|
|||
cpu->env.pc = value; |
|||
} |
|||
|
|||
static vaddr cris_cpu_get_pc(CPUState *cs) |
|||
{ |
|||
CRISCPU *cpu = CRIS_CPU(cs); |
|||
|
|||
return cpu->env.pc; |
|||
} |
|||
|
|||
static void cris_restore_state_to_opc(CPUState *cs, |
|||
const TranslationBlock *tb, |
|||
const uint64_t *data) |
|||
{ |
|||
CRISCPU *cpu = CRIS_CPU(cs); |
|||
|
|||
cpu->env.pc = data[0]; |
|||
} |
|||
|
|||
static bool cris_cpu_has_work(CPUState *cs) |
|||
{ |
|||
return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); |
|||
} |
|||
|
|||
static int cris_cpu_mmu_index(CPUState *cs, bool ifetch) |
|||
{ |
|||
return !!(cpu_env(cs)->pregs[PR_CCS] & U_FLAG); |
|||
} |
|||
|
|||
static void cris_cpu_reset_hold(Object *obj, ResetType type) |
|||
{ |
|||
CPUState *cs = CPU(obj); |
|||
CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(obj); |
|||
CPUCRISState *env = cpu_env(cs); |
|||
uint32_t vr; |
|||
|
|||
if (ccc->parent_phases.hold) { |
|||
ccc->parent_phases.hold(obj, type); |
|||
} |
|||
|
|||
vr = env->pregs[PR_VR]; |
|||
memset(env, 0, offsetof(CPUCRISState, end_reset_fields)); |
|||
env->pregs[PR_VR] = vr; |
|||
|
|||
#if defined(CONFIG_USER_ONLY) |
|||
/* start in user mode with interrupts enabled. */ |
|||
env->pregs[PR_CCS] |= U_FLAG | I_FLAG | P_FLAG; |
|||
#else |
|||
cris_mmu_init(env); |
|||
env->pregs[PR_CCS] = 0; |
|||
#endif |
|||
} |
|||
|
|||
static ObjectClass *cris_cpu_class_by_name(const char *cpu_model) |
|||
{ |
|||
ObjectClass *oc; |
|||
char *typename; |
|||
|
|||
#if defined(CONFIG_USER_ONLY) |
|||
if (strcasecmp(cpu_model, "any") == 0) { |
|||
return object_class_by_name(CRIS_CPU_TYPE_NAME("crisv32")); |
|||
} |
|||
#endif |
|||
|
|||
typename = g_strdup_printf(CRIS_CPU_TYPE_NAME("%s"), cpu_model); |
|||
oc = object_class_by_name(typename); |
|||
g_free(typename); |
|||
|
|||
return oc; |
|||
} |
|||
|
|||
static void cris_cpu_realizefn(DeviceState *dev, Error **errp) |
|||
{ |
|||
CPUState *cs = CPU(dev); |
|||
CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(dev); |
|||
Error *local_err = NULL; |
|||
|
|||
cpu_exec_realizefn(cs, &local_err); |
|||
if (local_err != NULL) { |
|||
error_propagate(errp, local_err); |
|||
return; |
|||
} |
|||
|
|||
cpu_reset(cs); |
|||
qemu_init_vcpu(cs); |
|||
|
|||
ccc->parent_realize(dev, errp); |
|||
} |
|||
|
|||
#ifndef CONFIG_USER_ONLY |
|||
static void cris_cpu_set_irq(void *opaque, int irq, int level) |
|||
{ |
|||
CRISCPU *cpu = opaque; |
|||
CPUState *cs = CPU(cpu); |
|||
int type = irq == CRIS_CPU_IRQ ? CPU_INTERRUPT_HARD : CPU_INTERRUPT_NMI; |
|||
|
|||
if (irq == CRIS_CPU_IRQ) { |
|||
/*
|
|||
* The PIC passes us the vector for the IRQ as the value it sends |
|||
* over the qemu_irq line |
|||
*/ |
|||
cpu->env.interrupt_vector = level; |
|||
} |
|||
|
|||
if (level) { |
|||
cpu_interrupt(cs, type); |
|||
} else { |
|||
cpu_reset_interrupt(cs, type); |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
static void cris_disas_set_info(CPUState *cpu, disassemble_info *info) |
|||
{ |
|||
if (cpu_env(cpu)->pregs[PR_VR] != 32) { |
|||
info->mach = bfd_mach_cris_v0_v10; |
|||
info->print_insn = print_insn_crisv10; |
|||
} else { |
|||
info->mach = bfd_mach_cris_v32; |
|||
info->print_insn = print_insn_crisv32; |
|||
} |
|||
} |
|||
|
|||
static void cris_cpu_initfn(Object *obj) |
|||
{ |
|||
CRISCPU *cpu = CRIS_CPU(obj); |
|||
CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(obj); |
|||
CPUCRISState *env = &cpu->env; |
|||
|
|||
env->pregs[PR_VR] = ccc->vr; |
|||
|
|||
#ifndef CONFIG_USER_ONLY |
|||
/* IRQ and NMI lines. */ |
|||
qdev_init_gpio_in(DEVICE(cpu), cris_cpu_set_irq, 2); |
|||
#endif |
|||
} |
|||
|
|||
#ifndef CONFIG_USER_ONLY |
|||
#include "hw/core/sysemu-cpu-ops.h" |
|||
|
|||
static const struct SysemuCPUOps cris_sysemu_ops = { |
|||
.get_phys_page_debug = cris_cpu_get_phys_page_debug, |
|||
}; |
|||
#endif |
|||
|
|||
#include "hw/core/tcg-cpu-ops.h" |
|||
|
|||
static const TCGCPUOps crisv10_tcg_ops = { |
|||
.initialize = cris_initialize_crisv10_tcg, |
|||
.restore_state_to_opc = cris_restore_state_to_opc, |
|||
|
|||
#ifndef CONFIG_USER_ONLY |
|||
.tlb_fill = cris_cpu_tlb_fill, |
|||
.cpu_exec_interrupt = cris_cpu_exec_interrupt, |
|||
.cpu_exec_halt = cris_cpu_has_work, |
|||
.do_interrupt = crisv10_cpu_do_interrupt, |
|||
#endif /* !CONFIG_USER_ONLY */ |
|||
}; |
|||
|
|||
static const TCGCPUOps crisv32_tcg_ops = { |
|||
.initialize = cris_initialize_tcg, |
|||
.restore_state_to_opc = cris_restore_state_to_opc, |
|||
|
|||
#ifndef CONFIG_USER_ONLY |
|||
.tlb_fill = cris_cpu_tlb_fill, |
|||
.cpu_exec_interrupt = cris_cpu_exec_interrupt, |
|||
.cpu_exec_halt = cris_cpu_has_work, |
|||
.do_interrupt = cris_cpu_do_interrupt, |
|||
#endif /* !CONFIG_USER_ONLY */ |
|||
}; |
|||
|
|||
static void crisv8_cpu_class_init(ObjectClass *oc, void *data) |
|||
{ |
|||
CPUClass *cc = CPU_CLASS(oc); |
|||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); |
|||
|
|||
ccc->vr = 8; |
|||
cc->gdb_read_register = crisv10_cpu_gdb_read_register; |
|||
cc->tcg_ops = &crisv10_tcg_ops; |
|||
} |
|||
|
|||
static void crisv9_cpu_class_init(ObjectClass *oc, void *data) |
|||
{ |
|||
CPUClass *cc = CPU_CLASS(oc); |
|||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); |
|||
|
|||
ccc->vr = 9; |
|||
cc->gdb_read_register = crisv10_cpu_gdb_read_register; |
|||
cc->tcg_ops = &crisv10_tcg_ops; |
|||
} |
|||
|
|||
static void crisv10_cpu_class_init(ObjectClass *oc, void *data) |
|||
{ |
|||
CPUClass *cc = CPU_CLASS(oc); |
|||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); |
|||
|
|||
ccc->vr = 10; |
|||
cc->gdb_read_register = crisv10_cpu_gdb_read_register; |
|||
cc->tcg_ops = &crisv10_tcg_ops; |
|||
} |
|||
|
|||
static void crisv11_cpu_class_init(ObjectClass *oc, void *data) |
|||
{ |
|||
CPUClass *cc = CPU_CLASS(oc); |
|||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); |
|||
|
|||
ccc->vr = 11; |
|||
cc->gdb_read_register = crisv10_cpu_gdb_read_register; |
|||
cc->tcg_ops = &crisv10_tcg_ops; |
|||
} |
|||
|
|||
static void crisv17_cpu_class_init(ObjectClass *oc, void *data) |
|||
{ |
|||
CPUClass *cc = CPU_CLASS(oc); |
|||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); |
|||
|
|||
ccc->vr = 17; |
|||
cc->gdb_read_register = crisv10_cpu_gdb_read_register; |
|||
cc->tcg_ops = &crisv10_tcg_ops; |
|||
} |
|||
|
|||
static void crisv32_cpu_class_init(ObjectClass *oc, void *data) |
|||
{ |
|||
CPUClass *cc = CPU_CLASS(oc); |
|||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); |
|||
|
|||
ccc->vr = 32; |
|||
cc->tcg_ops = &crisv32_tcg_ops; |
|||
} |
|||
|
|||
static void cris_cpu_class_init(ObjectClass *oc, void *data) |
|||
{ |
|||
DeviceClass *dc = DEVICE_CLASS(oc); |
|||
CPUClass *cc = CPU_CLASS(oc); |
|||
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); |
|||
ResettableClass *rc = RESETTABLE_CLASS(oc); |
|||
|
|||
device_class_set_parent_realize(dc, cris_cpu_realizefn, |
|||
&ccc->parent_realize); |
|||
|
|||
resettable_class_set_parent_phases(rc, NULL, cris_cpu_reset_hold, NULL, |
|||
&ccc->parent_phases); |
|||
|
|||
cc->class_by_name = cris_cpu_class_by_name; |
|||
cc->has_work = cris_cpu_has_work; |
|||
cc->mmu_index = cris_cpu_mmu_index; |
|||
cc->dump_state = cris_cpu_dump_state; |
|||
cc->set_pc = cris_cpu_set_pc; |
|||
cc->get_pc = cris_cpu_get_pc; |
|||
cc->gdb_read_register = cris_cpu_gdb_read_register; |
|||
cc->gdb_write_register = cris_cpu_gdb_write_register; |
|||
#ifndef CONFIG_USER_ONLY |
|||
dc->vmsd = &vmstate_cris_cpu; |
|||
cc->sysemu_ops = &cris_sysemu_ops; |
|||
#endif |
|||
|
|||
cc->gdb_num_core_regs = 49; |
|||
cc->gdb_stop_before_watchpoint = true; |
|||
|
|||
cc->disas_set_info = cris_disas_set_info; |
|||
} |
|||
|
|||
#define DEFINE_CRIS_CPU_TYPE(cpu_model, initfn) \ |
|||
{ \ |
|||
.parent = TYPE_CRIS_CPU, \ |
|||
.class_init = initfn, \ |
|||
.name = CRIS_CPU_TYPE_NAME(cpu_model), \ |
|||
} |
|||
|
|||
static const TypeInfo cris_cpu_model_type_infos[] = { |
|||
{ |
|||
.name = TYPE_CRIS_CPU, |
|||
.parent = TYPE_CPU, |
|||
.instance_size = sizeof(CRISCPU), |
|||
.instance_align = __alignof(CRISCPU), |
|||
.instance_init = cris_cpu_initfn, |
|||
.abstract = true, |
|||
.class_size = sizeof(CRISCPUClass), |
|||
.class_init = cris_cpu_class_init, |
|||
}, |
|||
DEFINE_CRIS_CPU_TYPE("crisv8", crisv8_cpu_class_init), |
|||
DEFINE_CRIS_CPU_TYPE("crisv9", crisv9_cpu_class_init), |
|||
DEFINE_CRIS_CPU_TYPE("crisv10", crisv10_cpu_class_init), |
|||
DEFINE_CRIS_CPU_TYPE("crisv11", crisv11_cpu_class_init), |
|||
DEFINE_CRIS_CPU_TYPE("crisv17", crisv17_cpu_class_init), |
|||
DEFINE_CRIS_CPU_TYPE("crisv32", crisv32_cpu_class_init), |
|||
}; |
|||
|
|||
DEFINE_TYPES(cris_cpu_model_type_infos) |
|||
@ -1,286 +0,0 @@ |
|||
/*
|
|||
* 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.1 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, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#ifndef CRIS_CPU_H |
|||
#define CRIS_CPU_H |
|||
|
|||
#include "cpu-qom.h" |
|||
#include "exec/cpu-defs.h" |
|||
|
|||
#define EXCP_NMI 1 |
|||
#define EXCP_GURU 2 |
|||
#define EXCP_BUSFAULT 3 |
|||
#define EXCP_IRQ 4 |
|||
#define EXCP_BREAK 5 |
|||
|
|||
/* CRIS-specific interrupt pending bits. */ |
|||
#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3 |
|||
|
|||
/* CRUS CPU device objects interrupt lines. */ |
|||
/* PIC passes the vector for the IRQ as the value of it sends over qemu_irq */ |
|||
#define CRIS_CPU_IRQ 0 |
|||
#define CRIS_CPU_NMI 1 |
|||
|
|||
/* Register aliases. R0 - R15 */ |
|||
#define R_FP 8 |
|||
#define R_SP 14 |
|||
#define R_ACR 15 |
|||
|
|||
/* Support regs, P0 - P15 */ |
|||
#define PR_BZ 0 |
|||
#define PR_VR 1 |
|||
#define PR_PID 2 |
|||
#define PR_SRS 3 |
|||
#define PR_WZ 4 |
|||
#define PR_EXS 5 |
|||
#define PR_EDA 6 |
|||
#define PR_PREFIX 6 /* On CRISv10 P6 is reserved, we use it as prefix. */ |
|||
#define PR_MOF 7 |
|||
#define PR_DZ 8 |
|||
#define PR_EBP 9 |
|||
#define PR_ERP 10 |
|||
#define PR_SRP 11 |
|||
#define PR_NRP 12 |
|||
#define PR_CCS 13 |
|||
#define PR_USP 14 |
|||
#define PRV10_BRP 14 |
|||
#define PR_SPC 15 |
|||
|
|||
/* CPU flags. */ |
|||
#define Q_FLAG 0x80000000 |
|||
#define M_FLAG_V32 0x40000000 |
|||
#define PFIX_FLAG 0x800 /* CRISv10 Only. */ |
|||
#define F_FLAG_V10 0x400 |
|||
#define P_FLAG_V10 0x200 |
|||
#define S_FLAG 0x200 |
|||
#define R_FLAG 0x100 |
|||
#define P_FLAG 0x80 |
|||
#define M_FLAG_V10 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 |
|||
|
|||
typedef struct { |
|||
uint32_t hi; |
|||
uint32_t lo; |
|||
} TLBSet; |
|||
|
|||
typedef struct CPUArchState { |
|||
uint32_t regs[16]; |
|||
/* P0 - P15 are referred to as special registers in the docs. */ |
|||
uint32_t pregs[16]; |
|||
|
|||
/* Pseudo register for the PC. Not directly accessible on CRIS. */ |
|||
uint32_t pc; |
|||
|
|||
/* Pseudo register for the kernel stack. */ |
|||
uint32_t ksp; |
|||
|
|||
/* Branch. */ |
|||
int dslot; |
|||
int btaken; |
|||
uint32_t btarget; |
|||
|
|||
/* 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; |
|||
/* X flag at the time of cc snapshot. */ |
|||
int cc_x; |
|||
|
|||
/* CRIS has certain insns that lockout interrupts. */ |
|||
int locked_irq; |
|||
int interrupt_vector; |
|||
int fault_vector; |
|||
int trap_vector; |
|||
|
|||
/* FIXME: add a check in the translator to avoid writing to support
|
|||
register sets beyond the 4th. The ISA allows up to 256! but in |
|||
practice there is no core that implements more than 4. |
|||
|
|||
Support function registers are used to control units close to the |
|||
core. Accesses do not pass down the normal hierarchy. |
|||
*/ |
|||
uint32_t sregs[4][16]; |
|||
|
|||
/* Linear feedback shift reg in the mmu. Used to provide pseudo
|
|||
randomness for the 'hint' the mmu gives to sw for choosing valid |
|||
sets on TLB refills. */ |
|||
uint32_t mmu_rand_lfsr; |
|||
|
|||
/*
|
|||
* 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. |
|||
*/ |
|||
TLBSet tlbsets[2][4][16]; |
|||
|
|||
/* Fields up to this point are cleared by a CPU reset */ |
|||
struct {} end_reset_fields; |
|||
|
|||
/* Members from load_info on are preserved across resets. */ |
|||
void *load_info; |
|||
} CPUCRISState; |
|||
|
|||
/**
|
|||
* CRISCPU: |
|||
* @env: #CPUCRISState |
|||
* |
|||
* A CRIS CPU. |
|||
*/ |
|||
struct ArchCPU { |
|||
CPUState parent_obj; |
|||
|
|||
CPUCRISState env; |
|||
}; |
|||
|
|||
/**
|
|||
* CRISCPUClass: |
|||
* @parent_realize: The parent class' realize handler. |
|||
* @parent_phases: The parent class' reset phase handlers. |
|||
* @vr: Version Register value. |
|||
* |
|||
* A CRIS CPU model. |
|||
*/ |
|||
struct CRISCPUClass { |
|||
CPUClass parent_class; |
|||
|
|||
DeviceRealize parent_realize; |
|||
ResettablePhases parent_phases; |
|||
|
|||
uint32_t vr; |
|||
}; |
|||
|
|||
#ifndef CONFIG_USER_ONLY |
|||
extern const VMStateDescription vmstate_cris_cpu; |
|||
|
|||
void cris_cpu_do_interrupt(CPUState *cpu); |
|||
void crisv10_cpu_do_interrupt(CPUState *cpu); |
|||
bool cris_cpu_exec_interrupt(CPUState *cpu, int int_req); |
|||
|
|||
bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size, |
|||
MMUAccessType access_type, int mmu_idx, |
|||
bool probe, uintptr_t retaddr); |
|||
hwaddr cris_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); |
|||
#endif |
|||
|
|||
void cris_cpu_dump_state(CPUState *cs, FILE *f, int flags); |
|||
|
|||
int crisv10_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); |
|||
int cris_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); |
|||
int cris_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); |
|||
|
|||
void cris_initialize_tcg(void); |
|||
void cris_initialize_crisv10_tcg(void); |
|||
|
|||
/* Instead of computing the condition codes after each CRIS instruction,
|
|||
* QEMU just stores one operand (called CC_SRC), the result |
|||
* (called CC_DEST) and the type of operation (called CC_OP). When the |
|||
* condition codes are needed, the condition codes can be calculated |
|||
* using this information. Condition codes are not generated if they |
|||
* are only needed for conditional branches. |
|||
*/ |
|||
enum { |
|||
CC_OP_DYNAMIC, /* Use env->cc_op */ |
|||
CC_OP_FLAGS, |
|||
CC_OP_CMP, |
|||
CC_OP_MOVE, |
|||
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_MSTEP, |
|||
CC_OP_BOUND, |
|||
|
|||
CC_OP_OR, |
|||
CC_OP_AND, |
|||
CC_OP_XOR, |
|||
CC_OP_LSL, |
|||
CC_OP_LSR, |
|||
CC_OP_ASR, |
|||
CC_OP_LZ |
|||
}; |
|||
|
|||
/* CRIS uses 8k pages. */ |
|||
#define MMAP_SHIFT TARGET_PAGE_BITS |
|||
|
|||
#define CPU_RESOLVING_TYPE TYPE_CRIS_CPU |
|||
|
|||
/* MMU modes definitions */ |
|||
#define MMU_USER_IDX 1 |
|||
|
|||
/* Support function regs. */ |
|||
#define SFR_RW_GC_CFG 0][0 |
|||
#define SFR_RW_MM_CFG env->pregs[PR_SRS]][0 |
|||
#define SFR_RW_MM_KBASE_LO env->pregs[PR_SRS]][1 |
|||
#define SFR_RW_MM_KBASE_HI env->pregs[PR_SRS]][2 |
|||
#define SFR_R_MM_CAUSE env->pregs[PR_SRS]][3 |
|||
#define SFR_RW_MM_TLB_SEL env->pregs[PR_SRS]][4 |
|||
#define SFR_RW_MM_TLB_LO env->pregs[PR_SRS]][5 |
|||
#define SFR_RW_MM_TLB_HI env->pregs[PR_SRS]][6 |
|||
|
|||
#include "exec/cpu-all.h" |
|||
|
|||
static inline void cpu_get_tb_cpu_state(CPUCRISState *env, vaddr *pc, |
|||
uint64_t *cs_base, uint32_t *flags) |
|||
{ |
|||
*pc = env->pc; |
|||
*cs_base = 0; |
|||
*flags = env->dslot | |
|||
(env->pregs[PR_CCS] & (S_FLAG | P_FLAG | U_FLAG |
|||
| X_FLAG | PFIX_FLAG)); |
|||
} |
|||
|
|||
#endif |
|||
@ -1,112 +0,0 @@ |
|||
/*
|
|||
* CRISv10 insn decoding macros. |
|||
* |
|||
* Copyright (c) 2010 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.1 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/>.
|
|||
*/ |
|||
|
|||
#ifndef TARGET_CRIS_CRISV10_DECODE_H |
|||
#define TARGET_CRIS_CRISV10_DECODE_H |
|||
|
|||
#define CRISV10_MODE_QIMMEDIATE 0 |
|||
#define CRISV10_MODE_REG 1 |
|||
#define CRISV10_MODE_INDIRECT 2 |
|||
#define CRISV10_MODE_AUTOINC 3 |
|||
|
|||
/* Quick Immediate. */ |
|||
#define CRISV10_QIMM_BCC_R0 0 |
|||
#define CRISV10_QIMM_BCC_R1 1 |
|||
#define CRISV10_QIMM_BCC_R2 2 |
|||
#define CRISV10_QIMM_BCC_R3 3 |
|||
|
|||
#define CRISV10_QIMM_BDAP_R0 4 |
|||
#define CRISV10_QIMM_BDAP_R1 5 |
|||
#define CRISV10_QIMM_BDAP_R2 6 |
|||
#define CRISV10_QIMM_BDAP_R3 7 |
|||
|
|||
#define CRISV10_QIMM_ADDQ 8 |
|||
#define CRISV10_QIMM_MOVEQ 9 |
|||
#define CRISV10_QIMM_SUBQ 10 |
|||
#define CRISV10_QIMM_CMPQ 11 |
|||
#define CRISV10_QIMM_ANDQ 12 |
|||
#define CRISV10_QIMM_ORQ 13 |
|||
#define CRISV10_QIMM_ASHQ 14 |
|||
#define CRISV10_QIMM_LSHQ 15 |
|||
|
|||
|
|||
#define CRISV10_REG_ADDX 0 |
|||
#define CRISV10_REG_MOVX 1 |
|||
#define CRISV10_REG_SUBX 2 |
|||
#define CRISV10_REG_LSL 3 |
|||
#define CRISV10_REG_ADDI 4 |
|||
#define CRISV10_REG_BIAP 5 |
|||
#define CRISV10_REG_NEG 6 |
|||
#define CRISV10_REG_BOUND 7 |
|||
#define CRISV10_REG_ADD 8 |
|||
#define CRISV10_REG_MOVE_R 9 |
|||
#define CRISV10_REG_MOVE_SPR_R 9 |
|||
#define CRISV10_REG_MOVE_R_SPR 8 |
|||
#define CRISV10_REG_SUB 10 |
|||
#define CRISV10_REG_CMP 11 |
|||
#define CRISV10_REG_AND 12 |
|||
#define CRISV10_REG_OR 13 |
|||
#define CRISV10_REG_ASR 14 |
|||
#define CRISV10_REG_LSR 15 |
|||
|
|||
#define CRISV10_REG_BTST 3 |
|||
#define CRISV10_REG_SCC 4 |
|||
#define CRISV10_REG_SETF 6 |
|||
#define CRISV10_REG_CLEARF 7 |
|||
#define CRISV10_REG_BIAP 5 |
|||
#define CRISV10_REG_ABS 10 |
|||
#define CRISV10_REG_DSTEP 11 |
|||
#define CRISV10_REG_LZ 12 |
|||
#define CRISV10_REG_NOT 13 |
|||
#define CRISV10_REG_SWAP 13 |
|||
#define CRISV10_REG_XOR 14 |
|||
#define CRISV10_REG_MSTEP 15 |
|||
|
|||
/* Indirect, var size. */ |
|||
#define CRISV10_IND_TEST 14 |
|||
#define CRISV10_IND_MUL 4 |
|||
#define CRISV10_IND_BDAP_M 5 |
|||
#define CRISV10_IND_ADD 8 |
|||
#define CRISV10_IND_MOVE_M_R 9 |
|||
|
|||
|
|||
/* indirect fixed size. */ |
|||
#define CRISV10_IND_ADDX 0 |
|||
#define CRISV10_IND_MOVX 1 |
|||
#define CRISV10_IND_SUBX 2 |
|||
#define CRISV10_IND_CMPX 3 |
|||
#define CRISV10_IND_JUMP_M 4 |
|||
#define CRISV10_IND_DIP 5 |
|||
#define CRISV10_IND_JUMP_R 6 |
|||
#define CRISV17_IND_ADDC 6 |
|||
#define CRISV10_IND_BOUND 7 |
|||
#define CRISV10_IND_BCC_M 7 |
|||
#define CRISV10_IND_MOVE_M_SPR 8 |
|||
#define CRISV10_IND_MOVE_SPR_M 9 |
|||
#define CRISV10_IND_SUB 10 |
|||
#define CRISV10_IND_CMP 11 |
|||
#define CRISV10_IND_AND 12 |
|||
#define CRISV10_IND_OR 13 |
|||
#define CRISV10_IND_MOVE_R_M 15 |
|||
|
|||
#define CRISV10_IND_MOVEM_M_R 14 |
|||
#define CRISV10_IND_MOVEM_R_M 15 |
|||
|
|||
#endif |
|||
@ -1,133 +0,0 @@ |
|||
/*
|
|||
* CRIS insn decoding macros. |
|||
* |
|||
* 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.1 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/>.
|
|||
*/ |
|||
|
|||
#ifndef CRISV32_DECODE_H |
|||
#define CRISV32_DECODE_H |
|||
|
|||
/* Convenient binary macros. */ |
|||
#define HEX__(n) 0x##n##LU |
|||
#define B8__(x) ((x&0x0000000FLU)?1:0) \ |
|||
+ ((x&0x000000F0LU)?2:0) \ |
|||
+ ((x&0x00000F00LU)?4:0) \ |
|||
+ ((x&0x0000F000LU)?8:0) \ |
|||
+ ((x&0x000F0000LU)?16:0) \ |
|||
+ ((x&0x00F00000LU)?32:0) \ |
|||
+ ((x&0x0F000000LU)?64:0) \ |
|||
+ ((x&0xF0000000LU)?128:0) |
|||
#define B8(d) ((unsigned char)B8__(HEX__(d))) |
|||
|
|||
/* Quick imm. */ |
|||
#define DEC_BCCQ {B8(00000000), B8(11110000)} |
|||
#define DEC_ADDOQ {B8(00010000), B8(11110000)} |
|||
#define DEC_ADDQ {B8(00100000), B8(11111100)} |
|||
#define DEC_MOVEQ {B8(00100100), B8(11111100)} |
|||
#define DEC_SUBQ {B8(00101000), B8(11111100)} |
|||
#define DEC_CMPQ {B8(00101100), B8(11111100)} |
|||
#define DEC_ANDQ {B8(00110000), B8(11111100)} |
|||
#define DEC_ORQ {B8(00110100), B8(11111100)} |
|||
#define DEC_BTSTQ {B8(00111000), B8(11111110)} |
|||
#define DEC_ASRQ {B8(00111010), B8(11111110)} |
|||
#define DEC_LSLQ {B8(00111100), B8(11111110)} |
|||
#define DEC_LSRQ {B8(00111110), B8(11111110)} |
|||
|
|||
/* Register. */ |
|||
#define DEC_MOVU_R {B8(01000100), B8(11111110)} |
|||
#define DEC_MOVU_R {B8(01000100), B8(11111110)} |
|||
#define DEC_MOVS_R {B8(01000110), B8(11111110)} |
|||
#define DEC_MOVE_R {B8(01100100), B8(11111100)} |
|||
#define DEC_MOVE_RP {B8(01100011), B8(11111111)} |
|||
#define DEC_MOVE_PR {B8(01100111), B8(11111111)} |
|||
#define DEC_DSTEP_R {B8(01101111), B8(11111111)} |
|||
#define DEC_MOVE_RS {B8(10110111), B8(11111111)} |
|||
#define DEC_MOVE_SR {B8(11110111), B8(11111111)} |
|||
#define DEC_ADDU_R {B8(01000000), B8(11111110)} |
|||
#define DEC_ADDS_R {B8(01000010), B8(11111110)} |
|||
#define DEC_ADD_R {B8(01100000), B8(11111100)} |
|||
#define DEC_ADDI_R {B8(01010000), B8(11111100)} |
|||
#define DEC_MULS_R {B8(11010000), B8(11111100)} |
|||
#define DEC_MULU_R {B8(10010000), B8(11111100)} |
|||
#define DEC_ADDI_ACR {B8(01010100), B8(11111100)} |
|||
#define DEC_NEG_R {B8(01011000), B8(11111100)} |
|||
#define DEC_BOUND_R {B8(01011100), B8(11111100)} |
|||
#define DEC_SUBU_R {B8(01001000), B8(11111110)} |
|||
#define DEC_SUBS_R {B8(01001010), B8(11111110)} |
|||
#define DEC_SUB_R {B8(01101000), B8(11111100)} |
|||
#define DEC_CMP_R {B8(01101100), B8(11111100)} |
|||
#define DEC_AND_R {B8(01110000), B8(11111100)} |
|||
#define DEC_ABS_R {B8(01101011), B8(11111111)} |
|||
#define DEC_LZ_R {B8(01110011), B8(11111111)} |
|||
#define DEC_MCP_R {B8(01111111), B8(11111111)} |
|||
#define DEC_SWAP_R {B8(01110111), B8(11111111)} |
|||
#define DEC_XOR_R {B8(01111011), B8(11111111)} |
|||
#define DEC_LSL_R {B8(01001100), B8(11111100)} |
|||
#define DEC_LSR_R {B8(01111100), B8(11111100)} |
|||
#define DEC_ASR_R {B8(01111000), B8(11111100)} |
|||
#define DEC_OR_R {B8(01110100), B8(11111100)} |
|||
#define DEC_BTST_R {B8(01001111), B8(11111111)} |
|||
|
|||
/* Fixed. */ |
|||
#define DEC_SETF {B8(01011011), B8(11111111)} |
|||
#define DEC_CLEARF {B8(01011111), B8(11111111)} |
|||
|
|||
/* Memory. */ |
|||
#define DEC_ADDU_M {B8(10000000), B8(10111110)} |
|||
#define DEC_ADDS_M {B8(10000010), B8(10111110)} |
|||
#define DEC_MOVU_M {B8(10000100), B8(10111110)} |
|||
#define DEC_MOVS_M {B8(10000110), B8(10111110)} |
|||
#define DEC_SUBU_M {B8(10001000), B8(10111110)} |
|||
#define DEC_SUBS_M {B8(10001010), B8(10111110)} |
|||
#define DEC_CMPU_M {B8(10001100), B8(10111110)} |
|||
#define DEC_CMPS_M {B8(10001110), B8(10111110)} |
|||
#define DEC_ADDO_M {B8(10010100), B8(10111100)} |
|||
#define DEC_BOUND_M {B8(10011100), B8(10111100)} |
|||
#define DEC_ADD_M {B8(10100000), B8(10111100)} |
|||
#define DEC_MOVE_MR {B8(10100100), B8(10111100)} |
|||
#define DEC_SUB_M {B8(10101000), B8(10111100)} |
|||
#define DEC_CMP_M {B8(10101100), B8(10111100)} |
|||
#define DEC_AND_M {B8(10110000), B8(10111100)} |
|||
#define DEC_OR_M {B8(10110100), B8(10111100)} |
|||
#define DEC_TEST_M {B8(10111000), B8(10111100)} |
|||
#define DEC_MOVE_RM {B8(10111100), B8(10111100)} |
|||
|
|||
#define DEC_ADDC_R {B8(01010111), B8(11111111)} |
|||
#define DEC_ADDC_MR {B8(10011010), B8(10111111)} |
|||
#define DEC_LAPCQ {B8(10010111), B8(11111111)} |
|||
#define DEC_LAPC_IM {B8(11010111), B8(11111111)} |
|||
|
|||
#define DEC_MOVE_MP {B8(10100011), B8(10111111)} |
|||
#define DEC_MOVE_PM {B8(10100111), B8(10111111)} |
|||
|
|||
#define DEC_SCC_R {B8(01010011), B8(11111111)} |
|||
#define DEC_RFE_ETC {B8(10010011), B8(11111111)} |
|||
#define DEC_JUMP_P {B8(10011111), B8(11111111)} |
|||
#define DEC_BCC_IM {B8(11011111), B8(11111111)} |
|||
#define DEC_JAS_R {B8(10011011), B8(11111111)} |
|||
#define DEC_JASC_R {B8(10110011), B8(11111111)} |
|||
#define DEC_JAS_IM {B8(11011011), B8(11111111)} |
|||
#define DEC_JASC_IM {B8(11110011), B8(11111111)} |
|||
#define DEC_BAS_IM {B8(11101011), B8(11111111)} |
|||
#define DEC_BASC_IM {B8(11101111), B8(11111111)} |
|||
#define DEC_MOVEM_MR {B8(10111011), B8(10111111)} |
|||
#define DEC_MOVEM_RM {B8(10111111), B8(10111111)} |
|||
|
|||
#define DEC_FTAG_FIDX_D_M {B8(10101011), B8(11111111)} |
|||
#define DEC_FTAG_FIDX_I_M {B8(11010011), B8(11111111)} |
|||
|
|||
#endif |
|||
@ -1,127 +0,0 @@ |
|||
/*
|
|||
* CRIS gdb server stub |
|||
* |
|||
* Copyright (c) 2003-2005 Fabrice Bellard |
|||
* Copyright (c) 2013 SUSE LINUX Products GmbH |
|||
* |
|||
* 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.1 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 "gdbstub/helpers.h" |
|||
|
|||
int crisv10_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) |
|||
{ |
|||
CPUCRISState *env = cpu_env(cs); |
|||
|
|||
if (n < 15) { |
|||
return gdb_get_reg32(mem_buf, env->regs[n]); |
|||
} |
|||
|
|||
if (n == 15) { |
|||
return gdb_get_reg32(mem_buf, env->pc); |
|||
} |
|||
|
|||
if (n < 32) { |
|||
switch (n) { |
|||
case 16: |
|||
return gdb_get_reg8(mem_buf, env->pregs[n - 16]); |
|||
case 17: |
|||
return gdb_get_reg8(mem_buf, env->pregs[n - 16]); |
|||
case 20: |
|||
case 21: |
|||
return gdb_get_reg16(mem_buf, env->pregs[n - 16]); |
|||
default: |
|||
if (n >= 23) { |
|||
return gdb_get_reg32(mem_buf, env->pregs[n - 16]); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
int cris_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) |
|||
{ |
|||
CPUCRISState *env = cpu_env(cs); |
|||
uint8_t srs; |
|||
|
|||
srs = env->pregs[PR_SRS]; |
|||
if (n < 16) { |
|||
return gdb_get_reg32(mem_buf, env->regs[n]); |
|||
} |
|||
|
|||
if (n >= 21 && n < 32) { |
|||
return gdb_get_reg32(mem_buf, env->pregs[n - 16]); |
|||
} |
|||
if (n >= 33 && n < 49) { |
|||
return gdb_get_reg32(mem_buf, env->sregs[srs][n - 33]); |
|||
} |
|||
switch (n) { |
|||
case 16: |
|||
return gdb_get_reg8(mem_buf, env->pregs[0]); |
|||
case 17: |
|||
return gdb_get_reg8(mem_buf, env->pregs[1]); |
|||
case 18: |
|||
return gdb_get_reg32(mem_buf, env->pregs[2]); |
|||
case 19: |
|||
return gdb_get_reg8(mem_buf, srs); |
|||
case 20: |
|||
return gdb_get_reg16(mem_buf, env->pregs[4]); |
|||
case 32: |
|||
return gdb_get_reg32(mem_buf, env->pc); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int cris_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) |
|||
{ |
|||
CPUCRISState *env = cpu_env(cs); |
|||
uint32_t tmp; |
|||
|
|||
if (n > 49) { |
|||
return 0; |
|||
} |
|||
|
|||
tmp = ldl_p(mem_buf); |
|||
|
|||
if (n < 16) { |
|||
env->regs[n] = tmp; |
|||
} |
|||
|
|||
if (n >= 21 && n < 32) { |
|||
env->pregs[n - 16] = tmp; |
|||
} |
|||
|
|||
/* FIXME: Should support function regs be writable? */ |
|||
switch (n) { |
|||
case 16: |
|||
return 1; |
|||
case 17: |
|||
return 1; |
|||
case 18: |
|||
env->pregs[PR_PID] = tmp; |
|||
break; |
|||
case 19: |
|||
return 1; |
|||
case 20: |
|||
return 2; |
|||
case 32: |
|||
env->pc = tmp; |
|||
break; |
|||
} |
|||
|
|||
return 4; |
|||
} |
|||
@ -1,287 +0,0 @@ |
|||
/*
|
|||
* 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.1 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 "qemu/log.h" |
|||
#include "cpu.h" |
|||
#include "hw/core/tcg-cpu-ops.h" |
|||
#include "mmu.h" |
|||
#include "qemu/host-utils.h" |
|||
#include "exec/exec-all.h" |
|||
#include "exec/cpu_ldst.h" |
|||
#include "exec/helper-proto.h" |
|||
|
|||
|
|||
//#define CRIS_HELPER_DEBUG
|
|||
|
|||
|
|||
#ifdef CRIS_HELPER_DEBUG |
|||
#define D(x) x |
|||
#define D_LOG(...) qemu_log(__VA_ARGS__) |
|||
#else |
|||
#define D(x) |
|||
#define D_LOG(...) do { } while (0) |
|||
#endif |
|||
|
|||
static void cris_shift_ccs(CPUCRISState *env) |
|||
{ |
|||
uint32_t ccs; |
|||
/* Apply the ccs shift. */ |
|||
ccs = env->pregs[PR_CCS]; |
|||
ccs = ((ccs & 0xc0000000) | ((ccs << 12) >> 2)) & ~0x3ff; |
|||
env->pregs[PR_CCS] = ccs; |
|||
} |
|||
|
|||
bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size, |
|||
MMUAccessType access_type, int mmu_idx, |
|||
bool probe, uintptr_t retaddr) |
|||
{ |
|||
CPUCRISState *env = cpu_env(cs); |
|||
struct cris_mmu_result res; |
|||
int prot, miss; |
|||
target_ulong phy; |
|||
|
|||
miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK, |
|||
access_type, mmu_idx, 0); |
|||
if (likely(!miss)) { |
|||
/*
|
|||
* Mask off the cache selection bit. The ETRAX busses do not |
|||
* see the top bit. |
|||
*/ |
|||
phy = res.phy & ~0x80000000; |
|||
prot = res.prot; |
|||
tlb_set_page(cs, address & TARGET_PAGE_MASK, phy, |
|||
prot, mmu_idx, TARGET_PAGE_SIZE); |
|||
return true; |
|||
} |
|||
|
|||
if (probe) { |
|||
return false; |
|||
} |
|||
|
|||
if (cs->exception_index == EXCP_BUSFAULT) { |
|||
cpu_abort(cs, "CRIS: Illegal recursive bus fault." |
|||
"addr=%" VADDR_PRIx " access_type=%d\n", |
|||
address, access_type); |
|||
} |
|||
|
|||
env->pregs[PR_EDA] = address; |
|||
cs->exception_index = EXCP_BUSFAULT; |
|||
env->fault_vector = res.bf_vec; |
|||
if (retaddr) { |
|||
if (cpu_restore_state(cs, retaddr)) { |
|||
/* Evaluate flags after retranslation. */ |
|||
helper_top_evaluate_flags(env); |
|||
} |
|||
} |
|||
cpu_loop_exit(cs); |
|||
} |
|||
|
|||
void crisv10_cpu_do_interrupt(CPUState *cs) |
|||
{ |
|||
CPUCRISState *env = cpu_env(cs); |
|||
int ex_vec = -1; |
|||
|
|||
D_LOG("exception index=%d interrupt_req=%d\n", |
|||
cs->exception_index, |
|||
cs->interrupt_request); |
|||
|
|||
if (env->dslot) { |
|||
/* CRISv10 never takes interrupts while in a delay-slot. */ |
|||
cpu_abort(cs, "CRIS: Interrupt on delay-slot\n"); |
|||
} |
|||
|
|||
assert(!(env->pregs[PR_CCS] & PFIX_FLAG)); |
|||
switch (cs->exception_index) { |
|||
case EXCP_BREAK: |
|||
/* These exceptions are generated by the core itself.
|
|||
ERP should point to the insn following the brk. */ |
|||
ex_vec = env->trap_vector; |
|||
env->pregs[PRV10_BRP] = env->pc; |
|||
break; |
|||
|
|||
case EXCP_NMI: |
|||
/* NMI is hardwired to vector zero. */ |
|||
ex_vec = 0; |
|||
env->pregs[PR_CCS] &= ~M_FLAG_V10; |
|||
env->pregs[PRV10_BRP] = env->pc; |
|||
break; |
|||
|
|||
case EXCP_BUSFAULT: |
|||
cpu_abort(cs, "Unhandled busfault"); |
|||
break; |
|||
|
|||
default: |
|||
/* The interrupt controller gives us the vector. */ |
|||
ex_vec = env->interrupt_vector; |
|||
/* Normal interrupts are taken between
|
|||
TB's. env->pc is valid here. */ |
|||
env->pregs[PR_ERP] = env->pc; |
|||
break; |
|||
} |
|||
|
|||
if (env->pregs[PR_CCS] & U_FLAG) { |
|||
/* Swap stack pointers. */ |
|||
env->pregs[PR_USP] = env->regs[R_SP]; |
|||
env->regs[R_SP] = env->ksp; |
|||
} |
|||
|
|||
/* Now that we are in kernel mode, load the handlers address. */ |
|||
env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4); |
|||
env->locked_irq = 1; |
|||
env->pregs[PR_CCS] |= F_FLAG_V10; /* set F. */ |
|||
|
|||
qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", |
|||
__func__, env->pc, ex_vec, |
|||
env->pregs[PR_CCS], |
|||
env->pregs[PR_PID], |
|||
env->pregs[PR_ERP]); |
|||
} |
|||
|
|||
void cris_cpu_do_interrupt(CPUState *cs) |
|||
{ |
|||
CPUCRISState *env = cpu_env(cs); |
|||
int ex_vec = -1; |
|||
|
|||
D_LOG("exception index=%d interrupt_req=%d\n", |
|||
cs->exception_index, |
|||
cs->interrupt_request); |
|||
|
|||
switch (cs->exception_index) { |
|||
case EXCP_BREAK: |
|||
/* These exceptions are generated by the core itself.
|
|||
ERP should point to the insn following the brk. */ |
|||
ex_vec = env->trap_vector; |
|||
env->pregs[PR_ERP] = env->pc; |
|||
break; |
|||
|
|||
case EXCP_NMI: |
|||
/* NMI is hardwired to vector zero. */ |
|||
ex_vec = 0; |
|||
env->pregs[PR_CCS] &= ~M_FLAG_V32; |
|||
env->pregs[PR_NRP] = env->pc; |
|||
break; |
|||
|
|||
case EXCP_BUSFAULT: |
|||
ex_vec = env->fault_vector; |
|||
env->pregs[PR_ERP] = env->pc; |
|||
break; |
|||
|
|||
default: |
|||
/* The interrupt controller gives us the vector. */ |
|||
ex_vec = env->interrupt_vector; |
|||
/* Normal interrupts are taken between
|
|||
TB's. env->pc is valid here. */ |
|||
env->pregs[PR_ERP] = env->pc; |
|||
break; |
|||
} |
|||
|
|||
/* Fill in the IDX field. */ |
|||
env->pregs[PR_EXS] = (ex_vec & 0xff) << 8; |
|||
|
|||
if (env->dslot) { |
|||
D_LOG("excp isr=%x PC=%x ds=%d SP=%x" |
|||
" ERP=%x pid=%x ccs=%x cc=%d %x\n", |
|||
ex_vec, env->pc, env->dslot, |
|||
env->regs[R_SP], |
|||
env->pregs[PR_ERP], env->pregs[PR_PID], |
|||
env->pregs[PR_CCS], |
|||
env->cc_op, env->cc_mask); |
|||
/* We loose the btarget, btaken state here so rexec the
|
|||
branch. */ |
|||
env->pregs[PR_ERP] -= env->dslot; |
|||
/* Exception starts with dslot cleared. */ |
|||
env->dslot = 0; |
|||
} |
|||
|
|||
if (env->pregs[PR_CCS] & U_FLAG) { |
|||
/* Swap stack pointers. */ |
|||
env->pregs[PR_USP] = env->regs[R_SP]; |
|||
env->regs[R_SP] = env->ksp; |
|||
} |
|||
|
|||
/* Apply the CRIS CCS shift. Clears U if set. */ |
|||
cris_shift_ccs(env); |
|||
|
|||
/* Now that we are in kernel mode, load the handlers address.
|
|||
This load may not fault, real hw leaves that behaviour as |
|||
undefined. */ |
|||
env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4); |
|||
|
|||
/* Clear the excption_index to avoid spurious hw_aborts for recursive
|
|||
bus faults. */ |
|||
cs->exception_index = -1; |
|||
|
|||
D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", |
|||
__func__, env->pc, ex_vec, |
|||
env->pregs[PR_CCS], |
|||
env->pregs[PR_PID], |
|||
env->pregs[PR_ERP]); |
|||
} |
|||
|
|||
hwaddr cris_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) |
|||
{ |
|||
CRISCPU *cpu = CRIS_CPU(cs); |
|||
uint32_t phy = addr; |
|||
struct cris_mmu_result res; |
|||
int miss; |
|||
|
|||
miss = cris_mmu_translate(&res, &cpu->env, addr, MMU_DATA_LOAD, 0, 1); |
|||
/* If D TLB misses, try I TLB. */ |
|||
if (miss) { |
|||
miss = cris_mmu_translate(&res, &cpu->env, addr, MMU_INST_FETCH, 0, 1); |
|||
} |
|||
|
|||
if (!miss) { |
|||
phy = res.phy; |
|||
} |
|||
D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy)); |
|||
return phy; |
|||
} |
|||
|
|||
bool cris_cpu_exec_interrupt(CPUState *cs, int interrupt_request) |
|||
{ |
|||
CPUClass *cc = CPU_GET_CLASS(cs); |
|||
CPUCRISState *env = cpu_env(cs); |
|||
bool ret = false; |
|||
|
|||
if (interrupt_request & CPU_INTERRUPT_HARD |
|||
&& (env->pregs[PR_CCS] & I_FLAG) |
|||
&& !env->locked_irq) { |
|||
cs->exception_index = EXCP_IRQ; |
|||
cc->tcg_ops->do_interrupt(cs); |
|||
ret = true; |
|||
} |
|||
if (interrupt_request & CPU_INTERRUPT_NMI) { |
|||
unsigned int m_flag_archval; |
|||
if (env->pregs[PR_VR] < 32) { |
|||
m_flag_archval = M_FLAG_V10; |
|||
} else { |
|||
m_flag_archval = M_FLAG_V32; |
|||
} |
|||
if ((env->pregs[PR_CCS] & m_flag_archval)) { |
|||
cs->exception_index = EXCP_NMI; |
|||
cc->tcg_ops->do_interrupt(cs); |
|||
ret = true; |
|||
} |
|||
} |
|||
|
|||
return ret; |
|||
} |
|||
@ -1,23 +0,0 @@ |
|||
DEF_HELPER_2(raise_exception, noreturn, env, i32) |
|||
DEF_HELPER_2(tlb_flush_pid, void, env, i32) |
|||
DEF_HELPER_2(spc_write, void, env, i32) |
|||
DEF_HELPER_1(rfe, void, env) |
|||
DEF_HELPER_1(rfn, void, env) |
|||
|
|||
DEF_HELPER_3(movl_sreg_reg, void, env, i32, i32) |
|||
DEF_HELPER_3(movl_reg_sreg, void, env, i32, i32) |
|||
|
|||
DEF_HELPER_FLAGS_4(btst, TCG_CALL_NO_SE, i32, env, i32, i32, i32) |
|||
|
|||
DEF_HELPER_FLAGS_4(evaluate_flags_muls, TCG_CALL_NO_SE, i32, env, i32, i32, i32) |
|||
DEF_HELPER_FLAGS_4(evaluate_flags_mulu, TCG_CALL_NO_SE, i32, env, i32, i32, i32) |
|||
DEF_HELPER_FLAGS_5(evaluate_flags_mcp, TCG_CALL_NO_SE, i32, env, |
|||
i32, i32, i32, i32) |
|||
DEF_HELPER_FLAGS_5(evaluate_flags_alu_4, TCG_CALL_NO_SE, i32, env, |
|||
i32, i32, i32, i32) |
|||
DEF_HELPER_FLAGS_5(evaluate_flags_sub_4, TCG_CALL_NO_SE, i32, env, |
|||
i32, i32, i32, i32) |
|||
DEF_HELPER_FLAGS_3(evaluate_flags_move_4, TCG_CALL_NO_SE, i32, env, i32, i32) |
|||
DEF_HELPER_FLAGS_3(evaluate_flags_move_2, TCG_CALL_NO_SE, i32, env, i32, i32) |
|||
DEF_HELPER_1(evaluate_flags, void, env) |
|||
DEF_HELPER_1(top_evaluate_flags, void, env) |
|||
@ -1,93 +0,0 @@ |
|||
/*
|
|||
* CRIS virtual CPU state save/load support |
|||
* |
|||
* Copyright (c) 2012 Red Hat, Inc. |
|||
* Written by Juan Quintela <quintela@redhat.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.1 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, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include "qemu/osdep.h" |
|||
#include "cpu.h" |
|||
#include "migration/cpu.h" |
|||
|
|||
static const VMStateDescription vmstate_tlbset = { |
|||
.name = "cpu/tlbset", |
|||
.version_id = 1, |
|||
.minimum_version_id = 1, |
|||
.fields = (const VMStateField[]) { |
|||
VMSTATE_UINT32(lo, TLBSet), |
|||
VMSTATE_UINT32(hi, TLBSet), |
|||
VMSTATE_END_OF_LIST() |
|||
} |
|||
}; |
|||
|
|||
static const VMStateDescription vmstate_cris_env = { |
|||
.name = "env", |
|||
.version_id = 2, |
|||
.minimum_version_id = 2, |
|||
.fields = (const VMStateField[]) { |
|||
VMSTATE_UINT32_ARRAY(regs, CPUCRISState, 16), |
|||
VMSTATE_UINT32_ARRAY(pregs, CPUCRISState, 16), |
|||
VMSTATE_UINT32(pc, CPUCRISState), |
|||
VMSTATE_UINT32(ksp, CPUCRISState), |
|||
VMSTATE_INT32(dslot, CPUCRISState), |
|||
VMSTATE_INT32(btaken, CPUCRISState), |
|||
VMSTATE_UINT32(btarget, CPUCRISState), |
|||
VMSTATE_UINT32(cc_op, CPUCRISState), |
|||
VMSTATE_UINT32(cc_mask, CPUCRISState), |
|||
VMSTATE_UINT32(cc_dest, CPUCRISState), |
|||
VMSTATE_UINT32(cc_src, CPUCRISState), |
|||
VMSTATE_UINT32(cc_result, CPUCRISState), |
|||
VMSTATE_INT32(cc_size, CPUCRISState), |
|||
VMSTATE_INT32(cc_x, CPUCRISState), |
|||
VMSTATE_INT32(locked_irq, CPUCRISState), |
|||
VMSTATE_INT32(interrupt_vector, CPUCRISState), |
|||
VMSTATE_INT32(fault_vector, CPUCRISState), |
|||
VMSTATE_INT32(trap_vector, CPUCRISState), |
|||
VMSTATE_UINT32_ARRAY(sregs[0], CPUCRISState, 16), |
|||
VMSTATE_UINT32_ARRAY(sregs[1], CPUCRISState, 16), |
|||
VMSTATE_UINT32_ARRAY(sregs[2], CPUCRISState, 16), |
|||
VMSTATE_UINT32_ARRAY(sregs[3], CPUCRISState, 16), |
|||
VMSTATE_UINT32(mmu_rand_lfsr, CPUCRISState), |
|||
VMSTATE_STRUCT_ARRAY(tlbsets[0][0], CPUCRISState, 16, 0, |
|||
vmstate_tlbset, TLBSet), |
|||
VMSTATE_STRUCT_ARRAY(tlbsets[0][1], CPUCRISState, 16, 0, |
|||
vmstate_tlbset, TLBSet), |
|||
VMSTATE_STRUCT_ARRAY(tlbsets[0][2], CPUCRISState, 16, 0, |
|||
vmstate_tlbset, TLBSet), |
|||
VMSTATE_STRUCT_ARRAY(tlbsets[0][3], CPUCRISState, 16, 0, |
|||
vmstate_tlbset, TLBSet), |
|||
VMSTATE_STRUCT_ARRAY(tlbsets[1][0], CPUCRISState, 16, 0, |
|||
vmstate_tlbset, TLBSet), |
|||
VMSTATE_STRUCT_ARRAY(tlbsets[1][1], CPUCRISState, 16, 0, |
|||
vmstate_tlbset, TLBSet), |
|||
VMSTATE_STRUCT_ARRAY(tlbsets[1][2], CPUCRISState, 16, 0, |
|||
vmstate_tlbset, TLBSet), |
|||
VMSTATE_STRUCT_ARRAY(tlbsets[1][3], CPUCRISState, 16, 0, |
|||
vmstate_tlbset, TLBSet), |
|||
VMSTATE_END_OF_LIST() |
|||
} |
|||
}; |
|||
|
|||
const VMStateDescription vmstate_cris_cpu = { |
|||
.name = "cpu", |
|||
.version_id = 1, |
|||
.minimum_version_id = 1, |
|||
.fields = (const VMStateField[]) { |
|||
VMSTATE_CPU(), |
|||
VMSTATE_STRUCT(env, CRISCPU, 1, vmstate_cris_env, CPUCRISState), |
|||
VMSTATE_END_OF_LIST() |
|||
} |
|||
}; |
|||
@ -1,17 +0,0 @@ |
|||
cris_ss = ss.source_set() |
|||
cris_ss.add(files( |
|||
'cpu.c', |
|||
'gdbstub.c', |
|||
'op_helper.c', |
|||
'translate.c', |
|||
)) |
|||
|
|||
cris_system_ss = ss.source_set() |
|||
cris_system_ss.add(files( |
|||
'helper.c', |
|||
'machine.c', |
|||
'mmu.c', |
|||
)) |
|||
|
|||
target_arch += {'cris': cris_ss} |
|||
target_system_arch += {'cris': cris_system_ss} |
|||
@ -1,356 +0,0 @@ |
|||
/*
|
|||
* CRIS mmu emulation. |
|||
* |
|||
* 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.1 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/exec-all.h" |
|||
#include "exec/page-protection.h" |
|||
#include "mmu.h" |
|||
|
|||
#ifdef DEBUG |
|||
#define D(x) x |
|||
#define D_LOG(...) qemu_log(__VA_ARGS__) |
|||
#else |
|||
#define D(x) do { } while (0) |
|||
#define D_LOG(...) do { } while (0) |
|||
#endif |
|||
|
|||
void cris_mmu_init(CPUCRISState *env) |
|||
{ |
|||
env->mmu_rand_lfsr = 0xcccc; |
|||
} |
|||
|
|||
#define SR_POLYNOM 0x8805 |
|||
static inline unsigned int compute_polynom(unsigned int sr) |
|||
{ |
|||
unsigned int i; |
|||
unsigned int f; |
|||
|
|||
f = 0; |
|||
for (i = 0; i < 16; i++) { |
|||
f += ((SR_POLYNOM >> i) & 1) & ((sr >> i) & 1); |
|||
} |
|||
|
|||
return f; |
|||
} |
|||
|
|||
static void cris_mmu_update_rand_lfsr(CPUCRISState *env) |
|||
{ |
|||
unsigned int f; |
|||
|
|||
/* Update lfsr at every fault. */ |
|||
f = compute_polynom(env->mmu_rand_lfsr); |
|||
env->mmu_rand_lfsr >>= 1; |
|||
env->mmu_rand_lfsr |= (f << 15); |
|||
env->mmu_rand_lfsr &= 0xffff; |
|||
} |
|||
|
|||
static inline int cris_mmu_enabled(uint32_t rw_gc_cfg) |
|||
{ |
|||
return (rw_gc_cfg & 12) != 0; |
|||
} |
|||
|
|||
static inline int cris_mmu_segmented_addr(int seg, uint32_t rw_mm_cfg) |
|||
{ |
|||
return (1 << seg) & rw_mm_cfg; |
|||
} |
|||
|
|||
static uint32_t cris_mmu_translate_seg(CPUCRISState *env, int seg) |
|||
{ |
|||
uint32_t base; |
|||
int i; |
|||
|
|||
if (seg < 8) { |
|||
base = env->sregs[SFR_RW_MM_KBASE_LO]; |
|||
} else { |
|||
base = env->sregs[SFR_RW_MM_KBASE_HI]; |
|||
} |
|||
|
|||
i = seg & 7; |
|||
base >>= i * 4; |
|||
base &= 15; |
|||
|
|||
base <<= 28; |
|||
return base; |
|||
} |
|||
|
|||
/* Used by the tlb decoder. */ |
|||
#define EXTRACT_FIELD(src, start, end) \ |
|||
(((src) >> start) & ((1 << (end - start + 1)) - 1)) |
|||
|
|||
static inline void set_field(uint32_t *dst, unsigned int val, |
|||
unsigned int offset, unsigned int width) |
|||
{ |
|||
uint32_t mask; |
|||
|
|||
mask = (1 << width) - 1; |
|||
mask <<= offset; |
|||
val <<= offset; |
|||
|
|||
val &= mask; |
|||
*dst &= ~(mask); |
|||
*dst |= val; |
|||
} |
|||
|
|||
#ifdef DEBUG |
|||
static void dump_tlb(CPUCRISState *env, int mmu) |
|||
{ |
|||
int set; |
|||
int idx; |
|||
uint32_t hi, lo, tlb_vpn, tlb_pfn; |
|||
|
|||
for (set = 0; set < 4; set++) { |
|||
for (idx = 0; idx < 16; idx++) { |
|||
lo = env->tlbsets[mmu][set][idx].lo; |
|||
hi = env->tlbsets[mmu][set][idx].hi; |
|||
tlb_vpn = EXTRACT_FIELD(hi, 13, 31); |
|||
tlb_pfn = EXTRACT_FIELD(lo, 13, 31); |
|||
|
|||
printf("TLB: [%d][%d] hi=%x lo=%x v=%x p=%x\n", |
|||
set, idx, hi, lo, tlb_vpn, tlb_pfn); |
|||
} |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
static int cris_mmu_translate_page(struct cris_mmu_result *res, |
|||
CPUCRISState *env, uint32_t vaddr, |
|||
MMUAccessType access_type, |
|||
int usermode, int debug) |
|||
{ |
|||
unsigned int vpage; |
|||
unsigned int idx; |
|||
uint32_t pid, lo, hi; |
|||
uint32_t tlb_vpn, tlb_pfn = 0; |
|||
int tlb_pid, tlb_g, tlb_v, tlb_k, tlb_w, tlb_x; |
|||
int cfg_v, cfg_k, cfg_w, cfg_x; |
|||
int set, match = 0; |
|||
uint32_t r_cause; |
|||
uint32_t r_cfg; |
|||
int rwcause; |
|||
int mmu = 1; /* Data mmu is default. */ |
|||
int vect_base; |
|||
|
|||
r_cause = env->sregs[SFR_R_MM_CAUSE]; |
|||
r_cfg = env->sregs[SFR_RW_MM_CFG]; |
|||
pid = env->pregs[PR_PID] & 0xff; |
|||
|
|||
switch (access_type) { |
|||
case MMU_INST_FETCH: |
|||
rwcause = CRIS_MMU_ERR_EXEC; |
|||
mmu = 0; |
|||
break; |
|||
case MMU_DATA_STORE: |
|||
rwcause = CRIS_MMU_ERR_WRITE; |
|||
break; |
|||
default: |
|||
case MMU_DATA_LOAD: |
|||
rwcause = CRIS_MMU_ERR_READ; |
|||
break; |
|||
} |
|||
|
|||
/* I exception vectors 4 - 7, D 8 - 11. */ |
|||
vect_base = (mmu + 1) * 4; |
|||
|
|||
vpage = vaddr >> 13; |
|||
|
|||
/*
|
|||
* We know the index which to check on each set. |
|||
* Scan both I and D. |
|||
*/ |
|||
idx = vpage & 15; |
|||
for (set = 0; set < 4; set++) { |
|||
lo = env->tlbsets[mmu][set][idx].lo; |
|||
hi = env->tlbsets[mmu][set][idx].hi; |
|||
|
|||
tlb_vpn = hi >> 13; |
|||
tlb_pid = EXTRACT_FIELD(hi, 0, 7); |
|||
tlb_g = EXTRACT_FIELD(lo, 4, 4); |
|||
|
|||
D_LOG("TLB[%d][%d][%d] v=%x vpage=%x lo=%x hi=%x\n", |
|||
mmu, set, idx, tlb_vpn, vpage, lo, hi); |
|||
if ((tlb_g || (tlb_pid == pid)) && tlb_vpn == vpage) { |
|||
match = 1; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
res->bf_vec = vect_base; |
|||
if (match) { |
|||
cfg_w = EXTRACT_FIELD(r_cfg, 19, 19); |
|||
cfg_k = EXTRACT_FIELD(r_cfg, 18, 18); |
|||
cfg_x = EXTRACT_FIELD(r_cfg, 17, 17); |
|||
cfg_v = EXTRACT_FIELD(r_cfg, 16, 16); |
|||
|
|||
tlb_pfn = EXTRACT_FIELD(lo, 13, 31); |
|||
tlb_v = EXTRACT_FIELD(lo, 3, 3); |
|||
tlb_k = EXTRACT_FIELD(lo, 2, 2); |
|||
tlb_w = EXTRACT_FIELD(lo, 1, 1); |
|||
tlb_x = EXTRACT_FIELD(lo, 0, 0); |
|||
|
|||
/*
|
|||
* set_exception_vector(0x04, i_mmu_refill); |
|||
* set_exception_vector(0x05, i_mmu_invalid); |
|||
* set_exception_vector(0x06, i_mmu_access); |
|||
* set_exception_vector(0x07, i_mmu_execute); |
|||
* set_exception_vector(0x08, d_mmu_refill); |
|||
* set_exception_vector(0x09, d_mmu_invalid); |
|||
* set_exception_vector(0x0a, d_mmu_access); |
|||
* set_exception_vector(0x0b, d_mmu_write); |
|||
*/ |
|||
if (cfg_k && tlb_k && usermode) { |
|||
D(printf("tlb: kernel protected %x lo=%x pc=%x\n", |
|||
vaddr, lo, env->pc)); |
|||
match = 0; |
|||
res->bf_vec = vect_base + 2; |
|||
} else if (access_type == MMU_DATA_STORE && cfg_w && !tlb_w) { |
|||
D(printf("tlb: write protected %x lo=%x pc=%x\n", |
|||
vaddr, lo, env->pc)); |
|||
match = 0; |
|||
/* write accesses never go through the I mmu. */ |
|||
res->bf_vec = vect_base + 3; |
|||
} else if (access_type == MMU_INST_FETCH && cfg_x && !tlb_x) { |
|||
D(printf("tlb: exec protected %x lo=%x pc=%x\n", |
|||
vaddr, lo, env->pc)); |
|||
match = 0; |
|||
res->bf_vec = vect_base + 3; |
|||
} else if (cfg_v && !tlb_v) { |
|||
D(printf("tlb: invalid %x\n", vaddr)); |
|||
match = 0; |
|||
res->bf_vec = vect_base + 1; |
|||
} |
|||
|
|||
res->prot = 0; |
|||
if (match) { |
|||
res->prot |= PAGE_READ; |
|||
if (tlb_w) { |
|||
res->prot |= PAGE_WRITE; |
|||
} |
|||
if (mmu == 0 && (cfg_x || tlb_x)) { |
|||
res->prot |= PAGE_EXEC; |
|||
} |
|||
} else { |
|||
D(dump_tlb(env, mmu)); |
|||
} |
|||
} else { |
|||
/* If refill, provide a randomized set. */ |
|||
set = env->mmu_rand_lfsr & 3; |
|||
} |
|||
|
|||
if (!match && !debug) { |
|||
cris_mmu_update_rand_lfsr(env); |
|||
|
|||
/* Compute index. */ |
|||
idx = vpage & 15; |
|||
|
|||
/* Update RW_MM_TLB_SEL. */ |
|||
env->sregs[SFR_RW_MM_TLB_SEL] = 0; |
|||
set_field(&env->sregs[SFR_RW_MM_TLB_SEL], idx, 0, 4); |
|||
set_field(&env->sregs[SFR_RW_MM_TLB_SEL], set, 4, 2); |
|||
|
|||
/* Update RW_MM_CAUSE. */ |
|||
set_field(&r_cause, rwcause, 8, 2); |
|||
set_field(&r_cause, vpage, 13, 19); |
|||
set_field(&r_cause, pid, 0, 8); |
|||
env->sregs[SFR_R_MM_CAUSE] = r_cause; |
|||
D(printf("refill vaddr=%x pc=%x\n", vaddr, env->pc)); |
|||
} |
|||
|
|||
D(printf("%s access=%u mtch=%d pc=%x va=%x vpn=%x tlbvpn=%x pfn=%x pid=%x" |
|||
" %x cause=%x sel=%x sp=%x %x %x\n", |
|||
__func__, access_type, match, env->pc, |
|||
vaddr, vpage, |
|||
tlb_vpn, tlb_pfn, tlb_pid, |
|||
pid, |
|||
r_cause, |
|||
env->sregs[SFR_RW_MM_TLB_SEL], |
|||
env->regs[R_SP], env->pregs[PR_USP], env->ksp)); |
|||
|
|||
res->phy = tlb_pfn << TARGET_PAGE_BITS; |
|||
return !match; |
|||
} |
|||
|
|||
void cris_mmu_flush_pid(CPUCRISState *env, uint32_t pid) |
|||
{ |
|||
target_ulong vaddr; |
|||
unsigned int idx; |
|||
uint32_t lo, hi; |
|||
uint32_t tlb_vpn; |
|||
int tlb_pid, tlb_g, tlb_v; |
|||
unsigned int set; |
|||
unsigned int mmu; |
|||
|
|||
pid &= 0xff; |
|||
for (mmu = 0; mmu < 2; mmu++) { |
|||
for (set = 0; set < 4; set++) { |
|||
for (idx = 0; idx < 16; idx++) { |
|||
lo = env->tlbsets[mmu][set][idx].lo; |
|||
hi = env->tlbsets[mmu][set][idx].hi; |
|||
|
|||
tlb_vpn = EXTRACT_FIELD(hi, 13, 31); |
|||
tlb_pid = EXTRACT_FIELD(hi, 0, 7); |
|||
tlb_g = EXTRACT_FIELD(lo, 4, 4); |
|||
tlb_v = EXTRACT_FIELD(lo, 3, 3); |
|||
|
|||
if (tlb_v && !tlb_g && (tlb_pid == pid)) { |
|||
vaddr = tlb_vpn << TARGET_PAGE_BITS; |
|||
D_LOG("flush pid=%x vaddr=%x\n", pid, vaddr); |
|||
tlb_flush_page(env_cpu(env), vaddr); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
int cris_mmu_translate(struct cris_mmu_result *res, |
|||
CPUCRISState *env, uint32_t vaddr, |
|||
MMUAccessType access_type, int mmu_idx, int debug) |
|||
{ |
|||
int seg; |
|||
int miss = 0; |
|||
int is_user = mmu_idx == MMU_USER_IDX; |
|||
uint32_t old_srs; |
|||
|
|||
old_srs = env->pregs[PR_SRS]; |
|||
|
|||
env->pregs[PR_SRS] = access_type == MMU_INST_FETCH ? 1 : 2; |
|||
|
|||
if (!cris_mmu_enabled(env->sregs[SFR_RW_GC_CFG])) { |
|||
res->phy = vaddr; |
|||
res->prot = PAGE_RWX; |
|||
goto done; |
|||
} |
|||
|
|||
seg = vaddr >> 28; |
|||
if (!is_user && cris_mmu_segmented_addr(seg, env->sregs[SFR_RW_MM_CFG])) { |
|||
uint32_t base; |
|||
|
|||
miss = 0; |
|||
base = cris_mmu_translate_seg(env, seg); |
|||
res->phy = base | (0x0fffffff & vaddr); |
|||
res->prot = PAGE_RWX; |
|||
} else { |
|||
miss = cris_mmu_translate_page(res, env, vaddr, access_type, |
|||
is_user, debug); |
|||
} |
|||
done: |
|||
env->pregs[PR_SRS] = old_srs; |
|||
return miss; |
|||
} |
|||
@ -1,22 +0,0 @@ |
|||
#ifndef TARGET_CRIS_MMU_H |
|||
#define TARGET_CRIS_MMU_H |
|||
|
|||
#define CRIS_MMU_ERR_EXEC 0 |
|||
#define CRIS_MMU_ERR_READ 1 |
|||
#define CRIS_MMU_ERR_WRITE 2 |
|||
#define CRIS_MMU_ERR_FLUSH 3 |
|||
|
|||
struct cris_mmu_result |
|||
{ |
|||
uint32_t phy; |
|||
int prot; |
|||
int bf_vec; |
|||
}; |
|||
|
|||
void cris_mmu_init(CPUCRISState *env); |
|||
void cris_mmu_flush_pid(CPUCRISState *env, uint32_t pid); |
|||
int cris_mmu_translate(struct cris_mmu_result *res, |
|||
CPUCRISState *env, uint32_t vaddr, |
|||
MMUAccessType access_type, int mmu_idx, int debug); |
|||
|
|||
#endif |
|||
@ -1,580 +0,0 @@ |
|||
/*
|
|||
* 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.1 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 "mmu.h" |
|||
#include "exec/helper-proto.h" |
|||
#include "qemu/host-utils.h" |
|||
#include "exec/exec-all.h" |
|||
|
|||
//#define CRIS_OP_HELPER_DEBUG
|
|||
|
|||
|
|||
#ifdef CRIS_OP_HELPER_DEBUG |
|||
#define D(x) x |
|||
#define D_LOG(...) qemu_log(__VA_ARGS__) |
|||
#else |
|||
#define D(x) |
|||
#define D_LOG(...) do { } while (0) |
|||
#endif |
|||
|
|||
void helper_raise_exception(CPUCRISState *env, uint32_t index) |
|||
{ |
|||
CPUState *cs = env_cpu(env); |
|||
|
|||
cs->exception_index = index; |
|||
cpu_loop_exit(cs); |
|||
} |
|||
|
|||
void helper_tlb_flush_pid(CPUCRISState *env, uint32_t pid) |
|||
{ |
|||
#if !defined(CONFIG_USER_ONLY) |
|||
pid &= 0xff; |
|||
if (pid != (env->pregs[PR_PID] & 0xff)) { |
|||
cris_mmu_flush_pid(env, env->pregs[PR_PID]); |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
void helper_spc_write(CPUCRISState *env, uint32_t new_spc) |
|||
{ |
|||
#if !defined(CONFIG_USER_ONLY) |
|||
CPUState *cs = env_cpu(env); |
|||
|
|||
tlb_flush_page(cs, env->pregs[PR_SPC]); |
|||
tlb_flush_page(cs, new_spc); |
|||
#endif |
|||
} |
|||
|
|||
/* Used by the tlb decoder. */ |
|||
#define EXTRACT_FIELD(src, start, end) \ |
|||
(((src) >> start) & ((1 << (end - start + 1)) - 1)) |
|||
|
|||
void helper_movl_sreg_reg(CPUCRISState *env, uint32_t sreg, uint32_t reg) |
|||
{ |
|||
uint32_t srs; |
|||
srs = env->pregs[PR_SRS]; |
|||
srs &= 3; |
|||
env->sregs[srs][sreg] = env->regs[reg]; |
|||
|
|||
#if !defined(CONFIG_USER_ONLY) |
|||
if (srs == 1 || srs == 2) { |
|||
if (sreg == 6) { |
|||
/* Writes to tlb-hi write to mm_cause as a side effect. */ |
|||
env->sregs[SFR_RW_MM_TLB_HI] = env->regs[reg]; |
|||
env->sregs[SFR_R_MM_CAUSE] = env->regs[reg]; |
|||
} else if (sreg == 5) { |
|||
uint32_t set; |
|||
uint32_t idx; |
|||
uint32_t lo, hi; |
|||
uint32_t vaddr; |
|||
int tlb_v; |
|||
|
|||
idx = set = env->sregs[SFR_RW_MM_TLB_SEL]; |
|||
set >>= 4; |
|||
set &= 3; |
|||
|
|||
idx &= 15; |
|||
/* We've just made a write to tlb_lo. */ |
|||
lo = env->sregs[SFR_RW_MM_TLB_LO]; |
|||
/* Writes are done via r_mm_cause. */ |
|||
hi = env->sregs[SFR_R_MM_CAUSE]; |
|||
|
|||
vaddr = EXTRACT_FIELD(env->tlbsets[srs - 1][set][idx].hi, 13, 31); |
|||
vaddr <<= TARGET_PAGE_BITS; |
|||
tlb_v = EXTRACT_FIELD(env->tlbsets[srs - 1][set][idx].lo, 3, 3); |
|||
env->tlbsets[srs - 1][set][idx].lo = lo; |
|||
env->tlbsets[srs - 1][set][idx].hi = hi; |
|||
|
|||
D_LOG("tlb flush vaddr=%x v=%d pc=%x\n", |
|||
vaddr, tlb_v, env->pc); |
|||
if (tlb_v) { |
|||
tlb_flush_page(env_cpu(env), vaddr); |
|||
} |
|||
} |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
void helper_movl_reg_sreg(CPUCRISState *env, uint32_t reg, uint32_t sreg) |
|||
{ |
|||
uint32_t srs; |
|||
env->pregs[PR_SRS] &= 3; |
|||
srs = env->pregs[PR_SRS]; |
|||
|
|||
#if !defined(CONFIG_USER_ONLY) |
|||
if (srs == 1 || srs == 2) { |
|||
uint32_t set; |
|||
uint32_t idx; |
|||
uint32_t lo, hi; |
|||
|
|||
idx = set = env->sregs[SFR_RW_MM_TLB_SEL]; |
|||
set >>= 4; |
|||
set &= 3; |
|||
idx &= 15; |
|||
|
|||
/* Update the mirror regs. */ |
|||
hi = env->tlbsets[srs - 1][set][idx].hi; |
|||
lo = env->tlbsets[srs - 1][set][idx].lo; |
|||
env->sregs[SFR_RW_MM_TLB_HI] = hi; |
|||
env->sregs[SFR_RW_MM_TLB_LO] = lo; |
|||
} |
|||
#endif |
|||
env->regs[reg] = env->sregs[srs][sreg]; |
|||
} |
|||
|
|||
static void cris_ccs_rshift(CPUCRISState *env) |
|||
{ |
|||
uint32_t ccs; |
|||
|
|||
/* Apply the ccs shift. */ |
|||
ccs = env->pregs[PR_CCS]; |
|||
ccs = (ccs & 0xc0000000) | ((ccs & 0x0fffffff) >> 10); |
|||
if (ccs & U_FLAG) { |
|||
/* Enter user mode. */ |
|||
env->ksp = env->regs[R_SP]; |
|||
env->regs[R_SP] = env->pregs[PR_USP]; |
|||
} |
|||
|
|||
env->pregs[PR_CCS] = ccs; |
|||
} |
|||
|
|||
void helper_rfe(CPUCRISState *env) |
|||
{ |
|||
int rflag = env->pregs[PR_CCS] & R_FLAG; |
|||
|
|||
D_LOG("rfe: erp=%x pid=%x ccs=%x btarget=%x\n", |
|||
env->pregs[PR_ERP], env->pregs[PR_PID], |
|||
env->pregs[PR_CCS], |
|||
env->btarget); |
|||
|
|||
cris_ccs_rshift(env); |
|||
|
|||
/* RFE sets the P_FLAG only if the R_FLAG is not set. */ |
|||
if (!rflag) { |
|||
env->pregs[PR_CCS] |= P_FLAG; |
|||
} |
|||
} |
|||
|
|||
void helper_rfn(CPUCRISState *env) |
|||
{ |
|||
int rflag = env->pregs[PR_CCS] & R_FLAG; |
|||
|
|||
D_LOG("rfn: erp=%x pid=%x ccs=%x btarget=%x\n", |
|||
env->pregs[PR_ERP], env->pregs[PR_PID], |
|||
env->pregs[PR_CCS], |
|||
env->btarget); |
|||
|
|||
cris_ccs_rshift(env); |
|||
|
|||
/* Set the P_FLAG only if the R_FLAG is not set. */ |
|||
if (!rflag) { |
|||
env->pregs[PR_CCS] |= P_FLAG; |
|||
} |
|||
|
|||
/* Always set the M flag. */ |
|||
env->pregs[PR_CCS] |= M_FLAG_V32; |
|||
} |
|||
|
|||
uint32_t helper_btst(CPUCRISState *env, uint32_t t0, uint32_t t1, uint32_t ccs) |
|||
{ |
|||
/* FIXME: clean this up. */ |
|||
|
|||
/*
|
|||
* des ref: |
|||
* The N flag is set according to the selected bit in the dest reg. |
|||
* The Z flag is set if the selected bit and all bits to the right are |
|||
* zero. |
|||
* The X flag is cleared. |
|||
* Other flags are left untouched. |
|||
* The destination reg is not affected. |
|||
*/ |
|||
unsigned int fz, sbit, bset, mask, masked_t0; |
|||
|
|||
sbit = t1 & 31; |
|||
bset = !!(t0 & (1 << sbit)); |
|||
mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1; |
|||
masked_t0 = t0 & mask; |
|||
fz = !(masked_t0 | bset); |
|||
|
|||
/* Clear the X, N and Z flags. */ |
|||
ccs = ccs & ~(X_FLAG | N_FLAG | Z_FLAG); |
|||
if (env->pregs[PR_VR] < 32) { |
|||
ccs &= ~(V_FLAG | C_FLAG); |
|||
} |
|||
/* Set the N and Z flags accordingly. */ |
|||
ccs |= (bset << 3) | (fz << 2); |
|||
return ccs; |
|||
} |
|||
|
|||
static inline uint32_t evaluate_flags_writeback(CPUCRISState *env, |
|||
uint32_t flags, uint32_t ccs) |
|||
{ |
|||
unsigned int x, z, mask; |
|||
|
|||
/* Extended arithmetic, leave the z flag alone. */ |
|||
x = env->cc_x; |
|||
mask = env->cc_mask | X_FLAG; |
|||
if (x) { |
|||
z = flags & Z_FLAG; |
|||
mask = mask & ~z; |
|||
} |
|||
flags &= mask; |
|||
|
|||
/* all insn clear the x-flag except setf or clrf. */ |
|||
ccs &= ~mask; |
|||
ccs |= flags; |
|||
return ccs; |
|||
} |
|||
|
|||
uint32_t helper_evaluate_flags_muls(CPUCRISState *env, |
|||
uint32_t ccs, uint32_t res, uint32_t mof) |
|||
{ |
|||
uint32_t flags = 0; |
|||
int64_t tmp; |
|||
int dneg; |
|||
|
|||
dneg = ((int32_t)res) < 0; |
|||
|
|||
tmp = mof; |
|||
tmp <<= 32; |
|||
tmp |= res; |
|||
if (tmp == 0) { |
|||
flags |= Z_FLAG; |
|||
} else if (tmp < 0) { |
|||
flags |= N_FLAG; |
|||
} |
|||
if ((dneg && mof != -1) || (!dneg && mof != 0)) { |
|||
flags |= V_FLAG; |
|||
} |
|||
return evaluate_flags_writeback(env, flags, ccs); |
|||
} |
|||
|
|||
uint32_t helper_evaluate_flags_mulu(CPUCRISState *env, |
|||
uint32_t ccs, uint32_t res, uint32_t mof) |
|||
{ |
|||
uint32_t flags = 0; |
|||
uint64_t tmp; |
|||
|
|||
tmp = mof; |
|||
tmp <<= 32; |
|||
tmp |= res; |
|||
if (tmp == 0) { |
|||
flags |= Z_FLAG; |
|||
} else if (tmp >> 63) { |
|||
flags |= N_FLAG; |
|||
} |
|||
if (mof) { |
|||
flags |= V_FLAG; |
|||
} |
|||
|
|||
return evaluate_flags_writeback(env, flags, ccs); |
|||
} |
|||
|
|||
uint32_t helper_evaluate_flags_mcp(CPUCRISState *env, uint32_t ccs, |
|||
uint32_t src, uint32_t dst, uint32_t res) |
|||
{ |
|||
uint32_t flags = 0; |
|||
|
|||
src = src & 0x80000000; |
|||
dst = dst & 0x80000000; |
|||
|
|||
if ((res & 0x80000000L) != 0L) { |
|||
flags |= N_FLAG; |
|||
if (!src && !dst) { |
|||
flags |= V_FLAG; |
|||
} else if (src & dst) { |
|||
flags |= R_FLAG; |
|||
} |
|||
} else { |
|||
if (res == 0L) { |
|||
flags |= Z_FLAG; |
|||
} |
|||
if (src & dst) { |
|||
flags |= V_FLAG; |
|||
} |
|||
if (dst | src) { |
|||
flags |= R_FLAG; |
|||
} |
|||
} |
|||
|
|||
return evaluate_flags_writeback(env, flags, ccs); |
|||
} |
|||
|
|||
uint32_t helper_evaluate_flags_alu_4(CPUCRISState *env, uint32_t ccs, |
|||
uint32_t src, uint32_t dst, uint32_t res) |
|||
{ |
|||
uint32_t flags = 0; |
|||
|
|||
src = src & 0x80000000; |
|||
dst = dst & 0x80000000; |
|||
|
|||
if ((res & 0x80000000L) != 0L) { |
|||
flags |= N_FLAG; |
|||
if (!src && !dst) { |
|||
flags |= V_FLAG; |
|||
} else if (src & dst) { |
|||
flags |= C_FLAG; |
|||
} |
|||
} else { |
|||
if (res == 0L) { |
|||
flags |= Z_FLAG; |
|||
} |
|||
if (src & dst) { |
|||
flags |= V_FLAG; |
|||
} |
|||
if (dst | src) { |
|||
flags |= C_FLAG; |
|||
} |
|||
} |
|||
|
|||
return evaluate_flags_writeback(env, flags, ccs); |
|||
} |
|||
|
|||
uint32_t helper_evaluate_flags_sub_4(CPUCRISState *env, uint32_t ccs, |
|||
uint32_t src, uint32_t dst, uint32_t res) |
|||
{ |
|||
uint32_t flags = 0; |
|||
|
|||
src = (~src) & 0x80000000; |
|||
dst = dst & 0x80000000; |
|||
|
|||
if ((res & 0x80000000L) != 0L) { |
|||
flags |= N_FLAG; |
|||
if (!src && !dst) { |
|||
flags |= V_FLAG; |
|||
} else if (src & dst) { |
|||
flags |= C_FLAG; |
|||
} |
|||
} else { |
|||
if (res == 0L) { |
|||
flags |= Z_FLAG; |
|||
} |
|||
if (src & dst) { |
|||
flags |= V_FLAG; |
|||
} |
|||
if (dst | src) { |
|||
flags |= C_FLAG; |
|||
} |
|||
} |
|||
|
|||
flags ^= C_FLAG; |
|||
return evaluate_flags_writeback(env, flags, ccs); |
|||
} |
|||
|
|||
uint32_t helper_evaluate_flags_move_4(CPUCRISState *env, |
|||
uint32_t ccs, uint32_t res) |
|||
{ |
|||
uint32_t flags = 0; |
|||
|
|||
if ((int32_t)res < 0) { |
|||
flags |= N_FLAG; |
|||
} else if (res == 0L) { |
|||
flags |= Z_FLAG; |
|||
} |
|||
|
|||
return evaluate_flags_writeback(env, flags, ccs); |
|||
} |
|||
|
|||
uint32_t helper_evaluate_flags_move_2(CPUCRISState *env, |
|||
uint32_t ccs, uint32_t res) |
|||
{ |
|||
uint32_t flags = 0; |
|||
|
|||
if ((int16_t)res < 0L) { |
|||
flags |= N_FLAG; |
|||
} else if (res == 0) { |
|||
flags |= Z_FLAG; |
|||
} |
|||
|
|||
return evaluate_flags_writeback(env, flags, ccs); |
|||
} |
|||
|
|||
/*
|
|||
* TODO: This is expensive. We could split things up and only evaluate part of |
|||
* CCR on a need to know basis. For now, we simply re-evaluate everything. |
|||
*/ |
|||
void helper_evaluate_flags(CPUCRISState *env) |
|||
{ |
|||
uint32_t src, dst, res; |
|||
uint32_t flags = 0; |
|||
|
|||
src = env->cc_src; |
|||
dst = env->cc_dest; |
|||
res = env->cc_result; |
|||
|
|||
if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP) { |
|||
src = ~src; |
|||
} |
|||
|
|||
/*
|
|||
* Now, evaluate the flags. This stuff is based on |
|||
* Per Zander's CRISv10 simulator. |
|||
*/ |
|||
switch (env->cc_size) { |
|||
case 1: |
|||
if ((res & 0x80L) != 0L) { |
|||
flags |= N_FLAG; |
|||
if (((src & 0x80L) == 0L) && ((dst & 0x80L) == 0L)) { |
|||
flags |= V_FLAG; |
|||
} else if (((src & 0x80L) != 0L) && ((dst & 0x80L) != 0L)) { |
|||
flags |= C_FLAG; |
|||
} |
|||
} else { |
|||
if ((res & 0xFFL) == 0L) { |
|||
flags |= Z_FLAG; |
|||
} |
|||
if (((src & 0x80L) != 0L) && ((dst & 0x80L) != 0L)) { |
|||
flags |= V_FLAG; |
|||
} |
|||
if ((dst & 0x80L) != 0L || (src & 0x80L) != 0L) { |
|||
flags |= C_FLAG; |
|||
} |
|||
} |
|||
break; |
|||
case 2: |
|||
if ((res & 0x8000L) != 0L) { |
|||
flags |= N_FLAG; |
|||
if (((src & 0x8000L) == 0L) && ((dst & 0x8000L) == 0L)) { |
|||
flags |= V_FLAG; |
|||
} else if (((src & 0x8000L) != 0L) && ((dst & 0x8000L) != 0L)) { |
|||
flags |= C_FLAG; |
|||
} |
|||
} else { |
|||
if ((res & 0xFFFFL) == 0L) { |
|||
flags |= Z_FLAG; |
|||
} |
|||
if (((src & 0x8000L) != 0L) && ((dst & 0x8000L) != 0L)) { |
|||
flags |= V_FLAG; |
|||
} |
|||
if ((dst & 0x8000L) != 0L || (src & 0x8000L) != 0L) { |
|||
flags |= C_FLAG; |
|||
} |
|||
} |
|||
break; |
|||
case 4: |
|||
if ((res & 0x80000000L) != 0L) { |
|||
flags |= N_FLAG; |
|||
if (((src & 0x80000000L) == 0L) && ((dst & 0x80000000L) == 0L)) { |
|||
flags |= V_FLAG; |
|||
} else if (((src & 0x80000000L) != 0L) && |
|||
((dst & 0x80000000L) != 0L)) { |
|||
flags |= C_FLAG; |
|||
} |
|||
} else { |
|||
if (res == 0L) { |
|||
flags |= Z_FLAG; |
|||
} |
|||
if (((src & 0x80000000L) != 0L) && ((dst & 0x80000000L) != 0L)) { |
|||
flags |= V_FLAG; |
|||
} |
|||
if ((dst & 0x80000000L) != 0L || (src & 0x80000000L) != 0L) { |
|||
flags |= C_FLAG; |
|||
} |
|||
} |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
|
|||
if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP) { |
|||
flags ^= C_FLAG; |
|||
} |
|||
|
|||
env->pregs[PR_CCS] = evaluate_flags_writeback(env, flags, |
|||
env->pregs[PR_CCS]); |
|||
} |
|||
|
|||
void helper_top_evaluate_flags(CPUCRISState *env) |
|||
{ |
|||
switch (env->cc_op) { |
|||
case CC_OP_MCP: |
|||
env->pregs[PR_CCS] |
|||
= helper_evaluate_flags_mcp(env, env->pregs[PR_CCS], |
|||
env->cc_src, env->cc_dest, |
|||
env->cc_result); |
|||
break; |
|||
case CC_OP_MULS: |
|||
env->pregs[PR_CCS] |
|||
= helper_evaluate_flags_muls(env, env->pregs[PR_CCS], |
|||
env->cc_result, env->pregs[PR_MOF]); |
|||
break; |
|||
case CC_OP_MULU: |
|||
env->pregs[PR_CCS] |
|||
= helper_evaluate_flags_mulu(env, env->pregs[PR_CCS], |
|||
env->cc_result, env->pregs[PR_MOF]); |
|||
break; |
|||
case CC_OP_MOVE: |
|||
case CC_OP_AND: |
|||
case CC_OP_OR: |
|||
case CC_OP_XOR: |
|||
case CC_OP_ASR: |
|||
case CC_OP_LSR: |
|||
case CC_OP_LSL: |
|||
switch (env->cc_size) { |
|||
case 4: |
|||
env->pregs[PR_CCS] = |
|||
helper_evaluate_flags_move_4(env, |
|||
env->pregs[PR_CCS], |
|||
env->cc_result); |
|||
break; |
|||
case 2: |
|||
env->pregs[PR_CCS] = |
|||
helper_evaluate_flags_move_2(env, |
|||
env->pregs[PR_CCS], |
|||
env->cc_result); |
|||
break; |
|||
default: |
|||
helper_evaluate_flags(env); |
|||
break; |
|||
} |
|||
break; |
|||
case CC_OP_FLAGS: |
|||
/* live. */ |
|||
break; |
|||
case CC_OP_SUB: |
|||
case CC_OP_CMP: |
|||
if (env->cc_size == 4) { |
|||
env->pregs[PR_CCS] = |
|||
helper_evaluate_flags_sub_4(env, |
|||
env->pregs[PR_CCS], |
|||
env->cc_src, env->cc_dest, |
|||
env->cc_result); |
|||
} else { |
|||
helper_evaluate_flags(env); |
|||
} |
|||
break; |
|||
default: |
|||
switch (env->cc_size) { |
|||
case 4: |
|||
env->pregs[PR_CCS] = |
|||
helper_evaluate_flags_alu_4(env, |
|||
env->pregs[PR_CCS], |
|||
env->cc_src, env->cc_dest, |
|||
env->cc_result); |
|||
break; |
|||
default: |
|||
helper_evaluate_flags(env); |
|||
break; |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
@ -1,355 +0,0 @@ |
|||
/* cris.h -- Header file for CRIS opcode and register tables.
|
|||
Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. |
|||
Contributed by Axis Communications AB, Lund, Sweden. |
|||
Originally written for GAS 1.38.1 by Mikael Asker. |
|||
Updated, BFDized and GNUified by Hans-Peter Nilsson. |
|||
|
|||
This file is part of GAS, GDB and the GNU binutils. |
|||
|
|||
GAS, GDB, and GNU binutils is free software; you can redistribute it |
|||
and/or modify it under the terms of the GNU General Public License as |
|||
published by the Free Software Foundation; either version 2, or (at your |
|||
option) any later version. |
|||
|
|||
GAS, GDB, and GNU binutils are distributed in the hope that they 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 General Public License |
|||
along with this program; if not, see <http://www.gnu.org/licenses/>. */
|
|||
|
|||
#ifndef TARGET_CRIS_OPCODE_CRIS_H |
|||
#define TARGET_CRIS_OPCODE_CRIS_H |
|||
|
|||
#if !defined(__STDC__) && !defined(const) |
|||
#define const |
|||
#endif |
|||
|
|||
|
|||
/* Registers. */ |
|||
#define MAX_REG (15) |
|||
#define CRIS_REG_SP (14) |
|||
#define CRIS_REG_PC (15) |
|||
|
|||
/* CPU version control of disassembly and assembly of instructions.
|
|||
May affect how the instruction is assembled, at least the size of |
|||
immediate operands. */ |
|||
enum cris_insn_version_usage |
|||
{ |
|||
/* Any version. */ |
|||
cris_ver_version_all=0, |
|||
|
|||
/* Indeterminate (intended for disassembly only, or obsolete). */ |
|||
cris_ver_warning, |
|||
|
|||
/* Only for v0..3 (Etrax 1..4). */ |
|||
cris_ver_v0_3, |
|||
|
|||
/* Only for v3 or higher (ETRAX 4 and beyond). */ |
|||
cris_ver_v3p, |
|||
|
|||
/* Only for v8 (Etrax 100). */ |
|||
cris_ver_v8, |
|||
|
|||
/* Only for v8 or higher (ETRAX 100, ETRAX 100 LX). */ |
|||
cris_ver_v8p, |
|||
|
|||
/* Only for v0..10. FIXME: Not sure what to do with this. */ |
|||
cris_ver_sim_v0_10, |
|||
|
|||
/* Only for v0..10. */ |
|||
cris_ver_v0_10, |
|||
|
|||
/* Only for v3..10. (ETRAX 4, ETRAX 100 and ETRAX 100 LX). */ |
|||
cris_ver_v3_10, |
|||
|
|||
/* Only for v8..10 (ETRAX 100 and ETRAX 100 LX). */ |
|||
cris_ver_v8_10, |
|||
|
|||
/* Only for v10 (ETRAX 100 LX) and same series. */ |
|||
cris_ver_v10, |
|||
|
|||
/* Only for v10 (ETRAX 100 LX) and same series. */ |
|||
cris_ver_v10p, |
|||
|
|||
/* Only for v32 or higher (codename GUINNESS).
|
|||
Of course some or all these of may change to cris_ver_v32p if/when |
|||
there's a new revision. */ |
|||
cris_ver_v32p |
|||
}; |
|||
|
|||
|
|||
/* Special registers. */ |
|||
struct cris_spec_reg |
|||
{ |
|||
const char *const name; |
|||
unsigned int number; |
|||
|
|||
/* The size of the register. */ |
|||
unsigned int reg_size; |
|||
|
|||
/* What CPU version the special register of that name is implemented
|
|||
in. If cris_ver_warning, emit an unimplemented-warning. */ |
|||
enum cris_insn_version_usage applicable_version; |
|||
|
|||
/* There might be a specific warning for using a special register
|
|||
here. */ |
|||
const char *const warning; |
|||
}; |
|||
extern const struct cris_spec_reg cris_spec_regs[]; |
|||
|
|||
|
|||
/* Support registers (kind of special too, but not named as such). */ |
|||
struct cris_support_reg |
|||
{ |
|||
const char *const name; |
|||
unsigned int number; |
|||
}; |
|||
extern const struct cris_support_reg cris_support_regs[]; |
|||
|
|||
/* Opcode-dependent constants. */ |
|||
#define AUTOINCR_BIT (0x04) |
|||
|
|||
/* Prefixes. */ |
|||
#define BDAP_QUICK_OPCODE (0x0100) |
|||
#define BDAP_QUICK_Z_BITS (0x0e00) |
|||
|
|||
#define BIAP_OPCODE (0x0540) |
|||
#define BIAP_Z_BITS (0x0a80) |
|||
|
|||
#define DIP_OPCODE (0x0970) |
|||
#define DIP_Z_BITS (0xf280) |
|||
|
|||
#define BDAP_INDIR_LOW (0x40) |
|||
#define BDAP_INDIR_LOW_Z (0x80) |
|||
#define BDAP_INDIR_HIGH (0x09) |
|||
#define BDAP_INDIR_HIGH_Z (0x02) |
|||
|
|||
#define BDAP_INDIR_OPCODE (BDAP_INDIR_HIGH * 0x0100 + BDAP_INDIR_LOW) |
|||
#define BDAP_INDIR_Z_BITS (BDAP_INDIR_HIGH_Z * 0x100 + BDAP_INDIR_LOW_Z) |
|||
#define BDAP_PC_LOW (BDAP_INDIR_LOW + CRIS_REG_PC) |
|||
#define BDAP_INCR_HIGH (BDAP_INDIR_HIGH + AUTOINCR_BIT) |
|||
|
|||
/* No prefix must have this code for its "match" bits in the
|
|||
opcode-table. "BCC .+2" will do nicely. */ |
|||
#define NO_CRIS_PREFIX 0 |
|||
|
|||
/* Definitions for condition codes. */ |
|||
#define CC_CC 0x0 |
|||
#define CC_HS 0x0 |
|||
#define CC_CS 0x1 |
|||
#define CC_LO 0x1 |
|||
#define CC_NE 0x2 |
|||
#define CC_EQ 0x3 |
|||
#define CC_VC 0x4 |
|||
#define CC_VS 0x5 |
|||
#define CC_PL 0x6 |
|||
#define CC_MI 0x7 |
|||
#define CC_LS 0x8 |
|||
#define CC_HI 0x9 |
|||
#define CC_GE 0xA |
|||
#define CC_LT 0xB |
|||
#define CC_GT 0xC |
|||
#define CC_LE 0xD |
|||
#define CC_A 0xE |
|||
#define CC_EXT 0xF |
|||
|
|||
/* A table of strings "cc", "cs"... indexed with condition code
|
|||
values as above. */ |
|||
extern const char *const cris_cc_strings[]; |
|||
|
|||
/* Bcc quick. */ |
|||
#define BRANCH_QUICK_LOW (0) |
|||
#define BRANCH_QUICK_HIGH (0) |
|||
#define BRANCH_QUICK_OPCODE (BRANCH_QUICK_HIGH * 0x0100 + BRANCH_QUICK_LOW) |
|||
#define BRANCH_QUICK_Z_BITS (0x0F00) |
|||
|
|||
/* BA quick. */ |
|||
#define BA_QUICK_HIGH (BRANCH_QUICK_HIGH + CC_A * 0x10) |
|||
#define BA_QUICK_OPCODE (BA_QUICK_HIGH * 0x100 + BRANCH_QUICK_LOW) |
|||
|
|||
/* Bcc [PC+]. */ |
|||
#define BRANCH_PC_LOW (0xFF) |
|||
#define BRANCH_INCR_HIGH (0x0D) |
|||
#define BA_PC_INCR_OPCODE \ |
|||
((BRANCH_INCR_HIGH + CC_A * 0x10) * 0x0100 + BRANCH_PC_LOW) |
|||
|
|||
/* Jump. */ |
|||
/* Note that old versions generated special register 8 (in high bits)
|
|||
and not-that-old versions recognized it as a jump-instruction. |
|||
That opcode now belongs to JUMPU. */ |
|||
#define JUMP_INDIR_OPCODE (0x0930) |
|||
#define JUMP_INDIR_Z_BITS (0xf2c0) |
|||
#define JUMP_PC_INCR_OPCODE \ |
|||
(JUMP_INDIR_OPCODE + AUTOINCR_BIT * 0x0100 + CRIS_REG_PC) |
|||
|
|||
#define MOVE_M_TO_PREG_OPCODE 0x0a30 |
|||
#define MOVE_M_TO_PREG_ZBITS 0x01c0 |
|||
|
|||
/* BDAP.D N,PC. */ |
|||
#define MOVE_PC_INCR_OPCODE_PREFIX \ |
|||
(((BDAP_INCR_HIGH | (CRIS_REG_PC << 4)) << 8) | BDAP_PC_LOW | (2 << 4)) |
|||
#define MOVE_PC_INCR_OPCODE_SUFFIX \ |
|||
(MOVE_M_TO_PREG_OPCODE | CRIS_REG_PC | (AUTOINCR_BIT << 8)) |
|||
|
|||
#define JUMP_PC_INCR_OPCODE_V32 (0x0DBF) |
|||
|
|||
/* BA DWORD (V32). */ |
|||
#define BA_DWORD_OPCODE (0x0EBF) |
|||
|
|||
/* Nop. */ |
|||
#define NOP_OPCODE (0x050F) |
|||
#define NOP_Z_BITS (0xFFFF ^ NOP_OPCODE) |
|||
|
|||
#define NOP_OPCODE_V32 (0x05B0) |
|||
#define NOP_Z_BITS_V32 (0xFFFF ^ NOP_OPCODE_V32) |
|||
|
|||
/* For the compatibility mode, let's use "MOVE R0,P0". Doesn't affect
|
|||
registers or flags. Unfortunately shuts off interrupts for one cycle |
|||
for < v32, but there doesn't seem to be any alternative without that |
|||
effect. */ |
|||
#define NOP_OPCODE_COMMON (0x630) |
|||
#define NOP_OPCODE_ZBITS_COMMON (0xffff & ~NOP_OPCODE_COMMON) |
|||
|
|||
/* LAPC.D */ |
|||
#define LAPC_DWORD_OPCODE (0x0D7F) |
|||
#define LAPC_DWORD_Z_BITS (0x0fff & ~LAPC_DWORD_OPCODE) |
|||
|
|||
/* Structure of an opcode table entry. */ |
|||
enum cris_imm_oprnd_size_type |
|||
{ |
|||
/* No size is applicable. */ |
|||
SIZE_NONE, |
|||
|
|||
/* Always 32 bits. */ |
|||
SIZE_FIX_32, |
|||
|
|||
/* Indicated by size of special register. */ |
|||
SIZE_SPEC_REG, |
|||
|
|||
/* Indicated by size field, signed. */ |
|||
SIZE_FIELD_SIGNED, |
|||
|
|||
/* Indicated by size field, unsigned. */ |
|||
SIZE_FIELD_UNSIGNED, |
|||
|
|||
/* Indicated by size field, no sign implied. */ |
|||
SIZE_FIELD |
|||
}; |
|||
|
|||
/* For GDB. FIXME: Is this the best way to handle opcode
|
|||
interpretation? */ |
|||
enum cris_op_type |
|||
{ |
|||
cris_not_implemented_op = 0, |
|||
cris_abs_op, |
|||
cris_addi_op, |
|||
cris_asr_op, |
|||
cris_asrq_op, |
|||
cris_ax_ei_setf_op, |
|||
cris_bdap_prefix, |
|||
cris_biap_prefix, |
|||
cris_break_op, |
|||
cris_btst_nop_op, |
|||
cris_clearf_di_op, |
|||
cris_dip_prefix, |
|||
cris_dstep_logshift_mstep_neg_not_op, |
|||
cris_eight_bit_offset_branch_op, |
|||
cris_move_mem_to_reg_movem_op, |
|||
cris_move_reg_to_mem_movem_op, |
|||
cris_move_to_preg_op, |
|||
cris_muls_op, |
|||
cris_mulu_op, |
|||
cris_none_reg_mode_add_sub_cmp_and_or_move_op, |
|||
cris_none_reg_mode_clear_test_op, |
|||
cris_none_reg_mode_jump_op, |
|||
cris_none_reg_mode_move_from_preg_op, |
|||
cris_quick_mode_add_sub_op, |
|||
cris_quick_mode_and_cmp_move_or_op, |
|||
cris_quick_mode_bdap_prefix, |
|||
cris_reg_mode_add_sub_cmp_and_or_move_op, |
|||
cris_reg_mode_clear_op, |
|||
cris_reg_mode_jump_op, |
|||
cris_reg_mode_move_from_preg_op, |
|||
cris_reg_mode_test_op, |
|||
cris_scc_op, |
|||
cris_sixteen_bit_offset_branch_op, |
|||
cris_three_operand_add_sub_cmp_and_or_op, |
|||
cris_three_operand_bound_op, |
|||
cris_two_operand_bound_op, |
|||
cris_xor_op |
|||
}; |
|||
|
|||
struct cris_opcode |
|||
{ |
|||
/* The name of the insn. */ |
|||
const char *name; |
|||
|
|||
/* Bits that must be 1 for a match. */ |
|||
unsigned int match; |
|||
|
|||
/* Bits that must be 0 for a match. */ |
|||
unsigned int lose; |
|||
|
|||
/* See the table in "opcodes/cris-opc.c". */ |
|||
const char *args; |
|||
|
|||
/* Nonzero if this is a delayed branch instruction. */ |
|||
char delayed; |
|||
|
|||
/* Size of immediate operands. */ |
|||
enum cris_imm_oprnd_size_type imm_oprnd_size; |
|||
|
|||
/* Indicates which version this insn was first implemented in. */ |
|||
enum cris_insn_version_usage applicable_version; |
|||
|
|||
/* What kind of operation this is. */ |
|||
enum cris_op_type op; |
|||
}; |
|||
extern const struct cris_opcode cris_opcodes[]; |
|||
|
|||
|
|||
/* These macros are for the target-specific flags in disassemble_info
|
|||
used at disassembly. */ |
|||
|
|||
/* This insn accesses memory. This flag is more trustworthy than
|
|||
checking insn_type for "dis_dref" which does not work for |
|||
e.g. "JSR [foo]". */ |
|||
#define CRIS_DIS_FLAG_MEMREF (1 << 0) |
|||
|
|||
/* The "target" field holds a register number. */ |
|||
#define CRIS_DIS_FLAG_MEM_TARGET_IS_REG (1 << 1) |
|||
|
|||
/* The "target2" field holds a register number; add it to "target". */ |
|||
#define CRIS_DIS_FLAG_MEM_TARGET2_IS_REG (1 << 2) |
|||
|
|||
/* Yet another add-on: the register in "target2" must be multiplied
|
|||
by 2 before adding to "target". */ |
|||
#define CRIS_DIS_FLAG_MEM_TARGET2_MULT2 (1 << 3) |
|||
|
|||
/* Yet another add-on: the register in "target2" must be multiplied
|
|||
by 4 (mutually exclusive with .._MULT2). */ |
|||
#define CRIS_DIS_FLAG_MEM_TARGET2_MULT4 (1 << 4) |
|||
|
|||
/* The register in "target2" is an indirect memory reference (of the
|
|||
register there), add to "target". Assumed size is dword (mutually |
|||
exclusive with .._MULT[24]). */ |
|||
#define CRIS_DIS_FLAG_MEM_TARGET2_MEM (1 << 5) |
|||
|
|||
/* Add-on to CRIS_DIS_FLAG_MEM_TARGET2_MEM; the memory access is "byte";
|
|||
sign-extended before adding to "target". */ |
|||
#define CRIS_DIS_FLAG_MEM_TARGET2_MEM_BYTE (1 << 6) |
|||
|
|||
/* Add-on to CRIS_DIS_FLAG_MEM_TARGET2_MEM; the memory access is "word";
|
|||
sign-extended before adding to "target". */ |
|||
#define CRIS_DIS_FLAG_MEM_TARGET2_MEM_WORD (1 << 7) |
|||
|
|||
#endif /* TARGET_CRIS_OPCODE_CRIS_H */ |
|||
|
|||
/*
|
|||
* Local variables: |
|||
* eval: (c-set-style "gnu") |
|||
* indent-tabs-mode: t |
|||
* End: |
|||
*/ |
|||
File diff suppressed because it is too large
File diff suppressed because it is too large
Loading…
Reference in new issue