diff options
-rw-r--r-- | sparc-dis.c | 4 | ||||
-rw-r--r-- | target-sparc/cpu.h | 1 | ||||
-rw-r--r-- | target-sparc/op.c | 24 | ||||
-rw-r--r-- | target-sparc/translate.c | 47 |
4 files changed, 72 insertions, 4 deletions
diff --git a/sparc-dis.c b/sparc-dis.c index 597dc8a703..2be874ac94 100644 --- a/sparc-dis.c +++ b/sparc-dis.c @@ -2887,7 +2887,9 @@ print_insn_sparc (memaddr, info) { const char *name; - if (info->mach == bfd_mach_sparc_v9) + if ((info->mach == bfd_mach_sparc_v8plusa) || + ((info->mach >= bfd_mach_sparc_v9) && + (info->mach <= bfd_mach_sparc_v9b))) name = sparc_decode_asi_v9 (X_ASI (insn)); else name = sparc_decode_asi_v8 (X_ASI (insn)); diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index d0bcd40674..8cbf0b2e30 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -210,6 +210,7 @@ typedef struct CPUSPARCState { uint64_t version; uint64_t fprs; uint64_t tick_cmpr, stick_cmpr; + uint64_t gsr; #endif #if !defined(TARGET_SPARC64) && !defined(reg_T2) target_ulong t2; diff --git a/target-sparc/op.c b/target-sparc/op.c index f6d417f475..7ea209ea86 100644 --- a/target-sparc/op.c +++ b/target-sparc/op.c @@ -1514,6 +1514,9 @@ void OPPROTO op_saved(void) env->cansave++; if (env->otherwin == 0) env->canrestore--; + else + env->otherwin--; + FORCE_RET(); } void OPPROTO op_restored(void) @@ -1525,6 +1528,7 @@ void OPPROTO op_restored(void) env->cansave--; else env->otherwin--; + FORCE_RET(); } void OPPROTO op_popc(void) @@ -1571,3 +1575,23 @@ void OPPROTO op_st_asi() helper_st_asi(PARAM1, PARAM2, PARAM3); } +#ifdef TARGET_SPARC64 +void OPPROTO op_alignaddr() +{ + uint64_t tmp; + + tmp = T0 + T1; + env->gsr &= ~7ULL; + env->gsr |= tmp & 7ULL; + T0 = tmp & ~7ULL; +} + +void OPPROTO op_faligndata() +{ + uint64_t tmp; + + tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8); + tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8); + (*((uint64_t *)&DT0)) = tmp; +} +#endif diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 26c81454a1..4a8ad7061b 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -364,6 +364,9 @@ GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf); case 0x80: /* Primary address space */ \ gen_op_##width##_raw(); \ break; \ + case 0x82: /* Primary address space, non-faulting load */ \ + gen_op_##width##_raw(); \ + break; \ default: \ break; \ } \ @@ -1151,6 +1154,12 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs)); gen_movl_T0_reg(rd); break; + case 0x13: /* Graphics Status */ + if (gen_trap_ifnofpu(dc)) + goto jmp_insn; + gen_op_movtl_T0_env(offsetof(CPUSPARCState, gsr)); + gen_movl_T0_reg(rd); + break; case 0x17: /* Tick compare */ gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr)); gen_movl_T0_reg(rd); @@ -1166,7 +1175,6 @@ static void disas_sparc_insn(DisasContext * dc) case 0x10: /* Performance Control */ case 0x11: /* Performance Instrumentation Counter */ case 0x12: /* Dispatch Control */ - case 0x13: /* Graphics Status */ case 0x14: /* Softint set, WO */ case 0x15: /* Softint clear, WO */ case 0x16: /* Softint write */ @@ -1870,6 +1878,11 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_sir(); #endif break; + case 0x13: /* Graphics Status */ + if (gen_trap_ifnofpu(dc)) + goto jmp_insn; + gen_op_movtl_env_T0(offsetof(CPUSPARCState, gsr)); + break; case 0x17: /* Tick compare */ #if !defined(CONFIG_USER_ONLY) if (!supervisor(dc)) @@ -1895,7 +1908,6 @@ static void disas_sparc_insn(DisasContext * dc) case 0x10: /* Performance Control */ case 0x11: /* Performance Instrumentation Counter */ case 0x12: /* Dispatch Control */ - case 0x13: /* Graphics Status */ case 0x14: /* Softint set */ case 0x15: /* Softint clear */ case 0x16: /* Softint write */ @@ -2077,7 +2089,36 @@ static void disas_sparc_insn(DisasContext * dc) } case 0x36: /* UltraSparc shutdown, VIS */ { - // XXX + int opf = GET_FIELD_SP(insn, 5, 13); + rs1 = GET_FIELD(insn, 13, 17); + rs2 = GET_FIELD(insn, 27, 31); + + switch (opf) { + case 0x018: /* VIS I alignaddr */ + if (gen_trap_ifnofpu(dc)) + goto jmp_insn; + gen_movl_reg_T0(rs1); + gen_movl_reg_T1(rs2); + gen_op_alignaddr(); + gen_movl_T0_reg(rd); + break; + case 0x01a: /* VIS I alignaddrl */ + if (gen_trap_ifnofpu(dc)) + goto jmp_insn; + // XXX + break; + case 0x048: /* VIS I faligndata */ + if (gen_trap_ifnofpu(dc)) + goto jmp_insn; + gen_op_load_fpr_DT0(rs1); + gen_op_load_fpr_DT1(rs2); + gen_op_faligndata(); + gen_op_store_DT0_fpr(rd); + break; + default: + goto illegal_insn; + } + break; } #endif default: |