summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2003-11-06 04:26:40 +0000
committermarcel <marcel@FreeBSD.org>2003-11-06 04:26:40 +0000
commit636849aec5c4eb6b782ab6ad5f7623b8bea34680 (patch)
treeaf2c54a9c2dae1c2eb62a0a3a9675345e6fc3998
parent96ae8eeca766dcb5847ec19ab6a191da8ae2387d (diff)
downloadFreeBSD-src-636849aec5c4eb6b782ab6ad5f7623b8bea34680.zip
FreeBSD-src-636849aec5c4eb6b782ab6ad5f7623b8bea34680.tar.gz
Add support for unaligned ld2, st2, st4 and st8. While here, make
sure we handle stacked registers properly by taking into account that: 1. bspstore points after the frame (due to cover), 2. we need to adjust for intermediate NaT collections.
-rw-r--r--sys/ia64/ia64/unaligned.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/sys/ia64/ia64/unaligned.c b/sys/ia64/ia64/unaligned.c
index bcbb638..0b04f38 100644
--- a/sys/ia64/ia64/unaligned.c
+++ b/sys/ia64/ia64/unaligned.c
@@ -74,12 +74,16 @@ static void *
greg_ptr(mcontext_t *mc, int gr)
{
uint64_t *p;
+ int bias, nslots;
if (gr <= 0 || gr >= 32 + (mc->mc_special.cfm & 0x7f))
return (NULL);
if (gr >= 32) {
p = (void*)mc->mc_special.bspstore;
- p += gr - 32;
+ nslots = (mc->mc_special.cfm & 0x7f) - gr + 32;
+ bias = (0x1f8 - (mc->mc_special.bspstore & 0x1f8)) >> 3;
+ nslots += (nslots + bias) / 63;
+ p -= nslots;
gr = 0;
} else if (gr >= 14) {
p = &mc->mc_scratch.gr14;
@@ -134,6 +138,13 @@ fixup(struct asm_inst *i, mcontext_t *mc, uint64_t va)
uint64_t postinc;
switch (i->i_op) {
+ case ASM_OP_LD2:
+ copyin((void*)va, (void*)&buf.i, 2);
+ reg = greg_ptr(mc, (int)i->i_oper[1].o_value);
+ if (reg == NULL)
+ return (EINVAL);
+ wrreg(reg, buf.i & 0xffffU);
+ break;
case ASM_OP_LD4:
copyin((void*)va, (void*)&buf.i, 4);
reg = greg_ptr(mc, (int)i->i_oper[1].o_value);
@@ -155,6 +166,27 @@ fixup(struct asm_inst *i, mcontext_t *mc, uint64_t va)
return (EINVAL);
spillfd((void*)&buf.d, reg);
break;
+ case ASM_OP_ST2:
+ reg = greg_ptr(mc, (int)i->i_oper[2].o_value);
+ if (reg == NULL)
+ return (EINVAL);
+ buf.i = rdreg(reg);
+ copyout((void*)&buf.i, (void*)va, 2);
+ break;
+ case ASM_OP_ST4:
+ reg = greg_ptr(mc, (int)i->i_oper[2].o_value);
+ if (reg == NULL)
+ return (EINVAL);
+ buf.i = rdreg(reg);
+ copyout((void*)&buf.i, (void*)va, 4);
+ break;
+ case ASM_OP_ST8:
+ reg = greg_ptr(mc, (int)i->i_oper[2].o_value);
+ if (reg == NULL)
+ return (EINVAL);
+ buf.i = rdreg(reg);
+ copyout((void*)&buf.i, (void*)va, 8);
+ break;
default:
return (ENOENT);
}
OpenPOWER on IntegriCloud