[mips] fix up the assembly generation of unaligned exception loads
I noticed that unaligned accesses were returning garbage values. Give test data like this: char testdata[] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x5a }; Iterating through uint32_t space 1 byte at a time should look like this: freebsd-carambola2:/mnt# ./test Hello, world! offset 0 pointer 0x410b00 value 0x12345678 0x12345678 offset 1 pointer 0x410b01 value 0x3456789a 0x3456789a offset 2 pointer 0x410b02 value 0x56789abc 0x56789abc offset 3 pointer 0x410b03 value 0x789abcde 0x789abcde offset 4 pointer 0x410b04 value 0x9abcdef1 0x9abcdef1 offset 5 pointer 0x410b05 value 0xbcdef123 0xbcdef123 offset 6 pointer 0x410b06 value 0xdef12345 0xdef12345 offset 7 pointer 0x410b07 value 0xf1234567 0xf1234567 .. but to begin with it looked like this: offset 0 value 0x12345678 offset 1 value 0x00410a9a offset 2 value 0x00419abc offset 3 value 0x009abcde offset 4 value 0x9abcdef1 offset 5 value 0x00410a23 offset 6 value 0x00412345 offset 7 value 0x00234567 The amusing reason? The compiler is generating the lwr/lwl incorrectly. Here's an example after I tried to replace the two macros with a single invocation and offset, rather than having the compiler compile in addiu to s3 - but the bug is the same: 1044: 8a620003 lwl v0,0(s3) 1048: 9a730000 lwr s3,3(s3) .. which is just totally trashy and wrong. This explicitly tells the compiler to treat the output as being read and written to, which is what lwl/lwr does with the destination register. I think a subsequent commit should unify these macros to skip an addiu, but that can be a later commit. Reviewed by: jhb Differential Revision: https://reviews.freebsd.org/D25040
This commit is contained in:
parent
f4903a79fb
commit
5687a376df
@ -114,22 +114,22 @@ SYSCTL_INT(_machdep, OID_AUTO, trap_debug, CTLFLAG_RW,
|
||||
|
||||
#define lwl_macro(data, addr) \
|
||||
__asm __volatile ("lwl %0, 0x0(%1)" \
|
||||
: "=r" (data) /* outputs */ \
|
||||
: "+r" (data) /* outputs */ \
|
||||
: "r" (addr)); /* inputs */
|
||||
|
||||
#define lwr_macro(data, addr) \
|
||||
__asm __volatile ("lwr %0, 0x0(%1)" \
|
||||
: "=r" (data) /* outputs */ \
|
||||
: "+r" (data) /* outputs */ \
|
||||
: "r" (addr)); /* inputs */
|
||||
|
||||
#define ldl_macro(data, addr) \
|
||||
__asm __volatile ("ldl %0, 0x0(%1)" \
|
||||
: "=r" (data) /* outputs */ \
|
||||
: "+r" (data) /* outputs */ \
|
||||
: "r" (addr)); /* inputs */
|
||||
|
||||
#define ldr_macro(data, addr) \
|
||||
__asm __volatile ("ldr %0, 0x0(%1)" \
|
||||
: "=r" (data) /* outputs */ \
|
||||
: "+r" (data) /* outputs */ \
|
||||
: "r" (addr)); /* inputs */
|
||||
|
||||
#define sb_macro(data, addr) \
|
||||
@ -1528,7 +1528,7 @@ mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, re
|
||||
{
|
||||
register_t *reg = (register_t *) frame;
|
||||
u_int32_t inst = *((u_int32_t *)(intptr_t)pc);
|
||||
register_t value_msb, value;
|
||||
register_t value_msb = 0, value = 0;
|
||||
unsigned size;
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user