diff options
| author | Ralf Baechle <ralf@linux-mips.org> | 2013-05-09 17:57:30 +0200 | 
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2013-05-09 17:57:30 +0200 | 
| commit | b22d1b6a91ca4260f869e349179ae53f18c664db (patch) | |
| tree | 6ac6c2bd202100727638f02ae5037ec78144e8d5 /arch/mips/math-emu/dsemul.c | |
| parent | 5e0e61dd2c89c673f89fb57dcd3cc746dc0c1706 (diff) | |
| parent | 0ab2b7d08ea7226dc72ff0f8c05f470566facf7c (diff) | |
| download | olio-linux-3.10-b22d1b6a91ca4260f869e349179ae53f18c664db.tar.xz olio-linux-3.10-b22d1b6a91ca4260f869e349179ae53f18c664db.zip  | |
Merge branch 'mti-next' of git://git.linux-mips.org/pub/scm/sjhill/linux-sjhill into mips-for-linux-next
Diffstat (limited to 'arch/mips/math-emu/dsemul.c')
| -rw-r--r-- | arch/mips/math-emu/dsemul.c | 30 | 
1 files changed, 24 insertions, 6 deletions
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c index 384a3b0091e..7ea622ab8da 100644 --- a/arch/mips/math-emu/dsemul.c +++ b/arch/mips/math-emu/dsemul.c @@ -55,7 +55,9 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)  	struct emuframe __user *fr;  	int err; -	if (ir == 0) {		/* a nop is easy */ +	if ((get_isa16_mode(regs->cp0_epc) && ((ir >> 16) == MM_NOP16)) || +		(ir == 0)) { +		/* NOP is easy */  		regs->cp0_epc = cpc;  		regs->cp0_cause &= ~CAUSEF_BD;  		return 0; @@ -91,8 +93,16 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)  	if (unlikely(!access_ok(VERIFY_WRITE, fr, sizeof(struct emuframe))))  		return SIGBUS; -	err = __put_user(ir, &fr->emul); -	err |= __put_user((mips_instruction)BREAK_MATH, &fr->badinst); +	if (get_isa16_mode(regs->cp0_epc)) { +		err = __put_user(ir >> 16, (u16 __user *)(&fr->emul)); +		err |= __put_user(ir & 0xffff, (u16 __user *)((long)(&fr->emul) + 2)); +		err |= __put_user(BREAK_MATH >> 16, (u16 __user *)(&fr->badinst)); +		err |= __put_user(BREAK_MATH & 0xffff, (u16 __user *)((long)(&fr->badinst) + 2)); +	} else { +		err = __put_user(ir, &fr->emul); +		err |= __put_user((mips_instruction)BREAK_MATH, &fr->badinst); +	} +  	err |= __put_user((mips_instruction)BD_COOKIE, &fr->cookie);  	err |= __put_user(cpc, &fr->epc); @@ -101,7 +111,8 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)  		return SIGBUS;  	} -	regs->cp0_epc = (unsigned long) &fr->emul; +	regs->cp0_epc = ((unsigned long) &fr->emul) | +		get_isa16_mode(regs->cp0_epc);  	flush_cache_sigtramp((unsigned long)&fr->badinst); @@ -114,9 +125,10 @@ int do_dsemulret(struct pt_regs *xcp)  	unsigned long epc;  	u32 insn, cookie;  	int err = 0; +	u16 instr[2];  	fr = (struct emuframe __user *) -		(xcp->cp0_epc - sizeof(mips_instruction)); +		(msk_isa16_mode(xcp->cp0_epc) - sizeof(mips_instruction));  	/*  	 * If we can't even access the area, something is very wrong, but we'll @@ -131,7 +143,13 @@ int do_dsemulret(struct pt_regs *xcp)  	 *  - Is the instruction pointed to by the EPC an BREAK_MATH?  	 *  - Is the following memory word the BD_COOKIE?  	 */ -	err = __get_user(insn, &fr->badinst); +	if (get_isa16_mode(xcp->cp0_epc)) { +		err = __get_user(instr[0], (u16 __user *)(&fr->badinst)); +		err |= __get_user(instr[1], (u16 __user *)((long)(&fr->badinst) + 2)); +		insn = (instr[0] << 16) | instr[1]; +	} else { +		err = __get_user(insn, &fr->badinst); +	}  	err |= __get_user(cookie, &fr->cookie);  	if (unlikely(err || (insn != BREAK_MATH) || (cookie != BD_COOKIE))) {  |