diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td --- a/llvm/lib/Target/ARM/ARMInstrMVE.td +++ b/llvm/lib/Target/ARM/ARMInstrMVE.td @@ -712,6 +712,36 @@ def VMINNMf32 : VMINMAXNM<"vminnm", "f32", 0b0, 0b1>; def VMINNMf16 : VMINMAXNM<"vminnm", "f16", 0b1, 0b1>; +class VMINMAX size, + bit bit_4, list pattern=[]> + : MVE_comp { + + let Inst{28} = U; + let Inst{25-24} = 0b11; + let Inst{23} = 0b0; + let Inst{21-20} = size{1-0}; + let Inst{11} = 0b0; + let Inst{8} = 0b0; + let Inst{6} = 0b1; + let Inst{4} = bit_4; +} + +// prefix with MVE to avoid conflict with NEON equivalents. +def MVE_VMAXs8 : VMINMAX<"vmax", "s8", 0b0, 0b00, 0b0>; +def MVE_VMAXs16 : VMINMAX<"vmax", "s16", 0b0, 0b01, 0b0>; +def MVE_VMAXs32 : VMINMAX<"vmax", "s32", 0b0, 0b10, 0b0>; +def MVE_VMAXu8 : VMINMAX<"vmax", "u8", 0b1, 0b00, 0b0>; +def MVE_VMAXu16 : VMINMAX<"vmax", "u16", 0b1, 0b01, 0b0>; +def MVE_VMAXu32 : VMINMAX<"vmax", "u32", 0b1, 0b10, 0b0>; + +// prefix with MVE to avoid conflict with NEON equivalents. +def MVE_VMINs8 : VMINMAX<"vmin", "s8", 0b0, 0b00, 0b1>; +def MVE_VMINs16 : VMINMAX<"vmin", "s16", 0b0, 0b01, 0b1>; +def MVE_VMINs32 : VMINMAX<"vmin", "s32", 0b0, 0b10, 0b1>; +def MVE_VMINu8 : VMINMAX<"vmin", "u8", 0b1, 0b00, 0b1>; +def MVE_VMINu16 : VMINMAX<"vmin", "u16", 0b1, 0b01, 0b1>; +def MVE_VMINu32 : VMINMAX<"vmin", "u32", 0b1, 0b10, 0b1>; + // end of mve_comp instructions class t2VPT size, dag iops, string asm, list pattern=[]> diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5943,7 +5943,9 @@ if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" && Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" && Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" && - Mnemonic != "sbcs" && Mnemonic != "rscs") { + Mnemonic != "sbcs" && Mnemonic != "rscs" && + !(hasMVE() && + Mnemonic.startswith("vmine"))) { unsigned CC = ARMCondCodeFromString(Mnemonic.substr(Mnemonic.size()-2)); if (CC != ~0U) { Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2); diff --git a/llvm/test/MC/ARM/mve-minmax.s b/llvm/test/MC/ARM/mve-minmax.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ARM/mve-minmax.s @@ -0,0 +1,62 @@ +# RUN: llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+mve -show-encoding < %s \ +# RUN: | FileCheck --check-prefix=CHECK-NOFP %s +# RUN: llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+mve.fp,+fp64 -show-encoding < %s \ +# RUN: | FileCheck --check-prefix=CHECK %s + +# CHECK: vmin.s8 q3, q0, q7 @ encoding: [0x00,0xef,0x5e,0x66] +# CHECK-NOFP: vmin.s8 q3, q0, q7 @ encoding: [0x00,0xef,0x5e,0x66] +vmin.s8 q3, q0, q7 + +# CHECK: vmin.s16 q0, q1, q2 @ encoding: [0x12,0xef,0x54,0x06] +# CHECK-NOFP: vmin.s16 q0, q1, q2 @ encoding: [0x12,0xef,0x54,0x06] +vmin.s16 q0, q1, q2 + +# CHECK: vmin.s32 q0, q1, q2 @ encoding: [0x22,0xef,0x54,0x06] +# CHECK-NOFP: vmin.s32 q0, q1, q2 @ encoding: [0x22,0xef,0x54,0x06] +vmin.s32 q0, q1, q2 + +# CHECK: vmin.u8 q0, q1, q2 @ encoding: [0x02,0xff,0x54,0x06] +# CHECK-NOFP: vmin.u8 q0, q1, q2 @ encoding: [0x02,0xff,0x54,0x06] +vmin.u8 q0, q1, q2 + +# CHECK: vmin.u16 q0, q1, q2 @ encoding: [0x12,0xff,0x54,0x06] +# CHECK-NOFP: vmin.u16 q0, q1, q2 @ encoding: [0x12,0xff,0x54,0x06] +vmin.u16 q0, q1, q2 + +# CHECK: vmin.u32 q0, q1, q2 @ encoding: [0x22,0xff,0x54,0x06] +# CHECK-NOFP: vmin.u32 q0, q1, q2 @ encoding: [0x22,0xff,0x54,0x06] +vmin.u32 q0, q1, q2 + +# CHECK: vmax.s8 q3, q0, q7 @ encoding: [0x00,0xef,0x4e,0x66] +# CHECK-NOFP: vmax.s8 q3, q0, q7 @ encoding: [0x00,0xef,0x4e,0x66] +vmax.s8 q3, q0, q7 + +# CHECK: vmax.s16 q0, q1, q2 @ encoding: [0x12,0xef,0x44,0x06] +# CHECK-NOFP: vmax.s16 q0, q1, q2 @ encoding: [0x12,0xef,0x44,0x06] +vmax.s16 q0, q1, q2 + +# CHECK: vmax.s32 q0, q1, q2 @ encoding: [0x22,0xef,0x44,0x06] +# CHECK-NOFP: vmax.s32 q0, q1, q2 @ encoding: [0x22,0xef,0x44,0x06] +vmax.s32 q0, q1, q2 + +# CHECK: vmax.u8 q0, q1, q2 @ encoding: [0x02,0xff,0x44,0x06] +# CHECK-NOFP: vmax.u8 q0, q1, q2 @ encoding: [0x02,0xff,0x44,0x06] +vmax.u8 q0, q1, q2 + +# CHECK: vmax.u16 q0, q1, q2 @ encoding: [0x12,0xff,0x44,0x06] +# CHECK-NOFP: vmax.u16 q0, q1, q2 @ encoding: [0x12,0xff,0x44,0x06] +vmax.u16 q0, q1, q2 + +# CHECK: vmax.u32 q0, q1, q2 @ encoding: [0x22,0xff,0x44,0x06] +# CHECK-NOFP: vmax.u32 q0, q1, q2 @ encoding: [0x22,0xff,0x44,0x06] +vmax.u32 q0, q1, q2 + +vpste +vmint.s8 q0, q1, q2 +vmine.s16 q0, q1, q2 +# CHECK: vpste @ encoding: [0x71,0xfe,0x4d,0x8f] +# CHECK-NOFP: vpste @ encoding: [0x71,0xfe,0x4d,0x8f] +# CHECK: vmint.s8 q0, q1, q2 @ encoding: [0x02,0xef,0x54,0x06] +# CHECK-NOFP: vmint.s8 q0, q1, q2 @ encoding: [0x02,0xef,0x54,0x06] +# CHECK: vmine.s16 q0, q1, q2 @ encoding: [0x12,0xef,0x54,0x06] +# CHECK-NOFP: vmine.s16 q0, q1, q2 @ encoding: [0x12,0xef,0x54,0x06] diff --git a/llvm/test/MC/Disassembler/ARM/mve-minmax.txt b/llvm/test/MC/Disassembler/ARM/mve-minmax.txt new file mode 100644 --- /dev/null +++ b/llvm/test/MC/Disassembler/ARM/mve-minmax.txt @@ -0,0 +1,51 @@ +# RUN: llvm-mc -disassemble -triple=thumbv8.1m.main-none-eabi -mattr=+mve.fp,+fp64 -show-encoding %s | FileCheck %s +# RUN: not llvm-mc -disassemble -triple=thumbv8.1m.main-none-eabi -show-encoding %s &> %t +# RUN: FileCheck --check-prefix=CHECK-NOMVE < %t %s + +# CHECK: vmin.s8 q3, q0, q7 @ encoding: [0x00,0xef,0x5e,0x66] +# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding +[0x00,0xef,0x5e,0x66] + +# CHECK: vmin.s16 q0, q1, q2 @ encoding: [0x12,0xef,0x54,0x06] +# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding +[0x12,0xef,0x54,0x06] + +# CHECK: vmin.s32 q0, q1, q2 @ encoding: [0x22,0xef,0x54,0x06] +# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding +[0x22,0xef,0x54,0x06] + +# CHECK: vmin.u8 q0, q1, q2 @ encoding: [0x02,0xff,0x54,0x06] +# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding +[0x02,0xff,0x54,0x06] + +# CHECK: vmin.u16 q0, q1, q2 @ encoding: [0x12,0xff,0x54,0x06] +# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding +[0x12,0xff,0x54,0x06] + +# CHECK: vmin.u32 q0, q1, q2 @ encoding: [0x22,0xff,0x54,0x06] +# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding +[0x22,0xff,0x54,0x06] + +# CHECK: vmax.s8 q3, q0, q7 @ encoding: [0x00,0xef,0x4e,0x66] +# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding +[0x00,0xef,0x4e,0x66] + +# CHECK: vmax.s16 q0, q1, q2 @ encoding: [0x12,0xef,0x44,0x06] +# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding +[0x12,0xef,0x44,0x06] + +# CHECK: vmax.s32 q0, q1, q2 @ encoding: [0x22,0xef,0x44,0x06] +# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding +[0x22,0xef,0x44,0x06] + +# CHECK: vmax.u8 q0, q1, q2 @ encoding: [0x02,0xff,0x44,0x06] +# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding +[0x02,0xff,0x44,0x06] + +# CHECK: vmax.u16 q0, q1, q2 @ encoding: [0x12,0xff,0x44,0x06] +# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding +[0x12,0xff,0x44,0x06] + +# CHECK: vmax.u32 q0, q1, q2 @ encoding: [0x22,0xff,0x44,0x06] +# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding +[0x22,0xff,0x44,0x06]