aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meissner <meissner@gcc.gnu.org>1996-02-28 17:09:44 +0000
committerMichael Meissner <meissner@gcc.gnu.org>1996-02-28 17:09:44 +0000
commit7c59dc5dd818d8658902070cab03c57d331b4185 (patch)
tree027eba1ba2823e8d08c72e3ef3742c1913dfa499
parent375490e0a596633eb84479a8d81192bec71fcfb2 (diff)
downloadgcc-7c59dc5dd818d8658902070cab03c57d331b4185.zip
gcc-7c59dc5dd818d8658902070cab03c57d331b4185.tar.gz
gcc-7c59dc5dd818d8658902070cab03c57d331b4185.tar.bz2
try to fix NT trampolines
From-SVN: r11360
-rw-r--r--gcc/config/rs6000/rs6000.c89
1 files changed, 41 insertions, 48 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index cb05d88..20c72d2 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -4035,6 +4035,7 @@ rs6000_trampoline_template (file)
{
char *sc = reg_names[STATIC_CHAIN_REGNUM];
char *r0 = reg_names[0];
+ char *r2 = reg_names[2];
switch (DEFAULT_ABI)
{
@@ -4087,23 +4088,26 @@ rs6000_trampoline_template (file)
/* NT function pointers point to a two word area (real address, TOC)
which unfortunately does not include a static chain field. So we
- need to have a 2 word area followed by the code to load up the
- static chain. */
+ use the function field to point to ..LTRAMP1 and the toc field
+ to point to the whole table. */
case ABI_NT:
- if (STATIC_CHAIN_REGNUM == 0 || !TARGET_NEW_MNEMONICS || TARGET_64BIT)
+ if (STATIC_CHAIN_REGNUM == 0
+ || STATIC_CHAIN_REGNUM == 2
+ || TARGET_64BIT
+ || !TARGET_NEW_MNEMONICS)
abort ();
- fprintf (file, "\t.ualong 0,0\n"); /* offset 0 */
- fprintf (file, "\tmflr %s\n", r0); /* offset 8 */
- fprintf (file, "\tbl .LTRAMP1\n"); /* offset 12 */
- fprintf (file, "\t.ualong 0,0\n"); /* offset 16 */
- fprintf (file, ".LTRAMP1:\n");
- fprintf (file, "\tmflr %s\n", sc); /* offset 28 */
- fprintf (file, "\tmtlr %s\n", r0); /* offset 32 */
- fprintf (file, "\tlwz %s,0(%s)\n", r0, sc); /* offset 36 */
- fprintf (file, "\tlwz %s,4(%s)\n", sc, sc); /* offset 40 */
- fprintf (file, "\tmtctr %s\n", r0); /* offset 44 */
- fprintf (file, "\tbctr\n"); /* offset 48 */
+ fprintf (file, "\t.ualong 0\n"); /* offset 0 */
+ fprintf (file, "\t.ualong 0\n"); /* offset 4 */
+ fprintf (file, "\t.ualong 0\n"); /* offset 8 */
+ fprintf (file, "\t.ualong 0\n"); /* offset 12 */
+ fprintf (file, "\t.ualong 0\n"); /* offset 16 */
+ fprintf (file, "..LTRAMP1:\n"); /* offset 20 */
+ fprintf (file, "\tlwz %s,8(%s)\n", r0, r2); /* offset 24 */
+ fprintf (file, "\tlwz %s,12(%s)\n", sc, r2); /* offset 28 */
+ fprintf (file, "\tmtctr %s\n", r0); /* offset 32 */
+ fprintf (file, "\tlwz %s,16(%s)\n", r2, r2); /* offset 36 */
+ fprintf (file, "\tbctr\n"); /* offset 40 */
break;
}
@@ -4132,7 +4136,7 @@ rs6000_trampoline_size ()
break;
case ABI_NT:
- ret = 52;
+ ret = 20;
break;
}
@@ -4157,22 +4161,15 @@ rs6000_initialize_trampoline (addr, fnaddr, cxt)
default:
abort ();
+#define MEM_PLUS(addr,offset) gen_rtx (MEM, pmode, memory_address (pmode, plus_constant (addr, offset)))
+
/* Under AIX, just build the 3 word function descriptor */
case ABI_AIX:
- emit_move_insn (gen_rtx (MEM, pmode,
- memory_address (pmode, (addr))),
- gen_rtx (MEM, pmode,
- memory_address (pmode, (fnaddr))));
- emit_move_insn (gen_rtx (MEM, pmode,
- memory_address (pmode,
- plus_constant ((addr), 4))),
- gen_rtx (MEM, pmode,
- memory_address (pmode,
- plus_constant ((fnaddr), 4))));
- emit_move_insn (gen_rtx (MEM, pmode,
- memory_address (pmode,
- plus_constant ((addr), 8))),
- force_reg (pmode, (cxt)));
+ emit_move_insn (gen_rtx (MEM, pmode, memory_address (pmode, addr)),
+ gen_rtx (MEM, pmode, memory_address (pmode, fnaddr)));
+
+ emit_move_insn (MEM_PLUS (addr, 4), MEM_PLUS (fnaddr, 4));
+ emit_move_insn (MEM_PLUS (addr, 8), force_reg (pmode, cxt));
break;
/* Under V.4/eabi, update the two words after the bl to have the real
@@ -4182,31 +4179,27 @@ rs6000_initialize_trampoline (addr, fnaddr, cxt)
reg = gen_reg_rtx (pmode);
emit_move_insn (reg, fnaddr);
- emit_move_insn (gen_rtx (MEM, pmode, plus_constant (addr, 8)), reg);
- emit_move_insn (gen_rtx (MEM, pmode,
- plus_constant (addr, (TARGET_64BIT ? 16 : 12))),
- cxt);
+ emit_move_insn (MEM_PLUS (addr, 8), reg);
+ emit_move_insn (MEM_PLUS (addr, (TARGET_64BIT ? 16 : 12)), cxt);
rs6000_sync_trampoline (addr);
break;
- /* Under NT, update the first 2 words to look like a normal descriptor, and
- then fill in the fields with the function address and static chain after
- the bl instruction. */
+ /* Under NT, update the first word to point to the ..LTRAMP1 header,
+ second word will point to the whole trampoline, third-fifth words
+ will then have the real address, static chain, and toc value. */
case ABI_NT:
- reg = gen_reg_rtx (pmode);
+ addr = force_reg (pmode, addr);
+ reg = gen_reg_rtx (pmode);
reg2 = gen_reg_rtx (pmode);
- reg3 = gen_reg_rtx (pmode);
-
- emit_move_insn (gen_rtx (MEM, pmode, plus_constant (addr, 4)),
- gen_rtx (REG, pmode, 2));
- emit_move_insn (reg, fnaddr);
- emit_move_insn (reg2, gen_rtx (MEM, pmode, reg));
- emit_move_insn (reg3, plus_constant (addr, 8));
- emit_move_insn (gen_rtx (MEM, pmode, plus_constant (addr, 16)), reg);
- emit_move_insn (gen_rtx (MEM, pmode, addr), reg3);
- emit_move_insn (gen_rtx (MEM, pmode, plus_constant (addr, 20)), cxt);
- rs6000_sync_trampoline (addr);
+ emit_move_insn (reg, gen_rtx (SYMBOL_REF, pmode, "..LTRAMP1"));
+ emit_move_insn (reg2, fnaddr);
+ reg3 = force_reg (pmode, cxt);
+ emit_move_insn (MEM_PLUS (addr, 4), addr);
+ emit_move_insn (gen_rtx (MEM, pmode, addr), reg);
+ emit_move_insn (MEM_PLUS (addr, 8), reg2);
+ emit_move_insn (MEM_PLUS (addr, 12), reg3);
+ emit_move_insn (MEM_PLUS (addr, 16), gen_rtx (REG, pmode, 2));
break;
}