diff --git a/mach/powerpc/mcg/table b/mach/powerpc/mcg/table index b6bc0ac48..8511dbb5b 100644 --- a/mach/powerpc/mcg/table +++ b/mach/powerpc/mcg/table @@ -392,17 +392,33 @@ PATTERNS emit "li32 %out.1, 0" cost 8; - out:(iret)reg = FROMF.I(in:(dret)reg) + out:(iret)reg = FROMSF.I(in:(dret)reg) with corrupted(volatile) emit "bl .fromf2i" cost 4; - out:(iret)reg = FROMD.I(in:(dret)reg) + out:(int)reg = FROMSD.I(in:(double)reg) + with preserved(%in) + emit "fctiwz %in, %in" + emit "stfdu %in, -8(sp)" + emit "lwz %out, 4(sp)" + emit "addi sp, sp, 8" + cost 16; + + out:(int)reg = FROMUD.I(in:(double)reg) with corrupted(volatile) - emit "bl .fromd2i" + emit "stfdu %in, -8(sp)" + emit "bl .cfu8" + emit "lwz %out, 0(sp)" + emit "addi sp, sp, 4" + cost 16; + + out:(lret)reg = FROMSF.L(in:(fret)reg) + with corrupted(volatile) + emit "bl .fromf2l" cost 4; - out:(lret)reg = FROMF.L(in:(fret)reg) + out:(lret)reg = FROMUF.I(in:(fret)reg) with corrupted(volatile) emit "bl .fromf2l" cost 4; diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 66347447f..5462cbf79 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -404,11 +404,11 @@ static void insn_simple(int opcode) case op_cii: simple_convert(IR_FROMSI); break; case op_ciu: simple_convert(IR_FROMSI); break; case op_cui: simple_convert(IR_FROMUI); break; - case op_cfu: simple_convert(IR_FROMF); break; /* FIXME: technically wrong */ - case op_cfi: simple_convert(IR_FROMF); break; + case op_cfu: simple_convert(IR_FROMUF); break; + case op_cfi: simple_convert(IR_FROMSF); break; case op_cif: simple_convert(IR_FROMSI); break; case op_cuf: simple_convert(IR_FROMUI); break; - case op_cff: simple_convert(IR_FROMF); break; + case op_cff: simple_convert(IR_FROMSF); break; case op_cmp: push( diff --git a/plat/qemuppc/tests/from_d_to_si_e.c b/plat/qemuppc/tests/from_d_to_si_e.c new file mode 100644 index 000000000..8c7e31c3e --- /dev/null +++ b/plat/qemuppc/tests/from_d_to_si_e.c @@ -0,0 +1,20 @@ +#include "test.h" + +/* Constants in globals to defeat constant folding. */ +double one = 1.0; +double zero = 0.0; +double minusone = -1.0; +double big = 2147483647.0; +double minusbig = -2147483648.0; + +/* Bypasses the CRT, so there's no stdio or BSS initialisation. */ +void _m_a_i_n(void) +{ + ASSERT((int)zero == 0); + ASSERT((int)one == 1); + ASSERT((int)minusone == -1); + ASSERT((int)big == 2147483647); + ASSERT((int)minusbig == -2147483648); + + finished(); +} \ No newline at end of file diff --git a/plat/qemuppc/tests/from_d_to_ui_e.c b/plat/qemuppc/tests/from_d_to_ui_e.c new file mode 100644 index 000000000..b16667502 --- /dev/null +++ b/plat/qemuppc/tests/from_d_to_ui_e.c @@ -0,0 +1,16 @@ +#include "test.h" + +/* Constants in globals to defeat constant folding. */ +double one = 1.0; +double zero = 0.0; +double big = 4294967295.0; + +/* Bypasses the CRT, so there's no stdio or BSS initialisation. */ +void _m_a_i_n(void) +{ + ASSERT((unsigned int)zero == 0); + ASSERT((unsigned int)one == 1); + ASSERT((unsigned int)big == 4294967295); + + finished(); +} \ No newline at end of file diff --git a/plat/qemuppc/tests/cif8_e.c b/plat/qemuppc/tests/from_si_to_d_e.c similarity index 100% rename from plat/qemuppc/tests/cif8_e.c rename to plat/qemuppc/tests/from_si_to_d_e.c diff --git a/plat/qemuppc/tests/cuf8_e.c b/plat/qemuppc/tests/from_ui_to_d_e.c similarity index 100% rename from plat/qemuppc/tests/cuf8_e.c rename to plat/qemuppc/tests/from_ui_to_d_e.c diff --git a/util/mcgg/ir.dat b/util/mcgg/ir.dat index b34f37fbb..4b7c4e920 100644 --- a/util/mcgg/ir.dat +++ b/util/mcgg/ir.dat @@ -69,8 +69,10 @@ S ?=I. FROMUI S ?=L. FROMUL S ?=I. FROMSI S ?=L. FROMSL -S ?=F. FROMF -S ?=D. FROMD +S ?=F. FROMUF +S ?=D. FROMUD +S ?=F. FROMSF +S ?=D. FROMSD S L=II FROMIPAIR S I=L. FROML0 S I=L. FROML1