Better (and more correct) floating point conversions; fif; various new opcodes.
authorDavid Given <dg@cowlark.com>
Fri, 21 Oct 2016 22:48:26 +0000 (00:48 +0200)
committerDavid Given <dg@cowlark.com>
Fri, 21 Oct 2016 22:48:26 +0000 (00:48 +0200)
mach/powerpc/mcg/platform.c
mach/powerpc/mcg/table
mach/proto/mcg/hop.c
mach/proto/mcg/pass_promotefloatops.c
mach/proto/mcg/treebuilder.c
util/mcgg/ir.dat

index e0a7c1a..2b22ec1 100644 (file)
@@ -112,6 +112,11 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg*
                 hop_add_insel(hop, "stwu %H, -4(sp)", src);
                 break;
 
+            case burm_pair_ATTR:
+                hop_add_insel(hop, "stwu %0H, -4(sp)", src);
+                hop_add_insel(hop, "stwu %1H, -4(sp)", src);
+                break;
+
             case burm_float_ATTR:
                 hop_add_insel(hop, "stfsu %H, -4(sp)", src);
                 break;
@@ -130,6 +135,11 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg*
                 hop_add_insel(hop, "lwz %H, 0(sp)", dest);
                 break;
 
+            case burm_pair_ATTR:
+                hop_add_insel(hop, "lwz %0H, 4(sp)", dest);
+                hop_add_insel(hop, "lwz %1H, 0(sp)", dest);
+                break;
+
             case burm_float_ATTR:
                 hop_add_insel(hop, "lfs %H, 0(sp)", dest);
                 break;
@@ -174,6 +184,10 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg*
                     hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest);
                     break;
 
+                case burm_double_ATTR:
+                    hop_add_insel(hop, "stfd %H, %S(fp) ! %H", src, dest, dest);
+                    break;
+
                 default:
                     assert(false);
             }
@@ -190,6 +204,10 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg*
                     hop_add_insel(hop, "lfs %H, %S(fp) ! %H", dest, src, src);
                     break;
 
+                case burm_double_ATTR:
+                    hop_add_insel(hop, "lfd %H, %S(fp) ! %H", dest, src, src);
+                    break;
+
                 default:
                     assert(false);
             }
index f1bc27a..632a47e 100644 (file)
@@ -408,38 +408,28 @@ PATTERNS
 
 /* Comparisons */
 
-       cr:(cr)cr = COMPARES4(left:(int)reg, right:(int)reg)
+       cr:(cr)cr = COMPARES44(left:(int)reg, right:(int)reg)
         emit "cmp %cr, 0, %left, %right"
                cost 4;
 
-       cr:(cr)cr = COMPARES4(left:(int)reg, right:CONST4)
+       cr:(cr)cr = COMPARES44(left:(int)reg, right:CONST4)
         when signed_constant(%right, 16)
         emit "cmpi %cr, 0, %left, $right"
                cost 4;
 
-       cr:(cr)cr = COMPAREU4(left:(int)reg, right:(int)reg)
+       cr:(cr)cr = COMPAREU44(left:(int)reg, right:(int)reg)
         emit "cmpl %cr, 0, %left, %right"
                cost 4;
 
-       cr:(cr)cr = COMPAREU4(left:(int)reg, right:CONST4)
+       cr:(cr)cr = COMPAREU44(left:(int)reg, right:CONST4)
         when signed_constant(%right, 16)
         emit "cmpli %cr, 0, %left, $right"
                cost 4;
 
-    cr:(cr)cr = COMPARES4(COMPARES4(left:(int)reg, right:(int)reg), result:CONST4)
+    out:(cr)cr = COMPARES44(in:(cr)cr, result:CONST4)
         when specific_constant(%result, 0)
-        emit "cmp %cr, 0, %left, %right"
-        cost 4;
-
-    cr:(cr)cr = COMPARES4(COMPARES4(left:(int)reg, right:CONST4), result:CONST4)
-        when specific_constant(%result, 0)
-        when signed_constant(%right, 16)
-        emit "cmpi %cr, 0, %left, $right"
-        cost 4;
-
-    cr:(cr)cr = COMPARES4(COMPAREU4(left:(int)reg, right:(int)reg), result:CONST4)
-        when specific_constant(%result, 0)
-        emit "cmpl %cr, 0, %left, %right"
+        with %out == %in
+        emit "! COMPARES(cr, 0)"
         cost 4;
 
 
@@ -580,32 +570,61 @@ PATTERNS
                emit "fsubs %out, %left, %right"
                cost 4;
 
+       out:(double)reg = SUBF8(left:(double)reg, right:(double)reg)
+               emit "fsub %out, %left, %right"
+               cost 4;
+
     out:(float)reg = MULF4(left:(float)reg, right:(float)reg)
         emit "fmuls %out, %left, %right"
         cost 4;
 
+    out:(double)reg = MULF8(left:(double)reg, right:(double)reg)
+        emit "fmul %out, %left, %right"
+        cost 4;
+
     out:(float)reg = NEGF4(left:(float)reg)
         emit "fneg %out, %left"
         cost 4;
 
-       cr:(cr)cr = COMPAREF4(left:(float)reg, right:(float)reg)
+    out:(double)reg = NEGF8(left:(double)reg)
+        emit "fneg %out, %left"
+        cost 4;
+
+       cr:(cr)cr = COMPAREF44(left:(float)reg, right:(float)reg)
         emit "fcmpu %cr, %left, %right"
                cost 4;
 
-    cr:(cr)cr = COMPARES4(COMPAREF4(left:(float)reg, right:(float)reg), result:CONST4)
-        when specific_constant(%result, 0)
+       cr:(cr)cr = COMPAREF84(left:(double)reg, right:(double)reg)
         emit "fcmpu %cr, %left, %right"
-        cost 4;
+               cost 4;
 
     out:(ret)reg = CFI44(val:(fret)reg)
         with corrupted(volatile)
-        emit "bl .cfi4"
+        emit "bl .cfi44"
         cost 4;
 
     out:(fret)reg = CIF44(val:(ret)reg)
         with corrupted(volatile)
-        emit "bl .cif4"
+        emit "bl .cif44"
+        cost 4;
+
+    out:(ret)reg = CFI84(val:(dret)reg)
+        with corrupted(volatile)
+        emit "bl .cfi84"
         cost 4;
 
+    out:(dret)reg = CIF48(val:(ret)reg)
+        with corrupted(volatile)
+        emit "bl .cif48"
+        cost 4;
+
+    out:(float)reg = CFF84(val:(double)reg)
+        emit "frsp %out, %val"
+        cost 4;
+
+    out:(double)reg = CFF48(val:(float)reg)
+        emit "fmr %out, %val"
+        cost 1;
+
 /* vim: set sw=4 ts=4 expandtab : */
 
index 32bd44d..02f6b29 100644 (file)
@@ -223,7 +223,10 @@ char* hop_render(struct hop* hop)
             case INSEL_HREG:
             {
                 struct hreg* hreg = insel->u.hreg;
-                appendf("%s", hreg->brd->names[insel->index]);
+                if (hreg->brd)
+                    appendf("%s", hreg->brd->names[insel->index]);
+                else
+                    appendf("%s.%d", hreg->id, insel->index);
                 break;
             }
 
index 2708c7f..7e5f87c 100644 (file)
@@ -69,6 +69,14 @@ static void search_for_promotable_irs(void)
             case IR_MULF:
             case IR_DIVF:
             case IR_NEGF:
+            case IR_COMPAREF1:
+            case IR_COMPAREF2:
+            case IR_COMPAREF4:
+            case IR_COMPAREF8:
+            case IR_CFF1:
+            case IR_CFF2:
+            case IR_CFF4:
+            case IR_CFF8:
                 if (ir->left)
                     promote(ir->left);
                 if (ir->right)
index 180f410..a48f59e 100644 (file)
@@ -149,10 +149,18 @@ static struct ir* convert(struct ir* src, int destsize, int opcode)
         );
 }
 
-static struct ir* tristate_compare(int size, int opcode)
+static struct ir* compare(struct ir* left, struct ir* right,
+        int size, int opcode)
 {
-    struct ir* right = pop(size);
-    struct ir* left = pop(size);
+    switch (size)
+    {
+        case 1: opcode += 0; break;
+        case 2: opcode += 1; break;
+        case 4: opcode += 2; break;
+        case 8: opcode += 3; break;
+        default:
+            fatal("can't compare things of size %d", size);
+    }
 
     return
         new_ir2(
@@ -161,6 +169,14 @@ static struct ir* tristate_compare(int size, int opcode)
         );
 }
 
+static struct ir* tristate_compare(int size, int opcode)
+{
+    struct ir* right = pop(size);
+    struct ir* left = pop(size);
+
+    return compare(left, right, size, opcode);
+}
+
 static void simple_convert(int opcode)
 {
     struct ir* destsize = pop(EM_wordsize);
@@ -199,10 +215,11 @@ static void insn_simple(int opcode)
         case op_cui: simple_convert(IR_CUI1); break;
         case op_cfi: simple_convert(IR_CFI1); break;
         case op_cif: simple_convert(IR_CIF1); break;
+        case op_cff: simple_convert(IR_CFF1); break;
 
         case op_cmp:
             push(
-                tristate_compare(EM_pointersize, IR_COMPAREU)
+                tristate_compare(EM_pointersize, IR_COMPAREU1)
             );
             break;
 
@@ -276,6 +293,17 @@ static void insn_simple(int opcode)
             break;
         }
 
+        case op_trp:
+        {
+            materialise_stack();
+            appendir(
+                new_ir1(
+                    IR_CALL, 0,
+                    new_labelir(".trp")
+                )
+            );
+        }
+
         case op_lni:
         {
             /* Increment line number --- ignore. */
@@ -299,10 +327,7 @@ static void simple_branch2(int opcode, int size,
     appendir(
         new_ir2(
             irop, 0,
-            new_ir2(
-                IR_COMPARES,  size,
-                left, right
-            ),
+            compare(left, right, size, IR_COMPARES1),
             new_ir2(
                 IR_PAIR, 0,
                 new_bbir(truebb),
@@ -463,9 +488,9 @@ static void insn_ivalue(int opcode, arith value)
         case op_ngf: simple_alu1(opcode, value, IR_NEGF); break;
 
         case op_cmu: /* fall through */
-        case op_cms: push(tristate_compare(value, IR_COMPAREU)); break;
-        case op_cmi: push(tristate_compare(value, IR_COMPARES)); break;
-        case op_cmf: push(tristate_compare(value, IR_COMPAREF)); break;
+        case op_cms: push(tristate_compare(value, IR_COMPAREU1)); break;
+        case op_cmi: push(tristate_compare(value, IR_COMPARES1)); break;
+        case op_cmf: push(tristate_compare(value, IR_COMPAREF1)); break;
 
         case op_lol:
             push(
@@ -910,8 +935,8 @@ static void insn_ivalue(int opcode, arith value)
 
         case op_fef:
         {
-            struct ir* e;
             struct ir* f = pop(value);
+
             /* fef is implemented by calling a helper function which then mutates
              * the stack. We read the return values off the stack when retracting
              * the stack pointer. */
@@ -931,6 +956,26 @@ static void insn_ivalue(int opcode, arith value)
             break;
         }
             
+        case op_fif:
+        {
+            /* fif is implemented by calling a helper function which then mutates
+             * the stack. We read the return values off the stack when retracting
+             * the stack pointer. */
+
+            /* We start with two floats on the stack. */
+
+            materialise_stack();
+            appendir(
+                new_ir1(
+                    IR_CALL, 0,
+                    new_labelir((value == 4) ? ".fif4" : ".fif8")
+                )
+            );
+                    
+            /* exit, leaving two floats (or doubles) on the stack. */
+            break;
+        }
+            
         case op_lin:
         {
             /* Set line number --- ignore. */
index 5765872..93f7b3c 100644 (file)
@@ -74,10 +74,26 @@ S CIF2
 S CIF4
 S CIF8
 
+S CFF1
+S CFF2
+S CFF4
+S CFF8
+
 # Tristate comparisons
-S COMPARES
-S COMPAREU
-S COMPAREF
+S COMPARES1
+S COMPARES2
+S COMPARES4
+S COMPARES8
+
+S COMPAREU1
+S COMPAREU2
+S COMPAREU4
+S COMPAREU8
+
+S COMPAREF1
+S COMPAREF2
+S COMPAREF4
+S COMPAREF8
 
 # Boolean comparisons
 S IFEQ