More opcodes.
authorDavid Given <dg@cowlark.com>
Sat, 22 Oct 2016 18:32:51 +0000 (20:32 +0200)
committerDavid Given <dg@cowlark.com>
Sat, 22 Oct 2016 18:32:51 +0000 (20:32 +0200)
mach/powerpc/mcg/table
mach/proto/mcg/treebuilder.c
util/mcgg/ir.dat

index 240086b..8a87e07 100644 (file)
@@ -464,12 +464,12 @@ PATTERNS
 
     out:(int)reg = IFEQ4(in:(cr)cr)
         emit "mfcr %out" /* get cr0 */
-        emit "rlwinmi %out, %out, 32-2, 2, 31" /* extract just EQ */
+        emit "rlwinm %out, %out, [32-2], 2, 31" /* extract just EQ */
         cost 8;
 
     out:(int)reg = IFEQ4(in:(int)reg)
         emit "cntlzw %out, %in" /* returns 0..32 */
-        emit "rlwinmi %out, %out, 32-5, 5, 31" /* if 32, return 1, otherwise 0 */
+        emit "rlwinm %out, %out, [32-5], 5, 31" /* if 32, return 1, otherwise 0 */
         cost 8;
 
 
@@ -527,6 +527,12 @@ PATTERNS
         emit "subf %out, %out, %left"
                cost 12;
 
+       out:(int)reg = MODU4(left:(int)reg, right:(int)reg)
+               emit "divwu %out, %left, %right"
+        emit "mullw %out, %out, %right"
+        emit "subf %out, %out, %left"
+               cost 12;
+
     ALUR(MUL4, "mullw")
     ALUCC(MUL4, "mulli")
 
@@ -535,10 +541,17 @@ PATTERNS
 
     ALUR(ASL4, "slw")
 
+    ALUR(LSL4, "slw")
+
     out:(int)reg = NEG4(left:(int)reg)
         emit "neg %out, %left"
         cost 4;
 
+    out:(int)reg = NOT4(left:(int)reg)
+        emit "cntlzw %out, %left"
+        emit "rlwinm %out, %out, 32-5, 5, 31"
+        cost 8;
+
     ALUR(AND4, "and")
     ALUCC(AND4, "andi.")
 
index 91a0826..4ec1b46 100644 (file)
@@ -178,6 +178,14 @@ static struct ir* tristate_compare(int size, int opcode)
     return compare(left, right, size, opcode);
 }
 
+static struct ir* tristate_compare0(int size, int opcode)
+{
+    struct ir* right = new_wordir(0);
+    struct ir* left = pop(size);
+
+    return compare(left, right, size, opcode);
+}
+
 static void simple_convert(int opcode)
 {
     struct ir* destsize = pop(EM_wordsize);
@@ -193,6 +201,60 @@ static void simple_convert(int opcode)
     );
 }
 
+static void simple_branch2(int opcode, int size,
+    struct basicblock* truebb, struct basicblock* falsebb,
+    int irop)
+{
+    struct ir* right = pop(size);
+    struct ir* left = pop(size);
+
+    materialise_stack();
+    appendir(
+        new_ir2(
+            irop, 0,
+            compare(left, right, size, IR_COMPARES1),
+            new_ir2(
+                IR_PAIR, 0,
+                new_bbir(truebb),
+                new_bbir(falsebb)
+            )
+        )
+    );
+}
+
+static void compare0_branch2(int opcode,
+    struct basicblock* truebb, struct basicblock* falsebb,
+    int irop)
+{
+    push(
+        new_wordir(0)
+    );
+
+    simple_branch2(opcode, EM_wordsize, truebb, falsebb, irop);
+}
+
+static void simple_test(int size, int irop)
+{
+    push(
+        new_ir1(
+            irop, EM_wordsize,
+            tristate_compare0(size, IR_COMPARES1)
+        )
+    );
+}
+
+static void simple_test_neg(int size, int irop)
+{
+    simple_test(size, irop);
+
+    push(
+        new_ir1(
+            IR_NOT, EM_wordsize,
+            pop(EM_wordsize)
+        )
+    );
+}
+
 static void insn_simple(int opcode)
 {
     switch (opcode)
@@ -224,14 +286,8 @@ static void insn_simple(int opcode)
             );
             break;
 
-        case op_teq: 
-            push(
-                new_ir1(
-                    IR_IFEQ, EM_wordsize,
-                    pop(EM_wordsize)
-                )
-            );
-            break;
+        case op_teq: simple_test(EM_wordsize, IR_IFEQ); break;
+        case op_tne: simple_test_neg(EM_wordsize, IR_IFEQ); break;
 
         case op_cai:
         {
@@ -318,38 +374,6 @@ static void insn_simple(int opcode)
     }
 }
 
-static void simple_branch2(int opcode, int size,
-    struct basicblock* truebb, struct basicblock* falsebb,
-    int irop)
-{
-    struct ir* right = pop(size);
-    struct ir* left = pop(size);
-
-    materialise_stack();
-    appendir(
-        new_ir2(
-            irop, 0,
-            compare(left, right, size, IR_COMPARES1),
-            new_ir2(
-                IR_PAIR, 0,
-                new_bbir(truebb),
-                new_bbir(falsebb)
-            )
-        )
-    );
-}
-
-static void compare0_branch2(int opcode,
-    struct basicblock* truebb, struct basicblock* falsebb,
-    int irop)
-{
-    push(
-        new_wordir(0)
-    );
-
-    simple_branch2(opcode, EM_wordsize, truebb, falsebb, irop);
-}
-
 static void insn_bvalue(int opcode, struct basicblock* leftbb, struct basicblock* rightbb)
 {
     switch (opcode)
@@ -490,6 +514,7 @@ static void insn_ivalue(int opcode, arith value)
         case op_mlu: simple_alu2(opcode, value, IR_MUL); break;
         case op_slu: simple_alu2(opcode, value, IR_LSL); break;
         case op_sru: simple_alu2(opcode, value, IR_LSR); break;
+        case op_rmu: simple_alu2(opcode, value, IR_MODU); break;
         case op_dvu: simple_alu2(opcode, value, IR_DIVU); break;
 
         case op_and: simple_alu2(opcode, value, IR_AND); break;
@@ -595,6 +620,14 @@ static void insn_ivalue(int opcode, arith value)
             );
             break;
 
+        case op_zrf:
+        {
+            struct ir* ir = new_constir(value, 0);
+            ir->opcode = IR_CONSTF;
+            push(ir);
+            break;
+        }
+
         case op_loe:
             push(
                 new_ir1(
index 6b3c375..5c47c66 100644 (file)
@@ -32,6 +32,7 @@ S MUL
 S DIV
 S DIVU
 S MOD
+S MODU
 S NEG
 
 S ADDF
@@ -96,7 +97,7 @@ S COMPAREF2
 S COMPAREF4
 S COMPAREF8
 
-# Boolean comparisons
+# Tristate to boolean conversion
 S IFEQ
 S IFLT
 S IFLE