+2020-01-15 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/tc-msp430.c (CHECK_RELOC_MSP430): Always generate 430X
+ relocations when the target is 430X, except when extracting part of an
+ expression.
+ (msp430_srcoperand): Adjust comment.
+ Initialize the expp member of the msp430_operand_s struct as
+ appropriate.
+ (msp430_dstoperand): Likewise.
+ * testsuite/gas/msp430/msp430.exp: Run new test.
+ * testsuite/gas/msp430/reloc-lo-430x.d: New test.
+ * testsuite/gas/msp430/reloc-lo-430x.s: New test.
+
2020-01-15 Alan Modra <amodra@gmail.com>
* configure.tgt: Add sparc-*-freebsd case.
return selected_isa == MSP_ISA_430Xv2;
}
-/* Generate an absolute 16-bit relocation.
- For the 430X we generate a relocation without linker range checking
- if the value is being used in an extended (ie 20-bit) instruction,
- otherwise if have a shifted expression we use a HI reloc.
+/* Generate an absolute 16-bit relocation, for 430 (!extended_op) instructions
+ only.
+ For the 430X we generate a 430 relocation only for the case where part of an
+ expression is being extracted (e.g. #hi(EXP), #lo(EXP). Otherwise generate
+ a 430X relocation.
For the 430 we generate a relocation without assembler range checking
- if we are handling an immediate value or a byte-width instruction. */
+ if we are handling an immediate value or a byte-width instruction. */
#undef CHECK_RELOC_MSP430
#define CHECK_RELOC_MSP430(OP) \
(target_is_430x () \
- ? (extended_op \
- ? BFD_RELOC_16 \
- : ((OP).vshift == 1) \
- ? BFD_RELOC_MSP430_ABS_HI16 \
- : BFD_RELOC_MSP430X_ABS16) \
+ ? ((OP).expp == MSP_EXPP_ALL \
+ ? BFD_RELOC_MSP430X_ABS16 \
+ : ((OP).vshift == 1 \
+ ? BFD_RELOC_MSP430_ABS_HI16 : BFD_RELOC_16)) \
: ((imm_op || byte_op) \
? BFD_RELOC_MSP430_16_BYTE : BFD_RELOC_MSP430_16))
char *h = l;
int vshift = -1;
int rval = 0;
+ /* Use all parts of the constant expression by default. */
+ enum msp430_expp_e expp = MSP_EXPP_ALL;
/* Check if there is:
llo(x) - least significant 16 bits, x &= 0xffff
lhi(x) - x = (x >> 16) & 0xffff,
hlo(x) - x = (x >> 32) & 0xffff,
hhi(x) - x = (x >> 48) & 0xffff
- The value _MUST_ be constant expression: #hlo(1231231231). */
+ The value _MUST_ be an immediate expression: #hlo(1231231231). */
*imm_op = TRUE;
{
vshift = 0;
rval = 3;
+ expp = MSP_EXPP_LLO;
}
else if (strncasecmp (h, "#lhi(", 5) == 0)
{
vshift = 1;
rval = 3;
+ expp = MSP_EXPP_LHI;
}
else if (strncasecmp (h, "#hlo(", 5) == 0)
{
vshift = 2;
rval = 3;
+ expp = MSP_EXPP_HLO;
}
else if (strncasecmp (h, "#hhi(", 5) == 0)
{
vshift = 3;
rval = 3;
+ expp = MSP_EXPP_HHI;
}
else if (strncasecmp (h, "#lo(", 4) == 0)
{
vshift = 0;
rval = 2;
+ expp = MSP_EXPP_LO;
}
else if (strncasecmp (h, "#hi(", 4) == 0)
{
vshift = 1;
rval = 2;
+ expp = MSP_EXPP_HI;
}
op->reg = 0; /* Reg PC. */
__tl = h + 1 + rval;
op->mode = OP_EXP;
op->vshift = vshift;
+ op->expp = expp;
end = parse_exp (__tl, &(op->exp));
if (end != NULL && *end != 0 && *end != ')' )
}
op->mode = OP_EXP;
op->vshift = 0;
+ op->expp = MSP_EXPP_ALL;
if (op->exp.X_op == O_constant)
{
int x = op->exp.X_add_number;
*h = 0;
op->mode = OP_EXP;
op->vshift = 0;
+ op->expp = MSP_EXPP_ALL;
end = parse_exp (__tl, &(op->exp));
if (end != NULL && *end != 0)
{
op->am = (*l == '-' ? 3 : 1);
op->ol = 1;
op->vshift = 0;
+ op->expp = MSP_EXPP_ALL;
__tl = l;
end = parse_exp (__tl, &(op->exp));
if (end != NULL && * end != 0)
op->am = 1;
op->ol = 1;
op->vshift = 0;
+ op->expp = MSP_EXPP_ALL;
(void) parse_exp (__tl, &(op->exp));
if (op->exp.X_op != O_constant || op->exp.X_add_number != 0)
#ifndef __MSP430_H_
#define __MSP430_H_
+enum msp430_expp_e
+{
+ MSP_EXPP_ALL = 0, /* Use full the value of the expression - default. */
+ MSP_EXPP_LO, /* Extract least significant word from expression. */
+ MSP_EXPP_HI, /* Extract 2nd word from expression. */
+ MSP_EXPP_LLO, /* Extract least significant word from an
+ immediate value. */
+ MSP_EXPP_LHI, /* Extract 2nd word from an immediate value. */
+ MSP_EXPP_HLO, /* Extract 3rd word from an immediate value. */
+ MSP_EXPP_HHI, /* Extract 4th word from an immediate value. */
+};
+
struct msp430_operand_s
{
int ol; /* Operand length words. */
int reg; /* Register. */
int mode; /* Operand mode. */
int vshift; /* Number of bytes to shift operand down. */
+ enum msp430_expp_e expp; /* For when the operand is a constant
+ expression, the part of the expression to
+ extract. */
#define OP_REG 0
#define OP_EXP 1
#ifndef DASM_SECTION