summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgallatin <gallatin@FreeBSD.org>2002-05-16 00:03:32 +0000
committergallatin <gallatin@FreeBSD.org>2002-05-16 00:03:32 +0000
commitb005f02fe7b6d76737de49db8ffce8e82656935c (patch)
treeab5136afefb679b9b612f393de52d565494a237d
parent5637f2111a58203b453bd7d31615a0d7c51c21a2 (diff)
downloadFreeBSD-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
-rw-r--r--sys/alpha/alpha/trap.c32
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);
OpenPOWER on IntegriCloud