The MIPS backend is still full of holes, and cut-and-pasted PowerPC code, but
is beginning to look like an actual code generator.
This commit is contained in:
parent
a023fd8591
commit
1d6ecddcf4
|
@ -7,6 +7,12 @@
|
||||||
# only. It's based on the MIPS32 Instruction Set v5.04 manual (available from
|
# only. It's based on the MIPS32 Instruction Set v5.04 manual (available from
|
||||||
# https://www.mips.com/products/architectures/mips32-2/).
|
# 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
|
000000<RS-><RT-><RD->00000100000 "add" RD=gpr ',' RS=gpr ',' RT=gpr
|
||||||
001000<RS-><RT-><IMM-----------> "addi" RT=gpr ',' RT=gpr ',' IMM=e16
|
001000<RS-><RT-><IMM-----------> "addi" RT=gpr ',' RT=gpr ',' IMM=e16
|
||||||
001001<RS-><RT-><IMM-----------> "addiu" RT=gpr ',' RT=gpr ',' IMM=e16
|
001001<RS-><RT-><IMM-----------> "addiu" RT=gpr ',' RT=gpr ',' IMM=e16
|
||||||
|
|
|
@ -1,83 +1,78 @@
|
||||||
/*
|
|
||||||
* $Source$
|
|
||||||
* $State$
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Integer registers */
|
/* Integer registers */
|
||||||
|
|
||||||
0, GPR, 0, "$0",
|
0, GPR, 0, "r0",
|
||||||
0, GPR, 0, "$zero",
|
0, GPR, 0, "zero",
|
||||||
0, GPR, 1, "$1",
|
0, GPR, 1, "r1",
|
||||||
0, GPR, 1, "$at",
|
0, GPR, 1, "at",
|
||||||
0, GPR, 2, "$2",
|
0, GPR, 2, "r2",
|
||||||
0, GPR, 3, "$3",
|
0, GPR, 3, "r3",
|
||||||
0, GPR, 4, "$4",
|
0, GPR, 4, "r4",
|
||||||
0, GPR, 5, "$5",
|
0, GPR, 5, "r5",
|
||||||
0, GPR, 6, "$6",
|
0, GPR, 6, "r6",
|
||||||
0, GPR, 7, "$7",
|
0, GPR, 7, "r7",
|
||||||
0, GPR, 8, "$8",
|
0, GPR, 8, "r8",
|
||||||
0, GPR, 9, "$9",
|
0, GPR, 9, "r9",
|
||||||
0, GPR, 10, "$10",
|
0, GPR, 10, "r10",
|
||||||
0, GPR, 11, "$11",
|
0, GPR, 11, "r11",
|
||||||
0, GPR, 12, "$12",
|
0, GPR, 12, "r12",
|
||||||
0, GPR, 13, "$13",
|
0, GPR, 13, "r13",
|
||||||
0, GPR, 14, "$14",
|
0, GPR, 14, "r14",
|
||||||
0, GPR, 15, "$15",
|
0, GPR, 15, "r15",
|
||||||
0, GPR, 16, "$16",
|
0, GPR, 16, "r16",
|
||||||
0, GPR, 17, "$17",
|
0, GPR, 17, "r17",
|
||||||
0, GPR, 18, "$18",
|
0, GPR, 18, "r18",
|
||||||
0, GPR, 19, "$19",
|
0, GPR, 19, "r19",
|
||||||
0, GPR, 20, "$20",
|
0, GPR, 20, "r20",
|
||||||
0, GPR, 21, "$21",
|
0, GPR, 21, "r21",
|
||||||
0, GPR, 22, "$22",
|
0, GPR, 22, "r22",
|
||||||
0, GPR, 23, "$23",
|
0, GPR, 23, "r23",
|
||||||
0, GPR, 24, "$24",
|
0, GPR, 24, "r24",
|
||||||
0, GPR, 25, "$25",
|
0, GPR, 25, "r25",
|
||||||
0, GPR, 26, "$26",
|
0, GPR, 26, "r26",
|
||||||
0, GPR, 27, "$27",
|
0, GPR, 27, "r27",
|
||||||
0, GPR, 28, "$28",
|
0, GPR, 28, "r28",
|
||||||
0, GPR, 28, "$gp",
|
0, GPR, 28, "gp",
|
||||||
0, GPR, 29, "$29",
|
0, GPR, 29, "r29",
|
||||||
0, GPR, 29, "$sp",
|
0, GPR, 29, "sp",
|
||||||
0, GPR, 30, "$30",
|
0, GPR, 30, "r30",
|
||||||
0, GPR, 30, "$fp",
|
0, GPR, 30, "fp",
|
||||||
0, GPR, 31, "$31",
|
0, GPR, 31, "r31",
|
||||||
0, GPR, 31, "$a",
|
0, GPR, 31, "ra",
|
||||||
|
|
||||||
/* Floating-point registers */
|
/* Floating-point registers */
|
||||||
|
|
||||||
0, FPR, 0, "$f0",
|
0, FPR, 0, "f0",
|
||||||
0, FPR, 1, "$f1",
|
0, FPR, 1, "f1",
|
||||||
0, FPR, 2, "$f2",
|
0, FPR, 2, "f2",
|
||||||
0, FPR, 3, "$f3",
|
0, FPR, 3, "f3",
|
||||||
0, FPR, 4, "$f4",
|
0, FPR, 4, "f4",
|
||||||
0, FPR, 5, "$f5",
|
0, FPR, 5, "f5",
|
||||||
0, FPR, 6, "$f6",
|
0, FPR, 6, "f6",
|
||||||
0, FPR, 7, "$f7",
|
0, FPR, 7, "f7",
|
||||||
0, FPR, 8, "$f8",
|
0, FPR, 8, "f8",
|
||||||
0, FPR, 9, "$f9",
|
0, FPR, 9, "f9",
|
||||||
0, FPR, 10, "$f10",
|
0, FPR, 10, "f10",
|
||||||
0, FPR, 11, "$f11",
|
0, FPR, 11, "f11",
|
||||||
0, FPR, 12, "$f12",
|
0, FPR, 12, "f12",
|
||||||
0, FPR, 13, "$f13",
|
0, FPR, 13, "f13",
|
||||||
0, FPR, 14, "$f14",
|
0, FPR, 14, "f14",
|
||||||
0, FPR, 15, "$f15",
|
0, FPR, 15, "f15",
|
||||||
0, FPR, 16, "$f16",
|
0, FPR, 16, "f16",
|
||||||
0, FPR, 17, "$f17",
|
0, FPR, 17, "f17",
|
||||||
0, FPR, 18, "$f18",
|
0, FPR, 18, "f18",
|
||||||
0, FPR, 19, "$f19",
|
0, FPR, 19, "f19",
|
||||||
0, FPR, 20, "$f20",
|
0, FPR, 20, "f20",
|
||||||
0, FPR, 21, "$f21",
|
0, FPR, 21, "f21",
|
||||||
0, FPR, 22, "$f22",
|
0, FPR, 22, "f22",
|
||||||
0, FPR, 23, "$f23",
|
0, FPR, 23, "f23",
|
||||||
0, FPR, 24, "$f24",
|
0, FPR, 24, "f24",
|
||||||
0, FPR, 25, "$f25",
|
0, FPR, 25, "f25",
|
||||||
0, FPR, 26, "$f26",
|
0, FPR, 26, "f26",
|
||||||
0, FPR, 27, "$f27",
|
0, FPR, 27, "f27",
|
||||||
0, FPR, 28, "$f28",
|
0, FPR, 28, "f28",
|
||||||
0, FPR, 29, "$f29",
|
0, FPR, 29, "f29",
|
||||||
0, FPR, 30, "$f30",
|
0, FPR, 30, "f30",
|
||||||
0, FPR, 31, "$f31",
|
0, FPR, 31, "f31",
|
||||||
|
|
||||||
#include "tokens.y"
|
#include "tokens.y"
|
||||||
|
|
||||||
|
|
331
mach/mips/mcg/platform.c
Normal file
331
mach/mips/mcg/platform.c
Normal file
|
@ -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 : */
|
||||||
|
|
566
mach/mips/mcg/table
Normal file
566
mach/mips/mcg/table
Normal file
|
@ -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 : */
|
||||||
|
|
20
mach/mips/top/table
Normal file
20
mach/mips/top/table
Normal file
|
@ -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 ;
|
||||||
|
|
||||||
|
%%;
|
||||||
|
|
|
@ -6,23 +6,22 @@ build_as {
|
||||||
deps = { "mach/mips/as+astables" }
|
deps = { "mach/mips/as+astables" }
|
||||||
}
|
}
|
||||||
|
|
||||||
--build_mcg {
|
build_mcg {
|
||||||
-- name = "mcg",
|
name = "mcg",
|
||||||
-- arch = "powerpc",
|
arch = "mips",
|
||||||
--}
|
}
|
||||||
--
|
|
||||||
--build_top {
|
build_top {
|
||||||
-- name = "top",
|
name = "top",
|
||||||
-- arch = "powerpc",
|
arch = "mips",
|
||||||
--}
|
}
|
||||||
|
|
||||||
return installable {
|
return installable {
|
||||||
name = "tools",
|
name = "tools",
|
||||||
map = {
|
map = {
|
||||||
["$(PLATDEP)/linuxmips/as"] = "+as",
|
["$(PLATDEP)/linuxmips/as"] = "+as",
|
||||||
--["$(PLATDEP)/linuxppc/ncg"] = "+ncg",
|
["$(PLATDEP)/linuxmips/mcg"] = "+mcg",
|
||||||
--["$(PLATDEP)/linuxppc/mcg"] = "+mcg",
|
["$(PLATDEP)/linuxmips/top"] = "+top",
|
||||||
--["$(PLATDEP)/linuxppc/top"] = "+top",
|
|
||||||
["$(PLATIND)/descr/linuxmips"] = "./descr",
|
["$(PLATIND)/descr/linuxmips"] = "./descr",
|
||||||
"util/amisc+aelflod-pkg",
|
"util/amisc+aelflod-pkg",
|
||||||
"util/opt+pkg",
|
"util/opt+pkg",
|
||||||
|
|
|
@ -20,7 +20,7 @@ var PLATFORMDIR={EM}/share/ack/{PLATFORM}
|
||||||
var CPP_F=-D__unix
|
var CPP_F=-D__unix
|
||||||
var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x00400054
|
var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x00400054
|
||||||
var MACHOPT_F=-m2
|
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
|
# Override the setting in fe so that files compiled for linuxppc can see
|
||||||
# the platform-specific headers.
|
# 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
|
name be
|
||||||
from .m.g
|
from .m.g
|
||||||
to .s
|
to .s
|
||||||
program {EM}/lib/ack/{PLATFORM}/ncg
|
program {EM}/lib/ack/{PLATFORM}/mcg
|
||||||
mapflag -gdb GF=-gdb
|
mapflag -gdb GF=-gdb
|
||||||
args {GF?} <
|
args {GF?} <
|
||||||
stdout
|
stdout
|
||||||
|
@ -83,5 +83,5 @@ name cv
|
||||||
to .exe
|
to .exe
|
||||||
program {EM}/bin/aelflod
|
program {EM}/bin/aelflod
|
||||||
args -m20 -b < >
|
args -m20 -b < >
|
||||||
outfile linuxppc.exe
|
outfile linuxmips.exe
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue