Improve gas error messages for invalid instructions.

* cpu-ia64-opc.c (elf64_ia64_operands}: Fix typo: error string for
	C8 said "1" instead of "8".  Clarify error string for IMM22:
	"signed integer" instead of just "integer".
	* config/tc-ia64.c (enum operand_match_result): New type.
	(operand_match): Change return type to operand_match_result.
	Fix all returns appropriately, adding support for returning the
	out-of-range result.
	(parse_operands): New locals result, error_pos, out_of_range_pos,
	curr_out_of_range_pos.  Rewrite operand matching loop to give better
	error messages.
	* ia64-opc-d.c (ia64_opcodes_d): Break the "add" pattern into two
	separate variants: one for IMM22 and the other for IMM14.
	* ia64-asmtab.c: Regenerate.
This commit is contained in:
Jim Wilson 2001-02-22 03:16:21 +00:00
parent aacc1edd3a
commit 87f8eb977e
7 changed files with 4146 additions and 4012 deletions

View File

@ -1,3 +1,9 @@
2001-02-21 David Mosberger <davidm@hpl.hp.com>
* cpu-ia64-opc.c (elf64_ia64_operands}: Fix typo: error string for
C8 said "1" instead of "8". Clarify error string for IMM22:
"signed integer" instead of just "integer".
2001-02-20 Andreas Jaeger <aj@suse.de> 2001-02-20 Andreas Jaeger <aj@suse.de>
* elf64-x86-64.c (elf64_x86_64_finish_dynamic_symbol): Don't make * elf64-x86-64.c (elf64_x86_64_finish_dynamic_symbol): Don't make

View File

@ -421,7 +421,7 @@ const struct ia64_operand elf64_ia64_operands[IA64_OPND_COUNT] =
{ CST, ins_const, ext_const, "ar.ccv", {{ 0, 0}}, 0, "ar.ccv" }, { CST, ins_const, ext_const, "ar.ccv", {{ 0, 0}}, 0, "ar.ccv" },
{ CST, ins_const, ext_const, "ar.pfs", {{ 0, 0}}, 0, "ar.pfs" }, { CST, ins_const, ext_const, "ar.pfs", {{ 0, 0}}, 0, "ar.pfs" },
{ CST, ins_const, ext_const, "1", {{ 0, 0}}, 0, "1" }, { CST, ins_const, ext_const, "1", {{ 0, 0}}, 0, "1" },
{ CST, ins_const, ext_const, "8", {{ 0, 0}}, 0, "1" }, { CST, ins_const, ext_const, "8", {{ 0, 0}}, 0, "8" },
{ CST, ins_const, ext_const, "16", {{ 0, 0}}, 0, "16" }, { CST, ins_const, ext_const, "16", {{ 0, 0}}, 0, "16" },
{ CST, ins_const, ext_const, "r0", {{ 0, 0}}, 0, "r0" }, { CST, ins_const, ext_const, "r0", {{ 0, 0}}, 0, "r0" },
{ CST, ins_const, ext_const, "ip", {{ 0, 0}}, 0, "ip" }, { CST, ins_const, ext_const, "ip", {{ 0, 0}}, 0, "ip" },
@ -551,7 +551,7 @@ const struct ia64_operand elf64_ia64_operands[IA64_OPND_COUNT] =
"a 21-bit unsigned" }, "a 21-bit unsigned" },
{ ABS, ins_imms, ext_imms, 0, /* IMM22 */ { ABS, ins_imms, ext_imms, 0, /* IMM22 */
{{ 7, 13}, { 9, 27}, { 5, 22}, { 1, 36}}, SDEC, {{ 7, 13}, { 9, 27}, { 5, 22}, { 1, 36}}, SDEC,
"a 22-bit integer" }, "a 22-bit signed integer" },
{ ABS, ins_immu, ext_immu, 0, /* IMMU24 */ { ABS, ins_immu, ext_immu, 0, /* IMMU24 */
{{21, 6}, { 2, 31}, { 1, 36}}, 0, {{21, 6}, { 2, 31}, { 1, 36}}, 0,
"a 24-bit unsigned" }, "a 24-bit unsigned" },

View File

@ -1,3 +1,13 @@
2001-02-21 David Mosberger <davidm@hpl.hp.com>
* config/tc-ia64.c (enum operand_match_result): New type.
(operand_match): Change return type to operand_match_result.
Fix all returns appropriately, adding support for returning the
out-of-range result.
(parse_operands): New locals result, error_pos, out_of_range_pos,
curr_out_of_range_pos. Rewrite operand matching loop to give better
error messages.
2001-02-21 David Mosberger <davidm@hpl.hp.com> 2001-02-21 David Mosberger <davidm@hpl.hp.com>
* config/tc-ia64.c (struct unwind): Add member "prologue_count". * config/tc-ia64.c (struct unwind): Add member "prologue_count".

View File

@ -124,6 +124,13 @@ enum dynreg_type
DYNREG_NUM_TYPES DYNREG_NUM_TYPES
}; };
enum operand_match_result
{
OPERAND_MATCH,
OPERAND_OUT_OF_RANGE,
OPERAND_MISMATCH
};
/* On the ia64, we can't know the address of a text label until the /* On the ia64, we can't know the address of a text label until the
instructions are packed into a bundle. To handle this, we keep instructions are packed into a bundle. To handle this, we keep
track of the list of labels that appear in front of each track of the list of labels that appear in front of each
@ -690,8 +697,9 @@ static void add_unwind_entry PARAMS((unw_rec_list *ptr));
static symbolS *declare_register PARAMS ((const char *name, int regnum)); static symbolS *declare_register PARAMS ((const char *name, int regnum));
static void declare_register_set PARAMS ((const char *, int, int)); static void declare_register_set PARAMS ((const char *, int, int));
static unsigned int operand_width PARAMS ((enum ia64_opnd)); static unsigned int operand_width PARAMS ((enum ia64_opnd));
static int operand_match PARAMS ((const struct ia64_opcode *idesc, static enum operand_match_result operand_match PARAMS ((const struct ia64_opcode *idesc,
int index, expressionS *e)); int index,
expressionS *e));
static int parse_operand PARAMS ((expressionS *e)); static int parse_operand PARAMS ((expressionS *e));
static struct ia64_opcode * parse_operands PARAMS ((struct ia64_opcode *)); static struct ia64_opcode * parse_operands PARAMS ((struct ia64_opcode *));
static void build_insn PARAMS ((struct slot *, bfd_vma *)); static void build_insn PARAMS ((struct slot *, bfd_vma *));
@ -4740,7 +4748,7 @@ operand_width (opnd)
return bits; return bits;
} }
static int static enum operand_match_result
operand_match (idesc, index, e) operand_match (idesc, index, e)
const struct ia64_opcode *idesc; const struct ia64_opcode *idesc;
int index; int index;
@ -4757,62 +4765,77 @@ operand_match (idesc, index, e)
case IA64_OPND_AR_CCV: case IA64_OPND_AR_CCV:
if (e->X_op == O_register && e->X_add_number == REG_AR + 32) if (e->X_op == O_register && e->X_add_number == REG_AR + 32)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_AR_PFS: case IA64_OPND_AR_PFS:
if (e->X_op == O_register && e->X_add_number == REG_AR + 64) if (e->X_op == O_register && e->X_add_number == REG_AR + 64)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_GR0: case IA64_OPND_GR0:
if (e->X_op == O_register && e->X_add_number == REG_GR + 0) if (e->X_op == O_register && e->X_add_number == REG_GR + 0)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_IP: case IA64_OPND_IP:
if (e->X_op == O_register && e->X_add_number == REG_IP) if (e->X_op == O_register && e->X_add_number == REG_IP)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_PR: case IA64_OPND_PR:
if (e->X_op == O_register && e->X_add_number == REG_PR) if (e->X_op == O_register && e->X_add_number == REG_PR)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_PR_ROT: case IA64_OPND_PR_ROT:
if (e->X_op == O_register && e->X_add_number == REG_PR_ROT) if (e->X_op == O_register && e->X_add_number == REG_PR_ROT)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_PSR: case IA64_OPND_PSR:
if (e->X_op == O_register && e->X_add_number == REG_PSR) if (e->X_op == O_register && e->X_add_number == REG_PSR)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_PSR_L: case IA64_OPND_PSR_L:
if (e->X_op == O_register && e->X_add_number == REG_PSR_L) if (e->X_op == O_register && e->X_add_number == REG_PSR_L)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_PSR_UM: case IA64_OPND_PSR_UM:
if (e->X_op == O_register && e->X_add_number == REG_PSR_UM) if (e->X_op == O_register && e->X_add_number == REG_PSR_UM)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_C1: case IA64_OPND_C1:
if (e->X_op == O_constant && e->X_add_number == 1) if (e->X_op == O_constant)
return 1; {
if (e->X_add_number == 1)
return OPERAND_MATCH;
else
return OPERAND_OUT_OF_RANGE;
}
break; break;
case IA64_OPND_C8: case IA64_OPND_C8:
if (e->X_op == O_constant && e->X_add_number == 8) if (e->X_op == O_constant)
return 1; {
if (e->X_add_number == 8)
return OPERAND_MATCH;
else
return OPERAND_OUT_OF_RANGE;
}
break; break;
case IA64_OPND_C16: case IA64_OPND_C16:
if (e->X_op == O_constant && e->X_add_number == 16) if (e->X_op == O_constant)
return 1; {
if (e->X_add_number == 16)
return OPERAND_MATCH;
else
return OPERAND_OUT_OF_RANGE;
}
break; break;
/* register operands: */ /* register operands: */
@ -4820,20 +4843,20 @@ operand_match (idesc, index, e)
case IA64_OPND_AR3: case IA64_OPND_AR3:
if (e->X_op == O_register && e->X_add_number >= REG_AR if (e->X_op == O_register && e->X_add_number >= REG_AR
&& e->X_add_number < REG_AR + 128) && e->X_add_number < REG_AR + 128)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_B1: case IA64_OPND_B1:
case IA64_OPND_B2: case IA64_OPND_B2:
if (e->X_op == O_register && e->X_add_number >= REG_BR if (e->X_op == O_register && e->X_add_number >= REG_BR
&& e->X_add_number < REG_BR + 8) && e->X_add_number < REG_BR + 8)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_CR3: case IA64_OPND_CR3:
if (e->X_op == O_register && e->X_add_number >= REG_CR if (e->X_op == O_register && e->X_add_number >= REG_CR
&& e->X_add_number < REG_CR + 128) && e->X_add_number < REG_CR + 128)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_F1: case IA64_OPND_F1:
@ -4842,14 +4865,14 @@ operand_match (idesc, index, e)
case IA64_OPND_F4: case IA64_OPND_F4:
if (e->X_op == O_register && e->X_add_number >= REG_FR if (e->X_op == O_register && e->X_add_number >= REG_FR
&& e->X_add_number < REG_FR + 128) && e->X_add_number < REG_FR + 128)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_P1: case IA64_OPND_P1:
case IA64_OPND_P2: case IA64_OPND_P2:
if (e->X_op == O_register && e->X_add_number >= REG_P if (e->X_op == O_register && e->X_add_number >= REG_P
&& e->X_add_number < REG_P + 64) && e->X_add_number < REG_P + 64)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_R1: case IA64_OPND_R1:
@ -4857,13 +4880,17 @@ operand_match (idesc, index, e)
case IA64_OPND_R3: case IA64_OPND_R3:
if (e->X_op == O_register && e->X_add_number >= REG_GR if (e->X_op == O_register && e->X_add_number >= REG_GR
&& e->X_add_number < REG_GR + 128) && e->X_add_number < REG_GR + 128)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_R3_2: case IA64_OPND_R3_2:
if (e->X_op == O_register && e->X_add_number >= REG_GR if (e->X_op == O_register && e->X_add_number >= REG_GR)
&& e->X_add_number < REG_GR + 4) {
return 1; if (e->X_add_number < REG_GR + 4)
return OPERAND_MATCH;
else if (e->X_add_number < REG_GR + 128)
return OPERAND_OUT_OF_RANGE;
}
break; break;
/* indirect operands: */ /* indirect operands: */
@ -4880,12 +4907,12 @@ operand_match (idesc, index, e)
if (e->X_op == O_index && e->X_op_symbol if (e->X_op == O_index && e->X_op_symbol
&& (S_GET_VALUE (e->X_op_symbol) - IND_CPUID && (S_GET_VALUE (e->X_op_symbol) - IND_CPUID
== opnd - IA64_OPND_CPUID_R3)) == opnd - IA64_OPND_CPUID_R3))
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_MR3: case IA64_OPND_MR3:
if (e->X_op == O_index && !e->X_op_symbol) if (e->X_op == O_index && !e->X_op_symbol)
return 1; return OPERAND_MATCH;
break; break;
/* immediate operands: */ /* immediate operands: */
@ -4893,40 +4920,58 @@ operand_match (idesc, index, e)
case IA64_OPND_LEN4: case IA64_OPND_LEN4:
case IA64_OPND_LEN6: case IA64_OPND_LEN6:
bits = operand_width (idesc->operands[index]); bits = operand_width (idesc->operands[index]);
if (e->X_op == O_constant if (e->X_op == O_constant)
&& (bfd_vma) (e->X_add_number - 1) < ((bfd_vma) 1 << bits)) {
return 1; if ((bfd_vma) (e->X_add_number - 1) < ((bfd_vma) 1 << bits))
return OPERAND_MATCH;
else
return OPERAND_OUT_OF_RANGE;
}
break; break;
case IA64_OPND_CNT2b: case IA64_OPND_CNT2b:
if (e->X_op == O_constant if (e->X_op == O_constant)
&& (bfd_vma) (e->X_add_number - 1) < 3) {
return 1; if ((bfd_vma) (e->X_add_number - 1) < 3)
return OPERAND_MATCH;
else
return OPERAND_OUT_OF_RANGE;
}
break; break;
case IA64_OPND_CNT2c: case IA64_OPND_CNT2c:
val = e->X_add_number; val = e->X_add_number;
if (e->X_op == O_constant if (e->X_op == O_constant)
&& (val == 0 || val == 7 || val == 15 || val == 16)) {
return 1; if ((val == 0 || val == 7 || val == 15 || val == 16))
return OPERAND_MATCH;
else
return OPERAND_OUT_OF_RANGE;
}
break; break;
case IA64_OPND_SOR: case IA64_OPND_SOR:
/* SOR must be an integer multiple of 8 */ /* SOR must be an integer multiple of 8 */
if (e->X_add_number & 0x7) if (e->X_op == O_constant && e->X_add_number & 0x7)
break; return OPERAND_OUT_OF_RANGE;
case IA64_OPND_SOF: case IA64_OPND_SOF:
case IA64_OPND_SOL: case IA64_OPND_SOL:
if (e->X_op == O_constant && if (e->X_op == O_constant)
(bfd_vma) e->X_add_number <= 96) {
return 1; if ((bfd_vma) e->X_add_number <= 96)
return OPERAND_MATCH;
else
return OPERAND_OUT_OF_RANGE;
}
break; break;
case IA64_OPND_IMMU62: case IA64_OPND_IMMU62:
if (e->X_op == O_constant) if (e->X_op == O_constant)
{ {
if ((bfd_vma) e->X_add_number < ((bfd_vma) 1 << 62)) if ((bfd_vma) e->X_add_number < ((bfd_vma) 1 << 62))
return 1; return OPERAND_MATCH;
else
return OPERAND_OUT_OF_RANGE;
} }
else else
{ {
@ -4952,10 +4997,10 @@ operand_match (idesc, index, e)
fix->expr = *e; fix->expr = *e;
fix->is_pcrel = 0; fix->is_pcrel = 0;
++CURR_SLOT.num_fixups; ++CURR_SLOT.num_fixups;
return 1; return OPERAND_MATCH;
} }
else if (e->X_op == O_constant) else if (e->X_op == O_constant)
return 1; return OPERAND_MATCH;
break; break;
case IA64_OPND_CCNT5: case IA64_OPND_CCNT5:
@ -4973,30 +5018,42 @@ operand_match (idesc, index, e)
case IA64_OPND_MHTYPE8: case IA64_OPND_MHTYPE8:
case IA64_OPND_POS6: case IA64_OPND_POS6:
bits = operand_width (idesc->operands[index]); bits = operand_width (idesc->operands[index]);
if (e->X_op == O_constant if (e->X_op == O_constant)
&& (bfd_vma) e->X_add_number < ((bfd_vma) 1 << bits)) {
return 1; if ((bfd_vma) e->X_add_number < ((bfd_vma) 1 << bits))
return OPERAND_MATCH;
else
return OPERAND_OUT_OF_RANGE;
}
break; break;
case IA64_OPND_IMMU9: case IA64_OPND_IMMU9:
bits = operand_width (idesc->operands[index]); bits = operand_width (idesc->operands[index]);
if (e->X_op == O_constant if (e->X_op == O_constant)
&& (bfd_vma) e->X_add_number < ((bfd_vma) 1 << bits)) {
if ((bfd_vma) e->X_add_number < ((bfd_vma) 1 << bits))
{ {
int lobits = e->X_add_number & 0x3; int lobits = e->X_add_number & 0x3;
if (((bfd_vma) e->X_add_number & 0x3C) != 0 && lobits == 0) if (((bfd_vma) e->X_add_number & 0x3C) != 0 && lobits == 0)
e->X_add_number |= (bfd_vma) 0x3; e->X_add_number |= (bfd_vma) 0x3;
return 1; return OPERAND_MATCH;
}
else
return OPERAND_OUT_OF_RANGE;
} }
break; break;
case IA64_OPND_IMM44: case IA64_OPND_IMM44:
/* least 16 bits must be zero */ /* least 16 bits must be zero */
if ((e->X_add_number & 0xffff) != 0) if ((e->X_add_number & 0xffff) != 0)
/* XXX technically, this is wrong: we should not be issuing warning
messages until we're sure this instruction pattern is going to
be used! */
as_warn (_("lower 16 bits of mask ignored")); as_warn (_("lower 16 bits of mask ignored"));
if (e->X_op == O_constant if (e->X_op == O_constant)
&& ((e->X_add_number >= 0 {
if (((e->X_add_number >= 0
&& (bfd_vma) e->X_add_number < ((bfd_vma) 1 << 44)) && (bfd_vma) e->X_add_number < ((bfd_vma) 1 << 44))
|| (e->X_add_number < 0 || (e->X_add_number < 0
&& (bfd_vma) -e->X_add_number <= ((bfd_vma) 1 << 44)))) && (bfd_vma) -e->X_add_number <= ((bfd_vma) 1 << 44))))
@ -5007,14 +5064,18 @@ operand_match (idesc, index, e)
{ {
e->X_add_number |= ~(((bfd_vma) 1 << 44) - 1); e->X_add_number |= ~(((bfd_vma) 1 << 44) - 1);
} }
return 1; return OPERAND_MATCH;
}
else
return OPERAND_OUT_OF_RANGE;
} }
break; break;
case IA64_OPND_IMM17: case IA64_OPND_IMM17:
/* bit 0 is a don't care (pr0 is hardwired to 1) */ /* bit 0 is a don't care (pr0 is hardwired to 1) */
if (e->X_op == O_constant if (e->X_op == O_constant)
&& ((e->X_add_number >= 0 {
if (((e->X_add_number >= 0
&& (bfd_vma) e->X_add_number < ((bfd_vma) 1 << 17)) && (bfd_vma) e->X_add_number < ((bfd_vma) 1 << 17))
|| (e->X_add_number < 0 || (e->X_add_number < 0
&& (bfd_vma) -e->X_add_number <= ((bfd_vma) 1 << 17)))) && (bfd_vma) -e->X_add_number <= ((bfd_vma) 1 << 17))))
@ -5025,7 +5086,10 @@ operand_match (idesc, index, e)
{ {
e->X_add_number |= ~(((bfd_vma) 1 << 17) - 1); e->X_add_number |= ~(((bfd_vma) 1 << 17) - 1);
} }
return 1; return OPERAND_MATCH;
}
else
return OPERAND_OUT_OF_RANGE;
} }
break; break;
@ -5063,18 +5127,18 @@ operand_match (idesc, index, e)
fix->expr = *e; fix->expr = *e;
fix->is_pcrel = 0; fix->is_pcrel = 0;
++CURR_SLOT.num_fixups; ++CURR_SLOT.num_fixups;
return 1; return OPERAND_MATCH;
} }
else if (e->X_op != O_constant else if (e->X_op != O_constant
&& ! (e->X_op == O_big && opnd == IA64_OPND_IMM8M1U8)) && ! (e->X_op == O_big && opnd == IA64_OPND_IMM8M1U8))
return 0; return OPERAND_MISMATCH;
if (opnd == IA64_OPND_IMM8M1U4) if (opnd == IA64_OPND_IMM8M1U4)
{ {
/* Zero is not valid for unsigned compares that take an adjusted /* Zero is not valid for unsigned compares that take an adjusted
constant immediate range. */ constant immediate range. */
if (e->X_add_number == 0) if (e->X_add_number == 0)
return 0; return OPERAND_OUT_OF_RANGE;
/* Sign-extend 32-bit unsigned numbers, so that the following range /* Sign-extend 32-bit unsigned numbers, so that the following range
checks will work. */ checks will work. */
@ -5086,7 +5150,7 @@ operand_match (idesc, index, e)
/* Check for 0x100000000. This is valid because /* Check for 0x100000000. This is valid because
0x100000000-1 is the same as ((uint32_t) -1). */ 0x100000000-1 is the same as ((uint32_t) -1). */
if (val == ((bfd_signed_vma) 1 << 32)) if (val == ((bfd_signed_vma) 1 << 32))
return 1; return OPERAND_MATCH;
val = val - 1; val = val - 1;
} }
@ -5095,7 +5159,7 @@ operand_match (idesc, index, e)
/* Zero is not valid for unsigned compares that take an adjusted /* Zero is not valid for unsigned compares that take an adjusted
constant immediate range. */ constant immediate range. */
if (e->X_add_number == 0) if (e->X_add_number == 0)
return 0; return OPERAND_OUT_OF_RANGE;
/* Check for 0x10000000000000000. */ /* Check for 0x10000000000000000. */
if (e->X_op == O_big) if (e->X_op == O_big)
@ -5105,9 +5169,9 @@ operand_match (idesc, index, e)
&& generic_bignum[2] == 0 && generic_bignum[2] == 0
&& generic_bignum[3] == 0 && generic_bignum[3] == 0
&& generic_bignum[4] == 1) && generic_bignum[4] == 1)
return 1; return OPERAND_MATCH;
else else
return 0; return OPERAND_OUT_OF_RANGE;
} }
else else
val = e->X_add_number - 1; val = e->X_add_number - 1;
@ -5128,17 +5192,22 @@ operand_match (idesc, index, e)
if ((val >= 0 && (bfd_vma) val < ((bfd_vma) 1 << (bits - 1))) if ((val >= 0 && (bfd_vma) val < ((bfd_vma) 1 << (bits - 1)))
|| (val < 0 && (bfd_vma) -val <= ((bfd_vma) 1 << (bits - 1)))) || (val < 0 && (bfd_vma) -val <= ((bfd_vma) 1 << (bits - 1))))
return 1; return OPERAND_MATCH;
break; else
return OPERAND_OUT_OF_RANGE;
case IA64_OPND_INC3: case IA64_OPND_INC3:
/* +/- 1, 4, 8, 16 */ /* +/- 1, 4, 8, 16 */
val = e->X_add_number; val = e->X_add_number;
if (val < 0) if (val < 0)
val = -val; val = -val;
if (e->X_op == O_constant if (e->X_op == O_constant)
&& (val == 1 || val == 4 || val == 8 || val == 16)) {
return 1; if ((val == 1 || val == 4 || val == 8 || val == 16))
return OPERAND_MATCH;
else
return OPERAND_OUT_OF_RANGE;
}
break; break;
case IA64_OPND_TGT25: case IA64_OPND_TGT25:
@ -5164,14 +5233,14 @@ operand_match (idesc, index, e)
fix->expr = *e; fix->expr = *e;
fix->is_pcrel = 1; fix->is_pcrel = 1;
++CURR_SLOT.num_fixups; ++CURR_SLOT.num_fixups;
return 1; return OPERAND_MATCH;
} }
case IA64_OPND_TAG13: case IA64_OPND_TAG13:
case IA64_OPND_TAG13b: case IA64_OPND_TAG13b:
switch (e->X_op) switch (e->X_op)
{ {
case O_constant: case O_constant:
return 1; return OPERAND_MATCH;
case O_symbol: case O_symbol:
fix = CURR_SLOT.fixup + CURR_SLOT.num_fixups; fix = CURR_SLOT.fixup + CURR_SLOT.num_fixups;
@ -5183,7 +5252,7 @@ operand_match (idesc, index, e)
fix->expr = *e; fix->expr = *e;
fix->is_pcrel = 1; fix->is_pcrel = 1;
++CURR_SLOT.num_fixups; ++CURR_SLOT.num_fixups;
return 1; return OPERAND_MATCH;
default: default:
break; break;
@ -5193,7 +5262,7 @@ operand_match (idesc, index, e)
default: default:
break; break;
} }
return 0; return OPERAND_MISMATCH;
} }
static int static int
@ -5241,8 +5310,9 @@ parse_operands (idesc)
struct ia64_opcode *idesc; struct ia64_opcode *idesc;
{ {
int i = 0, highest_unmatched_operand, num_operands = 0, num_outputs = 0; int i = 0, highest_unmatched_operand, num_operands = 0, num_outputs = 0;
int sep = 0; int error_pos, out_of_range_pos, curr_out_of_range_pos, sep = 0;
enum ia64_opnd expected_operand = IA64_OPND_NIL; enum ia64_opnd expected_operand = IA64_OPND_NIL;
enum operand_match_result result;
char mnemonic[129]; char mnemonic[129];
char *first_arg = 0, *end, *saved_input_pointer; char *first_arg = 0, *end, *saved_input_pointer;
unsigned int sof; unsigned int sof;
@ -5324,6 +5394,8 @@ parse_operands (idesc)
} }
highest_unmatched_operand = 0; highest_unmatched_operand = 0;
curr_out_of_range_pos = -1;
error_pos = 0;
expected_operand = idesc->operands[0]; expected_operand = idesc->operands[0];
for (; idesc; idesc = get_next_opcode (idesc)) for (; idesc; idesc = get_next_opcode (idesc))
{ {
@ -5331,16 +5403,52 @@ parse_operands (idesc)
continue; /* mismatch in # of outputs */ continue; /* mismatch in # of outputs */
CURR_SLOT.num_fixups = 0; CURR_SLOT.num_fixups = 0;
for (i = 0; i < num_operands && idesc->operands[i]; ++i)
if (!operand_match (idesc, i, CURR_SLOT.opnd + i))
break;
if (i != num_operands) /* Try to match all operands. If we see an out-of-range operand,
then continue trying to match the rest of the operands, since if
the rest match, then this idesc will give the best error message. */
out_of_range_pos = -1;
for (i = 0; i < num_operands && idesc->operands[i]; ++i)
{ {
if (i > highest_unmatched_operand) result = operand_match (idesc, i, CURR_SLOT.opnd + i);
if (result != OPERAND_MATCH)
{
if (result != OPERAND_OUT_OF_RANGE)
break;
if (out_of_range_pos < 0)
/* remember position of the first out-of-range operand: */
out_of_range_pos = i;
}
}
/* If we did not match all operands, or if at least one operand was
out-of-range, then this idesc does not match. Keep track of which
idesc matched the most operands before failing. If we have two
idescs that failed at the same position, and one had an out-of-range
operand, then prefer the out-of-range operand. Thus if we have
"add r0=0x1000000,r1" we get an error saying the constant is out
of range instead of an error saying that the constant should have been
a register. */
if (i != num_operands || out_of_range_pos >= 0)
{
if (i > highest_unmatched_operand
|| (i == highest_unmatched_operand
&& out_of_range_pos > curr_out_of_range_pos))
{ {
highest_unmatched_operand = i; highest_unmatched_operand = i;
if (out_of_range_pos >= 0)
{
expected_operand = idesc->operands[out_of_range_pos];
error_pos = out_of_range_pos;
}
else
{
expected_operand = idesc->operands[i]; expected_operand = idesc->operands[i];
error_pos = i;
}
curr_out_of_range_pos = out_of_range_pos;
} }
continue; continue;
} }
@ -5355,7 +5463,7 @@ parse_operands (idesc)
{ {
if (expected_operand) if (expected_operand)
as_bad ("Operand %u of `%s' should be %s", as_bad ("Operand %u of `%s' should be %s",
highest_unmatched_operand + 1, mnemonic, error_pos + 1, mnemonic,
elf64_ia64_operands[expected_operand].desc); elf64_ia64_operands[expected_operand].desc);
else else
as_bad ("Operand mismatch"); as_bad ("Operand mismatch");

View File

@ -1,3 +1,9 @@
2001-02-21 David Mosberger <davidm@hpl.hp.com>
* ia64-opc-d.c (ia64_opcodes_d): Break the "add" pattern into two
separate variants: one for IMM22 and the other for IMM14.
* ia64-asmtab.c: Regenerate.
2001-02-21 Greg McGary <greg@mcgary.org> 2001-02-21 Greg McGary <greg@mcgary.org>
* cgen-opc.c (cgen_get_insn_value): Add missing `return'. * cgen-opc.c (cgen_get_insn_value): Add missing `return'.

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,9 @@
struct ia64_opcode ia64_opcodes_d[] = struct ia64_opcode ia64_opcodes_d[] =
{ {
{"add", IA64_TYPE_DYN, 1, 0, 0, {"add", IA64_TYPE_DYN, 1, 0, 0,
{IA64_OPND_R1, IA64_OPND_IMM22, IA64_OPND_R3}}, {IA64_OPND_R1, IA64_OPND_IMM22, IA64_OPND_R3_2}},
{"add", IA64_TYPE_DYN, 1, 0, 0,
{IA64_OPND_R1, IA64_OPND_IMM14, IA64_OPND_R3}},
{"break", IA64_TYPE_DYN, 0, 0, 0, {IA64_OPND_IMMU21}}, {"break", IA64_TYPE_DYN, 0, 0, 0, {IA64_OPND_IMMU21}},
{"chk.s", IA64_TYPE_DYN, 0, 0, 0, {IA64_OPND_R2, IA64_OPND_TGT25b}}, {"chk.s", IA64_TYPE_DYN, 0, 0, 0, {IA64_OPND_R2, IA64_OPND_TGT25b}},
{"mov", IA64_TYPE_DYN, 1, 0, 0, {IA64_OPND_R1, IA64_OPND_AR3}}, {"mov", IA64_TYPE_DYN, 1, 0, 0, {IA64_OPND_R1, IA64_OPND_AR3}},