}
static void
-my_getExpression (expressionS *ep, char *str)
+my_getExpression (expressionS *ep, char *str, bool defer)
{
char *save_in;
save_in = input_line_pointer;
input_line_pointer = str;
- expression (ep);
+ if (defer)
+ deferred_expression (ep);
+ else
+ expression (ep);
expr_parse_end = input_line_pointer;
input_line_pointer = save_in;
}
size_t reloc_index;
unsigned crux_depth, str_depth;
bool orig_probing = probing_insn_operands;
+ bool force_reloc = false;
char *crux;
/* Search for the start of the main expression.
if (str_depth || reloc_index)
probing_insn_operands = false;
- my_getExpression (ep, crux);
+ if (*reloc == BFD_RELOC_RISCV_GOT_HI20)
+ force_reloc = true;
+
+ my_getExpression (ep, crux, force_reloc);
str = expr_parse_end;
probing_insn_operands = orig_probing;
}
else
{
- my_getExpression (ep, str);
+ my_getExpression (ep, str, false/* defer */);
str = expr_parse_end;
}
}
}
else
{
- my_getExpression (ep, str);
+ my_getExpression (ep, str, false/* defer */);
str = expr_parse_end;
}
}
error.missing_ext = NULL;
/* Indicate we are assembling instruction with CSR. */
bool insn_with_csr = false;
+ bool force_reloc = false;
/* Parse the name of the instruction. Terminate the string if whitespace
is found so that str_hash_find only sees the name part of the string. */
continue;
case 'i': /* vector arith signed immediate */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
if (imm_expr->X_add_number > 15
|| imm_expr->X_add_number < -16)
continue;
case 'j': /* vector arith unsigned immediate */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
if (imm_expr->X_add_number < 0
|| imm_expr->X_add_number >= 32)
continue;
case 'k': /* vector arith signed immediate, minus 1 */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
if (imm_expr->X_add_number > 16
|| imm_expr->X_add_number < -15)
continue;
case 'l': /* 6-bit vector arith unsigned immediate */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
if (imm_expr->X_add_number < 0
|| imm_expr->X_add_number >= 64)
break;
case '<': /* Shift amount, 0 - 31. */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, false);
if ((unsigned long) imm_expr->X_add_number > 31)
as_bad (_("improper shift amount (%"PRIu64")"),
continue;
case '>': /* Shift amount, 0 - (XLEN-1). */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, false);
if ((unsigned long) imm_expr->X_add_number >= xlen)
as_bad (_("improper shift amount (%"PRIu64")"),
continue;
case 'Z': /* CSRRxI immediate. */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, false);
if ((unsigned long) imm_expr->X_add_number > 31)
as_bad (_("improper CSRxI immediate (%"PRIu64")"),
INSERT_OPERAND (CSR, *ip, regno);
else
{
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, true);
if ((unsigned long) imm_expr->X_add_number > 0xfff)
as_bad (_("improper CSR address (%"PRIu64")"),
break;
case 'I':
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
if (imm_expr->X_op != O_big
&& imm_expr->X_op != O_constant)
break;
continue;
case 'A':
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
normalize_constant_expr (imm_expr);
/* The 'A' format specifier must be a symbol. */
if (imm_expr->X_op != O_symbol)
continue;
case 'B':
- my_getExpression (imm_expr, asarg);
+ if (ip->insn_mo->mask == M_LGA
+ || (riscv_opts.pic && ip->insn_mo->mask == M_LA))
+ force_reloc = true;
+ my_getExpression (imm_expr, asarg, force_reloc);
normalize_constant_expr (imm_expr);
/* The 'B' format specifier must be a symbol or a constant. */
if (imm_expr->X_op != O_symbol && imm_expr->X_op != O_constant)
case 'p': /* PC-relative offset. */
branch:
*imm_reloc = BFD_RELOC_12_PCREL;
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
asarg = expr_parse_end;
continue;
case 'a': /* 20-bit PC-relative offset. */
jump:
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
asarg = expr_parse_end;
*imm_reloc = BFD_RELOC_RISCV_JMP;
continue;
case 'c':
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
asarg = expr_parse_end;
if (strcmp (asarg, "@plt") == 0)
asarg += 4;
break;
case 'y': /* bs immediate */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
if ((unsigned long)imm_expr->X_add_number > 3)
as_bad(_("Improper bs immediate (%lu)"),
continue;
case 'Y': /* rnum immediate */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
if ((unsigned long)imm_expr->X_add_number > 10)
as_bad(_("Improper rnum immediate (%lu)"),
pseudo S-type but lower 5-bits zero. */
if (riscv_handle_implicit_zero_offset (imm_expr, asarg))
continue;
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, false);
if (((unsigned) (imm_expr->X_add_number) & 0x1fU)
|| imm_expr->X_add_number >= RISCV_IMM_REACH / 2
s = strtol (oparg + 1, (char **)&oparg, 10);
oparg--;
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, false);
if (!sign)
{
switch (*++oparg)
{
case '2':
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
asarg = expr_parse_end;
if (imm_expr->X_add_number<0
|= ENCODE_CV_IS2_UIMM5 (imm_expr->X_add_number);
continue;
case '3':
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
asarg = expr_parse_end;
if (imm_expr->X_add_number < 0
|= ENCODE_CV_IS3_UIMM5 (imm_expr->X_add_number);
continue;
case '4':
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
asarg = expr_parse_end;
if (imm_expr->X_add_number < -16
|= ENCODE_CV_IS2_UIMM5 (imm_expr->X_add_number);
continue;
case '5':
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
asarg = expr_parse_end;
if (imm_expr->X_add_number < -32
|= ENCODE_CV_SIMD_IMM6 (imm_expr->X_add_number);
continue;
case '6':
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
asarg = expr_parse_end;
if (imm_expr->X_add_number < 0
|= ENCODE_CV_BITMANIP_UIMM5 (imm_expr->X_add_number);
continue;
case '7':
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
asarg = expr_parse_end;
if (imm_expr->X_add_number < 0
|= ENCODE_CV_BITMANIP_UIMM2 (imm_expr->X_add_number);
continue;
case '8':
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
asarg = expr_parse_end;
++oparg;
switch (*++oparg)
{
case '@': /* hint 0 - 31. */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
if ((unsigned long)imm_expr->X_add_number > 31)
as_bad(_("Improper hint amount (%lu)"),
continue;
case '#': /* immediate 0 - 511. */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
if ((unsigned long)imm_expr->X_add_number > 511)
as_bad(_("Improper immediate amount (%lu)"),
continue;
case '$': /* LDP offset 0 to (1<<7)-8. */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
if ((unsigned long)imm_expr->X_add_number >= (1 << 7)
|| ((unsigned long)imm_expr->X_add_number & 0x7) != 0)
continue;
case '%': /* LWP offset 0 to (1<<7)-4. */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
if ((unsigned long)imm_expr->X_add_number >= (1 << 7)
|| ((unsigned long)imm_expr->X_add_number & 0x3) != 0)
continue;
case '^': /* SDP offset 0 to (1<<7)-8. */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
if ((unsigned long)imm_expr->X_add_number >= (1 << 7)
|| ((unsigned long)imm_expr->X_add_number & 0x7) != 0)
continue;
case '&': /* SWP offset 0 to (1<<7)-4. */
- my_getExpression (imm_expr, asarg);
+ my_getExpression (imm_expr, asarg, force_reloc);
check_absolute_expr (ip, imm_expr, FALSE);
if ((unsigned long)imm_expr->X_add_number >= (1 << 7)
|| ((unsigned long)imm_expr->X_add_number & 0x3) != 0)
if (!probing_insn_operands)
return false;
- gas_assert (mode == expr_normal);
+ gas_assert (mode == expr_normal || expr_defer_p (mode));
regno = reg_lookup_internal (name, RCLASS_GPR);
if (regno == -1u)