- <val> and <width> are themselves expressionS.
- <val> stores the expression which when evaluated gives the value of the
start address offset of the FRE.
- - <width> stores the expression when when evaluated gives the number of
- bytes needed to encode the start address offset of the FRE.
+ - <width> stores the expression when evaluated gives the number of bytes
+ needed to encode the start address offset of the FRE.
The use of OP_absent as the X_op_symbol helps identify this expression
later when fragments are fixed up. */
cexp->X_add_number = 0;
}
+/* Create a composite exression CEXP (for SFrame FDE function info) such that:
+
+ exp = <rest_of_func_info> OP_modulus <width>, where,
+
+ - <rest_of_func_info> and <width> are themselves expressionS.
+ - <rest_of_func_info> stores a constant expression where X_add_number is
+ used to stash away the func_info. The upper 4-bits of the func_info are copied
+ back to the resulting byte by the fragment fixup logic.
+ - <width> stores the expression when evaluated gives the size of the
+ funtion in number of bytes.
+
+ The use of OP_modulus as the X_op_symbol helps identify this expression
+ later when fragments are fixed up. */
+
+static void
+create_func_info_exp (expressionS *cexp, symbolS *dw_fde_end_addrS,
+ symbolS *dw_fde_start_addrS, uint8_t func_info)
+{
+ expressionS width;
+ expressionS rest_of_func_info;
+
+ width.X_op = O_subtract;
+ width.X_add_symbol = dw_fde_end_addrS;
+ width.X_op_symbol = dw_fde_start_addrS;
+ width.X_add_number = 0;
+
+ rest_of_func_info.X_op = O_constant;
+ rest_of_func_info.X_add_number = func_info;
+
+ cexp->X_op = O_modulus;
+ cexp->X_add_symbol = make_expr_symbol (&rest_of_func_info);
+ cexp->X_op_symbol = make_expr_symbol (&width);
+ cexp->X_add_number = 0;
+}
+
#endif
static void
out_four (sframe_fde->num_fres);
/* SFrame FDE function info. */
+ unsigned char func_info;
+ func_info = sframe_set_func_info (SFRAME_FDE_TYPE_PCINC,
+ SFRAME_FRE_TYPE_ADDR4);
#if SFRAME_FRE_TYPE_SELECTION_OPT
- expressionS width;
- width.X_op = O_subtract;
- width.X_add_symbol = dw_fde_end_addrS;
- width.X_op_symbol = dw_fde_start_addrS;
- width.X_add_number = 0;
+ expressionS cexp;
+ create_func_info_exp (&cexp, dw_fde_end_addrS, dw_fde_start_addrS,
+ func_info);
frag_grow (1); /* Size of func info is unsigned char. */
frag_var (rs_sframe, 1, 0, (relax_substateT) 0,
- make_expr_symbol (&width), 0, (char *) frag_now);
+ make_expr_symbol (&cexp), 0, (char *) frag_now);
#else
- unsigned char func_info;
- func_info = sframe_set_func_info (SFRAME_FDE_TYPE_PCINC,
- SFRAME_FRE_TYPE_ADDR4);
out_one (func_info);
#endif
}
The two kind of fragments can be differentiated based on the opcode
of the symbol. */
exp = symbol_get_value_expression (frag->fr_symbol);
- gas_assert ((exp->X_op == O_subtract) || (exp->X_op == O_absent));
+ gas_assert ((exp->X_op == O_modulus) || (exp->X_op == O_absent));
/* Fragment for function info in an SFrame FDE will always write
only one byte. */
- if (exp->X_op == O_subtract)
+ if (exp->X_op == O_modulus)
ret = 1;
/* Fragment for the start address in an SFrame FRE may write out
1/2/4 bytes depending on the value of the diff. */
offsetT fsize;
offsetT diff;
offsetT value;
- unsigned char func_info = SFRAME_FRE_TYPE_ADDR4;
+
+ offsetT rest_of_data;
+ uint8_t fde_type, fre_type;
+
expressionS *exp;
+ symbolS *dataS;
symbolS *fsizeS, *diffS;
/* We are dealing with two different kind of fragments here which need
The two kind of fragments can be differentiated based on the opcode
of the symbol. */
exp = symbol_get_value_expression (frag->fr_symbol);
- gas_assert ((exp->X_op == O_subtract) || (exp->X_op == O_absent));
+ gas_assert ((exp->X_op == O_modulus) || (exp->X_op == O_absent));
/* Fragment for function info in an SFrame FDE. */
- if (exp->X_op == O_subtract)
+ if (exp->X_op == O_modulus)
{
- fsizeS = frag->fr_symbol;
+ /* Gather the existing value of the rest of the data except
+ the fre_type. */
+ dataS = exp->X_add_symbol;
+ rest_of_data = (symbol_get_value_expression(dataS))->X_add_number;
+ fde_type = SFRAME_V1_FUNC_FDE_TYPE (rest_of_data);
+ gas_assert (fde_type == SFRAME_FDE_TYPE_PCINC);
+
+ /* Calculate the applicable fre_type. */
+ fsizeS = exp->X_op_symbol;
fsize = resolve_symbol_value (fsizeS);
if (fsize < SFRAME_FRE_TYPE_ADDR1_LIMIT)
- func_info = SFRAME_FRE_TYPE_ADDR1;
+ fre_type = SFRAME_FRE_TYPE_ADDR1;
else if (fsize < SFRAME_FRE_TYPE_ADDR2_LIMIT)
- func_info = SFRAME_FRE_TYPE_ADDR2;
+ fre_type = SFRAME_FRE_TYPE_ADDR2;
else
- func_info = SFRAME_FRE_TYPE_ADDR4;
- value = func_info;
+ fre_type = SFRAME_FRE_TYPE_ADDR4;
+
+ /* Create the new function info. */
+ value = SFRAME_V1_FUNC_INFO (fde_type, fre_type);
frag->fr_literal[frag->fr_fix] = value;
}