Browse Source

Fix Q extension on big-endian targets

The previous routines always stored the low-order bits into the
low-order doubleword, which is only correct on little-endian targets.
pull/2176/head
Andrew Waterman 5 months ago
parent
commit
57fb2facf3
  1. 4
      riscv/insns/flq.h
  2. 3
      riscv/insns/fsq.h
  3. 22
      riscv/mmu.h

4
riscv/insns/flq.h

@ -1,3 +1,5 @@
require_extension('Q');
require_fp;
WRITE_FRD(MMU.load_float128(RS1 + insn.i_imm()));
uint128_t v = MMU.load<uint128_t>(RS1 + insn.i_imm());
float128_t f = { uint64_t(v), uint64_t(v >> 64) };
WRITE_FRD(f);

3
riscv/insns/fsq.h

@ -1,3 +1,4 @@
require_extension('Q');
require_fp;
MMU.store_float128(RS1 + insn.s_imm(), FRS2);
uint128_t v = FRS2.v[0] | (uint128_t(FRS2.v[1]) << 64);
MMU.store<uint128_t>(RS1 + insn.s_imm(), v);

22
riscv/mmu.h

@ -211,28 +211,6 @@ public:
})
}
void store_float128(reg_t addr, float128_t val)
{
if (unlikely(addr & (sizeof(float128_t)-1)) && !is_misaligned_enabled()) {
throw trap_store_address_misaligned((proc) ? proc->state.v : false, addr, 0, 0);
}
store<uint64_t>(addr, val.v[0]);
store<uint64_t>(addr + 8, val.v[1]);
}
float128_t load_float128(reg_t addr)
{
if (unlikely(addr & (sizeof(float128_t)-1)) && !is_misaligned_enabled()) {
throw trap_load_address_misaligned((proc) ? proc->state.v : false, addr, 0, 0);
}
float128_t res;
res.v[0] = load<uint64_t>(addr);
res.v[1] = load<uint64_t>(addr + 8);
return res;
}
void cbo_zero(reg_t addr) {
auto access_info = generate_access_info(addr, STORE, {});
reg_t transformed_addr = access_info.transformed_vaddr;

Loading…
Cancel
Save