Changeset View
Changeset View
Standalone View
Standalone View
head/sys/powerpc/powerpc/exec_machdep.c
Show First 20 Lines • Show All 1,015 Lines • ▼ Show 20 Lines | cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg, | ||||
} | } | ||||
td->td_pcb->pcb_flags = 0; | td->td_pcb->pcb_flags = 0; | ||||
td->td_retval[0] = (register_t)entry; | td->td_retval[0] = (register_t)entry; | ||||
td->td_retval[1] = 0; | td->td_retval[1] = 0; | ||||
} | } | ||||
static int | |||||
emulate_mfspr(int spr, int reg, struct trapframe *frame){ | |||||
struct thread *td; | |||||
td = curthread; | |||||
if (spr == SPR_DSCR) { | |||||
// If DSCR was never set, get the default DSCR | |||||
if ((td->td_pcb->pcb_flags & PCB_CDSCR) == 0) | |||||
td->td_pcb->pcb_dscr = mfspr(SPR_DSCR); | |||||
frame->fixreg[reg] = td->td_pcb->pcb_dscr; | |||||
frame->srr0 += 4; | |||||
return 0; | |||||
} else | |||||
return SIGILL; | |||||
} | |||||
static int | |||||
emulate_mtspr(int spr, int reg, struct trapframe *frame){ | |||||
struct thread *td; | |||||
td = curthread; | |||||
if (spr == SPR_DSCR) { | |||||
td->td_pcb->pcb_flags |= PCB_CDSCR; | |||||
td->td_pcb->pcb_dscr = frame->fixreg[reg]; | |||||
frame->srr0 += 4; | |||||
return 0; | |||||
} else | |||||
return SIGILL; | |||||
} | |||||
#define XFX 0xFC0007FF | |||||
int | int | ||||
ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb) | ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb) | ||||
{ | { | ||||
uint32_t instr; | uint32_t instr; | ||||
int reg, sig; | int reg, sig; | ||||
int rs, spr; | |||||
instr = fuword32((void *)frame->srr0); | instr = fuword32((void *)frame->srr0); | ||||
sig = SIGILL; | sig = SIGILL; | ||||
if ((instr & 0xfc1fffff) == 0x7c1f42a6) { /* mfpvr */ | if ((instr & 0xfc1fffff) == 0x7c1f42a6) { /* mfpvr */ | ||||
reg = (instr & ~0xfc1fffff) >> 21; | reg = (instr & ~0xfc1fffff) >> 21; | ||||
frame->fixreg[reg] = mfpvr(); | frame->fixreg[reg] = mfpvr(); | ||||
frame->srr0 += 4; | frame->srr0 += 4; | ||||
return (0); | return (0); | ||||
} | } else if ((instr & XFX) == 0x7c0002a6) { /* mfspr */ | ||||
rs = (instr & 0x3e00000) >> 21; | |||||
if ((instr & 0xfc000ffe) == 0x7c0004ac) { /* various sync */ | spr = (instr & 0x1ff800) >> 16; | ||||
return emulate_mfspr(spr, rs, frame); | |||||
} else if ((instr & XFX) == 0x7c0003a6) { /* mtspr */ | |||||
rs = (instr & 0x3e00000) >> 21; | |||||
spr = (instr & 0x1ff800) >> 16; | |||||
return emulate_mtspr(spr, rs, frame); | |||||
} else if ((instr & 0xfc000ffe) == 0x7c0004ac) { /* various sync */ | |||||
powerpc_sync(); /* Do a heavy-weight sync */ | powerpc_sync(); /* Do a heavy-weight sync */ | ||||
frame->srr0 += 4; | frame->srr0 += 4; | ||||
return (0); | return (0); | ||||
} | } | ||||
#ifdef FPU_EMU | #ifdef FPU_EMU | ||||
if (!(pcb->pcb_flags & PCB_FPREGS)) { | if (!(pcb->pcb_flags & PCB_FPREGS)) { | ||||
bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu)); | bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu)); | ||||
pcb->pcb_flags |= PCB_FPREGS; | pcb->pcb_flags |= PCB_FPREGS; | ||||
} | } | ||||
sig = fpu_emulate(frame, &pcb->pcb_fpu); | sig = fpu_emulate(frame, &pcb->pcb_fpu); | ||||
#endif | #endif | ||||
return (sig); | return (sig); | ||||
} | } | ||||