diff options
author | Jan Beulich <jbeulich@novell.com> | 2005-02-15 07:50:23 +0000 |
---|---|---|
committer | Jan Beulich <jbeulich@novell.com> | 2005-02-15 07:50:23 +0000 |
commit | 4b09e82862bd1cdc6a6d89f19c556bfd2307bd9a (patch) | |
tree | 2a69088531ba9b490d0f2879139c059100e96879 /gas/config/tc-ia64.c | |
parent | 0ca3e4557f03289c3b174dd841dfa73dbe51d505 (diff) | |
download | gdb-4b09e82862bd1cdc6a6d89f19c556bfd2307bd9a.zip gdb-4b09e82862bd1cdc6a6d89f19c556bfd2307bd9a.tar.gz gdb-4b09e82862bd1cdc6a6d89f19c556bfd2307bd9a.tar.bz2 |
gas/
2005-02-15 Jan Beulich <jbeulich@novell.com>
* config/tc-ia64.c (parse_operands): New local variables reg1, reg2,
reg_class. Check operands and emit diagnostics for illegal use of
registers.
gas/testsuite/
2005-02-15 Jan Beulich <jbeulich@novell.com>
* gas/ia64/dv-raw-err.s: Don't use r0 or f0 as output operand.
* gas/ia64/dv-waw-err.s: Likewise.
* gas/ia64/reg-err.[ls]: New.
* gas/ia64/ia64.exp: Run new test.
Diffstat (limited to 'gas/config/tc-ia64.c')
-rw-r--r-- | gas/config/tc-ia64.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/gas/config/tc-ia64.c b/gas/config/tc-ia64.c index 387a1b7..c7a6b07 100644 --- a/gas/config/tc-ia64.c +++ b/gas/config/tc-ia64.c @@ -6012,6 +6012,8 @@ parse_operands (idesc) { int i = 0, highest_unmatched_operand, num_operands = 0, num_outputs = 0; int error_pos, out_of_range_pos, curr_out_of_range_pos, sep = 0; + int reg1, reg2; + char reg_class; enum ia64_opnd expected_operand = IA64_OPND_NIL; enum operand_match_result result; char mnemonic[129]; @@ -6193,6 +6195,127 @@ parse_operands (idesc) as_bad ("Operand mismatch"); return 0; } + + /* Check that the instruction doesn't use + - r0, f0, or f1 as output operands + - the same predicate twice as output operands + - r0 as address of a base update load or store + - the same GR as output and address of a base update load + - two even- or two odd-numbered FRs as output operands of a floating + point parallel load. + At most two (conflicting) output (or output-like) operands can exist, + (floating point parallel loads have three outputs, but the base register, + if updated, cannot conflict with the actual outputs). */ + reg2 = reg1 = -1; + for (i = 0; i < num_operands; ++i) + { + int regno = 0; + + reg_class = 0; + switch (idesc->operands[i]) + { + case IA64_OPND_R1: + case IA64_OPND_R2: + case IA64_OPND_R3: + if (i < num_outputs) + { + if (CURR_SLOT.opnd[i].X_add_number == REG_GR) + reg_class = 'r'; + else if (reg1 < 0) + reg1 = CURR_SLOT.opnd[i].X_add_number; + else if (reg2 < 0) + reg2 = CURR_SLOT.opnd[i].X_add_number; + } + break; + case IA64_OPND_P1: + case IA64_OPND_P2: + if (i < num_outputs) + { + if (reg1 < 0) + reg1 = CURR_SLOT.opnd[i].X_add_number; + else if (reg2 < 0) + reg2 = CURR_SLOT.opnd[i].X_add_number; + } + break; + case IA64_OPND_F1: + case IA64_OPND_F2: + case IA64_OPND_F3: + case IA64_OPND_F4: + if (i < num_outputs) + { + if (CURR_SLOT.opnd[i].X_add_number >= REG_FR + && CURR_SLOT.opnd[i].X_add_number <= REG_FR + 1) + { + reg_class = 'f'; + regno = CURR_SLOT.opnd[i].X_add_number - REG_FR; + } + else if (reg1 < 0) + reg1 = CURR_SLOT.opnd[i].X_add_number; + else if (reg2 < 0) + reg2 = CURR_SLOT.opnd[i].X_add_number; + } + break; + case IA64_OPND_MR3: + if (idesc->flags & IA64_OPCODE_POSTINC) + { + if (CURR_SLOT.opnd[i].X_add_number == REG_GR) + reg_class = 'm'; + else if (reg1 < 0) + reg1 = CURR_SLOT.opnd[i].X_add_number; + else if (reg2 < 0) + reg2 = CURR_SLOT.opnd[i].X_add_number; + } + break; + default: + break; + } + switch (reg_class) + { + case 0: + break; + default: + as_warn ("Invalid use of `%c%d' as output operand", reg_class, regno); + break; + case 'm': + as_warn ("Invalid use of `r%d' as base update address operand", regno); + break; + } + } + if (reg1 == reg2) + { + if (reg1 >= REG_GR && reg1 <= REG_GR + 127) + { + reg1 -= REG_GR; + reg_class = 'r'; + } + else if (reg1 >= REG_P && reg1 <= REG_P + 63) + { + reg1 -= REG_P; + reg_class = 'p'; + } + else if (reg1 >= REG_FR && reg1 <= REG_FR + 127) + { + reg1 -= REG_FR; + reg_class = 'f'; + } + else + reg_class = 0; + if (reg_class) + as_warn ("Invalid duplicate use of `%c%d'", reg_class, reg1); + } + else if (((reg1 >= REG_FR && reg1 <= REG_FR + 31 + && reg2 >= REG_FR && reg2 <= REG_FR + 31) + || (reg1 >= REG_FR + 32 && reg1 <= REG_FR + 127 + && reg2 >= REG_FR + 32 && reg2 <= REG_FR + 127)) + && ! ((reg1 ^ reg2) & 1)) + as_warn ("Invalid simultaneous use of `f%d' and `f%d'", + reg1 - REG_FR, reg2 - REG_FR); + else if ((reg1 >= REG_FR && reg1 <= REG_FR + 31 + && reg2 >= REG_FR + 32 && reg2 <= REG_FR + 127) + || (reg1 >= REG_FR + 32 && reg1 <= REG_FR + 127 + && reg2 >= REG_FR && reg2 <= REG_FR + 31)) + as_warn ("Dangerous simultaneous use of `f%d' and `f%d'", + reg1 - REG_FR, reg2 - REG_FR); return idesc; } |