diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index e1762df395e..ba0a46227a7 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -3394,6 +3394,11 @@ parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode) } operand->shifter.amount = 0; } + else if (exp.X_op == O_big) + { + set_fatal_syntax_error (_("shift amount out of range")); + return FALSE; + } else if (exp.X_op != O_constant) { set_syntax_error (_("constant shift amount required")); @@ -6438,10 +6443,19 @@ parse_operands (char *str, const aarch64_opcode *opcode) po_misc_or_fail (parse_shifter_operand_imm (&str, info, SHIFTED_ARITH_IMM)); + if (inst.reloc.exp.X_op != O_constant) + { + set_fatal_syntax_error (_(inst.reloc.exp.X_op == O_big + ? "immediate out of range" + : "expected constant expression")); + goto failure; + } + /* Try to coerce into shifted form if the immediate is out of range. */ - if (inst.reloc.exp.X_add_number > 63 && (info->imm.value & 16) == 0 - && (inst.reloc.exp.X_add_number >> 4) <= 64 + if (inst.reloc.exp.X_add_number > 63 + && (inst.reloc.exp.X_add_number & 0xf) == 0 + && (inst.reloc.exp.X_add_number >> 4) <= 63 && info->shifter.amount == 0) { info->shifter.amount = 4; diff --git a/gas/testsuite/gas/aarch64/scbnds-immed.d b/gas/testsuite/gas/aarch64/scbnds-immed.d new file mode 100644 index 00000000000..d11aac40b16 --- /dev/null +++ b/gas/testsuite/gas/aarch64/scbnds-immed.d @@ -0,0 +1,16 @@ +#name: test valid scbnds immediates +#as: -march=morello +#objdump: -dr + +.*: file format .* + + +Disassembly of section \.text: + +.* <\.text>: +.*: c2c03820 scbnds c0, c1, #0x0 +.*: c2d03820 scbnds c0, c1, #0x20 +.*: c2dfb820 scbnds c0, c1, #0x3f +.*: c2c27820 scbnds c0, c1, #0x4, lsl #4 +.*: c2c2f820 scbnds c0, c1, #0x5, lsl #4 +.*: c2dff820 scbnds c0, c1, #0x3f, lsl #4 diff --git a/gas/testsuite/gas/aarch64/scbnds-immed.s b/gas/testsuite/gas/aarch64/scbnds-immed.s new file mode 100644 index 00000000000..f45ea66ff78 --- /dev/null +++ b/gas/testsuite/gas/aarch64/scbnds-immed.s @@ -0,0 +1,6 @@ +scbnds c0, c1, #0 +scbnds c0, c1, #32 +scbnds c0, c1, #63 +scbnds c0, c1, #64 +scbnds c0, c1, #80 +scbnds c0, c1, #1008 diff --git a/gas/testsuite/gas/aarch64/scbnds-invalid.d b/gas/testsuite/gas/aarch64/scbnds-invalid.d new file mode 100644 index 00000000000..bdd0ce3f55e --- /dev/null +++ b/gas/testsuite/gas/aarch64/scbnds-invalid.d @@ -0,0 +1,4 @@ +#name: invalid scbnds instructions +#as: -march=morello +#source: scbnds-invalid.s +#error_output: scbnds-invalid.l diff --git a/gas/testsuite/gas/aarch64/scbnds-invalid.l b/gas/testsuite/gas/aarch64/scbnds-invalid.l new file mode 100644 index 00000000000..a204c0aeee5 --- /dev/null +++ b/gas/testsuite/gas/aarch64/scbnds-invalid.l @@ -0,0 +1,30 @@ +.*: Assembler messages: +.*: Error: operand 2 must be a Capability register or a capability stack pointer register -- `scbnds c0,czr,#1' +.*: Error: operand 1 must be a Capability register or a capability stack pointer register -- `scbnds czr,c0,#1' +.*: Error: operand 1 must be a Capability register or a capability stack pointer register -- `scbnds czr,czr,#1' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#-1' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#65' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#66' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#67' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#68' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#69' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#70' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#71' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#72' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#73' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#74' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#75' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#76' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#77' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#78' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#79' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#81' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#1009' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#1024' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#1000000000000000000000001' +.*: Error: shift amount out of range 0 to 63 at operand 3 -- `scbnds c0,c1,#1,lsl#-1' +.*: Error: shift amount must be 4 at operand 3 -- `scbnds c0,c1,#1,lsl#2' +.*: Error: shift amount must be 4 at operand 3 -- `scbnds c0,c1,#1,lsl#3' +.*: Error: shift amount must be 4 at operand 3 -- `scbnds c0,c1,#1,lsl#5' +.*: Error: shift amount out of range at operand 3 -- `scbnds c0,c1,#1,lsl#10000000000000000000000001' +.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#64,lsl#4' diff --git a/gas/testsuite/gas/aarch64/scbnds-invalid.s b/gas/testsuite/gas/aarch64/scbnds-invalid.s new file mode 100644 index 00000000000..4c1fab89edb --- /dev/null +++ b/gas/testsuite/gas/aarch64/scbnds-invalid.s @@ -0,0 +1,29 @@ +scbnds c0, czr, #1 +scbnds czr, c0, #1 +scbnds czr, czr, #1 +scbnds c0, c1, #-1 +scbnds c0, c1, #65 +scbnds c0, c1, #66 +scbnds c0, c1, #67 +scbnds c0, c1, #68 +scbnds c0, c1, #69 +scbnds c0, c1, #70 +scbnds c0, c1, #71 +scbnds c0, c1, #72 +scbnds c0, c1, #73 +scbnds c0, c1, #74 +scbnds c0, c1, #75 +scbnds c0, c1, #76 +scbnds c0, c1, #77 +scbnds c0, c1, #78 +scbnds c0, c1, #79 +scbnds c0, c1, #81 +scbnds c0, c1, #1009 +scbnds c0, c1, #1024 +scbnds c0, c1, #1000000000000000000000001 +scbnds c0, c1, #1, lsl #-1 +scbnds c0, c1, #1, lsl #2 +scbnds c0, c1, #1, lsl #3 +scbnds c0, c1, #1, lsl #5 +scbnds c0, c1, #1, lsl #10000000000000000000000001 +scbnds c0, c1, #64, lsl #4 diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c index a13ff33ce43..c4c5841746a 100644 --- a/opcodes/aarch64-opc.c +++ b/opcodes/aarch64-opc.c @@ -2239,13 +2239,13 @@ operand_general_constraint_met_p (aarch64_feature_set features, _("shift amount must be 4")); return 0; } - if (!value_fit_unsigned_field_p (opnd->imm.value, 6)) - { - set_other_error (mismatch_detail, idx, - _("immediate out of range")); - return 0; - } } + if (!value_fit_unsigned_field_p (opnd->imm.value, 6)) + { + set_other_error (mismatch_detail, idx, + _("immediate out of range")); + return 0; + } break; case AARCH64_OPND_AIMM: