mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-24 20:49:43 +00:00
* 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:
parent
c84e511732
commit
1c97116001
@ -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>
|
||||
|
||||
* 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 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
|
||||
line_separator_chars for CRIS, so we avoid it. */
|
||||
#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.
|
||||
|
||||
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);
|
||||
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
|
||||
{
|
||||
/* Absolute expression. */
|
||||
@ -526,7 +636,10 @@ md_convert_frag (abfd, sec, fragP)
|
||||
break;
|
||||
|
||||
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;
|
||||
break;
|
||||
|
||||
@ -536,7 +649,10 @@ md_convert_frag (abfd, sec, fragP)
|
||||
opcodep[0] = BDAP_PC_LOW + (1 << 4);
|
||||
opcodep[1] &= 0xF0;
|
||||
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;
|
||||
break;
|
||||
|
||||
@ -813,12 +929,13 @@ md_assemble (str)
|
||||
{
|
||||
/* Handle complex expressions. */
|
||||
valueT addvalue
|
||||
= (output_instruction.expr.X_op_symbol != NULL
|
||||
? 0 : output_instruction.expr.X_add_number);
|
||||
= (SIMPLE_EXPR (&output_instruction.expr)
|
||||
? output_instruction.expr.X_add_number
|
||||
: 0);
|
||||
symbolS *sym
|
||||
= (output_instruction.expr.X_op_symbol != NULL
|
||||
? make_expr_symbol (&output_instruction.expr)
|
||||
: output_instruction.expr.X_add_symbol);
|
||||
= (SIMPLE_EXPR (&output_instruction.expr)
|
||||
? output_instruction.expr.X_add_symbol
|
||||
: make_expr_symbol (&output_instruction.expr));
|
||||
|
||||
/* If is_undefined, then the expression may BECOME now_seg. */
|
||||
length_code = is_undefined ? STATE_UNDF : STATE_BYTE;
|
||||
@ -2386,10 +2503,10 @@ gen_bdap (base_regno, exprP)
|
||||
{
|
||||
/* Handle complex expressions. */
|
||||
valueT addvalue
|
||||
= exprP->X_op_symbol != NULL ? 0 : exprP->X_add_number;
|
||||
= SIMPLE_EXPR (exprP) ? exprP->X_add_number : 0;
|
||||
symbolS *sym
|
||||
= (exprP->X_op_symbol != NULL
|
||||
? make_expr_symbol (exprP) : exprP->X_add_symbol);
|
||||
= (SIMPLE_EXPR (exprP)
|
||||
? exprP->X_add_symbol : make_expr_symbol (exprP));
|
||||
|
||||
/* The expression is not defined yet but may become absolute. We
|
||||
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[];
|
||||
#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)
|
||||
extern int md_cris_force_relocation PARAMS ((struct fix *));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user