READ_FREG reads fp16 from offset into reg array
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 31 Oct 2018 07:47:05 +0000 (07:47 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 31 Oct 2018 07:47:05 +0000 (07:47 +0000)
riscv/sv_insn_redirect.cc

index 06a154f2bbfd0d6b4498edc1ff48b1a5efe7ee7a..a11ec6aa2bcc13ab6d52c6fc53ae1fd1eea19c99 100644 (file)
@@ -143,17 +143,51 @@ 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)
     reg_t reg = spec.reg;
-    uint8_t elwidth = _insn->reg_elwidth(reg, true);
-    if (spec.offset) {
-        reg += *spec.offset;
+    uint8_t elwidth = _insn->reg_elwidth(reg, false);
+    int bitwidth = get_bitwidth(elwidth, flen);
+    int shift = 0;
+    int offs = 0;
+    if (spec.offset != NULL) {
+        int nbytes = flen / bitwidth;
+        if (nbytes == 0) {
+            nbytes = 1;
+        }
+        offs = *spec.offset;
+        shift = offs % nbytes;
+        offs /= nbytes;
+        reg += offs;
+    }
+    freg_shift fs;
+    fs.f = _insn->p->get_state()->FPR[reg];
+    fprintf(stderr, "READ_FREG rd %ld ew %d bw %d fl %d data %lx %lx\n",
+            reg, elwidth, bitwidth, flen, fs.f.v[0], fs.f.v[1]);
+
+    if (flen != bitwidth)
+    {
+        // shuffle the data down by bytes (annoying but easier)
+        int sblen = shift*bitwidth/8;
+        for (int i = 0; i < ((int)flen/8); i++) {
+            if (i < (bitwidth/8)) {
+               fs.b[i] = fs.b[i+sblen];
+            } else {
+                fs.b[i] = 0xff;
+            }
+        }
+        fprintf(stderr, "readfreg %ld bitwidth %d offs %d " \
+                        "shift %d %lx:%lx\n",
+                        spec.reg, bitwidth, offs, shift,
+                        fs.f.v[0], fs.f.v[1]);
     }
-    freg_t value = _insn->p->get_state()->FPR[reg];
-    fprintf(stderr, "READ_FREG rd %ld ew %d data %lx %lx\n",
-            reg, elwidth, ((freg_t)value).v[0], ((freg_t)value).v[1]);
-    return value;
+    return fs.f;
 }
 
 reg_t sv_proc_t::READ_REG(reg_spec_t const& spec,