cris: Add support for CRISv10 translation.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
This commit is contained in:
Edgar E. Iglesias 2010-02-15 12:18:57 +01:00
parent 46e246c911
commit 40e9eddd38
4 changed files with 1486 additions and 30 deletions

View File

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

View 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

View File

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

File diff suppressed because it is too large Load Diff