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>
master
Anthony Liguori 2013-11-21 07:08:47 -08:00
commit ffb62da7a2
8 changed files with 119 additions and 107 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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