mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-27 13:30:52 +00:00
cris: Add support for CRISv10 translation.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
This commit is contained in:
parent
46e246c911
commit
40e9eddd38
@ -262,4 +262,7 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
|
||||
| X_FLAG | PFIX_FLAG));
|
||||
}
|
||||
|
||||
#define cpu_list cris_cpu_list
|
||||
void cris_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
|
||||
|
||||
#endif
|
||||
|
108
target-cris/crisv10-decode.h
Normal file
108
target-cris/crisv10-decode.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#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 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
|
||||
|
@ -86,6 +86,7 @@ typedef struct DisasContext {
|
||||
target_ulong pc, ppc;
|
||||
|
||||
/* Decoder. */
|
||||
unsigned int (*decoder)(struct DisasContext *dc);
|
||||
uint32_t ir;
|
||||
uint32_t opcode;
|
||||
unsigned int op1;
|
||||
@ -94,6 +95,11 @@ typedef struct DisasContext {
|
||||
unsigned int mode;
|
||||
unsigned int postinc;
|
||||
|
||||
unsigned int size;
|
||||
unsigned int src;
|
||||
unsigned int dst;
|
||||
unsigned int cond;
|
||||
|
||||
int update_cc;
|
||||
int cc_op;
|
||||
int cc_size;
|
||||
@ -108,6 +114,8 @@ typedef struct DisasContext {
|
||||
int flags_x;
|
||||
|
||||
int clear_x; /* Clear x after this insn? */
|
||||
int clear_prefix; /* Clear prefix after this insn? */
|
||||
int clear_locked_irq; /* Clear the irq lockout. */
|
||||
int cpustate_changed;
|
||||
unsigned int tb_flags; /* tb dependent flags. */
|
||||
int is_jmp;
|
||||
@ -219,6 +227,12 @@ static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn)
|
||||
}
|
||||
}
|
||||
|
||||
static void cris_lock_irq(DisasContext *dc)
|
||||
{
|
||||
dc->clear_locked_irq = 0;
|
||||
t_gen_mov_env_TN(locked_irq, tcg_const_tl(1));
|
||||
}
|
||||
|
||||
static inline void t_gen_raise_exception(uint32_t index)
|
||||
{
|
||||
TCGv_i32 tmp = tcg_const_i32(index);
|
||||
@ -332,6 +346,24 @@ static void t_gen_cris_dstep(TCGv d, TCGv a, TCGv b)
|
||||
gen_set_label(l1);
|
||||
}
|
||||
|
||||
static void t_gen_cris_mstep(TCGv d, TCGv a, TCGv b, TCGv ccs)
|
||||
{
|
||||
TCGv t;
|
||||
|
||||
/*
|
||||
* d <<= 1
|
||||
* if (n)
|
||||
* d += s;
|
||||
*/
|
||||
t = tcg_temp_new();
|
||||
tcg_gen_shli_tl(d, a, 1);
|
||||
tcg_gen_shli_tl(t, ccs, 31 - 3);
|
||||
tcg_gen_sari_tl(t, t, 31);
|
||||
tcg_gen_and_tl(t, t, b);
|
||||
tcg_gen_add_tl(d, d, t);
|
||||
tcg_temp_free(t);
|
||||
}
|
||||
|
||||
/* Extended arithmetics on CRIS. */
|
||||
static inline void t_gen_add_flag(TCGv d, int flag)
|
||||
{
|
||||
@ -634,7 +666,7 @@ static void cris_evaluate_flags(DisasContext *dc)
|
||||
if (dc->flags_x)
|
||||
tcg_gen_ori_tl(cpu_PR[PR_CCS],
|
||||
cpu_PR[PR_CCS], X_FLAG);
|
||||
else
|
||||
else if (dc->cc_op == CC_OP_FLAGS)
|
||||
tcg_gen_andi_tl(cpu_PR[PR_CCS],
|
||||
cpu_PR[PR_CCS], ~X_FLAG);
|
||||
}
|
||||
@ -774,6 +806,9 @@ static void cris_alu_op_exec(DisasContext *dc, int op,
|
||||
case CC_OP_DSTEP:
|
||||
t_gen_cris_dstep(dst, a, b);
|
||||
break;
|
||||
case CC_OP_MSTEP:
|
||||
t_gen_cris_mstep(dst, a, b, cpu_PR[PR_CCS]);
|
||||
break;
|
||||
case CC_OP_BOUND:
|
||||
{
|
||||
int l1;
|
||||
@ -878,7 +913,8 @@ static void gen_tst_cc (DisasContext *dc, TCGv cc, int cond)
|
||||
move_opt = (dc->cc_op == CC_OP_MOVE);
|
||||
switch (cond) {
|
||||
case CC_EQ:
|
||||
if (arith_opt || move_opt) {
|
||||
if ((arith_opt || move_opt)
|
||||
&& dc->cc_x_uptodate != (2 | X_FLAG)) {
|
||||
/* If cc_result is zero, T0 should be
|
||||
non-zero otherwise T0 should be zero. */
|
||||
int l1;
|
||||
@ -896,9 +932,10 @@ static void gen_tst_cc (DisasContext *dc, TCGv cc, int cond)
|
||||
}
|
||||
break;
|
||||
case CC_NE:
|
||||
if (arith_opt || move_opt)
|
||||
if ((arith_opt || move_opt)
|
||||
&& dc->cc_x_uptodate != (2 | X_FLAG)) {
|
||||
tcg_gen_mov_tl(cc, cc_result);
|
||||
else {
|
||||
} else {
|
||||
cris_evaluate_flags(dc);
|
||||
tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
|
||||
Z_FLAG);
|
||||
@ -2058,16 +2095,17 @@ static unsigned int dec_setclrf(DisasContext *dc)
|
||||
dc->flags_x = 0;
|
||||
}
|
||||
|
||||
/* Break the TB if the P flag changes. */
|
||||
if (flags & P_FLAG) {
|
||||
if ((set && !(dc->tb_flags & P_FLAG))
|
||||
|| (!set && (dc->tb_flags & P_FLAG))) {
|
||||
tcg_gen_movi_tl(env_pc, dc->pc + 2);
|
||||
dc->is_jmp = DISAS_UPDATE;
|
||||
dc->cpustate_changed = 1;
|
||||
}
|
||||
/* Break the TB if any of the SPI flag changes. */
|
||||
if (flags & (P_FLAG | S_FLAG)) {
|
||||
tcg_gen_movi_tl(env_pc, dc->pc + 2);
|
||||
dc->is_jmp = DISAS_UPDATE;
|
||||
dc->cpustate_changed = 1;
|
||||
}
|
||||
if (flags & S_FLAG) {
|
||||
|
||||
/* For the I flag, only act on posedge. */
|
||||
if ((flags & I_FLAG)) {
|
||||
tcg_gen_movi_tl(env_pc, dc->pc + 2);
|
||||
dc->is_jmp = DISAS_UPDATE;
|
||||
dc->cpustate_changed = 1;
|
||||
}
|
||||
|
||||
@ -2143,17 +2181,22 @@ static unsigned int dec_move_rp(DisasContext *dc)
|
||||
static unsigned int dec_move_pr(DisasContext *dc)
|
||||
{
|
||||
TCGv t0;
|
||||
LOG_DIS("move $p%u, $r%u\n", dc->op1, dc->op2);
|
||||
LOG_DIS("move $p%u, $r%u\n", dc->op2, dc->op1);
|
||||
cris_cc_mask(dc, 0);
|
||||
|
||||
if (dc->op2 == PR_CCS)
|
||||
cris_evaluate_flags(dc);
|
||||
|
||||
t0 = tcg_temp_new();
|
||||
t_gen_mov_TN_preg(t0, dc->op2);
|
||||
cris_alu(dc, CC_OP_MOVE,
|
||||
cpu_R[dc->op1], cpu_R[dc->op1], t0, preg_sizes[dc->op2]);
|
||||
tcg_temp_free(t0);
|
||||
if (dc->op2 == PR_DZ) {
|
||||
tcg_gen_movi_tl(cpu_R[dc->op1], 0);
|
||||
} else {
|
||||
t0 = tcg_temp_new();
|
||||
t_gen_mov_TN_preg(t0, dc->op2);
|
||||
cris_alu(dc, CC_OP_MOVE,
|
||||
cpu_R[dc->op1], cpu_R[dc->op1], t0,
|
||||
preg_sizes[dc->op2]);
|
||||
tcg_temp_free(t0);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
@ -3026,8 +3069,7 @@ static struct decoder_info {
|
||||
{{0, 0}, dec_null}
|
||||
};
|
||||
|
||||
static inline unsigned int
|
||||
cris_decoder(DisasContext *dc)
|
||||
static unsigned int crisv32_decoder(DisasContext *dc)
|
||||
{
|
||||
unsigned int insn_len = 2;
|
||||
int i;
|
||||
@ -3090,6 +3132,7 @@ static void check_breakpoint(CPUState *env, DisasContext *dc)
|
||||
}
|
||||
}
|
||||
|
||||
#include "translate_v10.c"
|
||||
|
||||
/*
|
||||
* Delay slots on QEMU/CRIS.
|
||||
@ -3132,7 +3175,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
||||
{
|
||||
uint16_t *gen_opc_end;
|
||||
uint32_t pc_start;
|
||||
unsigned int insn_len;
|
||||
unsigned int insn_len, orig_flags;
|
||||
int j, lj;
|
||||
struct DisasContext ctx;
|
||||
struct DisasContext *dc = &ctx;
|
||||
@ -3143,6 +3186,11 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
||||
|
||||
qemu_log_try_set_file(stderr);
|
||||
|
||||
if (env->pregs[PR_VR] == 32)
|
||||
dc->decoder = crisv32_decoder;
|
||||
else
|
||||
dc->decoder = crisv10_decoder;
|
||||
|
||||
/* Odd PC indicates that branch is rexecuting due to exception in the
|
||||
* delayslot, like in real hw.
|
||||
*/
|
||||
@ -3162,12 +3210,15 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
||||
dc->cc_x_uptodate = 0;
|
||||
dc->cc_mask = 0;
|
||||
dc->update_cc = 0;
|
||||
dc->clear_prefix = 0;
|
||||
dc->clear_locked_irq = 1;
|
||||
|
||||
cris_update_cc_op(dc, CC_OP_FLAGS, 4);
|
||||
dc->cc_size_uptodate = -1;
|
||||
|
||||
/* Decode TB flags. */
|
||||
dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG | X_FLAG);
|
||||
orig_flags = dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG \
|
||||
| X_FLAG | PFIX_FLAG);
|
||||
dc->delayed_branch = !!(tb->flags & 7);
|
||||
if (dc->delayed_branch)
|
||||
dc->jmp = JMP_INDIRECT;
|
||||
@ -3233,7 +3284,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
||||
gen_io_start();
|
||||
dc->clear_x = 1;
|
||||
|
||||
insn_len = cris_decoder(dc);
|
||||
insn_len = dc->decoder(dc);
|
||||
dc->ppc = dc->pc;
|
||||
dc->pc += insn_len;
|
||||
if (dc->clear_x)
|
||||
@ -3271,6 +3322,13 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
||||
&& (dc->pc < next_page_start)
|
||||
&& num_insns < max_insns);
|
||||
|
||||
if (dc->tb_flags != orig_flags) {
|
||||
dc->cpustate_changed = 1;
|
||||
}
|
||||
|
||||
if (dc->clear_locked_irq)
|
||||
t_gen_mov_env_TN(locked_irq, tcg_const_tl(0));
|
||||
|
||||
npc = dc->pc;
|
||||
if (dc->jmp == JMP_DIRECT && !dc->delayed_branch)
|
||||
npc = dc->jmp_pc;
|
||||
@ -3330,7 +3388,8 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
||||
#ifdef DEBUG_DISAS
|
||||
#if !DISAS_CRIS
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
|
||||
log_target_disas(pc_start, dc->pc - pc_start, 0);
|
||||
log_target_disas(pc_start, dc->pc - pc_start,
|
||||
dc->env->pregs[PR_VR]);
|
||||
qemu_log("\nisize=%d osize=%zd\n",
|
||||
dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
|
||||
}
|
||||
@ -3390,6 +3449,39 @@ void cpu_dump_state (CPUState *env, FILE *f,
|
||||
|
||||
}
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t vr;
|
||||
const char *name;
|
||||
} cris_cores[] = {
|
||||
{8, "crisv8"},
|
||||
{9, "crisv9"},
|
||||
{10, "crisv10"},
|
||||
{11, "crisv11"},
|
||||
{32, "crisv32"},
|
||||
};
|
||||
|
||||
void cris_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
(*cpu_fprintf)(f, "Available CPUs:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(cris_cores); i++) {
|
||||
(*cpu_fprintf)(f, " %s\n", cris_cores[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t vr_by_name(const char *name)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < ARRAY_SIZE(cris_cores); i++) {
|
||||
if (strcmp(name, cris_cores[i].name) == 0) {
|
||||
return cris_cores[i].vr;
|
||||
}
|
||||
}
|
||||
return 32;
|
||||
}
|
||||
|
||||
CPUCRISState *cpu_cris_init (const char *cpu_model)
|
||||
{
|
||||
CPUCRISState *env;
|
||||
@ -3398,6 +3490,7 @@ CPUCRISState *cpu_cris_init (const char *cpu_model)
|
||||
|
||||
env = qemu_mallocz(sizeof(CPUCRISState));
|
||||
|
||||
env->pregs[PR_VR] = vr_by_name(cpu_model);
|
||||
cpu_exec_init(env);
|
||||
cpu_reset(env);
|
||||
qemu_init_vcpu(env);
|
||||
@ -3407,6 +3500,15 @@ CPUCRISState *cpu_cris_init (const char *cpu_model)
|
||||
|
||||
tcg_initialized = 1;
|
||||
|
||||
#define GEN_HELPER 2
|
||||
#include "helper.h"
|
||||
|
||||
if (env->pregs[PR_VR] < 32) {
|
||||
cpu_crisv10_init(env);
|
||||
return env;
|
||||
}
|
||||
|
||||
|
||||
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
|
||||
cc_x = tcg_global_mem_new(TCG_AREG0,
|
||||
offsetof(CPUState, cc_x), "cc_x");
|
||||
@ -3447,26 +3549,26 @@ CPUCRISState *cpu_cris_init (const char *cpu_model)
|
||||
pregnames[i]);
|
||||
}
|
||||
|
||||
#define GEN_HELPER 2
|
||||
#include "helper.h"
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
void cpu_reset (CPUCRISState *env)
|
||||
{
|
||||
uint32_t vr;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
|
||||
qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
|
||||
log_cpu_state(env, 0);
|
||||
}
|
||||
|
||||
vr = env->pregs[PR_VR];
|
||||
memset(env, 0, offsetof(CPUCRISState, breakpoints));
|
||||
env->pregs[PR_VR] = vr;
|
||||
tlb_flush(env, 1);
|
||||
|
||||
env->pregs[PR_VR] = 32;
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
/* start in user mode with interrupts enabled. */
|
||||
env->pregs[PR_CCS] |= U_FLAG | I_FLAG;
|
||||
env->pregs[PR_CCS] |= U_FLAG | I_FLAG | P_FLAG;
|
||||
#else
|
||||
cris_mmu_init(env);
|
||||
env->pregs[PR_CCS] = 0;
|
||||
|
1243
target-cris/translate_v10.c
Normal file
1243
target-cris/translate_v10.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user