aboutsummaryrefslogtreecommitdiff
path: root/machine
diff options
context:
space:
mode:
authorMarcus Comstedt <marcus@mc.pp.se>2020-11-24 01:05:59 +0100
committerGitHub <noreply@github.com>2020-11-23 16:05:59 -0800
commit1f2e2b3b8dd6866d4e8c0e3937bf355464d31c50 (patch)
treef5c8a680d0a21d7367a90ac916ef292bfbd970ee /machine
parentf0959f9d18c3bd04f601867e57fdf55bc2dba8d2 (diff)
downloadriscv-pk-1f2e2b3b8dd6866d4e8c0e3937bf355464d31c50.zip
riscv-pk-1f2e2b3b8dd6866d4e8c0e3937bf355464d31c50.tar.gz
riscv-pk-1f2e2b3b8dd6866d4e8c0e3937bf355464d31c50.tar.bz2
Fix emulation of misaligned access on big endian target (#224)
Diffstat (limited to 'machine')
-rw-r--r--machine/misaligned_ldst.c14
-rw-r--r--machine/unprivileged_memory.h21
2 files changed, 32 insertions, 3 deletions
diff --git a/machine/misaligned_ldst.c b/machine/misaligned_ldst.c
index a187d25..707de2a 100644
--- a/machine/misaligned_ldst.c
+++ b/machine/misaligned_ldst.c
@@ -10,6 +10,7 @@
union byte_array {
uint8_t bytes[8];
uintptr_t intx;
+ uint32_t int32;
uint64_t int64;
};
@@ -75,11 +76,15 @@ void misaligned_load_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc)
val.bytes[i] = load_uint8_t((void *)(addr + i), mepc);
if (!fp)
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
SET_RD(insn, regs, (intptr_t)val.intx << shift >> shift);
+#else
+ SET_RD(insn, regs, (intptr_t)val.intx >> shift);
+#endif
else if (len == 8)
SET_F64_RD(insn, regs, val.int64);
else
- SET_F32_RD(insn, regs, val.intx);
+ SET_F32_RD(insn, regs, val.int32);
write_csr(mepc, npc);
}
@@ -138,8 +143,13 @@ void misaligned_store_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc)
}
uintptr_t addr = read_csr(mbadaddr);
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ intptr_t offs = (len == 8? 0 : sizeof(val.intx) - len);
+#else
+ intptr_t offs = 0;
+#endif
for (int i = 0; i < len; i++)
- store_uint8_t((void *)(addr + i), val.bytes[i], mepc);
+ store_uint8_t((void *)(addr + i), val.bytes[offs + i], mepc);
write_csr(mepc, npc);
}
diff --git a/machine/unprivileged_memory.h b/machine/unprivileged_memory.h
index fb70baa..b54c601 100644
--- a/machine/unprivileged_memory.h
+++ b/machine/unprivileged_memory.h
@@ -79,22 +79,37 @@ static uintptr_t __attribute__((always_inline)) get_insn(uintptr_t mepc, uintptr
: [mstatus] "+&r" (__mstatus), [insn] "=&r" (val)
: [mprv] "r" (__mstatus_adjust), [addr] "r" (__mepc));
#else
- uintptr_t rvc_mask = 3, tmp;
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ uintptr_t rvc_mask = 3 << 24;
+#else
+ uintptr_t rvc_mask = 3;
+#endif
+ uintptr_t tmp;
asm ("csrrs %[mstatus], mstatus, %[mprv]\n"
"and %[tmp], %[addr], 2\n"
"bnez %[tmp], 1f\n"
STR(LWU) " %[insn], (%[addr])\n"
"and %[tmp], %[insn], %[rvc_mask]\n"
"beq %[tmp], %[rvc_mask], 2f\n"
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
"sll %[insn], %[insn], %[xlen_minus_16]\n"
"srl %[insn], %[insn], %[xlen_minus_16]\n"
+#else
+ "srl %[insn], %[insn], 16\n"
+ "sll %[insn], %[insn], 16\n"
+#endif
"j 2f\n"
"1:\n"
"lhu %[insn], (%[addr])\n"
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ "sll %[insn], %[insn], 16\n"
+#endif
"and %[tmp], %[insn], %[rvc_mask]\n"
"bne %[tmp], %[rvc_mask], 2f\n"
"lhu %[tmp], 2(%[addr])\n"
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
"sll %[tmp], %[tmp], 16\n"
+#endif
"add %[insn], %[insn], %[tmp]\n"
"2: csrw mstatus, %[mstatus]"
: [mstatus] "+&r" (__mstatus), [insn] "=&r" (val), [tmp] "=&r" (tmp)
@@ -102,7 +117,11 @@ static uintptr_t __attribute__((always_inline)) get_insn(uintptr_t mepc, uintptr
[rvc_mask] "r" (rvc_mask), [xlen_minus_16] "i" (__riscv_xlen - 16));
#endif
*mstatus = __mstatus;
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ return __builtin_bswap32(val);
+#else
return val;
+#endif
}
#endif