10b57cec5SDimitry Andric//===-- X86Instr3DNow.td - The 3DNow! Instruction Set ------*- tablegen -*-===//
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric//
90b57cec5SDimitry Andric// This file describes the 3DNow! instruction set, which extends MMX to support
100b57cec5SDimitry Andric// floating point and also adds a few more random instructions for good measure.
110b57cec5SDimitry Andric//
120b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andricclass I3DNow<bits<8> o, Format F, dag outs, dag ins, string asm, list<dag> pat>
150b57cec5SDimitry Andric      : I<o, F, outs, ins, asm, pat>, Requires<[Has3DNow]> {
160b57cec5SDimitry Andric}
170b57cec5SDimitry Andric
180b57cec5SDimitry Andricclass I3DNow_binop<bits<8> o, Format F, dag ins, string Mnemonic, list<dag> pat>
190b57cec5SDimitry Andric      : I3DNow<o, F, (outs VR64:$dst), ins,
200b57cec5SDimitry Andric          !strconcat(Mnemonic, "\t{$src2, $dst|$dst, $src2}"), pat>, ThreeDNow {
210b57cec5SDimitry Andric  let Constraints = "$src1 = $dst";
220b57cec5SDimitry Andric}
230b57cec5SDimitry Andric
240b57cec5SDimitry Andricclass I3DNow_conv<bits<8> o, Format F, dag ins, string Mnemonic, list<dag> pat>
250b57cec5SDimitry Andric      : I3DNow<o, F, (outs VR64:$dst), ins,
260b57cec5SDimitry Andric          !strconcat(Mnemonic, "\t{$src, $dst|$dst, $src}"), pat>, ThreeDNow;
270b57cec5SDimitry Andric
280b57cec5SDimitry Andricmulticlass I3DNow_binop_rm_int<bits<8> opc, string Mn,
290b57cec5SDimitry Andric                               X86FoldableSchedWrite sched, bit Commutable = 0,
300b57cec5SDimitry Andric                               string Ver = ""> {
310b57cec5SDimitry Andric  let isCommutable = Commutable in
320b57cec5SDimitry Andric  def rr : I3DNow_binop<opc, MRMSrcReg, (ins VR64:$src1, VR64:$src2), Mn,
330b57cec5SDimitry Andric    [(set VR64:$dst, (!cast<Intrinsic>(
340b57cec5SDimitry Andric      !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src1, VR64:$src2))]>,
350b57cec5SDimitry Andric      Sched<[sched]>;
360b57cec5SDimitry Andric  def rm : I3DNow_binop<opc, MRMSrcMem, (ins VR64:$src1, i64mem:$src2), Mn,
370b57cec5SDimitry Andric    [(set VR64:$dst, (!cast<Intrinsic>(
380b57cec5SDimitry Andric      !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src1,
390b57cec5SDimitry Andric        (bitconvert (load_mmx addr:$src2))))]>,
400b57cec5SDimitry Andric        Sched<[sched.Folded, sched.ReadAfterFold]>;
410b57cec5SDimitry Andric}
420b57cec5SDimitry Andric
430b57cec5SDimitry Andricmulticlass I3DNow_conv_rm_int<bits<8> opc, string Mn,
440b57cec5SDimitry Andric                              X86FoldableSchedWrite sched, string Ver = ""> {
450b57cec5SDimitry Andric  def rr : I3DNow_conv<opc, MRMSrcReg, (ins VR64:$src), Mn,
460b57cec5SDimitry Andric    [(set VR64:$dst, (!cast<Intrinsic>(
470b57cec5SDimitry Andric      !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src))]>,
480b57cec5SDimitry Andric      Sched<[sched]>;
490b57cec5SDimitry Andric  def rm : I3DNow_conv<opc, MRMSrcMem, (ins i64mem:$src), Mn,
500b57cec5SDimitry Andric    [(set VR64:$dst, (!cast<Intrinsic>(
510b57cec5SDimitry Andric      !strconcat("int_x86_3dnow", Ver, "_", Mn))
520b57cec5SDimitry Andric        (bitconvert (load_mmx addr:$src))))]>,
530b57cec5SDimitry Andric        Sched<[sched.Folded, sched.ReadAfterFold]>;
540b57cec5SDimitry Andric}
550b57cec5SDimitry Andric
560b57cec5SDimitry Andricdefm PAVGUSB  : I3DNow_binop_rm_int<0xBF, "pavgusb", SchedWriteVecALU.MMX, 1>;
570b57cec5SDimitry Andricdefm PF2ID    : I3DNow_conv_rm_int<0x1D, "pf2id", WriteCvtPS2I>;
580b57cec5SDimitry Andricdefm PFACC    : I3DNow_binop_rm_int<0xAE, "pfacc", WriteFAdd>;
590b57cec5SDimitry Andricdefm PFADD    : I3DNow_binop_rm_int<0x9E, "pfadd", WriteFAdd, 1>;
600b57cec5SDimitry Andricdefm PFCMPEQ  : I3DNow_binop_rm_int<0xB0, "pfcmpeq", WriteFAdd, 1>;
610b57cec5SDimitry Andricdefm PFCMPGE  : I3DNow_binop_rm_int<0x90, "pfcmpge", WriteFAdd>;
620b57cec5SDimitry Andricdefm PFCMPGT  : I3DNow_binop_rm_int<0xA0, "pfcmpgt", WriteFAdd>;
630b57cec5SDimitry Andricdefm PFMAX    : I3DNow_binop_rm_int<0xA4, "pfmax", WriteFAdd>;
640b57cec5SDimitry Andricdefm PFMIN    : I3DNow_binop_rm_int<0x94, "pfmin", WriteFAdd>;
650b57cec5SDimitry Andricdefm PFMUL    : I3DNow_binop_rm_int<0xB4, "pfmul", WriteFAdd, 1>;
660b57cec5SDimitry Andricdefm PFRCP    : I3DNow_conv_rm_int<0x96, "pfrcp", WriteFAdd>;
670b57cec5SDimitry Andricdefm PFRCPIT1 : I3DNow_binop_rm_int<0xA6, "pfrcpit1", WriteFAdd>;
680b57cec5SDimitry Andricdefm PFRCPIT2 : I3DNow_binop_rm_int<0xB6, "pfrcpit2", WriteFAdd>;
690b57cec5SDimitry Andricdefm PFRSQIT1 : I3DNow_binop_rm_int<0xA7, "pfrsqit1", WriteFAdd>;
700b57cec5SDimitry Andricdefm PFRSQRT  : I3DNow_conv_rm_int<0x97, "pfrsqrt", WriteFAdd>;
710b57cec5SDimitry Andricdefm PFSUB    : I3DNow_binop_rm_int<0x9A, "pfsub", WriteFAdd, 1>;
720b57cec5SDimitry Andricdefm PFSUBR   : I3DNow_binop_rm_int<0xAA, "pfsubr", WriteFAdd, 1>;
730b57cec5SDimitry Andricdefm PI2FD    : I3DNow_conv_rm_int<0x0D, "pi2fd", WriteCvtI2PS>;
740b57cec5SDimitry Andricdefm PMULHRW  : I3DNow_binop_rm_int<0xB7, "pmulhrw", SchedWriteVecIMul.MMX, 1>;
750b57cec5SDimitry Andric
760b57cec5SDimitry Andriclet SchedRW = [WriteEMMS],
770b57cec5SDimitry Andric    Defs = [MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
780b57cec5SDimitry Andric            ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7] in
790b57cec5SDimitry Andricdef FEMMS : I3DNow<0x0E, RawFrm, (outs), (ins), "femms",
800b57cec5SDimitry Andric                   [(int_x86_mmx_femms)]>, TB;
810b57cec5SDimitry Andric
820b57cec5SDimitry Andriclet SchedRW = [WriteLoad] in {
830b57cec5SDimitry Andriclet Predicates = [Has3DNow, NoSSEPrefetch] in
840b57cec5SDimitry Andricdef PREFETCH : I3DNow<0x0D, MRM0m, (outs), (ins i8mem:$addr),
850b57cec5SDimitry Andric                      "prefetch\t$addr",
865f757f3fSDimitry Andric                      [(prefetch addr:$addr, timm, timm, (i32 1))]>, TB;
870b57cec5SDimitry Andric
880b57cec5SDimitry Andricdef PREFETCHW : I<0x0D, MRM1m, (outs), (ins i8mem:$addr), "prefetchw\t$addr",
890b57cec5SDimitry Andric                  [(prefetch addr:$addr, (i32 1), (i32 PrefetchWLevel), (i32 1))]>,
900b57cec5SDimitry Andric                  TB, Requires<[HasPrefetchW]>;
910b57cec5SDimitry Andric
920b57cec5SDimitry Andricdef PREFETCHWT1 : I<0x0D, MRM2m, (outs), (ins i8mem:$addr), "prefetchwt1\t$addr",
930b57cec5SDimitry Andric                    [(prefetch addr:$addr, (i32 1), (i32 PrefetchWT1Level), (i32 1))]>,
940b57cec5SDimitry Andric                    TB, Requires<[HasPREFETCHWT1]>;
950b57cec5SDimitry Andric}
960b57cec5SDimitry Andric
970b57cec5SDimitry Andric// "3DNowA" instructions
980b57cec5SDimitry Andricdefm PF2IW    : I3DNow_conv_rm_int<0x1C, "pf2iw", WriteCvtPS2I, "a">;
990b57cec5SDimitry Andricdefm PI2FW    : I3DNow_conv_rm_int<0x0C, "pi2fw", WriteCvtI2PS, "a">;
1000b57cec5SDimitry Andricdefm PFNACC   : I3DNow_binop_rm_int<0x8A, "pfnacc", WriteFAdd, 0, "a">;
1010b57cec5SDimitry Andricdefm PFPNACC  : I3DNow_binop_rm_int<0x8E, "pfpnacc", WriteFAdd, 0, "a">;
1020b57cec5SDimitry Andricdefm PSWAPD   : I3DNow_conv_rm_int<0xBB, "pswapd", SchedWriteShuffle.MMX, "a">;
103