Implement saving of dirty registers onto the stack.
authorDavid Given <dg@cowlark.com>
Sun, 16 Oct 2016 20:37:42 +0000 (22:37 +0200)
committerDavid Given <dg@cowlark.com>
Sun, 16 Oct 2016 20:37:42 +0000 (22:37 +0200)
mach/proto/mcg/pass_prologueepilogue.c
mach/proto/mcg/powerpc.c
mach/proto/mcg/procedure.h

index 53cc498..9a5762e 100644 (file)
@@ -2,6 +2,25 @@
 
 void pass_add_prologue_epilogue(void)
 {
+    int i, j, k;
+
+    current_proc->usedregs.count = 0;
+    for (i=0; i<cfg.preorder.count; i++)
+    {
+        struct basicblock* bb = cfg.preorder.item[i];
+
+        for (j=0; j<bb->hops.count; j++)
+        {
+            struct hop* hop = bb->hops.item[j];
+
+            for (k=0; k<hop->regsin.count; k++)
+                array_appendu(&current_proc->usedregs, hop->regsin.item[k].left);
+
+            for (k=0; k<hop->regsout.count; k++)
+                array_appendu(&current_proc->usedregs, hop->regsout.item[k].left);
+        }
+    }
+
        platform_calculate_offsets();
 
        array_insert(&current_proc->entry->hops, platform_prologue(), 0);
index 1c900be..ab08209 100644 (file)
  * st indexes up; lb indexes down.
  */
 
+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_int_ATTR) || (hreg->attrs & burm_float_ATTR)))
+        {
+            current_proc->saved_size += 4;
+            array_append(&saved_regs, hreg);
+        }
+    }
+
        current_proc->fp_to_st = 0;
        current_proc->fp_to_ab = current_proc->spills_size + current_proc->saved_size + 8;
        current_proc->fp_to_lb = 0;
@@ -24,6 +41,8 @@ void platform_calculate_offsets(void)
 
 struct hop* platform_prologue(void)
 {
+    int i;
+    int saved_offset;
        struct hop* hop = new_hop(current_proc->entry, NULL);
 
        hop_add_insel(hop, "! saved_size = %d+8 bytes", current_proc->saved_size);
@@ -31,18 +50,47 @@ struct hop* platform_prologue(void)
        hop_add_insel(hop, "! locals_size = %d bytes", current_proc->locals_size);
        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 fp, %d(sp)", current_proc->fp_to_st + current_proc->locals_size);
-       hop_add_insel(hop, "stw r0, %d(sp)", current_proc->fp_to_st + current_proc->locals_size + 4);
+
+       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, "addi fp, sp, %d", current_proc->locals_size);
 
+    saved_offset = current_proc->spills_size + 8;
+    for (i=0; i<saved_regs.count; i++)
+    {
+        struct hreg* hreg = saved_regs.item[i];
+        if (hreg->type & burm_int_ATTR)
+            hop_add_insel(hop, "stw %H, %d(fp)", hreg, saved_offset);
+        else if (hreg->type & burm_float_ATTR)
+            hop_add_insel(hop, "stfs %H, %d(fp)", hreg, saved_offset);
+        saved_offset += 4;
+    }
        return hop;
 }
 
 struct hop* platform_epilogue(void)
 {
        struct hop* hop = new_hop(current_proc->exit, NULL);
+    int i;
+    int saved_offset;
+
+    saved_offset = current_proc->spills_size + 8;
+    for (i=0; i<saved_regs.count; i++)
+    {
+        struct hreg* hreg = saved_regs.item[i];
+        if (hreg->type & burm_int_ATTR)
+            hop_add_insel(hop, "lwz %H, %d(fp)", hreg, saved_offset);
+        else if (hreg->type & burm_float_ATTR)
+            hop_add_insel(hop, "lfs %H, %d(fp)", hreg, saved_offset);
+        saved_offset += 4;
+    }
 
-       hop_add_insel(hop, "b .ret");
+    hop_add_insel(hop, "lwz r0, %d(fp)", current_proc->spills_size);
+    hop_add_insel(hop, "mtspr lr, r0");
+    hop_add_insel(hop, "lwz r0, %d(fp)", current_proc->spills_size + 4);
+    hop_add_insel(hop, "addi sp, fp, %d", current_proc->fp_to_ab);
+    hop_add_insel(hop, "mr fp, r0");
+    hop_add_insel(hop, "blr");
 
        return hop;
 }
index 2c0baf8..ead7abc 100644 (file)
@@ -21,6 +21,7 @@ struct procedure
     int fp_to_lb;
     ARRAYOF(struct basicblock) blocks;
     IMAPOF(struct local) locals;
+    ARRAYOF(struct hreg) usedregs;
 };
 
 extern void procedure_compile(struct procedure* proc);