Gross macro abuse. Get rid of gpreg_t, vaddr_t, REG_TO_VA and
VA_TO_REG. Who ever wrote this apparently did enjoy the C Puzzle Book. ISBN 0201604612, a little old but still fun reading for the next blackout ;) Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
@@ -196,7 +196,7 @@ static int isBranchInstr(mips_instruction * i)
|
|||||||
static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
|
static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
|
||||||
{
|
{
|
||||||
mips_instruction ir;
|
mips_instruction ir;
|
||||||
vaddr_t emulpc, contpc;
|
void * emulpc, *contpc;
|
||||||
unsigned int cond;
|
unsigned int cond;
|
||||||
|
|
||||||
if (get_user(ir, (mips_instruction *) xcp->cp0_epc)) {
|
if (get_user(ir, (mips_instruction *) xcp->cp0_epc)) {
|
||||||
@@ -221,12 +221,12 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
|
|||||||
* Linux MIPS branch emulator operates on context, updating the
|
* Linux MIPS branch emulator operates on context, updating the
|
||||||
* cp0_epc.
|
* cp0_epc.
|
||||||
*/
|
*/
|
||||||
emulpc = REG_TO_VA(xcp->cp0_epc + 4); /* Snapshot emulation target */
|
emulpc = (void *) (xcp->cp0_epc + 4); /* Snapshot emulation target */
|
||||||
|
|
||||||
if (__compute_return_epc(xcp)) {
|
if (__compute_return_epc(xcp)) {
|
||||||
#ifdef CP1DBG
|
#ifdef CP1DBG
|
||||||
printk("failed to emulate branch at %p\n",
|
printk("failed to emulate branch at %p\n",
|
||||||
REG_TO_VA(xcp->cp0_epc));
|
(void *) (xcp->cp0_epc));
|
||||||
#endif
|
#endif
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
}
|
}
|
||||||
@@ -235,13 +235,12 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
|
|||||||
return SIGBUS;
|
return SIGBUS;
|
||||||
}
|
}
|
||||||
/* __compute_return_epc() will have updated cp0_epc */
|
/* __compute_return_epc() will have updated cp0_epc */
|
||||||
contpc = REG_TO_VA xcp->cp0_epc;
|
contpc = (void *) xcp->cp0_epc;
|
||||||
/* In order not to confuse ptrace() et al, tweak context */
|
/* In order not to confuse ptrace() et al, tweak context */
|
||||||
xcp->cp0_epc = VA_TO_REG emulpc - 4;
|
xcp->cp0_epc = (unsigned long) emulpc - 4;
|
||||||
}
|
} else {
|
||||||
else {
|
emulpc = (void *) xcp->cp0_epc;
|
||||||
emulpc = REG_TO_VA xcp->cp0_epc;
|
contpc = (void *) (xcp->cp0_epc + 4);
|
||||||
contpc = REG_TO_VA(xcp->cp0_epc + 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emul:
|
emul:
|
||||||
@@ -249,7 +248,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
|
|||||||
switch (MIPSInst_OPCODE(ir)) {
|
switch (MIPSInst_OPCODE(ir)) {
|
||||||
#ifndef SINGLE_ONLY_FPU
|
#ifndef SINGLE_ONLY_FPU
|
||||||
case ldc1_op:{
|
case ldc1_op:{
|
||||||
u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
|
u64 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +
|
||||||
MIPSInst_SIMM(ir));
|
MIPSInst_SIMM(ir));
|
||||||
u64 val;
|
u64 val;
|
||||||
|
|
||||||
@@ -263,7 +262,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case sdc1_op:{
|
case sdc1_op:{
|
||||||
u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
|
u64 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +
|
||||||
MIPSInst_SIMM(ir));
|
MIPSInst_SIMM(ir));
|
||||||
u64 val;
|
u64 val;
|
||||||
|
|
||||||
@@ -278,7 +277,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
case lwc1_op:{
|
case lwc1_op:{
|
||||||
u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
|
u32 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +
|
||||||
MIPSInst_SIMM(ir));
|
MIPSInst_SIMM(ir));
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
@@ -298,7 +297,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case swc1_op:{
|
case swc1_op:{
|
||||||
u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
|
u32 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +
|
||||||
MIPSInst_SIMM(ir));
|
MIPSInst_SIMM(ir));
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
@@ -371,7 +370,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
|
|||||||
value = ctx->fcr31;
|
value = ctx->fcr31;
|
||||||
#ifdef CSRTRACE
|
#ifdef CSRTRACE
|
||||||
printk("%p gpr[%d]<-csr=%08x\n",
|
printk("%p gpr[%d]<-csr=%08x\n",
|
||||||
REG_TO_VA(xcp->cp0_epc),
|
(void *) (xcp->cp0_epc),
|
||||||
MIPSInst_RT(ir), value);
|
MIPSInst_RT(ir), value);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -398,7 +397,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
|
|||||||
if (MIPSInst_RD(ir) == FPCREG_CSR) {
|
if (MIPSInst_RD(ir) == FPCREG_CSR) {
|
||||||
#ifdef CSRTRACE
|
#ifdef CSRTRACE
|
||||||
printk("%p gpr[%d]->csr=%08x\n",
|
printk("%p gpr[%d]->csr=%08x\n",
|
||||||
REG_TO_VA(xcp->cp0_epc),
|
(void *) (xcp->cp0_epc),
|
||||||
MIPSInst_RT(ir), value);
|
MIPSInst_RT(ir), value);
|
||||||
#endif
|
#endif
|
||||||
ctx->fcr31 = value;
|
ctx->fcr31 = value;
|
||||||
@@ -445,12 +444,12 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
|
|||||||
* instruction
|
* instruction
|
||||||
*/
|
*/
|
||||||
xcp->cp0_epc += 4;
|
xcp->cp0_epc += 4;
|
||||||
contpc = REG_TO_VA
|
contpc = (void *)
|
||||||
(xcp->cp0_epc +
|
(xcp->cp0_epc +
|
||||||
(MIPSInst_SIMM(ir) << 2));
|
(MIPSInst_SIMM(ir) << 2));
|
||||||
|
|
||||||
if (get_user(ir, (mips_instruction *)
|
if (get_user(ir, (mips_instruction *)
|
||||||
REG_TO_VA xcp->cp0_epc)) {
|
(void *) xcp->cp0_epc)) {
|
||||||
fpuemuprivate.stats.errors++;
|
fpuemuprivate.stats.errors++;
|
||||||
return SIGBUS;
|
return SIGBUS;
|
||||||
}
|
}
|
||||||
@@ -480,7 +479,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
|
|||||||
* Single step the non-cp1
|
* Single step the non-cp1
|
||||||
* instruction in the dslot
|
* instruction in the dslot
|
||||||
*/
|
*/
|
||||||
return mips_dsemul(xcp, ir, VA_TO_REG contpc);
|
return mips_dsemul(xcp, ir, (unsigned long) contpc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* branch not taken */
|
/* branch not taken */
|
||||||
@@ -539,8 +538,9 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* we did it !! */
|
/* we did it !! */
|
||||||
xcp->cp0_epc = VA_TO_REG(contpc);
|
xcp->cp0_epc = (unsigned long) contpc;
|
||||||
xcp->cp0_cause &= ~CAUSEF_BD;
|
xcp->cp0_cause &= ~CAUSEF_BD;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -628,7 +628,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
|
|||||||
|
|
||||||
switch (MIPSInst_FUNC(ir)) {
|
switch (MIPSInst_FUNC(ir)) {
|
||||||
case lwxc1_op:
|
case lwxc1_op:
|
||||||
va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
|
va = (void *) (xcp->regs[MIPSInst_FR(ir)] +
|
||||||
xcp->regs[MIPSInst_FT(ir)]);
|
xcp->regs[MIPSInst_FT(ir)]);
|
||||||
|
|
||||||
fpuemuprivate.stats.loads++;
|
fpuemuprivate.stats.loads++;
|
||||||
@@ -648,7 +648,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case swxc1_op:
|
case swxc1_op:
|
||||||
va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
|
va = (void *) (xcp->regs[MIPSInst_FR(ir)] +
|
||||||
xcp->regs[MIPSInst_FT(ir)]);
|
xcp->regs[MIPSInst_FT(ir)]);
|
||||||
|
|
||||||
fpuemuprivate.stats.stores++;
|
fpuemuprivate.stats.stores++;
|
||||||
@@ -724,7 +724,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
|
|||||||
|
|
||||||
switch (MIPSInst_FUNC(ir)) {
|
switch (MIPSInst_FUNC(ir)) {
|
||||||
case ldxc1_op:
|
case ldxc1_op:
|
||||||
va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
|
va = (void *) (xcp->regs[MIPSInst_FR(ir)] +
|
||||||
xcp->regs[MIPSInst_FT(ir)]);
|
xcp->regs[MIPSInst_FT(ir)]);
|
||||||
|
|
||||||
fpuemuprivate.stats.loads++;
|
fpuemuprivate.stats.loads++;
|
||||||
@@ -736,7 +736,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case sdxc1_op:
|
case sdxc1_op:
|
||||||
va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
|
va = (void *) (xcp->regs[MIPSInst_FR(ir)] +
|
||||||
xcp->regs[MIPSInst_FT(ir)]);
|
xcp->regs[MIPSInst_FT(ir)]);
|
||||||
|
|
||||||
fpuemuprivate.stats.stores++;
|
fpuemuprivate.stats.stores++;
|
||||||
@@ -1282,7 +1282,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
|
|||||||
int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp,
|
int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp,
|
||||||
struct mips_fpu_soft_struct *ctx)
|
struct mips_fpu_soft_struct *ctx)
|
||||||
{
|
{
|
||||||
gpreg_t oldepc, prevepc;
|
unsigned long oldepc, prevepc;
|
||||||
mips_instruction insn;
|
mips_instruction insn;
|
||||||
int sig = 0;
|
int sig = 0;
|
||||||
|
|
||||||
|
@@ -49,10 +49,10 @@ struct emuframe {
|
|||||||
mips_instruction emul;
|
mips_instruction emul;
|
||||||
mips_instruction badinst;
|
mips_instruction badinst;
|
||||||
mips_instruction cookie;
|
mips_instruction cookie;
|
||||||
gpreg_t epc;
|
unsigned long epc;
|
||||||
};
|
};
|
||||||
|
|
||||||
int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc)
|
int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
|
||||||
{
|
{
|
||||||
extern asmlinkage void handle_dsemulret(void);
|
extern asmlinkage void handle_dsemulret(void);
|
||||||
mips_instruction *dsemul_insns;
|
mips_instruction *dsemul_insns;
|
||||||
@@ -88,7 +88,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Ensure that the two instructions are in the same cache line */
|
/* Ensure that the two instructions are in the same cache line */
|
||||||
dsemul_insns = (mips_instruction *) REG_TO_VA ((regs->regs[29] - sizeof(struct emuframe)) & ~0x7);
|
dsemul_insns = (mips_instruction *) ((regs->regs[29] - sizeof(struct emuframe)) & ~0x7);
|
||||||
fr = (struct emuframe *) dsemul_insns;
|
fr = (struct emuframe *) dsemul_insns;
|
||||||
|
|
||||||
/* Verify that the stack pointer is not competely insane */
|
/* Verify that the stack pointer is not competely insane */
|
||||||
@@ -105,7 +105,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc)
|
|||||||
return SIGBUS;
|
return SIGBUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
regs->cp0_epc = VA_TO_REG & fr->emul;
|
regs->cp0_epc = (unsigned long) &fr->emul;
|
||||||
|
|
||||||
flush_cache_sigtramp((unsigned long)&fr->badinst);
|
flush_cache_sigtramp((unsigned long)&fr->badinst);
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc)
|
|||||||
int do_dsemulret(struct pt_regs *xcp)
|
int do_dsemulret(struct pt_regs *xcp)
|
||||||
{
|
{
|
||||||
struct emuframe *fr;
|
struct emuframe *fr;
|
||||||
gpreg_t epc;
|
unsigned long epc;
|
||||||
u32 insn, cookie;
|
u32 insn, cookie;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
@@ -1,11 +1,5 @@
|
|||||||
typedef long gpreg_t;
|
extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc);
|
||||||
typedef void *vaddr_t;
|
extern int do_dsemulret(struct pt_regs *xcp);
|
||||||
|
|
||||||
#define REG_TO_VA (vaddr_t)
|
|
||||||
#define VA_TO_REG (gpreg_t)
|
|
||||||
|
|
||||||
int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc);
|
|
||||||
int do_dsemulret(struct pt_regs *xcp);
|
|
||||||
|
|
||||||
/* Instruction which will always cause an address error */
|
/* Instruction which will always cause an address error */
|
||||||
#define AdELOAD 0x8c000001 /* lw $0,1($0) */
|
#define AdELOAD 0x8c000001 /* lw $0,1($0) */
|
||||||
|
Reference in New Issue
Block a user