patch-2.2.4 linux/arch/sparc64/kernel/unaligned.c
Next file: linux/arch/sparc64/math-emu/fabsq.c
Previous file: linux/arch/sparc64/kernel/traps.c
Back to the patch index
Back to the overall index
- Lines: 111
- Date:
Wed Mar 10 16:53:37 1999
- Orig file:
v2.2.3/linux/arch/sparc64/kernel/unaligned.c
- Orig date:
Sun Nov 8 14:02:48 1998
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/unaligned.c linux/arch/sparc64/kernel/unaligned.c
@@ -1,4 +1,4 @@
-/* $Id: unaligned.c,v 1.13 1998/10/07 22:43:13 davem Exp $
+/* $Id: unaligned.c,v 1.14 1999/03/02 15:42:16 jj Exp $
* unaligned.c: Unaligned load/store trap handling with special
* cases for the kernel to do them more quickly.
*
@@ -470,7 +470,7 @@
extern void do_privact(struct pt_regs *regs);
extern void data_access_exception(struct pt_regs *regs);
-int handle_ldq_stq(u32 insn, struct pt_regs *regs)
+int handle_ldf_stq(u32 insn, struct pt_regs *regs)
{
unsigned long addr = compute_effective_address(regs, insn, 0);
int freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20);
@@ -522,8 +522,10 @@
return 1;
}
} else {
- /* LDQ */
- u32 first, second, third, fourth;
+ /* LDF, LDDF, LDQF */
+ u32 data[4] __attribute__ ((aligned(8)));
+ int size, i;
+ int err;
if (asi < 0x80) {
do_privact(regs);
@@ -532,25 +534,35 @@
data_access_exception(regs);
return 1;
}
- if (get_user (first, (u32 *)addr) ||
- __get_user (second, (u32 *)(addr + 4)) ||
- __get_user (third, (u32 *)(addr + 8)) ||
- __get_user (fourth, (u32 *)(addr + 12))) {
- if (asi & 0x2) /* NF */ {
- first = 0; second = 0; third = 0; fourth = 0;
- } else {
- data_access_exception(regs);
- return 1;
- }
+ switch (insn & 0x180000) {
+ case 0x000000: size = 1; break;
+ case 0x100000: size = 4; break;
+ default: size = 2; break;
+ }
+ for (i = 0; i < size; i++)
+ data[i] = 0;
+
+ err = get_user (data[0], (u32 *)addr);
+ if (!err) {
+ for (i = 1; i < size; i++)
+ err |= __get_user (data[i], (u32 *)(addr + 4*i));
+ }
+ if (err && !(asi & 0x2 /* NF */)) {
+ data_access_exception(regs);
+ return 1;
}
if (asi & 0x8) /* Little */ {
- u32 tmp = le32_to_cpup(&first);
-
- first = le32_to_cpup(&fourth);
- fourth = tmp;
- tmp = le32_to_cpup(&second);
- second = le32_to_cpup(&third);
- third = tmp;
+ u64 tmp;
+
+ switch (size) {
+ case 1: data[0] = le32_to_cpup(data + 0); break;
+ default:*(u64 *)(data + 0) = le64_to_cpup((u64 *)(data + 0));
+ break;
+ case 4: tmp = le64_to_cpup((u64 *)(data + 0));
+ *(u64 *)(data + 0) = le64_to_cpup((u64 *)(data + 2));
+ *(u64 *)(data + 2) = tmp;
+ break;
+ }
}
if (!(current->tss.fpsaved[0] & FPRS_FEF)) {
current->tss.fpsaved[0] = FPRS_FEF;
@@ -562,14 +574,25 @@
else
memset(f->regs+32, 0, 32*sizeof(u32));
}
- f->regs[freg] = first;
- f->regs[freg+1] = second;
- f->regs[freg+2] = third;
- f->regs[freg+3] = fourth;
+ memcpy(f->regs + freg, data, size * 4);
current->tss.fpsaved[0] |= flag;
}
advance(regs);
return 1;
+}
+
+void handle_ld_nf(u32 insn, struct pt_regs *regs)
+{
+ int rd = ((insn >> 25) & 0x1f);
+ int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
+ unsigned long *reg;
+
+ maybe_flush_windows(0, 0, rd, from_kernel);
+ reg = fetch_reg_addr(rd, regs);
+ if ((insn & 0x780000) == 0x180000)
+ reg[1] = 0;
+ reg[0] = 0;
+ advance(regs);
}
void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)