aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--amd64/emit.c32
-rw-r--r--amd64/isel.c13
-rw-r--r--test/flt.c25
3 files changed, 68 insertions, 2 deletions
diff --git a/amd64/emit.c b/amd64/emit.c
index 505735c..a6ce774 100644
--- a/amd64/emit.c
+++ b/amd64/emit.c
@@ -580,7 +580,27 @@ DEFINSTR2(Xshr,
)
DEFINSTR2(Xcvtss2sd,
{-1, PFPR, PFPR, "\xF3\x0F\x5A", EN_RR}, /* CVTSS2SD xmm, xmm */
- {-1, PFPR, PMEM, "\xF3\x0F\x5A", EN_RM}, /* CVTSS2SD xmm, xmm */
+ {-1, PFPR, PMEM, "\xF3\x0F\x5A", EN_RM}, /* CVTSS2SD xmm, m32/64 */
+)
+DEFINSTR2(Xcvtsd2ss,
+ {-1, PFPR, PFPR, "\xF2\x0F\x5A", EN_RR}, /* CVTSD2SS xmm, xmm */
+ {-1, PFPR, PMEM, "\xF2\x0F\x5A", EN_RM}, /* CVTSD2SS xmm, m32/64 */
+)
+DEFINSTR2(Xcvtsi2ss,
+ {-1, PFPR, PGPR, "\xF3\x0F\x2A", EN_RR}, /* CVTSI2SS xmm, r32/64 */
+ {-1, PFPR, PMEM, "\xF3\x0F\x2A", EN_RM}, /* CVTSI2SS xmm, m32/64 */
+)
+DEFINSTR2(Xcvtsi2sd,
+ {-1, PFPR, PGPR, "\xF2\x0F\x2A", EN_RR}, /* CVTSI2SD xmm, r32/64 */
+ {-1, PFPR, PMEM, "\xF2\x0F\x2A", EN_RM}, /* CVTSI2SD xmm, m32/64 */
+)
+DEFINSTR2(Xcvttss2si,
+ {-1, PGPR, PFPR, "\xF3\x0F\x2C", EN_RR}, /* CVTTSS2SI r32/64, xmm */
+ {-1, PGPR, PMEM, "\xF3\x0F\x2C", EN_RM}, /* CVTTSS2SI r32/64, m32 */
+)
+DEFINSTR2(Xcvttsd2si,
+ {-1, PGPR, PFPR, "\xF2\x0F\x2C", EN_RR}, /* CVTTSD2SI r32/64, xmm */
+ {-1, PGPR, PMEM, "\xF2\x0F\x2C", EN_RM}, /* CVTTSD2SI r32/64, m32 */
)
DEFINSTR1(Xinc,
{4|8, PGPR, 0, "\xFF", EN_R, .ext=0} /* INC r32/64 */
@@ -887,7 +907,15 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc
case Oloadu4: src = mkmemoper(ins->l); Movzxl: Xmov(pcode, KI4, reg2oper(ins->reg-1), src); break;
case Oloadf4: case Oloadf8: Xmov(pcode, cls, reg2oper(ins->reg-1), mkmemoper(ins->l)); break;
case Oloadi8: Xmov(pcode, KI8, reg2oper(ins->reg-1), mkmemoper(ins->l)); break;
- case Ocvtf4f8: Xcvtss2sd(pcode, KF4, reg2oper(ins->reg-1), mkdatregoper(ins->l)); break;
+ case Ocvtf4f8: X = Xcvtss2sd; goto FloatsCvt;
+ case Ocvtf8f4: X = Xcvtsd2ss; goto FloatsCvt;
+ case Ocvtf4s: X = Xcvttss2si; goto FloatsCvt;
+ case Ocvtf8s: X = Xcvttsd2si; goto FloatsCvt;
+ case Ocvts4f: X = cls == KF4 ? Xcvtsi2ss : Xcvtsi2sd; cls = KI4; goto FloatsCvt;
+ case Ocvts8f: X = cls == KF4 ? Xcvtsi2ss : Xcvtsi2sd; cls = KI8; goto FloatsCvt;
+ FloatsCvt:
+ X(pcode, cls, reg2oper(ins->reg-1), mkdatregoper(ins->l));
+ break;
case Oadd:
dst = mkregoper(ins->l);
if (kisflt(cls)) {
diff --git a/amd64/isel.c b/amd64/isel.c
index 2c2e9be..65ccfb7 100644
--- a/amd64/isel.c
+++ b/amd64/isel.c
@@ -405,7 +405,20 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi)
else
fixarg(&ins->r, ins, blk, curi);
break;
+ case Ocvtu4f:
+ fixarg(&ins->l, ins, blk, curi);
+ ins->l = insertinstr(blk, (*curi)++, mkinstr(Oextu4, KI8, ins->l));
+ ins->op = Ocvts8f;
+ break;
+ case Ocvtf4u: case Ocvtf8u:
+ fixarg(&ins->l, ins, blk, curi);
+ if (ins->cls == KI4) {
+ ins->l = insertinstr(blk, (*curi)++, mkinstr(ins->op == Ocvtf4u ? Ocvtf4s : Ocvtf8s, KI8, ins->l));
+ ins->op = Oextu4;
+ } else assert(!"nyi flt -> u64");
+ break;
case Ocvtf4f8: case Ocvtf8f4: case Ocvtf4s: case Ocvtf8s: case Ocvts4f: case Ocvts8f:
+ case Ocvtu8f:
case Oexts1: case Oextu1: case Oexts2: case Oextu2: case Oexts4: case Oextu4:
case Ocopy:
fixarg(&ins->l, ins, blk, curi);
diff --git a/test/flt.c b/test/flt.c
new file mode 100644
index 0000000..7866c10
--- /dev/null
+++ b/test/flt.c
@@ -0,0 +1,25 @@
+typedef unsigned u32;
+typedef signed s32;
+typedef float f32;
+typedef double f64;
+typedef unsigned long long u64;
+typedef signed long long s64;
+
+f32 s32_to_f32(s32 x) { return x; }
+f32 u32_to_f32(u32 x) { return x; }
+f64 s32_to_f64(s32 x) { return x; }
+f64 u32_to_f64(u32 x) { return x; }
+f32 s64_to_f32(s64 x) { return x; }
+//f32 u64_to_f32(u64 x) { return x; }
+f64 s64_to_f64(s64 x) { return x; }
+//f64 u64_to_f64(u64 x) { return x; }
+s32 f32_to_s32(f32 x) { return x; }
+u32 f32_to_u32(f32 x) { return x; }
+s32 f64_to_s32(f64 x) { return x; }
+u32 f64_to_u32(f64 x) { return x; }
+s64 f32_to_s64(f32 x) { return x; }
+//u64 f32_to_u64(f32 x) { return x; }
+s64 f64_to_s64(f64 x) { return x; }
+//u64 f64_to_u64(f64 x) { return x; }
+f32 f64_to_f32(f64 x) { return x; }
+f64 f32_to_f64(f32 x) { return x; }