The MIPS backend is still full of holes, and cut-and-pasted PowerPC code, but
authorDavid Given <dg@cowlark.com>
Sun, 2 Sep 2018 16:57:25 +0000 (18:57 +0200)
committerDavid Given <dg@cowlark.com>
Sun, 2 Sep 2018 16:57:25 +0000 (18:57 +0200)
is beginning to look like an actual code generator.

mach/mips/as/instructions.dat
mach/mips/as/mach3.c
mach/mips/mcg/platform.c [new file with mode: 0644]
mach/mips/mcg/table [new file with mode: 0644]
mach/mips/top/table [new file with mode: 0644]
plat/linuxmips/build-tools.lua
plat/linuxmips/descr

index af5209e..1f7aae7 100644 (file)
@@ -7,6 +7,12 @@
 # only. It's based on the MIPS32 Instruction Set v5.04 manual (available from
 # https://www.mips.com/products/architectures/mips32-2/).
 
+# Useful pseudoops.
+
+000000<RS->00000<RD->00000100000 "move" RD=gpr ',' RS=gpr
+
+# Core ALU instructions.
+
 000000<RS-><RT-><RD->00000100000 "add" RD=gpr ',' RS=gpr ',' RT=gpr
 001000<RS-><RT-><IMM-----------> "addi" RT=gpr ',' RT=gpr ',' IMM=e16
 001001<RS-><RT-><IMM-----------> "addiu" RT=gpr ',' RT=gpr ',' IMM=e16
index d6da5e0..0de4b37 100644 (file)
@@ -1,83 +1,78 @@
-/*
- * $Source$
- * $State$
- */
-
 /* Integer registers */
 
-0,     GPR,        0,          "$0",
-0,     GPR,        0,          "$zero",
-0,     GPR,        1,          "$1",
-0,     GPR,        1,          "$at",
-0,     GPR,        2,          "$2",
-0,     GPR,        3,          "$3",
-0,     GPR,        4,          "$4",
-0,     GPR,        5,          "$5",
-0,     GPR,        6,          "$6",
-0,     GPR,        7,          "$7",
-0,     GPR,        8,          "$8",
-0,     GPR,        9,          "$9",
-0,     GPR,        10,         "$10",
-0,     GPR,        11,         "$11",
-0,     GPR,        12,         "$12",
-0,     GPR,        13,         "$13",
-0,     GPR,        14,         "$14",
-0,     GPR,        15,         "$15",
-0,     GPR,        16,         "$16",
-0,     GPR,        17,         "$17",
-0,     GPR,        18,         "$18",
-0,     GPR,        19,         "$19",
-0,     GPR,        20,         "$20",
-0,     GPR,        21,         "$21",
-0,     GPR,        22,         "$22",
-0,     GPR,        23,         "$23",
-0,     GPR,        24,         "$24",
-0,     GPR,        25,         "$25",
-0,     GPR,        26,         "$26",
-0,     GPR,        27,         "$27",
-0,     GPR,        28,         "$28",
-0,     GPR,        28,         "$gp",
-0,     GPR,        29,         "$29",
-0,     GPR,        29,         "$sp",
-0,     GPR,        30,         "$30",
-0,     GPR,        30,         "$fp",
-0,     GPR,        31,         "$31",
-0,     GPR,        31,         "$a",
+0,     GPR,        0,          "r0",
+0,     GPR,        0,          "zero",
+0,     GPR,        1,          "r1",
+0,     GPR,        1,          "at",
+0,     GPR,        2,          "r2",
+0,     GPR,        3,          "r3",
+0,     GPR,        4,          "r4",
+0,     GPR,        5,          "r5",
+0,     GPR,        6,          "r6",
+0,     GPR,        7,          "r7",
+0,     GPR,        8,          "r8",
+0,     GPR,        9,          "r9",
+0,     GPR,        10,         "r10",
+0,     GPR,        11,         "r11",
+0,     GPR,        12,         "r12",
+0,     GPR,        13,         "r13",
+0,     GPR,        14,         "r14",
+0,     GPR,        15,         "r15",
+0,     GPR,        16,         "r16",
+0,     GPR,        17,         "r17",
+0,     GPR,        18,         "r18",
+0,     GPR,        19,         "r19",
+0,     GPR,        20,         "r20",
+0,     GPR,        21,         "r21",
+0,     GPR,        22,         "r22",
+0,     GPR,        23,         "r23",
+0,     GPR,        24,         "r24",
+0,     GPR,        25,         "r25",
+0,     GPR,        26,         "r26",
+0,     GPR,        27,         "r27",
+0,     GPR,        28,         "r28",
+0,     GPR,        28,         "gp",
+0,     GPR,        29,         "r29",
+0,     GPR,        29,         "sp",
+0,     GPR,        30,         "r30",
+0,     GPR,        30,         "fp",
+0,     GPR,        31,         "r31",
+0,     GPR,        31,         "ra",
 
 /* Floating-point registers */
 
-0,     FPR,        0,          "$f0",
-0,     FPR,        1,          "$f1",
-0,     FPR,        2,          "$f2",
-0,     FPR,        3,          "$f3",
-0,     FPR,        4,          "$f4",
-0,     FPR,        5,          "$f5",
-0,     FPR,        6,          "$f6",
-0,     FPR,        7,          "$f7",
-0,     FPR,        8,          "$f8",
-0,     FPR,        9,          "$f9",
-0,     FPR,        10,         "$f10",
-0,     FPR,        11,         "$f11",
-0,     FPR,        12,         "$f12",
-0,     FPR,        13,         "$f13",
-0,     FPR,        14,         "$f14",
-0,     FPR,        15,         "$f15",
-0,     FPR,        16,         "$f16",
-0,     FPR,        17,         "$f17",
-0,     FPR,        18,         "$f18",
-0,     FPR,        19,         "$f19",
-0,     FPR,        20,         "$f20",
-0,     FPR,        21,         "$f21",
-0,     FPR,        22,         "$f22",
-0,     FPR,        23,         "$f23",
-0,     FPR,        24,         "$f24",
-0,     FPR,        25,         "$f25",
-0,     FPR,        26,         "$f26",
-0,     FPR,        27,         "$f27",
-0,     FPR,        28,         "$f28",
-0,     FPR,        29,         "$f29",
-0,     FPR,        30,         "$f30",
-0,     FPR,        31,         "$f31",
+0,     FPR,        0,          "f0",
+0,     FPR,        1,          "f1",
+0,     FPR,        2,          "f2",
+0,     FPR,        3,          "f3",
+0,     FPR,        4,          "f4",
+0,     FPR,        5,          "f5",
+0,     FPR,        6,          "f6",
+0,     FPR,        7,          "f7",
+0,     FPR,        8,          "f8",
+0,     FPR,        9,          "f9",
+0,     FPR,        10,         "f10",
+0,     FPR,        11,         "f11",
+0,     FPR,        12,         "f12",
+0,     FPR,        13,         "f13",
+0,     FPR,        14,         "f14",
+0,     FPR,        15,         "f15",
+0,     FPR,        16,         "f16",
+0,     FPR,        17,         "f17",
+0,     FPR,        18,         "f18",
+0,     FPR,        19,         "f19",
+0,     FPR,        20,         "f20",
+0,     FPR,        21,         "f21",
+0,     FPR,        22,         "f22",
+0,     FPR,        23,         "f23",
+0,     FPR,        24,         "f24",
+0,     FPR,        25,         "f25",
+0,     FPR,        26,         "f26",
+0,     FPR,        27,         "f27",
+0,     FPR,        28,         "f28",
+0,     FPR,        29,         "f29",
+0,     FPR,        30,         "f30",
+0,     FPR,        31,         "f31",
 
 #include "tokens.y"
 
diff --git a/mach/mips/mcg/platform.c b/mach/mips/mcg/platform.c
new file mode 100644 (file)
index 0000000..23b01f1
--- /dev/null
@@ -0,0 +1,331 @@
+#include "mcg.h"
+
+/* mcg stack frames are laid out as:
+ *
+ * |    ...params...
+ * |  --------------- <- ab
+ * |       old FR
+ * |       old FP
+ * |  --------------- <- fp (a.k.a. lb) 
+ * |      locals
+ * |  ---------------
+ * |      spills
+ * |  --------------- <- sb
+ * |     saved regs
+ * |  --------------- <- sp, rb
+ * V  ...user area...
+ *
+ * st indexes up; lb indexes down.
+ *
+ * Note that [fp] == old_fp and ab == fp + 8.
+ */
+
+static ARRAYOF(struct hreg) saved_regs;
+
+void platform_calculate_offsets(void)
+{
+    int i;
+
+    saved_regs.count = 0;
+    for (i=0; i<current_proc->usedregs.count; i++)
+    {
+        struct hreg* hreg = current_proc->usedregs.item[i];
+
+        if (!(hreg->attrs & burm_volatile_ATTR) &&
+            ((hreg->attrs & burm_long_ATTR) || (hreg->attrs & burm_double_ATTR)))
+        {
+            hreg->offset = current_proc->saved_size;
+            current_proc->saved_size += 8;
+            array_append(&saved_regs, hreg);
+        }
+    }
+    for (i=0; i<current_proc->usedregs.count; i++)
+    {
+        struct hreg* hreg = current_proc->usedregs.item[i];
+
+        if (!(hreg->attrs & burm_volatile_ATTR) &&
+            ((hreg->attrs & burm_int_ATTR) || (hreg->attrs & burm_float_ATTR)))
+        {
+            hreg->offset = current_proc->saved_size;
+            current_proc->saved_size += 4;
+            array_append(&saved_regs, hreg);
+        }
+    }
+
+       current_proc->fp_to_ab = 8;
+       current_proc->fp_to_lb = 0;
+       current_proc->fp_to_sb = -(current_proc->locals_size + current_proc->spills_size);
+    current_proc->fp_to_rb = current_proc->fp_to_sb - current_proc->saved_size;
+}
+
+struct hop* platform_prologue(void)
+{
+    int i;
+    int spoffset = current_proc->saved_size + current_proc->spills_size +
+        current_proc->locals_size;
+       struct hop* hop = new_hop(current_proc->entry, NULL);
+
+    hop_add_insel(hop, "! locals_size = %d", current_proc->locals_size);
+    hop_add_insel(hop, "! spills_size = %d", current_proc->spills_size);
+    hop_add_insel(hop, "! saved_size = %d", current_proc->saved_size);
+    hop_add_insel(hop, "! params @ fp+%d", current_proc->fp_to_ab);
+    hop_add_insel(hop, "! lr @ fp+4");  
+    hop_add_insel(hop, "! fp @ fp+0");  
+    hop_add_insel(hop, "! locals @ fp-%d to fp+0",
+        current_proc->locals_size);
+    hop_add_insel(hop, "! spills @ fp-%d to fp-%d",
+        -current_proc->fp_to_sb, current_proc->locals_size);
+    for (i=saved_regs.count-1; i>=0; i--)
+    {
+        struct hreg* hreg = saved_regs.item[i];
+        hop_add_insel(hop, "! %s @ fp-%d",
+            hreg->id, -(current_proc->fp_to_rb + hreg->offset));
+    }
+
+       hop_add_insel(hop, "addiu sp, sp, %d", -(spoffset + 8));
+       hop_add_insel(hop, "sw fp, %d(sp)", spoffset + 0);
+       hop_add_insel(hop, "sw ra, %d(sp)", spoffset + 4);
+       hop_add_insel(hop, "addiu fp, sp, %d", spoffset);
+
+    /* Saved reg offsets are negative. */
+    for (i=0; i<saved_regs.count; i++)
+    {
+        struct hreg* hreg = saved_regs.item[i];
+        if (hreg->attrs & burm_int_ATTR)
+            hop_add_insel(hop, "sw %H, %d(fp)",
+                hreg, current_proc->fp_to_rb + hreg->offset);
+        else if (hreg->attrs & burm_float_ATTR)
+            hop_add_insel(hop, "swc1 %H, %d(fp)",
+                hreg, current_proc->fp_to_rb + hreg->offset);
+    }
+       return hop;
+}
+
+struct hop* platform_epilogue(void)
+{
+       struct hop* hop = new_hop(current_proc->exit, NULL);
+    int i;
+
+    for (i=0; i<saved_regs.count; i++)
+    {
+        struct hreg* hreg = saved_regs.item[i];
+        if (hreg->attrs & burm_int_ATTR)
+            hop_add_insel(hop, "lw %H, %d(fp)",
+                hreg, current_proc->fp_to_rb + hreg->offset);
+        else if (hreg->attrs & burm_float_ATTR)
+            hop_add_insel(hop, "lwc1 %H, %d(fp)",
+                hreg, current_proc->fp_to_rb + hreg->offset);
+    }
+
+    hop_add_insel(hop, "lw ra, 4(fp)");
+    hop_add_insel(hop, "lw at, 0(fp)"); /* load old fp */
+    hop_add_insel(hop, "addiu sp, fp, %d", current_proc->fp_to_ab);
+    hop_add_insel(hop, "move fp, at");
+    hop_add_insel(hop, "jr ra");
+
+       return hop;
+}
+
+struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest)
+{
+    struct hop* hop = new_hop(bb, NULL);
+
+    if ((src->attrs & TYPE_ATTRS) != (dest->attrs & TYPE_ATTRS))
+    {
+        assert(!src->is_stacked);
+        assert(!dest->is_stacked);
+
+        switch (src->attrs & TYPE_ATTRS)
+        {
+            case burm_int_ATTR:
+                hop_add_insel(hop, "stwu %H, -4(sp)", src);
+                break;
+
+            case burm_long_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;
+
+            case burm_double_ATTR:
+                hop_add_insel(hop, "stfdu %H, -8(sp)", src);
+                break;
+
+            default:
+                goto nomove;
+        }
+
+        switch (dest->attrs & TYPE_ATTRS)
+        {
+            case burm_int_ATTR:
+                hop_add_insel(hop, "lwz %H, 0(sp)", dest);
+                break;
+
+            case burm_long_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;
+
+            case burm_double_ATTR:
+                hop_add_insel(hop, "lfd %H, 0(sp)", dest);
+                break;
+
+            default:
+                goto nomove;
+        }
+
+        switch (dest->attrs & TYPE_ATTRS)
+        {
+            case burm_int_ATTR:
+            case burm_float_ATTR:
+                hop_add_insel(hop, "addi sp, sp, 4");
+                break;
+
+            case burm_double_ATTR:
+            case burm_long_ATTR:
+                hop_add_insel(hop, "addi sp, sp, 8");
+                break;
+
+            default:
+                goto nomove;
+        }
+    }
+    else
+    {
+        uint32_t type = src->attrs & TYPE_ATTRS;
+
+        if (!src->is_stacked && dest->is_stacked)
+        {
+            switch (type)
+            {
+                case burm_int_ATTR:
+                    hop_add_insel(hop, "stw %H, %S(fp) ! %H", src, dest, dest);
+                    break;
+
+                case burm_float_ATTR:
+                    hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest);
+                    break;
+
+                case burm_long_ATTR:
+                    hop_add_insel(hop, "stw %0H, 4+%S(fp) ! %H", src, dest, dest);
+                    hop_add_insel(hop, "stw %1H, 0+%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:
+                    goto nomove;
+            }
+        }
+        else if (src->is_stacked && !dest->is_stacked)
+        {
+            switch (type)
+            {
+                case burm_int_ATTR:
+                    hop_add_insel(hop, "lwz %H, %S(fp) ! %H", dest, src, src);
+                    break;
+
+                case burm_float_ATTR:
+                    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:
+                    goto nomove;
+            }
+        }
+        else if (!src->is_stacked && !dest->is_stacked)
+        {
+            switch (type)
+            {
+                case burm_int_ATTR:
+                    hop_add_insel(hop, "move %H, %H", dest, src);
+                    break;
+
+                case burm_long_ATTR:
+                    hop_add_insel(hop, "move %0H, %0H", dest, src);
+                    hop_add_insel(hop, "move %1H, %1H", dest, src);
+                    break;
+
+                case burm_float_ATTR:
+                case burm_double_ATTR:
+                    hop_add_insel(hop, "fmr %H, %H", dest, src);
+                    break;
+
+                default:
+                    goto nomove;
+            }
+        }
+        else
+            goto nomove;
+    }
+
+    return hop;
+
+nomove:
+    fatal("cannot move %s to %s", src->id, dest->id);
+}
+
+struct hop* platform_swap(struct basicblock* bb, struct hreg* src, struct hreg* dest)
+{
+    struct hop* hop = new_hop(bb, NULL);
+
+    assert(!src->is_stacked);
+    assert(!dest->is_stacked);
+    assert((src->attrs & TYPE_ATTRS) == (dest->attrs & TYPE_ATTRS));
+    
+    switch (src->attrs & TYPE_ATTRS)
+    {
+        case burm_int_ATTR:
+            hop_add_insel(hop, "mr r0, %H", src);
+            hop_add_insel(hop, "mr %H, %H", src, dest);
+            hop_add_insel(hop, "mr %H, r0", dest);
+            break;
+
+        case burm_long_ATTR:
+            hop_add_insel(hop, "mr r0, %0H", src);
+            hop_add_insel(hop, "mr %0H, %0H", src, dest);
+            hop_add_insel(hop, "mr %0H, r0", dest);
+
+            hop_add_insel(hop, "mr r0, %1H", src);
+            hop_add_insel(hop, "mr %1H, %1H", src, dest);
+            hop_add_insel(hop, "mr %1H, r0", dest);
+            break;
+
+        case burm_float_ATTR:
+        case burm_double_ATTR:
+            hop_add_insel(hop, "fmr f0, %H", src);
+            hop_add_insel(hop, "fmr %H, %H", src, dest);
+            hop_add_insel(hop, "fmr %H, f0", dest);
+            break;
+    }
+
+    return hop;
+}
+
+const char* platform_label(const char* label)
+{
+    /* Labels starting with . are internal, not exported, and don't need mangling. */
+
+    if (label[0] == '.')
+        return label;
+
+    /* Otherwise, mangle. */
+
+    return aprintf("_%s", label);
+}
+
+/* vim: set sw=4 ts=4 expandtab : */
+
diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table
new file mode 100644 (file)
index 0000000..e255372
--- /dev/null
@@ -0,0 +1,566 @@
+REGISTERS
+
+    /* Registers are allocated top down. The odd order below is to make sure
+     * that cheap registers get allocated first.
+     *
+     * Attributes may have at most one of: int, float, long, double. These
+     * indicate that the register is used to store a value of that type. If
+     * your register can store more than one type, create an alias. Registers
+     * with none of these cannot be copied by the code generator (and so cannot
+     * be moved from register to register or spilt).
+     */
+
+       r4 named("r4")                                int volatile;
+       r5 named("r5")                                int volatile;
+       r6 named("r6")                                int volatile;
+       r7 named("r7")                                int volatile;
+       r8 named("r8")                                int volatile;
+       r9 named("r9")                                int volatile;
+       r10 named("r10")                              int volatile;
+       r11 named("r11")                              int volatile;
+       r12 named("r12")                              int volatile;
+       r13 named("r13")                              int volatile;
+       r14 named("r14")                              int volatile;
+       r15 named("r15")                              int volatile;
+       r24 named("r24")                              int volatile;
+       r25 named("r25")                              int volatile;
+       r2 named("r2")                                int volatile iret;
+       r3 named("r3")                                int volatile;
+
+       r17 named("r16")                              int;
+       r18 named("r18")                              int;
+       r19 named("r19")                              int;
+       r20 named("r20")                              int;
+       r21 named("r21")                              int;
+       r22 named("r22")                              int;
+       r23 named("r23")                              int;
+
+       r4r5    named("r4", "r5")   aliases(r4,  r5)  long volatile;
+       r6r7    named("r6", "r7")   aliases(r6,  r7)  long volatile;
+       r8r9    named("r8", "r9")   aliases(r8,  r9)  long volatile;
+       r10r11  named("r10", "r11") aliases(r10, r11) long volatile;
+       r12r13  named("r12", "r13") aliases(r12, r13) long volatile;
+       r14r15  named("r14", "r15") aliases(r14, r15) long volatile;
+       r24r25  named("r24", "r25") aliases(r24, r25) long volatile;
+       r2r3    named("r2", "r3")   aliases(r2,  r3)  long volatile lret;
+
+    zero named("zero")                            zero int volatile;
+
+    f0 float;
+    d0 double;
+
+DECLARATIONS
+
+    ubyteX;   /* bottom 8 bits valid, the rest undefined */
+    ubyte0;   /* bottom 8 bits valid, the rest 0 */
+    ushortX;  /* bottom 16 bits valid, the rest undefined */
+    ushort0;  /* bottom 16 bits valid, the rest 0 */
+
+       address fragment;
+
+
+
+PATTERNS
+
+/* Special */
+
+       PAIR(BLOCK.I, BLOCK.I);
+
+
+
+/* Miscellaneous special things */
+
+       PUSH.I(in:(int)reg)
+               emit "addiu sp, sp, -4"
+               emit "sw %in, 0(sp)"
+               cost 8;
+
+    PUSH.L(in:(long)reg)
+        emit "addiu sp, sp, -8"
+        emit "sw %in.0, 0(sp)"
+        emit "sw %in.1, 4(sp)"
+        cost 12;
+
+       out:(int)reg = POP.I
+               emit "lw %out, 0(sp)"
+        emit "addiu sp, sp, 4"
+               cost 8;
+
+    out:(long)reg = POP.L
+        emit "lw %out.0, 4(sp)"
+        emit "lw %out.1, 0(sp)"
+        emit "addiu sp, sp, 8"
+        cost 12;
+
+       SETRET.I(in:(iret)reg)
+               emit "! setret4"
+               cost 1;
+
+    SETRET.L(in:(lret)reg)
+        emit "! setret8"
+        cost 1;
+
+       STACKADJUST.I(delta:CONST.I)
+        when signed_constant(%delta, 16)
+               emit "addiu sp, sp, $delta"
+               cost 4;
+
+       STACKADJUST.I(in:(int)reg)
+               emit "addu sp, sp, %in"
+               cost 4;
+
+       STACKADJUST.I(NEG.I(in:(int)reg))
+               emit "subu sp, sp, %in"
+               cost 4;
+
+    out:(int)reg = GETFP.I
+        emit "move %out, fp"
+        cost 4;
+
+    SETFP.I(in:(int)reg)
+        emit "move fp, %in"
+        cost 4;
+
+    out:(int)reg = CHAINFP.I(in:(int)reg)
+        emit "lw %out, 0(%in)"
+        cost 4;
+
+    out:(int)reg = FPTOAB.I(GETFP.I)
+        emit "addiu %out, fp, 8"
+        cost 4;
+
+    out:(int)reg = FPTOAB.I(in:(int)reg)
+        emit "addiu %out, %in, 8"
+        cost 4;
+
+    out:(int)reg = FPTOLB.I(in:(int)reg)
+        with %out == %in
+        cost 1;
+
+    out:(int)reg = GETSP.I
+        emit "move %out, sp"
+        cost 4;
+
+    SETSP.I(in:(int)reg)
+        emit "move sp, %in"
+        cost 4;
+
+    out:(int)reg = ANY.I
+        cost 1;
+
+    out:(long)reg = ANY.L
+        cost 1;
+
+
+
+/* Memory operations */
+
+    /* Stores */
+
+       STORE.L(addr:address, value:(long)reg)
+               emit "sw %value.0, 4+%addr"
+               emit "sw %value.1, 0+%addr"
+               cost 8;
+
+       STORE.I(addr:address, value:(int)reg)
+               emit "sw %value, %addr"
+               cost 4;
+
+       STOREH.I(addr:address, value:(int)ushortX)
+               emit "sh %value, %addr"
+               cost 4;
+
+    STOREB.I(addr:address, value:(int)ubyteX)
+               emit "sb %value, %addr"
+               cost 4;
+
+    /* Loads */
+
+       out:(int)reg = LOAD.I(addr:address)
+               emit "lw %out, %addr"
+               cost 4;
+
+    /* We can't just load directly because %out.0 and %addr might share
+     * a register, resulting in %addr being corrupted before %out.1 is
+     * loaded. */
+    out:(long)reg = LOAD.L(addr:address)
+        emit "lw at, 4+%addr"
+        emit "lw %out.1, 0+%addr"
+        emit "move %out.0, at"
+        cost 12;
+
+       out:(int)ushort0 = LOADH.I(addr:address)
+               emit "lh %out, %addr"
+               cost 4;
+
+       out:(int)ubyte0 = LOADB.I(addr:address)
+               emit "lb %out, %addr"
+               cost 4;
+
+    /* ubyte intrinsics */
+
+    out:(int)ubyteX = in:(int)ubyte0
+        with %out == %in
+        emit "! ubyte0 -> ubyteX"
+        cost 1;
+
+    out:(int)ubyte0 = in:(int)ubyteX
+        emit "andiu %out, %in, 0xff ! ubyteX -> ubyte0"
+        cost 4;
+
+    out:(int)reg = in:(int)ubyte0
+        with %out == %in
+        emit "! ubyte0 -> reg"
+        cost 4;
+
+    out:(int)ubyteX = in:(int)reg
+        with %out == %in
+        emit "! reg -> ubyteX"
+        cost 1;
+
+    /* ushort intrinsics */
+
+    out:(int)ushortX = in:(int)ushort0
+        with %out == %in
+        emit "! ushort0 -> ushortX"
+        cost 1;
+
+    out:(int)ushort0 = in:(int)ushortX
+        emit "andiu %out, %in, 0xffff ! ushortX -> ushort0"
+        cost 4;
+
+    out:(int)reg = in:(int)ushort0
+        with %out == %in
+        emit "! ushort0 -> reg"
+        cost 4;
+
+    out:(int)ushortX = in:(int)reg
+        with %out == %in
+        emit "! reg -> ushortX"
+        cost 1;
+
+
+
+/* Extensions and conversions */
+
+    out:(int)reg = EXTENDB.I(in:(int)reg)
+        emit "seb %out, %in"
+        cost 4;
+
+    out:(int)reg = EXTENDH.I(in:(int)reg)
+        emit "seh %out, %in"
+        cost 4;
+
+    out:(int)reg = FROMSI.I(in:(int)reg)
+        with %out == %in
+        emit "! FROMSI.I(int) -> int"
+        cost 1;
+
+    out:(int)reg = FROMUI.I(in:(int)reg)
+        with %out == %in
+        emit "! FROMUI.I(int) -> int"
+        cost 1;
+
+    out:(long)reg = FROMSI.L(in:(int)reg)
+        emit "move %out.0, %in"
+        emit "sra %out.1, %in, 31"
+        cost 8;
+
+    out:(long)reg = FROMUI.L(in:(int)reg)
+        emit "mr %out.0, %in"
+        emit "li %out.1, 0"
+        cost 8;
+
+    out:(lret)reg = FROMIPAIR.L(in1:(int)reg, in2:(int)reg)
+        emit "move %out.0, %in1"
+        emit "move %out.1, %in2"
+        cost 8;
+    
+    out:(int)reg = FROML0.I(in:(long)reg)
+        emit "move %out, %in.0"
+        cost 4;
+
+    out:(int)reg = FROML1.I(in:(long)reg)
+        emit "move %out, %in.1"
+        cost 4;
+
+
+
+/* Locals */
+
+       out:(int)reg = in:LOCAL.I
+               emit "addiu %out, fp, $in"
+               cost 4;
+
+       address = in:LOCAL.I
+               emit "$in(fp)";
+
+
+
+/* Memory addressing modes */
+
+       address = ADD.I(addr:(int)reg, offset:CONST.I)
+        when signed_constant(%offset, 16)
+               emit "$offset(%addr)";
+
+       address = addr:(int)reg
+               emit "0(%addr)";
+
+
+
+/* Branches */
+
+       JUMP(addr:BLOCK.I)
+               emit "b $addr"
+        emit "nop"
+               cost 8;
+
+       FARJUMP(addr:LABEL.I)
+        with corrupted(volatile)
+               emit "b $addr"
+        emit "nop"
+               cost 8;
+
+    JUMP(dest:(int)reg)
+        emit "jr %dest"
+        emit "nop"
+        cost 8;
+
+       CJUMPEQ(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I))
+        emit "beq %left, %right, $true"
+        emit "nop"
+        emit "b $false"
+        emit "nop"
+        cost 16;
+
+       CJUMPLT(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I))
+        emit "slt at, %left, %right"
+        emit "bne at, zero, $true"
+        emit "nop"
+        emit "b $false"
+        emit "nop"
+        cost 20;
+
+       CJUMPLT(COMPAREUI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I))
+        emit "sltu at, %left, %right"
+        emit "bne at, zero, $true"
+        emit "nop"
+        emit "b $false"
+        emit "nop"
+        cost 20;
+
+       CJUMPLT(COMPARESI.I(left:(int)reg, right:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I))
+        when specific_constant(%right, 0)
+        emit "bltz %left, $true"
+        emit "nop"
+        emit "b $false"
+        emit "nop"
+        cost 16;
+
+       CJUMPLE(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I))
+        emit "sle at, %left, %right"
+        emit "bne at, zero, $true"
+        emit "nop"
+        emit "b $false"
+        emit "nop"
+        cost 20;
+
+       CJUMPLE(COMPAREUI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I))
+        emit "sleu at, %left, %right"
+        emit "bne at, zero, $true"
+        emit "nop"
+        emit "b $false"
+        emit "nop"
+        cost 20;
+
+       CJUMPLE(COMPARESI.I(left:(int)reg, right:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I))
+        when specific_constant(%right, 0)
+        emit "blez %left, $true"
+        emit "nop"
+        emit "b $false"
+        emit "nop"
+        cost 16;
+
+    COMPAREUI.I(left:(int)reg, right:(int)reg);
+
+    #define CALLLABEL(insn) \
+        insn (dest:LABEL.I) \
+            with corrupted(volatile) \
+            emit "bal $dest" \
+            emit "nop" \
+            cost 8;
+
+    CALLLABEL(CALL)
+    out:(iret)reg = CALLLABEL(CALL.I)
+    out:(lret)reg = CALLLABEL(CALL.L)
+
+    #define CALLINDIRECT(insn) \
+        insn (dest:(int)reg) \
+            with corrupted(volatile) \
+            emit "jalr %dest" \
+            emit "nop" \
+            cost 8;
+
+    CALLINDIRECT(CALL)
+    out:(iret)reg = CALLINDIRECT(CALL.I)
+    out:(lret)reg = CALLINDIRECT(CALL.L)
+
+    JUMP(dest:LABEL.I)
+        emit "b $dest"
+        emit "nop"
+        cost 8;
+
+
+
+/* Comparisons */
+
+       /* The COMPARE nodes return tristate integer values; -1, 0 or 1. */
+
+    out:(int)reg = COMPARESI.I(left:(int)reg, right:(int)reg)
+        emit "slt at, %left, %right"
+        emit "bne at, zero, 1f"
+        emit "li %out, -1"
+        emit "slt %out, %right, %left"
+        emit "1:"
+        cost 20;
+
+    out:(int)reg = COMPAREUI.I(left:(int)reg, right:(int)reg)
+        emit "sltu at, %left, %right"
+        emit "bne at, zero, 1f"
+        emit "li %out, -1"
+        emit "sltu %out, %right, %left"
+        emit "1:"
+        cost 20;
+
+/* Booleans */
+
+       /* If 0 then 1, else 0 */
+       out:(int)reg = IFEQ.I(in:(int)reg)
+               emit "sleu %out, %in, zero"
+               cost 4;;
+
+       /* If -1 then 1, else 0 */
+       out:(int)reg = IFLT.I(in:(int)reg)
+               emit "slt %out, %in, zero"
+               cost 4;
+
+       /* If 1 or 0 then 1, else 0 */
+       out:(int)reg = IFLE.I(in:(int)reg)
+               emit "sle %out, %in, zero"
+               cost 4;
+
+
+
+/* Conversions */
+
+#if 0
+    out:(int)reg = CIU44(in:(int)reg)
+        with %out == %in
+        emit "! ciu44"
+        cost 4;
+
+    out:(int)reg = CUI44(in:(int)reg)
+        with %out == %in
+        emit "! cui44"
+        cost 4;
+#endif
+
+/* ALU operations */
+
+       /* reg + reg */
+    #define ALUR(name, instr) \
+        out:(int)reg = name(left:(int)reg, right:(int)reg) \
+            emit instr " %out, %left, %right"              \
+            cost 4;                                        \
+
+       /* reg + const */
+    #define ALUC(name, instr) \
+        out:(int)reg = name(left:(int)reg, right:CONST.I)  \
+            when signed_constant(%right, 16)               \
+            emit instr " %out, %left, $right"              \
+            cost 4;                                        \
+
+       /* const + reg */
+    #define ALUC_reversed(name, instr) \
+        out:(int)reg = name(left:CONST.I, right:(int)reg)  \
+            when signed_constant(%left, 16)                \
+            emit instr " %out, %right, $left"              \
+            cost 4;                                        \
+
+       /* reg + const AND const + reg */
+    #define ALUCC(name, instr) \
+        ALUC(name, instr) \
+        ALUC_reversed(name, instr)
+
+    ALUR(ADD.I, "addu")
+    ALUCC(ADD.I, "addiu")
+
+       out:(int)reg = SUB.I(left:(int)reg, right:(int)reg)
+               emit "subu %out, %right, %left"
+               cost 4;
+
+       out:(int)reg = SUB.I(left:(int)reg, right:CONST.I)
+               emit "addiu %out, %left, -[$right]"
+               cost 4;
+
+       out:(int)reg = MOD.I(left:(int)reg, right:(int)reg)
+               emit "div %left, %right"
+               emit "mfhi %out"
+               cost 8;
+
+       out:(int)reg = MODU.I(left:(int)reg, right:(int)reg)
+               emit "divu %left, %right"
+               emit "mfhi %out"
+               cost 8;
+
+    ALUR(MUL.I, "mul")
+
+    ALUR(DIV.I, "divw")
+    ALUR(DIVU.I, "divwu")
+
+    ALUR(ASL.I, "sll")
+    ALUC(ASL.I, "sllv")
+    ALUR(ASR.I, "sra")
+    ALUC(ASR.I, "srav")
+
+    ALUR(LSL.I, "sll")
+    ALUC(LSL.I, "sllv")
+    ALUR(LSR.I, "srl")
+    ALUC(LSR.I, "srlv")
+
+    out:(int)reg = NEG.I(left:(int)reg)
+        emit "neg %out, %left"
+        cost 4;
+
+    out:(int)reg = NOT.I(in:(int)reg)
+        emit "nor %out, %in, %in"
+        cost 4;
+
+    ALUR(AND.I, "and")
+    ALUCC(AND.I, "andi.")
+
+    ALUR(OR.I, "or")
+    ALUCC(OR.I, "ori")
+
+    ALUR(EOR.I, "xor")
+    ALUCC(EOR.I, "xori")
+
+       out:(int)reg = value:LABEL.I
+               emit "li32 %out, $value"
+               cost 4;
+
+       out:(int)reg = value:BLOCK.I
+               emit "li32 %out, $value"
+               cost 4;
+
+       out:(int)reg = value:CONST.I
+               emit "li %out, $value"
+               cost 4;
+
+       out:(zero)reg = value:CONST.I
+        when specific_constant(%value, 0)
+               cost 1;
+
+
+/* vim: set sw=4 ts=4 expandtab : */
+
diff --git a/mach/mips/top/table b/mach/mips/top/table
new file mode 100644 (file)
index 0000000..8f6a5d6
--- /dev/null
@@ -0,0 +1,20 @@
+
+/* MIPS table for ACK target optimizer */
+
+MAXOP 5;
+LABEL_STARTER '.';
+
+%%;
+
+X, Y, Z                      { TRUE };
+
+%%;
+
+/* Whitespace is significant here! */
+
+addiu RNZ, RNZ, 0            -> ;
+
+b X : nop : labdef X         -> labdef X ;
+
+%%;
+
index 04a385d..92167ba 100644 (file)
@@ -6,23 +6,22 @@ build_as {
        deps = { "mach/mips/as+astables" }
 }
 
---build_mcg {
---     name = "mcg",
---     arch = "powerpc",
---}
---
---build_top {
---     name = "top",
---     arch = "powerpc",
---}
+build_mcg {
+       name = "mcg",
+       arch = "mips",
+}
+
+build_top {
+       name = "top",
+       arch = "mips",
+}
 
 return installable {
        name = "tools",
        map = {
                ["$(PLATDEP)/linuxmips/as"] = "+as",
-               --["$(PLATDEP)/linuxppc/ncg"] = "+ncg",
-               --["$(PLATDEP)/linuxppc/mcg"] = "+mcg",
-               --["$(PLATDEP)/linuxppc/top"] = "+top",
+               ["$(PLATDEP)/linuxmips/mcg"] = "+mcg",
+               ["$(PLATDEP)/linuxmips/top"] = "+top",
                ["$(PLATIND)/descr/linuxmips"] = "./descr",
                "util/amisc+aelflod-pkg",
                "util/opt+pkg",
index 7ddaf94..ad7f518 100644 (file)
@@ -20,7 +20,7 @@ var PLATFORMDIR={EM}/share/ack/{PLATFORM}
 var CPP_F=-D__unix
 var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x00400054
 var MACHOPT_F=-m2
-var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr
+#var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr
 
 # Override the setting in fe so that files compiled for linuxppc can see
 # the platform-specific headers.
@@ -30,7 +30,7 @@ var C_INCLUDES=-I{EM}/share/ack/linux/include -I{EM}/share/ack/include/ansi
 name be
        from .m.g
        to .s
-       program {EM}/lib/ack/{PLATFORM}/ncg
+       program {EM}/lib/ack/{PLATFORM}/mcg
        mapflag -gdb GF=-gdb
        args {GF?} <
        stdout
@@ -83,5 +83,5 @@ name cv
        to .exe
        program {EM}/bin/aelflod
        args -m20 -b < >
-       outfile linuxppc.exe
+       outfile linuxmips.exe
 end