PDP11: FP fix from Bob Supnik: MMR1 does not track register changes (Johnny Billquist) Fix #44

This commit is contained in:
Mark Pizzolato 2015-03-26 14:32:34 -07:00
parent 6bf32c0687
commit 4da7f5e028

View file

@ -1,6 +1,6 @@
/* pdp11_fp.c: PDP-11 floating point simulator (32b version) /* pdp11_fp.c: PDP-11 floating point simulator (32b version)
Copyright (c) 1993-2013, Robert M Supnik Copyright (c) 1993-2015, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,7 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
24-Mar-15 RMS MMR1 does not track register changes (Johnny Billquist)
20-Apr-13 RMS MMR1 does not track PC changes (Johnny Billquist) 20-Apr-13 RMS MMR1 does not track PC changes (Johnny Billquist)
22-Sep-05 RMS Fixed declarations (Sterling Garwood) 22-Sep-05 RMS Fixed declarations (Sterling Garwood)
04-Oct-04 RMS Added FIS instructions 04-Oct-04 RMS Added FIS instructions
@ -69,10 +70,8 @@
and exception enable bits for individual error conditions. Exceptions and exception enable bits for individual error conditions. Exceptions
cause a trap through 0244, unless the individual exception, or all cause a trap through 0244, unless the individual exception, or all
exceptions, are disabled. Illegal address mode, undefined variable, exceptions, are disabled. Illegal address mode, undefined variable,
and divide by zero abort the current instruction; all other exceptions and divide by zero NOP the current instruction; all other exceptions
permit the instruction to complete. (Aborts are implemented as traps permit the instruction to complete.
that request an "interrupt" trap. If an interrupt is pending, it is
serviced; if not, trap_req is updated and processing continues.)
Floating point specifiers are similar to integer specifiers, with Floating point specifiers are similar to integer specifiers, with
the length of the operand being up to 8 bytes. In two specific cases, the length of the operand being up to 8 bytes. In two specific cases,
@ -85,7 +84,14 @@
immediate for integers or floating point, only 16b are immediate for integers or floating point, only 16b are
accessed; if the operand is 32b or 64b, these accessed; if the operand is 32b or 64b, these
are the high order 16b of the operand are the high order 16b of the operand.
The FP11 cannot update MMR1 on specifier changes, because the
quantity field is too narrow for +8 or -8. Instead, the simulator
records changes to be made and only commits them at instruction
completion. Instructions that can overwrite a general register
(STFPS, STST, STEXP, STCFi in mode 0) need not check for conflicts;
in mode 0, no general register changes occur in the specifier flow.
*/ */
#include "pdp11_defs.h" #include "pdp11_defs.h"
@ -107,7 +113,7 @@
#define FPS_C (1u << FPS_V_C) #define FPS_C (1u << FPS_V_C)
#define FPS_CC (FPS_N + FPS_Z + FPS_V + FPS_C) #define FPS_CC (FPS_N + FPS_Z + FPS_V + FPS_C)
#define FPS_RW (FPS_ER + FPS_ID + FPS_IUV + FPS_IU + FPS_IV + \ #define FPS_RW (FPS_ER + FPS_ID + FPS_IUV + FPS_IU + FPS_IV + \
FPS_IC + FPS_D + FPS_L + FPS_T + FPS_CC) FPS_IC + FPS_D + FPS_L + FPS_T + FPS_CC)
/* Floating point exception codes */ /* Floating point exception codes */
@ -144,6 +150,14 @@
#define LONG 4 #define LONG 4
#define QUAD 8 #define QUAD 8
/* Reg change word */
#define FPCHG(v,r) (((v) << FPCHG_V_VAL) | (r))
#define FPCHG_REG 07 /* register number */
#define FPCHG_V_VAL 3 /* offset to value */
#define FPCHG_GETREG(x) ((x) & FPCHG_REG)
#define FPCHG_GETVAL(x) ((x) >> FPCHG_V_VAL)
/* Double precision operations on 64b quantities */ /* Double precision operations on 64b quantities */
#define F_LOAD(qd,ac,ds) \ #define F_LOAD(qd,ac,ds) \
@ -231,11 +245,13 @@ static const uint32 and_mask[33] = { 0,
0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
}; };
int32 backup_PC; int32 backup_PC;
int32 fpnotrap (int32 code); int32 fp_change;
int32 GeteaFP (int32 spec, int32 len);
int32 fpnotrap (int32 code);
int32 GeteaFW (int32 spec);
int32 GeteaFP (int32 spec, int32 len);
uint32 ReadI (int32 addr, int32 spec, int32 len); uint32 ReadI (int32 addr, int32 spec, int32 len);
void ReadFP (fpac_t *fac, int32 addr, int32 spec, int32 len); t_bool ReadFP (fpac_t *fac, int32 addr, int32 spec, int32 len);
void WriteI (int32 data, int32 addr, int32 spec, int32 len); void WriteI (int32 data, int32 addr, int32 spec, int32 len);
void WriteFP (fpac_t *data, int32 addr, int32 spec, int32 len); void WriteFP (fpac_t *data, int32 addr, int32 spec, int32 len);
int32 setfcc (int32 old_status, int32 result_high, int32 newV); int32 setfcc (int32 old_status, int32 result_high, int32 newV);
@ -247,7 +263,6 @@ void frac_mulfp11 (fpac_t *src1, fpac_t *src2);
int32 roundfp11 (fpac_t *src); int32 roundfp11 (fpac_t *src);
int32 round_and_pack (fpac_t *fac, int32 exp, fpac_t *frac, int r); int32 round_and_pack (fpac_t *fac, int32 exp, fpac_t *frac, int r);
extern int32 GeteaW (int32 spec);
extern int32 ReadW (int32 addr); extern int32 ReadW (int32 addr);
extern void WriteW (int32 data, int32 addr); extern void WriteW (int32 data, int32 addr);
extern void set_stack_trap (int32 adr); extern void set_stack_trap (int32 adr);
@ -266,6 +281,7 @@ static const uint32 i_limit[2][2] = {
}; };
backup_PC = PC; /* save PC for FEA */ backup_PC = PC; /* save PC for FEA */
fp_change = 0; /* assume no reg chg */
ac = (IR >> 6) & 03; /* fac is IR<7:6> */ ac = (IR >> 6) & 03; /* fac is IR<7:6> */
dstspec = IR & 077; dstspec = IR & 077;
qdouble = FPS & FPS_D; qdouble = FPS & FPS_D;
@ -294,7 +310,7 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */
break; break;
case 1: /* LDFPS */ case 1: /* LDFPS */
dst = (dstspec <= 07)? R[dstspec]: ReadW (GeteaW (dstspec)); dst = (dstspec <= 07)? R[dstspec]: ReadW (GeteaFW (dstspec));
FPS = dst & FPS_RW; FPS = dst & FPS_RW;
break; break;
@ -302,7 +318,7 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */
FPS = FPS & FPS_RW; FPS = FPS & FPS_RW;
if (dstspec <= 07) if (dstspec <= 07)
R[dstspec] = FPS; R[dstspec] = FPS;
else WriteW (FPS, GeteaW (dstspec)); else WriteW (FPS, GeteaFW (dstspec));
break; break;
case 3: /* STST */ case 3: /* STST */
@ -323,34 +339,37 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */
break; break;
case 1: /* TSTf */ case 1: /* TSTf */
ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); if (ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf))
FPS = setfcc (FPS, fsrc.h, 0); FPS = setfcc (FPS, fsrc.h, 0);
break; break;
case 2: /* ABSf */ case 2: /* ABSf */
ReadFP (&fsrc, ea = GeteaFP (dstspec, lenf), dstspec, lenf); if (ReadFP (&fsrc, ea = GeteaFP (dstspec, lenf), dstspec, lenf)) {
if (GET_EXP (fsrc.h) == 0) if (GET_EXP (fsrc.h) == 0)
fsrc = zero_fac; fsrc = zero_fac;
else fsrc.h = fsrc.h & ~FP_SIGN; else fsrc.h = fsrc.h & ~FP_SIGN;
WriteFP (&fsrc, ea, dstspec, lenf); WriteFP (&fsrc, ea, dstspec, lenf);
FPS = setfcc (FPS, fsrc.h, 0); FPS = setfcc (FPS, fsrc.h, 0);
}
break; break;
case 3: /* NEGf */ case 3: /* NEGf */
ReadFP (&fsrc, ea = GeteaFP (dstspec, lenf), dstspec, lenf); if (ReadFP (&fsrc, ea = GeteaFP (dstspec, lenf), dstspec, lenf)) {
if (GET_EXP (fsrc.h) == 0) if (GET_EXP (fsrc.h) == 0)
fsrc = zero_fac; fsrc = zero_fac;
else fsrc.h = fsrc.h ^ FP_SIGN; else fsrc.h = fsrc.h ^ FP_SIGN;
WriteFP (&fsrc, ea, dstspec, lenf); WriteFP (&fsrc, ea, dstspec, lenf);
FPS = setfcc (FPS, fsrc.h, 0); FPS = setfcc (FPS, fsrc.h, 0);
}
break; break;
} /* end switch <7:6> */ } /* end switch <7:6> */
break; /* end case 1 */ break; /* end case 1 */
case 005: /* LDf */ case 005: /* LDf */
ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); if (ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf)) {
F_STORE (qdouble, fsrc, FR[ac]); F_STORE (qdouble, fsrc, FR[ac]);
FPS = setfcc (FPS, fsrc.h, 0); FPS = setfcc (FPS, fsrc.h, 0);
}
break; break;
case 010: /* STf */ case 010: /* STf */
@ -359,14 +378,15 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */
break; break;
case 017: /* LDCff' */ case 017: /* LDCff' */
ReadFP (&fsrc, GeteaFP (dstspec, 12 - lenf), dstspec, 12 - lenf); if (ReadFP (&fsrc, GeteaFP (dstspec, 12 - lenf), dstspec, 12 - lenf)) {
if (GET_EXP (fsrc.h) == 0) if (GET_EXP (fsrc.h) == 0)
fsrc = zero_fac; fsrc = zero_fac;
if ((FPS & (FPS_D + FPS_T)) == 0) if ((FPS & (FPS_D + FPS_T)) == 0)
newV = roundfp11 (&fsrc); newV = roundfp11 (&fsrc);
else newV = 0; else newV = 0;
F_STORE (qdouble, fsrc, FR[ac]); F_STORE (qdouble, fsrc, FR[ac]);
FPS = setfcc (FPS, fsrc.h, newV); FPS = setfcc (FPS, fsrc.h, newV);
}
break; break;
case 014: /* STCff' */ case 014: /* STCff' */
@ -381,27 +401,29 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */
break; break;
case 007: /* CMPf */ case 007: /* CMPf */
ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); if (ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf)) {
F_LOAD (qdouble, FR[ac], fac); F_LOAD (qdouble, FR[ac], fac);
if (GET_EXP (fsrc.h) == 0) if (GET_EXP (fsrc.h) == 0)
fsrc = zero_fac; fsrc = zero_fac;
if (GET_EXP (fac.h) == 0) if (GET_EXP (fac.h) == 0)
fac = zero_fac; fac = zero_fac;
if ((fsrc.h == fac.h) && (fsrc.l == fac.l)) { /* equal? */ if ((fsrc.h == fac.h) && (fsrc.l == fac.l)) { /* equal? */
FPS = (FPS & ~FPS_CC) | FPS_Z; FPS = (FPS & ~FPS_CC) | FPS_Z;
if ((fsrc.h | fsrc.l) == 0) { /* zero? */ if ((fsrc.h | fsrc.l) == 0) { /* zero? */
F_STORE (qdouble, zero_fac, FR[ac]); F_STORE (qdouble, zero_fac, FR[ac]);
}
}
else { /* unequal */
FPS = (FPS & ~FPS_CC) | ((fsrc.h >> (FP_V_SIGN - PSW_V_N)) & FPS_N);
if ((GET_SIGN (fsrc.h ^ fac.h) == 0) && (fac.h != 0) &&
F_LT (fsrc, fac))
FPS = FPS ^ FPS_N;
} }
break;
} }
FPS = (FPS & ~FPS_CC) | ((fsrc.h >> (FP_V_SIGN - PSW_V_N)) & FPS_N);
if ((GET_SIGN (fsrc.h ^ fac.h) == 0) && (fac.h != 0) &&
F_LT (fsrc, fac))
FPS = FPS ^ FPS_N;
break; break;
case 015: /* LDEXP */ case 015: /* LDEXP */
dst = (dstspec <= 07)? R[dstspec]: ReadW (GeteaW (dstspec)); dst = (dstspec <= 07)? R[dstspec]: ReadW (GeteaFW (dstspec));
F_LOAD (qdouble, FR[ac], fac); F_LOAD (qdouble, FR[ac], fac);
fac.h = (fac.h & ~FP_EXP) | (((dst + FP_BIAS) & FP_M_EXP) << FP_V_EXP); fac.h = (fac.h & ~FP_EXP) | (((dst + FP_BIAS) & FP_M_EXP) << FP_V_EXP);
newV = 0; newV = 0;
@ -429,7 +451,7 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */
FPS = (FPS & ~FPS_CC) | (N << PSW_V_N) | (Z << PSW_V_Z); FPS = (FPS & ~FPS_CC) | (N << PSW_V_N) | (Z << PSW_V_Z);
if (dstspec <= 07) if (dstspec <= 07)
R[dstspec] = dst; R[dstspec] = dst;
else WriteW (dst, GeteaW (dstspec)); else WriteW (dst, GeteaFW (dstspec));
break; break;
case 016: /* LDCif */ case 016: /* LDCif */
@ -500,56 +522,131 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */
break; break;
case 002: /* MULf */ case 002: /* MULf */
ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); if (ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf)) {
F_LOAD (qdouble, FR[ac], fac); F_LOAD (qdouble, FR[ac], fac);
newV = mulfp11 (&fac, &fsrc); newV = mulfp11 (&fac, &fsrc);
F_STORE (qdouble, fac, FR[ac]); F_STORE (qdouble, fac, FR[ac]);
FPS = setfcc (FPS, fac.h, newV); FPS = setfcc (FPS, fac.h, newV);
}
break; break;
case 003: /* MODf */ case 003: /* MODf */
ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); if (ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf)) {
F_LOAD (qdouble, FR[ac], fac); F_LOAD (qdouble, FR[ac], fac);
newV = modfp11 (&fac, &fsrc, &modfrac); newV = modfp11 (&fac, &fsrc, &modfrac);
F_STORE (qdouble, fac, FR[ac | 1]); F_STORE (qdouble, fac, FR[ac | 1]);
F_STORE (qdouble, modfrac, FR[ac]); F_STORE (qdouble, modfrac, FR[ac]);
FPS = setfcc (FPS, modfrac.h, newV); FPS = setfcc (FPS, modfrac.h, newV);
}
break; break;
case 004: /* ADDf */ case 004: /* ADDf */
ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); if (ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf)) {
F_LOAD (qdouble, FR[ac], fac); F_LOAD (qdouble, FR[ac], fac);
newV = addfp11 (&fac, &fsrc); newV = addfp11 (&fac, &fsrc);
F_STORE (qdouble, fac, FR[ac]); F_STORE (qdouble, fac, FR[ac]);
FPS = setfcc (FPS, fac.h, newV); FPS = setfcc (FPS, fac.h, newV);
}
break; break;
case 006: /* SUBf */ case 006: /* SUBf */
ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); if (ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf)) {
F_LOAD (qdouble, FR[ac], fac); F_LOAD (qdouble, FR[ac], fac);
if (GET_EXP (fsrc.h) != 0) if (GET_EXP (fsrc.h) != 0)
fsrc.h = fsrc.h ^ FP_SIGN; fsrc.h = fsrc.h ^ FP_SIGN;
newV = addfp11 (&fac, &fsrc); newV = addfp11 (&fac, &fsrc);
F_STORE (qdouble, fac, FR[ac]); F_STORE (qdouble, fac, FR[ac]);
FPS = setfcc (FPS, fac.h, newV); FPS = setfcc (FPS, fac.h, newV);
}
break; break;
case 011: /* DIVf */ case 011: /* DIVf */
ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); if (ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf)) {
F_LOAD (qdouble, FR[ac], fac); F_LOAD (qdouble, FR[ac], fac);
if (GET_EXP (fsrc.h) == 0) { /* divide by zero? */ if (GET_EXP (fsrc.h) == 0) /* divide by zero? */
fpnotrap (FEC_DZRO); fpnotrap (FEC_DZRO);
ABORT (TRAP_INT); else { /* no, do divide */
newV = divfp11 (&fac, &fsrc);
F_STORE (qdouble, fac, FR[ac]);
FPS = setfcc (FPS, fac.h, newV);
}
} }
newV = divfp11 (&fac, &fsrc);
F_STORE (qdouble, fac, FR[ac]);
FPS = setfcc (FPS, fac.h, newV);
break; break;
} /* end switch fop */ } /* end switch fop */
/* Now process any general register modification */
if (fp_change != 0) {
int32 reg = FPCHG_GETREG (fp_change); /* get register */
int32 val = FPCHG_GETVAL (fp_change); /* get value */
if (val & 020) /* negative? */
val = val | (-16); /* ensure proper sext */
R[reg] = (R[reg] + val) & 0177777; /* commit change */
}
return; return;
} }
/* Effective address calculation for word integers */
int32 GeteaFW (int32 spec)
{
int32 adr, reg, ds;
reg = spec & 07; /* register number */
ds = (reg == 7)? isenable: dsenable; /* dspace if not PC */
switch (spec >> 3) { /* decode spec<5:3> */
default: /* can't get here */
case 1: /* (R) */
return (R[reg] | ds);
case 2: /* (R)+ */
adr = R[reg]; /* post increment */
if (reg == 7) /* commit PC chg now */
R[reg] = (R[reg] + 2) & 0177777;
else fp_change = FPCHG (2, reg); /* others, update later */
return (adr | ds);
case 3: /* @(R)+ */
adr = R[reg]; /* post increment */
if (reg == 7) /* commit PC chg now */
R[reg] = (R[reg] + 2) & 0177777;
else fp_change = FPCHG (2, reg); /* others, update later */
adr = ReadW (adr | ds);
return (adr | dsenable);
case 4: /* -(R) */
adr = (R[reg] - 2) & 0177777; /* predecrement */
if (reg == 7) /* commit PC chg now */
R[reg] = adr;
else fp_change = FPCHG (-2, reg); /* others, update later */
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
set_stack_trap (adr);
return (adr | ds);
case 5: /* @-(R) */
adr = (R[reg] - 2) & 0177777; /* predecrement */
if (reg == 7) /* commit PC chg now */
R[reg] = adr;
else fp_change = FPCHG (-2, reg); /* others, update later */
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
set_stack_trap (adr);
adr = ReadW (adr | ds);
return (adr | dsenable);
case 6: /* d(r) */
adr = ReadW (PC | isenable);
PC = (PC + 2) & 0177777;
return (((R[reg] + adr) & 0177777) | dsenable);
case 7: /* @d(R) */
adr = ReadW (PC | isenable);
PC = (PC + 2) & 0177777;
adr = ReadW (((R[reg] + adr) & 0177777) | dsenable);
return (adr | dsenable);
} /* end switch */
}
/* Effective address calculation for fp operands /* Effective address calculation for fp operands
Inputs: Inputs:
@ -561,6 +658,9 @@ return;
Warnings: Warnings:
- Do not call this routine for integer mode 0 operands - Do not call this routine for integer mode 0 operands
- Do not call this routine more than once per instruction - Do not call this routine more than once per instruction
Note that for modes 06 and 07, it is OKAY to bail out of the FP
instruction immediately; no general register updates can occur.
*/ */
int32 GeteaFP (int32 spec, int32 len) int32 GeteaFP (int32 spec, int32 len)
@ -574,7 +674,7 @@ switch (spec >> 3) { /* case on spec */
case 0: /* floating AC */ case 0: /* floating AC */
if (reg >= 06) { if (reg >= 06) {
fpnotrap (FEC_OP); fpnotrap (FEC_OP);
ABORT (TRAP_INT); ABORT (TRAP_INT); /* scuttle instr */
} }
return 0; return 0;
@ -582,33 +682,35 @@ switch (spec >> 3) { /* case on spec */
return (R[reg] | ds); return (R[reg] | ds);
case 2: /* (R)+ */ case 2: /* (R)+ */
if (reg == 7) adr = R[reg]; /* post increment */
len = 2; if (reg == 7) /* commit PC chg now */
R[reg] = ((adr = R[reg]) + len) & 0177777; R[reg] = (R[reg] + 2) & 0177777;
if (update_MM && (reg != 7)) else fp_change = FPCHG (len, reg); /* others, update later */
MMR1 = (len << 3) | reg;
return (adr | ds); return (adr | ds);
case 3: /* @(R)+ */ case 3: /* @(R)+ */
R[reg] = ((adr = R[reg]) + 2) & 0177777; adr = R[reg]; /* post increment */
if (update_MM && (reg != 7)) if (reg == 7) /* commit PC chg now */
MMR1 = 020 | reg; R[reg] = (R[reg] + 2) & 0177777;
else fp_change = FPCHG (2, reg); /* others, update later */
adr = ReadW (adr | ds); adr = ReadW (adr | ds);
return (adr | dsenable); return (adr | dsenable);
case 4: /* -(R) */ case 4: /* -(R) */
adr = R[reg] = (R[reg] - len) & 0177777; adr = (R[reg] - len) & 0177777; /* predecrement */
if (update_MM && (reg != 7)) if (reg == 7) /* commit PC chg now */
MMR1 = (((-len) & 037) << 3) | reg; R[reg] = adr;
else fp_change = FPCHG (-len, reg); /* others, udpate later */
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
set_stack_trap (adr); set_stack_trap (adr);
return (adr | ds); return (adr | ds);
case 5: /* @-(R) */ case 5: /* @-(R) */
adr = R[reg] = (R[reg] - 2) & 0177777; adr = (R[reg] - 2) & 0177777; /* predecrement */
if (update_MM && (reg != 7)) if (reg == 7) /* commit PC chg now */
MMR1 = 0360 | reg; R[reg] = adr;
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) else fp_change = FPCHG (-2, reg); /* others, update later */
if ((reg == 6) && (cm == MD_KER) && ((adr - 2) < (STKLIM + STKL_Y)))
set_stack_trap (adr); set_stack_trap (adr);
adr = ReadW (adr | ds); adr = ReadW (adr | ds);
return (adr | dsenable); return (adr | dsenable);
@ -653,15 +755,18 @@ return ((ReadW (VA) << 16) |
VA = virtual address, VA<18:16> = mode, I/D space VA = virtual address, VA<18:16> = mode, I/D space
spec = specifier spec = specifier
len = length (4/8 bytes) len = length (4/8 bytes)
Output:
TRUE if read succeeded
FALSE if instruction must be NOP'd
*/ */
void ReadFP (fpac_t *fptr, int32 VA, int32 spec, int32 len) t_bool ReadFP (fpac_t *fptr, int32 VA, int32 spec, int32 len)
{ {
int32 exta; int32 exta;
if (spec <= 07) { if (spec <= 07) {
F_LOAD_P (len == QUAD, FR[spec], fptr); F_LOAD_P (len == QUAD, FR[spec], fptr);
return; return TRUE;
} }
if (spec == 027) { if (spec == 027) {
fptr->h = (ReadW (VA) << FP_V_F0); fptr->h = (ReadW (VA) << FP_V_F0);
@ -676,9 +781,11 @@ else {
(ReadW (exta | ((VA + 6) & 0177777)) << FP_V_F3); (ReadW (exta | ((VA + 6) & 0177777)) << FP_V_F3);
else fptr->l = 0; else fptr->l = 0;
} }
if ((GET_SIGN (fptr->h) != 0) && (GET_EXP (fptr->h) == 0) && if ((GET_SIGN (fptr->h) != 0) &&
(fpnotrap (FEC_UNDFV) == 0)) ABORT (TRAP_INT); (GET_EXP (fptr->h) == 0) &&
return; (fpnotrap (FEC_UNDFV) == 0))
return FALSE;
return TRUE;
} }
/* Write integer result /* Write integer result
@ -1228,7 +1335,8 @@ int32 fpnotrap (int32 code)
{ {
static const int32 test_code[] = { 0, 0, 0, FPS_IC, FPS_IV, FPS_IU, FPS_IUV }; static const int32 test_code[] = { 0, 0, 0, FPS_IC, FPS_IV, FPS_IU, FPS_IUV };
if ((code >= FEC_ICVT) && (code <= FEC_UNDFV) && if ((code >= FEC_ICVT) &&
(code <= FEC_UNDFV) &&
((FPS & test_code[code >> 1]) == 0)) ((FPS & test_code[code >> 1]) == 0))
return TRUE; return TRUE;
FPS = FPS | FPS_ER; FPS = FPS | FPS_ER;