Hacky workaround the way the Modula-2 compiler generates non-standard sized
authorDavid Given <dg@cowlark.com>
Sat, 22 Oct 2016 08:48:22 +0000 (10:48 +0200)
committerDavid Given <dg@cowlark.com>
Sat, 22 Oct 2016 08:48:22 +0000 (10:48 +0200)
loads and saves. More opcodes; simplified table using macros.

mach/powerpc/mcg/table
mach/proto/mcg/treebuilder.c
util/mcgg/build.lua
util/mcgg/ir.dat

index 632a47e..15a278e 100644 (file)
@@ -463,19 +463,29 @@ PATTERNS
 
 /* ALU operations */
 
-       out:(int)reg = ADD4(left:(int)reg, right:(int)reg)
-               emit "add %out, %left, %right"
-               cost 4;
-
-       out:(int)reg = ADD4(left:(int)reg, right:CONST4)
-        when signed_constant(%right, 16)
-               emit "addi %out, %left, $right"
-               cost 4;
-
-       out:(int)reg = ADD4(left:CONST4, right:(int)reg)
-        when signed_constant(%left, 16)
-               emit "addi %out, %right, $left"
-               cost 4;
+    #define ALUR(name, instr) \
+        out:(int)reg = name(left:(int)reg, right:(int)reg) \
+            emit instr " %out, %left, %right"              \
+            cost 4;                                        \
+
+    #define ALUC(name, instr) \
+        out:(int)reg = name(left:(int)reg, right:CONST4)   \
+            when signed_constant(%right, 16)               \
+            emit instr " %out, %left, $right"              \
+            cost 4;                                        \
+
+    #define ALUC_reversed(name, instr) \
+        out:(int)reg = name(left:CONST4, right:(int)reg)   \
+            when signed_constant(%left, 16)                \
+            emit instr " %out, %right, $left"              \
+            cost 4;                                        \
+
+    #define ALUCC(name, instr) \
+        ALUC(name, instr) \
+        ALUC_reversed(name, instr)
+
+    ALUR(ADD4, "add")
+    ALUCC(ADD4, "addi")
 
        out:(int)reg = SUB4(left:(int)reg, right:(int)reg)
                emit "subf %out, %left, %right"
@@ -485,51 +495,32 @@ PATTERNS
                emit "addi %out, %left, -[$right]"
                cost 4;
 
-       out:(int)reg = MUL4(left:(int)reg, right:(int)reg)
-               emit "mullw %out, %right, %left"
-               cost 4;
-
        out:(int)reg = MOD4(left:(int)reg, right:(int)reg)
                emit "divw %out, %left, %right"
         emit "mullw %out, %out, %right"
         emit "subf %out, %out, %left"
                cost 12;
 
-       out:(int)reg = MUL4(left:(int)reg, right:(int)reg)
-               emit "mullw %out, %left, %right"
-               cost 4;
+    ALUR(MUL4, "mullw")
+    ALUCC(MUL4, "mulli")
 
-       out:(int)reg = DIV4(left:(int)reg, right:(int)reg)
-               emit "divw %out, %left, %right"
-               cost 4;
+    ALUR(DIV4, "divw")
+    ALUR(DIVU4, "divwu")
 
-    out:(int)reg = ASL4(left:(int)reg, right:(int)reg)
-        emit "slw %out, %left, %right"
-        cost 4;
+    ALUR(ASL4, "slw")
 
     out:(int)reg = NEG4(left:(int)reg)
         emit "neg %out, %left"
         cost 4;
 
-       out:(int)reg = AND4(left:CONST4, right:(int)reg)
-               emit "andi. %out, %right, $left"
-               cost 4;
+    ALUR(AND4, "and")
+    ALUCC(AND4, "andi.")
 
-       out:(int)reg = AND4(left:(int)reg, right:CONST4)
-               emit "andi. %out, %left, $right"
-               cost 4;
+    ALUR(OR4, "or")
+    ALUCC(OR4, "ori")
 
-       out:(int)reg = AND4(left:(int)reg, right:(int)reg)
-               emit "and %out, %left, %right"
-               cost 4;
-
-       out:(int)reg = OR4(left:(int)reg, right:(int)reg)
-               emit "or %out, %right, %left"
-               cost 4;
-
-       out:(int)reg = EOR4(left:(int)reg, right:(int)reg)
-               emit "xor %out, %right, %left"
-               cost 4;
+    ALUR(EOR4, "xor")
+    ALUCC(EOR4, "xori")
 
        out:(int)reg = value:LABEL4
                emit "la %out, $value"
@@ -546,6 +537,16 @@ PATTERNS
 
 /* FPU operations */
 
+    #define FPU4R(name, instr) \
+        out:(float)reg = name(left:(float)reg, right:(float)reg) \
+            emit instr " %out, %left, %right"                    \
+            cost 4;                                              \
+
+    #define FPU8R(name, instr) \
+        out:(double)reg = name(left:(double)reg, right:(double)reg) \
+            emit instr " %out, %left, %right"                       \
+            cost 4;                                                 \
+
     out:(float)reg = LOADF4(addr:address)
         emit "lfs %out, %addr"
         cost 4;
@@ -558,29 +559,17 @@ PATTERNS
                emit "lfs %out, address-containing-$value"
                cost 8;
 
-       out:(float)reg = ADDF4(left:(float)reg, right:(float)reg)
-               emit "fadds %out, %left, %right"
-               cost 4;
-
-       out:(double)reg = ADDF8(left:(double)reg, right:(double)reg)
-               emit "fadd %out, %left, %right"
-               cost 4;
+    FPU4R(ADDF4, "fadds")
+    FPU8R(ADDF8, "fadd")
 
-       out:(float)reg = SUBF4(left:(float)reg, right:(float)reg)
-               emit "fsubs %out, %left, %right"
-               cost 4;
+    FPU4R(SUBF4, "fsubs")
+    FPU8R(SUBF8, "fsub")
 
-       out:(double)reg = SUBF8(left:(double)reg, right:(double)reg)
-               emit "fsub %out, %left, %right"
-               cost 4;
+    FPU4R(MULF4, "fmuls")
+    FPU8R(MULF8, "fmul")
 
-    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;
+    FPU4R(DIVF4, "fdivs")
+    FPU8R(DIVF8, "fdiv")
 
     out:(float)reg = NEGF4(left:(float)reg)
         emit "fneg %out, %left"
index 12aa5c2..4ee49eb 100644 (file)
@@ -458,6 +458,19 @@ static void change_by(struct ir* address, int amount)
     );
 }
 
+static struct ir* ptradd(struct ir* address, int offset)
+{
+    if (offset == 0)
+        return address;
+
+    return
+        new_ir2(
+            IR_ADD, EM_pointersize,
+            address,
+            new_wordir(offset)
+        );
+}
+
 static void insn_ivalue(int opcode, arith value)
 {
     switch (opcode)
@@ -476,6 +489,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_dvu: simple_alu2(opcode, value, IR_DIVU); break;
 
         case op_and: simple_alu2(opcode, value, IR_AND); break;
         case op_ior: simple_alu2(opcode, value, IR_OR); break;
@@ -628,13 +642,37 @@ static void insn_ivalue(int opcode, arith value)
             break;
 
         case op_loi:
-            push(
-                new_ir1(
-                    IR_LOAD, value,
-                    pop(EM_pointersize)
-                )
-            );
+        {
+            struct ir* ptr = pop(EM_pointersize);
+            int offset = 0;
+
+            /* FIXME: this is awful; need a better way of dealing with
+             * non-standard EM sizes. */
+            if (value > (EM_wordsize*2))
+                appendir(ptr);
+
+            while (value > 0)
+            {
+                int s;
+                if (value > (EM_wordsize*2))
+                    s = EM_wordsize*2;
+                else
+                    s = value;
+
+                push(
+                    new_ir1(
+                        IR_LOAD, s,
+                        ptradd(ptr, offset)
+                    )
+                );
+
+                value -= s;
+                offset += s;
+            }
+
+            assert(value == 0);
             break;
+        }
 
         case op_lof:
         {
index 8606755..f805505 100644 (file)
@@ -65,6 +65,12 @@ definerule("mcgg",
                        error("you must supply exactly one input file")
                end
 
+               local cpptable = cppfile {
+                       name = e.name.."/cpptable",
+                       outleaf = "cpptable",
+                       srcs = e.srcs
+               }
+
                return normalrule {
                        name = e.name,
                        cwd = e.cwd,
@@ -74,7 +80,7 @@ definerule("mcgg",
                        },
                        ins = {
                                "util/mcgg+mcgg",
-                               e.srcs[1]
+                               cpptable
                        },
                        commands = {
                                "%{ins[1]} -i %{ins[2]} -o %{outs[1]} -h %{outs[2]}",
index 93f7b3c..7fe51ed 100644 (file)
@@ -30,6 +30,7 @@ S ADD
 S SUB
 S MUL
 S DIV
+S DIVU
 S MOD
 S NEG