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)
|
void cpu_openrisc_count_update(OpenRISCCPU *cpu)
|
||||||
{
|
{
|
||||||
uint64_t now, next;
|
uint64_t now;
|
||||||
uint32_t wait;
|
|
||||||
|
|
||||||
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
|
||||||
if (!is_counting) {
|
if (!is_counting) {
|
||||||
timer_del(cpu->env.timer);
|
|
||||||
last_clk = now;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||||
cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
|
cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
|
||||||
get_ticks_per_sec());
|
get_ticks_per_sec());
|
||||||
last_clk = now;
|
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)) {
|
if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
|
||||||
wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
|
wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
|
||||||
|
@ -50,7 +59,6 @@ void cpu_openrisc_count_update(OpenRISCCPU *cpu)
|
||||||
} else {
|
} else {
|
||||||
wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
|
wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
|
||||||
}
|
}
|
||||||
|
|
||||||
next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
|
next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
|
||||||
timer_mod(cpu->env.timer, next);
|
timer_mod(cpu->env.timer, next);
|
||||||
}
|
}
|
||||||
|
@ -63,8 +71,9 @@ void cpu_openrisc_count_start(OpenRISCCPU *cpu)
|
||||||
|
|
||||||
void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
|
void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
|
||||||
{
|
{
|
||||||
is_counting = 0;
|
timer_del(cpu->env.timer);
|
||||||
cpu_openrisc_count_update(cpu);
|
cpu_openrisc_count_update(cpu);
|
||||||
|
is_counting = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void openrisc_timer_cb(void *opaque)
|
static void openrisc_timer_cb(void *opaque)
|
||||||
|
@ -84,15 +93,15 @@ static void openrisc_timer_cb(void *opaque)
|
||||||
break;
|
break;
|
||||||
case TIMER_INTR:
|
case TIMER_INTR:
|
||||||
cpu->env.ttcr = 0;
|
cpu->env.ttcr = 0;
|
||||||
cpu_openrisc_count_start(cpu);
|
|
||||||
break;
|
break;
|
||||||
case TIMER_SHOT:
|
case TIMER_SHOT:
|
||||||
cpu_openrisc_count_stop(cpu);
|
cpu_openrisc_count_stop(cpu);
|
||||||
break;
|
break;
|
||||||
case TIMER_CONT:
|
case TIMER_CONT:
|
||||||
cpu_openrisc_count_start(cpu);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpu_openrisc_timer_update(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
|
void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
|
||||||
|
|
|
@ -373,6 +373,7 @@ void cpu_openrisc_pic_init(OpenRISCCPU *cpu);
|
||||||
/* hw/openrisc_timer.c */
|
/* hw/openrisc_timer.c */
|
||||||
void cpu_openrisc_clock_init(OpenRISCCPU *cpu);
|
void cpu_openrisc_clock_init(OpenRISCCPU *cpu);
|
||||||
void cpu_openrisc_count_update(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_start(OpenRISCCPU *cpu);
|
||||||
void cpu_openrisc_count_stop(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);
|
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
|
||||||
CPUOpenRISCState *env = &cpu->env;
|
CPUOpenRISCState *env = &cpu->env;
|
||||||
#ifndef CONFIG_USER_ONLY
|
#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->flags &= ~D_FLAG;
|
||||||
env->sr |= SR_DSX;
|
env->sr |= SR_DSX;
|
||||||
if (env->exception_index == EXCP_TICK ||
|
env->epcr -= 4;
|
||||||
env->exception_index == EXCP_INT ||
|
}
|
||||||
env->exception_index == EXCP_SYSCALL ||
|
if (env->exception_index == EXCP_SYSCALL) {
|
||||||
env->exception_index == EXCP_FPE) {
|
env->epcr += 4;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For machine-state changed between user-mode and supervisor mode,
|
/* 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)
|
int *prot, target_ulong address, int rw)
|
||||||
{
|
{
|
||||||
*physical = address;
|
*physical = address;
|
||||||
*prot = PAGE_READ | PAGE_WRITE;
|
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||||
return TLBRET_MATCH;
|
return TLBRET_MATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
|
||||||
|
|
||||||
if (ret == TLBRET_MATCH) {
|
if (ret == TLBRET_MATCH) {
|
||||||
tlb_set_page(env, address & TARGET_PAGE_MASK,
|
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);
|
mmu_idx, TARGET_PAGE_SIZE);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else if (ret < 0) {
|
} else if (ret < 0) {
|
||||||
|
|
|
@ -81,7 +81,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
||||||
case TO_SPR(0, 64): /* ESR */
|
case TO_SPR(0, 64): /* ESR */
|
||||||
env->esr = rb;
|
env->esr = rb;
|
||||||
break;
|
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);
|
idx = spr - TO_SPR(1, 512);
|
||||||
if (!(rb & 1)) {
|
if (!(rb & 1)) {
|
||||||
tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
|
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;
|
env->tlb->dtlb[0][idx].mr = rb;
|
||||||
break;
|
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);
|
idx = spr - TO_SPR(1, 640);
|
||||||
env->tlb->dtlb[0][idx].tr = rb;
|
env->tlb->dtlb[0][idx].tr = rb;
|
||||||
break;
|
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, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
|
||||||
case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
|
case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
|
||||||
break;
|
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);
|
idx = spr - TO_SPR(2, 512);
|
||||||
if (!(rb & 1)) {
|
if (!(rb & 1)) {
|
||||||
tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
|
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;
|
env->tlb->itlb[0][idx].mr = rb;
|
||||||
break;
|
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);
|
idx = spr - TO_SPR(2, 640);
|
||||||
env->tlb->itlb[0][idx].tr = rb;
|
env->tlb->itlb[0][idx].tr = rb;
|
||||||
break;
|
break;
|
||||||
|
@ -127,33 +127,31 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
||||||
break;
|
break;
|
||||||
case TO_SPR(10, 0): /* TTMR */
|
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;
|
int ip = env->ttmr & TTMR_IP;
|
||||||
|
|
||||||
if (rb & TTMR_IP) { /* Keep IP bit. */
|
if (rb & TTMR_IP) { /* Keep IP bit. */
|
||||||
env->ttmr = (rb & ~TTMR_IP) + ip;
|
env->ttmr = (rb & ~TTMR_IP) | ip;
|
||||||
} else { /* Clear IP bit. */
|
} else { /* Clear IP bit. */
|
||||||
env->ttmr = rb & ~TTMR_IP;
|
env->ttmr = rb & ~TTMR_IP;
|
||||||
cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
|
cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_openrisc_count_update(cpu);
|
cpu_openrisc_timer_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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -162,7 +160,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
||||||
if (env->ttmr & TIMER_NONE) {
|
if (env->ttmr & TIMER_NONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cpu_openrisc_count_start(cpu);
|
cpu_openrisc_timer_update(cpu);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
||||||
|
@ -214,11 +212,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
|
||||||
case TO_SPR(0, 64): /* ESR */
|
case TO_SPR(0, 64): /* ESR */
|
||||||
return env->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);
|
idx = spr - TO_SPR(1, 512);
|
||||||
return env->tlb->dtlb[0][idx].mr;
|
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);
|
idx = spr - TO_SPR(1, 640);
|
||||||
return env->tlb->dtlb[0][idx].tr;
|
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 */
|
case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
|
||||||
break;
|
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);
|
idx = spr - TO_SPR(2, 512);
|
||||||
return env->tlb->itlb[0][idx].mr;
|
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);
|
idx = spr - TO_SPR(2, 640);
|
||||||
return env->tlb->itlb[0][idx].tr;
|
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)
|
static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
|
||||||
{
|
{
|
||||||
target_ulong tmp_pc;
|
target_ulong tmp_pc;
|
||||||
int lab = gen_new_label();
|
|
||||||
TCGv sr_f = tcg_temp_new();
|
|
||||||
/* N26, 26bits imm */
|
/* N26, 26bits imm */
|
||||||
tmp_pc = sign_extend((imm<<2), 26) + dc->pc;
|
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);
|
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(cpu_R[9], (dc->pc + 8));
|
||||||
tcg_gen_movi_tl(jmp_pc, tmp_pc);
|
tcg_gen_movi_tl(jmp_pc, tmp_pc);
|
||||||
} else if (op0 == 0x03) { /* l.bnf */
|
break;
|
||||||
tcg_gen_movi_tl(jmp_pc, dc->pc+8);
|
case 0x03: /* l.bnf */
|
||||||
tcg_gen_brcondi_i32(TCG_COND_EQ, sr_f, SR_F, lab);
|
case 0x04: /* l.bf */
|
||||||
tcg_gen_movi_tl(jmp_pc, tmp_pc);
|
{
|
||||||
gen_set_label(lab);
|
int lab = gen_new_label();
|
||||||
} else if (op0 == 0x04) { /* l.bf */
|
TCGv sr_f = tcg_temp_new();
|
||||||
tcg_gen_movi_tl(jmp_pc, dc->pc+8);
|
tcg_gen_movi_tl(jmp_pc, dc->pc+8);
|
||||||
tcg_gen_brcondi_i32(TCG_COND_NE, sr_f, SR_F, lab);
|
tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
|
||||||
tcg_gen_movi_tl(jmp_pc, tmp_pc);
|
tcg_gen_brcondi_i32(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE,
|
||||||
gen_set_label(lab);
|
sr_f, SR_F, lab);
|
||||||
} else if (op0 == 0x11) { /* l.jr */
|
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]);
|
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_movi_tl(cpu_R[9], (dc->pc + 8));
|
||||||
tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
|
tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
|
||||||
} else {
|
break;
|
||||||
|
default:
|
||||||
gen_illegal_exception(dc);
|
gen_illegal_exception(dc);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcg_temp_free(sr_f);
|
|
||||||
dc->delayed_branch = 2;
|
dc->delayed_branch = 2;
|
||||||
dc->tb_flags |= D_FLAG;
|
dc->tb_flags |= D_FLAG;
|
||||||
gen_sync_flags(dc);
|
gen_sync_flags(dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void dec_calc(DisasContext *dc, uint32_t insn)
|
static void dec_calc(DisasContext *dc, uint32_t insn)
|
||||||
{
|
{
|
||||||
uint32_t op0, op1, op2;
|
uint32_t op0, op1, op2;
|
||||||
|
@ -904,29 +911,33 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
|
||||||
case 0x27: /* l.addi */
|
case 0x27: /* l.addi */
|
||||||
LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
|
LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
|
||||||
{
|
{
|
||||||
int lab = gen_new_label();
|
if (I16 == 0) {
|
||||||
TCGv_i64 ta = tcg_temp_new_i64();
|
tcg_gen_mov_tl(cpu_R[rd], cpu_R[ra]);
|
||||||
TCGv_i64 td = tcg_temp_local_new_i64();
|
} else {
|
||||||
TCGv_i32 res = tcg_temp_local_new_i32();
|
int lab = gen_new_label();
|
||||||
TCGv_i32 sr_ove = tcg_temp_local_new_i32();
|
TCGv_i64 ta = tcg_temp_new_i64();
|
||||||
tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
|
TCGv_i64 td = tcg_temp_local_new_i64();
|
||||||
tcg_gen_addi_i64(td, ta, sign_extend(I16, 16));
|
TCGv_i32 res = tcg_temp_local_new_i32();
|
||||||
tcg_gen_trunc_i64_i32(res, td);
|
TCGv_i32 sr_ove = tcg_temp_local_new_i32();
|
||||||
tcg_gen_shri_i64(td, td, 32);
|
tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
|
||||||
tcg_gen_andi_i64(td, td, 0x3);
|
tcg_gen_addi_i64(td, ta, sign_extend(I16, 16));
|
||||||
/* Jump to lab when no overflow. */
|
tcg_gen_trunc_i64_i32(res, td);
|
||||||
tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
|
tcg_gen_shri_i64(td, td, 32);
|
||||||
tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
|
tcg_gen_andi_i64(td, td, 0x3);
|
||||||
tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
|
/* Jump to lab when no overflow. */
|
||||||
tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
|
tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
|
||||||
tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
|
tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
|
||||||
gen_exception(dc, EXCP_RANGE);
|
tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
|
||||||
gen_set_label(lab);
|
tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
|
||||||
tcg_gen_mov_i32(cpu_R[rd], res);
|
tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
|
||||||
tcg_temp_free_i64(ta);
|
gen_exception(dc, EXCP_RANGE);
|
||||||
tcg_temp_free_i64(td);
|
gen_set_label(lab);
|
||||||
tcg_temp_free_i32(res);
|
tcg_gen_mov_i32(cpu_R[rd], res);
|
||||||
tcg_temp_free_i32(sr_ove);
|
tcg_temp_free_i64(ta);
|
||||||
|
tcg_temp_free_i64(td);
|
||||||
|
tcg_temp_free_i32(res);
|
||||||
|
tcg_temp_free_i32(sr_ove);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,10 @@ int main(void)
|
||||||
|
|
||||||
b = 0x01;
|
b = 0x01;
|
||||||
c = 0xffffffff;
|
c = 0xffffffff;
|
||||||
result = 1;
|
result = 0;
|
||||||
__asm
|
__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"(a)
|
||||||
: "r"(b), "r"(c)
|
: "r"(b), "r"(c)
|
||||||
);
|
);
|
||||||
|
@ -22,7 +23,8 @@ int main(void)
|
||||||
c = 0xffffffff;
|
c = 0xffffffff;
|
||||||
result = 0x80000001;
|
result = 0x80000001;
|
||||||
__asm
|
__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.movhi %2, 0x7fff\n\t"
|
||||||
"l.ori %2, %2, 0xffff\n\t"
|
"l.ori %2, %2, 0xffff\n\t"
|
||||||
"l.addc %0, %1, %2\n\t"
|
"l.addc %0, %1, %2\n\t"
|
||||||
|
|
|
@ -6,9 +6,10 @@ int main(void)
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
a = 1;
|
a = 1;
|
||||||
result = 0x1;
|
result = 0x0;
|
||||||
__asm
|
__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)
|
: "+r"(a)
|
||||||
);
|
);
|
||||||
if (a != result) {
|
if (a != result) {
|
||||||
|
@ -16,10 +17,11 @@ int main(void)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
a = 0x1;
|
a = -1;
|
||||||
result = 0x201;
|
result = 0x201;
|
||||||
__asm
|
__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.ori %0, r0, 0x100\n\t"
|
||||||
"l.addic %0, %0, 0x100\n\t"
|
"l.addic %0, %0, 0x100\n\t"
|
||||||
: "+r"(a)
|
: "+r"(a)
|
||||||
|
|
Loading…
Reference in New Issue