Initial check-in of the ieee fp support for the pc532.

ieee fp support by Ian Dall, NetBSD/pc532 integration by Matthias Pfaller.
Includes setjmp/longjmp added to locore.s.
This commit is contained in:
phil 1996-04-04 06:36:03 +00:00
parent 83f9bdc359
commit dba4d32f68
25 changed files with 2268 additions and 172 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: KLONDIKE,v 1.3 1996/01/26 05:12:58 phil Exp $
# $NetBSD: KLONDIKE,v 1.4 1996/04/04 06:36:03 phil Exp $
#
# KLONDIKE: Matthias Pfaller's pc532
#
@ -62,7 +62,7 @@ membus0 at root
ncr0 at membus?
scsibus0 at scsi?
scsibus0 at ncr0
sd* at scsibus? target ? lun ? # SCSI disks
st* at scsibus? target ? lun ? # SCSI tapes

View File

@ -1,4 +1,4 @@
# $NetBSD: files.pc532,v 1.20 1996/03/17 01:38:52 thorpej Exp $
# $NetBSD: files.pc532,v 1.21 1996/04/04 06:36:08 phil Exp $
#
# new style config file for pc532 architecture
#
@ -18,9 +18,9 @@ attach rd at membus
file arch/pc532/dev/rd.c rd needs-count
major {rd = 3}
#device timer
#device timer
#attach timer at membus
#device clock
#device clock
#attach clock at membus
file arch/pc532/pc532/clock.c # clock timer
@ -28,9 +28,9 @@ device scn: tty
attach scn at membus
file arch/pc532/dev/scn.c scn needs-flag
device lpt: ether, ifnet
device lpt: ether, ifnet
attach lpt at membus
file arch/pc532/dev/lpt.c lpt needs-count
file arch/pc532/dev/lpt.c lpt needs-count
include "../../../scsi/files.scsi"
major {sd = 0}
@ -42,7 +42,7 @@ attach ncr at membus
file arch/pc532/dev/ncr.c ncr needs-count
device oldncr: scsi
attach oldncr at membus
file arch/pc532/dev/oldncr.c oldncr needs-count
file arch/pc532/dev/oldncr.c oldncr needs-count
device dp: scsi
attach dp at membus
file arch/pc532/dev/dp.c dp needs-count
@ -50,12 +50,18 @@ device aic: scsi
attach aic at membus
file arch/pc532/dev/aic.c aic needs-count
file arch/pc532/fpu/ieee_dze.c
file arch/pc532/fpu/ieee_handler.c
file arch/pc532/fpu/ieee_invop.c
file arch/pc532/fpu/ieee_ovfl.c
file arch/pc532/fpu/ieee_subnormal.c
file dev/cons.c
file dev/cninit.c
file arch/pc532/pc532/autoconf.c
file arch/pc532/pc532/conf.c
file arch/pc532/pc532/db_disasm.c ddb
file arch/pc532/pc532/db_interface.c ddb
file arch/pc532/pc532/db_interface.c ddb
file arch/pc532/pc532/db_trace.c ddb
file arch/pc532/pc532/disksubr.c disk
file arch/pc532/pc532/icuinit.c

View File

@ -0,0 +1,69 @@
/* $NetBSD: fpu_status.h,v 1.1 1996/04/04 06:36:14 phil Exp $ */
/*
* IEEE floating point support for NS32081 and NS32381 fpus.
* Copyright (c) 1995 Ian Dall
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* IAN DALL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
* IAN DALL DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
* WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*/
/*
* File: fpu_status.h
* Author: Ian Dall
* Date: November 1995
*
* FPU status register definitions
*
* HISTORY
* 14-Dec-95 Ian Dall (Ian.Dall@dsto.defence.gov.au)
* First release.
*
*/
#ifndef _FPU_STATUS_H_
#define _FPU_STATUS_H_
/*
* Control register
*/
#define FPC_RMB 0x00010000 /* register modify bit */
#define FPC_SWF 0x0000fe00 /* reserved for software */
#define FPC_RM 0x00000180 /* rounding mode */
#define FPC_RM_NEAREST 0x00000000 /* round to nearest */
#define FPC_RM_TOZERO 0x00000080 /* round towards zero */
#define FPC_RM_TOPOS 0x00000100 /* round towards +infinity */
#define FPC_RM_TONEG 0x00000180 /* round towards -infinity */
#define FPC_IF 0x00000040 /* inexact result flag */
#define FPC_IEN 0x00000020 /* inexact result trap enable */
#define FPC_UF 0x00000010 /* underflow flag (else 0) */
#define FPC_UEN 0x00000008 /* underflow trap enable */
#define FPC_TT 0x00000007 /* trap type */
#define FPC_TT_NONE 0x00000000 /* no exceptional condition */
#define FPC_TT_UNDFL 0x00000001 /* underflow */
#define FPC_TT_OVFL 0x00000002 /* overflow */
#define FPC_TT_DIV0 0x00000003 /* divide by zero */
#define FPC_TT_ILL 0x00000004 /* illegal instruction */
#define FPC_TT_INVOP 0x00000005 /* invalid operation */
#define FPC_TT_INEXACT 0x00000006 /* inexact result */
/* Bits in the SWF field used for software emulation */
#define FPC_OVE 0x200 /* Overflow enable */
#define FPC_OVF 0x400 /* Overflow flag */
#define FPC_IVE 0x800 /* Invalid enable */
#define FPC_IVF 0x1000 /* Invalid flag */
#define FPC_DZE 0x2000 /* Divide by zero enable */
#define FPC_DZF 0x4000 /* Divide by zero flag */
#define FPC_UNDE 0x8000 /* Soft Underflow enable, requires FPC_UEN */
#define GET_SET_FSR(val) ({int _tmp; asm volatile("sfsr %0; lfsr %1" : "&=g" (_tmp): "g" (val)); _tmp;})
#define GET_FSR() ({int _tmp; asm volatile("sfsr %0" : "=g" (_tmp)); _tmp;})
#define SET_FSR(val) ({asm volatile("lfsr %0" :: "g" (val));})
#endif /* _FPU_STATUS_H_ */

View File

@ -0,0 +1,60 @@
/* $NetBSD: ieee_dze.c,v 1.1 1996/04/04 06:36:16 phil Exp $ */
/*
* IEEE floating point support for NS32081 and NS32381 fpus.
* Copyright (c) 1995 Ian Dall
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* IAN DALL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
* IAN DALL DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
* WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*/
/*
* File: ieee_dze.c
* Author: Ian Dall
* Date: November 1995
*
* Handle divide by zero, generating +-Infty as required.
*
* HISTORY
* 14-Dec-95 Ian Dall (Ian.Dall@dsto.defence.gov.au)
* First release.
*
*/
#include "ieee_internal.h"
int ieee_dze(struct operand *op1, struct operand *op2,
struct operand *f0_op, int xopcode, state *state)
{
int user_trap = FPC_TT_NONE;
unsigned int fsr = state->FSR;
DP(1, "Divide by zero trap: xopcode = 0x%x\n", xopcode);
fsr |= FPC_DZF;
if (fsr & FPC_DZE) {
/* Users trap handler will fix it */
user_trap = FPC_TT_DIV0;
}
else {
/* Set dest to + or - infinity ? */
int sign1 = op2->data.d_bits.sign;
int sign2 = op1->data.d_bits.sign;
op2->data = infty;
op2->data.d_bits.sign = sign1 ^ sign2;
switch(xopcode) {
case LOGBF:
/* logb(0) gives a divide by zero exception according to ieee.
* No idea if the logbf instruction conforms, but just in case...
*/
op2->data.d_bits.sign = 1;
}
}
state->FSR = fsr;
return user_trap;
}

View File

@ -0,0 +1,747 @@
/* $NetBSD: ieee_handler.c,v 1.1 1996/04/04 06:36:18 phil Exp $ */
/*
* IEEE floating point support for NS32081 and NS32381 fpus.
* Copyright (c) 1995 Ian Dall
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* IAN DALL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
* IAN DALL DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
* WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*/
/*
* File: ieee_handler.c
* Author: Ian Dall
* Date: November 1995
*
* Entry points for the ieee exception handling package.
* decodes floating point instructions.
*
* HISTORY
* 14-Dec-95 Ian Dall (Ian.Dall@dsto.defence.gov.au)
* First release.
*
*/
#include <sys/types.h>
#include <stddef.h>
#include "ieee_internal.h"
#include <machine/param.h>
#if defined(KERNEL) || defined(_KERNEL)
# ifdef __NetBSD__
# include <sys/systm.h>
# define longjmp(x, y) longjmp(&x)
# define setjmp(x) setjmp(&x)
# define AT void *
# else
# include <setjmp.h>
# define setjmp _setjmp
# define longjmp _longjmp
# define AT vm_offset_t
# endif
# define get_dword(addr) ({long _t; COPYIN((addr), (vm_offset_t) &_t, sizeof(long)); _t;})
#else /* KERNEL */
# include <setjmp.h>
# ifdef DEBUG
# include <stdio.h>
# endif
# define copyin(u,k,n) ({vm_offset_t _u = (u), _k = (k); memcpy((char *) _k, (char *) _u,n);0;})
# define copyout(k,u,n) ({vm_offset_t _u = (u), _k = (k); memcpy((char *) _u, (char *) _k,n);0;})
# define get_dword(addr) (* (unsigned int *) addr)
# define ns532_round_page(addr) (((addr) + NBPG - 1) & ~(NBPG - 1))
static void get_fstate(state *state) {
asm("sfsr %0" : "=g" (state->FSR));
asm("movl f0, %0" : "=m" (state->LREG(0)));
asm("movl f1, %0" : "=m" (state->LREG(1)));
asm("movl f2, %0" : "=m" (state->LREG(2)));
asm("movl f3, %0" : "=m" (state->LREG(3)));
asm("movl f4, %0" : "=m" (state->LREG(4)));
asm("movl f5, %0" : "=m" (state->LREG(5)));
asm("movl f6, %0" : "=m" (state->LREG(6)));
asm("movl f7, %0" : "=m" (state->LREG(7)));
}
static void set_fstate(state *state) {
/* DON'T tell gcc we are clobbering fp registers, else it will
* save and restore some, undoing our changes!
*/
asm("lfsr %0":: "g" (state->FSR));
asm("movl %0, f0":: "m" (state->LREG(0)));
asm("movl %0, f1":: "m" (state->LREG(1)));
asm("movl %0, f2":: "m" (state->LREG(2)));
asm("movl %0, f3":: "m" (state->LREG(3)));
asm("movl %0, f4":: "m" (state->LREG(4)));
asm("movl %0, f5":: "m" (state->LREG(5)));
asm("movl %0, f6":: "m" (state->LREG(6)));
asm("movl %0, f7":: "m" (state->LREG(7)));
}
int ieee_sig(int sig, int code, struct sigcontext *scp)
{
int ret;
vm_offset_t orig_pc;
state state;
get_fstate(&state);
state.scp = scp;
orig_pc = state.PC;
DP(1, "sig = 0x%x, code = 0x%x, pc = 0x%x, fsr = 0x%x\n", sig, code, state.PC, state.FSR);
ret = ieee_handle_exception(&state);
DP(1, " pc incremented by %d\n", state.PC - orig_pc);
set_fstate(&state);
return ret;
}
#endif /* KERNEL */
int ieee_handler_debug = 0;
#define COPYIN(U,K,N) ({if (copyin((AT)U, (AT)K, N) != 0) longjmp(copyin_buffer.copyfail, 1);0;})
/* Adressing modes. */
#define Adrmod_index_byte 0x1c
#define Adrmod_index_word 0x1d
#define Adrmod_index_doubleword 0x1e
#define Adrmod_index_quadword 0x1f
/* Is MODE an indexed addressing mode? */
#define Adrmod_is_index(mode) \
(mode == Adrmod_index_byte \
|| mode == Adrmod_index_word \
|| mode == Adrmod_index_doubleword \
|| mode == Adrmod_index_quadword)
/* Extract a bit field from a stream. Assume nbits less that
* or equal to 8. Also assume little endian. Assume no alignment
* restrictions on short.
*/
static inline int bit_extract(char *buffer, int offset, int nbits)
{
int start_byte = offset/8;
int end_byte = (offset + nbits - 1)/8;
return (((start_byte == end_byte? buffer[start_byte]:
*(short *)(buffer + start_byte)) >> offset%8)
& ((1 << nbits) - 1));
}
#ifdef DEBUG
static int invalid_float(union t_conv *p, int size)
{
int val;
if ( size == sizeof (float) )
val = (p->f_bits.exp == 0xff
|| (p->f_bits.exp == 0 && p->f_bits.mantissa != 0));
else if ( size == sizeof (double) )
val = (p->d_bits.exp == 0x7ff
|| (p->d_bits.exp == 0 && (p->d_bits.mantissa != 0 || p->d_bits.mantissa2 != 0)));
else
val = 1;
return (val);
}
static void print_op(struct operand *op)
{
if (op->type == op_type_float) {
if (invalid_float(&op->data, op->size)) {
if (op->size == sizeof(double)) {
printf("s: %d, e: %x, m1: %x, m2: %x", op->data.d_bits.sign, op->data.d_bits.exp, op->data.d_bits.mantissa, op->data.d_bits.mantissa2);
}
else {
printf("s: %d, e: %x, m1: %x", op->data.f_bits.sign, op->data.f_bits.exp, op->data.f_bits.mantissa);
}
}
else {
if (op->size == sizeof(double))
printf("%25.17e", op->data.d);
else
printf("%18.10e", op->data.f);
}
}
else
switch(op->size) {
case 1:
printf("%d", op->data.c);
break;
case 2:
printf("%d", op->data.s);
break;
case 4:
printf("%d", op->data.i);
break;
}
}
#endif
static const int regoffsets[] = {REGOFFSET(0), REGOFFSET(1), REGOFFSET(2),
REGOFFSET(3), REGOFFSET(4), REGOFFSET(5),
REGOFFSET(6), REGOFFSET(7)};
static inline void read_reg(int regno, struct operand *op, state *state) {
vm_offset_t addr = REGBASE(state) + regoffsets[regno];
switch(op->size) {
case 1: *(char *) &op->data = *(char *) addr; break;
case 2: *(short *) &op->data = *(short *) addr; break;
default: *(int *) &op->data = *(int *) addr; break;
}
op->where.tag = op_where_register;
op->where.addr = (vm_offset_t) &op->data;
}
static inline vm_offset_t reg_addr(int regno, state *state) {
return REGBASE(state) + regoffsets[regno];
}
static void read_freg(int regno, struct operand *op, state *state) {
vm_offset_t addr;
if (op->size == sizeof(float)) {
static const int offsets[] = {
FREGOFFSET(0), FREGOFFSET(1), FREGOFFSET(2), FREGOFFSET(3),
FREGOFFSET(4), FREGOFFSET(5), FREGOFFSET(6), FREGOFFSET(7)};
addr = FREGBASE(state) + offsets[regno];
*(float *) &op->data = *(float *) addr;
}
else {
static const int offsets[] = {
LREGOFFSET(0), LREGOFFSET(1), LREGOFFSET(2), LREGOFFSET(3),
LREGOFFSET(4), LREGOFFSET(5), LREGOFFSET(6), LREGOFFSET(7)};
addr = LREGBASE(state) + offsets[regno];
*(double *) &op->data = *(double *) addr;
}
op->where.tag = op_where_register;
op->where.addr = addr;
}
static int canonical_to_size(struct operand *op) {
int ret = FPC_TT_NONE;
union t_conv t = op->data;
if(op->type == op_type_float) {
if (op->size == sizeof(float)) {
unsigned long mantissa;
int exp = t.d_bits.exp + EXP_FBIAS - EXP_DBIAS;
op->data.f_bits.sign = t.d_bits.sign;
op->data.f_bits.exp = (exp < 0)? 0: ((exp > 0xff)? 0xff: exp);
if(exp >= 0xff && t.d_bits.exp < 0x7ff) {
/* Overflow. need +- infinity.
* Allow for trap on overflow.
*/
ret = FPC_TT_OVFL;
mantissa = 0;
}
else {
mantissa = t.d_bits.mantissa << 3;
mantissa |= (t.d_bits.mantissa2 >> 29) & 7;
if(exp <= 0) {
/* Denormalize */
mantissa |= 0x800000;
mantissa >>= -exp;
ret = FPC_TT_UNDFL;
}
if (mantissa == 0 && ISNAN(t))
mantissa = 0x400000; /* Signaling NaN */
}
op->data.f_bits.mantissa = mantissa;
}
}
else {
switch (op->size) {
case sizeof(char):
op->data.c = t.i;
break;
case sizeof(short):
op->data.s = t.i;
break;
}
}
return ret;
}
static void canonicalise_op(struct operand *op) {
union t_conv t = op->data;
if(op->type == op_type_float) {
if (op->size == sizeof(float)) {
op->data.d_bits.sign = t.f_bits.sign;
op->data.d_bits.exp = (t.f_bits.exp == 0xff)? 0x7ff: t.f_bits.exp + EXP_DBIAS - EXP_FBIAS;
op->data.d_bits.mantissa = t.f_bits.mantissa >> 3;
op->data.d_bits.mantissa2 = (t.f_bits.mantissa & 7) << 29;
if (t.f_bits.exp == 0 && t.f_bits.mantissa != 0) {
/* Was a subnormal float. Subnormal floats can always be converted
* to normal doubles.
*/
int norm;
op->data.d_bits.exp = 0;
norm = ieee_normalize(&(op->data));
op->data.d_bits.exp = EXP_DBIAS - EXP_FBIAS + norm;
}
}
}
else {
switch (op->size) {
case sizeof(char):
op->data.i = t.c;
break;
case sizeof(short):
op->data.i = t.s;
break;
}
}
}
#define MAX_LEN 21 /* The longest an instruction can be */
static struct {
vm_offset_t base;
char *max;
char buf[MAX_LEN];
#if defined(_KERNEL) && defined(__NetBSD__)
label_t copyfail;
#else
jmp_buf copyfail;
#endif
} copyin_buffer;
static void store_result(struct operand *op)
{
if (op->where.tag == op_where_memory) {
/* copyout */
if (copyout((AT) &op->data, (AT)op->where.addr, op->size) != 0) {
longjmp (copyin_buffer.copyfail, 1);
}
}
else {
/* Register */
memcpy((char *)op->where.addr, (char *) &op->data, op->size);
}
}
#define FETCH_DATA(addr) ((addr) < copyin_buffer.max? 1: fetch_data(addr))
#define BUF_TO_UADDR(addr) ((addr) - copyin_buffer.buf + copyin_buffer.base)
#define FETCH_CHUNK 8 /* Size of chunks to copyin */
#define MAX(x,y) ((x) > (y)? (x): (y))
#define MIN(x,y) ((x) < (y)? (x): (y))
/* Fetch data from user space so as to validate buffer up to addr.
* We do some read ahead (to minimise the number of copyins) but
* we never read ahead past a page boundary incase that would not
* be mapped.
*/
static int fetch_data (char *addr) {
vm_offset_t u_addr = copyin_buffer.base + copyin_buffer.max - copyin_buffer.buf;
vm_offset_t u_end_addr = copyin_buffer.base + addr - copyin_buffer.buf;
vm_offset_t k_addr = (vm_offset_t) copyin_buffer.max;
int n;
int status;
int n_page = ns532_round_page(u_end_addr) - copyin_buffer.base + copyin_buffer.buf - copyin_buffer.max;
int n_max = MAX_LEN + copyin_buffer.buf - copyin_buffer.max;
int n_min = addr - copyin_buffer.max + 1;
n = MIN(n_max, MAX(n_min, MIN(FETCH_CHUNK, n_page)));
status = COPYIN(u_addr, k_addr, n);
DP(2, "fetch_data: addr = 0x%x, from 0x%x, to 0x%x, n = %d\n", addr, u_addr, k_addr, n);
if (status != 0) {
longjmp (copyin_buffer.copyfail, 1);
}
else
copyin_buffer.max += n;
return 1;
}
static int get_displacement (char **buffer)
{
int disp;
char *buf = *buffer;
FETCH_DATA(buf);
switch (*buf & 0xc0)
{
case 0x00:
case 0x40:
disp = *buf++ & 0x7f;
disp = (disp & 0x40) ? disp | 0xffffff80: disp;
break;
case 0x80:
FETCH_DATA(buf + 1);
disp = *buf++ & 0x3f;
disp = (disp & 0x20) ? disp | 0xffffffc0: disp;
disp = (disp << 8) | (0xff & *buf++);
break;
case 0xc0:
FETCH_DATA(buf + 3);
disp = *buf++ & 0x3f;
disp = (disp & 0x20) ? disp | 0xffffffc0: disp;
disp = (disp << 8) | (0xff & *buf++);
disp = (disp << 8) | (0xff & *buf++);
disp = (disp << 8) | (0xff & *buf++);
break;
}
*buffer = buf;
DP(1, "disp = %d\n", disp);
return disp;
}
static int get_operand(char **buf, unsigned char gen, unsigned char index, struct operand *op, state *state)
{
int ret = FPC_TT_NONE;
vm_offset_t addr;
int disp1, disp2;
DP(1,"gen = 0x%x\n", gen);
if (op->type == op_type_float && (gen & ~7) == 0) {
read_freg(gen, op, state);
return ret;
}
switch (gen) {
case 0: case 1: case 2: case 3:
case 4: case 5: case 6: case 7:
if (op->class != op_class_addr) {
read_reg(gen, op, state);
return ret;
}
else
addr = reg_addr(gen, state);
break;
case 0x8: case 0x9: case 0xa: case 0xb:
case 0xc: case 0xd: case 0xe: case 0xf:
/* Register relative disp(R0 -- R7) */
/* rn out of state, then get data out of res_addr */
disp1 = get_displacement (buf);
addr = (disp1 + reg_addr(gen & 7, state));
break;
case 0x10:
case 0x11:
case 0x12:
/* Memory relative disp2(disp1(FP, SP, SB)) */
disp1 = get_displacement (buf);
disp2 = get_displacement (buf);
addr = (disp1
+ (vm_offset_t) (gen == 0x10? state->FP: (gen == 0x11? state->SP:
state->SB)));
addr = disp2 + get_dword(addr);
break;
case 0x14:
/* Immediate */
if (op->class == op_class_read) {
char *p;
int i;
FETCH_DATA(*buf + op->size - 1);
for(p = (char *)&op->data, i = op->size; i--; p++) {
*p = *(*buf + i);
}
op->where.tag = op_where_immediate;
op->where.addr = 0;
*buf += op->size;
return ret;
}
else {
return FPC_TT_ILL;
}
case 0x15:
/* Absolute @disp */
disp1 = get_displacement (buf);
addr = disp1;
break;
case 0x16:
/* External EXT(disp1) + disp2 (Mod table stuff) */
disp1 = get_displacement (buf);
disp2 = get_displacement (buf);
return FPC_TT_ILL; /* Unsupported */
case 0x17:
/* Top of stack tos */
addr = state->SP;
switch (op->class) {
case op_class_read:
state->SP += op->size;
break;
case op_class_write:
state->SP -= op->size;
addr = state->SP;
break;
}
break;
case 0x18:
/* Memory space disp(FP) */
disp1 = get_displacement (buf);
addr = (disp1 + (unsigned int) state->FP);
break;
case 0x19:
/* Memory space disp(SP) */
disp1 = get_displacement (buf);
addr = (disp1 + (unsigned int) state->SP);
break;
case 0x1a:
/* Memory space disp(SB) */
disp1 = get_displacement (buf);
addr = (disp1 + (unsigned int) state->SB);
break;
case 0x1b:
/* Memory space disp(PC) */
{
vm_offset_t disp_addr = BUF_TO_UADDR(*buf);
disp1 = get_displacement (buf);
addr = disp1 + disp_addr;
}
break;
case 0x1c:
case 0x1d:
case 0x1e:
case 0x1f:
/* Scaled index basemode[R0 -- R7:B,W,D,Q] */
{
enum op_class save = op->class;
op->class = op_class_addr;
if ((ret = get_operand(buf, index >> 3, 0, op, state)) != FPC_TT_NONE)
return ret;
addr = op->where.addr + (* (int *) reg_addr(index & 7, state)) * (1 << (gen & 3));
op->class = save;
break;
}
}
if (op->class == op_class_read || op->class == op_class_rmw) {
COPYIN(addr, (vm_offset_t)&op->data, op->size);
}
op->where.tag = op_where_memory;
op->where.addr = addr;
return ret;
}
static int default_trap_handle(struct operand *op1, struct operand *op2, struct operand *f0_op, int xopcode, state *state)
{
int user_trap = FPC_TT_NONE;
unsigned int fsr = state->FSR;
int trap_type = fsr & FPC_TT;
DP(2, "trap type %d\n", trap_type);
{
int s = GET_SET_FSR(fsr & FPC_RM); /* Same rounding mode as at exception */
switch (trap_type)
{
case FPC_TT_UNDFL: /* Underflow */
user_trap = ieee_undfl(op1, op2, f0_op, xopcode, state);
break;
case FPC_TT_OVFL: /* Overflow */
user_trap = ieee_ovfl(op1, op2, f0_op, xopcode, state);
break;
case FPC_TT_DIV0: /* Divide by zero */
user_trap = ieee_dze(op1, op2, f0_op, xopcode, state);
break;
case FPC_TT_ILL: /* Illegal instruction */
/* Illegal instruction. Cause a SIGILL ? */
user_trap = FPC_TT_ILL;
break;
case FPC_TT_INVOP: /* Invalid operation */
user_trap = ieee_invop(op1, op2, f0_op, xopcode, state);
break;
case FPC_TT_INEXACT: /* Inexact result */
/* Nothing to be done */
/* Flags in hardware. We can't get here unless FPC_IEF is set */
user_trap = FPC_TT_INEXACT;
break;
case FPC_TT_NONE:
default:
DP(0,"ieee_handler: fpu trap type none\n");
}
SET_FSR(s);
}
return user_trap;
}
int ieee_handle_exception(state *state)
{
int fmt, xopcode, ret;
int fsr, user_trap = FPC_TT_NONE;
volatile int ofsr; /* Volatile for setjmp */
unsigned char int_type, float_type, opcode, gen1, gen2, index1, index2;
struct operand op1, op2, f0_op, *res;
char *buf = copyin_buffer.buf;
copyin_buffer.base = state->PC;
/* Save fsr and set fsr to 0 so that floating point operations within
* the emulation proceed in a known way. */
ofsr = GET_SET_FSR(0);
if (setjmp(copyin_buffer.copyfail) != 0) {
SET_FSR(ofsr);
return FPC_TT_ILL;
}
copyin_buffer.max = buf;
/* All fp instructions are 24 bits
* and extensions start after 3 bytes
*/
FETCH_DATA(buf + 2);
fsr = state->FSR;
switch(fmt = bit_extract(buf, 0, 8))
{
case 0x3e: /* Format 9 */
int_type = bit_extract(buf, 8, 2);
float_type = bit_extract(buf, 10, 1);
opcode = bit_extract(buf, 11, 3);
fmt = fmt9;
break;
case 0xbe: /* Format 11 */
case 0xfe: /* Format 12 */
fmt = (fmt == 0xbe)? fmt11: fmt12;
float_type = bit_extract(buf, 8, 1);
opcode = bit_extract(buf, 10, 4);
break;
default:
user_trap = FPC_TT_ILL;
DP(0, "ieee_handler: format not of a floating point instruction\n");
}
xopcode = XOPCODE(fmt, opcode);
DP(2, "xopcode: 0x%x\n", xopcode);
gen2 = bit_extract(buf, 14, 5);
gen1 = bit_extract(buf, 19, 5);
buf += 3;
if (Adrmod_is_index(gen1)) {
FETCH_DATA(buf);
index1 = *buf++;
}
if (Adrmod_is_index(gen2)) {
FETCH_DATA(buf);
index2 = *buf++;
}
op1.class = op_class_read;
op2.class = op_class_rmw;
op1.type = op2.type = op_type_float;
op1.size = op2.size = float_type? 4: 8;
res = &op2;
switch(xopcode) {
case MOVLF:
op1.type = op_type_float; op1.size = 8;
op2.size = 4; op2.class = op_class_write;
break;
case MOVFL:
op1.type = op_type_float; op1.size = 4;
op2.size = 8; op2.class = op_class_write;
break;
case MOVIF:
op1.type = op_type_int; op1.size = 1 << int_type;
op2.class = op_class_write;
break;
case NEGF:
op2.class = op_class_write;
break;
case ROUNDFI:
case TRUNCFI:
case FLOORFI:
op2.type = op_type_int; op2.size = 1 << int_type;
break;
case CMPF:
op2.class = op_class_read;
res = 0;
break;
case POLYF:
case DOTF:
op1.type = op2.type = f0_op.type = op_type_float;
op1.size = op2.size = f0_op.size = float_type? 4: 8;
op2.class = op_class_read;
f0_op.class = op_class_rmw;
read_freg(0, &f0_op, state);
canonicalise_op(&f0_op);
res = &f0_op;
break;
}
if ((ret = get_operand(&buf, gen1, index1, &op1, state)) != FPC_TT_NONE) {
user_trap = ret;
DP(0, "get_operand failed\n");
}
if ((ret = get_operand(&buf, gen2, index2, &op2, state)) != FPC_TT_NONE) {
user_trap = ret;
DP(0, "get_operand failed\n");
}
#ifdef DEBUG
if (ieee_handler_debug > 1) {
printf( "op1 = "); print_op(&op1); printf("\n");
printf( "op2 = "); print_op(&op2); printf("\n");
}
#endif
canonicalise_op(&op1);
canonicalise_op(&op2);
if(user_trap == FPC_TT_NONE) {
user_trap = default_trap_handle(&op1, &op2, &f0_op, xopcode, state);
/* user_trap now has traps generated during emulation. Correct ieee
* results already calculated, but must see whether we need to
* pass trap on to user.
*
* User trap can be set for many reasons. eg dividing a denorm by 0
* might initially result in an invalid operand trap, but during
* emulation we set the divide by zero trap.
*/
if (res) {
int ret;
if((ret = canonical_to_size(res)) != FPC_TT_NONE)
user_trap = ret;
}
switch (user_trap) {
case FPC_TT_UNDFL:
fsr |= FPC_UF;
if ((fsr & FPC_UNDE) == 0)
user_trap = FPC_TT_NONE;
break;
case FPC_TT_OVFL:
fsr |= FPC_OVF;
if ((fsr & FPC_OVE) == 0)
user_trap = FPC_TT_NONE;
break;
case FPC_TT_DIV0:
fsr |= FPC_DZF;
if ((fsr & FPC_DZE) == 0)
user_trap = FPC_TT_NONE;
break;
case FPC_TT_ILL:
break;
case FPC_TT_INVOP:
fsr |= FPC_IVF;
if ((fsr & FPC_IVE) == 0)
user_trap = FPC_TT_NONE;
break;
case FPC_TT_INEXACT:
fsr |= FPC_IF;
if ((fsr & FPC_IEN) == 0)
user_trap = FPC_TT_NONE;
break;
}
}
if(user_trap == FPC_TT_NONE) {
/* Otherwise the user trap must step over the instruction if it wants
* to resume
*/
if(res) {
#ifdef DEBUG
if (ieee_handler_debug > 1) {
printf( "res = "); print_op(res); printf("\n");
}
#endif
store_result(res);
}
state->PC = BUF_TO_UADDR(buf);
}
SET_FSR(ofsr);
state->FSR = fsr;
return user_trap;
}

View File

@ -0,0 +1,129 @@
/* $NetBSD: ieee_handler.h,v 1.1 1996/04/04 06:36:20 phil Exp $ */
/*
* IEEE floating point support for NS32081 and NS32381 fpus.
* Copyright (c) 1995 Ian Dall
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* IAN DALL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
* IAN DALL DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
* WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*/
/*
* File: ieee_handler.h
* Author: Ian Dall
* Date: November 1995
*
* Prototypes for entry points. Customization for in kernel version
* or unix signal handler version.
*
* HISTORY
* 14-Dec-95 Ian Dall (Ian.Dall@dsto.defence.gov.au)
* First release.
*
*/
#ifndef _IEEE_HANDLER_H_
#define _IEEE_HANDLER_H_
#if defined(KERNEL) || defined(_KERNEL)
#ifdef MACH
#include <ns532/thread.h>
#include <mach/vm_param.h>
#include "mach_kdb.h"
#if MACH_KDB
#define DEBUG
#endif
typedef struct {
struct ns532_saved_state *regs;
struct ns532_fp_state *fps;
} state;
#define LREGBASE(s) ((vm_offset_t) (s)->fps)
#define LREGOFFSET(n) offsetof(struct ns532_fp_state, regs.l.l ## n)
#define FREGBASE(s) ((vm_offset_t) (s)->fps)
#define FREGOFFSET(n) offsetof(struct ns532_fp_state, regs.f.f ## n)
#define REGBASE(s) ((vm_offset_t) (s)->regs)
#define REGOFFSET(n) offsetof(struct ns532_saved_state, r ## n)
#define FSR fps->fsr
#define FP regs->fp
#define SP regs->usp
#define SB regs->sb
#define PC regs->pc
#define PSR regs->psr
#elif defined(__NetBSD__) /* MACH */
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/user.h>
typedef struct proc state;
#define LREGBASE(s) ((vm_offset_t) (s)->p_addr->u_pcb.pcb_freg)
#define LREGOFFSET(n) (n * sizeof(double))
#define FREGBASE(s) ((vm_offset_t) (s)->p_addr->u_pcb.pcb_freg)
#define FREGOFFSET(n) ((n & ~1) * sizeof(double) + (n & 1) * sizeof(float))
#define REGBASE(s) ((vm_offset_t) (s)->p_md.md_regs)
#define REGOFFSET(n) offsetof(struct reg, r_r ## n)
#define FSR p_addr->u_pcb.pcb_fsr
#define FP p_md.md_regs->r_fp
#define SP p_md.md_regs->r_sp
#define SB p_md.md_regs->r_sb
#define PC p_md.md_regs->r_pc
#define PSR p_md.md_regs->r_psr
#define PSR_N PSL_N
#define PSR_Z PSL_Z
#define PSR_L PSL_L
#else /* __NetBSD__ */
#error OS unsupported
#endif /* __NetBSD__ */
#else /* KERNEL || _KERNEL */
#include <signal.h>
struct fstate {
unsigned int fsr;
union {
struct { double l0, l2, l4, l6, l1, l3, l5, l7;} l;
struct { float f0, f1, f2, f3, f4, f5, f6, f7;} f;
} regs;
};
struct ns532_combined_state {
struct sigcontext *scp;
struct fstate fs;
};
typedef struct ns532_combined_state state;
#define LREG(REG) fs.regs.l.l ## REG
#define LREGBASE(s) ((vm_offset_t) &(s)->fs)
#define LREGOFFSET(n) offsetof(struct fstate, regs.l.l ## n)
#define FREGBASE(s) ((vm_offset_t) &(s)->fs)
#define FREGOFFSET(n) offsetof(struct fstate, regs.f.f ## n)
#define REGBASE(s) ((vm_offset_t) (s)->scp)
#define REGOFFSET(n) offsetof(struct sigcontext, sc_reg[n])
#define FSR fs.fsr
#define FP scp->sc_fp
#define SP scp->sc_sp
#define SB scp->sc_sb
#define PC scp->sc_pc
#define PSR scp->sc_ps
int ieee_sig(int sig, int code, struct sigcontext *scp);
#endif /* KERNEL */
int ieee_handle_exception(state *state);
#endif /* _IEEE_HANDLER_H_ */

View File

@ -0,0 +1,158 @@
/* $NetBSD: ieee_internal.h,v 1.1 1996/04/04 06:36:22 phil Exp $ */
/*
* IEEE floating point support for NS32081 and NS32381 fpus.
* Copyright (c) 1995 Ian Dall
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* IAN DALL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
* IAN DALL DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
* WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*/
/*
* File: ieee_internal.h
* Author: Ian Dall
* Date: November 1995
*
* Prototypes and structure definitions internal to the ieee exception
* handling package.
*
*
* HISTORY
* 14-Dec-95 Ian Dall (Ian.Dall@dsto.defence.gov.au)
* First release.
*
*/
#ifndef _IEEE_INTERNAL_H_
#define _IEEE_INTERNAL_H_
#include "ieee_handler.h"
#include "fpu_status.h"
#ifdef DEBUG
extern int ieee_handler_debug;
#define DP(n, format, args...) if (ieee_handler_debug >= n) printf(format, ## args)
#else
#define DP(n, format, args...)
#endif
enum format { fmt9, fmt11, fmt12};
#define XOPCODE(fmt, opcode) ((opcode) << 2 | (fmt))
#define MOVF XOPCODE(fmt11, 1)
#define MOVLF XOPCODE(fmt9, 2)
#define MOVFL XOPCODE(fmt9, 3)
#define MOVIF XOPCODE(fmt9, 0)
#define ROUNDFI XOPCODE(fmt9, 4)
#define TRUNCFI XOPCODE(fmt9, 5)
#define FLOORFI XOPCODE(fmt9, 7)
#define ADDF XOPCODE(fmt11, 0)
#define SUBF XOPCODE(fmt11, 4)
#define MULF XOPCODE(fmt11, 12)
#define DIVF XOPCODE(fmt11, 8)
#define NEGF XOPCODE(fmt11, 5)
#define ABSF XOPCODE(fmt11, 13)
#define SCALBF XOPCODE(fmt12, 4)
#define LOGBF XOPCODE(fmt12, 5)
#define DOTF XOPCODE(fmt12, 3)
#define POLYF XOPCODE(fmt12, 2)
#define CMPF XOPCODE(fmt11, 2)
#define LFSR XOPCODE(fmt9, 1)
#define SFSR XOPCODE(fmt9, 6)
union t_conv {
double d;
float f;
struct {
unsigned int mantissa2:32;
unsigned int mantissa:20;
unsigned int exp:11;
unsigned int sign :1;
} d_bits;
struct {
unsigned int mantissa:23;
unsigned int exp:8;
unsigned int sign :1;
} f_bits;
signed char c;
short s;
int i;
};
/* These assume "double" interpretation of the union is valid */
#define ISNAN(data) ((data).d_bits.exp == 0x7ff && \
((data).d_bits.mantissa != 0 || (data).d_bits.mantissa2 != 0))
#define ISQNAN(data) ((data).d_bits.exp == 0x7ff && \
((data).d_bits.mantissa & 0x80000) != 0)
#define ISSNAN(data) ((data).d_bits.exp == 0x7ff && \
((data).d_bits.mantissa & 0x80000) == 0 && \
((data).d_bits.mantissa != 0 || (data).d_bits.mantissa2 != 0))
#define ISINFTY(data) ((data).d_bits.exp == 0x7ff && (data).d_bits.mantissa == 0 && \
(data).d_bits.mantissa2 == 0)
#define ISDENORM(data) ((data).d_bits.exp == 0 && ((data).d_bits.mantissa != 0 || (data).d_bits.mantissa2 != 0))
#define ISZERO(data) ((data).d_bits.exp == 0 && (data).d_bits.mantissa == 0 && (data).d_bits.mantissa2 == 0)
#define EXP_DBIAS 1023
#define EXP_FBIAS 127
enum op_type {op_type_float, op_type_int};
enum op_class {op_class_read, op_class_write, op_class_rmw, op_class_addr};
enum op_where_tag { op_where_register, op_where_memory, op_where_immediate };
static const union t_conv infty = {d_bits: { sign: 0, exp: 0x7ff, mantissa: 0, mantissa2: 0}};
static const union t_conv snan = {d_bits: { sign: 0, exp: 0x7ff, mantissa: 0x40000, mantissa2: 0}};
static const union t_conv qnan = {d_bits: { sign: 0, exp: 0x7ff, mantissa: 0x80000, mantissa2: 0}};
struct operand {
enum op_type type;
enum op_class class;
struct {
enum op_where_tag tag;
vm_offset_t addr;
} where;
char size;
union t_conv data;
};
int ieee_undfl(struct operand *op1, struct operand *op2,
struct operand *f0_op, int xopcode, state *state);
int ieee_ovfl(struct operand *op1, struct operand *op2,
struct operand *f0_op, int xopcode, state *state);
int ieee_dze(struct operand *op1, struct operand *op2,
struct operand *f0_op, int xopcode, state *state);
int ieee_invop(struct operand *op1, struct operand *op2,
struct operand *f0_op, int xopcode, state *state);
int ieee_add(double data1, double *data2);
int ieee_mul(double data1, double *data2);
int ieee_div(double data1, double *data2);
int ieee_dot(double data1, double data2, double *data3);
void ieee_cmp(double data1, double data2, state *status);
int ieee_normalize(union t_conv *data);
int ieee_scalb(double data1, double *data2);
#endif /* _IEEE_INTERNAL_H_ */

View File

@ -0,0 +1,294 @@
/* $NetBSD: ieee_invop.c,v 1.1 1996/04/04 06:36:25 phil Exp $ */
/*
* IEEE floating point support for NS32081 and NS32381 fpus.
* Copyright (c) 1995 Ian Dall
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* IAN DALL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
* IAN DALL DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
* WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*/
/*
* File: ieee_invop.c
* Author: Ian Dall
* Date: November 1995
*
* Handle operations which generated reserved operand traps.
*
* HISTORY
* 14-Dec-95 Ian Dall (Ian.Dall@dsto.defence.gov.au)
* First release.
*
*/
#include "ieee_internal.h"
#include <machine/psl.h>
#include <limits.h>
static int nan_2(union t_conv data1, union t_conv *data2)
{
int nans = (ISNAN(data1)? 1: 0) + (ISNAN(*data2)? 2: 0);
switch (nans) {
case 0:
return 0;
case 1:
*data2 = data1;
break;
case 2:
break;
case 3:
if((data1.d_bits.mantissa > data2->d_bits.mantissa)
|| (data1.d_bits.mantissa == data1.d_bits.mantissa
&& data1.d_bits.mantissa2 > data2->d_bits.mantissa2)) {
*data2 = data1;
}
break;
}
return 1;
}
static int add_iv (struct operand *op1, struct operand *op2)
{
int inftys;
int ret = FPC_TT_NONE;
if(nan_2(op1->data, &op2->data)) {
return ret;
}
inftys = (ISINFTY(op1->data)? 1: 0) + (ISINFTY(op2->data)? 2:0);
switch (inftys) {
case 0:
break;
case 1:
op2->data = op1->data;
return ret;
case 2:
return ret;
case 3:
if(op1->data.d_bits.sign != op2->data.d_bits.sign)
op2->data = qnan;
return ret;
}
/* Must be subnormals */
return ieee_add(op1->data.d, &op2->data.d);
}
static int div_iv (struct operand *op1, struct operand *op2)
{
int inftys, sign1, sign2;
int ret = FPC_TT_NONE;
if(nan_2(op1->data, &op2->data)) {
return ret;
}
inftys = (ISINFTY(op1->data)? 1: 0) + (ISINFTY(op2->data)? 2:0);
sign1 = op1->data.d_bits.sign;
sign2 = op2->data.d_bits.sign;
switch (inftys) {
case 0:
break;
case 1: /* n/oo */
{
op2->data.d = 0.0;
op2->data.d_bits.sign = sign1 ^ sign2;
return ret;
}
case 2: /* oo/n */
op2->data.d_bits.sign = sign1 ^ sign2;
return ret;
case 3:
op2->data = qnan;
return ret;
}
/* Must be subnormals */
return ieee_div(op1->data.d, &op2->data.d);
}
static int mul_iv (struct operand *op1, struct operand *op2)
{
int inftys, sign1, sign2;
int ret = FPC_TT_NONE;
if(nan_2(op1->data, &op2->data)) {
return ret;
}
inftys = (ISINFTY(op1->data)? 1: 0) + (ISINFTY(op2->data)? 2:0);
sign1 = op1->data.d_bits.sign;
sign2 = op2->data.d_bits.sign;
switch (inftys) {
case 0:
break;
case 1: /* oo * n */
{
op2->data = ISZERO(op1->data)? qnan: op1->data;
op2->data.d_bits.sign = sign1 ^ sign2;
return ret;
}
case 2: /* n * oo */
case 3: /* oo * oo */
op2->data.d_bits.sign = sign1 ^ sign2;
return ret;
}
/* Must be subnormals */
return ieee_mul(op1->data.d, &op2->data.d);
}
static int dot_iv (struct operand *op1, struct operand *op2, struct operand *op3)
{
int inftys;
int ret = FPC_TT_NONE;
union t_conv t = op2->data;
if(nan_2(op1->data, &t)) {
if(nan_2(t, &op3->data))
return ret;
}
inftys = ((ISINFTY(op1->data)? 1: 0) + (ISINFTY(op2->data)? 2:0)
+ (ISINFTY(op3->data)? 4: 0));
switch (inftys) {
case 0:
break;
case 1: case 2: case 3: /* oo * n + m or n * oo + m or oo * oo + m */
op3->data = op2->data;
return mul_iv(op1, op3);
case 4: /* n * m + oo */
return ret;
case 5: case 6: case 7:
{
struct operand t = *op2;
mul_iv(op1, &t);
add_iv(&t, op3);
return ret;
}
}
/* Must be subnormals */
return ieee_dot(op1->data.d, op2->data.d, &op3->data.d);
}
static int poly_iv (struct operand *op1, struct operand *op2, struct operand *op3)
{
int ret;
struct operand t = *op2;
ret = dot_iv(op3, op1, &t);
*op3 = t;
return ret;
}
static int round_iv (struct operand *op1, struct operand *op2, int xopcode)
{
int ret = FPC_TT_NONE;
if(ISNAN(op1->data)) {
/* XXX */
op2->data.i = 0;
return FPC_TT_INVOP; /* Need a special code */
}
else if (ISINFTY(op1->data)) {
op2->data.i = op1->data.d_bits.sign? INT_MIN: INT_MAX;
} else {
/* Must be a denorm */
op2->data.i = 0;
}
return ret;
}
static int scalb_iv (struct operand *op1, struct operand *op2)
{
int ret = FPC_TT_NONE;
if(nan_2(op1->data, &op2->data)) {
return ret;
}
return ieee_scalb(op1->data.d, &op2->data.d);
}
static int logb_iv (struct operand *op1, struct operand *op2)
{
int ret = FPC_TT_NONE;
if (ISNAN(op1->data))
op2->data = op1->data;
else if(ISINFTY(op1->data))
op2->data = infty;
else {
/* Is a denormal */
union t_conv t = op1->data;
int norm = ieee_normalize(&t);
op2->data.d = t.d_bits.exp + norm;
}
return ret;
}
static void cmp_iv(struct operand *op1, struct operand *op2, state *state)
{
state->PSR &= ~(PSR_N | PSR_Z | PSR_L);
if (ISNAN(op1->data) || ISNAN(op2->data)) {
return;
}
ieee_cmp(op1->data.d, op2->data.d, state);
return;
}
int ieee_invop(struct operand *op1, struct operand *op2,
struct operand *f0_op, int xopcode, state *state)
{
int user_trap = FPC_TT_NONE;
unsigned int fsr = state->FSR;
/* Source is Infty, NaN or Subnormal (or 0 if dividing 0 by 0) */
fsr |= FPC_IVF;
if (fsr & FPC_IVE) {
/* Users trap handler will fix it */
user_trap = FPC_TT_INVOP;
}
else {
/*
* Figure out right thing to do.
*/
switch(xopcode) {
case NEGF:
op1->data.d_bits.sign ^= 1;
/* Fall through */
case MOVF:
case MOVLF:
case MOVFL:
op2->data = op1->data;
break;
case CMPF:
cmp_iv(op1, op2, state);
break;
case SUBF:
op1->data.d_bits.sign ^= 1;
/* Fall through */
case ADDF:
user_trap = add_iv(op1, op2);
break;
case MULF:
user_trap = mul_iv(op1, op2);
break;
case DIVF:
user_trap = div_iv(op1, op2);
break;
case ROUNDFI:
case TRUNCFI:
case FLOORFI:
user_trap = round_iv(op1, op2, xopcode);
break;
case SCALBF:
user_trap = scalb_iv(op1, op2);
break;
case LOGBF:
user_trap = logb_iv(op1, op2);
break;
case DOTF:
user_trap = dot_iv(op1, op2, f0_op);
break;
case POLYF:
user_trap = poly_iv(op1, op2, f0_op);
break;
}
}
state->FSR = fsr;
return user_trap;
}

View File

@ -0,0 +1,104 @@
/* $NetBSD: ieee_ovfl.c,v 1.1 1996/04/04 06:36:27 phil Exp $ */
/*
* IEEE floating point support for NS32081 and NS32381 fpus.
* Copyright (c) 1995 Ian Dall
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* IAN DALL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
* IAN DALL DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
* WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*/
/*
* File: ieee_ovfl.c
* Author: Ian Dall
* Date: November 1995
*
* Handle operations which generated overflow traps.
*
* HISTORY
* 14-Dec-95 Ian Dall (Ian.Dall@dsto.defence.gov.au)
* First release.
*
*/
#include "ieee_internal.h"
#include <limits.h>
int ieee_ovfl(struct operand *op1, struct operand *op2,
struct operand *f0_op, int xopcode, state *state)
{
int user_trap = FPC_TT_NONE;
unsigned int fsr = state->FSR;
fsr |= FPC_OVF;
if (fsr & FPC_OVE) {
/* Users trap handler will fix it */
user_trap = FPC_TT_OVFL;
}
else {
/* If destination is float or double, set to +- Infty, else
* if byte, word or long, set to max/min int.
*/
int sign1 = op1->data.d_bits.sign;
int sign2 = op2->data.d_bits.sign;
switch(xopcode) {
case NEGF:
sign1 ^= 1;
/* Fall through */
case MOVF:
case MOVLF:
case MOVFL:
op2->data = infty;
op2->data.d_bits.sign = sign1;
break;
case CMPF:
/* Can't happen */
break;
case SUBF:
sign1 ^= 1;
/* Fall through */
case ADDF:
/* Overflow can only happen if both operands are same sign */
op2->data = infty;
op2->data.d_bits.sign = sign2;
break;
case MULF:
case DIVF:
op2->data = infty;
op2->data.d_bits.sign = sign1 ^ sign2;
break;
case ROUNDFI:
case TRUNCFI:
case FLOORFI:
op2->data.i = sign1? INT_MIN: INT_MAX;
break;
case SCALBF:
op2->data = infty;
op2->data.d_bits.sign = sign1;
break;
case LOGBF:
op2->data = infty;
op2->data.d_bits.sign = ISZERO(op1->data)? 1: 0;
break;
case DOTF:
(void) ieee_dot(op1->data.d, op2->data.d, &f0_op->data.d);
break;
case POLYF:
{
union t_conv t;
t = op2->data;
(void) ieee_dot(f0_op->data.d, op1->data.d, &t.d);
f0_op->data = t;
}
break;
}
}
state->FSR = fsr;
return user_trap;
}

View File

@ -0,0 +1,429 @@
/* $NetBSD: ieee_subnormal.c,v 1.1 1996/04/04 06:36:30 phil Exp $ */
/*
* IEEE floating point support for NS32081 and NS32381 fpus.
* Copyright (c) 1995 Ian Dall
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* IAN DALL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
* IAN DALL DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
* WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*/
/*
* File: ieee_subnormal.c
* Author: Ian Dall
* Date: November 1995
*
* Handle operations which generated underflow traps. Subnormal
* (denormalized numbers) are generated as required.
*
* HISTORY
* 14-Dec-95 Ian Dall (Ian.Dall@dsto.defence.gov.au)
* First release.
*
*/
#include "ieee_internal.h"
#include <machine/psl.h>
/* Return bit pos numbered from lsb 0 to 31. Returns 31 if no bit is set */
static int find_msb(unsigned int t) {
static const int b_mask[] = {
0xffff0000,
0xff00ff00,
0xf0f0f0f0,
0xcccccccc,
0xaaaaaaaa };
int i;
int pos = 31;
int bit_incr = 16; /* Half no of bits in int */
for (i = 0; i < 5; i++, bit_incr /= 2) {
if(t & b_mask[i]) {
t &= b_mask[i];
}
else {
pos -= bit_incr;
t &= ~b_mask[i];
}
}
return pos;
}
static int leading_zeros(union t_conv *data)
{
unsigned int t;
if ((t = data->d_bits.mantissa)) {
return 19 - find_msb(t);
}
else if ((t = data->d_bits.mantissa2)) {
return 51 - find_msb(t);
}
else
return 52;
}
static void lshift_mantissa(union t_conv *data, int n)
{
unsigned long t[2];
t[1] = data->d_bits.mantissa;
t[0] = data->d_bits.mantissa2;
*(unsigned long long *) t <<= n;
data->d_bits.mantissa = t[1];
data->d_bits.mantissa2 = t[0];
}
static void rshift_mantissa(union t_conv *data, int n)
{
unsigned long t[2];
t[1] = data->d_bits.mantissa | 0x100000;
t[0] = data->d_bits.mantissa2;
*(unsigned long long *) t >>= n;
data->d_bits.mantissa = t[1];
data->d_bits.mantissa2 = t[0];
}
/* After this, the data is a normal double and the returned value is
* such that:
* union t_conv t;
* t = *data;
* norm = normalize(&t);
* 2**norm * t.d == data->d;
*
* Assume data is not already normalized.
*/
int ieee_normalize(union t_conv *data)
{
int norm;
if(data->d_bits.exp != 0)
return 0;
norm = leading_zeros(data) + 1; /* plus one for the implied bit */
data->d_bits.exp = 1;
lshift_mantissa(data, norm);
return -norm;
}
/* Divide by 2**n producing a denormalized no if necessary */
static void denormalize(union t_conv *data, int n)
{
int exp = data->d_bits.exp;
if(exp > n)
exp -= n;
else if (exp <= n) {
rshift_mantissa(data, n - exp + 1); /* plus 1 for the implied bit */
exp = 0;
}
data->d_bits.exp = exp;
}
static int scale_and_check(union t_conv *d, int scale)
{
int exp;
exp = d->d_bits.exp - scale;
if(exp >= 0x7ff) {
/* Overflow */
d->d_bits.exp = 0x7ff;
d->d_bits.mantissa = 0;
d->d_bits.mantissa2 = 0; /* XXX sig */
return FPC_TT_OVFL;
}
if(exp <= 0) {
/* Underflow */
denormalize(d, scale); /* XXX sig */
return FPC_TT_UNDFL;
}
d->d_bits.exp = exp;
return FPC_TT_NONE;
}
/* Add two doubles, not caring if one or both is a de-norm.
* Strategy: First scale and normalize operands so the addition
* can't overflow or underflow, then do a normal floating point
* addition, then scale back and possibly denormalize.
*/
int ieee_add(double data1, double *data2)
{
union t_conv d1 = (union t_conv) data1;
union t_conv *d2 = (union t_conv *) data2;
int scale;
int norm1 = ieee_normalize(&d1);
int norm2 = ieee_normalize(d2);
int exp1 = d1.d_bits.exp + norm1;
int exp2 = d2->d_bits.exp + norm2;
if(exp1 > exp2) {
scale = EXP_DBIAS - exp1;
exp1 = EXP_DBIAS;
exp2 += scale;
}
else {
scale = EXP_DBIAS - exp2;
exp2 = EXP_DBIAS;
exp1 += scale;
}
if(exp1 > 0) {
d1.d_bits.exp = exp1;
if (exp2 > 0) {
d2->d_bits.exp = exp2;
d2->d += d1.d;
}
else {
d2->d = d1.d;
}
}
else {
d2->d_bits.exp = exp2;
}
return scale_and_check(d2, scale);
}
/* Multiply two doubles, not caring if one or both is a de-norm.
* Strategy: First scale and normalize operands so the multiplication
* can't overflow or underflow, then do a normal floating point
* addition, then scale back and possibly denormalize.
*/
int ieee_mul(double data1, double *data2)
{
union t_conv d1 = (union t_conv) data1;
union t_conv *d2 = (union t_conv *) data2;
int scale;
int norm1 = ieee_normalize(&d1);
int norm2 = ieee_normalize(d2);
int exp1 = d1.d_bits.exp + norm1;
int exp2 = d2->d_bits.exp + norm2;
d1.d_bits.exp = EXP_DBIAS; /* Add EXP_DBIAS - exp1 */
d2->d_bits.exp = EXP_DBIAS;
d2->d *= d1.d;
scale = EXP_DBIAS - exp1 + EXP_DBIAS - exp2;
return scale_and_check(d2, scale);
}
/* Divide d2 by d1, not caring if one or both is a de-norm.
* Strategy: First scale and normalize operands so the division
* can't overflow or underflow, then do a normal floating point
* division, then scale back and possibly denormalize.
*/
int ieee_div(double data1, double *data2)
{
union t_conv d1 = (union t_conv) data1;
union t_conv *d2 = (union t_conv *) data2;
int scale;
int norm1 = ieee_normalize(&d1);
int norm2 = ieee_normalize(d2);
int exp1 = d1.d_bits.exp + norm1;
int exp2 = d2->d_bits.exp + norm2;
d1.d_bits.exp = EXP_DBIAS; /* Add EXP_DBIAS - exp1 */
d2->d_bits.exp = EXP_DBIAS;
d2->d /= d1.d;
scale = exp1 - exp2;
return scale_and_check(d2, scale);
}
/* Add mul-add three doubles d1 * d2 + d3 -> d3, not caring if any a de-norm.
* Strategy: First scale and normalize operands so the operations
* can't overflow or underflow, then do a normal floating point operation
* addition, then scale back and possibly denormalize.
*/
int ieee_dot(double data1, double data2, double *data3)
{
union t_conv d1 = (union t_conv) data1;
union t_conv d2 = (union t_conv) data2;
union t_conv *d3 = (union t_conv *) data3;
int scale;
int norm1 = ieee_normalize(&d1);
int norm2 = ieee_normalize(&d2);
int norm3 = ieee_normalize(d3);
int exp1 = d1.d_bits.exp + norm1;
int exp2 = d2.d_bits.exp + norm2;
int exp3 = d3->d_bits.exp + norm3;
int exp_prod = exp1 + exp2;
if(exp_prod > exp3) {
scale = EXP_DBIAS + EXP_DBIAS - exp_prod;
exp1 = EXP_DBIAS; /* Add EXP_DBIAS - exp1 */
exp2 = EXP_DBIAS;
exp3 += scale;
}
else {
scale = EXP_DBIAS - exp3;
exp3 = EXP_DBIAS;
exp1 = (exp_prod + scale)/2;
exp2 = exp_prod + scale - exp1;
}
if(exp1 > 0 && exp2 > 0) {
d1.d_bits.exp = exp1;
d2.d_bits.exp = exp2;
if(exp3 > 0) {
d3->d_bits.exp = exp3;
d3->d += d1.d * d2.d;
}
else {
d3->d = d1.d * d2.d;
}
}
else {
d3->d_bits.exp = exp3;
}
return scale_and_check(d3, scale);
}
/* Compare the magnitude of two ops.
* return: 1 |op1| > |op2|
* -1 |op1| < |op2|
* 0 |op1| == |op2|
*/
static int u_cmp(double data1, double data2)
{
union t_conv d1 = (union t_conv) data1;
union t_conv d2 = (union t_conv) data2;
int exp1 = d1.d_bits.exp;
int exp2 = d2.d_bits.exp;
if (exp1 > exp2)
return 1;
else if (exp1 < exp2)
return -1;
else if (d1.d_bits.mantissa > d2.d_bits.mantissa)
return 1;
else if (d1.d_bits.mantissa < d2.d_bits.mantissa)
return -1;
else if (d1.d_bits.mantissa2 > d2.d_bits.mantissa2)
return 1;
else if (d1.d_bits.mantissa2 < d2.d_bits.mantissa2)
return -1;
else
return 0;
}
void ieee_cmp(double data1, double data2, state *state)
{
union t_conv d1 = (union t_conv) data1;
union t_conv d2 = (union t_conv) data2;
int sign1 = d1.d_bits.sign;
int sign2 = d2.d_bits.sign;
state->PSR &= ~(PSR_N | PSR_Z | PSR_L);
switch(sign2 * 2 + sign1) {
case 2: /* op2 is negative op1 is positive */
state->PSR |= PSR_N;
break;
case 1: /* op2 is positive op1 is negative */
break;
case 0: /* Both ops same sign */
case 3:
{
int cmp = u_cmp(d1.d, d2.d);
if(sign1)
cmp *= -1;
if(cmp > 0)
state->PSR |= PSR_N;
else if (cmp == 0)
state->PSR |= PSR_Z;
}
break;
}
return;
}
int ieee_scalb(double data1, double *data2)
{
union t_conv d1 = (union t_conv) data1;
union t_conv *d2 = (union t_conv *) data2;
int exp2 = d2->d_bits.exp - EXP_DBIAS;
int n;
if (exp2 > 16) {
*d2 = infty;
d2->d_bits.sign = d1.d_bits.sign;
return FPC_TT_OVFL;
}
else if (exp2 < -16) {
d2->d = 0.0;
d2->d_bits.sign = d1.d_bits.sign;
return FPC_TT_OVFL;
}
n = d2->d;
*d2 = d1;
return scale_and_check(d2, n);
}
/* With no trap, hardware produces zero, which is fast but not
* strictly correct. We should always have the hardware trap bit set
* and generate denormalized numbers by simulation unless the user
* indicates via the FPC_UNDE flag they want to handle it. */
int ieee_undfl(struct operand *op1, struct operand *op2,
struct operand *f0_op, int xopcode, state *state)
{
unsigned int fsr = state->FSR;
int user_trap = FPC_TT_NONE;
DP(1, "Underflow trap: xopcode = 0x%x\n", xopcode);
if (fsr & FPC_UNDE) {
user_trap = FPC_TT_UNDFL;
}
else {
user_trap = FPC_TT_NONE;
/* Calculate correct denormal output. The easiest way is to
* prescale the operands so they won't underflow, then use the
* hardware operation, then post scale.
*/
/* The exact sematics are a bit tricky. Apparently, we should only
* set flag if we underflowed *and* there was loss of precision
* For now, just set the flag always XXX
*/
fsr |= FPC_UF;
switch(xopcode) {
case NEGF:
op1->data.d_bits.sign ^= 1;
/* Fall through */
case MOVF:
case MOVLF:
case MOVFL:
op2->data = op1->data;
break;
case CMPF:
ieee_cmp(op1->data.d, op2->data.d, state);
break;
case SUBF:
op1->data.d_bits.sign ^= 1;
/* Fall through */
case ADDF:
user_trap = ieee_add(op1->data.d, &op2->data.d);
break;
case MULF:
user_trap = ieee_mul(op1->data.d, &op2->data.d);
break;
case DIVF:
user_trap = ieee_div(op1->data.d, &op2->data.d);
break;
case ROUNDFI:
case TRUNCFI:
case FLOORFI:
op2->data.i = 0;
break;
case SCALBF:
user_trap = ieee_scalb(op1->data.d, &op2->data.d);
break;
case LOGBF:
op2->data.d = 0.0;
break;
case DOTF:
user_trap = ieee_dot(op1->data.d, op2->data.d, &f0_op->data.d);
break;
case POLYF:
{
union t_conv t = op2->data;
user_trap = ieee_dot(f0_op->data.d, op1->data.d, &t.d);
f0_op->data = t;
}
break;
}
}
state->FSR = fsr;
return user_trap;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.15 1996/03/11 20:56:48 phil Exp $ */
/* $NetBSD: cpu.h,v 1.16 1996/04/04 06:36:36 phil Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@ -75,9 +75,9 @@
#define clockframe intrframe
#define CLKF_USERMODE(framep) USERMODE((framep)->if_psr)
#define CLKF_USERMODE(framep) USERMODE((framep)->if_regs.r_psr)
#define CLKF_BASEPRI(framep) ((framep)->if_pl == imask[IPL_ZERO])
#define CLKF_PC(framep) ((framep)->if_pc)
#define CLKF_PC(framep) ((framep)->if_regs.r_pc)
#define CLKF_INTR(frame) (0) /* XXX should have an interrupt stack */
/*

View File

@ -0,0 +1,65 @@
/* $NetBSD: fpu.h,v 1.1 1996/04/04 06:36:41 phil Exp $ */
/*
* IEEE floating point support for NS32081 and NS32381 fpus.
* Copyright (c) 1995 Ian Dall
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* IAN DALL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
* IAN DALL DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
* WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*/
/*
* File: fpu_status.h
* Author: Ian Dall
* Date: November 1995
*
* FPU status register definitions
*
* HISTORY
* 14-Dec-95 Ian Dall (Ian.Dall@dsto.defence.gov.au)
* First release.
*
*/
#ifndef _NS532_FPU_H_
#define _NS532_FPU_H_
/*
* Control register
*/
#define FPC_RMB 0x00010000 /* register modify bit */
#define FPC_SWF 0x0000fe00 /* reserved for software */
#define FPC_RM 0x00000180 /* rounding mode */
#define FPC_RM_NEAREST 0x00000000 /* round to nearest */
#define FPC_RM_TOZERO 0x00000080 /* round towards zero */
#define FPC_RM_TOPOS 0x00000100 /* round towards +infinity */
#define FPC_RM_TONEG 0x00000180 /* round towards -infinity */
#define FPC_IF 0x00000040 /* inexact result flag */
#define FPC_IEN 0x00000020 /* inexact result trap enable */
#define FPC_UF 0x00000010 /* underflow flag (else 0) */
#define FPC_UEN 0x00000008 /* underflow trap enable */
#define FPC_TT 0x00000007 /* trap type */
#define FPC_TT_NONE 0x00000000 /* no exceptional condition */
#define FPC_TT_UNDFL 0x00000001 /* underflow */
#define FPC_TT_OVFL 0x00000002 /* overflow */
#define FPC_TT_DIV0 0x00000003 /* divide by zero */
#define FPC_TT_ILL 0x00000004 /* illegal instruction */
#define FPC_TT_INVOP 0x00000005 /* invalid operation */
#define FPC_TT_INEXACT 0x00000006 /* inexact result */
/* Bits in the SWF field used for software emulation */
#define FPC_OVE 0x200 /* Overflow enable */
#define FPC_OVF 0x400 /* Overflow flag */
#define FPC_IVE 0x800 /* Invalid enable */
#define FPC_IVF 0x1000 /* Invalid flag */
#define FPC_DZE 0x2000 /* Divide by zero enable */
#define FPC_DZF 0x4000 /* Divide by zero flag */
#define FPC_UNDE 0x8000 /* Soft Underflow enable, requires FPC_UEN */
#endif /* _NS532_FPU_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: frame.h,v 1.5 1996/02/01 00:03:27 phil Exp $ */
/* $NetBSD: frame.h,v 1.6 1996/04/04 06:36:43 phil Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@ -38,8 +38,8 @@
* @(#)frame.h 5.2 (Berkeley) 1/18/91
*/
#ifndef _MACHINE_FRAME_H_
#define _MACHINE_FRAME_H_
#ifndef _NS532_FRAME_H_
#define _NS532_FRAME_H_
#include <sys/signal.h>
#include <machine/reg.h>
@ -56,14 +56,7 @@ struct trapframe {
long tf_msr; /* For abt. 0 for others. */
long tf_tear; /* For abt. 0 for others. */
long tf_trapno;
long tf_reg[8]; /* R7 - R0 from enter */
long tf_usp;
long tf_sb;
long tf_fp; /* From enter */
/* below portion defined in 532 hardware */
long tf_pc;
u_short tf_mod; /* Not used in direct excption mode. */
u_short tf_psr;
struct reg tf_regs;
};
/* Interrupt stack frame */
@ -71,14 +64,7 @@ struct trapframe {
struct intrframe {
long if_vec;
long if_pl; /* the "processor level" for clock. */
long if_reg[8]; /* R7 - R0 from enter */
long if_usp;
long if_sb;
long if_fp; /* From enter */
/* below portion defined in 532 hardware */
long if_pc;
u_short if_mod; /* Not used in direct excption mode. */
u_short if_psr;
struct reg if_regs;
};
/*
@ -86,14 +72,7 @@ struct intrframe {
*/
struct syscframe {
long sf_reg[8]; /* R7 - R0 from enter */
long sf_usp;
long sf_sb;
long sf_fp; /* From enter */
/* below portion defined in 532 hardware */
long sf_pc;
u_short sf_mod; /* Not used in direct excption mode. */
u_short sf_psr;
struct reg sf_regs;
};
/*
@ -101,7 +80,11 @@ struct syscframe {
*/
struct switchframe {
long sf_pl;
long sf_reg[5];
long sf_r7;
long sf_r6;
long sf_r5;
long sf_r4;
long sf_r3;
long sf_fp;
int sf_pc;
};
@ -117,4 +100,4 @@ struct sigframe {
struct sigcontext sf_sc;
};
#endif
#endif /* _NS532_FRAME_H_ */

View File

@ -1,3 +1,5 @@
/* $NetBSD: ieeefp.h,v 1.2 1996/04/04 06:36:45 phil Exp $ */
/*
* Written by J.T. Conklin, Apr 28, 1995
* Public domain.
@ -6,8 +8,12 @@
#ifndef _PC532_IEEEFP_H_
#define _PC532_IEEEFP_H_
/* defined just to keep prototypes in machine independant header happy. */
typedef int fp_except;
#define FP_X_IMP 0x0020 /* imprecise (loss of precision) */
#define FP_X_OFL 0x0200 /* overflow exception */
#define FP_X_INV 0x0800 /* invalid operation exception */
#define FP_X_DZ 0x2000 /* divide-by-zero exception */
#define FP_X_UFL 0x8000 /* underflow exception */
typedef enum {
FP_RN=0, /* round to nearest representable number */

View File

@ -1,4 +1,4 @@
/* $NetBSD: pcb.h,v 1.7 1996/02/01 00:03:32 phil Exp $ */
/* $NetBSD: pcb.h,v 1.8 1996/04/04 06:36:47 phil Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@ -48,21 +48,9 @@
*
*/
/* The registers as pushed from a trap/interrupt with the
exception of USP and SB, and they are placed by software. */
struct on_stack {
long pcb_reg[8]; /* R7 - R0 from enter */
long pcb_usp; /* User stack pointer, by software. */
long pcb_sb; /* Static Base pointer, by software. */
long pcb_fp; /* From enter */
long pcb_pc; /* From the trap/interrupt */
u_short pcb_mod; /* in direct exception mode. */
u_short pcb_psr;
};
struct pcb {
/* Put in a pointer to the trap/interrupt frame. */
struct on_stack *pcb_onstack;
struct reg *pcb_onstack;
/* Floating point stuff */
long pcb_fsr; /* fpu status reg */

View File

@ -1,4 +1,4 @@
/* $NetBSD: proc.h,v 1.4 1994/10/26 08:24:37 cgd Exp $ */
/* $NetBSD: proc.h,v 1.5 1996/04/04 06:36:50 phil Exp $ */
/*
* Copyright (c) 1991 Regents of the University of California.
@ -35,14 +35,14 @@
* @(#)proc.h 7.1 (Berkeley) 5/15/91
*/
#ifndef _MACHINE_PROC_H_
#define _MACHINE_PROC_H_
#ifndef _NS532_PROC_H_
#define _NS532_PROC_H_
/*
* Machine-dependent part of the proc structure for the pc532.
*/
struct mdproc {
int *md_regs; /* pointer to regs on the stack */
struct reg *md_regs; /* pointer to regs on the stack */
};
#endif
#endif /* _NS532_PROC_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: reg.h,v 1.10 1995/08/29 22:40:59 phil Exp $ */
/* $NetBSD: reg.h,v 1.11 1996/04/04 06:36:52 phil Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@ -64,7 +64,7 @@
#define REG_R7 (0)
#define REG_SP (8)
#define REG_SB (9)
#define REG_SB (9)
#define REG_FP (10)
#define REG_PC (11)
#define REG_PSR (12)
@ -85,7 +85,7 @@ struct reg {
int r_sb;
int r_fp;
int r_pc;
short r_mod;
short r_mod; /* This is not set in direct exception mode */
short r_psr;
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: types.h,v 1.14 1996/03/28 04:53:17 phil Exp $ */
/* $NetBSD: types.h,v 1.15 1996/04/04 06:36:55 phil Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@ -46,7 +46,7 @@ typedef struct _physadr {
} *physadr;
typedef struct label_t {
int val[6];
int val[8];
} label_t;
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: genassym.c,v 1.10 1996/02/02 19:43:03 mycroft Exp $ */
/* $NetBSD: genassym.c,v 1.11 1996/04/04 06:36:59 phil Exp $ */
/*-
* Copyright (c) 1982, 1990 The Regents of the University of California.
@ -58,7 +58,7 @@ main()
struct vmmeter *vm = 0;
struct pcb *pcb = 0;
struct sigframe *sigf = 0;
struct on_stack *regs = 0;
struct reg *regs = 0;
struct iv *iv = 0;
register unsigned i;
@ -100,11 +100,11 @@ main()
def("PCB_PTB", &pcb->pcb_ptb);
def("PCB_ONFAULT", &pcb->pcb_onfault);
def("ON_STK_SIZE", sizeof(struct on_stack));
def("REGS_USP", &regs->pcb_usp);
def("REGS_FP", &regs->pcb_fp);
def("REGS_SB", &regs->pcb_sb);
def("REGS_PSR", &regs->pcb_psr);
def("ON_STK_SIZE", sizeof(struct reg));
def("REGS_USP", &regs->r_sp);
def("REGS_FP", &regs->r_fp);
def("REGS_SB", &regs->r_sb);
def("REGS_PSR", &regs->r_psr);
def("SIGF_HANDLER", &sigf->sf_handler);
def("SIGF_SC", &sigf->sf_sc);

View File

@ -1,4 +1,4 @@
/* $NetBSD: intr.c,v 1.6 1996/01/31 21:33:53 phil Exp $ */
/* $NetBSD: intr.c,v 1.7 1996/04/04 06:37:00 phil Exp $ */
/*
* Copyright (c) 1994 Matthias Pfaller.
@ -204,7 +204,7 @@ badhard(struct intrframe *frame)
bad_count++;
if (bad_count < 5)
printf("Unknown hardware interrupt: vec=%d pc=0x%08x psr=0x%04x cpl=0x%08x\n",
frame->if_vec, frame->if_pc, frame->if_psr, frame->if_pl);
frame->if_vec, frame->if_regs.r_pc, frame->if_regs.r_psr, frame->if_pl);
if (bad_count == 5)
printf("Too many unknown hardware interrupts, quitting reporting them.\n");

View File

@ -1,4 +1,4 @@
/* $NetBSD: locore.s,v 1.35 1996/03/28 05:00:06 phil Exp $ */
/* $NetBSD: locore.s,v 1.36 1996/04/04 06:37:02 phil Exp $ */
/*
* Copyright (c) 1993 Philip A. Nelson.
@ -31,8 +31,6 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* locore.s
*
* locore.s,v 1.2 1993/09/13 07:26:47 phil Exp
*/
/*
@ -57,6 +55,7 @@
#include <machine/pte.h>
#include <machine/trap.h>
#include <machine/cpufunc.h>
#include <machine/jmpbuf.h>
/*
* PTmap is recursive pagemap at top of virtual address space.
@ -138,7 +137,7 @@ ENTRY(proc_trampoline)
cmpqd 0,tos
br rei
/*****************************************************************************/
/****************************************************************************/
/*
* Burn N microseconds in a delay loop.
@ -160,7 +159,7 @@ ENTRY(delay) /* bsr 2 cycles; 80 ns */
acbd -1,r0,1b /* 5 cycles; 200 ns */
2: ret 0 /* 4 cycles; 160 ns */
/*****************************************************************************/
/****************************************************************************/
/*
* Signal trampoline; copied to top of user stack.
@ -177,7 +176,7 @@ ENTRY(sigcode)
.globl _esigcode
_esigcode:
/*****************************************************************************/
/****************************************************************************/
/*
* The following primitives are used to fill and copy regions of memory.
@ -283,7 +282,7 @@ ENTRY(bzero)
acbd -1,r0,7b
br 3b
/*****************************************************************************/
/****************************************************************************/
/*
* The following primitives are used to copy data in and out of the user's
@ -610,7 +609,49 @@ ENTRY(fusubail)
movqd -1,r0
ret 0
/*****************************************************************************/
/***************************************************************************/
/*
* setjmp(label_t *);
* longjmp(label_t *);
*
* The kernel versions of setjmp and longjmp.
* r0-r2 and sb are not saved.
*/
ENTRY(setjmp)
movd S_ARG0,r0
sprd sp,0(r0) /* save stackpointer */
sprd fp,4(r0) /* save framepointer */
movd 0(sp),8(r0) /* save return address */
movd r3,12(r0) /* save registers r3-r7 */
movd r4,16(r0)
movd r5,20(r0)
movd r6,24(r0)
movd r7,28(r0)
movqd 0,r0 /* return(0) */
ret 0
ENTRY(longjmp)
movd S_ARG0,r0
lprd sp,0(r0) /* restore stackpointer */
lprd fp,4(r0) /* restore framepointer */
movd 8(r0),0(sp) /* modify return address */
movd 12(r0),r3 /* restore registers r3-r7 */
movd 16(r0),r4
movd 20(r0),r5
movd 24(r0),r6
movd 28(r0),r7
movqd 1,r0 /* return(1) */
ret 0
/****************************************************************************/
/*
* The following primitives manipulate the run queues.
@ -840,7 +881,7 @@ switch_return:
exit [r3,r4,r5,r6,r7]
ret 0
/*****************************************************************************/
/****************************************************************************/
/*
* FPU handling.
@ -898,7 +939,7 @@ ENTRY(restore_fpu_context)
movl PCB_F7(r0),f7
9: ret 0
/*****************************************************************************/
/****************************************************************************/
/*
* Trap and fault vector routines
@ -1094,7 +1135,7 @@ _inttab:
.long trap_dbg
.long trap_reserved
/*****************************************************************************/
/****************************************************************************/
/*
* void *ram_size(void *start);
@ -1239,7 +1280,7 @@ highagain:
/* Include all other .s files. */
#include "bcopy.s"
/*****************************************************************************/
/****************************************************************************/
/*
* vmstat -i uses the following labels and trap_int even increments the

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.45 1996/02/15 08:39:27 phil Exp $ */
/* $NetBSD: machdep.c,v 1.46 1996/04/04 06:37:05 phil Exp $ */
/*-
* Copyright (c) 1996 Matthias Pfaller.
@ -84,6 +84,7 @@ static char rcsid[] = "/b/source/CVS/src/sys/arch/pc532/pc532/machdep.c,v 1.2 19
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/psl.h>
#include <machine/fpu.h>
#include <machine/pmap.h>
/*
@ -360,7 +361,7 @@ sendsig(catcher, sig, mask, code)
u_long code;
{
register struct proc *p = curproc;
register int *regs;
register struct reg *regs;
register struct sigframe *fp;
struct sigacts *ps = p->p_sigacts;
int oonstack;
@ -378,7 +379,7 @@ sendsig(catcher, sig, mask, code)
ps->ps_sigstk.ss_size - sizeof(struct sigframe));
ps->ps_sigstk.ss_flags |= SS_ONSTACK;
} else {
fp = (struct sigframe *)regs[REG_SP] - 1;
fp = (struct sigframe *)regs->r_sp - 1;
}
if ((unsigned)fp <= (unsigned)p->p_vmspace->vm_maxsaddr + MAXSSIZ - ctob(p->p_vmspace->vm_ssize))
@ -406,18 +407,25 @@ sendsig(catcher, sig, mask, code)
*/
fp->sf_sc.sc_onstack = oonstack;
fp->sf_sc.sc_mask = mask;
fp->sf_sc.sc_fp = regs[REG_FP];
fp->sf_sc.sc_sp = regs[REG_SP];
fp->sf_sc.sc_pc = regs[REG_PC];
fp->sf_sc.sc_ps = regs[REG_PSR];
fp->sf_sc.sc_sb = regs[REG_SB];
bcopy (regs, fp->sf_sc.sc_reg, 8*sizeof(int));
fp->sf_sc.sc_fp = regs->r_fp;
fp->sf_sc.sc_sp = regs->r_sp;
fp->sf_sc.sc_pc = regs->r_pc;
fp->sf_sc.sc_ps = regs->r_psr;
fp->sf_sc.sc_sb = regs->r_sb;
fp->sf_sc.sc_reg[REG_R7] = regs->r_r7;
fp->sf_sc.sc_reg[REG_R6] = regs->r_r6;
fp->sf_sc.sc_reg[REG_R5] = regs->r_r5;
fp->sf_sc.sc_reg[REG_R4] = regs->r_r4;
fp->sf_sc.sc_reg[REG_R3] = regs->r_r3;
fp->sf_sc.sc_reg[REG_R2] = regs->r_r2;
fp->sf_sc.sc_reg[REG_R1] = regs->r_r1;
fp->sf_sc.sc_reg[REG_R0] = regs->r_r0;
/*
* Build context to run handler in.
*/
regs[REG_SP] = (int)fp;
regs[REG_PC] = (int)(((char *)PS_STRINGS) - (esigcode - sigcode));
regs->r_sp = (int)fp;
regs->r_pc = (int)(((char *)PS_STRINGS) - (esigcode - sigcode));
}
/*
@ -440,7 +448,7 @@ sys_sigreturn(p, v, retval)
syscallarg(struct sigcontext *) sigcntxp;
} */ *uap = v;
register struct sigcontext *scp;
register int *regs = p->p_md.md_regs;
register struct reg *regs = p->p_md.md_regs;
/*
* The trampoline code hands us the context.
@ -454,7 +462,7 @@ sys_sigreturn(p, v, retval)
/*
* Check for security violations.
*/
if (((scp->sc_ps ^ regs[REG_PSR]) & PSL_USERSTATIC) != 0)
if (((scp->sc_ps ^ regs->r_psr) & PSL_USERSTATIC) != 0)
return (EINVAL);
if (scp->sc_onstack & 01)
@ -466,19 +474,26 @@ sys_sigreturn(p, v, retval)
/*
* Restore signal context.
*/
regs[REG_FP] = scp->sc_fp;
regs[REG_SP] = scp->sc_sp;
regs[REG_PC] = scp->sc_pc;
regs[REG_PSR] = scp->sc_ps;
regs[REG_SB] = scp->sc_sb;
bcopy (scp->sc_reg, regs, 8*sizeof(int));
regs->r_fp = scp->sc_fp;
regs->r_sp = scp->sc_sp;
regs->r_pc = scp->sc_pc;
regs->r_psr = scp->sc_ps;
regs->r_sb = scp->sc_sb;
regs->r_r7 = scp->sc_reg[REG_R7];
regs->r_r6 = scp->sc_reg[REG_R6];
regs->r_r5 = scp->sc_reg[REG_R5];
regs->r_r4 = scp->sc_reg[REG_R4];
regs->r_r3 = scp->sc_reg[REG_R3];
regs->r_r2 = scp->sc_reg[REG_R2];
regs->r_r1 = scp->sc_reg[REG_R1];
regs->r_r0 = scp->sc_reg[REG_R0];
return(EJUSTRETURN);
}
int waittime = -1;
struct pcb dumppcb;
struct on_stack dumppcb_onstack;
struct reg dumppcb_regs;
void
boot(howto)
@ -532,15 +547,15 @@ boot(howto)
sprd(sp, dumppcb.pcb_ksp);
sprd(fp, dumppcb.pcb_kfp);
smr(ptb0, dumppcb.pcb_ptb);
dumppcb.pcb_onstack = &dumppcb_onstack;
sprw(psr, dumppcb_onstack.pcb_psr);
sprw(mod, dumppcb_onstack.pcb_mod);
lprd(sp, &dumppcb_onstack.pcb_mod);
dumppcb.pcb_onstack = &dumppcb_regs;
sprw(psr, dumppcb_regs.r_psr);
sprw(mod, dumppcb_regs.r_mod);
lprd(sp, &dumppcb_regs.r_mod);
__asm __volatile("bsr 1f; 1: enter [r0,r1,r2,r3,r4,r5,r6,r7],8");
lprd(sp, dumppcb.pcb_ksp);
lprd(fp, dumppcb.pcb_kfp);
sprd(sb, dumppcb_onstack.pcb_sb);
sprd(usp, dumppcb_onstack.pcb_usp);
sprd(sb, dumppcb_regs.r_sb);
sprd(usp, dumppcb_regs.r_sp);
ei();
dumpsys();
}
@ -751,21 +766,20 @@ setregs(p, pack, stack, retval)
u_long stack;
register_t *retval;
{
struct on_stack *r = (struct on_stack *)p->p_md.md_regs;
struct reg *r = p->p_md.md_regs;
struct pcb *pcbp = &p->p_addr->u_pcb;
extern struct proc *fpu_proc;
if (p == fpu_proc)
fpu_proc = 0;
r->pcb_usp = stack;
r->pcb_fp = 0;
r->pcb_pc = pack->ep_entry;
r->pcb_psr = PSL_USERSET;
bzero(r->pcb_reg, sizeof(r->pcb_reg));
r->pcb_reg[0] = (int)PS_STRINGS;
bzero(r, sizeof(*r));
r->r_sp = stack;
r->r_pc = pack->ep_entry;
r->r_psr = PSL_USERSET;
r->r_r7 = (int)PS_STRINGS;
pcbp->pcb_fsr = 0;
pcbp->pcb_fsr = FPC_UEN;
bzero(pcbp->pcb_freg, sizeof(pcbp->pcb_freg));
retval[1] = 0;
@ -985,7 +999,7 @@ init532()
/* Construct an empty syscframe for proc0. */
curpcb = &proc0.p_addr->u_pcb;
curpcb->pcb_onstack = (struct on_stack *)
curpcb->pcb_onstack = (struct reg *)
((u_int)proc0.p_addr + USPACE) - 1;
/* Switch to proc0's stack. */

View File

@ -1,4 +1,4 @@
/* $NetBSD: process_machdep.c,v 1.9 1996/01/31 21:34:02 phil Exp $ */
/* $NetBSD: process_machdep.c,v 1.10 1996/04/04 06:37:08 phil Exp $ */
/*
* Copyright (c) 1993 The Regents of the University of California.
@ -75,13 +75,6 @@
extern struct proc *fpu_proc;
static inline struct reg *
process_regs(p)
struct proc *p;
{
return ((struct reg *) p->p_md.md_regs);
}
int
process_read_regs(p, regs)
struct proc *p;
@ -89,7 +82,7 @@ process_read_regs(p, regs)
{
struct reg *pregs;
pregs = process_regs(p);
pregs = p->p_md.md_regs;
if (pregs == NULL)
return (EIO);
@ -104,7 +97,7 @@ process_write_regs(p, regs)
{
struct reg *pregs;
pregs = process_regs(p);
pregs = p->p_md.md_regs;
if (pregs == NULL)
return (EIO);
@ -154,7 +147,7 @@ process_sstep(p, sstep)
{
struct reg *pregs;
pregs = process_regs(p);
pregs = p->p_md.md_regs;
if (pregs == NULL)
return (EIO);
@ -173,7 +166,7 @@ process_set_pc(p, addr)
{
struct reg *pregs;
pregs = process_regs(p);
pregs = p->p_md.md_regs;
if (pregs == NULL)
return (EIO);

View File

@ -1,4 +1,4 @@
/* $NetBSD: trap.c,v 1.15 1996/03/28 05:00:16 phil Exp $ */
/* $NetBSD: trap.c,v 1.16 1996/04/04 06:37:12 phil Exp $ */
/*-
* Copyright (c) 1996 Matthias Pfaller. All rights reserved.
@ -63,6 +63,7 @@
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/psl.h>
#include <machine/fpu.h>
#include <machine/reg.h>
#include <machine/trap.h>
@ -173,10 +174,10 @@ trap(frame)
}
#endif
if (USERMODE(frame.tf_psr)) {
if (USERMODE(frame.tf_regs.r_psr)) {
type |= T_USER;
sticks = p->p_sticks;
p->p_md.md_regs = (int *)&(frame.tf_reg);
p->p_md.md_regs = &frame.tf_regs;
}
switch (type) {
@ -193,7 +194,7 @@ trap(frame)
printf("unknown trap %d", frame.tf_trapno);
printf(" in %s mode\n", (type & T_USER) ? "user" : "supervisor");
printf("trap type=%d, pc=0x%x, tear=0x%x, msr=0x%x\n",
type, frame.tf_pc, frame.tf_tear, frame.tf_msr);
type, frame.tf_regs.r_pc, frame.tf_tear, frame.tf_msr);
panic("trap");
/*NOTREACHED*/
@ -245,17 +246,26 @@ trap(frame)
goto out;
case T_SLAVE | T_USER: {
int fsr;
#ifdef MATH_IEEE
int rv;
if ((rv = math_ieee(&frame)) == 0) {
if (frame.tf_psr & PSL_T)
int fsr, sig = SIGFPE;
pcb = &p->p_addr->u_pcb;
save_fpu_context(pcb);
switch(ieee_handle_exception(p)) {
case FPC_TT_NONE:
restore_fpu_context(pcb);
if (frame.tf_regs.r_psr & PSL_T) {
type = T_TRC | T_USER;
goto trace;
}
return;
case FPC_TT_ILL:
sig = SIGILL;
break;
default:
break;
}
#endif
restore_fpu_context(pcb);
sfsr(fsr);
trapsignal(p, SIGFPE, 0x80000000 | fsr);
trapsignal(p, sig, 0x80000000 | fsr);
goto out;
}
@ -360,7 +370,7 @@ trap(frame)
if (type == T_ABT) {
if (pcb->pcb_onfault != 0) {
copyfault:
frame.tf_pc = (int)curpcb->pcb_onfault;
frame.tf_regs.r_pc = (int)curpcb->pcb_onfault;
return;
}
printf("vm_fault(%x, %x, %x, 0) -> %x\n",
@ -376,7 +386,7 @@ trap(frame)
case T_BPT | T_USER: /* breakpoint instruction */
case T_DBG | T_USER: /* debug trap */
trace:
frame.tf_psr &= ~PSL_P;
frame.tf_regs.r_psr &= ~PSL_P;
trapsignal(p, SIGTRAP, type &~ T_USER);
break;
@ -394,7 +404,7 @@ trap(frame)
if ((type & T_USER) == 0)
return;
out:
userret(p, frame.tf_pc, sticks);
userret(p, frame.tf_regs.r_pc, sticks);
}
/*
@ -416,18 +426,18 @@ syscall(frame)
u_quad_t sticks;
cnt.v_syscall++;
if (!USERMODE(frame.sf_psr))
if (!USERMODE(frame.sf_regs.r_psr))
panic("syscall");
p = curproc;
sticks = p->p_sticks;
p->p_md.md_regs = (int *) &frame.sf_reg;
opc = frame.sf_pc++;
code = frame.sf_reg[REG_R0];
p->p_md.md_regs = &frame.sf_regs;
opc = frame.sf_regs.r_pc++;
code = frame.sf_regs.r_r0;
nsys = p->p_emul->e_nsysent;
callp = p->p_emul->e_sysent;
params = (caddr_t)frame.sf_usp + sizeof(int);
params = (caddr_t)frame.sf_regs.r_sp + sizeof(int);
switch (code) {
case SYS_syscall:
@ -469,7 +479,7 @@ syscall(frame)
if (error)
goto bad;
rval[0] = 0;
rval[1] = frame.sf_reg[REG_R1];
rval[1] = frame.sf_regs.r_r1;
error = (*callp->sy_call)(p, args, rval);
switch (error) {
case 0:
@ -478,15 +488,15 @@ syscall(frame)
* if this is a child returning from fork syscall.
*/
p = curproc;
frame.sf_reg[REG_R0] = rval[0];
frame.sf_reg[REG_R1] = rval[1];
frame.sf_psr &= ~PSL_C; /* carry bit */
frame.sf_regs.r_r0 = rval[0];
frame.sf_regs.r_r1 = rval[1];
frame.sf_regs.r_psr &= ~PSL_C; /* carry bit */
break;
case ERESTART:
/*
* Just reset the pc to the SVC instruction.
*/
frame.sf_pc = opc;
frame.sf_regs.r_pc = opc;
break;
case EJUSTRETURN:
/* nothing to do */
@ -495,15 +505,15 @@ syscall(frame)
bad:
if (p->p_emul->e_errno)
error = p->p_emul->e_errno[error];
frame.sf_reg[REG_R0] = error;
frame.sf_psr |= PSL_C; /* carry bit */
frame.sf_regs.r_r0 = error;
frame.sf_regs.r_psr |= PSL_C; /* carry bit */
break;
}
#ifdef SYSCALL_DEBUG
scdebug_ret(p, code, error, rval);
#endif
userret(p, frame.sf_pc, sticks);
userret(p, frame.sf_regs.r_pc, sticks);
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSRET))
ktrsysret(p->p_tracep, code, error, rval[0]);
@ -515,10 +525,10 @@ child_return(p, frame)
struct proc *p;
struct syscframe frame;
{
frame.sf_reg[REG_R0] = 0;
frame.sf_psr &= ~PSL_C;
frame.sf_regs.r_r0 = 0;
frame.sf_regs.r_psr &= ~PSL_C;
userret(p, frame.sf_pc, 0);
userret(p, frame.sf_regs.r_pc, 0);
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSRET))
ktrsysret(p->p_tracep, SYS_fork, 0, 0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: vm_machdep.c,v 1.14 1996/02/05 20:33:37 christos Exp $ */
/* $NetBSD: vm_machdep.c,v 1.15 1996/04/04 06:37:15 phil Exp $ */
/*-
* Copyright (c) 1996 Matthias Pfaller.
@ -78,7 +78,7 @@ cpu_fork(p1, p2)
/* Copy curpcb (which is presumably p1's PCB) to p2. */
*pcb = p1->p_addr->u_pcb;
pcb->pcb_onstack = (struct on_stack *)((u_int)p2->p_addr + USPACE) - 1;
pcb->pcb_onstack = (struct reg *)((u_int)p2->p_addr + USPACE) - 1;
*pcb->pcb_onstack = *p1->p_addr->u_pcb.pcb_onstack;
/* If p1 is holding the FPU, update the FPU context of p2. */
if (fpu_proc == p1)
@ -90,12 +90,12 @@ cpu_fork(p1, p2)
* through rei().
*/
tf = (struct syscframe *)((u_int)p2->p_addr + USPACE) - 1;
p2->p_md.md_regs = (int *)&(tf->sf_reg);
p2->p_md.md_regs = &tf->sf_regs;
sf = (struct switchframe *)tf - 1;
sf->sf_pc = (long) proc_trampoline;
sf->sf_fp = (long) &tf->sf_fp;
sf->sf_reg[REG_R3] = (long) child_return;
sf->sf_reg[REG_R4] = (long) p2;
sf->sf_fp = (long) &tf->sf_regs.r_fp;
sf->sf_r3 = (long) child_return;
sf->sf_r4 = (long) p2;
sf->sf_pl = imask[IPL_ZERO];
pcb->pcb_ksp = (long) sf;
pcb->pcb_kfp = (long) &sf->sf_fp;
@ -123,8 +123,8 @@ cpu_set_kpc(p, pc)
pcbp = &p->p_addr->u_pcb;
sf = (struct switchframe *) pcbp->pcb_ksp;
sf->sf_pc = (long) proc_trampoline;
sf->sf_reg[REG_R3] = pc;
sf->sf_reg[REG_R4] = (long) p;
sf->sf_r3 = pc;
sf->sf_r4 = (long) p;
}
/*