aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ops.h4
-rw-r--r--qbe.c85
-rw-r--r--test/float-to-uint32.qbe2
-rw-r--r--test/float-to-uint64.qbe14
-rw-r--r--test/uint32-to-float.qbe5
-rw-r--r--test/uint64-to-float.qbe16
6 files changed, 19 insertions, 107 deletions
diff --git a/ops.h b/ops.h
index 9b2d48b..dd4b2c6 100644
--- a/ops.h
+++ b/ops.h
@@ -84,9 +84,13 @@ OP(IEXTUB, "extub")
OP(IEXTS, "exts")
OP(ITRUNCD, "truncd")
OP(ISTOSI, "stosi")
+OP(ISTOUI, "stoui")
OP(IDTOSI, "dtosi")
+OP(IDTOUI, "dtoui")
OP(ISWTOF, "swtof")
+OP(IUWTOF, "uwtof")
OP(ISLTOF, "sltof")
+OP(IULTOF, "ultof")
/* cast and copy */
OP(ICAST, "cast")
diff --git a/qbe.c b/qbe.c
index 41a38da..4b0a767 100644
--- a/qbe.c
+++ b/qbe.c
@@ -398,77 +398,6 @@ funcload(struct func *f, struct type *t, struct lvalue lval)
return funcbits(f, t, v, lval.bits);
}
-/* TODO: move these conversions to QBE */
-static struct value *
-utof(struct func *f, int dst, int src, struct value *v)
-{
- struct value *odd, *big;
- struct block *join;
-
- if (src == 'w') {
- v = funcinst(f, IEXTUW, 'l', v, NULL);
- return funcinst(f, ISLTOF, dst, v, NULL);
- }
-
- join = mkblock("utof_join");
- join->phi.blk[0] = mkblock("utof_small");
- join->phi.blk[1] = mkblock("utof_big");
-
- big = funcinst(f, ICSLTL, 'w', v, mkintconst(0));
- funcjnz(f, big, NULL, join->phi.blk[1], join->phi.blk[0]);
-
- funclabel(f, join->phi.blk[0]);
- join->phi.val[0] = funcinst(f, ISLTOF, dst, v, NULL);
- funcjmp(f, join);
-
- funclabel(f, join->phi.blk[1]);
- odd = funcinst(f, IAND, 'l', v, mkintconst(1));
- v = funcinst(f, ISHR, 'l', v, mkintconst(1));
- v = funcinst(f, IOR, 'l', v, odd); /* round to odd */
- v = funcinst(f, ISLTOF, dst, v, NULL);
- join->phi.val[1] = funcinst(f, IADD, dst, v, v);
-
- funclabel(f, join);
- functemp(f, &join->phi.res);
- join->phi.class = dst;
- return &join->phi.res;
-}
-
-static struct value *
-ftou(struct func *f, int dst, int src, struct value *v)
-{
- struct value *big, *maxflt, *maxint;
- struct block *join;
- enum instkind op = src == 's' ? ISTOSI : IDTOSI;
-
- if (dst == 'w')
- return funcinst(f, op, 'l', v, NULL);
-
- join = mkblock("ftou_join");
- join->phi.blk[0] = mkblock("ftou_small");
- join->phi.blk[1] = mkblock("ftou_big");
-
- maxflt = mkfltconst(src == 's' ? VALUE_FLTCONST : VALUE_DBLCONST, 0x1p63);
- maxint = mkintconst(1ull<<63);
-
- big = funcinst(f, src == 's' ? ICGES : ICGED, 'w', v, maxflt);
- funcjnz(f, big, NULL, join->phi.blk[1], join->phi.blk[0]);
-
- funclabel(f, join->phi.blk[0]);
- join->phi.val[0] = funcinst(f, op, dst, v, NULL);
- funcjmp(f, join);
-
- funclabel(f, join->phi.blk[1]);
- v = funcinst(f, ISUB, src, v, maxflt);
- v = funcinst(f, op, dst, v, NULL);
- join->phi.val[1] = funcinst(f, IXOR, dst, v, maxint);
-
- funclabel(f, join);
- functemp(f, &join->phi.res);
- join->phi.class = dst;
- return &join->phi.res;
-}
-
static struct value *
convert(struct func *f, struct type *dst, struct type *src, struct value *l)
{
@@ -515,16 +444,18 @@ convert(struct func *f, struct type *dst, struct type *src, struct value *l)
default: fatal("internal error; unknown integer conversion");
}
} else {
- if (!dst->u.basic.issigned)
- return ftou(f, class, src->size == 8 ? 'd' : 's', l);
- op = src->size == 8 ? IDTOSI : ISTOSI;
+ if (dst->u.basic.issigned)
+ op = src->size == 8 ? IDTOSI : ISTOSI;
+ else
+ op = src->size == 8 ? IDTOUI : ISTOUI;
}
} else {
class = dst->size == 8 ? 'd' : 's';
if (src->prop & PROPINT) {
- if (!src->u.basic.issigned)
- return utof(f, class, src->size == 8 ? 'l' : 'w', l);
- op = src->size == 8 ? ISLTOF : ISWTOF;
+ if (src->u.basic.issigned)
+ op = src->size == 8 ? ISLTOF : ISWTOF;
+ else
+ op = src->size == 8 ? IULTOF : IUWTOF;
} else {
assert(src->prop & PROPFLOAT);
if (src->size == dst->size)
diff --git a/test/float-to-uint32.qbe b/test/float-to-uint32.qbe
index 2cfc65f..a06c5fd 100644
--- a/test/float-to-uint32.qbe
+++ b/test/float-to-uint32.qbe
@@ -3,6 +3,6 @@ function w $f() {
@start.1
@body.2
%.1 =s call $g()
- %.2 =l stosi %.1
+ %.2 =w stoui %.1
ret %.2
}
diff --git a/test/float-to-uint64.qbe b/test/float-to-uint64.qbe
index 363fc30..2055abd 100644
--- a/test/float-to-uint64.qbe
+++ b/test/float-to-uint64.qbe
@@ -3,16 +3,6 @@ function l $f() {
@start.1
@body.2
%.1 =s call $g()
- %.2 =w cges %.1, s_9.2233720368547758e+18
- jnz %.2, @ftou_big.5, @ftou_small.4
-@ftou_small.4
- %.3 =l stosi %.1
- jmp @ftou_join.3
-@ftou_big.5
- %.4 =s sub %.1, s_9.2233720368547758e+18
- %.5 =l stosi %.4
- %.6 =l xor %.5, 9223372036854775808
-@ftou_join.3
- %.7 =l phi @ftou_small.4 %.3, @ftou_big.5 %.6
- ret %.7
+ %.2 =l stoui %.1
+ ret %.2
}
diff --git a/test/uint32-to-float.qbe b/test/uint32-to-float.qbe
index 0e90531..75c2e1e 100644
--- a/test/uint32-to-float.qbe
+++ b/test/uint32-to-float.qbe
@@ -3,7 +3,6 @@ function s $f() {
@start.1
@body.2
%.1 =w call $g()
- %.2 =l extuw %.1
- %.3 =s sltof %.2
- ret %.3
+ %.2 =s uwtof %.1
+ ret %.2
}
diff --git a/test/uint64-to-float.qbe b/test/uint64-to-float.qbe
index 4c3cf92..8e14a8a 100644
--- a/test/uint64-to-float.qbe
+++ b/test/uint64-to-float.qbe
@@ -3,18 +3,6 @@ function s $f() {
@start.1
@body.2
%.1 =l call $g()
- %.2 =w csltl %.1, 0
- jnz %.2, @utof_big.5, @utof_small.4
-@utof_small.4
- %.3 =s sltof %.1
- jmp @utof_join.3
-@utof_big.5
- %.4 =l and %.1, 1
- %.5 =l shr %.1, 1
- %.6 =l or %.5, %.4
- %.7 =s sltof %.6
- %.8 =s add %.7, %.7
-@utof_join.3
- %.9 =s phi @utof_small.4 %.3, @utof_big.5 %.8
- ret %.9
+ %.2 =s ultof %.1
+ ret %.2
}