target/cris: Remove the deprecated CRIS target
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>
This commit is contained in:
parent
01d01edc9f
commit
44e4075bf4
@ -227,7 +227,6 @@ F: tests/functional/test_avr_mega2560.py
|
||||
CRIS TCG CPUs
|
||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
S: Maintained
|
||||
F: target/cris/
|
||||
F: disas/cris.c
|
||||
|
||||
Hexagon TCG CPUs
|
||||
|
@ -206,14 +206,6 @@ in the QEMU object model anymore. ``Sun-UltraSparc-IIIi+`` and
|
||||
but for consistency these will get removed in a future release, too.
|
||||
Use ``Sun-UltraSparc-IIIi-plus`` and ``Sun-UltraSparc-IV-plus`` instead.
|
||||
|
||||
CRIS CPU architecture (since 9.0)
|
||||
'''''''''''''''''''''''''''''''''
|
||||
|
||||
The CRIS architecture was pulled from Linux in 4.17 and the compiler
|
||||
is no longer packaged in any distro making it harder to run the
|
||||
``check-tcg`` tests. Unless we can improve the testing situation there
|
||||
is a chance the code will bitrot without anyone noticing.
|
||||
|
||||
System emulator machines
|
||||
------------------------
|
||||
|
||||
|
@ -26,10 +26,6 @@ depending on the guest architecture.
|
||||
- :ref:`Yes<AVR-System-emulator>`
|
||||
- No
|
||||
- 8 bit micro controller, often used in maker projects
|
||||
* - Cris
|
||||
- Yes
|
||||
- Yes
|
||||
- Embedded RISC chip developed by AXIS
|
||||
* - Hexagon
|
||||
- No
|
||||
- Yes
|
||||
|
@ -889,6 +889,13 @@ Nios II CPU (removed in 9.1)
|
||||
QEMU Nios II architecture was orphan; Intel has EOL'ed the Nios II
|
||||
processor IP (see `Intel discontinuance notification`_).
|
||||
|
||||
CRIS CPU architecture (removed in 9.2)
|
||||
''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The CRIS architecture was pulled from Linux in 4.17 and the compiler
|
||||
was no longer packaged in any distro making it harder to run the
|
||||
``check-tcg`` tests.
|
||||
|
||||
System accelerators
|
||||
-------------------
|
||||
|
||||
|
@ -151,8 +151,8 @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
|
||||
#else
|
||||
/*
|
||||
* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
|
||||
* S390, SH4, TriCore, and Xtensa. Our other supported targets,
|
||||
* such CRIS, do not have floating-point.
|
||||
* S390, SH4, TriCore, and Xtensa. Our other supported targets
|
||||
* do not have floating-point.
|
||||
*/
|
||||
if (snan_bit_is_one(status)) {
|
||||
/* set all bits other than msb */
|
||||
|
@ -11,7 +11,6 @@
|
||||
#pragma GCC poison TARGET_AARCH64
|
||||
#pragma GCC poison TARGET_ALPHA
|
||||
#pragma GCC poison TARGET_ARM
|
||||
#pragma GCC poison TARGET_CRIS
|
||||
#pragma GCC poison TARGET_HEXAGON
|
||||
#pragma GCC poison TARGET_HPPA
|
||||
#pragma GCC poison TARGET_LOONGARCH64
|
||||
|
@ -9,9 +9,6 @@ arm
|
||||
avr
|
||||
~ .*/qemu((/include)?/hw/avr/.*|/target/avr/.*)
|
||||
|
||||
cris
|
||||
~ .*/qemu/target/cris/.*
|
||||
|
||||
hexagon-gen (component should be ignored in analysis)
|
||||
~ .*/qemu(/target/hexagon/.*generated.*)
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
source alpha/Kconfig
|
||||
source arm/Kconfig
|
||||
source avr/Kconfig
|
||||
source cris/Kconfig
|
||||
source hppa/Kconfig
|
||||
source i386/Kconfig
|
||||
source loongarch/Kconfig
|
||||
|
@ -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
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,6 @@
|
||||
subdir('alpha')
|
||||
subdir('arm')
|
||||
subdir('avr')
|
||||
subdir('cris')
|
||||
subdir('hexagon')
|
||||
subdir('hppa')
|
||||
subdir('i386')
|
||||
|
@ -3487,12 +3487,6 @@ cred-internals.h: 559
|
||||
CREDITS: 603
|
||||
crime.c: 2833
|
||||
crime.h: 5271
|
||||
cris: 4096
|
||||
cris_defs_asm.h: 3805
|
||||
crisksyms.c: 472
|
||||
cris_supp_reg.h: 198
|
||||
crisv10.c: 129158
|
||||
crisv10.h: 4289
|
||||
crm_regs.h: 1700
|
||||
cr_pll.c: 4842
|
||||
crt0_ram.S: 2152
|
||||
|
@ -30,7 +30,6 @@ static struct arch2cpu cpus_map[] = {
|
||||
{ "x86_64", "qemu64,apic-id=0" },
|
||||
{ "i386", "qemu32,apic-id=0" },
|
||||
{ "alpha", "ev67" },
|
||||
{ "cris", "crisv32" },
|
||||
{ "m68k", "m5206" },
|
||||
{ "microblaze", "any" },
|
||||
{ "microblazeel", "any" },
|
||||
|
Loading…
Reference in New Issue
Block a user