mirror of https://gitee.com/openkylin/qemu.git
Merge remote-tracking branch 'jliu/or32' into staging
# By Sebastian Macke # Via Jia Liu * jliu/or32: target-openrisc: Correct carry flag check of l.addc and l.addic test cases target-openrisc: Correct memory bounds checking for the tlb buffers openrisc-timer: Reduce overhead, Separate clock update functions target-openrisc: Correct wrong epcr register in interrupt handler target-openrisc: Remove executable flag for every page target-openrisc: Remove unnecessary code generated by jump instructions target-openrisc: Speed up move instruction Message-id: 1384958318-9145-1-git-send-email-proljc@gmail.com Signed-off-by: Anthony Liguori <aliguori@amazon.com>
This commit is contained in:
commit
ffb62da7a2
|
@ -30,19 +30,28 @@ static int is_counting;
|
|||
|
||||
void cpu_openrisc_count_update(OpenRISCCPU *cpu)
|
||||
{
|
||||
uint64_t now, next;
|
||||
uint32_t wait;
|
||||
uint64_t now;
|
||||
|
||||
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
if (!is_counting) {
|
||||
timer_del(cpu->env.timer);
|
||||
last_clk = now;
|
||||
return;
|
||||
}
|
||||
|
||||
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
|
||||
get_ticks_per_sec());
|
||||
last_clk = now;
|
||||
}
|
||||
|
||||
void cpu_openrisc_timer_update(OpenRISCCPU *cpu)
|
||||
{
|
||||
uint32_t wait;
|
||||
uint64_t now, next;
|
||||
|
||||
if (!is_counting) {
|
||||
return;
|
||||
}
|
||||
|
||||
cpu_openrisc_count_update(cpu);
|
||||
now = last_clk;
|
||||
|
||||
if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
|
||||
wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
|
||||
|
@ -50,7 +59,6 @@ void cpu_openrisc_count_update(OpenRISCCPU *cpu)
|
|||
} else {
|
||||
wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
|
||||
}
|
||||
|
||||
next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
|
||||
timer_mod(cpu->env.timer, next);
|
||||
}
|
||||
|
@ -63,8 +71,9 @@ void cpu_openrisc_count_start(OpenRISCCPU *cpu)
|
|||
|
||||
void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
|
||||
{
|
||||
is_counting = 0;
|
||||
timer_del(cpu->env.timer);
|
||||
cpu_openrisc_count_update(cpu);
|
||||
is_counting = 0;
|
||||
}
|
||||
|
||||
static void openrisc_timer_cb(void *opaque)
|
||||
|
@ -84,15 +93,15 @@ static void openrisc_timer_cb(void *opaque)
|
|||
break;
|
||||
case TIMER_INTR:
|
||||
cpu->env.ttcr = 0;
|
||||
cpu_openrisc_count_start(cpu);
|
||||
break;
|
||||
case TIMER_SHOT:
|
||||
cpu_openrisc_count_stop(cpu);
|
||||
break;
|
||||
case TIMER_CONT:
|
||||
cpu_openrisc_count_start(cpu);
|
||||
break;
|
||||
}
|
||||
|
||||
cpu_openrisc_timer_update(cpu);
|
||||
}
|
||||
|
||||
void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
|
||||
|
|
|
@ -373,6 +373,7 @@ void cpu_openrisc_pic_init(OpenRISCCPU *cpu);
|
|||
/* hw/openrisc_timer.c */
|
||||
void cpu_openrisc_clock_init(OpenRISCCPU *cpu);
|
||||
void cpu_openrisc_count_update(OpenRISCCPU *cpu);
|
||||
void cpu_openrisc_timer_update(OpenRISCCPU *cpu);
|
||||
void cpu_openrisc_count_start(OpenRISCCPU *cpu);
|
||||
void cpu_openrisc_count_stop(OpenRISCCPU *cpu);
|
||||
|
||||
|
|
|
@ -30,26 +30,15 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
|
|||
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
|
||||
CPUOpenRISCState *env = &cpu->env;
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (env->flags & D_FLAG) { /* Delay Slot insn */
|
||||
|
||||
env->epcr = env->pc;
|
||||
if (env->flags & D_FLAG) {
|
||||
env->flags &= ~D_FLAG;
|
||||
env->sr |= SR_DSX;
|
||||
if (env->exception_index == EXCP_TICK ||
|
||||
env->exception_index == EXCP_INT ||
|
||||
env->exception_index == EXCP_SYSCALL ||
|
||||
env->exception_index == EXCP_FPE) {
|
||||
env->epcr = env->jmp_pc;
|
||||
} else {
|
||||
env->epcr = env->pc - 4;
|
||||
}
|
||||
} else {
|
||||
if (env->exception_index == EXCP_TICK ||
|
||||
env->exception_index == EXCP_INT ||
|
||||
env->exception_index == EXCP_SYSCALL ||
|
||||
env->exception_index == EXCP_FPE) {
|
||||
env->epcr = env->npc;
|
||||
} else {
|
||||
env->epcr = env->pc;
|
||||
}
|
||||
env->epcr -= 4;
|
||||
}
|
||||
if (env->exception_index == EXCP_SYSCALL) {
|
||||
env->epcr += 4;
|
||||
}
|
||||
|
||||
/* For machine-state changed between user-mode and supervisor mode,
|
||||
|
|
|
@ -32,7 +32,7 @@ int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu,
|
|||
int *prot, target_ulong address, int rw)
|
||||
{
|
||||
*physical = address;
|
||||
*prot = PAGE_READ | PAGE_WRITE;
|
||||
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
return TLBRET_MATCH;
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
|
|||
|
||||
if (ret == TLBRET_MATCH) {
|
||||
tlb_set_page(env, address & TARGET_PAGE_MASK,
|
||||
physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
|
||||
physical & TARGET_PAGE_MASK, prot,
|
||||
mmu_idx, TARGET_PAGE_SIZE);
|
||||
ret = 0;
|
||||
} else if (ret < 0) {
|
||||
|
|
|
@ -81,7 +81,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
|||
case TO_SPR(0, 64): /* ESR */
|
||||
env->esr = rb;
|
||||
break;
|
||||
case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
|
||||
case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
|
||||
idx = spr - TO_SPR(1, 512);
|
||||
if (!(rb & 1)) {
|
||||
tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
|
||||
|
@ -89,7 +89,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
|||
env->tlb->dtlb[0][idx].mr = rb;
|
||||
break;
|
||||
|
||||
case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
|
||||
case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */
|
||||
idx = spr - TO_SPR(1, 640);
|
||||
env->tlb->dtlb[0][idx].tr = rb;
|
||||
break;
|
||||
|
@ -100,7 +100,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
|||
case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
|
||||
case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
|
||||
break;
|
||||
case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */
|
||||
case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */
|
||||
idx = spr - TO_SPR(2, 512);
|
||||
if (!(rb & 1)) {
|
||||
tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
|
||||
|
@ -108,7 +108,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
|||
env->tlb->itlb[0][idx].mr = rb;
|
||||
break;
|
||||
|
||||
case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
|
||||
case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */
|
||||
idx = spr - TO_SPR(2, 640);
|
||||
env->tlb->itlb[0][idx].tr = rb;
|
||||
break;
|
||||
|
@ -127,33 +127,31 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
|||
break;
|
||||
case TO_SPR(10, 0): /* TTMR */
|
||||
{
|
||||
if ((env->ttmr & TTMR_M) ^ (rb & TTMR_M)) {
|
||||
switch (rb & TTMR_M) {
|
||||
case TIMER_NONE:
|
||||
cpu_openrisc_count_stop(cpu);
|
||||
break;
|
||||
case TIMER_INTR:
|
||||
case TIMER_SHOT:
|
||||
case TIMER_CONT:
|
||||
cpu_openrisc_count_start(cpu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int ip = env->ttmr & TTMR_IP;
|
||||
|
||||
if (rb & TTMR_IP) { /* Keep IP bit. */
|
||||
env->ttmr = (rb & ~TTMR_IP) + ip;
|
||||
env->ttmr = (rb & ~TTMR_IP) | ip;
|
||||
} else { /* Clear IP bit. */
|
||||
env->ttmr = rb & ~TTMR_IP;
|
||||
cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
|
||||
}
|
||||
|
||||
cpu_openrisc_count_update(cpu);
|
||||
|
||||
switch (env->ttmr & TTMR_M) {
|
||||
case TIMER_NONE:
|
||||
cpu_openrisc_count_stop(cpu);
|
||||
break;
|
||||
case TIMER_INTR:
|
||||
cpu_openrisc_count_start(cpu);
|
||||
break;
|
||||
case TIMER_SHOT:
|
||||
cpu_openrisc_count_start(cpu);
|
||||
break;
|
||||
case TIMER_CONT:
|
||||
cpu_openrisc_count_start(cpu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cpu_openrisc_timer_update(cpu);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -162,7 +160,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
|||
if (env->ttmr & TIMER_NONE) {
|
||||
return;
|
||||
}
|
||||
cpu_openrisc_count_start(cpu);
|
||||
cpu_openrisc_timer_update(cpu);
|
||||
break;
|
||||
default:
|
||||
|
||||
|
@ -214,11 +212,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
|
|||
case TO_SPR(0, 64): /* ESR */
|
||||
return env->esr;
|
||||
|
||||
case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
|
||||
case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* DTLBW0MR 0-127 */
|
||||
idx = spr - TO_SPR(1, 512);
|
||||
return env->tlb->dtlb[0][idx].mr;
|
||||
|
||||
case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
|
||||
case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */
|
||||
idx = spr - TO_SPR(1, 640);
|
||||
return env->tlb->dtlb[0][idx].tr;
|
||||
|
||||
|
@ -230,11 +228,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
|
|||
case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
|
||||
break;
|
||||
|
||||
case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */
|
||||
case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* ITLBW0MR 0-127 */
|
||||
idx = spr - TO_SPR(2, 512);
|
||||
return env->tlb->itlb[0][idx].mr;
|
||||
|
||||
case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
|
||||
case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */
|
||||
idx = spr - TO_SPR(2, 640);
|
||||
return env->tlb->itlb[0][idx].tr;
|
||||
|
||||
|
|
|
@ -209,42 +209,49 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
|
|||
static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
|
||||
{
|
||||
target_ulong tmp_pc;
|
||||
int lab = gen_new_label();
|
||||
TCGv sr_f = tcg_temp_new();
|
||||
/* N26, 26bits imm */
|
||||
tmp_pc = sign_extend((imm<<2), 26) + dc->pc;
|
||||
tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
|
||||
|
||||
if (op0 == 0x00) { /* l.j */
|
||||
switch (op0) {
|
||||
case 0x00: /* l.j */
|
||||
tcg_gen_movi_tl(jmp_pc, tmp_pc);
|
||||
} else if (op0 == 0x01) { /* l.jal */
|
||||
break;
|
||||
case 0x01: /* l.jal */
|
||||
tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
|
||||
tcg_gen_movi_tl(jmp_pc, tmp_pc);
|
||||
} else if (op0 == 0x03) { /* l.bnf */
|
||||
tcg_gen_movi_tl(jmp_pc, dc->pc+8);
|
||||
tcg_gen_brcondi_i32(TCG_COND_EQ, sr_f, SR_F, lab);
|
||||
tcg_gen_movi_tl(jmp_pc, tmp_pc);
|
||||
gen_set_label(lab);
|
||||
} else if (op0 == 0x04) { /* l.bf */
|
||||
tcg_gen_movi_tl(jmp_pc, dc->pc+8);
|
||||
tcg_gen_brcondi_i32(TCG_COND_NE, sr_f, SR_F, lab);
|
||||
tcg_gen_movi_tl(jmp_pc, tmp_pc);
|
||||
gen_set_label(lab);
|
||||
} else if (op0 == 0x11) { /* l.jr */
|
||||
break;
|
||||
case 0x03: /* l.bnf */
|
||||
case 0x04: /* l.bf */
|
||||
{
|
||||
int lab = gen_new_label();
|
||||
TCGv sr_f = tcg_temp_new();
|
||||
tcg_gen_movi_tl(jmp_pc, dc->pc+8);
|
||||
tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
|
||||
tcg_gen_brcondi_i32(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE,
|
||||
sr_f, SR_F, lab);
|
||||
tcg_gen_movi_tl(jmp_pc, tmp_pc);
|
||||
gen_set_label(lab);
|
||||
tcg_temp_free(sr_f);
|
||||
}
|
||||
break;
|
||||
case 0x11: /* l.jr */
|
||||
tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
|
||||
} else if (op0 == 0x12) { /* l.jalr */
|
||||
break;
|
||||
case 0x12: /* l.jalr */
|
||||
tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
|
||||
tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
gen_illegal_exception(dc);
|
||||
break;
|
||||
}
|
||||
|
||||
tcg_temp_free(sr_f);
|
||||
dc->delayed_branch = 2;
|
||||
dc->tb_flags |= D_FLAG;
|
||||
gen_sync_flags(dc);
|
||||
}
|
||||
|
||||
|
||||
static void dec_calc(DisasContext *dc, uint32_t insn)
|
||||
{
|
||||
uint32_t op0, op1, op2;
|
||||
|
@ -904,29 +911,33 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
|
|||
case 0x27: /* l.addi */
|
||||
LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
|
||||
{
|
||||
int lab = gen_new_label();
|
||||
TCGv_i64 ta = tcg_temp_new_i64();
|
||||
TCGv_i64 td = tcg_temp_local_new_i64();
|
||||
TCGv_i32 res = tcg_temp_local_new_i32();
|
||||
TCGv_i32 sr_ove = tcg_temp_local_new_i32();
|
||||
tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
|
||||
tcg_gen_addi_i64(td, ta, sign_extend(I16, 16));
|
||||
tcg_gen_trunc_i64_i32(res, td);
|
||||
tcg_gen_shri_i64(td, td, 32);
|
||||
tcg_gen_andi_i64(td, td, 0x3);
|
||||
/* Jump to lab when no overflow. */
|
||||
tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
|
||||
tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
|
||||
tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
|
||||
tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
|
||||
tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
|
||||
gen_exception(dc, EXCP_RANGE);
|
||||
gen_set_label(lab);
|
||||
tcg_gen_mov_i32(cpu_R[rd], res);
|
||||
tcg_temp_free_i64(ta);
|
||||
tcg_temp_free_i64(td);
|
||||
tcg_temp_free_i32(res);
|
||||
tcg_temp_free_i32(sr_ove);
|
||||
if (I16 == 0) {
|
||||
tcg_gen_mov_tl(cpu_R[rd], cpu_R[ra]);
|
||||
} else {
|
||||
int lab = gen_new_label();
|
||||
TCGv_i64 ta = tcg_temp_new_i64();
|
||||
TCGv_i64 td = tcg_temp_local_new_i64();
|
||||
TCGv_i32 res = tcg_temp_local_new_i32();
|
||||
TCGv_i32 sr_ove = tcg_temp_local_new_i32();
|
||||
tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
|
||||
tcg_gen_addi_i64(td, ta, sign_extend(I16, 16));
|
||||
tcg_gen_trunc_i64_i32(res, td);
|
||||
tcg_gen_shri_i64(td, td, 32);
|
||||
tcg_gen_andi_i64(td, td, 0x3);
|
||||
/* Jump to lab when no overflow. */
|
||||
tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
|
||||
tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
|
||||
tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
|
||||
tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
|
||||
tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
|
||||
gen_exception(dc, EXCP_RANGE);
|
||||
gen_set_label(lab);
|
||||
tcg_gen_mov_i32(cpu_R[rd], res);
|
||||
tcg_temp_free_i64(ta);
|
||||
tcg_temp_free_i64(td);
|
||||
tcg_temp_free_i32(res);
|
||||
tcg_temp_free_i32(sr_ove);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -7,9 +7,10 @@ int main(void)
|
|||
|
||||
b = 0x01;
|
||||
c = 0xffffffff;
|
||||
result = 1;
|
||||
result = 0;
|
||||
__asm
|
||||
("l.addc %0, %1, %2\n\t"
|
||||
("l.add r1, r1, r0\n\t" /* clear carry */
|
||||
"l.addc %0, %1, %2\n\t"
|
||||
: "=r"(a)
|
||||
: "r"(b), "r"(c)
|
||||
);
|
||||
|
@ -22,7 +23,8 @@ int main(void)
|
|||
c = 0xffffffff;
|
||||
result = 0x80000001;
|
||||
__asm
|
||||
("l.addc %0, %1, %2\n\t"
|
||||
("l.add r1, r1, r0\n\t" /* clear carry */
|
||||
"l.addc %0, %1, %2\n\t"
|
||||
"l.movhi %2, 0x7fff\n\t"
|
||||
"l.ori %2, %2, 0xffff\n\t"
|
||||
"l.addc %0, %1, %2\n\t"
|
||||
|
|
|
@ -6,9 +6,10 @@ int main(void)
|
|||
int result;
|
||||
|
||||
a = 1;
|
||||
result = 0x1;
|
||||
result = 0x0;
|
||||
__asm
|
||||
("l.addic %0, %0, 0xffff\n\t"
|
||||
("l.add r1, r1, r0\n\t" /* clear carry */
|
||||
"l.addic %0, %0, 0xffff\n\t"
|
||||
: "+r"(a)
|
||||
);
|
||||
if (a != result) {
|
||||
|
@ -16,10 +17,11 @@ int main(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
a = 0x1;
|
||||
a = -1;
|
||||
result = 0x201;
|
||||
__asm
|
||||
("l.addic %0, %0, 0xffff\n\t"
|
||||
("l.add r1, r1, r0\n\t" /* clear carry */
|
||||
"l.addic %0, %0, 0x1\n\t"
|
||||
"l.ori %0, r0, 0x100\n\t"
|
||||
"l.addic %0, %0, 0x100\n\t"
|
||||
: "+r"(a)
|
||||
|
|
Loading…
Reference in New Issue