patch-2.4.15 linux/arch/ia64/kernel/unaligned.c
Next file: linux/arch/ia64/kernel/unwind.c
Previous file: linux/arch/ia64/kernel/traps.c
Back to the patch index
Back to the overall index
- Lines: 143
- Date:
Fri Nov 9 14:26:17 2001
- Orig file:
v2.4.14/linux/arch/ia64/kernel/unaligned.c
- Orig date:
Sun Aug 12 13:27:58 2001
diff -u --recursive --new-file v2.4.14/linux/arch/ia64/kernel/unaligned.c linux/arch/ia64/kernel/unaligned.c
@@ -5,6 +5,8 @@
* Copyright (C) 1999-2000 Stephane Eranian <eranian@hpl.hp.com>
* Copyright (C) 2001 David Mosberger-Tang <davidm@hpl.hp.com>
*
+ * 2001/10/11 Fix unaligned access to rotating registers in s/w pipelined loops.
+ * 2001/08/13 Correct size of extended floats (float_fsz) from 16 to 10 bytes.
* 2001/01/17 Add support emulation of unaligned kernel accesses.
*/
#include <linux/kernel.h>
@@ -282,9 +284,19 @@
unsigned long rnats, nat_mask;
unsigned long on_kbs;
long sof = (regs->cr_ifs) & 0x7f;
+ long sor = 8 * ((regs->cr_ifs >> 14) & 0xf);
+ long rrb_gr = (regs->cr_ifs >> 18) & 0x7f;
+ long ridx;
+
+ if ((r1 - 32) > sor)
+ ridx = -sof + (r1 - 32);
+ else if ((r1 - 32) < (sor - rrb_gr))
+ ridx = -sof + (r1 - 32) + rrb_gr;
+ else
+ ridx = -sof + (r1 - 32) - (sor - rrb_gr);
- DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld\n",
- r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f);
+ DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n",
+ r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx);
if ((r1 - 32) >= sof) {
/* this should never happen, as the "rsvd register fault" has higher priority */
@@ -293,7 +305,7 @@
}
on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore);
- addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + (r1 - 32));
+ addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, ridx);
if (addr >= kbs) {
/* the register is on the kernel backing store: easy... */
rnat_addr = ia64_rse_rnat_addr(addr);
@@ -318,12 +330,12 @@
return;
}
- bspstore = (unsigned long *) regs->ar_bspstore;
+ bspstore = (unsigned long *)regs->ar_bspstore;
ubs_end = ia64_rse_skip_regs(bspstore, on_kbs);
bsp = ia64_rse_skip_regs(ubs_end, -sof);
- addr = ia64_rse_skip_regs(bsp, r1 - 32);
+ addr = ia64_rse_skip_regs(bsp, ridx + sof);
- DPRINT("ubs_end=%p bsp=%p addr=%px\n", (void *) ubs_end, (void *) bsp, (void *) addr);
+ DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr);
ia64_poke(current, sw, (unsigned long) ubs_end, (unsigned long) addr, val);
@@ -353,9 +365,19 @@
unsigned long rnats, nat_mask;
unsigned long on_kbs;
long sof = (regs->cr_ifs) & 0x7f;
+ long sor = 8 * ((regs->cr_ifs >> 14) & 0xf);
+ long rrb_gr = (regs->cr_ifs >> 18) & 0x7f;
+ long ridx;
+
+ if ((r1 - 32) > sor)
+ ridx = -sof + (r1 - 32);
+ else if ((r1 - 32) < (sor - rrb_gr))
+ ridx = -sof + (r1 - 32) + rrb_gr;
+ else
+ ridx = -sof + (r1 - 32) - (sor - rrb_gr);
- DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld\n",
- r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f);
+ DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n",
+ r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx);
if ((r1 - 32) >= sof) {
/* this should never happen, as the "rsvd register fault" has higher priority */
@@ -364,7 +386,7 @@
}
on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore);
- addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + (r1 - 32));
+ addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, ridx);
if (addr >= kbs) {
/* the register is on the kernel backing store: easy... */
*val = *addr;
@@ -390,7 +412,7 @@
bspstore = (unsigned long *)regs->ar_bspstore;
ubs_end = ia64_rse_skip_regs(bspstore, on_kbs);
bsp = ia64_rse_skip_regs(ubs_end, -sof);
- addr = ia64_rse_skip_regs(bsp, r1 - 32);
+ addr = ia64_rse_skip_regs(bsp, ridx + sof);
DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr);
@@ -908,7 +930,7 @@
* floating point operations sizes in bytes
*/
static const unsigned char float_fsz[4]={
- 16, /* extended precision (e) */
+ 10, /* extended precision (e) */
8, /* integer (8) */
4, /* single precision (s) */
8 /* double precision (d) */
@@ -978,11 +1000,11 @@
unsigned long len = float_fsz[ld.x6_sz];
/*
- * fr0 & fr1 don't need to be checked because Illegal Instruction
- * faults have higher priority than unaligned faults.
+ * fr0 & fr1 don't need to be checked because Illegal Instruction faults have
+ * higher priority than unaligned faults.
*
- * r0 cannot be found as the base as it would never generate an
- * unaligned reference.
+ * r0 cannot be found as the base as it would never generate an unaligned
+ * reference.
*/
/*
@@ -996,8 +1018,10 @@
* invalidate the ALAT entry and execute updates, if any.
*/
if (ld.x6_op != 0x2) {
- /* this assumes little-endian byte-order: */
-
+ /*
+ * This assumes little-endian byte-order. Note that there is no "ldfpe"
+ * instruction:
+ */
if (copy_from_user(&fpr_init[0], (void *) ifa, len)
|| copy_from_user(&fpr_init[1], (void *) (ifa + len), len))
return -1;
@@ -1337,7 +1361,7 @@
/*
* IMPORTANT:
- * Notice that the swictch statement DOES not cover all possible instructions
+ * Notice that the switch statement DOES not cover all possible instructions
* that DO generate unaligned references. This is made on purpose because for some
* instructions it DOES NOT make sense to try and emulate the access. Sometimes it
* is WRONG to try and emulate. Here is a list of instruction we don't emulate i.e.,
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)