Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 140 additions & 24 deletions mach/mips/mcg/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,44 +250,160 @@ struct hop* platform_move(struct basicblock* bb, struct vreg* vreg, struct hreg*
fatal("cannot move %s to %s", src->id, dest->id);
}

struct hop* platform_swap(struct basicblock* bb, struct hreg* src, struct hreg* dest)
static void swap_reg_and_stack(struct hop* hop, struct hreg* reg, struct hreg* stack)
{
struct hop* hop = new_hop(bb, NULL);

tracef('R', "R: swap of %s to %s\n", src->id, dest->id);
assert(!src->is_stacked);
assert(!dest->is_stacked);
assert((src->attrs & TYPE_ATTRS) == (dest->attrs & TYPE_ATTRS));

switch (src->attrs & TYPE_ATTRS)
switch (reg->attrs & TYPE_ATTRS)
{
case burm_int_ATTR:
hop_add_insel(hop, "mov at, %H", src);
hop_add_insel(hop, "mov %H, %H", src, dest);
hop_add_insel(hop, "mov %H, at", dest);
hop_add_insel(hop, "mov at, %H", reg);
hop_add_insel(hop, "lw %H, %S(fp) ! %H", reg, stack, stack);
hop_add_insel(hop, "sw at, %S(fp) ! %H", stack, stack);
break;

case burm_long_ATTR:
hop_add_insel(hop, "mov at, %0H", src);
hop_add_insel(hop, "mov %0H, %0H", src, dest);
hop_add_insel(hop, "mov %0H, at", dest);
hop_add_insel(hop, "mov at, %0H", reg);
hop_add_insel(hop, "lw %0H, 0+%S(fp) ! %H", reg, stack, stack);
hop_add_insel(hop, "sw at, 0+%S(fp) ! %H", stack, stack);

hop_add_insel(hop, "mov at, %1H", src);
hop_add_insel(hop, "mov %1H, %1H", src, dest);
hop_add_insel(hop, "mov %1H, at", dest);
hop_add_insel(hop, "mov at, %1H", reg);
hop_add_insel(hop, "lw %1H, 4+%S(fp) ! %H", reg, stack, stack);
hop_add_insel(hop, "sw at, 4+%S(fp) ! %H", stack, stack);
break;

case burm_float_ATTR:
hop_add_insel(hop, "mov.s f30, %H", src);
hop_add_insel(hop, "mov.s %H, %H", src, dest);
hop_add_insel(hop, "mov.s %H, f30", dest);
hop_add_insel(hop, "mov.s f30, %H", reg);
hop_add_insel(hop, "lwc1 %H, %S(fp) ! %H", reg, stack, stack);
hop_add_insel(hop, "swc1 f30, %S(fp) ! %H", stack, stack);
break;

case burm_double_ATTR:
hop_add_insel(hop, "mov.d f30, %H", src);
hop_add_insel(hop, "mov.d %H, %H", src, dest);
hop_add_insel(hop, "mov.d %H, f30", dest);
hop_add_insel(hop, "mov.d f30, %H", reg);
hop_add_insel(hop, "ldc1 %H, %S(fp) ! %H", reg, stack, stack);
hop_add_insel(hop, "sdc1 f30, %S(fp) ! %H", stack, stack);
break;

default:
fatal("cannot swap %s and %s", reg->id, stack->id);
}
}

static void swap_stack_and_stack(struct hop* hop, struct hreg* src, struct hreg* dest)
{
switch (src->attrs & TYPE_ATTRS)
{
case burm_int_ATTR:
case burm_float_ATTR:
hop_add_insel(hop, "addiu sp, sp, -4");
if (src->attrs & burm_int_ATTR)
{
hop_add_insel(hop, "lw at, %S(fp) ! %H", src, src);
hop_add_insel(hop, "sw at, 0(sp)");
hop_add_insel(hop, "lw at, %S(fp) ! %H", dest, dest);
hop_add_insel(hop, "sw at, %S(fp) ! %H", src, src);
hop_add_insel(hop, "lw at, 0(sp)");
hop_add_insel(hop, "sw at, %S(fp) ! %H", dest, dest);
}
else
{
hop_add_insel(hop, "lwc1 f30, %S(fp) ! %H", src, src);
hop_add_insel(hop, "swc1 f30, 0(sp)");
hop_add_insel(hop, "lwc1 f30, %S(fp) ! %H", dest, dest);
hop_add_insel(hop, "swc1 f30, %S(fp) ! %H", src, src);
hop_add_insel(hop, "lwc1 f30, 0(sp)");
hop_add_insel(hop, "swc1 f30, %S(fp) ! %H", dest, dest);
}
hop_add_insel(hop, "addiu sp, sp, 4");
break;

case burm_long_ATTR:
case burm_double_ATTR:
hop_add_insel(hop, "addiu sp, sp, -8");
if (src->attrs & burm_long_ATTR)
{
hop_add_insel(hop, "lw at, 0+%S(fp) ! %H", src, src);
hop_add_insel(hop, "sw at, 0(sp)");
hop_add_insel(hop, "lw at, 4+%S(fp) ! %H", src, src);
hop_add_insel(hop, "sw at, 4(sp)");

hop_add_insel(hop, "lw at, 0+%S(fp) ! %H", dest, dest);
hop_add_insel(hop, "sw at, 0+%S(fp) ! %H", src, src);
hop_add_insel(hop, "lw at, 4+%S(fp) ! %H", dest, dest);
hop_add_insel(hop, "sw at, 4+%S(fp) ! %H", src, src);

hop_add_insel(hop, "lw at, 0(sp)");
hop_add_insel(hop, "sw at, 0+%S(fp) ! %H", dest, dest);
hop_add_insel(hop, "lw at, 4(sp)");
hop_add_insel(hop, "sw at, 4+%S(fp) ! %H", dest, dest);
}
else
{
hop_add_insel(hop, "ldc1 f30, %S(fp) ! %H", src, src);
hop_add_insel(hop, "sdc1 f30, 0(sp)");
hop_add_insel(hop, "ldc1 f30, %S(fp) ! %H", dest, dest);
hop_add_insel(hop, "sdc1 f30, %S(fp) ! %H", src, src);
hop_add_insel(hop, "ldc1 f30, 0(sp)");
hop_add_insel(hop, "sdc1 f30, %S(fp) ! %H", dest, dest);
}
hop_add_insel(hop, "addiu sp, sp, 8");
break;

default:
fatal("cannot swap %s and %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);

tracef('R', "R: swap of %s to %s\n", src->id, dest->id);
assert((src->attrs & TYPE_ATTRS) == (dest->attrs & TYPE_ATTRS));

if (src->is_stacked && dest->is_stacked)
{
swap_stack_and_stack(hop, src, dest);
}
else if (src->is_stacked || dest->is_stacked)
{
struct hreg* reg = src->is_stacked ? dest : src;
struct hreg* stack = src->is_stacked ? src : dest;
swap_reg_and_stack(hop, reg, stack);
}
else
{
switch (src->attrs & TYPE_ATTRS)
{
case burm_int_ATTR:
hop_add_insel(hop, "mov at, %H", src);
hop_add_insel(hop, "mov %H, %H", src, dest);
hop_add_insel(hop, "mov %H, at", dest);
break;

case burm_long_ATTR:
hop_add_insel(hop, "mov at, %0H", src);
hop_add_insel(hop, "mov %0H, %0H", src, dest);
hop_add_insel(hop, "mov %0H, at", dest);

hop_add_insel(hop, "mov at, %1H", src);
hop_add_insel(hop, "mov %1H, %1H", src, dest);
hop_add_insel(hop, "mov %1H, at", dest);
break;

case burm_float_ATTR:
hop_add_insel(hop, "mov.s f30, %H", src);
hop_add_insel(hop, "mov.s %H, %H", src, dest);
hop_add_insel(hop, "mov.s %H, f30", dest);
break;

case burm_double_ATTR:
hop_add_insel(hop, "mov.d f30, %H", src);
hop_add_insel(hop, "mov.d %H, %H", src, dest);
hop_add_insel(hop, "mov.d %H, f30", dest);
break;

default:
fatal("cannot swap %s and %s", src->id, dest->id);
}
}

return hop;
Expand Down
17 changes: 17 additions & 0 deletions mach/proto/mcg/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ static const char* section_to_str(int section)
}
}

static void align_to_word(void)
{
fprintf(outputfile, "\t.align %d\n", (int)EM_wordsize);
}

static void emit_header(int desired_section)
{
if (pending)
Expand All @@ -42,6 +47,7 @@ static void emit_header(int desired_section)
fatal("label '%s' can't change sections", pending->name);

fprintf(outputfile, "\n.sect %s\n", section_to_str(pending->section));
align_to_word();
fprintf(outputfile, "%s:\n", platform_label(pending->name));
pending = NULL;
}
Expand All @@ -57,8 +63,12 @@ static void writehex(arith data, int size)

void data_int(arith data, size_t size, bool is_ro)
{
bool had_pending = (pending != NULL);

emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
assert((size == 1) || (size == 2) || (size == 4) || (size == 8));
if (!had_pending && size >= EM_wordsize)
align_to_word();
fprintf(outputfile, "\t.data%ld ", size);
writehex(data, size);
fprintf(outputfile, "\n");
Expand All @@ -69,9 +79,12 @@ void data_float(const char* data, size_t size, bool is_ro)
{
unsigned char buffer[8];
int i;
bool had_pending = (pending != NULL);

emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
assert((size == 4) || (size == 8));
if (!had_pending)
align_to_word();

fprintf(outputfile, "\t.dataf%ld %s\n", size, data);
}
Expand Down Expand Up @@ -134,7 +147,11 @@ void data_block(const uint8_t* data, size_t datalen, size_t size, bool is_ro)

void data_offset(const char* label, arith offset, bool is_ro)
{
bool had_pending = (pending != NULL);

emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
if (!had_pending)
align_to_word();
fprintf(outputfile, "\t.data%d %s+%ld\n",
EM_pointersize, platform_label(label), offset);
}
Expand Down
11 changes: 6 additions & 5 deletions mach/proto/mcg/pass_registerallocator.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,14 +686,15 @@ static int insert_moves(struct basicblock* bb, int index,
hop = platform_swap(bb, src, dest);
pmap_remove(&copies, src, dest);

/* Now src and dest are swapped. We know that the old src is in the right place
* and now contains dest. Any copies from the old dest (now containing src) must
* be patched to point at the old src. */
/* After swap(src, dest), dest holds the value that was in src (so src->dest
* is done). The value that was in dest is now in src. Any remaining copy
* that still reads from dest must be rewritten to read from src instead.
* Rewriting destinations is wrong for cycles longer than 2. */

for (i=0; i<copies.count; i++)
{
if (copies.item[i].right == src)
copies.item[i].right = dest;
if (copies.item[i].left == dest)
copies.item[i].left = src;
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions mach/proto/mcg/treebuilder.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,9 +407,10 @@ static void simple_test_neg(int size, int irop)
simple_test(size, irop);

push(
new_ir1(
IR_NOT, EM_wordsize,
pop(EM_wordsize)
new_ir2(
IR_EOR, EM_wordsize,
pop(EM_wordsize),
new_wordir(1)
)
);
}
Expand Down
Loading