Emulate ldq and stq (load/store long double) instructions. GCC has started
using these to load long doubles, but they aren't implemented in hardware on (at least) UltraSPARC I and II machines. Emulate popc in the user trap handler as well. Re-arrange slightly to make support functions more accessible. Reviewed by: tmm
This commit is contained in:
parent
60ee831d3e
commit
a1a94cce5c
@ -2,5 +2,7 @@
|
||||
|
||||
.PATH: ${.CURDIR}/../libc/sparc64/fpu/
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/sparc64/sys
|
||||
|
||||
SRCS+= fpu.c fpu_add.c fpu_compare.c fpu_div.c fpu_explode.c fpu_implode.c \
|
||||
fpu_mul.c fpu_reg.S fpu_sqrt.c fpu_subr.c
|
||||
|
@ -87,7 +87,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/tstate.h>
|
||||
|
||||
#include "../sys/__sparc_utrap_private.h"
|
||||
#include "__sparc_utrap_private.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
|
||||
@ -119,89 +119,52 @@ int __fpe_debug = 0;
|
||||
#endif /* FPU_DEBUG */
|
||||
|
||||
static int __fpu_execute(struct utrapframe *, struct fpemu *, u_int32_t, u_long);
|
||||
static void utrap_write(char *);
|
||||
static void utrap_kill_self(int);
|
||||
|
||||
/*
|
||||
* System call wrappers usable in an utrap environment.
|
||||
*/
|
||||
static void
|
||||
utrap_write(char *str)
|
||||
{
|
||||
int berrno;
|
||||
|
||||
berrno = errno;
|
||||
__sys_write(STDERR_FILENO, str, strlen(str));
|
||||
errno = berrno;
|
||||
}
|
||||
|
||||
static void
|
||||
utrap_kill_self(sig)
|
||||
{
|
||||
int berrno;
|
||||
|
||||
berrno = errno;
|
||||
__sys_kill(__sys_getpid(), sig);
|
||||
errno = berrno;
|
||||
}
|
||||
|
||||
void
|
||||
__fpu_panic(char *msg)
|
||||
{
|
||||
|
||||
utrap_write(msg);
|
||||
utrap_write("\n");
|
||||
utrap_kill_self(SIGKILL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Need to use an fpstate on the stack; we could switch, so we cannot safely
|
||||
* modify the pcb one, it might get overwritten.
|
||||
*/
|
||||
void
|
||||
int
|
||||
__fpu_exception(struct utrapframe *uf)
|
||||
{
|
||||
struct fpemu fe;
|
||||
u_long fsr, tstate;
|
||||
u_int insn;
|
||||
int rv;
|
||||
int sig;
|
||||
|
||||
fsr = uf->uf_fsr;
|
||||
|
||||
switch (FSR_GET_FTT(fsr)) {
|
||||
case FSR_FTT_NONE:
|
||||
utrap_write("lost FPU trap type\n");
|
||||
return;
|
||||
__utrap_write("lost FPU trap type\n");
|
||||
return (0);
|
||||
case FSR_FTT_IEEE:
|
||||
goto fatal;
|
||||
return (SIGFPE);
|
||||
case FSR_FTT_SEQERR:
|
||||
utrap_write("FPU sequence error\n");
|
||||
goto fatal;
|
||||
__utrap_write("FPU sequence error\n");
|
||||
return (SIGFPE);
|
||||
case FSR_FTT_HWERR:
|
||||
utrap_write("FPU hardware error\n");
|
||||
goto fatal;
|
||||
__utrap_write("FPU hardware error\n");
|
||||
return (SIGFPE);
|
||||
case FSR_FTT_UNFIN:
|
||||
case FSR_FTT_UNIMP:
|
||||
break;
|
||||
default:
|
||||
utrap_write("unknown FPU error\n");
|
||||
goto fatal;
|
||||
__utrap_write("unknown FPU error\n");
|
||||
return (SIGFPE);
|
||||
}
|
||||
|
||||
fe.fe_fsr = fsr & ~FSR_FTT_MASK;
|
||||
insn = *(u_int32_t *)uf->uf_pc;
|
||||
if (IF_OP(insn) != IOP_MISC || (IF_F3_OP3(insn) != INS2_FPop1 &&
|
||||
IF_F3_OP3(insn) != INS2_FPop2))
|
||||
__fpu_panic("bogus FP fault");
|
||||
__utrap_panic("bogus FP fault");
|
||||
tstate = uf->uf_state;
|
||||
rv = __fpu_execute(uf, &fe, insn, tstate);
|
||||
if (rv != 0)
|
||||
utrap_kill_self(rv);
|
||||
sig = __fpu_execute(uf, &fe, insn, tstate);
|
||||
if (sig != 0)
|
||||
return (sig);
|
||||
__asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr));
|
||||
return;
|
||||
fatal:
|
||||
utrap_kill_self(SIGFPE);
|
||||
return;
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef FPU_DEBUG
|
||||
@ -223,29 +186,6 @@ __fpu_dumpfpn(struct fpn *fp)
|
||||
}
|
||||
#endif
|
||||
|
||||
static u_long
|
||||
fetch_reg(struct utrapframe *uf, int reg)
|
||||
{
|
||||
u_long offs;
|
||||
struct frame *frm;
|
||||
|
||||
if (reg == IREG_G0)
|
||||
return (0);
|
||||
else if (reg < IREG_O0) /* global */
|
||||
return (uf->uf_global[reg]);
|
||||
else if (reg < IREG_L0) /* out */
|
||||
return (uf->uf_out[reg - IREG_O0]);
|
||||
else { /* local, in */
|
||||
/*
|
||||
* The in registers are immediately after the locals in
|
||||
* the frame.
|
||||
*/
|
||||
frm = (struct frame *)(uf->uf_out[6] + SPOFF);
|
||||
return (frm->fr_local[reg - IREG_L0]);
|
||||
}
|
||||
__fpu_panic("fetch_reg: bogus register");
|
||||
}
|
||||
|
||||
static void
|
||||
__fpu_mov(struct fpemu *fe, int type, int rd, int rs1, int rs2)
|
||||
{
|
||||
@ -361,32 +301,32 @@ __fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn, u_long ts
|
||||
(tstate & TSTATE_XCC_MASK) >> (TSTATE_XCC_SHIFT));
|
||||
return (0);
|
||||
case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_Z)):
|
||||
reg = fetch_reg(uf, IF_F4_RS1(insn));
|
||||
reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
|
||||
if (reg == 0)
|
||||
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
|
||||
return (0);
|
||||
case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LEZ)):
|
||||
reg = fetch_reg(uf, IF_F4_RS1(insn));
|
||||
reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
|
||||
if (reg <= 0)
|
||||
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
|
||||
return (0);
|
||||
case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LZ)):
|
||||
reg = fetch_reg(uf, IF_F4_RS1(insn));
|
||||
reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
|
||||
if (reg < 0)
|
||||
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
|
||||
return (0);
|
||||
case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_NZ)):
|
||||
reg = fetch_reg(uf, IF_F4_RS1(insn));
|
||||
reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
|
||||
if (reg != 0)
|
||||
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
|
||||
return (0);
|
||||
case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GZ)):
|
||||
reg = fetch_reg(uf, IF_F4_RS1(insn));
|
||||
reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
|
||||
if (reg > 0)
|
||||
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
|
||||
return (0);
|
||||
case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GEZ)):
|
||||
reg = fetch_reg(uf, IF_F4_RS1(insn));
|
||||
reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
|
||||
if (reg >= 0)
|
||||
__fpu_mov(fe, type, rd, __fpu_getreg(rs2), rs2);
|
||||
return (0);
|
||||
|
@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "fpu_arith.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
#include "__sparc_utrap_private.h"
|
||||
|
||||
struct fpn *
|
||||
__fpu_add(fe)
|
||||
@ -198,7 +199,7 @@ __fpu_add(fe)
|
||||
*/
|
||||
#ifdef DIAGNOSTIC
|
||||
if (x->fp_exp != y->fp_exp || r->fp_sticky)
|
||||
__fpu_panic("fpu_add");
|
||||
__utrap_panic("fpu_add");
|
||||
#endif
|
||||
r->fp_sign = y->fp_sign;
|
||||
FPU_SUBS(r3, 0, r3);
|
||||
|
@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "fpu_arith.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
#include "__sparc_utrap_private.h"
|
||||
|
||||
/*
|
||||
* N.B.: in all of the following, we assume the FP format is
|
||||
@ -278,7 +279,7 @@ __fpu_explode(fe, fp, type, reg)
|
||||
break;
|
||||
|
||||
default:
|
||||
__fpu_panic("fpu_explode");
|
||||
__utrap_panic("fpu_explode");
|
||||
}
|
||||
|
||||
if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) {
|
||||
|
@ -40,16 +40,13 @@
|
||||
#ifndef _SPARC64_FPU_FPU_EXTERN_H_
|
||||
#define _SPARC64_FPU_FPU_EXTERN_H_
|
||||
|
||||
struct proc;
|
||||
struct fpstate;
|
||||
struct utrapframe;
|
||||
union instr;
|
||||
struct fpemu;
|
||||
struct fpn;
|
||||
|
||||
/* fpu.c */
|
||||
void __fpu_exception(struct utrapframe *tf);
|
||||
void __fpu_panic(char *msg);
|
||||
int __fpu_exception(struct utrapframe *tf);
|
||||
|
||||
/* fpu_add.c */
|
||||
struct fpn *__fpu_add(struct fpemu *);
|
||||
|
@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "fpu_arith.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
#include "__sparc_utrap_private.h"
|
||||
|
||||
static int round(struct fpemu *, struct fpn *);
|
||||
static int toinf(struct fpemu *, int);
|
||||
@ -354,7 +355,7 @@ __fpu_ftos(fe, fp)
|
||||
(void) __fpu_shr(fp, FP_NMANT - FP_NG - 1 - SNG_FRACBITS);
|
||||
#ifdef DIAGNOSTIC
|
||||
if ((fp->fp_mant[3] & SNG_EXP(1 << FP_NG)) == 0)
|
||||
__fpu_panic("fpu_ftos");
|
||||
__utrap_panic("fpu_ftos");
|
||||
#endif
|
||||
if (round(fe, fp) && fp->fp_mant[3] == SNG_EXP(2))
|
||||
exp++;
|
||||
@ -529,7 +530,7 @@ __fpu_implode(fe, fp, type, space)
|
||||
break;
|
||||
|
||||
default:
|
||||
__fpu_panic("fpu_implode");
|
||||
__utrap_panic("fpu_implode");
|
||||
}
|
||||
DPRINTF(FPE_REG, ("fpu_implode: %x %x %x %x\n",
|
||||
space[0], space[1], space[2], space[3]));
|
||||
|
@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "fpu_arith.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
#include "__sparc_utrap_private.h"
|
||||
|
||||
/*
|
||||
* Shift the given number right rsh bits. Any bits that `fall off' will get
|
||||
@ -75,7 +76,7 @@ __fpu_shr(struct fpn *fp, int rsh)
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (rsh <= 0 || (fp->fp_class != FPC_NUM && !ISNAN(fp)))
|
||||
__fpu_panic("fpu_rightshift 1");
|
||||
__utrap_panic("fpu_rightshift 1");
|
||||
#endif
|
||||
|
||||
m0 = fp->fp_mant[0];
|
||||
@ -87,7 +88,7 @@ __fpu_shr(struct fpn *fp, int rsh)
|
||||
if (rsh >= FP_NMANT) {
|
||||
#ifdef DIAGNOSTIC
|
||||
if ((m0 | m1 | m2 | m3) == 0)
|
||||
__fpu_panic("fpu_rightshift 2");
|
||||
__utrap_panic("fpu_rightshift 2");
|
||||
#endif
|
||||
fp->fp_mant[0] = 0;
|
||||
fp->fp_mant[1] = 0;
|
||||
|
@ -1,7 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SRCS+= __sparc_utrap.c __sparc_utrap_fp_disabled.S __sparc_utrap_gen.S \
|
||||
__sparc_utrap_install.c __sparc_utrap_setup.c
|
||||
SRCS+= __sparc_utrap.c __sparc_utrap_emul.c __sparc_utrap_fp_disabled.S \
|
||||
__sparc_utrap_gen.S __sparc_utrap_install.c __sparc_utrap_setup.c
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/sparc64/fpu
|
||||
|
||||
MDASM+= brk.S cerror.S exect.S pipe.S ptrace.S sbrk.S setlogin.S
|
||||
|
||||
|
@ -32,8 +32,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/utrap.h>
|
||||
#include <machine/sysarch.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "__sparc_utrap_private.h"
|
||||
|
||||
@ -77,23 +80,55 @@ static const char *utrap_msg[] = {
|
||||
void
|
||||
__sparc_utrap(struct utrapframe *uf)
|
||||
{
|
||||
int sig;
|
||||
|
||||
switch (uf->uf_type) {
|
||||
case UT_FP_EXCEPTION_IEEE_754:
|
||||
case UT_FP_EXCEPTION_OTHER:
|
||||
__fpu_exception(uf);
|
||||
UF_DONE(uf);
|
||||
return;
|
||||
sig = __fpu_exception(uf);
|
||||
break;
|
||||
case UT_ILLEGAL_INSTRUCTION:
|
||||
sig = __emul_insn(uf);
|
||||
break;
|
||||
case UT_MEM_ADDRESS_NOT_ALIGNED:
|
||||
break;
|
||||
case UT_TRAP_INSTRUCTION_16:
|
||||
UF_DONE(uf);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("__sparc_utrap: type=%s pc=%#lx npc=%#lx\n",
|
||||
utrap_msg[uf->uf_type], uf->uf_pc, uf->uf_npc);
|
||||
abort();
|
||||
if (sig) {
|
||||
__utrap_write("__sparc_utrap: fatal ");
|
||||
__utrap_write(utrap_msg[uf->uf_type]);
|
||||
__utrap_write("\n");
|
||||
__utrap_kill_self(sig);
|
||||
}
|
||||
UF_DONE(uf);
|
||||
}
|
||||
|
||||
void
|
||||
__utrap_write(const char *str)
|
||||
{
|
||||
int berrno;
|
||||
|
||||
berrno = errno;
|
||||
__sys_write(STDERR_FILENO, str, strlen(str));
|
||||
errno = berrno;
|
||||
}
|
||||
|
||||
void
|
||||
__utrap_kill_self(sig)
|
||||
{
|
||||
int berrno;
|
||||
|
||||
berrno = errno;
|
||||
__sys_kill(__sys_getpid(), sig);
|
||||
errno = berrno;
|
||||
}
|
||||
|
||||
void
|
||||
__utrap_panic(const char *msg)
|
||||
{
|
||||
|
||||
__utrap_write(msg);
|
||||
__utrap_write("\n");
|
||||
__utrap_kill_self(SIGKILL);
|
||||
}
|
||||
|
157
lib/libc/sparc64/sys/__sparc_utrap_emul.c
Normal file
157
lib/libc/sparc64/sys/__sparc_utrap_emul.c
Normal file
@ -0,0 +1,157 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/frame.h>
|
||||
#include <machine/instr.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "__sparc_utrap_private.h"
|
||||
#include "fpu_reg.h"
|
||||
|
||||
int
|
||||
__emul_insn(struct utrapframe *uf)
|
||||
{
|
||||
u_long reg, res;
|
||||
u_long *addr;
|
||||
u_int insn;
|
||||
int sig;
|
||||
int rd;
|
||||
int i;
|
||||
|
||||
sig = 0;
|
||||
insn = *(u_int *)uf->uf_pc;
|
||||
flushw();
|
||||
switch (IF_OP(insn)) {
|
||||
case IOP_MISC:
|
||||
switch (IF_F3_OP3(insn)) {
|
||||
case INS2_POPC:
|
||||
if (IF_F3_RS1(insn) != 0) {
|
||||
sig = SIGILL;
|
||||
break;
|
||||
}
|
||||
reg = __emul_f3_op2(uf, insn);
|
||||
for (i = 0; i < 64; i++)
|
||||
res += (reg >> i) & 1;
|
||||
__emul_store_reg(uf, IF_F3_RD(insn), res);
|
||||
break;
|
||||
default:
|
||||
sig = SIGILL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IOP_LDST:
|
||||
switch (IF_F3_OP3(insn)) {
|
||||
case INS3_LDQF:
|
||||
rd = IF_F3_RD(insn);
|
||||
rd = (rd & ~3) | ((rd & 1) << 5);
|
||||
addr = (u_long *)__emul_f3_memop_addr(uf, insn);
|
||||
__fpu_setreg64(rd, addr[0]);
|
||||
__fpu_setreg64(rd + 2, addr[1]);
|
||||
break;
|
||||
case INS3_STQF:
|
||||
rd = IF_F3_RD(insn);
|
||||
rd = (rd & ~3) | ((rd & 1) << 5);
|
||||
addr = (u_long *)__emul_f3_memop_addr(uf, insn);
|
||||
addr[0] = __fpu_getreg64(rd);
|
||||
addr[1] = __fpu_getreg64(rd + 2);
|
||||
break;
|
||||
default:
|
||||
sig = SIGILL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sig = SIGILL;
|
||||
break;
|
||||
}
|
||||
return (sig);
|
||||
}
|
||||
|
||||
u_long
|
||||
__emul_fetch_reg(struct utrapframe *uf, int reg)
|
||||
{
|
||||
struct frame *frm;
|
||||
|
||||
if (reg == IREG_G0)
|
||||
return (0);
|
||||
else if (reg < IREG_O0) /* global */
|
||||
return (uf->uf_global[reg]);
|
||||
else if (reg < IREG_L0) /* out */
|
||||
return (uf->uf_out[reg - IREG_O0]);
|
||||
else { /* local, in */
|
||||
/*
|
||||
* The in registers are immediately after the locals in
|
||||
* the frame.
|
||||
*/
|
||||
frm = (struct frame *)(uf->uf_out[6] + SPOFF);
|
||||
return (frm->fr_local[reg - IREG_L0]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__emul_store_reg(struct utrapframe *uf, int reg, u_long val)
|
||||
{
|
||||
struct frame *frm;
|
||||
|
||||
if (reg == IREG_G0)
|
||||
return;
|
||||
if (reg < IREG_O0) /* global */
|
||||
uf->uf_global[reg] = val;
|
||||
else if (reg < IREG_L0) /* out */
|
||||
uf->uf_out[reg - IREG_O0] = val;
|
||||
else {
|
||||
/*
|
||||
* The in registers are immediately after the locals in
|
||||
* the frame.
|
||||
*/
|
||||
frm = (struct frame *)(uf->uf_out[6] + SPOFF);
|
||||
frm->fr_local[reg - IREG_L0] = val;
|
||||
}
|
||||
}
|
||||
|
||||
u_long
|
||||
__emul_f3_op2(struct utrapframe *uf, u_int insn)
|
||||
{
|
||||
|
||||
if (IF_F3_I(insn) != 0)
|
||||
return (IF_SIMM(insn, 13));
|
||||
else
|
||||
return (__emul_fetch_reg(uf, IF_F3_RS2(insn)));
|
||||
}
|
||||
|
||||
u_long
|
||||
__emul_f3_memop_addr(struct utrapframe *uf, u_int insn)
|
||||
{
|
||||
u_long addr;
|
||||
|
||||
addr = __emul_f3_op2(uf, insn) + __emul_fetch_reg(uf, IF_F3_RS1(insn));
|
||||
return (addr);
|
||||
}
|
@ -50,6 +50,16 @@ struct utrapframe {
|
||||
extern char __sparc_utrap_fp_disabled[];
|
||||
extern char __sparc_utrap_gen[];
|
||||
|
||||
int __emul_insn(struct utrapframe *uf);
|
||||
u_long __emul_fetch_reg(struct utrapframe *uf, int reg);
|
||||
void __emul_store_reg(struct utrapframe *uf, int reg, u_long val);
|
||||
u_long __emul_f3_op2(struct utrapframe *uf, u_int insn);
|
||||
u_long __emul_f3_memop_addr(struct utrapframe *uf, u_int insn);
|
||||
|
||||
void __sparc_utrap(struct utrapframe *);
|
||||
|
||||
void __utrap_write(const char *);
|
||||
void __utrap_kill_self(int);
|
||||
void __utrap_panic(const char *);
|
||||
|
||||
#endif
|
||||
|
@ -40,11 +40,10 @@ static const struct sparc_utrap_args ua[] = {
|
||||
{ UT_FP_DISABLED, __sparc_utrap_fp_disabled, NULL, NULL, NULL },
|
||||
{ UT_FP_EXCEPTION_IEEE_754, __sparc_utrap_gen, NULL, NULL, NULL },
|
||||
{ UT_FP_EXCEPTION_OTHER, __sparc_utrap_gen, NULL, NULL, NULL },
|
||||
#if 0
|
||||
{ UT_ILLEGAL_INSTRUCTION, __sparc_utrap_gen, NULL, NULL, NULL },
|
||||
#if 0
|
||||
{ UT_MEM_ADDRESS_NOT_ALIGNED, __sparc_utrap_gen, NULL, NULL, NULL },
|
||||
#endif
|
||||
{ UT_TRAP_INSTRUCTION_16, __sparc_utrap_gen, NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
static const struct sparc_utrap_install_args uia[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user