mirror of
https://github.com/opnsense/src.git
synced 2026-06-12 18:20:49 -04:00
Fix some bugs that would prevent %fsr to be set correctly, and add
support for fcmp and fcmpe instructions with a condition code specification other than %fcc0. This (primarily the first part) seems to fix a lot of problems that people were seeing, e.g. perl and gawk failures. Reported and analyzed by: wollman
This commit is contained in:
parent
61de6bb54c
commit
d095bc220d
4 changed files with 25 additions and 8 deletions
|
|
@ -187,7 +187,7 @@ __fpu_exception(struct utrapframe *uf)
|
|||
goto fatal;
|
||||
}
|
||||
|
||||
fe.fe_fsr = fsr;
|
||||
fe.fe_fsr = fsr & ~FSR_FTT_MASK;
|
||||
insn = *(u_int32_t *)uf->uf_pc;
|
||||
if (IF_OP(insn) != IOP_MISC || (IF_F3_OP3(insn) != INS2_FPop1 &&
|
||||
IF_F3_OP3(insn) != INS2_FPop2))
|
||||
|
|
@ -268,7 +268,8 @@ __fpu_ccmov(struct fpemu *fe, int type, int rd, int rs1, int rs2,
|
|||
static int
|
||||
__fpu_cmpck(struct fpemu *fe)
|
||||
{
|
||||
int cx, fsr;
|
||||
u_long fsr;
|
||||
int cx;
|
||||
|
||||
/*
|
||||
* The only possible exception here is NV; catch it
|
||||
|
|
@ -391,12 +392,12 @@ __fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn, u_long ts
|
|||
case FOP(INS2_FPop2, INSFP2_FCMP):
|
||||
__fpu_explode(fe, &fe->fe_f1, type, rs1);
|
||||
__fpu_explode(fe, &fe->fe_f2, type, rs2);
|
||||
__fpu_compare(fe, 0);
|
||||
__fpu_compare(fe, 0, IF_F3_CC(insn));
|
||||
return (__fpu_cmpck(fe));
|
||||
case FOP(INS2_FPop2, INSFP2_FCMPE):
|
||||
__fpu_explode(fe, &fe->fe_f1, type, rs1);
|
||||
__fpu_explode(fe, &fe->fe_f2, type, rs2);
|
||||
__fpu_compare(fe, 1);
|
||||
__fpu_compare(fe, 1, IF_F3_CC(insn));
|
||||
return (__fpu_cmpck(fe));
|
||||
case FOP(INS2_FPop1, INSFP1_FMOV): /* these should all be pretty obvious */
|
||||
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,21 @@
|
|||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
|
||||
static u_long fcc_nmask[] = {
|
||||
~FSR_FCC0_MASK,
|
||||
~FSR_FCC1_MASK,
|
||||
~FSR_FCC2_MASK,
|
||||
~FSR_FCC3_MASK
|
||||
};
|
||||
|
||||
/* XXX: we don't use the FSR_FCCx macros here; it's much easier this way. */
|
||||
static int fcc_shift[] = {
|
||||
FSR_FCC0_SHIFT,
|
||||
FSR_FCC1_SHIFT,
|
||||
FSR_FCC2_SHIFT,
|
||||
FSR_FCC3_SHIFT
|
||||
};
|
||||
|
||||
/*
|
||||
* Perform a compare instruction (with or without unordered exception).
|
||||
* This updates the fcc field in the fsr.
|
||||
|
|
@ -78,7 +93,7 @@
|
|||
* complete).
|
||||
*/
|
||||
void
|
||||
__fpu_compare(struct fpemu *fe, int cmpe)
|
||||
__fpu_compare(struct fpemu *fe, int cmpe, int fcc)
|
||||
{
|
||||
register struct fpn *a, *b;
|
||||
register int cc;
|
||||
|
|
@ -160,5 +175,6 @@ __fpu_compare(struct fpemu *fe, int cmpe)
|
|||
cc = diff(FSR_CC_GT);
|
||||
|
||||
done:
|
||||
fe->fe_fsr = (fe->fe_fsr & ~FSR_FCC0_MASK) | FSR_FCC0(cc);
|
||||
fe->fe_fsr = (fe->fe_fsr & fcc_nmask[fcc]) |
|
||||
((u_long)cc << fcc_shift[fcc]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ struct fpn {
|
|||
* Emulator state.
|
||||
*/
|
||||
struct fpemu {
|
||||
int fe_fsr; /* fsr copy (modified during op) */
|
||||
u_long fe_fsr; /* fsr copy (modified during op) */
|
||||
int fe_cx; /* exceptions */
|
||||
struct fpn fe_f1; /* operand 1 */
|
||||
struct fpn fe_f2; /* operand 2, if required */
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ void __fpu_panic __P((char *msg));
|
|||
struct fpn *__fpu_add __P((struct fpemu *));
|
||||
|
||||
/* fpu_compare.c */
|
||||
void __fpu_compare __P((struct fpemu *, int));
|
||||
void __fpu_compare __P((struct fpemu *, int, int));
|
||||
|
||||
/* fpu_div.c */
|
||||
struct fpn *__fpu_div __P((struct fpemu *));
|
||||
|
|
|
|||
Loading…
Reference in a new issue