1//===- CSKYInstrInfoF2.td - CSKY Instruction Float2.0 ------*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file describes the CSKY instructions in TableGen format.
10//
11//===----------------------------------------------------------------------===//
12
13def regseq_f2 : Operand<i32> {
14  let EncoderMethod = "getRegisterSeqOpValue";
15  let ParserMatchClass = RegSeqAsmOperand<"V2">;
16  let PrintMethod = "printRegisterSeq";
17  let DecoderMethod = "DecodeRegSeqOperandF2";
18  let MIOperandInfo = (ops FPR32, uimm5);
19}
20
21def regseq_d2 : Operand<i32> {
22  let EncoderMethod = "getRegisterSeqOpValue";
23  let ParserMatchClass = RegSeqAsmOperand<"V2">;
24  let PrintMethod = "printRegisterSeq";
25  let DecoderMethod = "DecodeRegSeqOperandD2";
26  let MIOperandInfo = (ops FPR64, uimm5);
27}
28
29def FPR32Op : RegisterOperand<FPR32, "printFPR">;
30def FPR64Op : RegisterOperand<FPR64, "printFPR">;
31
32include "CSKYInstrFormatsF2.td"
33
34// Predicates
35def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{
36  return isOrEquivalentToAdd(N);
37}]>;
38
39//===----------------------------------------------------------------------===//
40// Instructions
41//===----------------------------------------------------------------------===//
42
43defm f2FADD   : F2_XYZ_T<0b000000, "fadd", BinOpFrag<(fadd node:$LHS, node:$RHS)>>;
44defm f2FSUB   : F2_XYZ_T<0b000001, "fsub", BinOpFrag<(fsub node:$LHS, node:$RHS)>>;
45defm f2FDIV   : F2_XYZ_T<0b011000, "fdiv", BinOpFrag<(fdiv node:$LHS, node:$RHS)>>;
46defm f2FMUL   : F2_XYZ_T<0b010000, "fmul", BinOpFrag<(fmul node:$LHS, node:$RHS)>>;
47
48defm f2FMAXNM : F2_XYZ_T<0b101000, "fmaxnm", BinOpFrag<(fmaxnum node:$LHS, node:$RHS)>>;
49defm f2FMINNM : F2_XYZ_T<0b101001, "fminnm", BinOpFrag<(fminnum node:$LHS, node:$RHS)>>;
50
51defm f2FABS   : F2_XZ_T<0b000110, "fabs", fabs>;
52defm f2FNEG   : F2_XZ_T<0b000111, "fneg", fneg>;
53defm f2FSQRT  : F2_XZ_T<0b011010, "fsqrt", fsqrt>;
54defm f2FMOV   : F2_XZ_SET_T<0b000100, "fmov">;
55def f2FMOVX   : F2_XZ_SET<0b00001, FPR32Op, 0b000101, "fmovx.32">;
56
57defm f2RECIP   : F2_XZ_SET_T<0b011001, "frecip">;
58
59// fld/fst
60let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
61  def f2FLD_S : F2_LDST_S<0b0, "fld", (outs FPR32Op:$vrz), (ins GPR:$rx, uimm8_2:$imm8)>;
62  let Predicates = [HasFPUv3_DF] in
63  def f2FLD_D : F2_LDST_D<0b0, "fld", (outs FPR64Op:$vrz), (ins GPR:$rx, uimm8_2:$imm8)>;
64}
65let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
66  def f2FST_S : F2_LDST_S<0b1, "fst", (outs), (ins FPR32Op:$vrz, GPR:$rx, uimm8_2:$imm8)>;
67  let Predicates = [HasFPUv3_DF] in
68  def f2FST_D : F2_LDST_D<0b1, "fst", (outs), (ins FPR64Op:$vrz, GPR:$rx, uimm8_2:$imm8)>;
69}
70
71let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
72  def f2FSTM_S : F2_LDSTM_S<0b1, 0, "fstm", (outs), (ins GPR:$rx, regseq_f2:$regs, variable_ops)>;
73  let Predicates = [HasFPUv3_DF] in
74  def f2FSTM_D : F2_LDSTM_D<0b1, 0, "fstm", (outs), (ins GPR:$rx, regseq_d2:$regs, variable_ops)>;
75
76  def f2FSTMU_S : F2_LDSTM_S<0b1, 0b100, "fstmu", (outs), (ins GPR:$rx, regseq_f2:$regs, variable_ops)>;
77  let Predicates = [HasFPUv3_DF] in
78  def f2FSTMU_D : F2_LDSTM_D<0b1, 0b100, "fstmu", (outs), (ins GPR:$rx, regseq_d2:$regs, variable_ops)>;
79}
80
81let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
82  def f2FLDM_S : F2_LDSTM_S<0b0, 0, "fldm", (outs), (ins GPR:$rx, regseq_f2:$regs, variable_ops)>;
83  let Predicates = [HasFPUv3_DF] in
84  def f2FLDM_D : F2_LDSTM_D<0b0, 0, "fldm", (outs), (ins GPR:$rx,  regseq_d2:$regs, variable_ops)>;
85
86  def f2FLDMU_S : F2_LDSTM_S<0b0, 0b100, "fldmu", (outs), (ins GPR:$rx, regseq_f2:$regs, variable_ops)>;
87  let Predicates = [HasFPUv3_DF] in
88  def f2FLDMU_D : F2_LDSTM_D<0b0, 0b100, "fldmu", (outs), (ins GPR:$rx, regseq_d2:$regs, variable_ops)>;
89}
90
91multiclass FLSR {
92  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
93    def FLDR_S : F2_LDSTR_S<0b0, "fldr", (outs FPR32Op:$rz), (ins GPR:$rx, GPR:$ry, uimm2:$imm)>;
94    let Predicates = [HasFPUv3_DF] in
95    def FLDR_D : F2_LDSTR_D<0b0, "fldr", (outs FPR64Op:$rz), (ins GPR:$rx, GPR:$ry, uimm2:$imm)>;
96  }
97  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
98    def FSTR_S : F2_LDSTR_S<0b1, "fstr", (outs), (ins FPR32Op:$rz, GPR:$rx, GPR:$ry, uimm2:$imm)>;
99    let Predicates = [HasFPUv3_DF] in
100    def FSTR_D : F2_LDSTR_D<0b1, "fstr", (outs), (ins FPR64Op:$rz, GPR:$rx, GPR:$ry, uimm2:$imm)>;
101  }
102}
103
104defm f2: FLSR;
105
106def f2FLRW_S : F2_LRW<0b00, 0b0, "flrw.32", (outs FPR32Op:$vrz), (ins fconstpool_symbol:$imm8)>;
107def f2FLRW_D : F2_LRW<0b01, 0b0, "flrw.64", (outs FPR64Op:$vrz), (ins fconstpool_symbol:$imm8)>;
108
109def : Pat<(f32 (load constpool:$src)), (f2FLRW_S (to_tconstpool tconstpool:$src))>, Requires<[HasFPUv3_SF]>;
110def : Pat<(f64 (load constpool:$src)), (f2FLRW_D (to_tconstpool tconstpool:$src))>, Requires<[HasFPUv3_DF]>;
111
112defm : LdPat<load, uimm8_2, f2FLD_S, f32>, Requires<[HasFPUv3_SF]>;
113defm : LdPat<load, uimm8_2, f2FLD_D, f64>, Requires<[HasFPUv3_DF]>;
114defm : LdrPat<load, f2FLDR_S, f32>, Requires<[HasFPUv3_SF]>;
115defm : LdrPat<load, f2FLDR_D, f64>, Requires<[HasFPUv3_DF]>;
116
117defm : StPat<store, f32, uimm8_2, f2FST_S>, Requires<[HasFPUv3_SF]>;
118defm : StPat<store, f64, uimm8_2, f2FST_D>, Requires<[HasFPUv3_DF]>;
119defm : StrPat<store, f32, f2FSTR_S>, Requires<[HasFPUv3_SF]>;
120defm : StrPat<store, f64, f2FSTR_D>, Requires<[HasFPUv3_DF]>;
121
122// fmfvr
123let vry = 0 in
124def f2FMFVRL   : F2_XYZ<0b00011, 0b011001, "fmfvr.32.1\t$vrz, $vrx",
125                        (outs GPR:$vrz), (ins FPR32Op:$vrx),
126                        [(set GPR:$vrz, (bitconvert FPR32Op:$vrx))]>;
127// TODO: vrz and vrz+1
128def f2FMFVRL_2 : F2_XYZ<0b00011, 0b111010, "fmfvr.32.2\t$vrz, $vry, $vrx",
129                        (outs GPR:$vrz, GPR:$vry), (ins FPR64Op:$vrx),
130                        []>;
131
132let Predicates = [HasFPUv3_DF] in {
133let vry = 0 in {
134let isCodeGenOnly = 1 in
135def f2FMFVRL_D : F2_XYZ<0b00011, 0b011001, "fmfvr.32.1\t$vrz, $vrx",
136                        (outs GPR:$vrz), (ins FPR64Op:$vrx),
137                        []>;
138def f2FMFVRH_D : F2_XYZ<0b00011, 0b011000, "fmfvrh\t$vrz, $vrx",
139                        (outs GPR:$vrz), (ins FPR64Op:$vrx),
140                        []>;
141}
142def f2FMFVR_D  : F2_XYZ<0b00011, 0b111000, "fmfvr.64\t$vrz, $vry, $vrx",
143                        (outs GPR:$vrz, GPR:$vry), (ins FPR64Op:$vrx),
144                        [(set GPR:$vrz, GPR:$vry, (CSKY_BITCAST_TO_LOHI FPR64Op:$vrx))]>;
145}
146
147// fmtvr
148def f2FMTVRL   : F2_XZ_P<0b00011, 0b011011, "fmtvr.32.1",
149                         [(set FPR32Op:$vrz, (bitconvert GPR:$vrx))],
150                         (outs FPR32Op:$vrz), (ins GPR:$vrx)>;
151// TODO: vrz and vrz+1
152def f2FMTVRL_2 : F2_XYZ<0b00011, 0b111110, "fmtvr.32.2\t$vrz, $vrx, $vry",
153                        (outs FPR32Op:$vrz), (ins GPR:$vrx, GPR:$vry),
154                        []>;
155
156let Predicates = [HasFPUv3_DF] in {
157let isCodeGenOnly = 1 in
158def f2FMTVRL_D : F2_XZ_P<0b00011, 0b011011, "fmtvr.32.1",
159                         [],
160                         (outs FPR64Op:$vrz), (ins GPR:$vrx)>;
161let Constraints = "$vrZ = $vrz" in
162def f2FMTVRH_D : F2_XZ_P<0b00011, 0b011010, "fmtvrh",
163                         [],
164                         (outs FPR64Op:$vrz), (ins FPR64Op:$vrZ, GPR:$vrx)>;
165def f2FMTVR_D  : F2_XYZ<0b00011, 0b111100, "fmtvr.64\t$vrz, $vrx, $vry",
166                        (outs FPR64Op:$vrz), (ins GPR:$vrx, GPR:$vry),
167                        [(set FPR64Op:$vrz, (CSKY_BITCAST_FROM_LOHI GPR:$vrx, GPR:$vry))]>;
168}
169
170// fcmp
171
172defm f2FCMPHS: F2_CXY_T<0b001100, "fcmphs">;
173defm f2FCMPLT: F2_CXY_T<0b001101, "fcmplt">;
174defm f2FCMPNE: F2_CXY_T<0b001110, "fcmpne">;
175defm f2FCMPUO: F2_CXY_T<0b001111, "fcmpuo">;
176
177defm f2FCMPHSZ: F2_CX_T<0b001000, "fcmphsz">;
178defm f2FCMPHZ : F2_CX_T<0b101010, "fcmphz">;
179defm f2FCMPLSZ: F2_CX_T<0b101011, "fcmplsz">;
180defm f2FCMPLTZ: F2_CX_T<0b001001, "fcmpltz">;
181defm f2FCMPNEZ: F2_CX_T<0b001010, "fcmpnez">;
182defm f2FCMPUOZ: F2_CX_T<0b001011, "fcmpuoz">;
183
184defm f2FMULA : F2_XYZZ_T<0b010100, "fmula",
185  TriOpFrag<(fadd (fmul node:$LHS, node:$MHS), node:$RHS)>>;
186
187defm f2FMULS : F2_XYZZ_T<0b010110, "fmuls",
188  TriOpFrag<(fsub node:$RHS, (fmul node:$LHS, node:$MHS))>>;
189
190defm f2FFMULA : F2_XYZZ_T<0b110000, "ffmula",
191  TriOpFrag<(fma node:$LHS, node:$MHS, node:$RHS)>>;
192
193defm f2FFMULS : F2_XYZZ_T<0b110001, "ffmuls",
194  TriOpFrag<(fma (fneg node:$LHS), node:$MHS, node:$RHS)>>;
195
196defm f2FFNMULA : F2_XYZZ_T<0b110010, "ffnmula",
197  TriOpFrag<(fneg (fma node:$LHS, node:$MHS, node:$RHS))>>;
198
199defm f2FFNMULS : F2_XYZZ_T<0b110011, "ffnmuls",
200  TriOpFrag<(fma node:$LHS, node:$MHS, (fneg node:$RHS))>>;
201
202defm f2FNMULA : F2_XYZZ_T<0b010111, "fnmula",
203  TriOpFrag<(fneg (fadd (fmul node:$LHS, node:$MHS), node:$RHS))>>;
204
205defm f2FNMULS : F2_XYZZ_T<0b010101, "fnmuls",
206  TriOpFrag<(fneg (fsub node:$RHS, (fmul node:$LHS, node:$MHS)))>>;
207
208defm f2FNMUL : F2_XYZ_T<0b010001, "fnmul",
209  BinOpFrag<(fneg (fmul node:$LHS, node:$RHS))>>;
210
211// fcvt
212def f2FFTOS32_S  : F2_XZ_P<0b01000, 0b011011, "fftoi.f32.s32", [], (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
213def f2FFTOU32_S  : F2_XZ_P<0b01000, 0b011010, "fftoi.f32.u32", [], (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
214def f2FS32TOF_S  : F2_XZ_P<0b01001, 0b011011, "fitof.s32.f32", [], (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
215def f2FU32TOF_S  : F2_XZ_P<0b01001, 0b011010, "fitof.u32.f32", [], (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
216def f2FFTOXU32_S  : F2_XZ_P<0b01000, 0b001010, "fftox.f32.u32", [], (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
217def f2FFTOXS32_S  : F2_XZ_P<0b01000, 0b001011, "fftox.f32.s32", [], (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
218def f2FXTOFU32_S  : F2_XZ_P<0b01001, 0b001010, "fxtof.u32.f32", [], (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
219def f2FXTOFS32_S  : F2_XZ_P<0b01001, 0b001011, "fxtof.s32.f32", [], (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
220let Predicates = [HasFPUv3_DF] in {
221def f2FFTOS32_D  : F2_XZ_P<0b01000, 0b011101, "fftoi.f64.s32", [], (outs FPR32Op:$vrz), (ins FPR64Op:$vrx)>;
222def f2FFTOU32_D  : F2_XZ_P<0b01000, 0b011100, "fftoi.f64.u32", [], (outs FPR32Op:$vrz), (ins FPR64Op:$vrx)>;
223def f2FS32TOF_D  : F2_XZ_P<0b01001, 0b011101, "fitof.s32.f64", [], (outs FPR64Op:$vrz), (ins FPR32Op:$vrx)>;
224def f2FU32TOF_D  : F2_XZ_P<0b01001, 0b011100, "fitof.u32.f64", [], (outs FPR64Op:$vrz), (ins FPR32Op:$vrx)>;
225def f2FFTOXU32_D  : F2_XZ_P<0b01000, 0b001100, "fftox.f64.u32", [], (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
226def f2FFTOXS32_D  : F2_XZ_P<0b01000, 0b001101, "fftox.f64.s32", [], (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
227def f2FXTOFU32_D  : F2_XZ_P<0b01001, 0b001100, "fxtof.u32.f64", [], (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
228def f2FXTOFS32_D  : F2_XZ_P<0b01001, 0b001101, "fxtof.s32.f64", [], (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
229}
230
231defm f2FF32TOSI32 : F2_XZ_RM<0b00011, 0b0000, "fftoi.f32.s32", (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
232defm f2FF32TOUI32 : F2_XZ_RM<0b00011, 0b0001, "fftoi.f32.u32", (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
233defm f2FF32TOFI32 : F2_XZ_RM<0b01000, 0b1001, "fftofi.f32", (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
234let Predicates = [HasFPUv3_DF] in {
235defm f2FF64TOSI32 : F2_XZ_RM<0b00011, 0b0010, "fftoi.f64.s32", (outs FPR32Op:$vrz), (ins FPR64Op:$vrx)>;
236defm f2FF64TOUI32 : F2_XZ_RM<0b00011, 0b0011, "fftoi.f64.u32", (outs FPR32Op:$vrz), (ins FPR64Op:$vrx)>;
237defm f2FF64TOFI32 : F2_XZ_RM<0b01000, 0b1010, "fftofi.f64", (outs FPR32Op:$vrz), (ins FPR32Op:$vrx)>;
238}
239
240def : Pat<(i32 (fp_to_sint (fround FPR32Op:$vrx))), (COPY_TO_REGCLASS (f2FF32TOSI32_RN  $vrx), GPR)>, Requires<[HasFPUv3_SF]>;
241def : Pat<(i32 (fp_to_uint (fround FPR32Op:$vrx))), (COPY_TO_REGCLASS (f2FF32TOUI32_RN  $vrx), GPR)>, Requires<[HasFPUv3_SF]>;
242def : Pat<(i32 (fp_to_sint (fceil  FPR32Op:$vrx))), (COPY_TO_REGCLASS (f2FF32TOSI32_RPI $vrx), GPR)>, Requires<[HasFPUv3_SF]>;
243def : Pat<(i32 (fp_to_uint (fceil  FPR32Op:$vrx))), (COPY_TO_REGCLASS (f2FF32TOUI32_RPI $vrx), GPR)>, Requires<[HasFPUv3_SF]>;
244def : Pat<(i32 (fp_to_sint (ffloor FPR32Op:$vrx))), (COPY_TO_REGCLASS (f2FF32TOSI32_RNI $vrx), GPR)>, Requires<[HasFPUv3_SF]>;
245def : Pat<(i32 (fp_to_uint (ffloor FPR32Op:$vrx))), (COPY_TO_REGCLASS (f2FF32TOUI32_RNI $vrx), GPR)>, Requires<[HasFPUv3_SF]>;
246def : Pat<(i32 (fp_to_sint (ftrunc FPR32Op:$vrx))), (COPY_TO_REGCLASS (f2FF32TOSI32_RZ  $vrx), GPR)>, Requires<[HasFPUv3_SF]>;
247def : Pat<(i32 (fp_to_uint (ftrunc FPR32Op:$vrx))), (COPY_TO_REGCLASS (f2FF32TOUI32_RZ  $vrx), GPR)>, Requires<[HasFPUv3_SF]>;
248def : Pat<(i32 (fp_to_sint FPR32Op:$vrx)), (COPY_TO_REGCLASS (f2FF32TOSI32_RZ $vrx), GPR)>, Requires<[HasFPUv3_SF]>;
249def : Pat<(i32 (fp_to_uint FPR32Op:$vrx)), (COPY_TO_REGCLASS (f2FF32TOUI32_RZ $vrx), GPR)>, Requires<[HasFPUv3_SF]>;
250
251def : Pat<(i32 (fp_to_sint (fround FPR64Op:$vrx))), (COPY_TO_REGCLASS (f2FF64TOSI32_RN  $vrx), GPR)>, Requires<[HasFPUv3_DF]>;
252def : Pat<(i32 (fp_to_uint (fround FPR64Op:$vrx))), (COPY_TO_REGCLASS (f2FF64TOUI32_RN  $vrx), GPR)>, Requires<[HasFPUv3_DF]>;
253def : Pat<(i32 (fp_to_sint (fceil  FPR64Op:$vrx))), (COPY_TO_REGCLASS (f2FF64TOSI32_RPI $vrx), GPR)>, Requires<[HasFPUv3_DF]>;
254def : Pat<(i32 (fp_to_uint (fceil  FPR64Op:$vrx))), (COPY_TO_REGCLASS (f2FF64TOUI32_RPI $vrx), GPR)>, Requires<[HasFPUv3_DF]>;
255def : Pat<(i32 (fp_to_sint (ffloor FPR64Op:$vrx))), (COPY_TO_REGCLASS (f2FF64TOSI32_RNI $vrx), GPR)>, Requires<[HasFPUv3_DF]>;
256def : Pat<(i32 (fp_to_uint (ffloor FPR64Op:$vrx))), (COPY_TO_REGCLASS (f2FF64TOUI32_RNI $vrx), GPR)>, Requires<[HasFPUv3_DF]>;
257def : Pat<(i32 (fp_to_sint (ftrunc FPR64Op:$vrx))), (COPY_TO_REGCLASS (f2FF64TOSI32_RZ  $vrx), GPR)>, Requires<[HasFPUv3_DF]>;
258def : Pat<(i32 (fp_to_uint (ftrunc FPR64Op:$vrx))), (COPY_TO_REGCLASS (f2FF64TOUI32_RZ  $vrx), GPR)>, Requires<[HasFPUv3_DF]>;
259def : Pat<(i32 (fp_to_sint FPR64Op:$vrx)), (COPY_TO_REGCLASS (f2FF64TOSI32_RZ $vrx), GPR)>, Requires<[HasFPUv3_DF]>;
260def : Pat<(i32 (fp_to_uint FPR64Op:$vrx)), (COPY_TO_REGCLASS (f2FF64TOUI32_RZ $vrx), GPR)>, Requires<[HasFPUv3_DF]>;
261
262def : Pat<(sint_to_fp GPR:$vrx), (f2FS32TOF_S (COPY_TO_REGCLASS $vrx, FPR32))>, Requires<[HasFPUv3_SF]>;
263def : Pat<(uint_to_fp GPR:$vrx), (f2FU32TOF_S (COPY_TO_REGCLASS $vrx, FPR32))>, Requires<[HasFPUv3_SF]>;
264def : Pat<(sint_to_fp GPR:$vrx), (f2FS32TOF_D (COPY_TO_REGCLASS $vrx, FPR32))>, Requires<[HasFPUv3_DF]>;
265def : Pat<(uint_to_fp GPR:$vrx), (f2FU32TOF_D (COPY_TO_REGCLASS $vrx, FPR32))>, Requires<[HasFPUv3_DF]>;
266
267let Predicates = [HasFPUv3_DF] in {
268def f2FDTOS   : F2_XZ_P<0b00011, 0b010110, "fdtos", [(set FPR32Op:$vrz, (fpround FPR64Op:$vrx))], (outs FPR32Op:$vrz),
269                        (ins FPR64Op:$vrx)>;
270def f2FSTOD   : F2_XZ_P<0b00011, 0b010111, "fstod", [(set FPR64Op:$vrz, (fpextend FPR32Op:$vrx))], (outs FPR64Op:$vrz),
271                        (ins FPR32Op:$vrx)>;
272}
273
274// fsel
275defm f2FSEL: F2_CXYZ_T<0b111001, "fsel">;
276
277def f2FINS: F2_XZ_SET<0b00000, FPR32Op, 0b011011, "fins.32">;
278
279def : Pat<(f32 fpimm16:$imm),(COPY_TO_REGCLASS (MOVI32 (fpimm32_lo16 fpimm16:$imm)), FPR32)>,
280        Requires<[HasFPUv3_SF]>;
281def : Pat<(f32 fpimm16_16:$imm), (COPY_TO_REGCLASS (MOVIH32 (fpimm32_hi16 fpimm16_16:$imm)), FPR32)>,
282        Requires<[HasFPUv3_SF]>;
283def : Pat<(f32 fpimm:$imm),(COPY_TO_REGCLASS (ORI32 (MOVIH32 (fpimm32_hi16 fpimm:$imm)), (fpimm32_lo16 fpimm:$imm)), FPR32)>,
284        Requires<[HasFPUv3_SF]>;
285
286
287multiclass BRCond_Bin_F2<CondCode CC, string Instr, Instruction Br, Instruction MV, bit IsSelectSwap = 0> {
288  let Predicates = [HasFPUv3_SF] in
289  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, FPR32Op:$rs2, CC)), bb:$imm16),
290            (Br (!cast<Instruction>(Instr#_S) FPR32Op:$rs1, FPR32Op:$rs2), bb:$imm16)>;
291  let Predicates = [HasFPUv3_DF] in
292  def : Pat<(brcond (i32 (setcc FPR64Op:$rs1, FPR64Op:$rs2, CC)), bb:$imm16),
293            (Br (!cast<Instruction>(Instr#_D) FPR64Op:$rs1, FPR64Op:$rs2), bb:$imm16)>;
294
295  let Predicates = [HasFPUv3_SF] in
296  def : Pat<(i32 (setcc FPR32Op:$rs1, FPR32Op:$rs2, CC)),
297            (MV (!cast<Instruction>(Instr#_S) FPR32Op:$rs1, FPR32Op:$rs2))>;
298  let Predicates = [HasFPUv3_DF] in
299  def : Pat<(i32 (setcc FPR64Op:$rs1, FPR64Op:$rs2, CC)),
300            (MV (!cast<Instruction>(Instr#_D) FPR64Op:$rs1, FPR64Op:$rs2))>;
301
302  let Predicates = [HasFPUv3_SF] in {
303  def : Pat<(select (i32 (setcc FPR32Op:$rs1, FPR32Op:$rs2, CC)), FPR32Op:$rx, FPR32Op:$false),
304            !if(
305                !eq(IsSelectSwap, 0),
306                (f2FSEL_S (!cast<Instruction>(Instr#_S) FPR32Op:$rs1, FPR32Op:$rs2), FPR32Op:$rx, FPR32Op:$false),
307                (f2FSEL_S (!cast<Instruction>(Instr#_S) FPR32Op:$rs1, FPR32Op:$rs2), FPR32Op:$false, FPR32Op:$rx)
308               )>;
309  }
310  let Predicates = [HasFPUv3_DF] in {
311  def : Pat<(select (i32 (setcc FPR64Op:$rs1, FPR64Op:$rs2, CC)), FPR64Op:$rx, FPR64Op:$false),
312            !if(
313                !eq(IsSelectSwap, 0),
314                (f2FSEL_D (!cast<Instruction>(Instr#_D) FPR64Op:$rs1, FPR64Op:$rs2), FPR64Op:$rx, FPR64Op:$false),
315                (f2FSEL_D (!cast<Instruction>(Instr#_D) FPR64Op:$rs1, FPR64Op:$rs2), FPR64Op:$false, FPR64Op:$rx)
316               )>;
317  }
318}
319
320multiclass BRCond_Bin_SWAP_F2<CondCode CC, string Instr, Instruction Br, Instruction MV, bit IsSelectSwap = 0> {
321  let Predicates = [HasFPUv3_SF] in
322  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, FPR32Op:$rs2, CC)), bb:$imm16),
323            (Br (!cast<Instruction>(Instr#_S) FPR32Op:$rs2, FPR32Op:$rs1), bb:$imm16)>;
324  let Predicates = [HasFPUv3_DF] in
325  def : Pat<(brcond (i32 (setcc FPR64Op:$rs1, FPR64Op:$rs2, CC)), bb:$imm16),
326            (Br (!cast<Instruction>(Instr#_D) FPR64Op:$rs2, FPR64Op:$rs1), bb:$imm16)>;
327
328  let Predicates = [HasFPUv3_SF] in
329  def : Pat<(i32 (setcc FPR32Op:$rs1, FPR32Op:$rs2, CC)),
330            (MV (!cast<Instruction>(Instr#_S) FPR32Op:$rs2, FPR32Op:$rs1))>;
331  let Predicates = [HasFPUv3_DF] in
332  def : Pat<(i32 (setcc FPR64Op:$rs1, FPR64Op:$rs2, CC)),
333            (MV (!cast<Instruction>(Instr#_D) FPR64Op:$rs2, FPR64Op:$rs1))>;
334
335  let Predicates = [HasFPUv3_SF] in {
336  def : Pat<(select (i32 (setcc FPR32Op:$rs1, FPR32Op:$rs2, CC)), FPR32Op:$rx, FPR32Op:$false),
337            !if(
338                !eq(IsSelectSwap, 0),
339                (f2FSEL_S (!cast<Instruction>(Instr#_S) FPR32Op:$rs2, FPR32Op:$rs1), FPR32Op:$rx, FPR32Op:$false),
340                (f2FSEL_S (!cast<Instruction>(Instr#_S) FPR32Op:$rs2, FPR32Op:$rs1), FPR32Op:$false, FPR32Op:$rx)
341               )>;
342  }
343  let Predicates = [HasFPUv3_DF] in {
344  def : Pat<(select (i32 (setcc FPR64Op:$rs1, FPR64Op:$rs2, CC)), FPR64Op:$rx, FPR64Op:$false),
345            !if(
346                !eq(IsSelectSwap, 0),
347                (f2FSEL_D (!cast<Instruction>(Instr#_D) FPR64Op:$rs2, FPR64Op:$rs1), FPR64Op:$rx, FPR64Op:$false),
348                (f2FSEL_D (!cast<Instruction>(Instr#_D) FPR64Op:$rs2, FPR64Op:$rs1), FPR64Op:$false, FPR64Op:$rx)
349               )>;
350  }
351}
352
353// inverse (order && compare) to (unorder || inverse(compare))
354
355defm : BRCond_Bin_F2<SETUNE, "f2FCMPNE", BT32, MVC32>;
356defm : BRCond_Bin_F2<SETOEQ, "f2FCMPNE", BF32, MVCV32, 1>;
357defm : BRCond_Bin_F2<SETOGE, "f2FCMPHS", BT32, MVC32>;
358defm : BRCond_Bin_F2<SETOLT, "f2FCMPLT", BT32, MVC32>;
359defm : BRCond_Bin_F2<SETUO, "f2FCMPUO", BT32, MVC32>;
360defm : BRCond_Bin_F2<SETO, "f2FCMPUO", BF32, MVCV32, 1>;
361defm : BRCond_Bin_SWAP_F2<SETOGT, "f2FCMPLT", BT32, MVC32>;
362defm : BRCond_Bin_SWAP_F2<SETOLE, "f2FCMPHS", BT32, MVC32>;
363
364defm : BRCond_Bin_F2<SETNE, "f2FCMPNE", BT32, MVC32>;
365defm : BRCond_Bin_F2<SETEQ, "f2FCMPNE", BF32, MVCV32, 1>;
366defm : BRCond_Bin_F2<SETGE, "f2FCMPHS", BT32, MVC32>;
367defm : BRCond_Bin_F2<SETLT, "f2FCMPLT", BT32, MVC32>;
368defm : BRCond_Bin_SWAP_F2<SETGT, "f2FCMPLT", BT32, MVC32>;
369defm : BRCond_Bin_SWAP_F2<SETLE, "f2FCMPHS", BT32, MVC32>;
370
371// ------
372
373let Predicates = [HasFPUv3_SF] in {
374  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, fpimm0, SETOGE)), bb:$imm16),
375            (BT32 (f2FCMPHSZ_S FPR32Op:$rs1), bb:$imm16)>;
376  def : Pat<(i32 (setcc FPR32Op:$rs1, fpimm0, SETOGE)),
377            (MVC32 (f2FCMPHSZ_S FPR32Op:$rs1))>;
378  def : Pat<(select (i32 (setcc FPR32Op:$rs1, fpimm0, SETOGE)), FPR32Op:$rx, FPR32Op:$false),
379            (f2FSEL_S (f2FCMPHSZ_S FPR32Op:$rs1), FPR32Op:$rx, FPR32Op:$false)>;
380  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, fpimm0, SETOLT)), bb:$imm16),
381            (BT32 (f2FCMPLTZ_S FPR32Op:$rs1), bb:$imm16)>;
382  def : Pat<(i32 (setcc FPR32Op:$rs1, fpimm0, SETOLT)),
383            (MVC32 (f2FCMPLTZ_S FPR32Op:$rs1))>;
384  def : Pat<(select (i32 (setcc FPR32Op:$rs1, fpimm0, SETOLT)), FPR32Op:$rx, FPR32Op:$false),
385            (f2FSEL_S (f2FCMPLTZ_S FPR32Op:$rs1), FPR32Op:$rx, FPR32Op:$false)>;
386  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, fpimm0, SETOLE)), bb:$imm16),
387            (BT32 (f2FCMPLSZ_S FPR32Op:$rs1), bb:$imm16)>;
388  def : Pat<(i32 (setcc FPR32Op:$rs1, fpimm0, SETOLE)),
389            (MVC32 (f2FCMPLSZ_S FPR32Op:$rs1))>;
390  def : Pat<(select (i32 (setcc FPR32Op:$rs1, fpimm0, SETOLE)), FPR32Op:$rx, FPR32Op:$false),
391            (f2FSEL_S (f2FCMPLSZ_S FPR32Op:$rs1), FPR32Op:$rx, FPR32Op:$false)>;
392  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, fpimm0, SETOGT)), bb:$imm16),
393            (BT32 (f2FCMPHZ_S FPR32Op:$rs1), bb:$imm16)>;
394  def : Pat<(i32 (setcc FPR32Op:$rs1, fpimm0, SETOGT)),
395            (MVC32 (f2FCMPHZ_S FPR32Op:$rs1))>;
396  def : Pat<(select (i32 (setcc FPR32Op:$rs1, fpimm0, SETOGT)), FPR32Op:$rx, FPR32Op:$false),
397            (f2FSEL_S (f2FCMPHZ_S FPR32Op:$rs1), FPR32Op:$rx, FPR32Op:$false)>;
398  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, fpimm0, SETUNE)), bb:$imm16),
399            (BT32 (f2FCMPNEZ_S FPR32Op:$rs1), bb:$imm16)>;
400  def : Pat<(i32 (setcc FPR32Op:$rs1, fpimm0, SETUNE)),
401            (MVC32 (f2FCMPNEZ_S FPR32Op:$rs1))>;
402  def : Pat<(select (i32 (setcc FPR32Op:$rs1, fpimm0, SETUNE)), FPR32Op:$rx, FPR32Op:$false),
403            (f2FSEL_S (f2FCMPNEZ_S FPR32Op:$rs1), FPR32Op:$rx, FPR32Op:$false)>;
404  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, fpimm, SETUO)), bb:$imm16),
405            (BT32 (f2FCMPUOZ_S FPR32Op:$rs1), bb:$imm16)>;
406  def : Pat<(i32 (setcc FPR32Op:$rs1, fpimm, SETUO)),
407            (MVC32 (f2FCMPUOZ_S FPR32Op:$rs1))>;
408  def : Pat<(select (i32 (setcc FPR32Op:$rs1, fpimm, SETUO)), FPR32Op:$rx, FPR32Op:$false),
409            (f2FSEL_S (f2FCMPUOZ_S FPR32Op:$rs1), FPR32Op:$rx, FPR32Op:$false)>;
410  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, fpimm0, SETGE)), bb:$imm16),
411            (BT32 (f2FCMPHSZ_S FPR32Op:$rs1), bb:$imm16)>;
412  def : Pat<(i32 (setcc FPR32Op:$rs1, fpimm0, SETGE)),
413            (MVC32 (f2FCMPHSZ_S FPR32Op:$rs1))>;
414  def : Pat<(select (i32 (setcc FPR32Op:$rs1, fpimm0, SETGE)), FPR32Op:$rx, FPR32Op:$false),
415            (f2FSEL_S (f2FCMPHSZ_S FPR32Op:$rs1), FPR32Op:$rx, FPR32Op:$false)>;
416  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, fpimm0, SETLT)), bb:$imm16),
417            (BT32 (f2FCMPLTZ_S FPR32Op:$rs1), bb:$imm16)>;
418  def : Pat<(i32 (setcc FPR32Op:$rs1, fpimm0, SETLT)),
419            (MVC32 (f2FCMPLTZ_S FPR32Op:$rs1))>;
420  def : Pat<(select (i32 (setcc FPR32Op:$rs1, fpimm0, SETLT)), FPR32Op:$rx, FPR32Op:$false),
421            (f2FSEL_S (f2FCMPLTZ_S FPR32Op:$rs1), FPR32Op:$rx, FPR32Op:$false)>;
422  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, fpimm0, SETLE)), bb:$imm16),
423            (BT32 (f2FCMPLSZ_S FPR32Op:$rs1), bb:$imm16)>;
424  def : Pat<(i32 (setcc FPR32Op:$rs1, fpimm0, SETLE)),
425            (MVC32 (f2FCMPLSZ_S FPR32Op:$rs1))>;
426  def : Pat<(select (i32 (setcc FPR32Op:$rs1, fpimm0, SETLE)), FPR32Op:$rx, FPR32Op:$false),
427            (f2FSEL_S (f2FCMPLSZ_S FPR32Op:$rs1), FPR32Op:$rx, FPR32Op:$false)>;
428  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, fpimm0, SETGT)), bb:$imm16),
429            (BT32 (f2FCMPHZ_S FPR32Op:$rs1), bb:$imm16)>;
430  def : Pat<(i32 (setcc FPR32Op:$rs1, fpimm0, SETGT)),
431            (MVC32 (f2FCMPHZ_S FPR32Op:$rs1))>;
432  def : Pat<(select (i32 (setcc FPR32Op:$rs1, fpimm0, SETGT)), FPR32Op:$rx, FPR32Op:$false),
433            (f2FSEL_S (f2FCMPHZ_S FPR32Op:$rs1), FPR32Op:$rx, FPR32Op:$false)>;
434
435
436  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, fpimm, SETO)), bb:$imm16),
437            (BF32 (f2FCMPUOZ_S FPR32Op:$rs1), bb:$imm16)>;
438  def : Pat<(i32 (setcc FPR32Op:$rs1, fpimm, SETO)),
439            (MVCV32 (f2FCMPUOZ_S FPR32Op:$rs1))>;
440  def : Pat<(select (i32 (setcc FPR32Op:$rs1, fpimm, SETO)), FPR32Op:$rx, FPR32Op:$false),
441            (f2FSEL_S (f2FCMPUOZ_S FPR32Op:$rs1), FPR32Op:$false, FPR32Op:$rx)>;
442  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, fpimm0, SETOEQ)), bb:$imm16),
443            (BF32 (f2FCMPNEZ_S FPR32Op:$rs1), bb:$imm16)>;
444  def : Pat<(i32 (setcc FPR32Op:$rs1, fpimm0, SETOEQ)),
445            (MVCV32 (f2FCMPNEZ_S FPR32Op:$rs1))>;
446  def : Pat<(select (i32 (setcc FPR32Op:$rs1, fpimm0, SETOEQ)), FPR32Op:$rx, FPR32Op:$false),
447            (f2FSEL_S (f2FCMPNEZ_S FPR32Op:$rs1), FPR32Op:$false, FPR32Op:$rx)>;
448  def : Pat<(brcond (i32 (setcc FPR32Op:$rs1, fpimm0, SETEQ)), bb:$imm16),
449            (BF32 (f2FCMPNEZ_S FPR32Op:$rs1), bb:$imm16)>;
450  def : Pat<(i32 (setcc FPR32Op:$rs1, fpimm0, SETEQ)),
451            (MVCV32 (f2FCMPNEZ_S FPR32Op:$rs1))>;
452  def : Pat<(select (i32 (setcc FPR32Op:$rs1, fpimm0, SETEQ)), FPR32Op:$rx, FPR32Op:$false),
453            (f2FSEL_S (f2FCMPNEZ_S FPR32Op:$rs1), FPR32Op:$false, FPR32Op:$rx)>;
454}
455
456
457let Predicates = [HasFPUv3_SF] in
458def : Pat<(select CARRY:$ca, FPR32Op:$rx, FPR32Op:$false),
459          (f2FSEL_S CARRY:$ca, FPR32Op:$rx, FPR32Op:$false)>;
460let Predicates = [HasFPUv3_DF] in
461def : Pat<(select CARRY:$ca, FPR64Op:$rx, FPR64Op:$false),
462          (f2FSEL_D CARRY:$ca, FPR64Op:$rx, FPR64Op:$false)>;