summaryrefslogtreecommitdiffstats
path: root/lib/libc/sparc64/fpu
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2010-03-10 19:55:48 +0000
committermarius <marius@FreeBSD.org>2010-03-10 19:55:48 +0000
commit7892dc274ebfd581dd00817e35c160a54162b807 (patch)
tree93fc70adb6b7ea88c6c5a18487f4de809f474be0 /lib/libc/sparc64/fpu
parentda95673165a59cb4afa6d3d67fb9b3d41916c9c2 (diff)
downloadFreeBSD-src-7892dc274ebfd581dd00817e35c160a54162b807.zip
FreeBSD-src-7892dc274ebfd581dd00817e35c160a54162b807.tar.gz
- The OPSZ macro actually only does the right thing for int32 and int64
operands but not for double and extended double ones. Instead of trying to fix the macro just nuke it and unroll the loops in the correct way though as extended double operands turn out to be the only special case. - For FxTO{s,d,q} the source operand is int64 so rs2 has to be re-decoded after setting type accordingly as it's generally decoded using the low 2 bits as the type, which are 0 for these three instructions. - Similarly, in case of F{s,d,q}TOx the target is int64 so rd has to be re-decoded using not only the operand mask appropriate for int64 but also the correct register number encoding. - Use const where appropriate. - Wrap long lines. Submitted by: Peter Jeremy (partly) MFC after: 3 days
Diffstat (limited to 'lib/libc/sparc64/fpu')
-rw-r--r--lib/libc/sparc64/fpu/fpu.c48
-rw-r--r--lib/libc/sparc64/fpu/fpu_emu.h2
2 files changed, 21 insertions, 29 deletions
diff --git a/lib/libc/sparc64/fpu/fpu.c b/lib/libc/sparc64/fpu/fpu.c
index 74f07ec..7c8a3a9 100644
--- a/lib/libc/sparc64/fpu/fpu.c
+++ b/lib/libc/sparc64/fpu/fpu.c
@@ -97,7 +97,7 @@ __FBSDID("$FreeBSD$");
#define X8(x) X4(x),X4(x)
#define X16(x) X8(x),X8(x)
-static char cx_to_trapx[] = {
+static const char cx_to_trapx[] = {
X1(FSR_NX),
X2(FSR_DZ),
X4(FSR_UF),
@@ -113,7 +113,8 @@ int __fpe_debug = 0;
#endif
#endif /* FPU_DEBUG */
-static int __fpu_execute(struct utrapframe *, struct fpemu *, u_int32_t, u_long);
+static int __fpu_execute(struct utrapframe *, struct fpemu *, u_int32_t,
+ u_long);
/*
* Need to use an fpstate on the stack; we could switch, so we cannot safely
@@ -169,7 +170,7 @@ __fpu_exception(struct utrapframe *uf)
void
__fpu_dumpfpn(struct fpn *fp)
{
- static char *class[] = {
+ static const char *const class[] = {
"SNAN", "QNAN", "ZERO", "NUM", "INF"
};
@@ -181,15 +182,11 @@ __fpu_dumpfpn(struct fpn *fp)
}
#endif
-static int opmask[] = {0, 0, 1, 3};
+static const int opmask[] = {0, 0, 1, 3, 1};
/* Decode 5 bit register field depending on the type. */
#define RN_DECODE(tp, rn) \
- ((tp == FTYPE_DBL || tp == FTYPE_EXT ? INSFPdq_RN((rn)) : (rn)) & \
- ~opmask[tp])
-
-/* Operand size in 32-bit registers. */
-#define OPSZ(tp) ((tp) == FTYPE_LNG ? 2 : (1 << (tp)))
+ ((tp) >= FTYPE_DBL ? INSFPdq_RN(rn) & ~opmask[tp] : (rn))
/*
* Helper for forming the below case statements. Build only the op3 and opf
@@ -209,8 +206,6 @@ static void
__fpu_mov(struct fpemu *fe, int type, int rd, int rs2, u_int32_t nand,
u_int32_t xor)
{
- u_int64_t tmp64;
- int i;
if (type == FTYPE_INT || type == FTYPE_SNG)
__fpu_setreg(rd, (__fpu_getreg(rs2) & ~nand) ^ xor);
@@ -219,13 +214,10 @@ __fpu_mov(struct fpemu *fe, int type, int rd, int rs2, u_int32_t nand,
* Need to use the double versions to be able to access
* the upper 32 fp registers.
*/
- for (i = 0; i < OPSZ(type); i += 2, rd += 2, rs2 += 2) {
- tmp64 = __fpu_getreg64(rs2);
- if (i == 0)
- tmp64 = (tmp64 & ~((u_int64_t)nand << 32)) ^
- ((u_int64_t)xor << 32);
- __fpu_setreg64(rd, tmp64);
- }
+ __fpu_setreg64(rd, (__fpu_getreg64(rs2) &
+ ~((u_int64_t)nand << 32)) ^ ((u_int64_t)xor << 32));
+ if (type == FTYPE_EXT)
+ __fpu_setreg64(rd + 2, __fpu_getreg64(rs2 + 2));
}
}
@@ -271,17 +263,17 @@ __fpu_cmpck(struct fpemu *fe)
* multiply two integers this way.
*/
static int
-__fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn, u_long tstate)
+__fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn,
+ u_long tstate)
{
struct fpn *fp;
int opf, rs1, rs2, rd, type, mask, cx, cond;
u_long reg, fsr;
u_int space[4];
- int i;
/*
* `Decode' and execute instruction. Start with no exceptions.
- * The type of any opf opcode is in the bottom two bits, so we
+ * The type of almost any OPF opcode is in the bottom two bits, so we
* squish them out here.
*/
opf = insn & (IF_MASK(IF_F3_OP3_SHIFT, IF_F3_OP3_BITS) |
@@ -359,7 +351,7 @@ __fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn, u_long ts
__fpu_explode(fe, &fe->fe_f2, type, rs2);
__fpu_compare(fe, 1, IF_F3_CC(insn));
return (__fpu_cmpck(fe));
- case FOP(INS2_FPop1, INSFP1_FMOV): /* these should all be pretty obvious */
+ case FOP(INS2_FPop1, INSFP1_FMOV):
__fpu_mov(fe, type, rd, rs2, 0, 0);
return (0);
case FOP(INS2_FPop1, INSFP1_FNEG):
@@ -410,6 +402,7 @@ __fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn, u_long ts
case FOP(INS2_FPop1, INSFP1_FxTOd):
case FOP(INS2_FPop1, INSFP1_FxTOq):
type = FTYPE_LNG;
+ rs2 = RN_DECODE(type, IF_F3_RS2(insn));
__fpu_explode(fe, fp = &fe->fe_f1, type, rs2);
/* sneaky; depends on instruction encoding */
type = (IF_F3_OPF(insn) >> 2) & 3;
@@ -418,8 +411,7 @@ __fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn, u_long ts
case FOP(INS2_FPop1, INSFP1_FTOx):
__fpu_explode(fe, fp = &fe->fe_f1, type, rs2);
type = FTYPE_LNG;
- mask = 1; /* needs 2 registers */
- rd = IF_F3_RD(insn) & ~mask;
+ rd = RN_DECODE(type, IF_F3_RD(insn));
break;
case FOP(INS2_FPop1, INSFP1_FTOs):
case FOP(INS2_FPop1, INSFP1_FTOd):
@@ -457,10 +449,10 @@ __fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn, u_long ts
if (type == FTYPE_INT || type == FTYPE_SNG)
__fpu_setreg(rd, space[0]);
else {
- for (i = 0; i < OPSZ(type); i += 2) {
- __fpu_setreg64(rd + i, ((u_int64_t)space[i] << 32) |
- space[i + 1]);
- }
+ __fpu_setreg64(rd, ((u_int64_t)space[0] << 32) | space[1]);
+ if (type == FTYPE_EXT)
+ __fpu_setreg64(rd + 2,
+ ((u_int64_t)space[2] << 32) | space[3]);
}
return (0); /* success */
}
diff --git a/lib/libc/sparc64/fpu/fpu_emu.h b/lib/libc/sparc64/fpu/fpu_emu.h
index de156e2..82c96d8 100644
--- a/lib/libc/sparc64/fpu/fpu_emu.h
+++ b/lib/libc/sparc64/fpu/fpu_emu.h
@@ -140,7 +140,7 @@ struct fpn {
#define FTYPE_SNG INSFP_s
#define FTYPE_DBL INSFP_d
#define FTYPE_EXT INSFP_q
-#define FTYPE_LNG -1
+#define FTYPE_LNG 5
/*
* Emulator state.
OpenPOWER on IntegriCloud