WRITE_REG( _insn->rd(), value ); // XXX TODO: replace properly
}
+union freg_shift {
+ freg_t f;
+ uint8_t b[sizeof(freg_t)*8];
+};
+
void (sv_proc_t::DO_WRITE_FREG)(reg_spec_t const& spec, sv_freg_t const& value)
{
+ int flen = sizeof(freg_t) * 8; // FLEN (not specified in spike)
reg_t reg = spec.reg;
uint8_t dest_elwidth = _insn->reg_elwidth(reg, false);
- if (spec.offset) {
- reg += *spec.offset;
- }
+ int bitwidth = get_bitwidth(dest_elwidth, flen);
fprintf(stderr, "DO_WRITE_FRD rd %ld ew %d data %lx %lx\n",
reg, dest_elwidth, ((freg_t)value).v[0], ((freg_t)value).v[1]);
- STATE.FPR.write(reg, value);
+ unsigned int shift = 0;
+ unsigned int offs = 0;
+ if (spec.offset != NULL) {
+ unsigned int nbytes = xlen / bitwidth;
+ offs = *spec.offset;
+ shift = offs % nbytes;
+ offs /= nbytes;
+ reg += offs;
+ fprintf(stderr, "writefreg spec %ld bitwidth %d offs %d shift %d\n",
+ reg, bitwidth, offs, shift);
+ }
+ freg_shift fd;
+ if (xlen != bitwidth)
+ {
+ char report[2] = {};
+ freg_shift fs;
+ fs.f = value;
+ fd.f = _insn->p->get_state()->FPR[reg];
+ int sblen = shift*bitwidth/8;
+ for (int i = 0; i < ((int)bitwidth/8); i++) {
+ if (i < (bitwidth/8)) {
+ fd.b[i+sblen] = fs.b[i];
+ }
+ }
+ if (!spec.isvec) {
+ for (int i = (bitwidth/8); i < ((int)flen/8); i++) {
+ fd.b[i] = 0xff;
+ }
+ report[0] = 's';
+ }
+ fprintf(stderr, "writefreg %s %ld bitwidth %d offs %d shift %d " \
+ " %lx:%lx %lx:%lx\n",
+ report, spec.reg, bitwidth, offs, shift,
+ fs.f.v[0], fs.f.v[1],
+ fd.f.v[0], fd.f.v[1]);
+ }
+ else
+ {
+ fd.f = value;
+ }
+ STATE.FPR.write(reg, fd.f);
dirty_fp_state;
}
STATE.XPR.write(reg, wval);
}
-union freg_shift {
- freg_t f;
- uint8_t b[sizeof(freg_t)*8];
-};
-
freg_t (sv_proc_t::READ_FREG)(reg_spec_t const& spec)
{
int flen = sizeof(freg_t) * 8; // FLEN (not specified in spike)