1 #include "sv_insn_redirect.h"
10 void (sv_proc_t::WRITE_FRD
)(sv_float32_t value
)
12 reg_t reg
= _insn
->rd().reg
;
13 uint8_t dest_elwidth
= _insn
->reg_elwidth(reg
, false);
14 fprintf(stderr
, "WRITE_FRD rd %ld ew %d sv_float32_t %x\n",
15 reg
, dest_elwidth
, ((float32_t
)value
).v
);
20 case 1: throw trap_illegal_instruction(0); // XXX for now
21 // 16-bit data, up-convert to f32
24 float16_t x16
= ::f32_to_f16((float32_t
)value
);
25 fprintf(stderr
, "f32-to-f16\n");
32 //float32_t x32 = ::f128_to_f32((float32_t)value);
33 //v = ::f32_to_f128(x32);
42 sv_freg_t vf
= sv_freg_t(v
, xlen
, value
.get_elwidth());
43 DO_WRITE_FREG( _insn
->rd(), vf
);
46 void (sv_proc_t::WRITE_FRD
)(sv_float64_t value
)
48 reg_t reg
= _insn
->rd().reg
;
49 fprintf(stderr
, "WRITE_FRD sv_float64_t %g\n",
50 (double)((float64_t
)value
).v
);
51 uint8_t dest_elwidth
= _insn
->reg_elwidth(reg
, false);
56 case 1: throw trap_illegal_instruction(0); // XXX for now
57 // 16-bit data, up-convert to f32
60 float16_t x16
= ::f64_to_f16((float64_t
)value
);
66 float32_t x32
= ::f64_to_f32((float64_t
)value
);
76 sv_freg_t vf
= sv_freg_t(v
, xlen
, value
.get_elwidth());
77 DO_WRITE_FREG( _insn
->rd(), vf
);
80 void (sv_proc_t::WRITE_FRD
)(sv_float128_t value
)
82 fprintf(stderr
, "WRITE_FRD sv_float128_t %g\n",
83 (double)((float128_t
)value
).v
[0]);
84 sv_freg_t v
= sv_freg_t(freg(((float128_t
)value
)), xlen
, value
.get_elwidth());
85 DO_WRITE_FREG( _insn
->rd(), v
);
88 void (sv_proc_t::WRITE_FRD
)(sv_freg_t value
)
90 fprintf(stderr
, "WRITE_FRD fsv_reg_t %lx\n", ((freg_t
)value
).v
[0]);
91 DO_WRITE_FREG( _insn
->rd(), freg(value
) );
94 void (sv_proc_t::WRITE_RVC_FRS2S
)(sv_float32_t value
)
96 WRITE_FREG(_insn
->rvc_rs2s(), freg(value
));
99 void (sv_proc_t::WRITE_RVC_FRS2S
)(sv_float64_t
const& value
)
101 WRITE_FREG(_insn
->rvc_rs2s(), freg(value
));
104 void (sv_proc_t::WRITE_RVC_RS1S
)(sv_reg_t
const& value
)
106 WRITE_REG(_insn
->rvc_rs1s(), value
);
109 void (sv_proc_t::WRITE_RVC_RS2S
)(sv_reg_t
const& value
)
111 WRITE_REG(_insn
->rvc_rs2s(), value
);
114 void (sv_proc_t::WRITE_RD
)(sv_reg_t
const& value
)
116 WRITE_REG( _insn
->rd(), value
); // XXX TODO: replace properly
121 uint8_t b
[sizeof(freg_t
)*8];
124 unsigned int sv_proc_t::pred_remap(reg_t reg
, int bit
)
126 int ignore_subvl
= 0; // predication does not use subvl
127 reg_spec_t rs
= {reg
, &bit
, &ignore_subvl
};
128 return remap(rs
, true);
131 unsigned int sv_proc_t::remap(reg_spec_t
const& spec
, bool pred
)
133 unsigned int offs
= *spec
.offset
;
134 unsigned int subo
= *spec
.suboff
;
135 // this is where (after all the fuss, passing info around) the actual
136 // register offset is computed. if subvl is active, it's a multiplier
137 //fprintf(stderr, "remap %ld subvl %ld offs %ld subo %ld\n",
138 // spec.reg, p->get_state()->sv().subvl, offs, subo);
140 offs
= offs
* p
->get_state()->sv().subvl
+ subo
;
142 sv_shape_t
*shape
= p
->get_state()->get_shape(spec
.reg
, pred
);
146 // this table is pre-calculated by sv_shape_t::setup_map().
147 // changing the CSRs is the way to change the map.
148 // the map is still calculated even for the 1D case
149 // because it's a linear map
150 unsigned int res
= (unsigned int)shape
->map
[offs
] + shape
->offs
;
151 fprintf(stderr
, "remap %ld %d -> %d\n",
152 spec
.reg
, offs
, res
);
156 void (sv_proc_t::DO_WRITE_FREG
)(reg_spec_t
const& spec
, sv_freg_t
const& value
)
158 int regflen
= sizeof(freg_t
) * 8; // FLEN (not specified in spike)
159 int flen
= _insn
->dest_flen
;
160 reg_t reg
= spec
.reg
;
161 uint8_t dest_elwidth
= _insn
->reg_elwidth(reg
, false);
163 //if (_insn->sv_check_reg(reg, false)) {
164 bitwidth
= get_bitwidth(dest_elwidth
, flen
);
166 // bitwidth = regflen;
169 fprintf(stderr
, "DO_WRITE_FRD rd %ld ew %d data %lx %lx\n",
170 reg
, dest_elwidth
, ((freg_t
)value
).v
[0], ((freg_t
)value
).v
[1]);
171 unsigned int shift
= 0;
172 unsigned int offs
= 0;
173 if (spec
.offset
!= NULL
) {
174 unsigned int nbytes
= flen
/ bitwidth
;
176 shift
= offs
% nbytes
;
181 fprintf(stderr
, "writefreg spec %ld bitwidth %d offs %d shift %d\n",
182 reg
, bitwidth
, offs
, shift
);
184 if (((int)reg
) >= SV_NFPR
) {
185 throw trap_illegal_instruction(0);
188 if (flen
!= bitwidth
)
193 fd
.f
= _insn
->p
->get_state()->FPR
[reg
];
194 int sblen
= shift
*bitwidth
/8;
195 for (int i
= 0; i
< ((int)bitwidth
/8); i
++) {
196 if (i
< (bitwidth
/8)) {
197 fd
.b
[i
+sblen
] = fs
.b
[i
];
201 for (int i
= (bitwidth
/8); i
< ((int)flen
/8); i
++) {
206 fprintf(stderr
, "writefreg %s %ld bitwidth %d offs %d shift %d " \
207 " %lx:%lx %lx:%lx\n",
208 report
, spec
.reg
, bitwidth
, offs
, shift
,
209 fs
.f
.v
[0], fs
.f
.v
[1],
210 fd
.f
.v
[0], fd
.f
.v
[1]);
216 STATE
.FPR
.write(reg
, fd
.f
);
220 void (sv_proc_t::WRITE_REG
)(reg_spec_t
const& spec
, sv_reg_t
const& value
)
222 uint64_t wval
= (uint64_t)value
;
223 reg_t reg
= spec
.reg
;
224 int bitwidth
= get_bitwidth(_insn
->reg_elwidth(reg
, true), xlen
);
225 unsigned int shift
= 0;
226 unsigned int offs
= 0;
227 if (spec
.offset
!= NULL
) {
228 unsigned int nbytes
= xlen
/ bitwidth
;
230 shift
= offs
% nbytes
;
235 fprintf(stderr
, "writereg spec %ld %lx bitwidth %d offs %d shift %d\n",
236 reg
, wval
, bitwidth
, offs
, shift
);
238 if (((int)reg
) >= SV_NFPR
) {
239 throw trap_illegal_instruction(0);
241 if (xlen
!= bitwidth
)
244 uint64_t data
= _insn
->p
->get_state()->XPR
[reg
];
245 uint64_t mask
= ((1UL<<bitwidth
)-1UL) << (shift
*bitwidth
);
246 wval
= (uint64_t)(wval
<< (shift
*bitwidth
)); // element within reg-block
248 uint64_t ndata
= data
;
250 ndata
= data
& (uint64_t)(~mask
); // masks off right bits
253 if (_insn
->signextended
) {
254 wval
= sext_bwid(wval
, bitwidth
);
257 wval
= zext_bwid(wval
, bitwidth
);
261 // XXX BAD HACK, keep an eye on this
262 // when xlen = 32, spike appears to expect all 32-bit
263 // results to be sign-extended in the 64-bit register.
264 // this MAY not be properly spec-compliant when xlen
265 // is changed at runtime.
266 if (xlen
== 32 && bitwidth
!= 32) {
267 wval
= sext_bwid(wval
, 32);
269 fprintf(stderr
, "writereg %s %ld bitwidth %d offs %d shift %d %lx " \
271 report
, spec
.reg
, bitwidth
, offs
, shift
, data
,
274 STATE
.XPR
.write(reg
, wval
);
277 freg_t (sv_proc_t::READ_FREG
)(reg_spec_t
const& spec
)
279 int regflen
= sizeof(freg_t
) * 8; // FLEN (not specified in spike)
280 int flen
= _insn
->src_flen
;
281 reg_t reg
= spec
.reg
;
282 uint8_t elwidth
= _insn
->reg_elwidth(reg
, false);
283 int bitwidth
= get_bitwidth(elwidth
, flen
);
286 if (spec
.offset
!= NULL
) {
287 int nbytes
= flen
/ bitwidth
;
292 shift
= offs
% nbytes
;
298 if (((int)reg
) >= SV_NFPR
) {
299 throw trap_illegal_instruction(0);
302 fs
.f
= _insn
->p
->get_state()->FPR
[reg
];
303 fprintf(stderr
, "READ_FREG rd %ld offs %d ew %d bw %d fl %d data %lx %lx\n",
304 reg
, offs
, elwidth
, bitwidth
, flen
, fs
.f
.v
[0], fs
.f
.v
[1]);
306 if (regflen
!= bitwidth
)
308 // shuffle the data down by bytes (annoying but easier)
309 int sblen
= shift
*bitwidth
/8;
310 for (int i
= 0; i
< ((int)regflen
/8); i
++) {
311 if (i
< (bitwidth
/8)) {
312 fs
.b
[i
] = fs
.b
[i
+sblen
];
317 fprintf(stderr
, "readfreg %ld bitwidth %d offs %d " \
318 "shift %d %lx:%lx\n",
319 spec
.reg
, bitwidth
, offs
, shift
,
320 fs
.f
.v
[0], fs
.f
.v
[1]);
325 reg_t
sv_proc_t::READ_REG(reg_spec_t
const& spec
,
326 bool addr_mode
, size_t width
)
328 reg_t reg
= spec
.reg
;
329 int bitwidth
= get_bitwidth(_insn
->reg_elwidth(reg
, true), width
);
333 if (spec
.offset
!= NULL
) {
334 int nbytes
= width
/ bitwidth
;
338 origoffs
= remap(spec
);
339 shift
= origoffs
% nbytes
;
340 offs
= origoffs
/ nbytes
;
345 if (((int)reg
) >= SV_NFPR
) {
346 throw trap_illegal_instruction(0);
348 uint64_t data
= _insn
->p
->get_state()->XPR
[reg
];
349 uint64_t ndata
= data
;
352 // offset data to load by the number of BYTES not bits
354 ndata
= data
+ (bitwidth
* shift
/ 8);
356 ndata
= data
+ (bitwidth
* origoffs
/ 8);
358 fprintf(stderr
, "readreg ADDRmode %p %ld %ld bw %d offs (%d) %d " \
359 "shift %d %lx->%lx\n",
360 spec
.offset
, spec
.reg
, reg
, bitwidth
,
361 origoffs
, offs
, shift
, data
, ndata
);
365 if (((uint64_t)xlen
) != ((uint64_t)bitwidth
))
367 // gets element within the reg-block
368 ndata
= data
>> (shift
*bitwidth
);
369 ndata
&= ((1UL<<bitwidth
)-1UL); // masks off the right bits
371 fprintf(stderr
, "readreg %ld bitwidth %d offs %d " \
372 "shift %d %lx->%lx\n",
373 spec
.reg
, bitwidth
, offs
, shift
, data
, ndata
);
378 sv_reg_t
sv_proc_t::get_intreg(reg_spec_t
const&spec
)
380 uint64_t data
= READ_REG(spec
);
381 uint8_t bitwidth
= _insn
->src_bitwidth
;
382 return sv_reg_t(data
, xlen
, bitwidth
);
385 sv_freg_t
sv_proc_t::get_fpreg(reg_spec_t
const&spec
)
387 freg_t data
= READ_FREG(spec
);
388 //uint8_t bitwidth = _insn->src_bitwidth;
389 reg_t reg
= spec
.reg
;
390 uint8_t elwidth
= _insn
->reg_elwidth(reg
, false);
391 return sv_freg_t(data
, xlen
, elwidth
);
394 #define GET_REG(name) \
395 sv_reg_t sv_proc_t::get_##name() \
397 reg_spec_t reg = _insn->name (); \
398 return get_intreg(reg); \
409 sv_reg_t
sv_proc_t::get_rvc_sp()
411 return get_intreg({X_SP
, _insn
->get_sp_offs(), _insn
->get_sp_subo()});
414 #define GET_FPREG(name, getter) \
415 sv_freg_t sv_proc_t::get_##name() \
417 reg_spec_t reg = _insn->getter (); \
418 return get_fpreg(reg); \
424 GET_FPREG(rvc_frs2
, rvc_rs2
)
425 GET_FPREG(rvc_frs2s
, rvc_rs2s
)
427 sv_reg_t
sv_proc_t::get_shamt()
429 return sv_reg_t(_insn
->i_imm() & 0x3F); // XXX TODO: has to be elwidth'd
432 sv_reg_t
sv_proc_t::uint64_max()
434 return ((UINT64_C(18446744073709551615)));
437 sv_sreg_t (sv_proc_t::sext_xlen
)(sv_sreg_t
const& v
)
440 x
= (((sreg_t
)(x
) << (64-xlen
)) >> (64-xlen
));
444 sv_sreg_t (sv_proc_t::sext_xlen
)(sv_reg_t
const& v
)
447 x
= (((sreg_t
)(x
) << (64-xlen
)) >> (64-xlen
));
448 return sv_sreg_t((sreg_t
)x
);
451 sv_reg_t (sv_proc_t::zext_xlen
)(sv_reg_t
const& v
)
454 x
= (((reg_t
)(x
) << (64-xlen
)) >> (64-xlen
));
458 sv_sreg_t (sv_proc_t::sext32
)(sv_reg_t
const& v
)
461 x
= ((sreg_t
)(int32_t)(x
));
462 return sv_sreg_t((int64_t)x
, v
.get_xlen(), v
.get_elwidth());
465 sv_reg_t (sv_proc_t::zext32
)(sv_reg_t
const& v
)
468 x
= ((reg_t
)(uint32_t)(x
));
472 #define OP_PREP_FINISH( SLHSTYPE, SRHSTYPE, SRESTYPE, \
473 LHSTYPE, RHSTYPE, RESTYPE ) \
474 bool sv_proc_t::rv_int_op_prepare(SLHSTYPE const & lhs, SRHSTYPE const & rhs, \
475 LHSTYPE &vlhs, RHSTYPE &vrhs, \
478 bitwidth = _insn->src_bitwidth; \
479 if (bitwidth == 0) { \
482 if (bitwidth == xlen) { \
487 uint8_t lbitwidth = get_bitwidth(lhs.get_elwidth(), xlen); \
488 uint8_t rbitwidth = get_bitwidth(lhs.get_elwidth(), xlen); \
489 if (_insn->signextended) { \
490 vlhs = sext_bwid(lhs, lbitwidth); \
491 vrhs = sext_bwid(rhs, rbitwidth); \
493 vlhs = zext_bwid(lhs, lbitwidth); \
494 vrhs = zext_bwid(rhs, rbitwidth); \
498 SRESTYPE sv_proc_t::rv_int_op_finish(SLHSTYPE const & lhs, \
499 SRHSTYPE const & rhs, \
500 RESTYPE &result, uint8_t &bitwidth) \
502 if (_insn->signextended) { \
503 result = sext_bwid(result, bitwidth); \
505 result = zext_bwid(result, bitwidth); \
507 uint8_t reswidth = maxelwidth(lhs.get_elwidth(), rhs.get_elwidth()); \
508 fprintf(stderr, "result sext %d wid %d %lx\n", _insn->signextended, \
510 return SRESTYPE(result, xlen, reswidth); \
514 OP_PREP_FINISH(sv_reg_t
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t, uint64_t)
515 OP_PREP_FINISH(sv_sreg_t
, sv_reg_t
, sv_sreg_t
, int64_t, uint64_t, int64_t)
516 OP_PREP_FINISH(sv_sreg_t
, sv_sreg_t
, sv_sreg_t
, int64_t, int64_t, int64_t)
518 #define OP_RES_FN( fname, SLHSTYPE, SRHSTYPE, SRESTYPE, \
519 LHSTYPE, RHSTYPE, RESTYPE ) \
520 SRESTYPE sv_proc_t::rv##fname (SLHSTYPE const & lhs, SRHSTYPE const & rhs) \
522 uint8_t bitwidth = _insn->src_bitwidth; \
525 if (rv_int_op_prepare(lhs, rhs, vlhs, vrhs, bitwidth)) { \
526 RESTYPE result = lhs fname rhs; \
527 fprintf(stderr, "%s result %lx %lx %lx\n", \
528 xstr(fname), (LHSTYPE)lhs, (RHSTYPE)rhs, (RESTYPE)result); \
529 return SRESTYPE(result); \
531 RESTYPE result = vlhs fname vrhs; \
532 fprintf(stderr, "%s result %lx %lx %lx bw %d\n", \
533 xstr(fname), (LHSTYPE)lhs, (RHSTYPE)rhs, (RESTYPE)result, bitwidth); \
534 return rv_int_op_finish(lhs, rhs, result, bitwidth); \
546 OP_RES_FN ( _add
, sv_reg_t
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t, uint64_t )
547 OP_RES_FN ( _sub
, sv_reg_t
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t, uint64_t )
548 OP_RES_FN ( _and
, sv_reg_t
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t, uint64_t )
549 OP_RES_FN ( _or
, sv_reg_t
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t, uint64_t )
550 OP_RES_FN ( _xor
, sv_reg_t
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t, uint64_t )
551 OP_RES_FN ( _div
, sv_reg_t
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t, uint64_t )
552 OP_RES_FN ( _div
, sv_sreg_t
, sv_sreg_t
, sv_sreg_t
, int64_t, int64_t, int64_t )
553 OP_RES_FN ( _rem
, sv_reg_t
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t, uint64_t )
554 OP_RES_FN ( _rem
, sv_sreg_t
, sv_sreg_t
, sv_sreg_t
, int64_t, int64_t, int64_t )
555 OP_RES_FN ( _mul
, sv_reg_t
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t, uint64_t )
556 OP_RES_FN ( _mul
, sv_sreg_t
, sv_reg_t
, sv_sreg_t
, int64_t, uint64_t, int64_t )
557 OP_RES_FN ( _mul
, sv_sreg_t
, sv_sreg_t
, sv_sreg_t
, int64_t, int64_t, int64_t )
559 /* 32-bit mulh/mulhu/mulhsu */
561 // normally the result is shuffled down by 32 bits (elwidth==default)
562 // however with variable bitwidth we want the top elwidth bits,
563 // using the SOURCE registers to determine that width.
564 // specifically: truncation of the result due to a shorter
565 // destination elwidth is NOT our problem.
566 #define OP_MULH_FN( fname, SLHSTYPE, SRHSTYPE, SRESTYPE, \
567 LHSTYPE, RHSTYPE, RESTYPE ) \
568 SRESTYPE sv_proc_t::rv##fname (SLHSTYPE const & lhs, SRHSTYPE const & rhs) \
570 uint8_t bitwidth = _insn->src_bitwidth; \
573 if (rv_int_op_prepare(lhs, rhs, vlhs, vrhs, bitwidth)) { \
574 RESTYPE result = (lhs * rhs) >> 32; \
575 fprintf(stderr, "%s result %lx %lx %lx\n", \
576 xstr(fname), (LHSTYPE)lhs, (RHSTYPE)rhs, (RESTYPE)result); \
577 return SRESTYPE(result); \
579 uint8_t bw32 = std::min(bitwidth, (uint8_t)32); \
580 RESTYPE result = (vlhs * vrhs) >> bw32; \
581 result = zext_bwid(result, bw32); \
582 fprintf(stderr, "%s result %lx %lx %lx bw %d\n", \
583 xstr(fname), (LHSTYPE)lhs, (RHSTYPE)rhs, (RESTYPE)result, bitwidth); \
584 return rv_int_op_finish(lhs, rhs, result, bitwidth); \
587 OP_MULH_FN(_mulhu
, sv_reg_t
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t, uint64_t )
588 OP_MULH_FN(_mulhsu
, sv_sreg_t
, sv_reg_t
, sv_sreg_t
, int64_t, uint64_t, int64_t )
589 OP_MULH_FN(_mulh
, sv_sreg_t
, sv_sreg_t
, sv_sreg_t
, int64_t, int64_t, int64_t )
591 /* 64-bit mulh/mulhu/mulhsu */
592 /* here is slightly different from other macros, because if either
593 src register is 64-bit it's necessary to use the 64-bit mulhu
594 function. then, if the result is <64bit it's truncated.
595 only when both source registers are <= 32 bit can we use
598 #define OP_M64_FN( fname, SLHSTYPE, SRHSTYPE, SRESTYPE, \
599 LHSTYPE, RHSTYPE, RESTYPE ) \
600 SRESTYPE sv_proc_t::fname (SLHSTYPE const & lhs, SRHSTYPE const & rhs) \
602 uint8_t bitwidth = _insn->src_bitwidth; \
605 if (rv_int_op_prepare(lhs, rhs, vlhs, vrhs, bitwidth) || \
606 lhs.get_elwidth() == 0 || rhs.get_elwidth() == 0 ) { \
607 RESTYPE result = ::fname(vlhs, vrhs); \
608 fprintf(stderr, "%s result %lx %lx %lx\n", \
609 xstr(fname), (LHSTYPE)lhs, (RHSTYPE)rhs, (RESTYPE)result); \
610 return rv_int_op_finish(lhs, rhs, result, bitwidth); \
612 return rv_##fname(lhs, rhs); \
615 OP_M64_FN( mulhu
, sv_reg_t
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t, uint64_t )
616 OP_M64_FN( mulhsu
, sv_sreg_t
, sv_reg_t
, sv_sreg_t
, int64_t, uint64_t, int64_t )
617 OP_M64_FN( mulh
, sv_sreg_t
, sv_sreg_t
, sv_sreg_t
, int64_t, int64_t, int64_t )
619 #define OP_SHF_FN( fname, SLHSTYPE, SRHSTYPE, SRESTYPE, \
620 LHSTYPE, RHSTYPE, RESTYPE ) \
621 SRESTYPE sv_proc_t::rv##fname (SLHSTYPE const & lhs, SRHSTYPE const & rhs, \
622 unsigned int dflt_bitwidth) \
624 uint8_t bitwidth = _insn->src_bitwidth; \
627 if (rv_int_op_prepare(lhs, rhs, vlhs, vrhs, bitwidth)) { \
628 RESTYPE result = lhs fname rv_and(rhs, sv_reg_t(dflt_bitwidth-1U)); \
629 fprintf(stderr, "%s result %lx %lx %lx\n", \
630 xstr(fname), (LHSTYPE)lhs, (RHSTYPE)rhs, (RESTYPE)result); \
631 return SRESTYPE(result); \
633 RESTYPE result = vlhs fname (vrhs & (bitwidth-1)); \
634 fprintf(stderr, "%s result %lx %lx %lx bw %d\n", \
635 xstr(fname), (LHSTYPE)lhs, (RHSTYPE)rhs, (RESTYPE)result, bitwidth); \
636 return rv_int_op_finish(lhs, rhs, result, bitwidth); \
642 OP_SHF_FN ( _sl
, sv_reg_t
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t, uint64_t )
643 OP_SHF_FN ( _sr
, sv_reg_t
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t, uint64_t )
652 #define OP_BOOL_FN( fname, SLHSTYPE, SRHSTYPE, \
654 bool sv_proc_t::rv_##fname (SLHSTYPE const & lhs, SRHSTYPE const & rhs) \
656 uint8_t bitwidth = _insn->src_bitwidth; \
659 if (rv_int_op_prepare(lhs, rhs, vlhs, vrhs, bitwidth)) { \
660 bool result = lhs fname rhs; \
661 fprintf(stderr, "%s result %lx %lx %x\n", \
662 xstr(fname), (LHSTYPE)lhs, (RHSTYPE)rhs, result); \
665 bool result = vlhs fname vrhs; \
666 fprintf(stderr, "%s result %lx %lx %d bw %d\n", \
667 xstr(fname), (LHSTYPE)lhs, (RHSTYPE)rhs, result, bitwidth); \
671 OP_BOOL_FN( lt
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t )
672 OP_BOOL_FN( lt
, sv_sreg_t
, sv_sreg_t
, int64_t, int64_t )
673 OP_BOOL_FN( gt
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t )
674 OP_BOOL_FN( gt
, sv_sreg_t
, sv_sreg_t
, int64_t, int64_t )
675 OP_BOOL_FN( ge
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t )
676 OP_BOOL_FN( ge
, sv_sreg_t
, sv_sreg_t
, int64_t, int64_t )
677 OP_BOOL_FN( eq
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t )
678 OP_BOOL_FN( ne
, sv_reg_t
, sv_reg_t
, uint64_t, uint64_t )
682 sv_sreg_t
sv_proc_t::sv_reg_to_sreg(sv_reg_t
const& v
)
685 return sv_sreg_t(sreg_t(x
));
688 sv_reg_t
sv_proc_t::sv_reg_int32(sv_reg_t
const& v
)
690 int32_t x
= (int32_t)v
;
691 return sv_reg_t((uint64_t)x
);
694 sv_reg_t
sv_proc_t::sv_reg_uint32(sv_reg_t
const& v
)
696 uint32_t x
= (uint32_t)v
;
697 return sv_reg_t((uint64_t)x
);
702 sv_float32_t (sv_proc_t::f32
)(sv_freg_t x
)
704 freg_t v
= (freg_t
)x
;
705 switch (x
.get_elwidth())
708 case 1: throw trap_illegal_instruction(0); // XXX for now
709 // 16-bit data, up-convert to f32
712 sv_reg_t
x32(x
.to_uint32());
713 float16_t f_16
= f16(x
);
714 fprintf(stderr
, "f16-to-f32 %lx\n", (uint64_t)x32
);
715 return f16_to_f32(f_16
);
719 return sv_float32_t(::f32(x
.to_uint32()));
723 sv_float32_t value
= ::f32(v
);
724 fprintf(stderr
, "::f32 %lx %lx %x\n", v
.v
[0], v
.v
[1], ((float32_t
)value
).v
);
728 sv_float32_t (sv_proc_t::f32
)(sv_reg_t
const& v
)
731 fprintf(stderr
, "::f32 %lx\n", x
);
732 switch (v
.get_elwidth())
735 case 1: throw trap_illegal_instruction(0); // XXX for now
736 // 16-bit data, up-convert to f32
738 fprintf(stderr
, "f16-to-f32\n");
739 return f16_to_f32(f16(x
));
740 // 0 and 3 are 32-bit
746 sv_float64_t (sv_proc_t::f64
)(sv_freg_t x
)
748 switch (x
.get_elwidth())
751 case 1: throw trap_illegal_instruction(0); // XXX for now
752 // 16-bit data, up-convert to f32
755 sv_reg_t
x64(x
.to_uint64());
756 float16_t f_16
= f16(x
);
757 fprintf(stderr
, "f16-to-f64 %lx\n", (uint64_t)x64
);
758 return f16_to_f64(f_16
);
762 sv_reg_t
x64(x
.to_uint64());
763 float32_t f_32
= f32(x
);
764 fprintf(stderr
, "f32-to-f64 %lx\n", (uint64_t)x64
);
765 return f32_to_f64(f_32
);
772 sv_float64_t (sv_proc_t::f64
)(sv_reg_t
const& v
)
775 switch (v
.get_elwidth())
778 case 1: throw trap_illegal_instruction(0); // XXX for now
779 // 16-bit data, up-convert to f32
782 float16_t f_16
= f16(x
);
783 fprintf(stderr
, "f16-to-f64 %lx\n", x
);
784 return f16_to_f64(f_16
);
788 float32_t f_32
= f32(x
);
789 fprintf(stderr
, "f32-to-f64 %lx\n", x
);
790 return f32_to_f64(f_32
);
797 sv_float128_t
sv_proc_t::f128( sv_freg_t v
)
799 uint64_t x
= ((float128_t
)v
).v
[0];
800 switch (v
.get_elwidth())
803 case 1: throw trap_illegal_instruction(0); // XXX for now
804 // 16-bit data, up-convert to f32
807 float16_t f_16
= f16(v
);
808 fprintf(stderr
, "f16-to-f128 %lx\n", x
);
809 return f16_to_f128(f_16
);
813 float32_t f_32
= f32(v
);
814 fprintf(stderr
, "f32-to-f128 %lx\n", x
);
815 return f32_to_f128(f_32
);
824 sv_reg_t (sv_proc_t::f32_classify
)(sv_float32_t a
)
826 return sv_reg_t(::f32_classify(a
));
829 sv_reg_t (sv_proc_t::f64_classify
)(sv_float64_t a
)
831 return sv_reg_t(::f64_classify(a
));
834 sv_reg_t (sv_proc_t::f128_classify
)(sv_float128_t a
)
836 return sv_reg_t(::f128_classify(a
));
839 sv_float32_t (sv_proc_t::i32_to_f32
)( sv_reg_t
const& v
)
842 return ::i32_to_f32(x
);
845 sv_float64_t (sv_proc_t::ui32_to_f64
)( sv_reg_t
const& v
)
848 return ::ui32_to_f64(x
);
851 sv_float64_t (sv_proc_t::i32_to_f64
)( sv_reg_t
const& v
)
854 return ::i32_to_f64(x
);
857 sv_float32_t (sv_proc_t::ui32_to_f32
)( sv_reg_t
const& v
)
860 return ::ui32_to_f32(x
);
863 sv_float32_t (sv_proc_t::i64_to_f32
)( sv_reg_t
const& v
)
866 return ::i64_to_f32(x
);
869 sv_float32_t (sv_proc_t::ui64_to_f32
)( sv_reg_t
const& v
)
872 return ::ui64_to_f32(x
);
875 sv_float64_t (sv_proc_t::i64_to_f64
)( sv_reg_t
const& v
)
878 return ::i64_to_f64(x
);
881 sv_float64_t (sv_proc_t::ui64_to_f64
)( sv_reg_t
const& v
)
884 return ::ui64_to_f64(x
);
887 sv_float128_t (sv_proc_t::ui64_to_f128
)( sv_reg_t
const& v
)
890 return ::ui64_to_f128(x
);
893 sv_float128_t (sv_proc_t::i64_to_f128
)( sv_reg_t
const& v
)
896 return ::i64_to_f128(x
);
899 sv_float128_t (sv_proc_t::i32_to_f128
)( sv_reg_t
const& v
)
902 return ::i32_to_f128(x
);
905 sv_float128_t (sv_proc_t::ui32_to_f128
)( sv_reg_t
const& v
)
908 return ::ui32_to_f128(x
);
911 sv_reg_t (sv_proc_t::f32_to_ui32
)( sv_float32_t a
, uint_fast8_t roundingMode
,
914 return sv_reg_t(::f32_to_ui32(a
, roundingMode
, exact
));
917 sv_reg_t (sv_proc_t::f32_to_i32
)( sv_float32_t a
, uint_fast8_t roundingMode
,
920 return sv_reg_t(::f32_to_i32(a
, roundingMode
, exact
));
923 sv_reg_t (sv_proc_t::f32_to_i64
)( sv_float32_t a
, uint_fast8_t roundingMode
,
926 return sv_reg_t(::f32_to_i64(a
, roundingMode
, exact
));
929 sv_reg_t (sv_proc_t::f32_to_ui64
)( sv_float32_t a
, uint_fast8_t roundingMode
,
932 return sv_reg_t(::f32_to_ui64(a
, roundingMode
, exact
));
935 sv_reg_t (sv_proc_t::f64_to_ui32
)( sv_float64_t a
, uint_fast8_t roundingMode
,
938 return sv_reg_t(::f64_to_ui32(a
, roundingMode
, exact
));
941 sv_reg_t (sv_proc_t::f64_to_i32
)( sv_float64_t a
, uint_fast8_t roundingMode
,
944 return sv_reg_t(::f64_to_i32(a
, roundingMode
, exact
));
947 sv_reg_t (sv_proc_t::f64_to_i64
)( sv_float64_t a
, uint_fast8_t roundingMode
,
950 return sv_reg_t(::f64_to_i64(a
, roundingMode
, exact
));
953 sv_reg_t (sv_proc_t::f64_to_ui64
)( sv_float64_t a
, uint_fast8_t roundingMode
,
956 return sv_reg_t(::f64_to_ui64(a
, roundingMode
, exact
));
959 sv_reg_t (sv_proc_t::f128_to_ui64
)( sv_float128_t a
, uint_fast8_t roundingMode
,
962 return sv_reg_t(::f128_to_ui64(a
, roundingMode
, exact
));
965 sv_reg_t (sv_proc_t::f128_to_ui32
)( sv_float128_t a
, uint_fast8_t roundingMode
,
968 return sv_reg_t(::f128_to_ui32(a
, roundingMode
, exact
));
971 sv_reg_t (sv_proc_t::f128_to_i32
)( sv_float128_t a
, uint_fast8_t roundingMode
,
974 return sv_reg_t(::f128_to_i32(a
, roundingMode
, exact
));
977 sv_reg_t (sv_proc_t::f128_to_i64
)( sv_float128_t a
, uint_fast8_t roundingMode
,
980 return sv_reg_t(::f128_to_i64(a
, roundingMode
, exact
));
985 sv_float64_t (sv_proc_t::f64_add
)( sv_float64_t a
, sv_float64_t b
)
987 return ::f64_add(a
, b
);
990 sv_float64_t (sv_proc_t::f64_sub
)( sv_float64_t a
, sv_float64_t b
)
992 return ::f64_sub(a
, b
);
995 sv_float64_t (sv_proc_t::f64_mul
)( sv_float64_t a
, sv_float64_t b
)
997 return ::f64_mul(a
, b
);
1000 sv_float64_t (sv_proc_t::f64_mulAdd
)( sv_float64_t a
, sv_float64_t b
, sv_float64_t c
)
1002 return ::f64_mulAdd(a
, b
, c
);
1005 sv_float64_t (sv_proc_t::f64_div
)( sv_float64_t a
, sv_float64_t b
)
1007 return ::f64_div(a
, b
);
1010 sv_float64_t (sv_proc_t::f64_rem
)( sv_float64_t a
, sv_float64_t b
)
1012 return ::f64_rem(a
, b
);
1015 sv_float64_t (sv_proc_t::f64_sqrt
)( sv_float64_t a
)
1017 return ::f64_sqrt(a
);
1020 bool (sv_proc_t::f64_eq
)( sv_float64_t a
, sv_float64_t b
)
1022 return ::f64_eq(a
, b
);
1025 bool (sv_proc_t::f64_le
)( sv_float64_t a
, sv_float64_t b
)
1027 return ::f64_le(a
, b
);
1030 bool (sv_proc_t::f64_lt
)( sv_float64_t a
, sv_float64_t b
)
1032 return ::f64_lt(a
, b
);
1035 bool (sv_proc_t::f64_eq_signaling
)( sv_float64_t a
, sv_float64_t b
)
1037 return ::f64_eq_signaling(a
, b
);
1040 bool (sv_proc_t::f64_le_quiet
)( sv_float64_t a
, sv_float64_t b
)
1042 return ::f64_le_quiet(a
, b
);
1045 bool (sv_proc_t::f64_lt_quiet
)( sv_float64_t a
, sv_float64_t b
)
1047 return ::f64_lt_quiet(a
, b
);
1053 sv_float32_t (sv_proc_t::f32_add
)( sv_float32_t a
, sv_float32_t b
)
1055 reg_t reg
= _insn
->rd().reg
;
1056 uint8_t dest_elwidth
= _insn
->reg_elwidth(reg
, false);
1057 //uint8_t reswidth = maxelwidth(a.get_elwidth(), b.get_elwidth());
1058 //return sv_float32_t(::f32_add(a, b), xlen, reswidth);
1059 sv_float32_t value
= ::f32_add(a
, b
);
1060 fprintf(stderr
, "f32_add a %x b %x sv_float32_t %x\n",
1061 ((float32_t
)a
).v
, ((float32_t
)b
).v
, ((float32_t
)value
).v
);
1065 sv_float32_t (sv_proc_t::f32_sub
)( sv_float32_t a
, sv_float32_t b
)
1067 return ::f32_sub(a
, b
);
1070 sv_float32_t (sv_proc_t::f32_mul
)( sv_float32_t a
, sv_float32_t b
)
1072 return ::f32_mul(a
, b
);
1075 sv_float32_t (sv_proc_t::f32_mulAdd
)( sv_float32_t a
, sv_float32_t b
, sv_float32_t c
)
1077 return ::f32_mulAdd(a
, b
, c
);
1080 sv_float32_t (sv_proc_t::f32_div
)( sv_float32_t a
, sv_float32_t b
)
1082 return ::f32_div(a
, b
);
1085 sv_float32_t (sv_proc_t::f32_rem
)( sv_float32_t a
, sv_float32_t b
)
1087 return ::f32_rem(a
, b
);
1090 sv_float32_t (sv_proc_t::f32_sqrt
)( sv_float32_t a
)
1092 return ::f32_sqrt(a
);
1095 bool (sv_proc_t::f32_eq
)( sv_float32_t a
, sv_float32_t b
)
1097 return ::f32_eq(a
, b
);
1100 bool (sv_proc_t::f32_le
)( sv_float32_t a
, sv_float32_t b
)
1102 return ::f32_le(a
, b
);
1105 bool (sv_proc_t::f32_lt
)( sv_float32_t a
, sv_float32_t b
)
1107 return ::f32_lt(a
, b
);
1110 bool (sv_proc_t::f32_eq_signaling
)( sv_float32_t a
, sv_float32_t b
)
1112 return ::f32_eq_signaling(a
, b
);
1115 bool (sv_proc_t::f32_le_quiet
)( sv_float32_t a
, sv_float32_t b
)
1117 return ::f32_le_quiet(a
, b
);
1120 bool (sv_proc_t::f32_lt_quiet
)( sv_float32_t a
, sv_float32_t b
)
1122 return ::f32_lt_quiet(a
, b
);
1128 sv_float128_t (sv_proc_t::f128_add
)( sv_float128_t a
, sv_float128_t b
)
1130 return ::f128_add(a
, b
);
1133 sv_float128_t (sv_proc_t::f128_sub
)( sv_float128_t a
, sv_float128_t b
)
1135 return ::f128_sub(a
, b
);
1138 sv_float128_t (sv_proc_t::f128_mul
)( sv_float128_t a
, sv_float128_t b
)
1140 return ::f128_mul(a
, b
);
1143 sv_float128_t (sv_proc_t::f128_mulAdd
)( sv_float128_t a
, sv_float128_t b
, sv_float128_t c
)
1145 return ::f128_mulAdd(a
, b
, c
);
1148 sv_float128_t (sv_proc_t::f128_div
)( sv_float128_t a
, sv_float128_t b
)
1150 return ::f128_div(a
, b
);
1153 sv_float128_t (sv_proc_t::f128_rem
)( sv_float128_t a
, sv_float128_t b
)
1155 return ::f128_rem(a
, b
);
1158 sv_float128_t (sv_proc_t::f128_sqrt
)( sv_float128_t a
)
1160 return ::f128_sqrt(a
);
1163 bool (sv_proc_t::f128_eq
)( sv_float128_t a
, sv_float128_t b
)
1165 return ::f128_eq(a
, b
);
1168 bool (sv_proc_t::f128_le
)( sv_float128_t a
, sv_float128_t b
)
1170 return ::f128_le(a
, b
);
1173 bool (sv_proc_t::f128_lt
)( sv_float128_t a
, sv_float128_t b
)
1175 return ::f128_lt(a
, b
);
1178 bool (sv_proc_t::f128_eq_signaling
)( sv_float128_t a
, sv_float128_t b
)
1180 return ::f128_eq_signaling(a
, b
);
1183 bool (sv_proc_t::f128_le_quiet
)( sv_float128_t a
, sv_float128_t b
)
1185 return ::f128_le_quiet(a
, b
);
1188 bool (sv_proc_t::f128_lt_quiet
)( sv_float128_t a
, sv_float128_t b
)
1190 return ::f128_lt_quiet(a
, b
);
1193 sv_freg_t
sv_proc_t::fsgnj128(sv_freg_t a
, sv_freg_t b
, bool n
, bool x
)
1195 return sv_freg_t(::fsgnj128(a
, b
, n
, x
), a
.get_xlen(), a
.get_elwidth());
1198 sv_float128_t
sv_proc_t::f32_to_f128( sv_float32_t a
)
1200 return ::f32_to_f128(a
);
1203 sv_float128_t
sv_proc_t::f64_to_f128( sv_float64_t a
)
1205 return ::f64_to_f128(a
);
1210 sv_reg_t
sv_proc_t::mmu_load(reg_spec_t
const& spec
, sv_reg_t
const& offs
,
1211 size_t width
, bool ext
)
1213 // okaay, so a different "mode" applies, here: addr_mode.
1214 // addr_mode doesn't truncate the register to elwidth-specified
1215 // bitsize, it adds a modulo-offset based on the current VL loop index
1216 reg_t reg
= READ_REG(spec
, true, width
);
1217 sv_reg_t addr
= sv_reg_t((uint64_t)reg
+ (int64_t)offs
);
1220 // now that the address has been moved on by the modulo-offset,
1221 // get only an elwidth-sized element (if not "default")
1222 uint8_t rwidth
= _insn
->reg_elwidth(spec
.reg
, true);
1223 width
= get_bitwidth(rwidth
, width
);
1224 fprintf(stderr
, "mmu_load wid %ld reg %lx offs %lx\n",
1225 width
, (uint64_t)reg
, (int64_t)offs
);
1229 if (ext
) v
= p
->get_mmu()->load_uint8(addr
);
1230 else v
= p
->get_mmu()->load_int8(addr
);
1233 if (ext
) v
= p
->get_mmu()->load_uint16(addr
);
1234 else v
= p
->get_mmu()->load_int16(addr
);
1237 if (ext
) v
= p
->get_mmu()->load_uint32(addr
);
1238 else v
= p
->get_mmu()->load_int32(addr
);
1241 if (ext
) v
= p
->get_mmu()->load_uint64(addr
);
1242 else v
= p
->get_mmu()->load_int64(addr
);
1245 fprintf(stderr
, "mmu_load wid %ld reg %lx offs %lx loaded %lx\n",
1246 width
, (uint64_t)reg
, (int64_t)offs
, (uint64_t)v
);
1247 v
.set_elwidth(rwidth
);
1252 void sv_proc_t::mmu_store(reg_spec_t
const& spec
, sv_reg_t
const& offs
,
1253 size_t width
, reg_t val
)
1255 // different "mode" applies, here: addr_mode.
1256 reg_t reg
= READ_REG(spec
, true, width
);
1257 sv_reg_t addr
= sv_reg_t((uint64_t)reg
+ (int64_t)offs
);
1259 // now that the address has been moved on by the modulo-offset,
1260 // get only an elwidth-sized element (if not "default")
1261 width
= get_bitwidth(_insn
->reg_elwidth(spec
.reg
, true), width
);
1262 fprintf(stderr
, "mmu_store wid %ld addr %lx offs %lx stored %lx\n",
1263 width
, (uint64_t)reg
, (int64_t)offs
, (uint64_t)val
);
1267 p
->get_mmu()->store_uint8(addr
, val
);
1270 p
->get_mmu()->store_uint16(addr
, val
);
1273 p
->get_mmu()->store_uint32(addr
, val
);
1276 p
->get_mmu()->store_uint64(addr
, val
);
1283 sv_reg_t
sv_proc_t::to_uint64(sv_freg_t
const& reg
)
1285 return sv_reg_t(reg
.to_uint64());
1288 sv_reg_t
sv_proc_t::to_uint32(sv_freg_t
const& reg
)
1290 switch (reg
.get_elwidth())
1293 case 1: throw trap_illegal_instruction(0); // XXX for now
1294 // 16-bit data, up-convert to f32
1297 float32_t x32
= ::f32(reg
.to_uint32());
1298 return sv_reg_t(f32_to_f16(x32
).v
, xlen
, reg
.get_elwidth());
1300 // 0 and 3 are 32-bit
1303 return sv_reg_t(reg
.to_uint32(), xlen
, reg
.get_elwidth());
1306 sv_reg_t
sv_proc_t::to_uint32(sv_float32_t
const& reg
)
1308 switch (reg
.get_elwidth())
1311 case 1: throw trap_illegal_instruction(0); // XXX for now
1312 // 16-bit data, up-convert to f32
1315 float32_t x32
= ::f32(reg
.to_uint32());
1316 return sv_reg_t(f32_to_f16(x32
).v
, xlen
, reg
.get_elwidth());
1318 // 0 and 3 are 32-bit
1321 return sv_reg_t(reg
.to_uint32(), xlen
, reg
.get_elwidth());
1326 uint64_t sv_freg_t::to_uint64() const&
1331 uint32_t sv_freg_t::to_uint32() const&
1336 uint32_t sv_float32_t::to_uint32() const&