static sval decode_spr_ins(struct cpu_thread* thr, uval addr, uval32 ins) { struct thread_control_area *tca = get_tca(); uval id = thr->vregs->active_vsave; struct vexc_save_regs *vr = &thr->vregs->vexc_save[id]; sval ret = -1; uval opcode = extract_bits(ins, 0, 6); uval type = extract_bits(ins, 21, 10); uval spr_0_4 = extract_bits(ins, 16, 5); uval spr_5_9 = extract_bits(ins, 11, 5); uval gpr = extract_bits(ins, 6, 5); uval spr = (spr_0_4 << 5) | spr_5_9; /* mfmsr */ if (opcode == 31 && type == 83) { //hprintf("mfmsr r%ld at 0x%lx\n",gpr, addr); mtgpr(thr, gpr, thr->vregs->v_msr); tca->srr0 += sizeof(uval32); return 0; } /* mtmsrd */ if (opcode == 31 && (type == 178 || type == 146)) { uval64 val = mfgpr(thr, gpr); //hprintf("mtmsrd r%ld <- 0x%llx at 0x%lx\n", gpr, val, addr); uval64 chg_mask = ~0ULL; uval l = extract_bits(ins, 15, 1); if (type == 146) { // mtmsr , 32-bits chg_mask = 0xffffffff; } if (l == 1) { chg_mask = (MSR_EE | MSR_RI); } /* These are the only bits we can change here */ val = (val & chg_mask) | (thr->vregs->v_msr & ~chg_mask); set_v_msr(thr, val); val = thr->vregs->v_msr; val |= V_LPAR_MSR_ON; val &= ~V_LPAR_MSR_OFF; tca->srr1 = val; tca->srr0 += sizeof(uval32); return 0; } /* mfspr */ #define SET_GPR(label, src) \ case label: mtgpr(thr, gpr, src); break; if (opcode == 31 && type == 339) { ret = 0; switch (spr) { SET_GPR(SPRN_SRR0, vr->v_srr0); SET_GPR(SPRN_SRR1, vr->v_srr1); SET_GPR(SPRN_PVR, mfpvr()); SET_GPR(SPRN_PIR, mfpir()); case SPRN_DSISR: case SPRN_DAR: mtgpr(thr, gpr, 0); break; case SPRN_HID0: case SPRN_HID1: case SPRN_HID4: case SPRN_HID5: mtgpr(thr, gpr, 0xdeadbeeffeedfaceULL); break; default: ret = -1; break; } if (ret != -1) { tca->srr0 += sizeof(uval32); return ret; } } #define SET_VREG(label, field) \ case label: thr->vregs->field = mfgpr(thr, gpr); break; /* mtspr */ if (opcode == 31 && type == 467) { ret = 0; switch (spr) { SET_VREG(SPRN_SPRG0, v_sprg0); SET_VREG(SPRN_SPRG1, v_sprg1); SET_VREG(SPRN_SPRG2, v_sprg2); SET_VREG(SPRN_SPRG3, v_sprg3); case SPRN_DEC: partition_set_dec(thr, mfgpr(thr, gpr)); thr->vregs->v_dec = mfgpr(thr, gpr); break; case SPRN_SRR0: vr->v_srr0 = mfgpr(thr, gpr); break; case SPRN_SRR1: vr->v_srr1 = mfgpr(thr, gpr); break; case SPRN_DSISR: case SPRN_DAR: break; default: ret = -1; break; } if (ret != -1) { tca->srr0 += sizeof(uval32); return ret; } } /* rfid */ if (opcode == 19 && type == 18) { uval val = vr->v_srr1; set_v_msr(thr, val); val |= V_LPAR_MSR_ON; val &= ~V_LPAR_MSR_OFF; tca->srr1 = val; tca->srr0 = vr->v_srr0; hprintf("rfid: %lx -> %lx\n",addr, vr->v_srr0); return 0; } if (ret == -1) { hprintf("Decode instruction: %ld %ld %ld %ld\n", opcode, type, spr, gpr); } return ret; }
kern_return_t DNBArchImplI386::GetGPRState(bool force) { if (force || m_state.GetError(e_regSetGPR, Read)) { #if DEBUG_GPR_VALUES SET_GPR(eax); SET_GPR(ebx); SET_GPR(ecx); SET_GPR(edx); SET_GPR(edi); SET_GPR(esi); SET_GPR(ebp); SET_GPR(esp); SET_GPR(ss); SET_GPR(eflags); SET_GPR(eip); SET_GPR(cs); SET_GPR(ds); SET_GPR(es); SET_GPR(fs); SET_GPR(gs); m_state.SetError(e_regSetGPR, Read, 0); #else mach_msg_type_number_t count = e_regSetWordSizeGPR; m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->ThreadID(), x86_THREAD_STATE32, (thread_state_t)&m_state.context.gpr, &count)); #endif } return m_state.GetError(e_regSetGPR, Read); }