/ externals / biscuit / src / assembler_floating_point.cpp
assembler_floating_point.cpp
  1  #include <biscuit/assert.hpp>
  2  #include <biscuit/assembler.hpp>
  3  
  4  #include <algorithm>
  5  #include <array>
  6  #include <cstring>
  7  #include <iterator>
  8  
  9  #include "assembler_util.hpp"
 10  
 11  // Various floating-point-based extension instructions.
 12  
 13  namespace biscuit {
 14  
 15  // RV32F Extension Instructions
 16  
 17  void Assembler::FADD_S(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
 18      EmitRType(m_buffer, 0b0000000, rs2, rs1, rmode, rd, 0b1010011);
 19  }
 20  void Assembler::FCLASS_S(GPR rd, FPR rs1) noexcept {
 21      EmitRType(m_buffer, 0b1110000, f0, rs1, 0b001, rd, 0b1010011);
 22  }
 23  void Assembler::FCVT_S_W(FPR rd, GPR rs1, RMode rmode) noexcept {
 24      EmitRType(m_buffer, 0b1101000, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
 25  }
 26  void Assembler::FCVT_S_WU(FPR rd, GPR rs1, RMode rmode) noexcept {
 27      EmitRType(m_buffer, 0b1101000, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
 28  }
 29  void Assembler::FCVT_W_S(GPR rd, FPR rs1, RMode rmode) noexcept {
 30      EmitRType(m_buffer, 0b1100000, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
 31  }
 32  void Assembler::FCVT_WU_S(GPR rd, FPR rs1, RMode rmode) noexcept {
 33      EmitRType(m_buffer, 0b1100000, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
 34  }
 35  void Assembler::FDIV_S(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
 36      EmitRType(m_buffer, 0b0001100, rs2, rs1, rmode, rd, 0b1010011);
 37  }
 38  void Assembler::FEQ_S(GPR rd, FPR rs1, FPR rs2) noexcept {
 39      EmitRType(m_buffer, 0b1010000, rs2, rs1, 0b010, rd, 0b1010011);
 40  }
 41  void Assembler::FLE_S(GPR rd, FPR rs1, FPR rs2) noexcept {
 42      EmitRType(m_buffer, 0b1010000, rs2, rs1, 0b000, rd, 0b1010011);
 43  }
 44  void Assembler::FLT_S(GPR rd, FPR rs1, FPR rs2) noexcept {
 45      EmitRType(m_buffer, 0b1010000, rs2, rs1, 0b001, rd, 0b1010011);
 46  }
 47  void Assembler::FLW(FPR rd, int32_t offset, GPR rs) noexcept {
 48      BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
 49      EmitIType(m_buffer, static_cast<uint32_t>(offset), rs, 0b010, rd, 0b0000111);
 50  }
 51  void Assembler::FMADD_S(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
 52      EmitR4Type(m_buffer, rs3, 0b00, rs2, rs1, rmode, rd, 0b1000011);
 53  }
 54  void Assembler::FMAX_S(FPR rd, FPR rs1, FPR rs2) noexcept {
 55      EmitRType(m_buffer, 0b0010100, rs2, rs1, 0b001, rd, 0b1010011);
 56  }
 57  void Assembler::FMIN_S(FPR rd, FPR rs1, FPR rs2) noexcept {
 58      EmitRType(m_buffer, 0b0010100, rs2, rs1, 0b000, rd, 0b1010011);
 59  }
 60  void Assembler::FMSUB_S(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
 61      EmitR4Type(m_buffer, rs3, 0b00, rs2, rs1, rmode, rd, 0b1000111);
 62  }
 63  void Assembler::FMUL_S(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
 64      EmitRType(m_buffer, 0b0001000, rs2, rs1, rmode, rd, 0b1010011);
 65  }
 66  void Assembler::FMV_W_X(FPR rd, GPR rs1) noexcept {
 67      EmitRType(m_buffer, 0b1111000, f0, rs1, 0b000, rd, 0b1010011);
 68  }
 69  void Assembler::FMV_X_W(GPR rd, FPR rs1) noexcept {
 70      EmitRType(m_buffer, 0b1110000, f0, rs1, 0b000, rd, 0b1010011);
 71  }
 72  void Assembler::FNMADD_S(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
 73      EmitR4Type(m_buffer, rs3, 0b00, rs2, rs1, rmode, rd, 0b1001111);
 74  }
 75  void Assembler::FNMSUB_S(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
 76      EmitR4Type(m_buffer, rs3, 0b00, rs2, rs1, rmode, rd, 0b1001011);
 77  }
 78  void Assembler::FSGNJ_S(FPR rd, FPR rs1, FPR rs2) noexcept {
 79      EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b000, rd, 0b1010011);
 80  }
 81  void Assembler::FSGNJN_S(FPR rd, FPR rs1, FPR rs2) noexcept {
 82      EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b001, rd, 0b1010011);
 83  }
 84  void Assembler::FSGNJX_S(FPR rd, FPR rs1, FPR rs2) noexcept {
 85      EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b010, rd, 0b1010011);
 86  }
 87  void Assembler::FSQRT_S(FPR rd, FPR rs1, RMode rmode) noexcept {
 88      EmitRType(m_buffer, 0b0101100, f0, rs1, rmode, rd, 0b1010011);
 89  }
 90  void Assembler::FSUB_S(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
 91      EmitRType(m_buffer, 0b0000100, rs2, rs1, rmode, rd, 0b1010011);
 92  }
 93  void Assembler::FSW(FPR rs2, int32_t offset, GPR rs1) noexcept {
 94      BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
 95      EmitSType(m_buffer, static_cast<uint32_t>(offset), rs2, rs1, 0b010, 0b0100111);
 96  }
 97  
 98  void Assembler::FABS_S(FPR rd, FPR rs) noexcept {
 99      FSGNJX_S(rd, rs, rs);
100  }
101  void Assembler::FMV_S(FPR rd, FPR rs) noexcept {
102      FSGNJ_S(rd, rs, rs);
103  }
104  void Assembler::FNEG_S(FPR rd, FPR rs) noexcept {
105      FSGNJN_S(rd, rs, rs);
106  }
107  
108  // RV64F Extension Instructions
109  
110  void Assembler::FCVT_L_S(GPR rd, FPR rs1, RMode rmode) noexcept {
111      BISCUIT_ASSERT(IsRV64(m_features));
112      EmitRType(m_buffer, 0b1100000, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
113  }
114  void Assembler::FCVT_LU_S(GPR rd, FPR rs1, RMode rmode) noexcept {
115      BISCUIT_ASSERT(IsRV64(m_features));
116      EmitRType(m_buffer, 0b1100000, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
117  }
118  void Assembler::FCVT_S_L(FPR rd, GPR rs1, RMode rmode) noexcept {
119      BISCUIT_ASSERT(IsRV64(m_features));
120      EmitRType(m_buffer, 0b1101000, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
121  }
122  void Assembler::FCVT_S_LU(FPR rd, GPR rs1, RMode rmode) noexcept {
123      BISCUIT_ASSERT(IsRV64(m_features));
124      EmitRType(m_buffer, 0b1101000, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
125  }
126  
127  // RV32D Extension Instructions
128  
129  void Assembler::FADD_D(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
130      EmitRType(m_buffer, 0b0000001, rs2, rs1, rmode, rd, 0b1010011);
131  }
132  void Assembler::FCLASS_D(GPR rd, FPR rs1) noexcept {
133      EmitRType(m_buffer, 0b1110001, f0, rs1, 0b001, rd, 0b1010011);
134  }
135  void Assembler::FCVT_D_W(FPR rd, GPR rs1, RMode rmode) noexcept {
136      EmitRType(m_buffer, 0b1101001, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
137  }
138  void Assembler::FCVT_D_WU(FPR rd, GPR rs1, RMode rmode) noexcept {
139      EmitRType(m_buffer, 0b1101001, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
140  }
141  void Assembler::FCVT_W_D(GPR rd, FPR rs1, RMode rmode) noexcept {
142      EmitRType(m_buffer, 0b1100001, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
143  }
144  void Assembler::FCVT_WU_D(GPR rd, FPR rs1, RMode rmode) noexcept {
145      EmitRType(m_buffer, 0b1100001, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
146  }
147  void Assembler::FCVT_D_S(FPR rd, FPR rs1, RMode rmode) noexcept {
148      EmitRType(m_buffer, 0b0100001, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
149  }
150  void Assembler::FCVT_S_D(FPR rd, FPR rs1, RMode rmode) noexcept {
151      EmitRType(m_buffer, 0b0100000, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
152  }
153  void Assembler::FDIV_D(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
154      EmitRType(m_buffer, 0b0001101, rs2, rs1, rmode, rd, 0b1010011);
155  }
156  void Assembler::FEQ_D(GPR rd, FPR rs1, FPR rs2) noexcept {
157      EmitRType(m_buffer, 0b1010001, rs2, rs1, 0b010, rd, 0b1010011);
158  }
159  void Assembler::FLE_D(GPR rd, FPR rs1, FPR rs2) noexcept {
160      EmitRType(m_buffer, 0b1010001, rs2, rs1, 0b000, rd, 0b1010011);
161  }
162  void Assembler::FLT_D(GPR rd, FPR rs1, FPR rs2) noexcept {
163      EmitRType(m_buffer, 0b1010001, rs2, rs1, 0b001, rd, 0b1010011);
164  }
165  void Assembler::FLD(FPR rd, int32_t offset, GPR rs) noexcept {
166      BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
167      EmitIType(m_buffer, static_cast<uint32_t>(offset), rs, 0b011, rd, 0b0000111);
168  }
169  void Assembler::FMADD_D(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
170      EmitR4Type(m_buffer, rs3, 0b01, rs2, rs1, rmode, rd, 0b1000011);
171  }
172  void Assembler::FMAX_D(FPR rd, FPR rs1, FPR rs2) noexcept {
173      EmitRType(m_buffer, 0b0010101, rs2, rs1, 0b001, rd, 0b1010011);
174  }
175  void Assembler::FMIN_D(FPR rd, FPR rs1, FPR rs2) noexcept {
176      EmitRType(m_buffer, 0b0010101, rs2, rs1, 0b000, rd, 0b1010011);
177  }
178  void Assembler::FMSUB_D(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
179      EmitR4Type(m_buffer, rs3, 0b01, rs2, rs1, rmode, rd, 0b1000111);
180  }
181  void Assembler::FMUL_D(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
182      EmitRType(m_buffer, 0b0001001, rs2, rs1, rmode, rd, 0b1010011);
183  }
184  void Assembler::FNMADD_D(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
185      EmitR4Type(m_buffer, rs3, 0b01, rs2, rs1, rmode, rd, 0b1001111);
186  }
187  void Assembler::FNMSUB_D(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
188      EmitR4Type(m_buffer, rs3, 0b01, rs2, rs1, rmode, rd, 0b1001011);
189  }
190  void Assembler::FSGNJ_D(FPR rd, FPR rs1, FPR rs2) noexcept {
191      EmitRType(m_buffer, 0b0010001, rs2, rs1, 0b000, rd, 0b1010011);
192  }
193  void Assembler::FSGNJN_D(FPR rd, FPR rs1, FPR rs2) noexcept {
194      EmitRType(m_buffer, 0b0010001, rs2, rs1, 0b001, rd, 0b1010011);
195  }
196  void Assembler::FSGNJX_D(FPR rd, FPR rs1, FPR rs2) noexcept {
197      EmitRType(m_buffer, 0b0010001, rs2, rs1, 0b010, rd, 0b1010011);
198  }
199  void Assembler::FSQRT_D(FPR rd, FPR rs1, RMode rmode) noexcept {
200      EmitRType(m_buffer, 0b0101101, f0, rs1, rmode, rd, 0b1010011);
201  }
202  void Assembler::FSUB_D(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
203      EmitRType(m_buffer, 0b0000101, rs2, rs1, rmode, rd, 0b1010011);
204  }
205  void Assembler::FSD(FPR rs2, int32_t offset, GPR rs1) noexcept {
206      BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
207      EmitSType(m_buffer, static_cast<uint32_t>(offset), rs2, rs1, 0b011, 0b0100111);
208  }
209  
210  void Assembler::FABS_D(FPR rd, FPR rs) noexcept {
211      FSGNJX_D(rd, rs, rs);
212  }
213  void Assembler::FMV_D(FPR rd, FPR rs) noexcept {
214      FSGNJ_D(rd, rs, rs);
215  }
216  void Assembler::FNEG_D(FPR rd, FPR rs) noexcept {
217      FSGNJN_D(rd, rs, rs);
218  }
219  
220  // RV64D Extension Instructions
221  
222  void Assembler::FCVT_L_D(GPR rd, FPR rs1, RMode rmode) noexcept {
223      BISCUIT_ASSERT(IsRV64(m_features));
224      EmitRType(m_buffer, 0b1100001, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
225  }
226  void Assembler::FCVT_LU_D(GPR rd, FPR rs1, RMode rmode) noexcept {
227      BISCUIT_ASSERT(IsRV64(m_features));
228      EmitRType(m_buffer, 0b1100001, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
229  }
230  void Assembler::FCVT_D_L(FPR rd, GPR rs1, RMode rmode) noexcept {
231      BISCUIT_ASSERT(IsRV64(m_features));
232      EmitRType(m_buffer, 0b1101001, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
233  }
234  void Assembler::FCVT_D_LU(FPR rd, GPR rs1, RMode rmode) noexcept {
235      BISCUIT_ASSERT(IsRV64(m_features));
236      EmitRType(m_buffer, 0b1101001, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
237  }
238  void Assembler::FMV_D_X(FPR rd, GPR rs1) noexcept {
239      BISCUIT_ASSERT(IsRV64OrRV128(m_features));
240      EmitRType(m_buffer, 0b1111001, f0, rs1, 0b000, rd, 0b1010011);
241  }
242  void Assembler::FMV_X_D(GPR rd, FPR rs1) noexcept {
243      BISCUIT_ASSERT(IsRV64OrRV128(m_features));
244      EmitRType(m_buffer, 0b1110001, f0, rs1, 0b000, rd, 0b1010011);
245  }
246  
247  // RV32Q Extension Instructions
248  
249  void Assembler::FADD_Q(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
250      EmitRType(m_buffer, 0b0000011, rs2, rs1, rmode, rd, 0b1010011);
251  }
252  void Assembler::FCLASS_Q(GPR rd, FPR rs1) noexcept {
253      EmitRType(m_buffer, 0b1110011, f0, rs1, 0b001, rd, 0b1010011);
254  }
255  void Assembler::FCVT_Q_W(FPR rd, GPR rs1, RMode rmode) noexcept {
256      EmitRType(m_buffer, 0b1101011, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
257  }
258  void Assembler::FCVT_Q_WU(FPR rd, GPR rs1, RMode rmode) noexcept {
259      EmitRType(m_buffer, 0b1101011, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
260  }
261  void Assembler::FCVT_W_Q(GPR rd, FPR rs1, RMode rmode) noexcept {
262      EmitRType(m_buffer, 0b1100011, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
263  }
264  void Assembler::FCVT_WU_Q(GPR rd, FPR rs1, RMode rmode) noexcept {
265      EmitRType(m_buffer, 0b1100011, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
266  }
267  void Assembler::FCVT_Q_D(FPR rd, FPR rs1, RMode rmode) noexcept {
268      EmitRType(m_buffer, 0b0100011, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
269  }
270  void Assembler::FCVT_D_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
271      EmitRType(m_buffer, 0b0100001, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
272  }
273  void Assembler::FCVT_Q_S(FPR rd, FPR rs1, RMode rmode) noexcept {
274      EmitRType(m_buffer, 0b0100011, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
275  }
276  void Assembler::FCVT_S_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
277      EmitRType(m_buffer, 0b0100000, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
278  }
279  void Assembler::FDIV_Q(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
280      EmitRType(m_buffer, 0b0001111, rs2, rs1, rmode, rd, 0b1010011);
281  }
282  void Assembler::FEQ_Q(GPR rd, FPR rs1, FPR rs2) noexcept {
283      EmitRType(m_buffer, 0b1010011, rs2, rs1, 0b010, rd, 0b1010011);
284  }
285  void Assembler::FLE_Q(GPR rd, FPR rs1, FPR rs2) noexcept {
286      EmitRType(m_buffer, 0b1010011, rs2, rs1, 0b000, rd, 0b1010011);
287  }
288  void Assembler::FLT_Q(GPR rd, FPR rs1, FPR rs2) noexcept {
289      EmitRType(m_buffer, 0b1010011, rs2, rs1, 0b001, rd, 0b1010011);
290  }
291  void Assembler::FLQ(FPR rd, int32_t offset, GPR rs) noexcept {
292      BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
293      EmitIType(m_buffer, static_cast<uint32_t>(offset), rs, 0b100, rd, 0b0000111);
294  }
295  void Assembler::FMADD_Q(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
296      EmitR4Type(m_buffer, rs3, 0b11, rs2, rs1, rmode, rd, 0b1000011);
297  }
298  void Assembler::FMAX_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
299      EmitRType(m_buffer, 0b0010111, rs2, rs1, 0b001, rd, 0b1010011);
300  }
301  void Assembler::FMIN_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
302      EmitRType(m_buffer, 0b0010111, rs2, rs1, 0b000, rd, 0b1010011);
303  }
304  void Assembler::FMSUB_Q(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
305      EmitR4Type(m_buffer, rs3, 0b11, rs2, rs1, rmode, rd, 0b1000111);
306  }
307  void Assembler::FMUL_Q(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
308      EmitRType(m_buffer, 0b0001011, rs2, rs1, rmode, rd, 0b1010011);
309  }
310  void Assembler::FNMADD_Q(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
311      EmitR4Type(m_buffer, rs3, 0b11, rs2, rs1, rmode, rd, 0b1001111);
312  }
313  void Assembler::FNMSUB_Q(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
314      EmitR4Type(m_buffer, rs3, 0b11, rs2, rs1, rmode, rd, 0b1001011);
315  }
316  void Assembler::FSGNJ_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
317      EmitRType(m_buffer, 0b0010011, rs2, rs1, 0b000, rd, 0b1010011);
318  }
319  void Assembler::FSGNJN_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
320      EmitRType(m_buffer, 0b0010011, rs2, rs1, 0b001, rd, 0b1010011);
321  }
322  void Assembler::FSGNJX_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
323      EmitRType(m_buffer, 0b0010011, rs2, rs1, 0b010, rd, 0b1010011);
324  }
325  void Assembler::FSQRT_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
326      EmitRType(m_buffer, 0b0101111, f0, rs1, rmode, rd, 0b1010011);
327  }
328  void Assembler::FSUB_Q(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
329      EmitRType(m_buffer, 0b0000111, rs2, rs1, rmode, rd, 0b1010011);
330  }
331  void Assembler::FSQ(FPR rs2, int32_t offset, GPR rs1) noexcept {
332      BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
333      EmitSType(m_buffer, static_cast<uint32_t>(offset), rs2, rs1, 0b100, 0b0100111);
334  }
335  
336  void Assembler::FABS_Q(FPR rd, FPR rs) noexcept {
337      FSGNJX_Q(rd, rs, rs);
338  }
339  void Assembler::FMV_Q(FPR rd, FPR rs) noexcept {
340      FSGNJ_Q(rd, rs, rs);
341  }
342  void Assembler::FNEG_Q(FPR rd, FPR rs) noexcept {
343      FSGNJN_Q(rd, rs, rs);
344  }
345  
346  // RV64Q Extension Instructions
347  
348  void Assembler::FCVT_L_Q(GPR rd, FPR rs1, RMode rmode) noexcept {
349      BISCUIT_ASSERT(IsRV64(m_features));
350      EmitRType(m_buffer, 0b1100011, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
351  }
352  void Assembler::FCVT_LU_Q(GPR rd, FPR rs1, RMode rmode) noexcept {
353      BISCUIT_ASSERT(IsRV64(m_features));
354      EmitRType(m_buffer, 0b1100011, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
355  }
356  void Assembler::FCVT_Q_L(FPR rd, GPR rs1, RMode rmode) noexcept {
357      BISCUIT_ASSERT(IsRV64(m_features));
358      EmitRType(m_buffer, 0b1101011, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
359  }
360  void Assembler::FCVT_Q_LU(FPR rd, GPR rs1, RMode rmode) noexcept {
361      BISCUIT_ASSERT(IsRV64(m_features));
362      EmitRType(m_buffer, 0b1101011, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
363  }
364  
365  // RV32Zfh Extension Instructions
366  
367  void Assembler::FADD_H(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
368      EmitRType(m_buffer, 0b0000010, rs2, rs1, rmode, rd, 0b1010011);
369  }
370  void Assembler::FCLASS_H(GPR rd, FPR rs1) noexcept {
371      EmitRType(m_buffer, 0b1110010, f0, rs1, 0b001, rd, 0b1010011);
372  }
373  void Assembler::FCVT_D_H(FPR rd, FPR rs1, RMode rmode) noexcept {
374      EmitRType(m_buffer, 0b0100001, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
375  }
376  void Assembler::FCVT_H_D(FPR rd, FPR rs1, RMode rmode) noexcept {
377      EmitRType(m_buffer, 0b0100010, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
378  }
379  void Assembler::FCVT_H_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
380      EmitRType(m_buffer, 0b0100010, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
381  }
382  void Assembler::FCVT_H_S(FPR rd, FPR rs1, RMode rmode) noexcept {
383      EmitRType(m_buffer, 0b0100010, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
384  }
385  void Assembler::FCVT_H_W(FPR rd, GPR rs1, RMode rmode) noexcept {
386      EmitRType(m_buffer, 0b1101010, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
387  }
388  void Assembler::FCVT_H_WU(FPR rd, GPR rs1, RMode rmode) noexcept {
389      EmitRType(m_buffer, 0b1101010, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
390  }
391  void Assembler::FCVT_Q_H(FPR rd, FPR rs1, RMode rmode) noexcept {
392      EmitRType(m_buffer, 0b0100011, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
393  }
394  void Assembler::FCVT_S_H(FPR rd, FPR rs1, RMode rmode) noexcept {
395      EmitRType(m_buffer, 0b0100000, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
396  }
397  void Assembler::FCVT_W_H(GPR rd, FPR rs1, RMode rmode) noexcept {
398      EmitRType(m_buffer, 0b1100010, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
399  }
400  void Assembler::FCVT_WU_H(GPR rd, FPR rs1, RMode rmode) noexcept {
401      EmitRType(m_buffer, 0b1100010, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
402  }
403  void Assembler::FDIV_H(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
404      EmitRType(m_buffer, 0b0001110, rs2, rs1, rmode, rd, 0b1010011);
405  }
406  void Assembler::FEQ_H(GPR rd, FPR rs1, FPR rs2) noexcept {
407      EmitRType(m_buffer, 0b1010010, rs2, rs1, 0b010, rd, 0b1010011);
408  }
409  void Assembler::FLE_H(GPR rd, FPR rs1, FPR rs2) noexcept {
410      EmitRType(m_buffer, 0b1010010, rs2, rs1, 0b000, rd, 0b1010011);
411  }
412  void Assembler::FLH(FPR rd, int32_t offset, GPR rs) noexcept {
413      BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
414      EmitIType(m_buffer, static_cast<uint32_t>(offset), rs, 0b001, rd, 0b0000111);
415  }
416  void Assembler::FLT_H(GPR rd, FPR rs1, FPR rs2) noexcept {
417      EmitRType(m_buffer, 0b1010010, rs2, rs1, 0b001, rd, 0b1010011);
418  }
419  void Assembler::FMADD_H(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
420      EmitR4Type(m_buffer, rs3, 0b10, rs2, rs1, rmode, rd, 0b1000011);
421  }
422  void Assembler::FMAX_H(FPR rd, FPR rs1, FPR rs2) noexcept {
423      EmitRType(m_buffer, 0b0010110, rs2, rs1, 0b001, rd, 0b1010011);
424  }
425  void Assembler::FMIN_H(FPR rd, FPR rs1, FPR rs2) noexcept {
426      EmitRType(m_buffer, 0b0010110, rs2, rs1, 0b000, rd, 0b1010011);
427  }
428  void Assembler::FMSUB_H(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
429      EmitR4Type(m_buffer, rs3, 0b10, rs2, rs1, rmode, rd, 0b1000111);
430  }
431  void Assembler::FMUL_H(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
432      EmitRType(m_buffer, 0b0001010, rs2, rs1, rmode, rd, 0b1010011);
433  }
434  void Assembler::FMV_H_X(FPR rd, GPR rs1) noexcept {
435      EmitRType(m_buffer, 0b1111010, f0, rs1, 0b000, rd, 0b1010011);
436  }
437  void Assembler::FMV_X_H(GPR rd, FPR rs1) noexcept {
438      EmitRType(m_buffer, 0b1110010, f0, rs1, 0b000, rd, 0b1010011);
439  }
440  void Assembler::FNMADD_H(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
441      EmitR4Type(m_buffer, rs3, 0b10, rs2, rs1, rmode, rd, 0b1001111);
442  }
443  void Assembler::FNMSUB_H(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
444      EmitR4Type(m_buffer, rs3, 0b10, rs2, rs1, rmode, rd, 0b1001011);
445  }
446  void Assembler::FSGNJ_H(FPR rd, FPR rs1, FPR rs2) noexcept {
447      EmitRType(m_buffer, 0b0010010, rs2, rs1, 0b000, rd, 0b1010011);
448  }
449  void Assembler::FSGNJN_H(FPR rd, FPR rs1, FPR rs2) noexcept {
450      EmitRType(m_buffer, 0b0010010, rs2, rs1, 0b001, rd, 0b1010011);
451  }
452  void Assembler::FSGNJX_H(FPR rd, FPR rs1, FPR rs2) noexcept {
453      EmitRType(m_buffer, 0b0010010, rs2, rs1, 0b010, rd, 0b1010011);
454  }
455  void Assembler::FSH(FPR rs2, int32_t offset, GPR rs1) noexcept {
456      BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
457      EmitSType(m_buffer, static_cast<uint32_t>(offset), rs2, rs1, 0b001, 0b0100111);
458  }
459  void Assembler::FSQRT_H(FPR rd, FPR rs1, RMode rmode) noexcept {
460      EmitRType(m_buffer, 0b0101110, f0, rs1, rmode, rd, 0b1010011);
461  }
462  void Assembler::FSUB_H(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
463      EmitRType(m_buffer, 0b0000110, rs2, rs1, rmode, rd, 0b1010011);
464  }
465  
466  // RV64Zfh Extension Instructions
467  
468  void Assembler::FCVT_L_H(GPR rd, FPR rs1, RMode rmode) noexcept {
469      EmitRType(m_buffer, 0b1100010, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
470  }
471  void Assembler::FCVT_LU_H(GPR rd, FPR rs1, RMode rmode) noexcept {
472      EmitRType(m_buffer, 0b1100010, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
473  }
474  void Assembler::FCVT_H_L(FPR rd, GPR rs1, RMode rmode) noexcept {
475      EmitRType(m_buffer, 0b1101010, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
476  }
477  void Assembler::FCVT_H_LU(FPR rd, GPR rs1, RMode rmode) noexcept {
478      EmitRType(m_buffer, 0b1101010, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
479  }
480  
481  // Zfa Extension Instructions
482  
483  static void FLIImpl(CodeBuffer& buffer, uint32_t funct7, FPR rd, double value) noexcept {
484      static constexpr std::array fli_table{
485          0xBFF0000000000000ULL, // -1.0
486          0x0010000000000000ULL, // Minimum positive normal
487          0x3EF0000000000000ULL, // 1.0 * 2^-16
488          0x3F00000000000000ULL, // 1.0 * 2^-15
489          0x3F70000000000000ULL, // 1.0 * 2^-8
490          0x3F80000000000000ULL, // 1.0 * 2^-7
491          0x3FB0000000000000ULL, // 1.0 * 2^-4
492          0x3FC0000000000000ULL, // 1.0 * 2^-3
493          0x3FD0000000000000ULL, // 0.25
494          0x3FD4000000000000ULL, // 0.3125
495          0x3FD8000000000000ULL, // 0.375
496          0x3FDC000000000000ULL, // 0.4375
497          0x3FE0000000000000ULL, // 0.5
498          0x3FE4000000000000ULL, // 0.625
499          0x3FE8000000000000ULL, // 0.75
500          0x3FEC000000000000ULL, // 0.875
501          0x3FF0000000000000ULL, // 1.0
502          0x3FF4000000000000ULL, // 1.25
503          0x3FF8000000000000ULL, // 1.5
504          0x3FFC000000000000ULL, // 1.75
505          0x4000000000000000ULL, // 2.0
506          0x4004000000000000ULL, // 2.5
507          0x4008000000000000ULL, // 3
508          0x4010000000000000ULL, // 4
509          0x4020000000000000ULL, // 8
510          0x4030000000000000ULL, // 16
511          0x4060000000000000ULL, // 2^7
512          0x4070000000000000ULL, // 2^8
513          0x40E0000000000000ULL, // 2^15
514          0x40F0000000000000ULL, // 2^16
515          0x7FF0000000000000ULL, // +inf
516          0x7FF8000000000000ULL, // Canonical NaN
517      };
518  
519      uint64_t ivalue{};
520      std::memcpy(&ivalue, &value, sizeof(uint64_t));
521  
522      const auto iter = std::find_if(fli_table.cbegin(), fli_table.cend(), [ivalue](uint64_t entry) {
523          return entry == ivalue;
524      });
525      BISCUIT_ASSERT(iter != fli_table.cend());
526  
527      const auto index = static_cast<uint32_t>(std::distance(fli_table.cbegin(), iter));
528      EmitRType(buffer, funct7, f1, GPR{index}, 0b000, rd, 0b1010011);
529  }
530  
531  void Assembler::FLI_D(FPR rd, double value) noexcept {
532      FLIImpl(m_buffer, 0b1111001, rd, value);
533  }
534  void Assembler::FLI_H(FPR rd, double value) noexcept {
535      FLIImpl(m_buffer, 0b1111010, rd, value);
536  }
537  void Assembler::FLI_S(FPR rd, double value) noexcept {
538      FLIImpl(m_buffer, 0b1111000, rd, value);
539  }
540  
541  void Assembler::FMINM_D(FPR rd, FPR rs1, FPR rs2) noexcept {
542      EmitRType(m_buffer, 0b0010101, rs2, rs1, 0b010, rd, 0b1010011);
543  }
544  void Assembler::FMINM_H(FPR rd, FPR rs1, FPR rs2) noexcept {
545      EmitRType(m_buffer, 0b0010110, rs2, rs1, 0b010, rd, 0b1010011);
546  }
547  void Assembler::FMINM_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
548      EmitRType(m_buffer, 0b0010111, rs2, rs1, 0b010, rd, 0b1010011);
549  }
550  void Assembler::FMINM_S(FPR rd, FPR rs1, FPR rs2) noexcept {
551      EmitRType(m_buffer, 0b0010100, rs2, rs1, 0b010, rd, 0b1010011);
552  }
553  
554  void Assembler::FMAXM_D(FPR rd, FPR rs1, FPR rs2) noexcept {
555      EmitRType(m_buffer, 0b0010101, rs2, rs1, 0b011, rd, 0b1010011);
556  }
557  void Assembler::FMAXM_H(FPR rd, FPR rs1, FPR rs2) noexcept {
558      EmitRType(m_buffer, 0b0010110, rs2, rs1, 0b011, rd, 0b1010011);
559  }
560  void Assembler::FMAXM_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
561      EmitRType(m_buffer, 0b0010111, rs2, rs1, 0b011, rd, 0b1010011);
562  }
563  void Assembler::FMAXM_S(FPR rd, FPR rs1, FPR rs2) noexcept {
564      EmitRType(m_buffer, 0b0010100, rs2, rs1, 0b011, rd, 0b1010011);
565  }
566  
567  void Assembler::FROUND_D(FPR rd, FPR rs1, RMode rmode) noexcept {
568      EmitRType(m_buffer, 0b0100001, f4, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
569  }
570  void Assembler::FROUND_H(FPR rd, FPR rs1, RMode rmode) noexcept {
571      EmitRType(m_buffer, 0b0100010, f4, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
572  }
573  void Assembler::FROUND_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
574      EmitRType(m_buffer, 0b0100011, f4, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
575  }
576  void Assembler::FROUND_S(FPR rd, FPR rs1, RMode rmode) noexcept {
577      EmitRType(m_buffer, 0b0100000, f4, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
578  }
579  
580  void Assembler::FROUNDNX_D(FPR rd, FPR rs1, RMode rmode) noexcept {
581      EmitRType(m_buffer, 0b0100001, f5, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
582  }
583  void Assembler::FROUNDNX_H(FPR rd, FPR rs1, RMode rmode) noexcept {
584      EmitRType(m_buffer, 0b0100010, f5, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
585  }
586  void Assembler::FROUNDNX_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
587      EmitRType(m_buffer, 0b0100011, f5, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
588  }
589  void Assembler::FROUNDNX_S(FPR rd, FPR rs1, RMode rmode) noexcept {
590      EmitRType(m_buffer, 0b0100000, f5, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
591  }
592  
593  void Assembler::FCVTMOD_W_D(GPR rd, FPR rs1) noexcept {
594      EmitRType(m_buffer, 0b1100001, f8, rs1, static_cast<uint32_t>(RMode::RTZ), rd, 0b1010011);
595  }
596  
597  void Assembler::FMVH_X_D(GPR rd, FPR rs1) noexcept {
598      EmitRType(m_buffer, 0b1110001, f1, rs1, 0b000, rd, 0b1010011);
599  }
600  void Assembler::FMVH_X_Q(GPR rd, FPR rs1) noexcept {
601      EmitRType(m_buffer, 0b1110011, f1, rs1, 0b000, rd, 0b1010011);
602  }
603  void Assembler::FMVP_D_X(FPR rd, GPR rs1, GPR rs2) noexcept {
604      EmitRType(m_buffer, 0b1011001, rs2, rs1, 0b000, rd, 0b1010011);
605  }
606  void Assembler::FMVP_Q_X(FPR rd, GPR rs1, GPR rs2) noexcept {
607      EmitRType(m_buffer, 0b1011011, rs2, rs1, 0b000, rd, 0b1010011);
608  }
609  
610  void Assembler::FLEQ_D(GPR rd, FPR rs1, FPR rs2) noexcept {
611      EmitRType(m_buffer, 0b1010001, rs2, rs1, 0b100, rd, 0b1010011);
612  }
613  void Assembler::FLTQ_D(GPR rd, FPR rs1, FPR rs2) noexcept {
614      EmitRType(m_buffer, 0b1010001, rs2, rs1, 0b101, rd, 0b1010011);
615  }
616  
617  void Assembler::FLEQ_H(GPR rd, FPR rs1, FPR rs2) noexcept {
618      EmitRType(m_buffer, 0b1010010, rs2, rs1, 0b100, rd, 0b1010011);
619  }
620  void Assembler::FLTQ_H(GPR rd, FPR rs1, FPR rs2) noexcept {
621      EmitRType(m_buffer, 0b1010010, rs2, rs1, 0b101, rd, 0b1010011);
622  }
623  
624  void Assembler::FLEQ_Q(GPR rd, FPR rs1, FPR rs2) noexcept {
625      EmitRType(m_buffer, 0b1010011, rs2, rs1, 0b100, rd, 0b1010011);
626  }
627  void Assembler::FLTQ_Q(GPR rd, FPR rs1, FPR rs2) noexcept {
628      EmitRType(m_buffer, 0b1010011, rs2, rs1, 0b101, rd, 0b1010011);
629  }
630  
631  void Assembler::FLEQ_S(GPR rd, FPR rs1, FPR rs2) noexcept {
632      EmitRType(m_buffer, 0b1010000, rs2, rs1, 0b100, rd, 0b1010011);
633  }
634  void Assembler::FLTQ_S(GPR rd, FPR rs1, FPR rs2) noexcept {
635      EmitRType(m_buffer, 0b1010000, rs2, rs1, 0b101, rd, 0b1010011);
636  }
637  
638  // Zfbfmin, Zvfbfmin, Zvfbfwma Extension Instructions
639  
640  void Assembler::FCVT_BF16_S(FPR rd, FPR rs, RMode rmode) noexcept {
641      EmitRType(m_buffer, 0b0100010, f8, rs, static_cast<uint32_t>(rmode), rd, 0b1010011);
642  }
643  
644  void Assembler::FCVT_S_BF16(FPR rd, FPR rs, RMode rmode) noexcept {
645      EmitRType(m_buffer, 0b0100000, f6, rs, static_cast<uint32_t>(rmode), rd, 0b1010011);
646  }
647  
648  } // namespace biscuit