The assembler silently permitted using - 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 Built and tested on ia64-unknown-linux-gnu. Jan gas/ 2005-02-10 Jan Beulich * config/tc-ia64.c (parse_operands): New local variables reg1, reg2, reg_class. Check operands and emit diagnostics for illegal use of registers. (md_assemble): Defer resolution of move to/from application registers dynamic insns when they can be issued on either the I- or M-units. gas/testsuite/ 2005-02-10 Jan Beulich * gas/ia64/dv-raw-err.l: Don't use r0 or f0 as output operand. * gas/ia64/dv-waw-err.l: Likewise. * gas/ia64/reg-err.[ls]: New. * gas/ia64/ia64.exp: Run new test. --- /home/jbeulich/src/binutils/mainline/2005-02-08/gas/config/tc-ia64.c 2005-02-02 08:33:18.000000000 +0100 +++ 2005-02-08/gas/config/tc-ia64.c 2005-02-10 13:41:21.796344557 +0100 @@ -5936,6 +5936,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]; @@ -6117,6 +6119,116 @@ parse_operands (idesc) as_bad ("Operand mismatch"); return 0; } + 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; } --- /home/jbeulich/src/binutils/mainline/2005-02-08/gas/testsuite/gas/ia64/dv-raw-err.s 2004-06-16 15:23:12.000000000 +0200 +++ 2005-02-08/gas/testsuite/gas/ia64/dv-raw-err.s 2005-02-10 13:41:21.802203932 +0100 @@ -6,8 +6,8 @@ .text .explicit // AR[BSP] - mov ar.bspstore = r1 - mov r0 = ar.bsp + mov ar.bspstore = r0 + mov r1 = ar.bsp ;; // AR[BSPSTORE] @@ -108,12 +108,12 @@ // BR% mov b0 = r0 - mov r0 = b0 + mov r2 = b0 ;; // CFM br.wtop.sptk L - fadd f0 = f1, f32 // read from rotating register region + fadd f2 = f1, f32 // read from rotating register region ;; // CR[CMCV] @@ -276,7 +276,7 @@ ;; // GR% - ld8.c.clr r0 = [r1] // no DV here + ld8.c.clr r1 = [r1] // no DV here mov r2 = r0 ;; mov r3 = r4 @@ -357,7 +357,7 @@ // PR63 br.wtop.sptk L -(p63) add r0 = r1, r2 +(p63) add r3 = r1, r2 ;; fcmp.eq p62, p63 = f2, f3 (p63) add r3 = r4, r5 @@ -368,17 +368,17 @@ // PSR.ac rum (1<<3) - ld8 r0 = [r1] + ld8 r2 = [r1] ;; // PSR.be rum (1<<1) - ld8 r0 = [r1] + ld8 r2 = [r1] ;; // PSR.bn bsw.0 - mov r0 = r15 // no DV here, since gr < 16 + mov r1 = r15 // no DV here, since gr < 16 ;; bsw.1 // GAS automatically emits a stop after bsw.n mov r1 = r16 // so this conflict is avoided @@ -439,24 +439,24 @@ // PSR.di rsm (1<<22) - mov r0 = psr + mov r1 = psr ;; // PSR.dt rsm (1<<17) - ld8 r0 = [r1] + ld8 r1 = [r1] ;; // PSR.ed (rfi is the only writer) // PSR.i ssm (1<<14) - mov r0 = psr + mov r1 = psr ;; // PSR.ia (no DV semantics) // PSR.ic ssm (1<<13) - mov r0 = psr + mov r1 = psr ;; srlz.d rsm (1<<13) @@ -479,17 +479,17 @@ // PSR.mc (rfi is the only writer) // PSR.mfh mov f32 = f33 - mov r0 = psr + mov r1 = psr ;; // PSR.mfl mov f2 = f3 - mov r0 = psr + mov r1 = psr ;; // PSR.pk rsm (1<<15) - ld8 r0 = [r1] + ld8 r1 = [r1] ;; rsm (1<<15) mov r2 = psr @@ -497,7 +497,7 @@ // PSR.pp rsm (1<<21) - mov r0 = psr + mov r1 = psr ;; // PSR.ri (no DV semantics) @@ -509,7 +509,7 @@ // PSR.si rsm (1<<23) - mov r0 = ar.itc + mov r1 = ar.itc ;; ssm (1<<23) mov r1 = ar.ec // no DV here @@ -517,13 +517,13 @@ // PSR.sp ssm (1<<20) - mov r0 = pmd[r1] + mov r1 = pmd[r1] ;; ssm (1<<20) rum 0xff ;; ssm (1<<20) - mov r0 = rr[r1] + mov r1 = rr[r1] ;; // PSR.ss (rfi is the only writer) @@ -534,7 +534,7 @@ // PSR.up rsm (1<<2) - mov r0 = psr.um + mov r1 = psr.um ;; srlz.d --- /home/jbeulich/src/binutils/mainline/2005-02-08/gas/testsuite/gas/ia64/dv-waw-err.s 2000-09-22 21:43:48.000000000 +0200 +++ 2005-02-08/gas/testsuite/gas/ia64/dv-waw-err.s 2005-02-10 08:25:00.000000000 +0100 @@ -186,8 +186,8 @@ ;; // CR[IRR%] (and others) - mov r0 = cr.ivr - mov r1 = cr.ivr + mov r2 = cr.ivr + mov r3 = cr.ivr ;; // CR[ISR] @@ -441,13 +441,13 @@ // PSR.mc (rfi is the only writer) // PSR.mfh mov f32 = f33 - mov r0 = psr + mov r10 = psr ;; ssm (1<<5) ssm (1<<5) ;; ssm (1<<5) - mov psr.um = r0 + mov psr.um = r10 ;; rum (1<<5) rum (1<<5) @@ -458,13 +458,13 @@ // PSR.mfl mov f2 = f3 - mov r0 = psr + mov r10 = psr ;; ssm (1<<4) ssm (1<<4) ;; ssm (1<<4) - mov psr.um = r0 + mov psr.um = r10 ;; rum (1<<4) rum (1<<4) --- /home/jbeulich/src/binutils/mainline/2005-02-08/gas/testsuite/gas/ia64/ia64.exp 2005-02-02 08:33:18.000000000 +0100 +++ 2005-02-08/gas/testsuite/gas/ia64/ia64.exp 2005-02-10 13:44:32.936967215 +0100 @@ -28,6 +28,7 @@ if [istarget "ia64-*"] then { run_dump_test "nop_x" run_dump_test "mov-ar" run_list_test "operands" "" + run_list_test "reg-err" "" run_list_test "dv-raw-err" "" run_list_test "dv-waw-err" "" --- /home/jbeulich/src/binutils/mainline/2005-02-08/gas/testsuite/gas/ia64/reg-err.l 1970-01-01 01:00:00.000000000 +0100 +++ 2005-02-08/gas/testsuite/gas/ia64/reg-err.l 2005-02-09 18:07:52.000000000 +0100 @@ -0,0 +1,14 @@ +.*: Assembler messages: +.*:3: (Error|Warning): Invalid use of `r0' as output operand +.*:4: (Error|Warning): Invalid use of `r0' as base update address operand +.*:5: (Error|Warning): Invalid duplicate use of `r1' +.*:6: (Error|Warning): Invalid use of `r0' as base update address operand +.*:7: (Error|Warning): Invalid duplicate use of `p1' +.*:8: (Error|Warning): Invalid use of `f0' as output operand +.*:9: (Error|Warning): Invalid use of `f1' as output operand +.*:10: (Error|Warning): Invalid use of `f0' as output operand +.*:11: (Error|Warning): Invalid use of `f1' as output operand +.*:12: (Error|Warning): Invalid use of `f0' as output operand +.*:12: (Error|Warning): Invalid use of `f1' as output operand +.*:13: (Error|Warning): Invalid simultaneous use of `f2' and `f4' +.*:14: (Error|Warning): Dangerous simultaneous use of `f31' and `f32' --- /home/jbeulich/src/binutils/mainline/2005-02-08/gas/testsuite/gas/ia64/reg-err.s 1970-01-01 01:00:00.000000000 +0100 +++ 2005-02-08/gas/testsuite/gas/ia64/reg-err.s 2005-02-09 18:06:38.000000000 +0100 @@ -0,0 +1,14 @@ + .text +_start: + mov r0 = r0 + ld1 r1 = [r0], 1 + ld1 r1 = [r1], 1 + st1 [r0] = r0, 1 + cmp.eq p1, p1 = 0, r0 + mov f0 = f0 + mov f1 = f1 + ldfs f0 = [r0] + ldfs f1 = [r0] + ldfps f0, f1 = [r0] + ldfps f2, f4 = [r0] + ldfps f31, f32 = [r0]