Revision 40e9eddd target-cris/translate.c
b/target-cris/translate.c | ||
---|---|---|
86 | 86 |
target_ulong pc, ppc; |
87 | 87 |
|
88 | 88 |
/* Decoder. */ |
89 |
unsigned int (*decoder)(struct DisasContext *dc); |
|
89 | 90 |
uint32_t ir; |
90 | 91 |
uint32_t opcode; |
91 | 92 |
unsigned int op1; |
... | ... | |
94 | 95 |
unsigned int mode; |
95 | 96 |
unsigned int postinc; |
96 | 97 |
|
98 |
unsigned int size; |
|
99 |
unsigned int src; |
|
100 |
unsigned int dst; |
|
101 |
unsigned int cond; |
|
102 |
|
|
97 | 103 |
int update_cc; |
98 | 104 |
int cc_op; |
99 | 105 |
int cc_size; |
... | ... | |
108 | 114 |
int flags_x; |
109 | 115 |
|
110 | 116 |
int clear_x; /* Clear x after this insn? */ |
117 |
int clear_prefix; /* Clear prefix after this insn? */ |
|
118 |
int clear_locked_irq; /* Clear the irq lockout. */ |
|
111 | 119 |
int cpustate_changed; |
112 | 120 |
unsigned int tb_flags; /* tb dependent flags. */ |
113 | 121 |
int is_jmp; |
... | ... | |
219 | 227 |
} |
220 | 228 |
} |
221 | 229 |
|
230 |
static void cris_lock_irq(DisasContext *dc) |
|
231 |
{ |
|
232 |
dc->clear_locked_irq = 0; |
|
233 |
t_gen_mov_env_TN(locked_irq, tcg_const_tl(1)); |
|
234 |
} |
|
235 |
|
|
222 | 236 |
static inline void t_gen_raise_exception(uint32_t index) |
223 | 237 |
{ |
224 | 238 |
TCGv_i32 tmp = tcg_const_i32(index); |
... | ... | |
332 | 346 |
gen_set_label(l1); |
333 | 347 |
} |
334 | 348 |
|
349 |
static void t_gen_cris_mstep(TCGv d, TCGv a, TCGv b, TCGv ccs) |
|
350 |
{ |
|
351 |
TCGv t; |
|
352 |
|
|
353 |
/* |
|
354 |
* d <<= 1 |
|
355 |
* if (n) |
|
356 |
* d += s; |
|
357 |
*/ |
|
358 |
t = tcg_temp_new(); |
|
359 |
tcg_gen_shli_tl(d, a, 1); |
|
360 |
tcg_gen_shli_tl(t, ccs, 31 - 3); |
|
361 |
tcg_gen_sari_tl(t, t, 31); |
|
362 |
tcg_gen_and_tl(t, t, b); |
|
363 |
tcg_gen_add_tl(d, d, t); |
|
364 |
tcg_temp_free(t); |
|
365 |
} |
|
366 |
|
|
335 | 367 |
/* Extended arithmetics on CRIS. */ |
336 | 368 |
static inline void t_gen_add_flag(TCGv d, int flag) |
337 | 369 |
{ |
... | ... | |
634 | 666 |
if (dc->flags_x) |
635 | 667 |
tcg_gen_ori_tl(cpu_PR[PR_CCS], |
636 | 668 |
cpu_PR[PR_CCS], X_FLAG); |
637 |
else |
|
669 |
else if (dc->cc_op == CC_OP_FLAGS)
|
|
638 | 670 |
tcg_gen_andi_tl(cpu_PR[PR_CCS], |
639 | 671 |
cpu_PR[PR_CCS], ~X_FLAG); |
640 | 672 |
} |
... | ... | |
774 | 806 |
case CC_OP_DSTEP: |
775 | 807 |
t_gen_cris_dstep(dst, a, b); |
776 | 808 |
break; |
809 |
case CC_OP_MSTEP: |
|
810 |
t_gen_cris_mstep(dst, a, b, cpu_PR[PR_CCS]); |
|
811 |
break; |
|
777 | 812 |
case CC_OP_BOUND: |
778 | 813 |
{ |
779 | 814 |
int l1; |
... | ... | |
878 | 913 |
move_opt = (dc->cc_op == CC_OP_MOVE); |
879 | 914 |
switch (cond) { |
880 | 915 |
case CC_EQ: |
881 |
if (arith_opt || move_opt) { |
|
916 |
if ((arith_opt || move_opt) |
|
917 |
&& dc->cc_x_uptodate != (2 | X_FLAG)) { |
|
882 | 918 |
/* If cc_result is zero, T0 should be |
883 | 919 |
non-zero otherwise T0 should be zero. */ |
884 | 920 |
int l1; |
... | ... | |
896 | 932 |
} |
897 | 933 |
break; |
898 | 934 |
case CC_NE: |
899 |
if (arith_opt || move_opt) |
|
935 |
if ((arith_opt || move_opt) |
|
936 |
&& dc->cc_x_uptodate != (2 | X_FLAG)) { |
|
900 | 937 |
tcg_gen_mov_tl(cc, cc_result); |
901 |
else {
|
|
938 |
} else {
|
|
902 | 939 |
cris_evaluate_flags(dc); |
903 | 940 |
tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], |
904 | 941 |
Z_FLAG); |
... | ... | |
2058 | 2095 |
dc->flags_x = 0; |
2059 | 2096 |
} |
2060 | 2097 |
|
2061 |
/* Break the TB if the P flag changes. */ |
|
2062 |
if (flags & P_FLAG) { |
|
2063 |
if ((set && !(dc->tb_flags & P_FLAG)) |
|
2064 |
|| (!set && (dc->tb_flags & P_FLAG))) { |
|
2065 |
tcg_gen_movi_tl(env_pc, dc->pc + 2); |
|
2066 |
dc->is_jmp = DISAS_UPDATE; |
|
2067 |
dc->cpustate_changed = 1; |
|
2068 |
} |
|
2098 |
/* Break the TB if any of the SPI flag changes. */ |
|
2099 |
if (flags & (P_FLAG | S_FLAG)) { |
|
2100 |
tcg_gen_movi_tl(env_pc, dc->pc + 2); |
|
2101 |
dc->is_jmp = DISAS_UPDATE; |
|
2102 |
dc->cpustate_changed = 1; |
|
2069 | 2103 |
} |
2070 |
if (flags & S_FLAG) { |
|
2104 |
|
|
2105 |
/* For the I flag, only act on posedge. */ |
|
2106 |
if ((flags & I_FLAG)) { |
|
2107 |
tcg_gen_movi_tl(env_pc, dc->pc + 2); |
|
2108 |
dc->is_jmp = DISAS_UPDATE; |
|
2071 | 2109 |
dc->cpustate_changed = 1; |
2072 | 2110 |
} |
2073 | 2111 |
|
... | ... | |
2143 | 2181 |
static unsigned int dec_move_pr(DisasContext *dc) |
2144 | 2182 |
{ |
2145 | 2183 |
TCGv t0; |
2146 |
LOG_DIS("move $p%u, $r%u\n", dc->op1, dc->op2);
|
|
2184 |
LOG_DIS("move $p%u, $r%u\n", dc->op2, dc->op1);
|
|
2147 | 2185 |
cris_cc_mask(dc, 0); |
2148 | 2186 |
|
2149 | 2187 |
if (dc->op2 == PR_CCS) |
2150 | 2188 |
cris_evaluate_flags(dc); |
2151 | 2189 |
|
2152 |
t0 = tcg_temp_new(); |
|
2153 |
t_gen_mov_TN_preg(t0, dc->op2); |
|
2154 |
cris_alu(dc, CC_OP_MOVE, |
|
2155 |
cpu_R[dc->op1], cpu_R[dc->op1], t0, preg_sizes[dc->op2]); |
|
2156 |
tcg_temp_free(t0); |
|
2190 |
if (dc->op2 == PR_DZ) { |
|
2191 |
tcg_gen_movi_tl(cpu_R[dc->op1], 0); |
|
2192 |
} else { |
|
2193 |
t0 = tcg_temp_new(); |
|
2194 |
t_gen_mov_TN_preg(t0, dc->op2); |
|
2195 |
cris_alu(dc, CC_OP_MOVE, |
|
2196 |
cpu_R[dc->op1], cpu_R[dc->op1], t0, |
|
2197 |
preg_sizes[dc->op2]); |
|
2198 |
tcg_temp_free(t0); |
|
2199 |
} |
|
2157 | 2200 |
return 2; |
2158 | 2201 |
} |
2159 | 2202 |
|
... | ... | |
3026 | 3069 |
{{0, 0}, dec_null} |
3027 | 3070 |
}; |
3028 | 3071 |
|
3029 |
static inline unsigned int |
|
3030 |
cris_decoder(DisasContext *dc) |
|
3072 |
static unsigned int crisv32_decoder(DisasContext *dc) |
|
3031 | 3073 |
{ |
3032 | 3074 |
unsigned int insn_len = 2; |
3033 | 3075 |
int i; |
... | ... | |
3090 | 3132 |
} |
3091 | 3133 |
} |
3092 | 3134 |
|
3135 |
#include "translate_v10.c" |
|
3093 | 3136 |
|
3094 | 3137 |
/* |
3095 | 3138 |
* Delay slots on QEMU/CRIS. |
... | ... | |
3132 | 3175 |
{ |
3133 | 3176 |
uint16_t *gen_opc_end; |
3134 | 3177 |
uint32_t pc_start; |
3135 |
unsigned int insn_len; |
|
3178 |
unsigned int insn_len, orig_flags;
|
|
3136 | 3179 |
int j, lj; |
3137 | 3180 |
struct DisasContext ctx; |
3138 | 3181 |
struct DisasContext *dc = &ctx; |
... | ... | |
3143 | 3186 |
|
3144 | 3187 |
qemu_log_try_set_file(stderr); |
3145 | 3188 |
|
3189 |
if (env->pregs[PR_VR] == 32) |
|
3190 |
dc->decoder = crisv32_decoder; |
|
3191 |
else |
|
3192 |
dc->decoder = crisv10_decoder; |
|
3193 |
|
|
3146 | 3194 |
/* Odd PC indicates that branch is rexecuting due to exception in the |
3147 | 3195 |
* delayslot, like in real hw. |
3148 | 3196 |
*/ |
... | ... | |
3162 | 3210 |
dc->cc_x_uptodate = 0; |
3163 | 3211 |
dc->cc_mask = 0; |
3164 | 3212 |
dc->update_cc = 0; |
3213 |
dc->clear_prefix = 0; |
|
3214 |
dc->clear_locked_irq = 1; |
|
3165 | 3215 |
|
3166 | 3216 |
cris_update_cc_op(dc, CC_OP_FLAGS, 4); |
3167 | 3217 |
dc->cc_size_uptodate = -1; |
3168 | 3218 |
|
3169 | 3219 |
/* Decode TB flags. */ |
3170 |
dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG | X_FLAG); |
|
3220 |
orig_flags = dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG \ |
|
3221 |
| X_FLAG | PFIX_FLAG); |
|
3171 | 3222 |
dc->delayed_branch = !!(tb->flags & 7); |
3172 | 3223 |
if (dc->delayed_branch) |
3173 | 3224 |
dc->jmp = JMP_INDIRECT; |
... | ... | |
3233 | 3284 |
gen_io_start(); |
3234 | 3285 |
dc->clear_x = 1; |
3235 | 3286 |
|
3236 |
insn_len = cris_decoder(dc);
|
|
3287 |
insn_len = dc->decoder(dc);
|
|
3237 | 3288 |
dc->ppc = dc->pc; |
3238 | 3289 |
dc->pc += insn_len; |
3239 | 3290 |
if (dc->clear_x) |
... | ... | |
3271 | 3322 |
&& (dc->pc < next_page_start) |
3272 | 3323 |
&& num_insns < max_insns); |
3273 | 3324 |
|
3325 |
if (dc->tb_flags != orig_flags) { |
|
3326 |
dc->cpustate_changed = 1; |
|
3327 |
} |
|
3328 |
|
|
3329 |
if (dc->clear_locked_irq) |
|
3330 |
t_gen_mov_env_TN(locked_irq, tcg_const_tl(0)); |
|
3331 |
|
|
3274 | 3332 |
npc = dc->pc; |
3275 | 3333 |
if (dc->jmp == JMP_DIRECT && !dc->delayed_branch) |
3276 | 3334 |
npc = dc->jmp_pc; |
... | ... | |
3330 | 3388 |
#ifdef DEBUG_DISAS |
3331 | 3389 |
#if !DISAS_CRIS |
3332 | 3390 |
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { |
3333 |
log_target_disas(pc_start, dc->pc - pc_start, 0); |
|
3391 |
log_target_disas(pc_start, dc->pc - pc_start, |
|
3392 |
dc->env->pregs[PR_VR]); |
|
3334 | 3393 |
qemu_log("\nisize=%d osize=%zd\n", |
3335 | 3394 |
dc->pc - pc_start, gen_opc_ptr - gen_opc_buf); |
3336 | 3395 |
} |
... | ... | |
3390 | 3449 |
|
3391 | 3450 |
} |
3392 | 3451 |
|
3452 |
struct |
|
3453 |
{ |
|
3454 |
uint32_t vr; |
|
3455 |
const char *name; |
|
3456 |
} cris_cores[] = { |
|
3457 |
{8, "crisv8"}, |
|
3458 |
{9, "crisv9"}, |
|
3459 |
{10, "crisv10"}, |
|
3460 |
{11, "crisv11"}, |
|
3461 |
{32, "crisv32"}, |
|
3462 |
}; |
|
3463 |
|
|
3464 |
void cris_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) |
|
3465 |
{ |
|
3466 |
unsigned int i; |
|
3467 |
|
|
3468 |
(*cpu_fprintf)(f, "Available CPUs:\n"); |
|
3469 |
for (i = 0; i < ARRAY_SIZE(cris_cores); i++) { |
|
3470 |
(*cpu_fprintf)(f, " %s\n", cris_cores[i].name); |
|
3471 |
} |
|
3472 |
} |
|
3473 |
|
|
3474 |
static uint32_t vr_by_name(const char *name) |
|
3475 |
{ |
|
3476 |
unsigned int i; |
|
3477 |
for (i = 0; i < ARRAY_SIZE(cris_cores); i++) { |
|
3478 |
if (strcmp(name, cris_cores[i].name) == 0) { |
|
3479 |
return cris_cores[i].vr; |
|
3480 |
} |
|
3481 |
} |
|
3482 |
return 32; |
|
3483 |
} |
|
3484 |
|
|
3393 | 3485 |
CPUCRISState *cpu_cris_init (const char *cpu_model) |
3394 | 3486 |
{ |
3395 | 3487 |
CPUCRISState *env; |
... | ... | |
3398 | 3490 |
|
3399 | 3491 |
env = qemu_mallocz(sizeof(CPUCRISState)); |
3400 | 3492 |
|
3493 |
env->pregs[PR_VR] = vr_by_name(cpu_model); |
|
3401 | 3494 |
cpu_exec_init(env); |
3402 | 3495 |
cpu_reset(env); |
3403 | 3496 |
qemu_init_vcpu(env); |
... | ... | |
3407 | 3500 |
|
3408 | 3501 |
tcg_initialized = 1; |
3409 | 3502 |
|
3503 |
#define GEN_HELPER 2 |
|
3504 |
#include "helper.h" |
|
3505 |
|
|
3506 |
if (env->pregs[PR_VR] < 32) { |
|
3507 |
cpu_crisv10_init(env); |
|
3508 |
return env; |
|
3509 |
} |
|
3510 |
|
|
3511 |
|
|
3410 | 3512 |
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); |
3411 | 3513 |
cc_x = tcg_global_mem_new(TCG_AREG0, |
3412 | 3514 |
offsetof(CPUState, cc_x), "cc_x"); |
... | ... | |
3447 | 3549 |
pregnames[i]); |
3448 | 3550 |
} |
3449 | 3551 |
|
3450 |
#define GEN_HELPER 2 |
|
3451 |
#include "helper.h" |
|
3452 |
|
|
3453 | 3552 |
return env; |
3454 | 3553 |
} |
3455 | 3554 |
|
3456 | 3555 |
void cpu_reset (CPUCRISState *env) |
3457 | 3556 |
{ |
3557 |
uint32_t vr; |
|
3558 |
|
|
3458 | 3559 |
if (qemu_loglevel_mask(CPU_LOG_RESET)) { |
3459 | 3560 |
qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); |
3460 | 3561 |
log_cpu_state(env, 0); |
3461 | 3562 |
} |
3462 | 3563 |
|
3564 |
vr = env->pregs[PR_VR]; |
|
3463 | 3565 |
memset(env, 0, offsetof(CPUCRISState, breakpoints)); |
3566 |
env->pregs[PR_VR] = vr; |
|
3464 | 3567 |
tlb_flush(env, 1); |
3465 | 3568 |
|
3466 |
env->pregs[PR_VR] = 32; |
|
3467 | 3569 |
#if defined(CONFIG_USER_ONLY) |
3468 | 3570 |
/* start in user mode with interrupts enabled. */ |
3469 |
env->pregs[PR_CCS] |= U_FLAG | I_FLAG; |
|
3571 |
env->pregs[PR_CCS] |= U_FLAG | I_FLAG | P_FLAG;
|
|
3470 | 3572 |
#else |
3471 | 3573 |
cris_mmu_init(env); |
3472 | 3574 |
env->pregs[PR_CCS] = 0; |
Also available in: Unified diff