forked from Imagelibrary/binutils-gdb
* config/tc-cris.c (SIMPLE_EXPR): New macro.
(cris_relax_frag): New function. (md_estimate_size_before_relax) <case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_UNDF)>: Pass on unresolved expressions that will become absolute expressions to relaxation. (md_convert_frag) <case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_WORD)>: Expect only absolute expressions. Use the symbol value, not distance to symbol. <case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_BYTE)>: Ditto. Correct placement of fixup. (md_assemble): Use SIMPLE_EXPR when dissecting expressions. (gen_bdap): Ditto. * config/tc-cris.h (cris_relax_frag): Declare. (md_relax_frag): Define.
This commit is contained in:
@@ -1,3 +1,20 @@
|
|||||||
|
2002-10-23 Hans-Peter Nilsson <hp@axis.com>
|
||||||
|
|
||||||
|
* config/tc-cris.c (SIMPLE_EXPR): New macro.
|
||||||
|
(cris_relax_frag): New function.
|
||||||
|
(md_estimate_size_before_relax) <case ENCODE_RELAX
|
||||||
|
(STATE_BASE_PLUS_DISP_PREFIX, STATE_UNDF)>: Pass on unresolved
|
||||||
|
expressions that will become absolute expressions to relaxation.
|
||||||
|
(md_convert_frag) <case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX,
|
||||||
|
STATE_WORD)>: Expect only absolute expressions. Use the symbol
|
||||||
|
value, not distance to symbol.
|
||||||
|
<case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_BYTE)>:
|
||||||
|
Ditto. Correct placement of fixup.
|
||||||
|
(md_assemble): Use SIMPLE_EXPR when dissecting expressions.
|
||||||
|
(gen_bdap): Ditto.
|
||||||
|
* config/tc-cris.h (cris_relax_frag): Declare.
|
||||||
|
(md_relax_frag): Define.
|
||||||
|
|
||||||
2002-10-22 Alan Modra <amodra@bigpond.net.au>
|
2002-10-22 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
* config/obj-elf.c (special_sections): Use correct types for init
|
* config/obj-elf.c (special_sections): Use correct types for init
|
||||||
|
|||||||
@@ -43,6 +43,13 @@
|
|||||||
#define SYNTAX_USER_SYM_NO_LEADING_UNDERSCORE "no_leading_underscore"
|
#define SYNTAX_USER_SYM_NO_LEADING_UNDERSCORE "no_leading_underscore"
|
||||||
#define REGISTER_PREFIX_CHAR '$'
|
#define REGISTER_PREFIX_CHAR '$'
|
||||||
|
|
||||||
|
/* True for expressions where getting X_add_symbol and X_add_number is
|
||||||
|
enough to get the "base" and "offset"; no need to make_expr_symbol.
|
||||||
|
It's not enough to check if X_op_symbol is NULL; that misses unary
|
||||||
|
operations like O_uminus. */
|
||||||
|
#define SIMPLE_EXPR(EXP) \
|
||||||
|
((EXP)->X_op == O_constant || (EXP)->X_op == O_symbol)
|
||||||
|
|
||||||
/* Like in ":GOT", ":GOTOFF" etc. Other ports use '@', but that's in
|
/* Like in ":GOT", ":GOTOFF" etc. Other ports use '@', but that's in
|
||||||
line_separator_chars for CRIS, so we avoid it. */
|
line_separator_chars for CRIS, so we avoid it. */
|
||||||
#define PIC_SUFFIX_CHAR ':'
|
#define PIC_SUFFIX_CHAR ':'
|
||||||
@@ -330,6 +337,98 @@ cris_target_format ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We need a port-specific relaxation function to cope with sym2 - sym1
|
||||||
|
relative expressions with both symbols in the same segment (but not
|
||||||
|
necessarily in the same frag as this insn), for example:
|
||||||
|
move.d [pc+sym2-(sym1-2)],r10
|
||||||
|
sym1:
|
||||||
|
The offset can be 8, 16 or 32 bits long. */
|
||||||
|
|
||||||
|
long
|
||||||
|
cris_relax_frag (seg, fragP, stretch)
|
||||||
|
segT seg ATTRIBUTE_UNUSED;
|
||||||
|
fragS *fragP;
|
||||||
|
long stretch ATTRIBUTE_UNUSED;
|
||||||
|
{
|
||||||
|
long growth;
|
||||||
|
offsetT aim = 0;
|
||||||
|
symbolS *symbolP;
|
||||||
|
const relax_typeS *this_type;
|
||||||
|
const relax_typeS *start_type;
|
||||||
|
relax_substateT next_state;
|
||||||
|
relax_substateT this_state;
|
||||||
|
const relax_typeS *table = TC_GENERIC_RELAX_TABLE;
|
||||||
|
|
||||||
|
/* We only have to cope with frags as prepared by
|
||||||
|
md_estimate_size_before_relax. The dword cases may geet here
|
||||||
|
because of the different reasons that they aren't relaxable. */
|
||||||
|
switch (fragP->fr_subtype)
|
||||||
|
{
|
||||||
|
case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_DWORD):
|
||||||
|
case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_DWORD):
|
||||||
|
/* When we get to these states, the frag won't grow any more. */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_WORD):
|
||||||
|
case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_BYTE):
|
||||||
|
if (fragP->fr_symbol == NULL
|
||||||
|
|| S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
|
||||||
|
as_fatal (_("internal inconsistency problem in %s: fr_symbol %lx"),
|
||||||
|
__FUNCTION__, (long) fragP->fr_symbol);
|
||||||
|
symbolP = fragP->fr_symbol;
|
||||||
|
if (symbol_resolved_p (symbolP))
|
||||||
|
as_fatal (_("internal inconsistency problem in %s: resolved symbol"),
|
||||||
|
__FUNCTION__);
|
||||||
|
aim = S_GET_VALUE (symbolP);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
as_fatal (_("internal inconsistency problem in %s: fr_subtype %d"),
|
||||||
|
__FUNCTION__, fragP->fr_subtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The rest is stolen from relax_frag. There's no obvious way to
|
||||||
|
share the code, but fortunately no requirement to keep in sync as
|
||||||
|
long as fragP->fr_symbol does not have its segment changed. */
|
||||||
|
|
||||||
|
this_state = fragP->fr_subtype;
|
||||||
|
start_type = this_type = table + this_state;
|
||||||
|
|
||||||
|
if (aim < 0)
|
||||||
|
{
|
||||||
|
/* Look backwards. */
|
||||||
|
for (next_state = this_type->rlx_more; next_state;)
|
||||||
|
if (aim >= this_type->rlx_backward)
|
||||||
|
next_state = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Grow to next state. */
|
||||||
|
this_state = next_state;
|
||||||
|
this_type = table + this_state;
|
||||||
|
next_state = this_type->rlx_more;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Look forwards. */
|
||||||
|
for (next_state = this_type->rlx_more; next_state;)
|
||||||
|
if (aim <= this_type->rlx_forward)
|
||||||
|
next_state = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Grow to next state. */
|
||||||
|
this_state = next_state;
|
||||||
|
this_type = table + this_state;
|
||||||
|
next_state = this_type->rlx_more;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
growth = this_type->rlx_length - start_type->rlx_length;
|
||||||
|
if (growth != 0)
|
||||||
|
fragP->fr_subtype = this_state;
|
||||||
|
return growth;
|
||||||
|
}
|
||||||
|
|
||||||
/* Prepare machine-dependent frags for relaxation.
|
/* Prepare machine-dependent frags for relaxation.
|
||||||
|
|
||||||
Called just before relaxation starts. Any symbol that is now undefined
|
Called just before relaxation starts. Any symbol that is now undefined
|
||||||
@@ -386,6 +485,17 @@ md_estimate_size_before_relax (fragP, segment_type)
|
|||||||
= ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_DWORD);
|
= ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_DWORD);
|
||||||
fragP->fr_var = md_cris_relax_table[fragP->fr_subtype].rlx_length;
|
fragP->fr_var = md_cris_relax_table[fragP->fr_subtype].rlx_length;
|
||||||
}
|
}
|
||||||
|
else if (!symbol_resolved_p (fragP->fr_symbol))
|
||||||
|
{
|
||||||
|
/* The symbol will eventually be completely resolved as an
|
||||||
|
absolute expression, but right now it depends on the result
|
||||||
|
of relaxation and we don't know anything else about the
|
||||||
|
value. We start relaxation with the assumption that it'll
|
||||||
|
fit in a byte. */
|
||||||
|
fragP->fr_subtype
|
||||||
|
= ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_BYTE);
|
||||||
|
fragP->fr_var = md_cris_relax_table[fragP->fr_subtype].rlx_length;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Absolute expression. */
|
/* Absolute expression. */
|
||||||
@@ -526,7 +636,10 @@ md_convert_frag (abfd, sec, fragP)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_BYTE):
|
case ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_BYTE):
|
||||||
var_partp[0] = target_address - (address_of_var_part + 1);
|
if (symbolP == NULL)
|
||||||
|
as_fatal (_("internal inconsistency in %s: bdapq no symbol"),
|
||||||
|
__FUNCTION__);
|
||||||
|
opcodep[0] = S_GET_VALUE (symbolP);
|
||||||
var_part_size = 0;
|
var_part_size = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -536,7 +649,10 @@ md_convert_frag (abfd, sec, fragP)
|
|||||||
opcodep[0] = BDAP_PC_LOW + (1 << 4);
|
opcodep[0] = BDAP_PC_LOW + (1 << 4);
|
||||||
opcodep[1] &= 0xF0;
|
opcodep[1] &= 0xF0;
|
||||||
opcodep[1] |= BDAP_INCR_HIGH;
|
opcodep[1] |= BDAP_INCR_HIGH;
|
||||||
md_number_to_chars (var_partp, (long) (target_address), 2);
|
if (symbolP == NULL)
|
||||||
|
as_fatal (_("internal inconsistency in %s: bdap.w with no symbol"),
|
||||||
|
__FUNCTION__);
|
||||||
|
md_number_to_chars (var_partp, S_GET_VALUE (symbolP), 2);
|
||||||
var_part_size = 2;
|
var_part_size = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -813,12 +929,13 @@ md_assemble (str)
|
|||||||
{
|
{
|
||||||
/* Handle complex expressions. */
|
/* Handle complex expressions. */
|
||||||
valueT addvalue
|
valueT addvalue
|
||||||
= (output_instruction.expr.X_op_symbol != NULL
|
= (SIMPLE_EXPR (&output_instruction.expr)
|
||||||
? 0 : output_instruction.expr.X_add_number);
|
? output_instruction.expr.X_add_number
|
||||||
|
: 0);
|
||||||
symbolS *sym
|
symbolS *sym
|
||||||
= (output_instruction.expr.X_op_symbol != NULL
|
= (SIMPLE_EXPR (&output_instruction.expr)
|
||||||
? make_expr_symbol (&output_instruction.expr)
|
? output_instruction.expr.X_add_symbol
|
||||||
: output_instruction.expr.X_add_symbol);
|
: make_expr_symbol (&output_instruction.expr));
|
||||||
|
|
||||||
/* If is_undefined, then the expression may BECOME now_seg. */
|
/* If is_undefined, then the expression may BECOME now_seg. */
|
||||||
length_code = is_undefined ? STATE_UNDF : STATE_BYTE;
|
length_code = is_undefined ? STATE_UNDF : STATE_BYTE;
|
||||||
@@ -2386,10 +2503,10 @@ gen_bdap (base_regno, exprP)
|
|||||||
{
|
{
|
||||||
/* Handle complex expressions. */
|
/* Handle complex expressions. */
|
||||||
valueT addvalue
|
valueT addvalue
|
||||||
= exprP->X_op_symbol != NULL ? 0 : exprP->X_add_number;
|
= SIMPLE_EXPR (exprP) ? exprP->X_add_number : 0;
|
||||||
symbolS *sym
|
symbolS *sym
|
||||||
= (exprP->X_op_symbol != NULL
|
= (SIMPLE_EXPR (exprP)
|
||||||
? make_expr_symbol (exprP) : exprP->X_add_symbol);
|
? exprP->X_add_symbol : make_expr_symbol (exprP));
|
||||||
|
|
||||||
/* The expression is not defined yet but may become absolute. We
|
/* The expression is not defined yet but may become absolute. We
|
||||||
make it a relocation to be relaxed. */
|
make it a relocation to be relaxed. */
|
||||||
|
|||||||
@@ -75,6 +75,16 @@ extern const int md_long_jump_size;
|
|||||||
extern const struct relax_type md_cris_relax_table[];
|
extern const struct relax_type md_cris_relax_table[];
|
||||||
#define TC_GENERIC_RELAX_TABLE md_cris_relax_table
|
#define TC_GENERIC_RELAX_TABLE md_cris_relax_table
|
||||||
|
|
||||||
|
long cris_relax_frag PARAMS ((segT, fragS *, long));
|
||||||
|
|
||||||
|
/* GAS only handles relaxations for pc-relative data targeting addresses
|
||||||
|
in the same segment, so we have to handle the rest on our own. */
|
||||||
|
#define md_relax_frag(SEG, FRAGP, STRETCH) \
|
||||||
|
((FRAGP)->fr_symbol != NULL \
|
||||||
|
&& S_GET_SEGMENT ((FRAGP)->fr_symbol) == (SEG) \
|
||||||
|
? relax_frag (SEG, FRAGP, STRETCH) \
|
||||||
|
: cris_relax_frag (SEG, FRAGP, STRETCH))
|
||||||
|
|
||||||
#define TC_FORCE_RELOCATION(FIX) md_cris_force_relocation (FIX)
|
#define TC_FORCE_RELOCATION(FIX) md_cris_force_relocation (FIX)
|
||||||
extern int md_cris_force_relocation PARAMS ((struct fix *));
|
extern int md_cris_force_relocation PARAMS ((struct fix *));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user