More fixup in the signal area.
64-bit syscall cleanup. Add emulation for some new FPU insns: conversion to 64-bit long int and conditional moves.
This commit is contained in:
parent
5a0ae6393f
commit
1cc6223a9c
@ -1,4 +1,4 @@
|
||||
# $NetBSD: Makefile,v 1.4 1998/09/13 16:02:47 eeh Exp $
|
||||
# $NetBSD: Makefile,v 1.5 1998/09/22 02:48:42 eeh Exp $
|
||||
|
||||
# Makefile for sparc64 tags file and boot blocks
|
||||
|
||||
@ -10,6 +10,8 @@ ASPARC64= ../sparc64/sparc64/*.s
|
||||
# Directories in which to place tags links
|
||||
DSPARC64= conf dev fpu include sparc64
|
||||
|
||||
.include "../../kern/Make.tags.inc"
|
||||
|
||||
tags:
|
||||
-ctags -wdtf ${TSPARC64} ${SSPARC64} ${COMM}
|
||||
egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${ASPARC64} | \
|
||||
@ -18,8 +20,8 @@ tags:
|
||||
sort -o ${TSPARC64} ${TSPARC64}
|
||||
|
||||
TAGS:
|
||||
etags ${TSPARC64} ${SSPARC64} ${COMM} \
|
||||
"--regex=/ENTRY(.*)|FUNC(.*)|SYSCALL(.*)/" ${ASPARC64}
|
||||
etags ${SSPARC64} ${COMM} "--regex=/ENTRY(.*)/" \
|
||||
"--regex=/FUNC(.*)/" "--regex=/SYSCALL(.*)/" ${ASPARC64}
|
||||
|
||||
links:
|
||||
-for i in ${DSPARC64}; do \
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: fpu.c,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */
|
||||
/* $NetBSD: fpu.c,v 1.2 1998/09/22 02:48:42 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -245,7 +245,7 @@ fpu_execute(fe, instr)
|
||||
union instr instr;
|
||||
{
|
||||
register struct fpn *fp;
|
||||
register int opf, rs1, rs2, rd, type, mask, fsr, cx;
|
||||
register int opf, rs1, rs2, rd, type, mask, fsr, cx, i, cond;
|
||||
register struct fpstate *fs;
|
||||
u_int space[4];
|
||||
|
||||
@ -267,6 +267,117 @@ fpu_execute(fe, instr)
|
||||
fs = fe->fe_fpstate;
|
||||
fe->fe_fsr = fs->fs_fsr & ~FSR_CX;
|
||||
fe->fe_cx = 0;
|
||||
/*
|
||||
* Check to see if we're dealing with a fancy cmove and handle
|
||||
* it first.
|
||||
*/
|
||||
if (instr.i_op3.i_op3 == IOP3_FPop2 && (opf&0xff0) != (FCMP&0xff0)) {
|
||||
switch (opf >>= 2) {
|
||||
case FMVFC0 >> 2:
|
||||
cond = (fs->fs_fsr>>FSR_FCC_SHIFT)&FSR_FCC_MASK;
|
||||
if (instr.i_fmovcc.i_cond != cond) return(0); /* success */
|
||||
rs1 = fs->fs_regs[rs2];
|
||||
goto mov;
|
||||
case FMVFC1 >> 2:
|
||||
cond = (fs->fs_fsr>>FSR_FCC1_SHIFT)&FSR_FCC_MASK;
|
||||
if (instr.i_fmovcc.i_cond != cond) return(0); /* success */
|
||||
rs1 = fs->fs_regs[rs2];
|
||||
goto mov;
|
||||
case FMVFC2 >> 2:
|
||||
cond = (fs->fs_fsr>>FSR_FCC2_SHIFT)&FSR_FCC_MASK;
|
||||
if (instr.i_fmovcc.i_cond != cond) return(0); /* success */
|
||||
rs1 = fs->fs_regs[rs2];
|
||||
goto mov;
|
||||
case FMVFC3 >> 2:
|
||||
cond = (fs->fs_fsr>>FSR_FCC3_SHIFT)&FSR_FCC_MASK;
|
||||
if (instr.i_fmovcc.i_cond != cond) return(0); /* success */
|
||||
rs1 = fs->fs_regs[rs2];
|
||||
goto mov;
|
||||
case FMVIC >> 2:
|
||||
/* Presume we're curproc */
|
||||
cond = (curproc->p_md.md_tf->tf_tstate>>TSTATE_CCR_SHIFT)&PSR_ICC;
|
||||
if (instr.i_fmovcc.i_cond != cond) return(0); /* success */
|
||||
rs1 = fs->fs_regs[rs2];
|
||||
goto mov;
|
||||
case FMVXC >> 2:
|
||||
/* Presume we're curproc */
|
||||
cond = (curproc->p_md.md_tf->tf_tstate>>(TSTATE_CCR_SHIFT+XCC_SHIFT))&PSR_ICC;
|
||||
if (instr.i_fmovcc.i_cond != cond) return(0); /* success */
|
||||
rs1 = fs->fs_regs[rs2];
|
||||
goto mov;
|
||||
case FMVRZ >> 2:
|
||||
/* Presume we're curproc */
|
||||
rs1 = instr.i_fmovr.i_rs1;
|
||||
if (rs1 != 0 && (int64_t)curproc->p_md.md_tf->tf_global[rs1] != 0)
|
||||
return (0); /* success */
|
||||
rs1 = fs->fs_regs[rs2];
|
||||
goto mov;
|
||||
case FMVRLEZ >> 2:
|
||||
/* Presume we're curproc */
|
||||
rs1 = instr.i_fmovr.i_rs1;
|
||||
if (rs1 != 0 && (int64_t)curproc->p_md.md_tf->tf_global[rs1] > 0)
|
||||
return (0); /* success */
|
||||
rs1 = fs->fs_regs[rs2];
|
||||
goto mov;
|
||||
case FMVRLZ >> 2:
|
||||
/* Presume we're curproc */
|
||||
rs1 = instr.i_fmovr.i_rs1;
|
||||
if (rs1 == 0 || (int64_t)curproc->p_md.md_tf->tf_global[rs1] >= 0)
|
||||
return (0); /* success */
|
||||
rs1 = fs->fs_regs[rs2];
|
||||
goto mov;
|
||||
case FMVRNZ >> 2:
|
||||
/* Presume we're curproc */
|
||||
rs1 = instr.i_fmovr.i_rs1;
|
||||
if (rs1 == 0 || (int64_t)curproc->p_md.md_tf->tf_global[rs1] == 0)
|
||||
return (0); /* success */
|
||||
rs1 = fs->fs_regs[rs2];
|
||||
goto mov;
|
||||
case FMVRGZ >> 2:
|
||||
/* Presume we're curproc */
|
||||
rs1 = instr.i_fmovr.i_rs1;
|
||||
if (rs1 == 0 || (int64_t)curproc->p_md.md_tf->tf_global[rs1] <= 0)
|
||||
return (0); /* success */
|
||||
rs1 = fs->fs_regs[rs2];
|
||||
goto mov;
|
||||
case FMVRGEZ >> 2:
|
||||
/* Presume we're curproc */
|
||||
rs1 = instr.i_fmovr.i_rs1;
|
||||
if (rs1 != 0 && (int64_t)curproc->p_md.md_tf->tf_global[rs1] < 0)
|
||||
return (0); /* success */
|
||||
rs1 = fs->fs_regs[rs2];
|
||||
goto mov;
|
||||
case FCMP >> 2:
|
||||
fpu_explode(fe, &fe->fe_f1, type, rs1);
|
||||
fpu_explode(fe, &fe->fe_f2, type, rs2);
|
||||
fpu_compare(fe, 0);
|
||||
goto cmpdone;
|
||||
|
||||
case FCMPE >> 2:
|
||||
fpu_explode(fe, &fe->fe_f1, type, rs1);
|
||||
fpu_explode(fe, &fe->fe_f2, type, rs2);
|
||||
fpu_compare(fe, 1);
|
||||
cmpdone:
|
||||
/*
|
||||
* The only possible exception here is NV; catch it
|
||||
* early and get out, as there is no result register.
|
||||
*/
|
||||
cx = fe->fe_cx;
|
||||
fsr = fe->fe_fsr | (cx << FSR_CX_SHIFT);
|
||||
if (cx != 0) {
|
||||
if (fsr & (FSR_NV << FSR_TEM_SHIFT)) {
|
||||
fs->fs_fsr = (fsr & ~FSR_FTT) |
|
||||
(FSR_TT_IEEE << FSR_FTT_SHIFT);
|
||||
return (FPE);
|
||||
}
|
||||
fsr |= FSR_NV << FSR_AX_SHIFT;
|
||||
}
|
||||
fs->fs_fsr = fsr;
|
||||
return (0);
|
||||
default:
|
||||
return (NOTFPU);
|
||||
}
|
||||
}
|
||||
switch (opf >>= 2) {
|
||||
|
||||
default:
|
||||
@ -283,7 +394,10 @@ fpu_execute(fe, instr)
|
||||
case FABS >> 2:
|
||||
rs1 = fs->fs_regs[rs2] & ~(1 << 31);
|
||||
mov:
|
||||
fs->fs_regs[rd] = rs1;
|
||||
i = 1<<type;
|
||||
fs->fs_regs[rd++] = rs1;
|
||||
while (--i)
|
||||
fs->fs_regs[rd++] = fs->fs_regs[++rs2];
|
||||
fs->fs_fsr = fe->fe_fsr;
|
||||
return (0); /* success */
|
||||
|
||||
@ -316,34 +430,6 @@ fpu_execute(fe, instr)
|
||||
fp = fpu_div(fe);
|
||||
break;
|
||||
|
||||
case FCMP >> 2:
|
||||
fpu_explode(fe, &fe->fe_f1, type, rs1);
|
||||
fpu_explode(fe, &fe->fe_f2, type, rs2);
|
||||
fpu_compare(fe, 0);
|
||||
goto cmpdone;
|
||||
|
||||
case FCMPE >> 2:
|
||||
fpu_explode(fe, &fe->fe_f1, type, rs1);
|
||||
fpu_explode(fe, &fe->fe_f2, type, rs2);
|
||||
fpu_compare(fe, 1);
|
||||
cmpdone:
|
||||
/*
|
||||
* The only possible exception here is NV; catch it
|
||||
* early and get out, as there is no result register.
|
||||
*/
|
||||
cx = fe->fe_cx;
|
||||
fsr = fe->fe_fsr | (cx << FSR_CX_SHIFT);
|
||||
if (cx != 0) {
|
||||
if (fsr & (FSR_NV << FSR_TEM_SHIFT)) {
|
||||
fs->fs_fsr = (fsr & ~FSR_FTT) |
|
||||
(FSR_TT_IEEE << FSR_FTT_SHIFT);
|
||||
return (FPE);
|
||||
}
|
||||
fsr |= FSR_NV << FSR_AX_SHIFT;
|
||||
}
|
||||
fs->fs_fsr = fsr;
|
||||
return (0);
|
||||
|
||||
case FSMULD >> 2:
|
||||
case FDMULX >> 2:
|
||||
if (type == FTYPE_EXT)
|
||||
@ -354,13 +440,23 @@ fpu_execute(fe, instr)
|
||||
fp = fpu_mul(fe);
|
||||
break;
|
||||
|
||||
case FXTOS >> 2:
|
||||
case FXTOD >> 2:
|
||||
case FXTOQ >> 2:
|
||||
type = FTYPE_LNG;
|
||||
fpu_explode(fe, fp = &fe->fe_f1, type, rs2);
|
||||
type = opf & 3; /* sneaky; depends on instruction encoding */
|
||||
break;
|
||||
case FTOS >> 2:
|
||||
case FTOD >> 2:
|
||||
case FTOX >> 2:
|
||||
case FTOQ >> 2:
|
||||
case FTOI >> 2:
|
||||
fpu_explode(fe, fp = &fe->fe_f1, type, rs2);
|
||||
type = opf & 3; /* sneaky; depends on instruction encoding */
|
||||
break;
|
||||
case FTOX >> 2:
|
||||
fpu_explode(fe, fp = &fe->fe_f1, type, rs2);
|
||||
type = FTYPE_LNG;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -385,7 +481,7 @@ fpu_execute(fe, instr)
|
||||
}
|
||||
fs->fs_fsr = fsr;
|
||||
fs->fs_regs[rd] = space[0];
|
||||
if (type >= FTYPE_DBL) {
|
||||
if (type >= FTYPE_DBL || type == FTYPE_LNG) {
|
||||
fs->fs_regs[rd + 1] = space[1];
|
||||
if (type > FTYPE_DBL) {
|
||||
fs->fs_regs[rd + 2] = space[2];
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: fpu_emu.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */
|
||||
/* $NetBSD: fpu_emu.h,v 1.2 1998/09/22 02:48:42 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -90,6 +90,7 @@ struct fpn {
|
||||
#define FP_NMANT 115 /* total bits in mantissa (incl g,r) */
|
||||
#define FP_NG 2 /* number of low-order guard bits */
|
||||
#define FP_LG ((FP_NMANT - 1) & 31) /* log2(1.0) for fp_mant[0] */
|
||||
#define FP_LG2 ((FP_NMANT - 1) & 63) /* log2(1.0) for fp_mant[0] and fp_mant[1] */
|
||||
#define FP_QUIETBIT (1 << (FP_LG - 1)) /* Quiet bit in NaNs (0.5) */
|
||||
#define FP_1 (1 << FP_LG) /* 1.0 in fp_mant[0] */
|
||||
#define FP_2 (1 << (FP_LG + 1)) /* 2.0 in fp_mant[0] */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: fpu_explode.c,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */
|
||||
/* $NetBSD: fpu_explode.c,v 1.2 1998/09/22 02:48:43 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -105,6 +105,31 @@ fpu_itof(fp, i)
|
||||
return (FPC_NUM);
|
||||
}
|
||||
|
||||
/*
|
||||
* 64-bit int -> fpn.
|
||||
*/
|
||||
int
|
||||
fpu_xitof(fp, i)
|
||||
register struct fpn *fp;
|
||||
register u_int64_t i;
|
||||
{
|
||||
|
||||
if (i == 0)
|
||||
return (FPC_ZERO);
|
||||
/*
|
||||
* The value FP_1 represents 2^FP_LG, so set the exponent
|
||||
* there and let normalization fix it up. Convert negative
|
||||
* numbers to sign-and-magnitude. Note that this relies on
|
||||
* fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
|
||||
*/
|
||||
fp->fp_exp = FP_LG2;
|
||||
*((int64_t*)fp->fp_mant) = (int64_t)i < 0 ? -i : i;
|
||||
fp->fp_mant[2] = 0;
|
||||
fp->fp_mant[3] = 0;
|
||||
fpu_norm(fp);
|
||||
return (FPC_NUM);
|
||||
}
|
||||
|
||||
#define mask(nbits) ((1 << (nbits)) - 1)
|
||||
|
||||
/*
|
||||
@ -220,13 +245,20 @@ fpu_explode(fe, fp, type, reg)
|
||||
int type, reg;
|
||||
{
|
||||
register u_int s, *space;
|
||||
u_int64_t l, *xspace;
|
||||
|
||||
space = &fe->fe_fpstate->fs_regs[reg];
|
||||
xspace = &fe->fe_fpstate->fs_regs[reg & ~1];
|
||||
s = space[0];
|
||||
l = xspace[0];
|
||||
fp->fp_sign = s >> 31;
|
||||
fp->fp_sticky = 0;
|
||||
switch (type) {
|
||||
|
||||
case FTYPE_LNG:
|
||||
s = fpu_xitof(fp, l);
|
||||
break;
|
||||
|
||||
case FTYPE_INT:
|
||||
s = fpu_itof(fp, s);
|
||||
break;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: fpu_extern.h,v 1.2 1998/09/05 15:28:09 christos Exp $ */
|
||||
/* $NetBSD: fpu_extern.h,v 1.3 1998/09/22 02:48:43 eeh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995 The NetBSD Foundation, Inc.
|
||||
@ -59,6 +59,7 @@ struct fpn *fpu_div __P((struct fpemu *));
|
||||
|
||||
/* fpu_explode.c */
|
||||
int fpu_itof __P((struct fpn *, u_int));
|
||||
int fpu_ixtof __P((struct fpn *, u_int64_t));
|
||||
int fpu_stof __P((struct fpn *, u_int));
|
||||
int fpu_dtof __P((struct fpn *, u_int, u_int ));
|
||||
int fpu_xtof __P((struct fpn *, u_int, u_int , u_int , u_int ));
|
||||
@ -66,6 +67,7 @@ void fpu_explode __P((struct fpemu *, struct fpn *, int, int ));
|
||||
|
||||
/* fpu_implode.c */
|
||||
u_int fpu_ftoi __P((struct fpemu *, struct fpn *));
|
||||
u_int fpu_ftoix __P((struct fpemu *, struct fpn *, u_int *));
|
||||
u_int fpu_ftos __P((struct fpemu *, struct fpn *));
|
||||
u_int fpu_ftod __P((struct fpemu *, struct fpn *, u_int *));
|
||||
u_int fpu_ftox __P((struct fpemu *, struct fpn *, u_int *));
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: fpu_implode.c,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */
|
||||
/* $NetBSD: fpu_implode.c,v 1.2 1998/09/22 02:48:43 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -238,6 +238,57 @@ fpu_ftoi(fe, fp)
|
||||
return (0x7fffffff + sign);
|
||||
}
|
||||
|
||||
/*
|
||||
* fpn -> extended int (high bits of int value returned as return value).
|
||||
*
|
||||
* N.B.: this conversion always rounds towards zero (this is a peculiarity
|
||||
* of the SPARC instruction set).
|
||||
*/
|
||||
u_int
|
||||
fpu_ftoxi(fe, fp, res)
|
||||
struct fpemu *fe;
|
||||
register struct fpn *fp;
|
||||
u_int *res;
|
||||
{
|
||||
register u_int64_t i;
|
||||
register int sign, exp;
|
||||
|
||||
sign = fp->fp_sign;
|
||||
switch (fp->fp_class) {
|
||||
|
||||
case FPC_ZERO:
|
||||
res[1] = 0;
|
||||
return (0);
|
||||
|
||||
case FPC_NUM:
|
||||
/*
|
||||
* If exp >= 2^64, overflow. Otherwise shift value right
|
||||
* into last mantissa word (this will not exceed 0xffffffffffffffff),
|
||||
* shifting any guard and round bits out into the sticky
|
||||
* bit. Then ``round'' towards zero, i.e., just set an
|
||||
* inexact exception if sticky is set (see round()).
|
||||
* If the result is > 0x8000000000000000, or is positive and equals
|
||||
* 0x8000000000000000, overflow; otherwise the last fraction word
|
||||
* is the result.
|
||||
*/
|
||||
if ((exp = fp->fp_exp) >= 64)
|
||||
break;
|
||||
/* NB: the following includes exp < 0 cases */
|
||||
if (fpu_shr(fp, FP_NMANT - 1 - exp) != 0)
|
||||
fe->fe_cx |= FSR_NX;
|
||||
i = (fp->fp_mant[2]<<32)|fp->fp_mant[3];
|
||||
if (i >= ((u_int64_t)0x8000000000000000LL + sign))
|
||||
break;
|
||||
return (sign ? -i : i);
|
||||
|
||||
default: /* Inf, qNaN, sNaN */
|
||||
break;
|
||||
}
|
||||
/* overflow: replace any inexact exception with invalid */
|
||||
fe->fe_cx = (fe->fe_cx & ~FSR_NX) | FSR_NV;
|
||||
return (0x7fffffffffffffffLL + sign);
|
||||
}
|
||||
|
||||
/*
|
||||
* fpn -> single (32 bit single returned as return value).
|
||||
* We assume <= 29 bits in a single-precision fraction (1.f part).
|
||||
@ -457,6 +508,10 @@ fpu_implode(fe, fp, type, space)
|
||||
|
||||
switch (type) {
|
||||
|
||||
case FTYPE_LNG:
|
||||
space[0] = fpu_ftoxi(fe, fp, space);
|
||||
break;
|
||||
|
||||
case FTYPE_INT:
|
||||
space[0] = fpu_ftoi(fe, fp);
|
||||
break;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: frame.h,v 1.4 1998/09/07 23:46:26 eeh Exp $ */
|
||||
/* $NetBSD: frame.h,v 1.5 1998/09/22 02:48:43 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -99,17 +99,15 @@ struct frame64 {
|
||||
/*
|
||||
* SVR4 reserves a bunch of extra stuff.
|
||||
*/
|
||||
int64_t fr_argd[6]; /* `arg dump area' (lunacy) */
|
||||
int64_t fr_argx[1]; /* arg extension (args 7..n; variable size) */
|
||||
int64_t fr_argd[6]; /* `register save area' (lunacy) */
|
||||
int64_t fr_argx[0]; /* arg extension (args 7..n; variable size) */
|
||||
};
|
||||
#endif
|
||||
|
||||
#define v9next_frame(f) ((struct frame64*)(f->fr_fp+BIAS))
|
||||
/*
|
||||
* CC64FSZ (C Compiler 64-bit Frame SiZe) is the size of a stack frame used
|
||||
* by the compiler in 64-bit mode. It is (16+1+6)*8; space for 8 ins, 8 outs,
|
||||
* one "hidden parameter", and 6 extended words where the callee can save its
|
||||
* arguments.
|
||||
* by the compiler in 64-bit mode. It is (16)*8; space for 8 ins, 8 outs.
|
||||
*/
|
||||
#define CC64FSZ 176
|
||||
#define STACK_ALIGN64 16
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: instr.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */
|
||||
/* $NetBSD: instr.h,v 1.2 1998/09/22 02:48:43 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -257,6 +257,52 @@ union instr {
|
||||
u_int i_rs2:5; /* source register 2 */
|
||||
} i_opf;
|
||||
|
||||
/*
|
||||
* Format 4 instructions (movcc, fmovr, fmovcc, and tcc). The
|
||||
* second-level decode almost always makes use of an `rd' and either
|
||||
* `rs1' or `cond'.
|
||||
*
|
||||
* Beyond that, the low 14 bits may be broken up in one of three
|
||||
* different ways, if at all:
|
||||
* 1 bit of imm=0 + 8 bits of asi + 5 bits of rs2 [reg & mem]
|
||||
* 1 bit of imm=1 + 13 bits of signed immediate [reg & mem]
|
||||
* 9 bits of copressor `opf' opcode + 5 bits of rs2 [reg only] */
|
||||
struct {
|
||||
u_int :2; /* 10 */
|
||||
u_int i_rd:5; /* destination register */
|
||||
u_int i_op3:6; /* second-level decode */
|
||||
u_int i_rs1:5; /* source register 1 */
|
||||
u_int i_low14:14; /* varies */
|
||||
} i_op4;
|
||||
|
||||
/*
|
||||
* Move fp register on condition codes.
|
||||
*/
|
||||
struct {
|
||||
u_int :2; /* 10 */
|
||||
u_int i_rd:5; /* destination register */
|
||||
u_int i_op3:6; /* second-level decode */
|
||||
u_int :1;
|
||||
u_int i_cond:4; /* condition */
|
||||
u_int i_opf_cc:3; /* condition code register */
|
||||
u_int i_opf_low:6; /* third level decode */
|
||||
u_int i_rs2:5; /* source register */
|
||||
} i_fmovcc;
|
||||
|
||||
/*
|
||||
* Move fp register on integer register.
|
||||
*/
|
||||
struct {
|
||||
u_int :2; /* 10 */
|
||||
u_int i_rd:5; /* destination register */
|
||||
u_int i_op3:6; /* second-level decode */
|
||||
u_int i_rs1:5; /* source register 1 */
|
||||
u_int :1;
|
||||
u_int i_rcond:3; /* register condition */
|
||||
u_int i_opf_low:6;
|
||||
u_int i_rs2:5; /* source register 2 */
|
||||
} i_fmovr;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
@ -347,14 +393,33 @@ union instr {
|
||||
#define FCMPE 0x54
|
||||
#define FSMULD 0x68
|
||||
#define FDMULX 0x6c
|
||||
#define FTOX 0x80
|
||||
#define FXTOS 0x84
|
||||
#define FXTOD 0x88
|
||||
#define FXTOQ 0x8c
|
||||
#define FTOS 0xc4
|
||||
#define FTOD 0xc8
|
||||
#define FTOX 0xcc
|
||||
#define FTOQ 0xcc
|
||||
#define FTOI 0xd0
|
||||
|
||||
/* These are in FPop2 space */
|
||||
#define FMVFC0 0x00
|
||||
#define FMVRZ 0x24
|
||||
#define FMVFC1 0x40
|
||||
#define FMVRLEZ 0x44
|
||||
#define FMVRLZ 0x64
|
||||
#define FMVFC2 0x80
|
||||
#define FMVRNZ 0xa4
|
||||
#define FMVFC3 0xc0
|
||||
#define FMVRGZ 0xc4
|
||||
#define FMVRGEZ 0xe4
|
||||
#define FMVIC 0x100
|
||||
#define FMVXC 0x180
|
||||
|
||||
/*
|
||||
* FPU data types.
|
||||
*/
|
||||
#define FTYPE_LNG -1 /* data = 64-bit signed long integer */
|
||||
#define FTYPE_INT 0 /* data = 32-bit signed integer */
|
||||
#define FTYPE_SNG 1 /* data = 32-bit float */
|
||||
#define FTYPE_DBL 2 /* data = 64-bit double */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pmap.h,v 1.7 1998/09/13 16:02:48 eeh Exp $ */
|
||||
/* $NetBSD: pmap.h,v 1.8 1998/09/22 02:48:43 eeh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
|
||||
@ -119,14 +119,6 @@ struct pmap {
|
||||
*/
|
||||
paddr_t pm_physaddr; /* physical address of pm_segs */
|
||||
int64_t *pm_segs;
|
||||
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
|
||||
/*
|
||||
* Here's a really ugly hack: all processes now allocate
|
||||
* one 8K page that is mapped little endian so we can do the
|
||||
* syscall args properly.
|
||||
*/
|
||||
void *syscallargs;
|
||||
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1,7 +1,8 @@
|
||||
/* $NetBSD: setjmp.h,v 1.1.1.1 1998/06/20 04:58:52 eeh Exp $ */
|
||||
/* $NetBSD: setjmp.h,v 1.2 1998/09/22 02:48:43 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* machine/setjmp.h: machine dependent setjmp-related information.
|
||||
*/
|
||||
|
||||
#define _JBLEN 10 /* size, in longs, of a jmp_buf */
|
||||
#define _JBLEN 14 /* size, in longs, of a jmp_buf */
|
||||
/* A sigcontext is 10 longs */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: signal.h,v 1.4 1998/09/17 04:51:29 thorpej Exp $ */
|
||||
/* $NetBSD: signal.h,v 1.5 1998/09/22 02:48:43 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -65,6 +65,7 @@ typedef int sig_atomic_t;
|
||||
* All machines must have an sc_onstack and sc_mask.
|
||||
*/
|
||||
#if defined(__LIBC12_SOURCE__) || defined(_KERNEL)
|
||||
/* Since we didn't start at 1.3, this is only for sparc32 code */
|
||||
struct sigcontext13 {
|
||||
int sc_onstack; /* sigstack state to restore */
|
||||
int sc_mask; /* signal mask to restore (old style) */
|
||||
@ -72,35 +73,22 @@ struct sigcontext13 {
|
||||
int sc_sp; /* %sp to restore */
|
||||
int sc_pc; /* pc to restore */
|
||||
int sc_npc; /* npc to restore */
|
||||
int sc_psr; /* psr to restore */
|
||||
int sc_psr; /* pstate to restore */
|
||||
int sc_g1; /* %g1 to restore */
|
||||
int sc_o0; /* %o0 to restore */
|
||||
};
|
||||
#endif /* __LIBC12_SOURCE__ || _KERNEL */
|
||||
struct sigcontext {
|
||||
#ifdef _LP64
|
||||
/* XXX Could just use register_t, but it's unsigned! */
|
||||
long sc_onstack; /* sigstack state to restore */
|
||||
long __sc_mask13; /* signal mask to restore (old style) */
|
||||
long sc_sp; /* %sp to restore */
|
||||
long sc_pc; /* pc to restore */
|
||||
long sc_npc; /* npc to restore */
|
||||
long sc_psr; /* psr to restore */
|
||||
long sc_g1; /* %g1 to restore */
|
||||
long sc_o0; /* %o0 to restore */
|
||||
sigset_t sc_mask; /* signal mask to restore (new style) */
|
||||
#else
|
||||
int sc_onstack; /* sigstack state to restore */
|
||||
int __sc_mask13; /* signal mask to restore (old style) */
|
||||
/* begin machine dependent portion */
|
||||
int sc_sp; /* %sp to restore */
|
||||
int sc_pc; /* pc to restore */
|
||||
int sc_npc; /* npc to restore */
|
||||
int sc_psr; /* psr to restore */
|
||||
int sc_g1; /* %g1 to restore */
|
||||
int sc_o0; /* %o0 to restore */
|
||||
long sc_sp; /* %sp to restore */
|
||||
long sc_pc; /* pc to restore */
|
||||
long sc_npc; /* npc to restore */
|
||||
long sc_tstate; /* pstate to restore */
|
||||
long sc_g1; /* %g1 to restore */
|
||||
long sc_o0; /* %o0 to restore */
|
||||
sigset_t sc_mask; /* signal mask to restore (new style) */
|
||||
#endif /* _LP64 */
|
||||
};
|
||||
#else /* _LOCORE */
|
||||
#define SC_SP_OFFSET 8
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: db_interface.c,v 1.8 1998/09/09 02:48:15 eeh Exp $ */
|
||||
/* $NetBSD: db_interface.c,v 1.9 1998/09/22 02:48:43 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Mach Operating System
|
||||
@ -124,6 +124,7 @@ void db_lock __P((db_expr_t, int, db_expr_t, char *));
|
||||
void db_traptrace __P((db_expr_t, int, db_expr_t, char *));
|
||||
void db_dump_buf __P((db_expr_t, int, db_expr_t, char *));
|
||||
void db_dump_espcmd __P((db_expr_t, int, db_expr_t, char *));
|
||||
void db_watch __P((db_expr_t, int, db_expr_t, char *));
|
||||
|
||||
static void db_dump_pmap __P((struct pmap*));
|
||||
|
||||
@ -140,6 +141,9 @@ kdb_kbd_trap(tf)
|
||||
}
|
||||
}
|
||||
|
||||
/* Flip this to turn on traptrace */
|
||||
int traptrace_enabled = 0;
|
||||
|
||||
/*
|
||||
* kdb_trap - field a TRACE or BPT trap
|
||||
*/
|
||||
@ -157,7 +161,9 @@ kdb_trap(type, tf)
|
||||
} ts[5];
|
||||
extern int savetstate(struct trapstate ts[]);
|
||||
extern void restoretstate(int tl, struct trapstate ts[]);
|
||||
extern int trap_trace_dis;
|
||||
|
||||
trap_trace_dis = 1;
|
||||
fb_unblank();
|
||||
|
||||
switch (type) {
|
||||
@ -170,10 +176,12 @@ kdb_trap(type, tf)
|
||||
default:
|
||||
printf("kernel trap %x: %s\n", type, trap_type[type & 0x1ff]);
|
||||
if (db_recover != 0) {
|
||||
#if 0
|
||||
#ifdef _LP64
|
||||
/* For now, don't get into infinite DDB trap loop */
|
||||
printf("Faulted in DDB; going to OBP...\n");
|
||||
OF_enter();
|
||||
#endif
|
||||
#endif
|
||||
db_error("Faulted in DDB; continuing...\n");
|
||||
OF_enter();
|
||||
@ -182,10 +190,6 @@ kdb_trap(type, tf)
|
||||
}
|
||||
|
||||
/* Should switch to kdb`s own stack here. */
|
||||
{
|
||||
extern int trap_trace_dis;
|
||||
trap_trace_dis = 1;
|
||||
}
|
||||
write_all_windows();
|
||||
|
||||
ddb_regs.ddb_tf = *tf;
|
||||
@ -238,10 +242,7 @@ kdb_trap(type, tf)
|
||||
*(struct frame *)tf->tf_out[6] = ddb_regs.ddb_fr;
|
||||
*tf = ddb_regs.ddb_tf;
|
||||
#endif
|
||||
{
|
||||
extern int trap_trace_dis;
|
||||
trap_trace_dis = 0;
|
||||
}
|
||||
trap_trace_dis = traptrace_enabled;
|
||||
|
||||
return (1);
|
||||
}
|
||||
@ -590,30 +591,30 @@ db_dump_pcb(addr, have_addr, count, modif)
|
||||
if (have_addr)
|
||||
pcb = (struct pcb*) addr;
|
||||
|
||||
db_printf("pcb@%x sp:%x pc:%x cwp:%d pil:%d nsaved:%x onfault:%p\nlastcall:%s\nfull windows:\n",
|
||||
pcb, (int)pcb->pcb_sp, (int)pcb->pcb_pc, pcb->pcb_cwp,
|
||||
db_printf("pcb@%x sp:%p pc:%p cwp:%d pil:%d nsaved:%x onfault:%p\nlastcall:%s\nfull windows:\n",
|
||||
pcb, pcb->pcb_sp, pcb->pcb_pc, pcb->pcb_cwp,
|
||||
pcb->pcb_pil, pcb->pcb_nsaved, pcb->pcb_onfault,
|
||||
(pcb->lastcall)?pcb->lastcall:"Null");
|
||||
|
||||
for (i=0; i<pcb->pcb_nsaved; i++) {
|
||||
db_printf("win %d: at %p:%p local, in\n", i,
|
||||
pcb->pcb_rw[i+1].rw_in[6]);
|
||||
db_printf("%8x:%8x %8x:%8x %8x:%8x %8x:%8x\n",
|
||||
db_printf("%16lx %16lx %16lx %16lx\n",
|
||||
pcb->pcb_rw[i].rw_local[0],
|
||||
pcb->pcb_rw[i].rw_local[1],
|
||||
pcb->pcb_rw[i].rw_local[2],
|
||||
pcb->pcb_rw[i].rw_local[3]);
|
||||
db_printf("%8x:%8x %8x:%8x %8x:%8x %8x:%8x\n",
|
||||
db_printf("%16lx %16lx %16lx %16lx\n",
|
||||
pcb->pcb_rw[i].rw_local[4],
|
||||
pcb->pcb_rw[i].rw_local[5],
|
||||
pcb->pcb_rw[i].rw_local[6],
|
||||
pcb->pcb_rw[i].rw_local[7]);
|
||||
db_printf("%8x:%8x %8x:%8x %8x:%8x %8x:%8x\n",
|
||||
db_printf("%16lx %16lx %16lx %16lx\n",
|
||||
pcb->pcb_rw[i].rw_in[0],
|
||||
pcb->pcb_rw[i].rw_in[1],
|
||||
pcb->pcb_rw[i].rw_in[2],
|
||||
pcb->pcb_rw[i].rw_in[3]);
|
||||
db_printf("%8x:%8x %8x:%8x %8x:%8x %8x:%8x\n",
|
||||
db_printf("%16lx %16lx %16lx %16lx\n",
|
||||
pcb->pcb_rw[i].rw_in[4],
|
||||
pcb->pcb_rw[i].rw_in[5],
|
||||
pcb->pcb_rw[i].rw_in[6],
|
||||
@ -666,41 +667,90 @@ db_traptrace(addr, have_addr, count, modif)
|
||||
extern struct traptrace {
|
||||
unsigned short tl:3, ns:4, tt:9;
|
||||
unsigned short pid;
|
||||
int tstate;
|
||||
int tsp;
|
||||
int tpc;
|
||||
u_int tstate;
|
||||
u_int tsp;
|
||||
u_int tpc;
|
||||
} trap_trace[], trap_trace_end[];
|
||||
int i, j;
|
||||
|
||||
if (have_addr) {
|
||||
i=addr;
|
||||
db_printf("%d:%d p:%d:%d tt:%x ts:%1x sp:%p tpc:%p ", i,
|
||||
db_printf("%d:%d p:%d:%d tt:%x ts:%lx sp:%p tpc:%p ", i,
|
||||
(int)trap_trace[i].tl, (int)trap_trace[i].pid,
|
||||
(int)trap_trace[i].ns, (int)trap_trace[i].tt,
|
||||
(int)trap_trace[i].tstate, (int)trap_trace[i].tsp,
|
||||
(int)trap_trace[i].tpc);
|
||||
db_printsym((int)trap_trace[i].tpc, DB_STGY_PROC);
|
||||
(u_long)trap_trace[i].tstate, (u_long)trap_trace[i].tsp,
|
||||
(u_long)trap_trace[i].tpc);
|
||||
db_printsym((u_long)trap_trace[i].tpc, DB_STGY_PROC);
|
||||
db_printf(": ");
|
||||
if ((int)trap_trace[i].tpc && !(trap_trace[i].tpc&0x3)) {
|
||||
db_disasm((int)trap_trace[i].tpc, 0);
|
||||
if (trap_trace[i].tpc && !(trap_trace[i].tpc&0x3)) {
|
||||
db_disasm((u_long)trap_trace[i].tpc, 0);
|
||||
} else db_printf("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0; &trap_trace[i] < &trap_trace_end[0] ; i++) {
|
||||
db_printf("%d:%d p:%d:%d tt:%x ts:%1x sp:%p tpc:%p ", i,
|
||||
db_printf("%d:%d p:%d:%d tt:%x ts:%lx sp:%p tpc:%p ", i,
|
||||
(int)trap_trace[i].tl, (int)trap_trace[i].pid,
|
||||
(int)trap_trace[i].ns, (int)trap_trace[i].tt,
|
||||
(int)trap_trace[i].tstate, (int)trap_trace[i].tsp,
|
||||
(int)trap_trace[i].tpc);
|
||||
db_printsym((int)trap_trace[i].tpc, DB_STGY_PROC);
|
||||
(u_long)trap_trace[i].tstate, (u_long)trap_trace[i].tsp,
|
||||
(u_long)trap_trace[i].tpc);
|
||||
db_printsym((u_long)trap_trace[i].tpc, DB_STGY_PROC);
|
||||
db_printf(": ");
|
||||
if ((int)trap_trace[i].tpc && !(trap_trace[i].tpc&0x3)) {
|
||||
db_disasm((int)trap_trace[i].tpc, 0);
|
||||
if (trap_trace[i].tpc && !(trap_trace[i].tpc&0x3)) {
|
||||
db_disasm((u_long)trap_trace[i].tpc, 0);
|
||||
} else db_printf("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Use physical or virtual watchpoint registers -- ugh
|
||||
*/
|
||||
void
|
||||
db_watch(addr, have_addr, count, modif)
|
||||
db_expr_t addr;
|
||||
int have_addr;
|
||||
db_expr_t count;
|
||||
char *modif;
|
||||
{
|
||||
int phys = 0;
|
||||
|
||||
#define WATCH_VR (1L<<22)
|
||||
#define WATCH_VW (1L<<21)
|
||||
#define WATCH_PR (1L<<24)
|
||||
#define WATCH_PW (1L<<23)
|
||||
#define WATCH_PM (0xffffL<<33)
|
||||
#define WATCH_VM (0xffffL<<25)
|
||||
|
||||
{
|
||||
register char c, *cp = modif;
|
||||
if (modif)
|
||||
while ((c = *cp++) != 0)
|
||||
if (c == 'p')
|
||||
phys = 1;
|
||||
}
|
||||
if (have_addr) {
|
||||
/* turn on the watchpoint */
|
||||
int64_t tmp = ldxa(0, ASI_MCCR);
|
||||
|
||||
if (phys) {
|
||||
tmp &= ~(WATCH_PM|WATCH_PR|WATCH_PW);
|
||||
stxa(PHYSICAL_WATCHPOINT, ASI_DMMU, addr);
|
||||
} else {
|
||||
tmp &= ~(WATCH_VM|WATCH_VR|WATCH_VW);
|
||||
stxa(VIRTUAL_WATCHPOINT, ASI_DMMU, addr);
|
||||
}
|
||||
stxa(0, ASI_MCCR, tmp);
|
||||
} else {
|
||||
/* turn off the watchpoint */
|
||||
int64_t tmp = ldxa(0, ASI_MCCR);
|
||||
if (phys) tmp &= ~(WATCH_PM);
|
||||
else tmp &= ~(WATCH_VM);
|
||||
stxa(0, ASI_MCCR, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include <sys/buf.h>
|
||||
|
||||
void
|
||||
@ -769,6 +819,7 @@ struct db_command sparc_db_command_table[] = {
|
||||
{ "window", db_dump_window, 0, 0 },
|
||||
{ "traptrace", db_traptrace, 0, 0 },
|
||||
{ "uvmdump", db_uvmhistdump, 0, 0 },
|
||||
{ "watch", db_watch, 0, 0 },
|
||||
{ (char *)0, }
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: db_trace.c,v 1.5 1998/09/11 00:16:59 eeh Exp $ */
|
||||
/* $NetBSD: db_trace.c,v 1.6 1998/09/22 02:48:44 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Mach Operating System
|
||||
@ -263,7 +263,7 @@ db_dump_stack(addr, have_addr, count, modif)
|
||||
db_printf("Window %x ", i);
|
||||
db_print_window(frame - BIAS);
|
||||
if (!INKERNEL(((struct frame64 *)(frame))))
|
||||
copyin(((caddr_t)&((struct frame64 *)frame)->fr_fp)+4, &frame, sizeof(frame));
|
||||
copyin(((caddr_t)&((struct frame64 *)frame)->fr_fp), &frame, sizeof(frame));
|
||||
else
|
||||
frame = ((struct frame64 *)frame)->fr_fp;
|
||||
} else {
|
||||
|
@ -687,8 +687,8 @@ _C_LABEL(trapbase):
|
||||
UTRAP(0x056); UTRAP(0x057); UTRAP(0x058); UTRAP(0x059); UTRAP(0x05a); UTRAP(0x05b)
|
||||
UTRAP(0x05c); UTRAP(0x05d); UTRAP(0x05e); UTRAP(0x05f)
|
||||
VTRAP(0x060, interrupt_vector); ! 060 = interrupt vector
|
||||
UTRAP(T_PA_WATCHPT) ! 061 = physical address data watchpoint
|
||||
UTRAP(T_VA_WATCHPT) ! 062 = virtual address data watchpoint
|
||||
TRAP(T_PA_WATCHPT) ! 061 = physical address data watchpoint
|
||||
TRAP(T_VA_WATCHPT) ! 062 = virtual address data watchpoint
|
||||
UTRAP(T_ECCERR) ! We'll implement this one later
|
||||
ufast_IMMU_miss: ! 063 = fast instr access MMU miss
|
||||
TRACEFLT ! DEBUG
|
||||
@ -913,8 +913,8 @@ kdatafault:
|
||||
UTRAP(0x031) ! 031 = data MMU miss -- no MMU
|
||||
VTRAP(T_DATA_ERROR, winfault) ! 032 = data fetch fault
|
||||
VTRAP(T_DATA_PROT, winfault) ! 033 = data fetch fault
|
||||
! TRAP(T_ALIGN) ! 034 = address alignment error -- we could fix it inline...
|
||||
sir; nop; TA8 ! DEBUG -- trap all kernel alignment errors
|
||||
TRAP(T_ALIGN) ! 034 = address alignment error -- we could fix it inline...
|
||||
! sir; nop; TA8 ! DEBUG -- trap all kernel alignment errors
|
||||
TRAP(T_LDDF_ALIGN) ! 035 = LDDF address alignment error -- we could fix it inline...
|
||||
TRAP(T_STDF_ALIGN) ! 036 = STDF address alignment error -- we could fix it inline...
|
||||
TRAP(T_PRIVACT) ! 037 = privileged action
|
||||
@ -940,8 +940,8 @@ kdatafault:
|
||||
UTRAP(0x056); UTRAP(0x057); UTRAP(0x058); UTRAP(0x059); UTRAP(0x05a); UTRAP(0x05b)
|
||||
UTRAP(0x05c); UTRAP(0x05d); UTRAP(0x05e); UTRAP(0x05f)
|
||||
VTRAP(0x060, interrupt_vector); ! 060 = interrupt vector
|
||||
UTRAP(T_PA_WATCHPT) ! 061 = physical address data watchpoint
|
||||
UTRAP(T_VA_WATCHPT) ! 062 = virtual address data watchpoint
|
||||
TRAP(T_PA_WATCHPT) ! 061 = physical address data watchpoint
|
||||
TRAP(T_VA_WATCHPT) ! 062 = virtual address data watchpoint
|
||||
UTRAP(T_ECCERR) ! We'll implement this one later
|
||||
kfast_IMMU_miss: ! 063 = fast instr access MMU miss
|
||||
TRACEFLT ! DEBUG
|
||||
@ -3130,7 +3130,7 @@ softtrap:
|
||||
nop
|
||||
sethi %hi(_C_LABEL(cpcb)), %g7
|
||||
LDPTR [%g7 + %lo(_C_LABEL(cpcb))], %g7
|
||||
set USPACE-CC64FSZ-TF_SIZE, %g5
|
||||
set USPACE-CC64FSZ-TF_SIZE-STKB, %g5
|
||||
add %g7, %g5, %g6
|
||||
SET_SP_REDZONE(%g7, %g5)
|
||||
stx %g1, [%g6 + CC64FSZ + STKB + TF_FAULT] ! Generate a new trapframe
|
||||
@ -3446,25 +3446,25 @@ syscall_setup:
|
||||
stx %g2, [%sp + CC64FSZ + STKB + TF_G + ( 2*8)]
|
||||
rdpr %tstate, %g1
|
||||
stx %g3, [%sp + CC64FSZ + STKB + TF_G + ( 3*8)]
|
||||
rdpr %tnpc, %g3
|
||||
rdpr %tnpc, %o3
|
||||
stx %g4, [%sp + CC64FSZ + STKB + TF_G + ( 4*8)]
|
||||
rd %y, %g4
|
||||
rd %y, %o4
|
||||
stx %g5, [%sp + CC64FSZ + STKB + TF_G + ( 5*8)]
|
||||
stx %g6, [%sp + CC64FSZ + STKB + TF_G + ( 6*8)]
|
||||
CHKPT(%g5,%g6,0x31)
|
||||
wrpr %g0, 0, %tl ! return to tl=0
|
||||
wrpr %g0, 0, %tl ! return to tl=0
|
||||
stx %g7, [%sp + CC64FSZ + STKB + TF_G + ( 7*8)]
|
||||
add %sp, CC64FSZ + STKB, %o1 ! (&tf)
|
||||
add %sp, CC64FSZ + STKB, %o1 ! (&tf)
|
||||
|
||||
stx %g1, [%sp + CC64FSZ + STKB + TF_TSTATE]
|
||||
stx %o2, [%sp + CC64FSZ + STKB + TF_PC]
|
||||
stx %g3, [%sp + CC64FSZ + STKB + TF_NPC]
|
||||
st %g4, [%sp + CC64FSZ + STKB + TF_Y]
|
||||
stx %o3, [%sp + CC64FSZ + STKB + TF_NPC]
|
||||
st %o4, [%sp + CC64FSZ + STKB + TF_Y]
|
||||
|
||||
rdpr %pil, %g5
|
||||
stb %g5, [%sp + CC64FSZ + STKB + TF_PIL]
|
||||
stb %g5, [%sp + CC64FSZ + STKB + TF_OLDPIL]
|
||||
|
||||
|
||||
!! In the medium anywhere model %g4 points to the start of the data segment.
|
||||
!! In our case we need to clear it before calling any C-code
|
||||
clr %g4
|
||||
@ -3905,6 +3905,13 @@ zshard:
|
||||
* If there are any, reload them
|
||||
*/
|
||||
return_from_trap:
|
||||
#ifdef DEBUG
|
||||
!! Make sure we don't have pc == npc or we suck.
|
||||
ldx [%sp + CC64FSZ + STKB + TF_PC], %g2
|
||||
ldx [%sp + CC64FSZ + STKB + TF_NPC], %g3
|
||||
cmp %g2, %g3
|
||||
tz %icc, 1
|
||||
#endif
|
||||
#ifdef NOTDEF_DEBUG
|
||||
mov %i6, %o1
|
||||
save %sp, -CC64FSZ, %sp
|
||||
@ -5315,7 +5322,9 @@ _C_LABEL(sigcode):
|
||||
* enabled and dirty.
|
||||
*/
|
||||
rd %fprs, %l0
|
||||
btst 1, %l0 ! test dl
|
||||
btst 3, %l0 ! All clean?
|
||||
bz,pt %icc, 2f
|
||||
btst 1, %l0 ! test dl
|
||||
bz,pt %icc, 1f
|
||||
btst 2, %l0 ! test du
|
||||
|
||||
@ -5334,17 +5343,18 @@ _C_LABEL(sigcode):
|
||||
inc BLOCK_SIZE, %l0
|
||||
stda %f48, [%l0] ASI_BLK_COMMIT_P
|
||||
2:
|
||||
ldx [%fp + BIAS + 64], %o0 ! sig
|
||||
ldx [%fp + BIAS + 64], %o1 ! code
|
||||
ldx [%fp + BIAS + 76], %o3 ! arg3
|
||||
call %g1 ! (*sa->sa_handler)(sig,code,scp,arg3)
|
||||
add %fp, BIAS + 64 + 16, %o2 ! scp
|
||||
lduw [%fp + BIAS + CC64FSZ], %o0 ! sig
|
||||
lduw [%fp + BIAS + CC64FSZ + 4], %o1 ! code
|
||||
call %g1 ! (*sa->sa_handler)(sig,code,scp)
|
||||
add %fp, BIAS + CC64FSZ + 8, %o2 ! scp
|
||||
|
||||
/*
|
||||
* Now that the handler has returned, re-establish all the state
|
||||
* we just saved above, then do a sigreturn.
|
||||
*/
|
||||
btst 1, %l0 ! test dl
|
||||
btst 3, %l0 ! All clean?
|
||||
bz,pt %icc, 2f
|
||||
btst 1, %l0 ! test dl
|
||||
bz,pt %icc, 1f
|
||||
btst 2, %l0 ! test du
|
||||
|
||||
@ -5355,7 +5365,7 @@ _C_LABEL(sigcode):
|
||||
inc BLOCK_SIZE, %o0
|
||||
ldda [%l0] ASI_BLK_P, %f16
|
||||
1:
|
||||
bz,pt %icc, 1f
|
||||
bz,pt %icc, 2f
|
||||
wr %l1, %g0, %y ! in any case, restore %y
|
||||
inc BLOCK_SIZE, %o0
|
||||
ldda [%l0] ASI_BLK_P, %f32
|
||||
@ -5370,7 +5380,7 @@ _C_LABEL(sigcode):
|
||||
mov %l7, %g7
|
||||
|
||||
restore %g0, SYS___sigreturn14, %g1 ! get registers back & set syscall #
|
||||
add %sp, 64 + 16, %o0 ! compute scp
|
||||
add %sp, BIAS + CC64FSZ + 8, %o0! compute scp
|
||||
t ST_SYSCALL ! sigreturn(scp)
|
||||
! sigreturn does not return unless it fails
|
||||
mov SYS_exit, %g1 ! exit(errno)
|
||||
@ -6597,12 +6607,12 @@ Lsw_scan:
|
||||
ld [%g2 + %lo(_C_LABEL(whichqs))], %o3
|
||||
|
||||
#ifndef POPC
|
||||
.globl ffstab
|
||||
.globl _C_LABEL(__ffstab)
|
||||
/*
|
||||
* Optimized inline expansion of `which = ffs(whichqs) - 1';
|
||||
* branches to idle if ffs(whichqs) was 0.
|
||||
*/
|
||||
set ffstab, %o2
|
||||
set _C_LABEL(__ffstab), %o2
|
||||
andcc %o3, 0xff, %o1 ! byte 0 zero?
|
||||
bz,a,pn %icc, 1f ! yes, try byte 1
|
||||
srl %o3, 8, %o0
|
||||
@ -8599,7 +8609,7 @@ ENTRY(ienab_bic)
|
||||
* The process switch code shares the table, so we just put the
|
||||
* whole thing here.
|
||||
*/
|
||||
ffstab:
|
||||
_C_LABEL(__ffstab):
|
||||
.byte -24,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 00-0f */
|
||||
.byte 5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 10-1f */
|
||||
.byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1 /* 20-2f */
|
||||
@ -8628,7 +8638,7 @@ ffstab:
|
||||
* that ffstab[0] must be -24 so that ffs(0) will return 0.
|
||||
*/
|
||||
ENTRY(ffs)
|
||||
set ffstab, %o2
|
||||
set _C_LABEL(__ffstab), %o2
|
||||
andcc %o0, 0xff, %o1 ! get low byte
|
||||
bz,a 1f ! try again if 0
|
||||
srl %o0, 8, %o0 ! delay slot, get ready for next byte
|
||||
@ -8753,6 +8763,12 @@ ENTRY(random)
|
||||
*
|
||||
* If we used the %tick register we could go into the nano-seconds,
|
||||
* and it must run for at least 10 years according to the v9 spec.
|
||||
*
|
||||
* For some insane reason timeval structure members are `long's so
|
||||
* we need to change this code depending on the memory model.
|
||||
*
|
||||
* NB: if somehow time was 128-bit aligned we could use an atomic
|
||||
* quad load to read it in and not bother de-bouncing it.
|
||||
*/
|
||||
#define MICROPERSEC (1000000)
|
||||
|
||||
@ -8763,12 +8779,6 @@ _C_LABEL(cpu_clockrate):
|
||||
.xword 142857143 ! 1/7ns or ~ 143MHz Really should be 142857142.85
|
||||
.text
|
||||
|
||||
#ifdef _LP64
|
||||
/* Use %tick on 64-bit kernels 'cause the other stuff don't work */
|
||||
#define TRY_TICK
|
||||
#endif
|
||||
|
||||
|
||||
ENTRY(microtime)
|
||||
#ifdef TRY_TICK
|
||||
rdpr %tick, %o1
|
||||
@ -8786,19 +8796,19 @@ ENTRY(microtime)
|
||||
stx %o1, [%o0]
|
||||
1:
|
||||
srlx %o1, 32, %o3 ! Isolate high word
|
||||
st %o3, [%o0] ! and store it
|
||||
STPTR %o3, [%o0] ! and store it
|
||||
retl
|
||||
st %o1, [%o0+4] ! Save time_t low word
|
||||
STPTR %o1, [%o0+PTRSZ] ! Save time_t low word
|
||||
#else
|
||||
sethi %hi(timerreg_4u), %g3
|
||||
sethi %hi(_C_LABEL(time)), %g2
|
||||
LDPTR [%g3+%lo(timerreg_4u)], %g3 ! usec counter
|
||||
2:
|
||||
ld [%g2+%lo(_C_LABEL(time))], %o2 ! time.tv_sec & time.tv_usec
|
||||
ld [%g2+%lo(_C_LABEL(time))+4], %o3 ! time.tv_sec & time.tv_usec
|
||||
LDPTR [%g2+%lo(_C_LABEL(time))], %o2 ! time.tv_sec & time.tv_usec
|
||||
LDPTR [%g2+%lo(_C_LABEL(time))+PTRSZ], %o3 ! time.tv_sec & time.tv_usec
|
||||
ldx [%g3], %g7 ! Load usec timer valuse
|
||||
ld [%g2+%lo(_C_LABEL(time))], %g1 ! see if time values changed
|
||||
ld [%g2+%lo(_C_LABEL(time))+4], %g5 ! see if time values changed
|
||||
LDPTR [%g2+%lo(_C_LABEL(time))], %g1 ! see if time values changed
|
||||
LDPTR [%g2+%lo(_C_LABEL(time))+PTRSZ], %g5 ! see if time values changed
|
||||
cmp %g1, %o2
|
||||
bne 2b ! if time.tv_sec changed
|
||||
cmp %g5, %o3
|
||||
@ -8817,13 +8827,13 @@ ENTRY(microtime)
|
||||
set 1000000, %g5 ! normalize usec value
|
||||
cmp %o3, %g5
|
||||
bl,a 4f
|
||||
st %o2, [%o0] ! (should be able to std here)
|
||||
STPTR %o2, [%o0] ! (should be able to std here)
|
||||
add %o2, 1, %o2 ! overflow
|
||||
sub %o3, %g5, %o3
|
||||
st %o2, [%o0] ! (should be able to std here)
|
||||
STPTR %o2, [%o0] ! (should be able to std here)
|
||||
4:
|
||||
retl
|
||||
st %o3, [%o0+4]
|
||||
STPTR %o3, [%o0+PTRSZ]
|
||||
#endif
|
||||
/*
|
||||
* delay function
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: machdep.c,v 1.17 1998/09/17 04:52:17 thorpej Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.18 1998/09/22 02:48:44 eeh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
|
||||
@ -474,6 +474,8 @@ allocsys(v)
|
||||
#define rwindow rwindow64
|
||||
#define STACK_OFFSET BIAS
|
||||
#define CPOUTREG(l,v) copyout(&(v), (l), sizeof(v))
|
||||
#undef CCFSZ
|
||||
#define CCFSZ CC64FSZ
|
||||
#else
|
||||
#define rwindow rwindow32
|
||||
#define STACK_OFFSET 0
|
||||
@ -623,6 +625,7 @@ sendsig(catcher, sig, mask, code)
|
||||
psp->ps_sigstk.ss_size);
|
||||
else
|
||||
fp = (struct sigframe *)oldsp;
|
||||
/* Allocate an aligned sigframe */
|
||||
fp = (struct sigframe *)((long)(fp - 1) & ~0x0f);
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -660,13 +663,15 @@ sendsig(catcher, sig, mask, code)
|
||||
*/
|
||||
native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13);
|
||||
#endif
|
||||
/* Save register context. */
|
||||
sf.sf_sc.sc_sp = (long)tf->tf_out[6];
|
||||
sf.sf_sc.sc_pc = tf->tf_pc;
|
||||
sf.sf_sc.sc_npc = tf->tf_npc;
|
||||
sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */
|
||||
sf.sf_sc.sc_tstate = tf->tf_tstate; /* XXX */
|
||||
sf.sf_sc.sc_g1 = tf->tf_global[1];
|
||||
sf.sf_sc.sc_o0 = tf->tf_out[0];
|
||||
|
||||
|
||||
/*
|
||||
* Put the stack in a consistent state before we whack away
|
||||
* at it. Note that write_user_windows may just dump the
|
||||
@ -676,7 +681,7 @@ sendsig(catcher, sig, mask, code)
|
||||
* joins seamlessly with the frame it was in when the signal occurred,
|
||||
* so that the debugger and _longjmp code can back up through it.
|
||||
*/
|
||||
newsp = (struct rwindow *)((vaddr_t)fp - sizeof(struct rwindow));
|
||||
newsp = (struct rwindow *)((vaddr_t)fp - CC64FSZ);
|
||||
write_user_windows();
|
||||
#ifdef DEBUG
|
||||
if ((sigdebug & SDB_KSTACK))
|
||||
@ -684,7 +689,7 @@ sendsig(catcher, sig, mask, code)
|
||||
fp, &(((struct rwindow *)newsp)->rw_in[6]), (vaddr_t)tf->tf_out[6]);
|
||||
#endif
|
||||
if (rwindow_save(p) || copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) ||
|
||||
#ifdef DEBUG
|
||||
#ifdef NOT_DEBUG
|
||||
copyin(oldsp, &tmpwin, sizeof(tmpwin)) || copyout(&tmpwin, newsp, sizeof(tmpwin)) ||
|
||||
#endif
|
||||
CPOUTREG(&(((struct rwindow *)newsp)->rw_in[6]), tf->tf_out[6])) {
|
||||
@ -781,7 +786,7 @@ sys___sigreturn14(p, v, retval)
|
||||
if ((vaddr_t)scp & 3 || (copyin((caddr_t)scp, &sc, sizeof sc) != 0))
|
||||
#ifdef DEBUG
|
||||
{
|
||||
printf("sigreturn: copyin failed\n");
|
||||
printf("sigreturn: copyin failed: scp=%p\n", scp);
|
||||
Debugger();
|
||||
return (EINVAL);
|
||||
}
|
||||
@ -807,7 +812,7 @@ sys___sigreturn14(p, v, retval)
|
||||
return (EINVAL);
|
||||
#endif
|
||||
/* take only psr ICC field */
|
||||
tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(scp->sc_psr);
|
||||
tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | (scp->sc_tstate & TSTATE_CCR);
|
||||
tf->tf_pc = (int64_t)scp->sc_pc;
|
||||
tf->tf_npc = (int64_t)scp->sc_npc;
|
||||
tf->tf_global[1] = (int64_t)scp->sc_g1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pmap.c,v 1.15 1998/09/13 16:02:49 eeh Exp $ */
|
||||
/* $NetBSD: pmap.c,v 1.16 1998/09/22 02:48:44 eeh Exp $ */
|
||||
/* #define NO_VCACHE /* Don't forget the locked TLB in dostart */
|
||||
#define HWREF
|
||||
/* #define BOOT_DEBUG */
|
||||
@ -1216,15 +1216,6 @@ pmap_pinit(pm)
|
||||
printf("pmap_pinit: segs %p == %p\n", pm->pm_segs, (void*)page->phys_addr);
|
||||
#endif
|
||||
ctx_alloc(pm);
|
||||
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
|
||||
/* Allocate an empty page */
|
||||
pm->syscallargs = malloc(NBPG, M_TEMP, M_WAITOK);
|
||||
/* Make it little endian */
|
||||
pseg_set(pmap_kernel(), pm->syscallargs, pseg_get(pmap_kernel(), pm->syscallargs)|TLB_IE, NULL);
|
||||
/* Flush all mappings */
|
||||
tsb[ptelookup_va(pm->syscallargs)].data.data = 0LL;
|
||||
tlb_flush_pte(pm->syscallargs, 0);
|
||||
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (pmapdebug & PDB_CREATE)
|
||||
@ -1277,17 +1268,6 @@ pmap_release(pm)
|
||||
#endif
|
||||
|
||||
s=splimp();
|
||||
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
|
||||
if (pm->syscallargs) {
|
||||
/* Make it big endian again */
|
||||
pseg_set(pmap_kernel(), pm->syscallargs, pseg_get(pmap_kernel(), pm->syscallargs)&(~TLB_IE), NULL);
|
||||
/* Flush all mappings */
|
||||
tsb[ptelookup_va(pm->syscallargs)].data.data = 0LL;
|
||||
tlb_flush_pte(pm->syscallargs, 0);
|
||||
/* Give it back to the system */
|
||||
free(pm->syscallargs, M_TEMP);
|
||||
}
|
||||
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
|
||||
for(i=0; i<STSZ; i++)
|
||||
if((pdir = (paddr_t *)ldxa(&pm->pm_segs[i], ASI_PHYS_CACHED))) {
|
||||
for (k=0; k<PDSZ; k++) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sunos_machdep.c,v 1.2 1998/09/13 16:02:49 eeh Exp $ */
|
||||
/* $NetBSD: sunos_machdep.c,v 1.3 1998/09/22 02:48:45 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Matthew R. Green
|
||||
@ -52,6 +52,148 @@
|
||||
#include <sys/syscallargs.h>
|
||||
#include <compat/sunos/sunos_syscallargs.h>
|
||||
|
||||
#include <machine/frame.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
int sunos_sigdebug = 0;
|
||||
int sunos_sigpid = 0;
|
||||
#define SDB_FOLLOW 0x01
|
||||
#define SDB_KSTACK 0x02
|
||||
#define SDB_FPSTATE 0x04
|
||||
#define SDB_DDB 0x08
|
||||
#endif
|
||||
|
||||
struct sunos_sigframe {
|
||||
int sf_signo; /* signal number */
|
||||
int sf_code; /* code */
|
||||
struct sigcontext13 *sf_scp; /* SunOS user addr of sigcontext */
|
||||
int sf_addr; /* SunOS compat, always 0 for now */
|
||||
struct sigcontext13 sf_sc; /* actual sigcontext */
|
||||
};
|
||||
|
||||
void
|
||||
sunos_sendsig(catcher, sig, mask, code)
|
||||
sig_t catcher;
|
||||
int sig;
|
||||
sigset_t *mask;
|
||||
u_long code;
|
||||
{
|
||||
register struct proc *p = curproc;
|
||||
register struct sigacts *psp = p->p_sigacts;
|
||||
register struct sunos_sigframe *fp;
|
||||
register struct trapframe *tf;
|
||||
register int addr, onstack;
|
||||
struct rwindow32 *kwin, *oldsp, *newsp;
|
||||
struct sunos_sigframe sf;
|
||||
extern char sigcode[], esigcode[];
|
||||
#define szsigcode (esigcode - sigcode)
|
||||
|
||||
tf = p->p_md.md_tf;
|
||||
/* Need to attempt to zero extend this 32-bit pointer */
|
||||
oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6];
|
||||
/*
|
||||
* Compute new user stack addresses, subtract off
|
||||
* one signal frame, and align.
|
||||
*/
|
||||
onstack =
|
||||
(psp->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
|
||||
(psp->ps_sigact[sig].sa_flags & SA_ONSTACK) != 0;
|
||||
|
||||
if (onstack)
|
||||
fp = (struct sunos_sigframe *)(psp->ps_sigstk.ss_sp +
|
||||
psp->ps_sigstk.ss_size);
|
||||
else
|
||||
fp = (struct sunos_sigframe *)oldsp;
|
||||
fp = (struct sunos_sigframe *)((long)(fp - 1) & ~7);
|
||||
|
||||
#ifdef DEBUG
|
||||
sunos_sigpid = p->p_pid;
|
||||
if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid) {
|
||||
printf("sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n",
|
||||
p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp);
|
||||
if (sunos_sigdebug & SDB_DDB) Debugger();
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Now set up the signal frame. We build it in kernel space
|
||||
* and then copy it out. We probably ought to just build it
|
||||
* directly in user space....
|
||||
*/
|
||||
sf.sf_signo = sig;
|
||||
sf.sf_code = code;
|
||||
sf.sf_scp = (u_long)&fp->sf_sc;
|
||||
sf.sf_addr = 0; /* XXX */
|
||||
|
||||
/*
|
||||
* Build the signal context to be used by sigreturn.
|
||||
*/
|
||||
sf.sf_sc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
|
||||
native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask);
|
||||
sf.sf_sc.sc_sp = (long)oldsp;
|
||||
sf.sf_sc.sc_pc = tf->tf_pc;
|
||||
sf.sf_sc.sc_npc = tf->tf_npc;
|
||||
sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */
|
||||
sf.sf_sc.sc_g1 = tf->tf_global[1];
|
||||
sf.sf_sc.sc_o0 = tf->tf_out[0];
|
||||
|
||||
/*
|
||||
* Put the stack in a consistent state before we whack away
|
||||
* at it. Note that write_user_windows may just dump the
|
||||
* registers into the pcb; we need them in the process's memory.
|
||||
* We also need to make sure that when we start the signal handler,
|
||||
* its %i6 (%fp), which is loaded from the newly allocated stack area,
|
||||
* joins seamlessly with the frame it was in when the signal occurred,
|
||||
* so that the debugger and _longjmp code can back up through it.
|
||||
*/
|
||||
newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32));
|
||||
write_user_windows();
|
||||
#ifdef DEBUG
|
||||
if ((sunos_sigdebug & SDB_KSTACK))
|
||||
printf("sendsig: saving sf to %p, setting stack pointer %p to %p\n",
|
||||
fp, &(((union rwindow *)newsp)->v8.rw_in[6]), oldsp);
|
||||
#endif
|
||||
kwin = (struct rwindow32 *)(((caddr_t)tf)-CCFSZ);
|
||||
if (rwindow_save(p) ||
|
||||
copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) ||
|
||||
suword(&(((union rwindow *)newsp)->v8.rw_in[6]), (u_long)oldsp)) {
|
||||
/*
|
||||
* Process has trashed its stack; give it an illegal
|
||||
* instruction to halt it in its tracks.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid)
|
||||
printf("sendsig: window save or copyout error\n");
|
||||
printf("sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig);
|
||||
if (sunos_sigdebug & SDB_DDB) Debugger();
|
||||
#endif
|
||||
sigexit(p, SIGILL);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (sunos_sigdebug & SDB_FOLLOW) {
|
||||
printf("sendsig: %s[%d] sig %d scp %p\n",
|
||||
p->p_comm, p->p_pid, sig, &fp->sf_sc);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Arrange to continue execution at the code copied out in exec().
|
||||
* It needs the function to call in %g1, and a new stack pointer.
|
||||
*/
|
||||
addr = (long)catcher; /* user does his own trampolining */
|
||||
tf->tf_pc = addr;
|
||||
tf->tf_npc = addr + 4;
|
||||
tf->tf_out[6] = (u_int64_t)(u_int)(u_long)newsp;
|
||||
#ifdef DEBUG
|
||||
if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid) {
|
||||
printf("sendsig: about to return to catcher %p thru %p\n",
|
||||
catcher, addr);
|
||||
if (sunos_sigdebug & SDB_DDB) Debugger();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
sunos_sys_sigreturn(p, v, retval)
|
||||
register struct proc *p;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: trap.c,v 1.16 1998/09/13 16:02:49 eeh Exp $ */
|
||||
/* $NetBSD: trap.c,v 1.17 1998/09/22 02:48:45 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996
|
||||
@ -141,7 +141,7 @@ extern int cold;
|
||||
#define RW_64 0x1
|
||||
#define RW_ERR 0x2
|
||||
#define RW_FOLLOW 0x4
|
||||
int rwindow_debug = RW_64|RW_ERR;
|
||||
int rwindow_debug = RW_ERR;
|
||||
#define TDB_ADDFLT 0x1
|
||||
#define TDB_TXTFLT 0x2
|
||||
#define TDB_TRAP 0x4
|
||||
@ -499,6 +499,10 @@ trap(type, tstate, pc, tf)
|
||||
#define ADVANCE (n = tf->tf_npc, tf->tf_pc = n, tf->tf_npc = n + 4)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (tf->tf_pc == tf->tf_npc) {
|
||||
printf("trap: tpc %p == tnpc %p\n", tf->tf_pc, tf->tf_npc);
|
||||
Debugger();
|
||||
}
|
||||
{
|
||||
/* Check to make sure we're on the normal stack */
|
||||
int* sp;
|
||||
@ -563,6 +567,12 @@ trap(type, tstate, pc, tf)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (type == T_PA_WATCHPT || type == T_VA_WATCHPT) {
|
||||
if (kdb_trap(type, tf)) {
|
||||
/* DDB must turn off watchpoints or something */
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef DIAGNOSTIC
|
||||
/*
|
||||
@ -690,37 +700,6 @@ badtrap:
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#define read_rw(src, dst) \
|
||||
((src&1)?copyin((caddr_t)(src), (caddr_t)(dst), sizeof(struct rwindow32))\
|
||||
:copyin((caddr_t)(src+BIAS), (caddr_t)(dst), sizeof(struct rwindow64)))
|
||||
|
||||
case T_RWRET:
|
||||
/*
|
||||
* T_RWRET is a window load needed in order to rett.
|
||||
* It simply needs the window to which tf->tf_out[6]
|
||||
* (%sp) points. There are no user or saved windows now.
|
||||
* Copy the one from %sp into pcb->pcb_rw[0] and set
|
||||
* nsaved to -1. If we decide to deliver a signal on
|
||||
* our way out, we will clear nsaved.
|
||||
*/
|
||||
if (pcb->pcb_nsaved)
|
||||
panic("trap T_RWRET 1");
|
||||
#ifdef DEBUG
|
||||
if (rwindow_debug&RW_FOLLOW)
|
||||
printf("%s[%d]: rwindow: pcb<-stack: %lx\n",
|
||||
p->p_comm, p->p_pid, tf->tf_out[6]);
|
||||
printf("trap: T_RWRET sent!?!\n");
|
||||
/* I don't think this is ever used */
|
||||
Debugger();
|
||||
#endif
|
||||
if (read_rw(tf->tf_out[6], &pcb->pcb_rw[0]))
|
||||
sigexit(p, SIGILL);
|
||||
if (pcb->pcb_nsaved)
|
||||
panic("trap T_RWRET 2");
|
||||
pcb->pcb_nsaved = -1; /* mark success */
|
||||
break;
|
||||
#endif
|
||||
case T_ALIGN:
|
||||
case T_LDDF_ALIGN:
|
||||
case T_STDF_ALIGN:
|
||||
@ -986,6 +965,10 @@ data_access_fault(type, addr, pc, tf)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
if (tf->tf_pc == tf->tf_npc) {
|
||||
printf("data_access_fault: tpc %p == tnpc %p\n", tf->tf_pc, tf->tf_npc);
|
||||
Debugger();
|
||||
}
|
||||
if (protmmu || missmmu) {
|
||||
extern int trap_trace_dis;
|
||||
trap_trace_dis = 1;
|
||||
@ -1206,6 +1189,10 @@ data_access_error(type, sfva, sfsr, afva, afsr, tf)
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
if (tf->tf_pc == tf->tf_npc) {
|
||||
printf("data_access_error: tpc %p == tnpc %p\n", tf->tf_pc, tf->tf_npc);
|
||||
Debugger();
|
||||
}
|
||||
if (protmmu || missmmu) {
|
||||
extern int trap_trace_dis;
|
||||
trap_trace_dis = 1;
|
||||
@ -1452,6 +1439,10 @@ text_access_fault(type, pc, tf)
|
||||
u_quad_t sticks;
|
||||
|
||||
#if DEBUG
|
||||
if (tf->tf_pc == tf->tf_npc) {
|
||||
printf("text_access_fault: tpc %p == tnpc %p\n", tf->tf_pc, tf->tf_npc);
|
||||
Debugger();
|
||||
}
|
||||
if (protmmu || missmmu) {
|
||||
extern int trap_trace_dis;
|
||||
trap_trace_dis = 1;
|
||||
@ -1586,6 +1577,10 @@ text_access_error(type, pc, sfsr, afva, afsr, tf)
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
if (tf->tf_pc == tf->tf_npc) {
|
||||
printf("text_access_error: tpc %p == tnpc %p\n", tf->tf_pc, tf->tf_npc);
|
||||
Debugger();
|
||||
}
|
||||
if (protmmu || missmmu) {
|
||||
extern int trap_trace_dis;
|
||||
trap_trace_dis = 1;
|
||||
@ -1772,7 +1767,7 @@ syscall(code, tf, pc)
|
||||
union args {
|
||||
register32_t i[8];
|
||||
register64_t l[8];
|
||||
} args, *argsp = &args;
|
||||
} args;
|
||||
register_t rval[2];
|
||||
u_quad_t sticks;
|
||||
#ifdef DIAGNOSTIC
|
||||
@ -1781,6 +1776,10 @@ syscall(code, tf, pc)
|
||||
|
||||
#ifdef DEBUG
|
||||
write_user_windows();
|
||||
if (tf->tf_pc == tf->tf_npc) {
|
||||
printf("syscall: tpc %p == tnpc %p\n", tf->tf_pc, tf->tf_npc);
|
||||
Debugger();
|
||||
}
|
||||
if ((trapdebug&TDB_NSAVED && cpcb->pcb_nsaved) || trapdebug&(TDB_SYSCALL|TDB_FOLLOW))
|
||||
printf("%d syscall(%x, %x, %x)\n",
|
||||
curproc?curproc->p_pid:-1, code, tf, pc);
|
||||
@ -1865,7 +1864,6 @@ syscall(code, tf, pc)
|
||||
callp += p->p_emul->e_nosys;
|
||||
else if (tf->tf_out[6] & 1L) {
|
||||
register64_t *argp;
|
||||
argsp = p->p_vmspace->vm_map.pmap->syscallargs;
|
||||
#ifndef _LP64
|
||||
#ifdef DEBUG
|
||||
printf("syscall(): 64-bit stack on a 32-bit kernel????\n");
|
||||
@ -1874,44 +1872,55 @@ syscall(code, tf, pc)
|
||||
#endif
|
||||
/* 64-bit stack -- not really supported on 32-bit kernels */
|
||||
callp += code;
|
||||
#if 1
|
||||
i = (long)callp->sy_argsize / sizeof(register64_t);
|
||||
#else
|
||||
i = callp->sy_narg; /* Why divide? */
|
||||
#ifdef DEBUG
|
||||
if (i != (long)callp->sy_argsize / sizeof(register64_t))
|
||||
printf("syscall %s: narg=%hd, argsize=%hd, call=%p, argsz/reg64=%ld\n",
|
||||
(code < 0 || code >= nsys)? "illegal syscall" : p->p_emul->e_syscallnames[code],
|
||||
callp->sy_narg, callp->sy_argsize, callp->sy_call, (long)callp->sy_argsize / sizeof(register64_t));
|
||||
#endif
|
||||
if (i > nap) { /* usually false */
|
||||
register64_t temp[6];
|
||||
int j = 0;
|
||||
#ifdef DEBUG
|
||||
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW) || i>8)
|
||||
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW) || i>8) {
|
||||
printf("Args64 %d>%d -- need to copyin\n", i , nap);
|
||||
}
|
||||
#endif
|
||||
if (i > 8)
|
||||
panic("syscall nargs");
|
||||
#if 0
|
||||
/* Read the whole block in */
|
||||
error = copyin((caddr_t)tf->tf_out[6] + BIAS +
|
||||
offsetof(struct frame64, fr_argd),
|
||||
offsetof(struct frame64, fr_argx),
|
||||
(caddr_t)&temp, (i - nap) * sizeof(register64_t));
|
||||
/* Copy each to the argument array */
|
||||
for (j=0; nap+j < i; j++)
|
||||
argsp->l[nap+j] = temp[j];
|
||||
args.l[nap+j] = temp[j];
|
||||
#else
|
||||
/* Read the whole block in */
|
||||
error = copyin((caddr_t)tf->tf_out[6] + BIAS +
|
||||
offsetof(struct frame64, fr_argx),
|
||||
(caddr_t)&args.l[nap], (i - nap) * sizeof(register64_t));
|
||||
#endif
|
||||
if (error) {
|
||||
#ifdef KTRACE
|
||||
if (KTRPOINT(p, KTR_SYSCALL))
|
||||
ktrsyscall(p->p_tracep, code,
|
||||
callp->sy_argsize, (register_t*)argsp->i);
|
||||
callp->sy_argsize, (register_t*)args.l);
|
||||
#endif
|
||||
goto bad;
|
||||
}
|
||||
i = nap;
|
||||
}
|
||||
/* Need to convert from int64 to int32 or we lose */
|
||||
for (argp = &argsp->l[0]; i--;)
|
||||
*argp++ = *ap++;
|
||||
/* It should be faster to do <=6 longword copies than call bcopy */
|
||||
for (argp = &args.l[0]; i--;)
|
||||
*argp++ = *ap++;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW)) {
|
||||
for (i=0; i < (long)callp->sy_argsize / sizeof(register64_t); i++)
|
||||
printf("arg[%d]=%x ", i, (long)(argsp->l[i]));
|
||||
for (i=0; i < callp->sy_narg; i++)
|
||||
printf("arg[%d]=%lx ", i, (long)(args.l[i]));
|
||||
printf("\n");
|
||||
}
|
||||
if (trapdebug&(TDB_STOPCALL|TDB_SYSTOP)) {
|
||||
@ -1923,6 +1932,13 @@ syscall(code, tf, pc)
|
||||
register32_t *argp;
|
||||
/* 32-bit stack */
|
||||
callp += code;
|
||||
#ifdef _LP64
|
||||
#ifdef DEBUG
|
||||
printf("syscall(): 32-bit stack on a 64-bit kernel????\n");
|
||||
Debugger();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
i = (long)callp->sy_argsize / sizeof(register32_t);
|
||||
#else
|
||||
@ -1943,33 +1959,33 @@ syscall(code, tf, pc)
|
||||
(caddr_t)&temp, (i - nap) * sizeof(register32_t));
|
||||
/* Copy each to the argument array */
|
||||
for (j=0; nap+j < i; j++)
|
||||
argsp->i[nap+j] = temp[j];
|
||||
args.i[nap+j] = temp[j];
|
||||
#ifdef DEBUG
|
||||
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW)) {
|
||||
int k;
|
||||
printf("Copyin args of %d from %p:\n", j,
|
||||
(caddr_t)(tf->tf_out[6] + offsetof(struct frame32, fr_argx)));
|
||||
for (k=0; k<j; k++)
|
||||
printf("arg %d = %p at %d val %p\n", k, (long)temp[k], nap+k, (long)argsp->i[nap+k]);
|
||||
printf("arg %d = %p at %d val %p\n", k, (long)temp[k], nap+k, (long)args.i[nap+k]);
|
||||
}
|
||||
#endif
|
||||
if (error) {
|
||||
#ifdef KTRACE
|
||||
if (KTRPOINT(p, KTR_SYSCALL))
|
||||
ktrsyscall(p->p_tracep, code,
|
||||
callp->sy_argsize, (register_t *)argsp->i);
|
||||
callp->sy_argsize, (register_t *)args.i);
|
||||
#endif
|
||||
goto bad;
|
||||
}
|
||||
i = nap;
|
||||
}
|
||||
/* Need to convert from int64 to int32 or we lose */
|
||||
for (argp = &argsp->i[0]; i--;)
|
||||
for (argp = &args.i[0]; i--;)
|
||||
*argp++ = *ap++;
|
||||
#ifdef DEBUG
|
||||
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW)) {
|
||||
for (i=0; i < (long)callp->sy_argsize / sizeof(register32_t); i++)
|
||||
printf("arg[%d]=%x ", i, (int)(argsp->i[i]));
|
||||
printf("arg[%d]=%x ", i, (int)(args.i[i]));
|
||||
printf("\n");
|
||||
}
|
||||
if (trapdebug&(TDB_STOPCALL|TDB_SYSTOP)) {
|
||||
@ -1980,43 +1996,44 @@ syscall(code, tf, pc)
|
||||
}
|
||||
#ifdef KTRACE
|
||||
if (KTRPOINT(p, KTR_SYSCALL))
|
||||
ktrsyscall(p->p_tracep, code, callp->sy_argsize, (register_t *)argsp->i);
|
||||
ktrsyscall(p->p_tracep, code, callp->sy_argsize, (register_t *)args.i);
|
||||
#endif
|
||||
rval[0] = 0;
|
||||
rval[1] = tf->tf_out[1];
|
||||
error = (*callp->sy_call)(p, argsp, rval);
|
||||
error = (*callp->sy_call)(p, &args, rval);
|
||||
|
||||
switch (error) {
|
||||
vaddr_t dest;
|
||||
case 0:
|
||||
/* Note: fork() does not return here in the child */
|
||||
tf->tf_out[0] = rval[0];
|
||||
tf->tf_out[1] = rval[1];
|
||||
if (new) {
|
||||
/* jmp %g2 (or %g7, deprecated) on success */
|
||||
i = tf->tf_global[new & SYSCALL_G2RFLAG ? 2 : 7];
|
||||
dest = tf->tf_global[new & SYSCALL_G2RFLAG ? 2 : 7];
|
||||
#ifdef DEBUG
|
||||
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW))
|
||||
printf("syscall: return tstate=%x:%x new success to %p retval %x:%x\n",
|
||||
(int)(tf->tf_tstate>>32), (int)(tf->tf_tstate),
|
||||
i, rval[0], rval[1]);
|
||||
printf("syscall: return tstate=%llx new success to %p retval %x:%x\n",
|
||||
tf->tf_tstate, dest, rval[0], rval[1]);
|
||||
#endif
|
||||
if (i & 3) {
|
||||
if (dest & 3) {
|
||||
error = EINVAL;
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
/* old system call convention: clear C on success */
|
||||
tf->tf_tstate &= ~(((int64_t)(ICC_C|XCC_C))<<TSTATE_CCR_SHIFT); /* success */
|
||||
i = tf->tf_npc;
|
||||
dest = tf->tf_npc;
|
||||
#ifdef DEBUG
|
||||
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW))
|
||||
printf("syscall: return tstate=%x:%x old success to %p retval %x:%x\n",
|
||||
(int)(tf->tf_tstate>>32), (int)(tf->tf_tstate),
|
||||
i, rval[0], rval[1]);
|
||||
printf("syscall: return tstate=%llx old success to %p retval %x:%x\n",
|
||||
tf->tf_tstate, dest, rval[0], rval[1]);
|
||||
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW))
|
||||
printf("old pc=%p npc=%p dest=%p\n", tf->tf_pc, tf->tf_npc, dest);
|
||||
#endif
|
||||
}
|
||||
tf->tf_pc = i;
|
||||
tf->tf_npc = i + 4;
|
||||
tf->tf_pc = dest;
|
||||
tf->tf_npc = dest + 4;
|
||||
break;
|
||||
|
||||
case ERESTART:
|
||||
@ -2030,14 +2047,13 @@ syscall(code, tf, pc)
|
||||
error = p->p_emul->e_errno[error];
|
||||
tf->tf_out[0] = error;
|
||||
tf->tf_tstate |= (((int64_t)(ICC_C|XCC_C))<<TSTATE_CCR_SHIFT); /* fail */
|
||||
i = tf->tf_npc;
|
||||
tf->tf_pc = i;
|
||||
tf->tf_npc = i + 4;
|
||||
dest = tf->tf_npc;
|
||||
tf->tf_pc = dest;
|
||||
tf->tf_npc = dest + 4;
|
||||
#ifdef DEBUG
|
||||
if (trapdebug&(TDB_SYSCALL|TDB_FOLLOW))
|
||||
printf("syscall: return tstate=%x:%x fail %d to %p\n",
|
||||
(int)(tf->tf_tstate>>32), (int)(tf->tf_tstate),
|
||||
error, i);
|
||||
printf("syscall: return tstate=%llx fail %d to %p\n",
|
||||
tf->tf_tstate, error, dest);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@ -2088,269 +2104,3 @@ child_return(p)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Code to handle alignment faults on the sparc. This is enabled by sending
|
||||
* a fixalign trap.
|
||||
*
|
||||
* Such code is generated by compiling with cc -misalign
|
||||
* on SunOS, but we don't have such a feature yet on our gcc.
|
||||
*
|
||||
* We don't do any funny ASIs, so don't expect endianess-inversion to work.
|
||||
*/
|
||||
#ifdef DEBUG_ALIGN
|
||||
# define DPRINTF(a) uprintf a
|
||||
#else
|
||||
# define DPRINTF(a)
|
||||
#endif
|
||||
|
||||
#define GPR(tf, i) ((int64_t *) &tf->tf_global)[i]
|
||||
#define IPR(tf, i) ((int64_t *) tf->tf_out[6])[i - 16]
|
||||
#define FPR(p, i) ((int32_t) p->p_md.md_fpstate->fs_regs[i])
|
||||
|
||||
static __inline int readgpreg __P((struct trapframe *, int, void *));
|
||||
static __inline int readfpreg __P((struct proc *, int, void *));
|
||||
static __inline int writegpreg __P((struct trapframe *, int, const void *));
|
||||
static __inline int writefpreg __P((struct proc *, int, const void *));
|
||||
|
||||
|
||||
static __inline int
|
||||
readgpreg(tf, i, val)
|
||||
struct trapframe *tf;
|
||||
int i;
|
||||
void *val;
|
||||
{
|
||||
int error = 0;
|
||||
if (i == 0)
|
||||
*(int64_t *) val = 0;
|
||||
else if (i < 16)
|
||||
*(int64_t *) val = GPR(tf, i);
|
||||
else
|
||||
error = copyin(&IPR(tf, i), val, sizeof(int64_t));
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static __inline int
|
||||
writegpreg(tf, i, val)
|
||||
struct trapframe *tf;
|
||||
int i;
|
||||
const void *val;
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
if (i == 0)
|
||||
return error;
|
||||
else if (i < 16)
|
||||
GPR(tf, i) = *(int64_t *) val;
|
||||
else
|
||||
/* XXX: Fix copyout prototype */
|
||||
error = copyout((caddr_t) val, &IPR(tf, i), sizeof(int64_t));
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static __inline int
|
||||
readfpreg(p, i, val)
|
||||
struct proc *p;
|
||||
int i;
|
||||
void *val;
|
||||
{
|
||||
*(int32_t *) val = FPR(p, i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static __inline int
|
||||
writefpreg(p, i, val)
|
||||
struct proc *p;
|
||||
int i;
|
||||
const void *val;
|
||||
{
|
||||
FPR(p, i) = *(const int32_t *) val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
fixalign(p, tf)
|
||||
struct proc *p;
|
||||
struct trapframe *tf;
|
||||
{
|
||||
static u_char sizedef[] = { 0x4, 0xff, 0x2, 0x8 };
|
||||
|
||||
/*
|
||||
* The following is not really a general instruction format;
|
||||
* it is tailored to our needs
|
||||
*/
|
||||
union {
|
||||
struct {
|
||||
unsigned fmt:2; /* 31..30 - 2 bit format */
|
||||
unsigned rd:5; /* 29..25 - 5 bit destination reg */
|
||||
unsigned fl:1; /* 24..24 - 1 bit float flag */
|
||||
unsigned op:1; /* 23..23 - 1 bit opcode */
|
||||
unsigned sgn:1; /* 22..22 - 1 bit sign */
|
||||
unsigned st:1; /* 21..21 - 1 bit load/store */
|
||||
unsigned sz:2; /* 20..19 - 2 bit size register */
|
||||
unsigned rs1:5; /* 18..14 - 5 bit source reg 1 */
|
||||
unsigned imm:1; /* 13..13 - 1 bit immediate flag */
|
||||
unsigned asi:8; /* 12.. 5 - 8 bit asi bits */
|
||||
unsigned rs2:5; /* 4.. 0 - 5 bit source reg 2 */
|
||||
} bits;
|
||||
int32_t word;
|
||||
} code;
|
||||
|
||||
union {
|
||||
double d;
|
||||
int64_t l;
|
||||
int32_t i[2];
|
||||
int16_t s[4];
|
||||
int8_t c[8];
|
||||
} data;
|
||||
|
||||
size_t size;
|
||||
int64_t offs, addr;
|
||||
int error;
|
||||
|
||||
/* fetch and check the instruction that caused the fault */
|
||||
error = copyin((caddr_t) tf->tf_pc, &code.word, sizeof(code.word));
|
||||
if (error != 0) {
|
||||
DPRINTF(("fixalign: Bad instruction fetch\n"));
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Only support format 3 */
|
||||
if (code.bits.fmt != 3) {
|
||||
DPRINTF(("fixalign: Not a load or store\n"));
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Check operand size */
|
||||
if ((size = sizedef[code.bits.sz]) == 0xff) {
|
||||
DPRINTF(("fixalign: Bad operand size\n"));
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
write_user_windows();
|
||||
|
||||
if ((error = readgpreg(tf, code.bits.rs1, &addr)) != 0) {
|
||||
DPRINTF(("fixalign: read rs1 %d\n", error));
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Handle immediate operands */
|
||||
if (code.bits.imm) {
|
||||
offs = code.word & 0x1fff;
|
||||
if (offs & 0x1000) /* Sign extend */
|
||||
offs |= 0xffffe;
|
||||
}
|
||||
else {
|
||||
if (code.bits.asi) {
|
||||
DPRINTF(("fixalign: Illegal instruction\n"));
|
||||
return EINVAL;
|
||||
}
|
||||
if ((error = readgpreg(tf, code.bits.rs2, &offs)) != 0) {
|
||||
DPRINTF(("fixalign: read rs2 %d\n", error));
|
||||
return error;
|
||||
}
|
||||
}
|
||||
addr += offs;
|
||||
|
||||
#ifdef DEBUG_ALIGN
|
||||
uprintf("memalign %x: %s%c%c %c%d, r%d, ", code.word,
|
||||
code.bits.st ? "st" : "ld", "us"[code.bits.sgn],
|
||||
"w*hd"[code.bits.sz], "rf"[code.bits.fl], code.bits.rd,
|
||||
code.bits.rs1);
|
||||
if (code.bits.imm)
|
||||
uprintf("0x%x\n", offs);
|
||||
else
|
||||
uprintf("r%d\n", code.bits.rs2);
|
||||
#endif
|
||||
#ifdef DIAGNOSTIC
|
||||
if (code.bits.fl && p != fpproc)
|
||||
panic("fp align without being the FP owning process");
|
||||
#endif
|
||||
|
||||
if (code.bits.st) {
|
||||
if (code.bits.fl) {
|
||||
savefpstate(p->p_md.md_fpstate);
|
||||
|
||||
error = readfpreg(p, code.bits.rd, &data.i[0]);
|
||||
if (error)
|
||||
return error;
|
||||
if (size == 8) {
|
||||
error = readfpreg(p, code.bits.rd + 1,
|
||||
&data.i[1]);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
error = readgpreg(tf, code.bits.rd, &data.l);
|
||||
if (error)
|
||||
return error;
|
||||
if (size == 8 && !code.bits.sgn) {
|
||||
int64_t temp;
|
||||
/* std or stda -- get things in the right regs. */
|
||||
|
||||
temp = data.l;
|
||||
data.i[0] = temp;
|
||||
error = readgpreg(tf, code.bits.rd + 1, &temp);
|
||||
data.i[1] = temp;
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if (size == 2)
|
||||
return copyout(&data.s[1], (caddr_t) addr, size);
|
||||
else
|
||||
return copyout(&data.d, (caddr_t) addr, size);
|
||||
}
|
||||
else { /* load */
|
||||
if (size == 2) {
|
||||
error = copyin((caddr_t) addr, &data.s[1], size);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Sign extend if necessary */
|
||||
if (code.bits.sgn && (data.s[1] & 0x8000) != 0)
|
||||
data.s[0] = ~0;
|
||||
else
|
||||
data.s[0] = 0;
|
||||
}
|
||||
else
|
||||
error = copyin((caddr_t) addr, &data.d, size);
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (code.bits.fl) {
|
||||
error = writefpreg(p, code.bits.rd, &data.i[0]);
|
||||
if (error)
|
||||
return error;
|
||||
if (size == 8) {
|
||||
error = writefpreg(p, code.bits.rd + 1,
|
||||
&data.i[1]);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
loadfpstate(p->p_md.md_fpstate);
|
||||
}
|
||||
else {
|
||||
if (size == 8 && !code.bits.sgn) {
|
||||
u_int64_t temp;
|
||||
/* ldd or ldda -- get things in the right regs. */
|
||||
|
||||
temp = (unsigned int)data.i[0]; /* Do not sign extend */
|
||||
error = writegpreg(tf, code.bits.rd, &temp);
|
||||
temp = (unsigned int)data.i[1]; /* Do not sign extend */
|
||||
if (!error)
|
||||
error = writegpreg(tf, code.bits.rd + 1, &temp);
|
||||
} else error = writegpreg(tf, code.bits.rd, &data.i[0]);
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user