Swaps work (at least for registers). More opcodes. Rearrange the stack layout

so we can always trivially find fp, which lets CHAINFP work.
This commit is contained in:
David Given 2016-10-27 21:50:58 +02:00
parent be3dece5af
commit 81525c0f2c
4 changed files with 61 additions and 28 deletions

View file

@ -4,15 +4,19 @@
*
* | ...params...
* | --------------- <- ab
* | saved regs
* | spills
* | ---------------
* | spills
* | saved regs
* | LR
* | FP
* | --------------- <- st, fp (a.k.a. lb)
* | locals
* | --------------- <- sp
* V ...user area...
*
* st indexes up; lb indexes down.
*
* We ensure that dereferencing fp always produces the caller's fp.
*/
static ARRAYOF(struct hreg) saved_regs;
@ -51,11 +55,12 @@ struct hop* platform_prologue(void)
hop_add_insel(hop, "addi sp, sp, %d", -(current_proc->fp_to_ab + current_proc->locals_size));
hop_add_insel(hop, "mfspr r0, lr");
hop_add_insel(hop, "stw r0, %d(sp)", current_proc->locals_size + current_proc->spills_size);
hop_add_insel(hop, "stw fp, %d(sp)", current_proc->locals_size + current_proc->spills_size + 4);
hop_add_insel(hop, "stw fp, %d(sp)", current_proc->locals_size + 0);
hop_add_insel(hop, "stw r0, %d(sp)", current_proc->locals_size + 4);
hop_add_insel(hop, "addi fp, sp, %d", current_proc->locals_size);
saved_offset = current_proc->spills_size + 8;
/* Saved reg offsets are negative. */
saved_offset = current_proc->saved_size + 8;
for (i=0; i<saved_regs.count; i++)
{
struct hreg* hreg = saved_regs.item[i];
@ -74,7 +79,8 @@ struct hop* platform_epilogue(void)
int i;
int saved_offset;
saved_offset = current_proc->spills_size + 8;
/* Saved reg offsets are negative. */
saved_offset = current_proc->saved_size + 8;
for (i=0; i<saved_regs.count; i++)
{
struct hreg* hreg = saved_regs.item[i];
@ -85,9 +91,9 @@ struct hop* platform_epilogue(void)
saved_offset += 4;
}
hop_add_insel(hop, "lwz r0, %d(fp)", current_proc->spills_size);
hop_add_insel(hop, "lwz r0, 4(fp)");
hop_add_insel(hop, "mtspr lr, r0");
hop_add_insel(hop, "lwz r0, %d(fp)", current_proc->spills_size + 4);
hop_add_insel(hop, "lwz r0, 0(fp)"); /* load old fp */
hop_add_insel(hop, "addi sp, fp, %d", current_proc->fp_to_ab);
hop_add_insel(hop, "mr fp, r0");
hop_add_insel(hop, "bclr 20, 0, 0");
@ -247,5 +253,42 @@ 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;
}
/* vim: set sw=4 ts=4 expandtab : */

View file

@ -210,6 +210,10 @@ PATTERNS
emit "mr %out, fp"
cost 4;
out:(int)reg = CHAINFP.I(in:(int)reg)
emit "lwz %out, 0(%in)"
cost 4;
out:(int)reg = FPTOARGS.I(GETFP.I)
emit "addi %out, fp, 8"
cost 4;
@ -641,8 +645,10 @@ PATTERNS
ALUR(DIVU.I, "divwu")
ALUR(ASL.I, "slw")
ALUR(ASR.I, "sraw")
ALUR(LSL.I, "slw")
ALUR(LSR.I, "srw")
out:(int)reg = NEG.I(left:(int)reg)
emit "neg %out, %left"
@ -694,10 +700,6 @@ PATTERNS
out:(double)reg = LOAD.D(addr:address)
emit "lfd %out, %addr"
cost 4;
out:(float)reg = value:CONST.F
emit "lfs %out, address-containing-$value"
cost 8;
FPU4R(ADDF.F, "fadds")
FPU8R(ADDF.D, "fadd")

View file

@ -123,6 +123,7 @@ extern void platform_calculate_offsets(void);
extern struct hop* platform_prologue(void);
extern struct hop* platform_epilogue(void);
extern struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest);
extern struct hop* platform_swap(struct basicblock* bb, struct hreg* src, struct hreg* dest);
extern FILE* outputfile;
extern FILE* dominance_dot_file;

View file

@ -578,19 +578,6 @@ static void assign_hregs_to_vregs(void)
}
}
static struct hop* create_swap(struct basicblock* bb, struct hreg* src, struct hreg* dest)
{
struct hop* hop = new_hop(bb, NULL);
hop_add_string_insel(hop, "! swap ");
hop_add_hreg_insel(hop, src, 0);
hop_add_string_insel(hop, " <-> ");
hop_add_hreg_insel(hop, dest, 0);
hop_add_eoi_insel(hop);
return hop;
}
/* returns the number of instructions inserted */
static int insert_moves(struct basicblock* bb, int index,
register_assignment_t* srcregs, register_assignment_t* destregs)
@ -640,12 +627,12 @@ static int insert_moves(struct basicblock* bb, int index,
}
else
{
/* Swap. */
/* There's nowhere to copy to --- the copies that are left form a cycle.
* So we need to swap instead. */
assert(false);
src = copies.item[0].left;
dest = pmap_findleft(&copies, src);
hop = create_swap(bb, src, dest);
hop = platform_swap(bb, src, dest);
pmap_remove(&copies, src, dest);
pmap_remove(&copies, dest, src);
}