From: Luke Kenneth Casson Leighton Date: Wed, 31 Oct 2018 11:37:15 +0000 (+0000) Subject: add packed (non-default) elwidth support in DO_WRITE_FREG X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9e75273cac18e1b983e5dacc4887e42321d408f0;p=riscv-isa-sim.git add packed (non-default) elwidth support in DO_WRITE_FREG --- diff --git a/riscv/sv_insn_redirect.cc b/riscv/sv_insn_redirect.cc index a11ec6a..b995c78 100644 --- a/riscv/sv_insn_redirect.cc +++ b/riscv/sv_insn_redirect.cc @@ -86,16 +86,60 @@ void (sv_proc_t::WRITE_RD)(sv_reg_t const& value) 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; } @@ -143,11 +187,6 @@ void (sv_proc_t::WRITE_REG)(reg_spec_t const& spec, sv_reg_t const& value) 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)