Add support for -membedded-pic

From-SVN: r6997
This commit is contained in:
Ian Lance Taylor 1994-04-08 15:23:06 +00:00
parent 8926095fe7
commit e0bfcea5c9
3 changed files with 156 additions and 12 deletions

View File

@ -3191,6 +3191,28 @@ override_options ()
else
mips_abicalls = MIPS_ABICALLS_NO;
/* -membedded-pic is a form of PIC code suitable for embedded
systems. All calls are made using PC relative addressing, and
all data is addressed using the $gp register. This requires gas,
which does most of the work, and GNU ld, which automatically
expands PC relative calls which are out of range into a longer
instruction sequence. All gcc really does differently is
generate a different sequence for a switch. */
if (TARGET_EMBEDDED_PIC)
{
flag_pic = 1;
if (TARGET_ABICALLS)
warning ("-membedded-pic and -mabicalls are incompatible");
if (g_switch_set)
warning ("-G and -membedded-pic are incompatible");
/* Setting mips_section_threshold is not required, because gas
will force everything to be GP addressable anyhow, but
setting it will cause gcc to make better estimates of the
number of instructions required to access a particular data
item. */
mips_section_threshold = 0x7fffffff;
}
/* -mrnames says to use the MIPS software convention for register
names instead of the hardware names (ie, $a0 instead of $4).
We do this by switching the names in mips_reg_names, which the
@ -3387,6 +3409,7 @@ mips_debugger_offset (addr, offset)
'M' print high-order register of double-word register operand.
'C' print part of opcode for a branch condition.
'N' print part of opcode for a branch condition, inverted.
'S' X is CODE_LABEL, print with prefix of "LS" (for embedded switch).
'(' Turn on .set noreorder
')' Turn on .set reorder
'[' Turn on .set noat
@ -3569,6 +3592,14 @@ print_operand (file, op, letter)
abort_with_insn (op, "PRINT_OPERAND, illegal insn for %%N");
}
else if (letter == 'S')
{
char buffer[100];
ASM_GENERATE_INTERNAL_LABEL (buffer, "LS", CODE_LABEL_NUMBER (op));
assemble_name (file, buffer);
}
else if (code == REG)
{
register int regnum = REGNO (op);

View File

@ -254,12 +254,12 @@ extern char *mktemp ();
#define MASK_HALF_PIC 0x00000800 /* Emit OSF-style pic refs to externs*/
#define MASK_LONG_CALLS 0x00001000 /* Always call through a register */
#define MASK_64BIT 0x00002000 /* Use 64 bit GP registers and insns */
#define MASK_UNUSED1 0x00004000
#define MASK_UNUSED2 0x00008000
#define MASK_UNUSED3 0x00010000
#define MASK_UNUSED4 0x00020000
#define MASK_UNUSED5 0x00040000
#define MASK_UNUSED6 0x00080000
#define MASK_EMBEDDED_PIC 0x00004000 /* Generate embedded PIC code */
#define MASK_UNUSED1 0x00008000
#define MASK_UNUSED2 0x00010000
#define MASK_UNUSED3 0x00020000
#define MASK_UNUSED4 0x00040000
#define MASK_UNUSED5 0x00080000
/* Dummy switches used only in spec's*/
#define MASK_MIPS_TFILE 0x00000000 /* flag for mips-tfile usage */
@ -327,6 +327,10 @@ extern char *mktemp ();
/* always call through a register */
#define TARGET_LONG_CALLS (target_flags & MASK_LONG_CALLS)
/* generate embedded PIC code;
requires gas. */
#define TARGET_EMBEDDED_PIC (target_flags & MASK_EMBEDDED_PIC)
/* Macro to define tables used to set the flags.
This is a list in braces of pairs in braces,
each pair being { "NAME", VALUE }
@ -364,6 +368,8 @@ extern char *mktemp ();
{"no-half-pic", -MASK_HALF_PIC}, \
{"long-calls", MASK_LONG_CALLS}, \
{"no-long-calls", -MASK_LONG_CALLS}, \
{"embedded-pic", MASK_EMBEDDED_PIC}, \
{"no-embedded-pic", -MASK_EMBEDDED_PIC}, \
{"debug", MASK_DEBUG}, \
{"debuga", MASK_DEBUG_A}, \
{"debugb", MASK_DEBUG_B}, \
@ -552,7 +558,8 @@ while (0)
%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \
%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \
%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \
%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3}"
%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3} \
%{membedded-pic}"
#else
/* not GAS */
@ -568,7 +575,8 @@ while (0)
%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \
%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \
%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \
%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3}"
%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3} \
%{membedded-pic}"
#endif
#endif /* ASM_SPEC */
@ -3375,12 +3383,33 @@ do { \
VALUE)
/* This is how to output an element of a case-vector that is relative.
This is used for pc-relative code (e.g. when TARGET_ABICALLS). */
This is used for pc-relative code (e.g. when TARGET_ABICALLS or
TARGET_EMBEDDED_PIC). */
#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, VALUE, REL) \
fprintf (STREAM, "\t%s\t$L%d\n", \
TARGET_LONG64 ? ".gpdword" : ".gpword", \
VALUE)
do { \
if (TARGET_EMBEDDED_PIC) \
fprintf (STREAM, "\t%s\t$L%d-$LS%d\n", \
TARGET_LONG64 ? ".dword" : ".word", \
VALUE, REL); \
else \
fprintf (STREAM, "\t%s\t$L%d\n", \
TARGET_LONG64 ? ".gpdword" : ".gpword", \
VALUE); \
} while (0)
/* When generating embedded PIC code we want to put the jump table in
the .text section. In all other cases, we want to put the jump
table in the .rdata section. Unfortunately, we can't use
JUMP_TABLES_IN_TEXT_SECTION, because it is not conditional.
Instead, we use ASM_OUTPUT_CASE_LABEL to switch back to the .text
section if appropriate. */
#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, INSN) \
do { \
if (TARGET_EMBEDDED_PIC) \
text_section (); \
ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \
} while (0)
/* This is how to output an assembler line
that says to advance the location counter

View File

@ -5410,6 +5410,90 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "none")
(set_attr "length" "1")])
;; Implement a switch statement when generating embedded PIC code.
;; Switches are implemented by `tablejump' when not using -membedded-pic.
(define_expand "casesi"
[(set (match_dup 5)
(minus:SI (match_operand:SI 0 "register_operand" "d")
(match_operand:SI 1 "arith_operand" "dI")))
(set (cc0)
(compare:CC (match_dup 5)
(match_operand:SI 2 "arith_operand" "")))
(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(label_ref (match_operand 4 "" ""))
(pc)))
(parallel
[(set (pc)
(mem:SI (plus:SI (mult:SI (match_dup 5)
(const_int 4))
(label_ref (match_operand 3 "" "")))))
(clobber (match_scratch:SI 6 ""))
(clobber (reg:SI 31))])]
"TARGET_EMBEDDED_PIC"
"
{
/* We need slightly different code for eight byte table entries. */
if (TARGET_LONG64)
abort ();
if (operands[0])
{
rtx reg = gen_reg_rtx (SImode);
/* The constraints should handle this, but they don't. */
operands[0] = force_reg (SImode, operands[0]);
if (! arith_operand (operands[1]))
operands[1] = force_reg (SImode, operands[1]);
if (! arith_operand (operands[2]))
operands[2] = force_reg (SImode, operands[2]);
/* If the index is too large, go to the default label. */
emit_insn (gen_subsi3 (reg, operands[0], operands[1]));
emit_insn (gen_cmpsi (reg, operands[2]));
emit_insn (gen_bgtu (operands[4]));
/* Do the PIC jump. */
emit_insn (gen_casesi_internal (reg, operands[3], gen_reg_rtx (SImode)));
DONE;
}
}")
;; An embedded PIC switch statement looks like this:
;; bal $LS1
;; sll $reg,$index,2
;; $LS1:
;; addu $reg,$reg,$31
;; lw $reg,$L1-$LS1($reg)
;; addu $reg,$reg,$31
;; j $reg
;; $L1:
;; .word case1-$LS1
;; .word case2-$LS1
;; ...
(define_insn "casesi_internal"
[(set (pc)
(mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "d")
(const_int 4))
(label_ref (match_operand 1 "" "")))))
(clobber (match_operand:SI 2 "register_operand" "d"))
(clobber (reg:SI 31))]
"TARGET_EMBEDDED_PIC"
"*
{
output_asm_insn (\"%(bal\\t%S1\;sll\\t%0,2\\n%S1:\", operands);
output_asm_insn (\"addu\\t%0,%0,$31%)\", operands);
output_asm_insn (\"lw\\t%0,%1-%S1(%0)\;addu\\t%0,%0,$31\", operands);
return \"j\\t%0\";
}"
[(set_attr "type" "jump")
(set_attr "mode" "none")
(set_attr "length" "6")])
;;
;; ....................