diff options
Diffstat (limited to 'gas/config/tc-ia64.c')
-rw-r--r-- | gas/config/tc-ia64.c | 69 |
1 files changed, 43 insertions, 26 deletions
diff --git a/gas/config/tc-ia64.c b/gas/config/tc-ia64.c index 6415647..51bf2ed 100644 --- a/gas/config/tc-ia64.c +++ b/gas/config/tc-ia64.c @@ -6157,8 +6157,7 @@ build_insn (slot, insnp) static void emit_one_bundle () { - unsigned int manual_bundling_on = 0, manual_bundling_off = 0; - unsigned int manual_bundling = 0; + int manual_bundling_off = 0, manual_bundling = 0; enum ia64_unit required_unit, insn_unit = 0; enum ia64_insn_type type[3], insn_type; unsigned int template, orig_template; @@ -6253,13 +6252,25 @@ emit_one_bundle () } } - if (idesc->flags & IA64_OPCODE_SLOT2) + manual_bundling_off = md.slot[curr].manual_bundling_off; + if (md.slot[curr].manual_bundling_on) { - if (manual_bundling && i != 2) - as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line, - "`%s' must be last in bundle", idesc->name); + if (curr == first) + manual_bundling = 1; else - i = 2; + break; /* Need to start a new bundle. */ + } + + if (idesc->flags & IA64_OPCODE_SLOT2) + { + if (manual_bundling && !manual_bundling_off) + { + as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line, + "`%s' must be last in bundle", idesc->name); + if (i < 2) + manual_bundling = -1; /* Suppress meaningless post-loop errors. */ + } + i = 2; } if (idesc->flags & IA64_OPCODE_LAST) { @@ -6292,10 +6303,19 @@ emit_one_bundle () required_slot = i; break; } - if (manual_bundling && i != required_slot) - as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line, - "`%s' must be last in instruction group", - idesc->name); + if (manual_bundling + && (i > required_slot + || (required_slot == 2 && !manual_bundling_off) + || (user_template >= 0 + /* Changing from MMI to M;MI is OK. */ + && (template ^ required_template) > 1))) + { + as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line, + "`%s' must be last in instruction group", + idesc->name); + if (i < 2 && required_slot == 2 && !manual_bundling_off) + manual_bundling = -1; /* Suppress meaningless post-loop errors. */ + } if (required_slot < i) /* Can't fit this instruction. */ break; @@ -6314,24 +6334,16 @@ emit_one_bundle () } if (curr != first && md.slot[curr].label_fixups) { - if (manual_bundling_on) - as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line, + if (manual_bundling) + { + as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line, "Label must be first in a bundle"); + manual_bundling = -1; /* Suppress meaningless post-loop errors. */ + } /* This insn must go into the first slot of a bundle. */ break; } - manual_bundling_on = md.slot[curr].manual_bundling_on; - manual_bundling_off = md.slot[curr].manual_bundling_off; - - if (manual_bundling_on) - { - if (curr == first) - manual_bundling = 1; - else - break; /* need to start a new bundle */ - } - if (end_of_insn_group && md.num_slots_in_use >= 1) { /* We need an instruction group boundary in the middle of a @@ -6359,12 +6371,17 @@ emit_one_bundle () reason we have to check for this is that otherwise we may end up generating "MI;;I M.." which has the deadly effect that the second M instruction is no longer the - first in the bundle! --davidm 99/12/16 */ + first in the group! --davidm 99/12/16 */ && (idesc->flags & IA64_OPCODE_FIRST) == 0) { template = 1; end_of_insn_group = 0; } + else if (i == 1 + && user_template == 0 + && !(idesc->flags & IA64_OPCODE_FIRST)) + /* Use the next slot. */ + continue; else if (curr != first) /* can't fit this insn */ break; @@ -6542,7 +6559,7 @@ emit_one_bundle () curr = (curr + 1) % NUM_SLOTS; idesc = md.slot[curr].idesc; } - if (manual_bundling) + if (manual_bundling > 0) { if (md.num_slots_in_use > 0) { |