diff options
author | gallatin <gallatin@FreeBSD.org> | 2002-05-16 00:03:32 +0000 |
---|---|---|
committer | gallatin <gallatin@FreeBSD.org> | 2002-05-16 00:03:32 +0000 |
commit | b005f02fe7b6d76737de49db8ffce8e82656935c (patch) | |
tree | ab5136afefb679b9b612f393de52d565494a237d /sys | |
parent | 5637f2111a58203b453bd7d31615a0d7c51c21a2 (diff) | |
download | FreeBSD-src-b005f02fe7b6d76737de49db8ffce8e82656935c.zip FreeBSD-src-b005f02fe7b6d76737de49db8ffce8e82656935c.tar.gz |
Fixup unaligned bwx instructions (ldwu, stw). This may fix some mysterious
natd sigbus errors being reported on the freebsd-alpha@ mailing list.
Obtained from: NetBSD
Diffstat (limited to 'sys')
-rw-r--r-- | sys/alpha/alpha/trap.c | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/sys/alpha/alpha/trap.c b/sys/alpha/alpha/trap.c index 7f97984..a64d7ec 100644 --- a/sys/alpha/alpha/trap.c +++ b/sys/alpha/alpha/trap.c @@ -968,6 +968,11 @@ Gfloat_reg_cvt(input) extern int alpha_unaligned_print, alpha_unaligned_fix; extern int alpha_unaligned_sigbus; +struct unaligned_fixup_data { + const char *type; /* opcode name */ + int size; /* size, 0 if fixup not supported */ +}; + int unaligned_fixup(va, opcode, reg, td) unsigned long va, opcode, reg; @@ -979,10 +984,11 @@ unaligned_fixup(va, opcode, reg, td) struct proc *p; unsigned long *regptr, longdata, uac; int intdata; /* signed to get extension when storing */ - struct { - const char *type; /* opcode name */ - int size; /* size, 0 if fixup not supported */ - } tab[0x10] = { + u_int16_t worddata; /* unsigned to _avoid_ extension */ + const struct unaligned_fixup_data tab_0c[0x2] = { + { "ldwu", 2 }, { "stw", 2 }, + }; + const struct unaligned_fixup_data tab_20[0x10] = { #ifdef FIX_UNALIGNED_VAX_FP { "ldf", 4 }, { "ldg", 8 }, #else @@ -1022,9 +1028,12 @@ unaligned_fixup(va, opcode, reg, td) * Find out which opcode it is. Arrange to have the opcode * printed if it's an unknown opcode. */ - if (opcode >= 0x20 && opcode <= 0x2f) { - type = tab[opcode - 0x20].type; - size = tab[opcode - 0x20].size; + if (opcode >= 0x0c && opcode <= 0x0d) { + type = tab_0c[opcode - 0x0c].type; + size = tab_0c[opcode - 0x0c].size; + } else if (opcode >= 0x20 && opcode <= 0x2f) { + type = tab_20[opcode - 0x20].type; + size = tab_20[opcode - 0x20].size; } else { type = "0x%lx"; size = 0; @@ -1067,6 +1076,15 @@ unaligned_fixup(va, opcode, reg, td) signal = SIGBUS; if (dofix && size != 0) { switch (opcode) { + case 0x0c: /* ldwu */ + /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */ + unaligned_load_integer(worddata); + break; + + case 0x0d: /* stw */ + /* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */ + unaligned_store_integer(worddata); + break; #ifdef FIX_UNALIGNED_VAX_FP case 0x20: /* ldf */ unaligned_load_floating(intdata, Ffloat_to_reg); |