aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog13
-rw-r--r--gas/config/tc-cris.c80
2 files changed, 81 insertions, 12 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 90b1f99..d4cd8ba 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,16 @@
+2005-12-07 Hans-Peter Nilsson <hp@axis.com>
+
+ Change 32-bit-branch expansion for --pic.
+ * config/tc-cris.c (STATE_COND_BRANCH_PIC): New relaxation state.
+ (md_cris_relax_table): Add entry for STATE_COND_BRANCH_PIC.
+ (cris_any_v0_v10_long_jump_size_pic): New macro.
+ (md_estimate_size_before_relax): Handle STATE_COND_BRANCH_PIC.
+ (md_convert_frag): Similar.
+ (md_create_long_jump): Change 32-bit-branch expansion for --pic.
+ (md_assemble, gen_cond_branch_32): Adjust similarly.
+ (md_parse_option) <case OPTION_PIC>: Adjust md_long_jump_size.
+ <case OPTION_ARCH>: Similar, if --pic.
+
2005-12-06 H.J. Lu <hongjiu.lu@intel.com>
PR gas/1874
diff --git a/gas/config/tc-cris.c b/gas/config/tc-cris.c
index b01c3f6..1c8e6dc 100644
--- a/gas/config/tc-cris.c
+++ b/gas/config/tc-cris.c
@@ -267,6 +267,7 @@ const char FLT_CHARS[] = "";
#define STATE_COND_BRANCH_COMMON (5)
#define STATE_ABS_BRANCH_V32 (6)
#define STATE_LAPC (7)
+#define STATE_COND_BRANCH_PIC (8)
#define STATE_LENGTH_MASK (3)
#define STATE_BYTE (0)
@@ -390,6 +391,18 @@ const relax_typeS md_cris_relax_table[] =
{0, 0, 4, 0},
/* Unused (7, 3). */
+ {1, 1, 0, 0},
+
+ /* PIC for pre-v32: Bcc o (8, 0). */
+ {BRANCH_BF, BRANCH_BB, 0, ENCODE_RELAX (STATE_COND_BRANCH_PIC, 1)},
+
+ /* Bcc [PC+] (8, 1). */
+ {BRANCH_WF, BRANCH_WB, 2, ENCODE_RELAX (STATE_COND_BRANCH_PIC, 2)},
+
+ /* 32-bit expansion, PIC (8, 2). */
+ {0, 0, 12, 0},
+
+ /* Unused (8, 3). */
{1, 1, 0, 0}
};
@@ -432,8 +445,10 @@ const char *md_shortopts = "hHN";
int md_short_jump_size = 6;
-/* The v32 version has a delay-slot, hence two bytes longer. */
+/* The v32 version has a delay-slot, hence two bytes longer.
+ The pre-v32 PIC version uses a prefixed insn. */
#define cris_any_v0_v10_long_jump_size 6
+#define cris_any_v0_v10_long_jump_size_pic 8
#define crisv32_long_jump_size 8
int md_long_jump_size = XCONCAT2 (DEFAULT_CRIS_ARCH,_long_jump_size);
@@ -633,6 +648,7 @@ md_estimate_size_before_relax (fragS *fragP, segT segment_type)
HANDLE_RELAXABLE (STATE_COND_BRANCH);
HANDLE_RELAXABLE (STATE_COND_BRANCH_V32);
HANDLE_RELAXABLE (STATE_COND_BRANCH_COMMON);
+ HANDLE_RELAXABLE (STATE_COND_BRANCH_PIC);
HANDLE_RELAXABLE (STATE_ABS_BRANCH_V32);
case ENCODE_RELAX (STATE_LAPC, STATE_UNDF):
@@ -740,6 +756,9 @@ md_estimate_size_before_relax (fragS *fragP, segT segment_type)
case ENCODE_RELAX (STATE_COND_BRANCH, STATE_BYTE):
case ENCODE_RELAX (STATE_COND_BRANCH, STATE_WORD):
case ENCODE_RELAX (STATE_COND_BRANCH, STATE_DWORD):
+ case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_BYTE):
+ case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_WORD):
+ case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_DWORD):
case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_BYTE):
case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_WORD):
case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_DWORD):
@@ -824,6 +843,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED,
switch (fragP->fr_subtype)
{
case ENCODE_RELAX (STATE_COND_BRANCH, STATE_BYTE):
+ case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_BYTE):
case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_BYTE):
case ENCODE_RELAX (STATE_COND_BRANCH_COMMON, STATE_BYTE):
case ENCODE_RELAX (STATE_ABS_BRANCH_V32, STATE_BYTE):
@@ -832,6 +852,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED,
break;
case ENCODE_RELAX (STATE_COND_BRANCH, STATE_WORD):
+ case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_WORD):
case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_WORD):
case ENCODE_RELAX (STATE_COND_BRANCH_COMMON, STATE_WORD):
case ENCODE_RELAX (STATE_ABS_BRANCH_V32, STATE_WORD):
@@ -859,6 +880,14 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED,
var_part_size = 2 + 2 + 4 + 2;
break;
+ case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_DWORD):
+ gen_cond_branch_32 (fragP->fr_opcode, var_partp, fragP,
+ fragP->fr_symbol, (symbolS *) NULL,
+ fragP->fr_offset);
+ /* Twelve bytes added: a branch, nop and a pic-branch-32. */
+ var_part_size = 2 + 2 + 4 + 2 + 2;
+ break;
+
case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_DWORD):
gen_cond_branch_32 (fragP->fr_opcode, var_partp, fragP,
fragP->fr_symbol, (symbolS *) NULL,
@@ -1093,12 +1122,13 @@ md_create_long_jump (char *storep, addressT from_addr, addressT to_addr,
else
{
/* We have a "long" long jump: "JUMP [PC+]". If CRISv32, always
- make it a BA. Else make it an "ADD [PC+],PC" if we're supposed
+ make it a BA. Else make it an "MOVE [PC=PC+N],P0" if we're supposed
to emit PIC code. */
md_number_to_chars (storep,
cris_arch == arch_crisv32
? BA_DWORD_OPCODE
- : (pic ? ADD_PC_INCR_OPCODE : JUMP_PC_INCR_OPCODE),
+ : (pic ? MOVE_PC_INCR_OPCODE_PREFIX
+ : JUMP_PC_INCR_OPCODE),
2);
/* Follow with a ".DWORD to_addr", PC-relative for PIC. */
@@ -1111,6 +1141,9 @@ md_create_long_jump (char *storep, addressT from_addr, addressT to_addr,
/* Follow it with a "NOP" for CRISv32. */
if (cris_arch == arch_crisv32)
md_number_to_chars (storep + 6, NOP_OPCODE_V32, 2);
+ else if (pic)
+ /* ...and the rest of the move-opcode for pre-v32 PIC. */
+ md_number_to_chars (storep + 6, MOVE_PC_INCR_OPCODE_SUFFIX, 2);
}
}
@@ -1321,11 +1354,12 @@ md_assemble (char *str)
That case is handled by md_estimate_size_before_relax. */
length_code = to_seg == now_seg ? STATE_BYTE : STATE_UNDF;
- /* Make room for max twelve bytes of variable length for v32 mode,
- ten for v10 and older. */
+ /* Make room for max twelve bytes of variable length for v32 mode
+ or PIC, ten for v10 and older. */
frag_var (rs_machine_dependent,
(cris_arch == arch_crisv32
- || cris_arch == arch_cris_common_v10_v32) ? 12 : 10, 0,
+ || cris_arch == arch_cris_common_v10_v32
+ || pic) ? 12 : 10, 0,
ENCODE_RELAX (cris_arch == arch_crisv32
? (output_instruction.opcode
== BA_QUICK_OPCODE
@@ -1333,7 +1367,8 @@ md_assemble (char *str)
: STATE_COND_BRANCH_V32)
: (cris_arch == arch_cris_common_v10_v32
? STATE_COND_BRANCH_COMMON
- : STATE_COND_BRANCH),
+ : (pic ? STATE_COND_BRANCH_PIC
+ : STATE_COND_BRANCH)),
length_code),
sym, addvalue, opcodep);
}
@@ -1344,7 +1379,8 @@ md_assemble (char *str)
section, perhaps an absolute address. Emit a 32-bit branch. */
char *cond_jump
= frag_more ((cris_arch == arch_crisv32
- || cris_arch == arch_cris_common_v10_v32)
+ || cris_arch == arch_cris_common_v10_v32
+ || pic)
? 12 : 10);
gen_cond_branch_32 (opcodep, cond_jump, frag_now,
@@ -3292,6 +3328,12 @@ gen_cond_branch_32 (char *opcodep, char *writep, fragS *fragP,
opc_offset = 10;
branch_offset = -2 - 8;
}
+ else if (pic)
+ {
+ nop_opcode = NOP_OPCODE;
+ opc_offset = 10;
+ branch_offset = -2 - 8;
+ }
else
{
nop_opcode = NOP_OPCODE;
@@ -3330,18 +3372,20 @@ gen_cond_branch_32 (char *opcodep, char *writep, fragS *fragP,
merged later. */
md_number_to_chars (opcodep, BA_QUICK_OPCODE
- + (cris_arch == arch_crisv32 ? 12 : 8), 2);
+ + (cris_arch == arch_crisv32 ? 12 : (pic ? 10 : 8)),
+ 2);
md_number_to_chars (writep, nop_opcode, 2);
/* Then the extended thing, the 32-bit jump insn.
opcodep+4: JUMP [PC+]
or, in the PIC case,
- opcodep+4: ADD [PC+],PC. */
+ opcodep+4: MOVE [PC=PC+N],P0. */
md_number_to_chars (writep + 2,
cris_arch == arch_crisv32
? BA_DWORD_OPCODE
- : (pic ? ADD_PC_INCR_OPCODE : JUMP_PC_INCR_OPCODE), 2);
+ : (pic ? MOVE_PC_INCR_OPCODE_PREFIX
+ : JUMP_PC_INCR_OPCODE), 2);
/* We have to fill in the actual value too.
opcodep+6: .DWORD
@@ -3377,6 +3421,9 @@ gen_cond_branch_32 (char *opcodep, char *writep, fragS *fragP,
if (cris_arch == arch_crisv32)
/* Follow it with a "NOP" for CRISv32. */
md_number_to_chars (writep + 8, NOP_OPCODE_V32, 2);
+ else if (pic)
+ /* ...and the rest of the move-opcode for pre-v32 PIC. */
+ md_number_to_chars (writep + 8, MOVE_PC_INCR_OPCODE_SUFFIX, 2);
}
/* Get the size of an immediate-reloc in bytes. Only valid for PIC
@@ -3716,6 +3763,10 @@ md_parse_option (int arg, char *argp ATTRIBUTE_UNUSED)
case OPTION_PIC:
pic = TRUE;
+ if (cris_arch != arch_crisv32)
+ md_long_jump_size = cris_any_v0_v10_long_jump_size_pic;
+ else
+ md_long_jump_size = crisv32_long_jump_size;
break;
case OPTION_ARCH:
@@ -3734,7 +3785,12 @@ md_parse_option (int arg, char *argp ATTRIBUTE_UNUSED)
md_long_jump_size = crisv32_long_jump_size;
}
else
- md_long_jump_size = cris_any_v0_v10_long_jump_size;
+ {
+ if (pic)
+ md_long_jump_size = cris_any_v0_v10_long_jump_size_pic;
+ else
+ md_long_jump_size = cris_any_v0_v10_long_jump_size;
+ }
}
break;