1// LoongArchFloatInstrFormats.td - LoongArch FP Instr Formats -*- 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//===----------------------------------------------------------------------===//
10//  Describe LoongArch floating-point instructions format
11//
12//  opcode       - operation code.
13//  fd           - destination register operand.
14//  {c/f}{j/k/a} - source register operand.
15//  immN         - immediate data operand.
16//
17//===----------------------------------------------------------------------===//
18
19// Some FP instructions are defined twice, for accepting FPR32 and FPR64, but
20// with the same mnemonic. Also some are codegen-only definitions that
21// nevertheless require a "normal" mnemonic.
22//
23// In order to accommodate these needs, the instruction defs have names
24// suffixed with `_x[SD]` or `_64`, that will get trimmed before the mnemonics
25// are derived.
26class deriveFPInsnMnemonic<string name> {
27  string ret = deriveInsnMnemonic<!subst("_64", "",
28                                         !subst("_xD", "",
29                                                !subst("_xS", "", name)))>.ret;
30}
31
32// 2R-type
33// <opcode | fj | fd>
34class FPFmt2R<bits<32> op, dag outs, dag ins, string opnstr,
35              list<dag> pattern = []>
36    : LAInst<outs, ins, deriveFPInsnMnemonic<NAME>.ret, opnstr, pattern> {
37  bits<5> fj;
38  bits<5> fd;
39
40  let Inst{31-0} = op;
41  let Inst{9-5} = fj;
42  let Inst{4-0} = fd;
43}
44
45// 3R-type
46// <opcode | fk | fj | fd>
47class FPFmt3R<bits<32> op, dag outs, dag ins, string opnstr,
48              list<dag> pattern = []>
49    : LAInst<outs, ins, deriveFPInsnMnemonic<NAME>.ret, opnstr, pattern> {
50  bits<5> fk;
51  bits<5> fj;
52  bits<5> fd;
53
54  let Inst{31-0} = op;
55  let Inst{14-10} = fk;
56  let Inst{9-5} = fj;
57  let Inst{4-0} = fd;
58}
59
60// 4R-type
61// <opcode | fa | fk | fj | fd>
62class FPFmt4R<bits<32> op, dag outs, dag ins, string opnstr,
63              list<dag> pattern = []>
64    : LAInst<outs, ins, deriveFPInsnMnemonic<NAME>.ret, opnstr, pattern> {
65  bits<5> fa;
66  bits<5> fk;
67  bits<5> fj;
68  bits<5> fd;
69
70  let Inst{31-0} = op;
71  let Inst{19-15} = fa;
72  let Inst{14-10} = fk;
73  let Inst{9-5} = fj;
74  let Inst{4-0} = fd;
75}
76
77// 2RI12-type
78// <opcode | I12 | rj | fd>
79class FPFmt2RI12<bits<32> op, dag outs, dag ins, string opnstr,
80                 list<dag> pattern = []>
81    : LAInst<outs, ins, deriveFPInsnMnemonic<NAME>.ret, opnstr, pattern> {
82  bits<12> imm12;
83  bits<5> rj;
84  bits<5> fd;
85
86  let Inst{31-0} = op;
87  let Inst{21-10} = imm12;
88  let Inst{9-5} = rj;
89  let Inst{4-0} = fd;
90}
91
92// FmtFCMP
93// <opcode | fk | fj | cd>
94class FPFmtFCMP<bits<32> op, dag outs, dag ins, string opnstr,
95                list<dag> pattern = []>
96    : LAInst<outs, ins, deriveFPInsnMnemonic<NAME>.ret, opnstr, pattern> {
97  bits<5> fk;
98  bits<5> fj;
99  bits<3> cd;
100
101  let Inst{31-0} = op;
102  let Inst{14-10} = fk;
103  let Inst{9-5} = fj;
104  let Inst{2-0} = cd;
105}
106
107// FPFmtBR
108// <opcode | I21[15:0] | cj | I21[20:16]>
109class FPFmtBR<bits<32> op, dag outs, dag ins, string opnstr,
110              list<dag> pattern = []>
111    : LAInst<outs, ins, deriveFPInsnMnemonic<NAME>.ret, opnstr, pattern> {
112  bits<21> imm21;
113  bits<3> cj;
114
115  let Inst{31-0} = op;
116  let Inst{25-10} = imm21{15-0};
117  let Inst{7-5} = cj;
118  let Inst{4-0} = imm21{20-16};
119}
120
121// FmtFSEL
122// <opcode | ca | fk | fj | fd>
123class FPFmtFSEL<bits<32> op, dag outs, dag ins, string opnstr,
124                list<dag> pattern = []>
125    : LAInst<outs, ins, deriveFPInsnMnemonic<NAME>.ret, opnstr, pattern> {
126  bits<3> ca;
127  bits<5> fk;
128  bits<5> fj;
129  bits<5> fd;
130
131  let Inst{31-0} = op;
132  let Inst{17-15} = ca;
133  let Inst{14-10} = fk;
134  let Inst{9-5} = fj;
135  let Inst{4-0} = fd;
136}
137
138// FPFmtMOV
139// <opcode | src | dst>
140class FPFmtMOV<bits<32> op, dag outs, dag ins, string opnstr,
141               list<dag> pattern = []>
142    : LAInst<outs, ins, deriveFPInsnMnemonic<NAME>.ret, opnstr, pattern> {
143  bits<5> src;
144  bits<5> dst;
145
146  let Inst{31-0} = op;
147  let Inst{9-5} = src;
148  let Inst{4-0} = dst;
149}
150
151// FPFmtMEM
152// <opcode | rk | rj | fd>
153class FPFmtMEM<bits<32> op, dag outs, dag ins, string opnstr,
154               list<dag> pattern = []>
155    : LAInst<outs, ins, deriveFPInsnMnemonic<NAME>.ret, opnstr, pattern> {
156  bits<5> rk;
157  bits<5> rj;
158  bits<5> fd;
159
160  let Inst{31-0} = op;
161  let Inst{14-10} = rk;
162  let Inst{9-5} = rj;
163  let Inst{4-0} = fd;
164}
165
166//===----------------------------------------------------------------------===//
167// Instruction class templates
168//===----------------------------------------------------------------------===//
169
170let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
171class FP_ALU_2R<bits<32> op, RegisterClass rc = FPR32>
172    : FPFmt2R<op, (outs rc:$fd), (ins rc:$fj), "$fd, $fj">;
173
174class FP_ALU_3R<bits<32> op, RegisterClass rc = FPR32>
175    : FPFmt3R<op, (outs rc:$fd), (ins rc:$fj, rc:$fk), "$fd, $fj, $fk">;
176
177class FP_ALU_4R<bits<32> op, RegisterClass rc = FPR32>
178    : FPFmt4R<op, (outs rc:$fd), (ins rc:$fj, rc:$fk, rc:$fa),
179              "$fd, $fj, $fk, $fa">;
180} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
181
182let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
183class FP_CMP<bits<32> op, RegisterClass rc = FPR32>
184    : FPFmtFCMP<op, (outs CFR:$cd), (ins rc:$fj, rc:$fk), "$cd, $fj, $fk">;
185
186class FP_CONV<bits<32> op, RegisterClass rcd = FPR32, RegisterClass rcs = FPR32>
187    : FPFmt2R<op, (outs rcd:$fd), (ins rcs:$fj), "$fd, $fj">;
188
189class FP_MOV<bits<32> op, RegisterClass rcd = FPR32, RegisterClass rcs = FPR32>
190    : FPFmtMOV<op, (outs rcd:$dst), (ins rcs:$src), "$dst, $src">;
191
192class FP_SEL<bits<32> op, RegisterClass rc = FPR32>
193    : FPFmtFSEL<op, (outs rc:$fd), (ins rc:$fj, rc:$fk, CFR:$ca),
194                "$fd, $fj, $fk, $ca">;
195
196class FP_BRANCH<bits<32> opcode>
197    : FPFmtBR<opcode, (outs), (ins CFR:$cj, simm21_lsl2:$imm21),
198              "$cj, $imm21"> {
199  let isBranch = 1;
200  let isTerminator = 1;
201}
202} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
203
204let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
205class FP_LOAD_3R<bits<32> op, RegisterClass rc = FPR32>
206    : FPFmtMEM<op, (outs rc:$fd), (ins GPR:$rj, GPR:$rk),
207               "$fd, $rj, $rk">;
208class FP_LOAD_2RI12<bits<32> op, RegisterClass rc = FPR32>
209    : FPFmt2RI12<op, (outs rc:$fd), (ins GPR:$rj, simm12:$imm12),
210                 "$fd, $rj, $imm12">;
211} // hasSideEffects = 0, mayLoad = 1, mayStore = 0
212
213let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
214class FP_STORE_3R<bits<32> op, RegisterClass rc = FPR32>
215    : FPFmtMEM<op, (outs), (ins rc:$fd, GPR:$rj, GPR:$rk),
216               "$fd, $rj, $rk">;
217class FP_STORE_2RI12<bits<32> op, RegisterClass rc = FPR32>
218    : FPFmt2RI12<op, (outs), (ins rc:$fd, GPR:$rj, simm12:$imm12),
219                 "$fd, $rj, $imm12">;
220} // hasSideEffects = 0, mayLoad = 0, mayStore = 1
221
222// This class is used to define `SET_CFR_{FALSE,TRUE}` instructions which are
223// used to expand `PseudoCopyCFR`.
224class SET_CFR<bits<32> op, string opcstr>
225    : FP_CMP<op> {
226  let isCodeGenOnly = 1;
227  let fj = 0; // fa0
228  let fk = 0; // fa0
229  let AsmString = opcstr # "\t$cd, $$fa0, $$fa0";
230  let OutOperandList = (outs CFR:$cd);
231  let InOperandList = (ins);
232}
233