Various inconsistencies were observable in manual bundling mode, mostly resulting in errors where there shouldn't be any (and the Intel assembler accepting the same code) or errors not getting generated when they should be. For example, - when a bundle has less than 3 instructions and the last one is required to go into slot 2, there is no problem doing so - when a label is in the middle of a bundle (past slot 0 and before slot 2), this is always an error, while a label before slot 0 or after slot 2 is valid - an MII bundle with only two (explicit) insns and a stop between them is valid Built and tested on ia64-unknown-linux-gnu. Jan gas/ 2005-01-24 Jan Beulich * config/tc-ia64.c (emit_one_bundle): Snapshot manual bundling state before actually using it. Don't generate an error in manual bundling mode when looking at an insn requiring slot 2 but not yet at slot 2. Don't generate an error in manual bundling mode when looking at an insn required to be last in its group but the required slot hasn't been reached, yet. Allow conversion from MII to MI;I for bundle consisting of only 2 insns with the stop between them. Suppress various meaningless errors resulting from detecting earlier ones. gas/testsuite/ 2005-01-24 Jan Beulich * gas/ia64/bundling[.ds]: New. * gas/ia64/label[.ls]: New. * gas/ia64/last[.ls]: New. * gas/ia64/slot2[.ls]: New. * gas/ia64/ia64.exp: Run new tests. --- /home/jbeulich/src/binutils/mainline/2005-01-24.08.40/gas/config/tc-ia64.c 2005-01-18 10:43:33.000000000 +0100 +++ 2005-01-24.08.40/gas/config/tc-ia64.c 2005-01-24 10:51:55.557354855 +0100 @@ -6145,8 +6145,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; @@ -6241,13 +6240,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) { @@ -6280,10 +6291,18 @@ 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 + && (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; @@ -6302,24 +6321,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 @@ -6347,12 +6358,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; @@ -6513,7 +6529,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) { --- /home/jbeulich/src/binutils/mainline/2005-01-24.08.40/gas/testsuite/gas/ia64/bundling.d 1970-01-01 01:00:00.000000000 +0100 +++ 2005-01-24.08.40/gas/testsuite/gas/ia64/bundling.d 2005-01-21 15:47:09.000000000 +0100 @@ -0,0 +1,14 @@ +# objdump: -d +# name: ia64 explicit bundling + +.*: +file format .* + +Disassembly of section \.text: + +0+0 <_start>: +[[:space:]]*[[:xdigit:]]*:[[:space:][:xdigit:]]+\[MII] nop\.m 0x0 +[[:space:]]*[[:xdigit:]]*:[[:space:][:xdigit:]]+nop\.i 0x0;; +[[:space:]]*[[:xdigit:]]*:[[:space:][:xdigit:]]+mov\.i r31=ar\.lc;; +[[:space:]]*[[:xdigit:]]*:[[:space:][:xdigit:]]+\[..B] nop\.. 0x0 +[[:space:]]*[[:xdigit:]]*:[[:space:][:xdigit:]]+nop\.. 0x0 +[[:space:]]*[[:xdigit:]]*:[[:space:][:xdigit:]]+br\.ret\.sptk\.few b0;; --- /home/jbeulich/src/binutils/mainline/2005-01-24.08.40/gas/testsuite/gas/ia64/bundling.s 1970-01-01 01:00:00.000000000 +0100 +++ 2005-01-24.08.40/gas/testsuite/gas/ia64/bundling.s 2005-01-21 15:49:31.000000000 +0100 @@ -0,0 +1,15 @@ +.explicit +.proc _start +_start: + .prologue +{.mii + nop.m 0 + ;; + .save ar.lc, r31 + mov r31 = ar.lc +} ;; + .body +{.mfb + br.ret.sptk rp +} ;; +.endp _start --- /home/jbeulich/src/binutils/mainline/2005-01-24.08.40/gas/testsuite/gas/ia64/ia64.exp 2004-07-02 08:26:34.000000000 +0200 +++ 2005-01-24.08.40/gas/testsuite/gas/ia64/ia64.exp 2005-01-24 10:51:55.558331417 +0100 @@ -58,4 +58,9 @@ if [istarget "ia64-*"] then { run_dump_test "alias" run_dump_test "group-1" } + + run_dump_test "bundling" + run_list_test "label" "" + run_list_test "last" "" + run_list_test "slot2" "" } --- /home/jbeulich/src/binutils/mainline/2005-01-24.08.40/gas/testsuite/gas/ia64/label.l 1970-01-01 01:00:00.000000000 +0100 +++ 2005-01-24.08.40/gas/testsuite/gas/ia64/label.l 2005-01-21 15:52:42.000000000 +0100 @@ -0,0 +1,3 @@ +.*: Assembler messages: +.*:11: Error: Label must be first in a bundle +.*:18: Error: Label must be first in a bundle --- /home/jbeulich/src/binutils/mainline/2005-01-24.08.40/gas/testsuite/gas/ia64/label.s 1970-01-01 01:00:00.000000000 +0100 +++ 2005-01-24.08.40/gas/testsuite/gas/ia64/label.s 2005-01-20 11:37:08.000000000 +0100 @@ -0,0 +1,25 @@ +start: +{.mii +label0: + nop 0 + nop 0 + nop 0 +} +{.mii + nop 0 +label1: + nop 0 + nop 0 +} +{.mii + nop 0 + nop 0 +label2: + nop 0 +} +{.mii + nop 0 + nop 0 + nop 0 +label3: +} --- /home/jbeulich/src/binutils/mainline/2005-01-24.08.40/gas/testsuite/gas/ia64/last.l 1970-01-01 01:00:00.000000000 +0100 +++ 2005-01-24.08.40/gas/testsuite/gas/ia64/last.l 2005-01-21 15:55:05.000000000 +0100 @@ -0,0 +1,3 @@ +.*: Assembler messages: +.*:4: Error: .* must be last in instruction group +.*:10: Error: .* must be last in instruction group --- /home/jbeulich/src/binutils/mainline/2005-01-24.08.40/gas/testsuite/gas/ia64/last.s 1970-01-01 01:00:00.000000000 +0100 +++ 2005-01-24.08.40/gas/testsuite/gas/ia64/last.s 2005-01-21 16:00:49.000000000 +0100 @@ -0,0 +1,12 @@ +.explicit +_start: +{.mib + itc.d r0 +} ;; +{.mib + cover +} ;; +{.mbb + cover + nop 0 +} ;; --- /home/jbeulich/src/binutils/mainline/2005-01-24.08.40/gas/testsuite/gas/ia64/slot2.l 1970-01-01 01:00:00.000000000 +0100 +++ 2005-01-24.08.40/gas/testsuite/gas/ia64/slot2.l 2005-01-21 16:02:23.000000000 +0100 @@ -0,0 +1,3 @@ +.*: Assembler messages: +.*:11: Error: .* must be last in bundle +.*:16: Error: .* must be last in bundle --- /home/jbeulich/src/binutils/mainline/2005-01-24.08.40/gas/testsuite/gas/ia64/slot2.s 1970-01-01 01:00:00.000000000 +0100 +++ 2005-01-24.08.40/gas/testsuite/gas/ia64/slot2.s 2005-01-21 16:00:27.000000000 +0100 @@ -0,0 +1,18 @@ +.explicit +_start: +{.mib + br.cloop.sptk start +} ;; +{.mib + nop 0 + br.cloop.sptk start +} ;; +{.mbb + br.cloop.sptk start + nop 0 +} ;; +{.mbb + nop 0 + br.cloop.sptk start + nop 0 +} ;;