3b2: WE32106 Math Acceleration Unit (MAU)
This change adds support for the WE32106 Math Acceleration Unit (MAU). The WE32106 is an IEEE-754 1985 compatible floating point math acceleration unit that was an optional component on the 3B2/310 and 3B2/400. The MAU is implemented using software floating point routines. As always, there may be bugs, but the MAU currently passes extensive floating point tests with exactly the same results as a real 3B2/400 equipped with a physical MAU, so I hope these are few.
This commit is contained in:
parent
47bac1f665
commit
571c8f96a5
11 changed files with 3964 additions and 40 deletions
|
@ -178,9 +178,6 @@ static DEBTAB cpu_deb_tab[] = {
|
|||
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX|UNIT_BINK|UNIT_IDLE, MAXMEMSIZE) };
|
||||
|
||||
#define UNIT_V_EXHALT (UNIT_V_UF + 0) /* halt to console */
|
||||
#define UNIT_EXHALT (1u << UNIT_V_EXHALT)
|
||||
|
||||
/*
|
||||
* TODO: This works fine for now, but the moment we want to emulate
|
||||
* SCSI (0x0100) or EPORTS (0x0102) we're in trouble!
|
||||
|
@ -236,7 +233,11 @@ DEVICE cpu_dev = {
|
|||
0, /* Debug control flags */
|
||||
cpu_deb_tab, /* Debug flag names */
|
||||
&cpu_set_size, /* Memory size change */
|
||||
NULL /* Logical names */
|
||||
NULL, /* Logical names */
|
||||
NULL, /* Help routine */
|
||||
NULL, /* Attach Help Routine */
|
||||
NULL, /* Help Context */
|
||||
&cpu_description /* Device Description */
|
||||
};
|
||||
|
||||
#define HWORD_OP_COUNT 11
|
||||
|
@ -259,12 +260,12 @@ mnemonic hword_ops[HWORD_OP_COUNT] = {
|
|||
mnemonic ops[256] = {
|
||||
{0x00, 0, OP_NONE, NA, "halt", -1, -1, -1, -1},
|
||||
{0x01, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
{0x02, 2, OP_COPR, WD, "SPOPRD", -1, -1, -1, -1},
|
||||
{0x03, 3, OP_COPR, WD, "SPOPD2", -1, -1, -1, -1},
|
||||
{0x02, 2, OP_COPR, WD, "SPOPRD", 1, -1, -1, -1},
|
||||
{0x03, 3, OP_COPR, WD, "SPOPD2", 1, -1, -1, 2},
|
||||
{0x04, 2, OP_DESC, WD, "MOVAW", 0, -1, -1, 1},
|
||||
{0x05, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
{0x06, 2, OP_COPR, WD, "SPOPRT", -1, -1, -1, -1},
|
||||
{0x07, 3, OP_COPR, WD, "SPOPT2", -1, -1, -1, -1},
|
||||
{0x06, 2, OP_COPR, WD, "SPOPRT", 1, -1, -1, -1},
|
||||
{0x07, 3, OP_COPR, WD, "SPOPT2", 1, -1, -1, 2},
|
||||
{0x08, 0, OP_NONE, NA, "RET", -1, -1, -1, -1},
|
||||
{0x09, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
{0x0a, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
|
@ -276,11 +277,11 @@ mnemonic ops[256] = {
|
|||
{0x10, 1, OP_DESC, WD, "SAVE", 0, -1, -1, -1},
|
||||
{0x11, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
{0x12, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
{0x13, 2, OP_COPR, WD, "SPOPWD", -1, -1, -1, -1},
|
||||
{0x13, 2, OP_COPR, WD, "SPOPWD", -1, -1, -1, 1},
|
||||
{0x14, 1, OP_BYTE, NA, "EXTOP", -1, -1, -1, -1},
|
||||
{0x15, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
{0x16, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
{0x17, 2, OP_COPR, WD, "SPOPWT", -1, -1, -1, -1},
|
||||
{0x17, 2, OP_COPR, WD, "SPOPWT", -1, -1, -1, 1},
|
||||
{0x18, 1, OP_DESC, WD, "RESTORE", 0, -1, -1, -1},
|
||||
{0x19, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
{0x1a, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
|
@ -291,8 +292,8 @@ mnemonic ops[256] = {
|
|||
{0x1f, 1, OP_DESC, BT, "SWAPBI", -1, -1, -1, 0}, /* 3-122 252 */
|
||||
{0x20, 1, OP_DESC, WD, "POPW", -1, -1, -1, 0},
|
||||
{0x21, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
{0x22, 2, OP_COPR, WD, "SPOPRS", -1, -1, -1, -1},
|
||||
{0x23, 3, OP_COPR, WD, "SPOPS2", -1, -1, -1, -1},
|
||||
{0x22, 2, OP_COPR, WD, "SPOPRS", 1, -1, -1, -1},
|
||||
{0x23, 3, OP_COPR, WD, "SPOPS2", 1, -1, -1, 2},
|
||||
{0x24, 1, OP_DESC, NA, "JMP", -1, -1, -1, 0},
|
||||
{0x25, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
{0x26, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
|
@ -308,7 +309,7 @@ mnemonic ops[256] = {
|
|||
{0x30, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, /* Two-byte instructions */
|
||||
{0x31, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
{0x32, 1, OP_COPR, WD, "SPOP", -1, -1, -1, -1},
|
||||
{0x33, 2, OP_COPR, WD, "SPOPWS", -1, -1, -1, -1},
|
||||
{0x33, 2, OP_COPR, WD, "SPOPWS", -1, -1, -1, 1},
|
||||
{0x34, 1, OP_DESC, WD, "JSB", -1, -1, -1, 0},
|
||||
{0x35, -1, OP_NONE, NA, "???", -1, -1, -1, -1},
|
||||
{0x36, 1, OP_HALF, NA, "BSBH", -1, -1, -1, 0},
|
||||
|
@ -1709,6 +1710,9 @@ t_stat sim_instr(void)
|
|||
/* Generic index */
|
||||
uint32 i;
|
||||
|
||||
/* Used by oprocessor instructions */
|
||||
uint32 coprocessor_word;
|
||||
|
||||
operand *src1, *src2, *src3, *dst;
|
||||
|
||||
stop_reason = 0;
|
||||
|
@ -1868,6 +1872,11 @@ t_stat sim_instr(void)
|
|||
* Operate on the decoded instruction.
|
||||
*/
|
||||
|
||||
/* Special case for coprocessor instructions */
|
||||
if (cpu_instr->mn->mode == OP_COPR) {
|
||||
coprocessor_word = cpu_instr->operands[0].embedded.w;
|
||||
}
|
||||
|
||||
/* Get the operands */
|
||||
if (cpu_instr->mn->src_op1 >= 0) {
|
||||
src1 = &cpu_instr->operands[cpu_instr->mn->src_op1];
|
||||
|
@ -2834,18 +2843,40 @@ t_stat sim_instr(void)
|
|||
pc_incr = 0;
|
||||
break;
|
||||
case SPOP:
|
||||
sim_debug(TRACE_DBG, &cpu_dev, "SPOP\n");
|
||||
/* Memory fault is signaled when no support processor is
|
||||
active */
|
||||
if (mau_broadcast(coprocessor_word, 0, 0) != SCPE_OK) {
|
||||
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
|
||||
}
|
||||
break;
|
||||
case SPOPD2:
|
||||
case SPOPS2:
|
||||
case SPOPT2:
|
||||
sim_debug(TRACE_DBG, &cpu_dev, "SPOP{D|S|T}2\n");
|
||||
a = cpu_effective_address(src1);
|
||||
b = cpu_effective_address(dst);
|
||||
if (mau_broadcast(coprocessor_word, a, b) != SCPE_OK) {
|
||||
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
|
||||
}
|
||||
break;
|
||||
case SPOPRD:
|
||||
case SPOPRS:
|
||||
case SPOPRT:
|
||||
sim_debug(TRACE_DBG, &cpu_dev, "SPOPR{D|S|T}\n");
|
||||
a = cpu_effective_address(src1);
|
||||
if (mau_broadcast(coprocessor_word, a, 0) != SCPE_OK) {
|
||||
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
|
||||
}
|
||||
break;
|
||||
case SPOPWD:
|
||||
case SPOPWS:
|
||||
case SPOPWT:
|
||||
/* Memory fault is signaled when no support processor is
|
||||
active */
|
||||
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
|
||||
sim_debug(TRACE_DBG, &cpu_dev, "SPOPW{D|S|T}\n");
|
||||
a = cpu_effective_address(dst);
|
||||
if (mau_broadcast(coprocessor_word, 0, a) != SCPE_OK) {
|
||||
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);
|
||||
}
|
||||
break;
|
||||
case SUBW2:
|
||||
case SUBH2:
|
||||
|
@ -3682,20 +3713,19 @@ static SIM_INLINE void add(t_uint64 a, t_uint64 b, operand *dst)
|
|||
void cpu_abort(uint8 et, uint8 isc)
|
||||
{
|
||||
/* We don't trap Integer Overflow if the OE bit is not set */
|
||||
if ((R[NUM_PSW] & PSW_OE_MASK) || isc != INTEGER_OVERFLOW) {
|
||||
R[NUM_PSW] &= ~(PSW_ET_MASK); /* Clear ET */
|
||||
R[NUM_PSW] &= ~(PSW_ISC_MASK); /* Clear ISC */
|
||||
R[NUM_PSW] |= et; /* Set ET */
|
||||
R[NUM_PSW] |= (uint32) (isc << PSW_ISC); /* Set ISC */
|
||||
|
||||
/* TODO: We no longer use ABORT_TRAP or ABORT_EXC, so
|
||||
* it would be nice to clean this up. */
|
||||
if (et == 3 && (isc == BREAKPOINT_TRAP ||
|
||||
isc == INTEGER_OVERFLOW ||
|
||||
isc == TRACE_TRAP)) {
|
||||
longjmp(save_env, ABORT_TRAP);
|
||||
} else {
|
||||
longjmp(save_env, ABORT_EXC);
|
||||
}
|
||||
if ((R[NUM_PSW] & PSW_OE_MASK) == 0 && isc == INTEGER_OVERFLOW) {
|
||||
return;
|
||||
}
|
||||
|
||||
R[NUM_PSW] &= ~(PSW_ET_MASK); /* Clear ET */
|
||||
R[NUM_PSW] &= ~(PSW_ISC_MASK); /* Clear ISC */
|
||||
R[NUM_PSW] |= et; /* Set ET */
|
||||
R[NUM_PSW] |= (uint32) (isc << PSW_ISC); /* Set ISC */
|
||||
|
||||
longjmp(save_env, ABORT_EXC);
|
||||
}
|
||||
|
||||
CONST char *cpu_description(DEVICE *dptr)
|
||||
{
|
||||
return "WE32100";
|
||||
}
|
||||
|
|
|
@ -377,7 +377,7 @@ typedef struct _operand {
|
|||
* An inst is a combination of a decoded instruction and
|
||||
* 0 to 4 operands. Also used for history record keeping.
|
||||
*/
|
||||
typedef struct _instr {
|
||||
typedef struct {
|
||||
mnemonic *mn;
|
||||
uint32 psw;
|
||||
uint32 sp;
|
||||
|
@ -401,6 +401,7 @@ t_stat cpu_show_cio(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
|||
t_stat cpu_set_halt(UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat cpu_clear_halt(UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat cpu_boot(int32 unit_num, DEVICE *dptr);
|
||||
CONST char *cpu_description(DEVICE *dptr);
|
||||
|
||||
t_bool cpu_is_pc_a_subroutine_call (t_addr **ret_addrs);
|
||||
|
||||
|
|
|
@ -60,6 +60,9 @@ noret __libc_longjmp (jmp_buf buf, int val);
|
|||
#define UNUSED(x) ((void)((x)))
|
||||
#endif
|
||||
|
||||
#define UNIT_V_EXHALT (UNIT_V_UF + 0)
|
||||
#define UNIT_EXHALT (1u << UNIT_V_EXHALT)
|
||||
|
||||
/* -t flag: Translate a virtual address */
|
||||
#define EX_T_FLAG 1 << 19
|
||||
/* -v flag for examine routine */
|
||||
|
@ -163,6 +166,7 @@ noret __libc_longjmp (jmp_buf buf, int val);
|
|||
#define PKT_DBG 0x0400
|
||||
#define ERR_MSG 0x0800
|
||||
#define CACHE_DBG 0x1000
|
||||
#define DECODE_DBG 0x2000
|
||||
|
||||
/* Data types operated on by instructions. NB: These integer values
|
||||
have meaning when decoding instructions, so this is not just an
|
||||
|
@ -405,6 +409,11 @@ extern uint32 read_w(uint32 va, uint8 acc);
|
|||
extern void write_b(uint32 va, uint8 val);
|
||||
extern void write_h(uint32 va, uint16 val);
|
||||
extern void write_w(uint32 va, uint32 val);
|
||||
extern void pwrite_w(uint32 pa, uint32 val);
|
||||
extern uint32 pread_w(uint32 pa);
|
||||
|
||||
/* global symbols from the MAU */
|
||||
extern t_stat mau_broadcast(uint32 cmd, uint32 src, uint32 dst);
|
||||
|
||||
/* Globally scoped CPU functions */
|
||||
extern void cpu_abort(uint8 et, uint8 isc);
|
||||
|
|
3470
3B2/3b2_mau.c
Normal file
3470
3B2/3b2_mau.c
Normal file
File diff suppressed because it is too large
Load diff
375
3B2/3b2_mau.h
Normal file
375
3B2/3b2_mau.h
Normal file
|
@ -0,0 +1,375 @@
|
|||
/* 3b2_mmu.c: AT&T 3B2 Model 400 Math Acceleration Unit (WE32106 MAU)
|
||||
Header
|
||||
|
||||
Copyright (c) 2019, Seth J. Morabito
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of the author shall
|
||||
not be used in advertising or otherwise to promote the sale, use or
|
||||
other dealings in this Software without prior written authorization
|
||||
from the author.
|
||||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
This file is part of a simulation of the WE32106 Math Acceleration
|
||||
Unit. The WE32106 MAU is an IEEE-754 compabitle floating point
|
||||
hardware math accelerator that was available as an optional
|
||||
component on the AT&T 3B2/310 and 3B2/400, and a standard component
|
||||
on the 3B2/500, 3B2/600, and 3B2/1000.
|
||||
|
||||
Portions of this code are derived from the SoftFloat 2c library by
|
||||
John R. Hauser. Functions derived from SoftFloat 2c are clearly
|
||||
marked in the comments.
|
||||
|
||||
Legal Notice
|
||||
============
|
||||
|
||||
SoftFloat was written by John R. Hauser. Release 2c of SoftFloat
|
||||
was made possible in part by the International Computer Science
|
||||
Institute, located at Suite 600, 1947 Center Street, Berkeley,
|
||||
California 94704. Funding was partially provided by the National
|
||||
Science Foundation under grant MIP-9311980. The original version
|
||||
of this code was written as part of a project to build a
|
||||
fixed-point vector processor in collaboration with the University
|
||||
of California at Berkeley, overseen by Profs. Nelson Morgan and
|
||||
John Wawrzynek.
|
||||
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable
|
||||
effort has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS
|
||||
THAT WILL AT TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS
|
||||
SOFTWARE IS RESTRICTED TO PERSONS AND ORGANIZATIONS WHO CAN AND
|
||||
WILL TOLERATE ALL LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE
|
||||
TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR THE
|
||||
INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE
|
||||
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER
|
||||
SCIENCE INSTITUTE (possibly via similar legal notice) AGAINST ALL
|
||||
LOSSES, COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND
|
||||
CLIENTS DUE TO THE SOFTWARE, OR INCURRED BY ANYONE DUE TO A
|
||||
DERIVATIVE WORK THEY CREATE USING ANY PART OF THE SOFTWARE.
|
||||
|
||||
The following are expressly permitted, even for commercial
|
||||
purposes:
|
||||
|
||||
(1) distribution of SoftFloat in whole or in part, as long as this
|
||||
and other legal notices remain and are prominent, and provided also
|
||||
that, for a partial distribution, prominent notice is given that it
|
||||
is a subset of the original; and
|
||||
|
||||
(2) inclusion or use of SoftFloat in whole or in part in a
|
||||
derivative work, provided that the use restrictions above are met
|
||||
and the minimal documentation requirements stated in the source
|
||||
code are satisfied.
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Data Types
|
||||
==========
|
||||
|
||||
The WE32106 MAU stores values using IEEE-754 1985 types, plus a
|
||||
non-standard Decimal type.
|
||||
|
||||
- Decimal Type - 18 BCD digits long. Each digit is 4 bits wide.
|
||||
Sign is encoded in byte 0.
|
||||
|
||||
3322 2222 2222 1111 1111 1100 0000 0000
|
||||
1098 7654 3210 9876 5432 1098 7654 3210
|
||||
+-------------------+----+----+----+----+
|
||||
| unused | D18| D17| D16| D15| High Word
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| D14| D13| D12| D11| D10| D09| D08| D07| Middle Word
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| D06| D05| D04| D03| D02| D01| D00|sign| Low Word
|
||||
+----+----+----+----+----+----+----+----+
|
||||
|
||||
Sign: 0: Positive Infinity 10: Positive Number
|
||||
1: Negative Infinity 11: Negative Number
|
||||
2: Positive NaN 12: Positive Number
|
||||
3: Negative NaN 13: Negative Number
|
||||
4-9: Trapping NaN 14-15: Positive Number
|
||||
|
||||
- Extended Precision (80-bit) - exponent biased by 16383
|
||||
|
||||
3 322222222221111 1 111110000000000
|
||||
1 098765432109876 5 432109876543210
|
||||
+-----------------+-+---------------+
|
||||
| unused |S| Exponent | High Word
|
||||
+-+---------------+-+---------------+
|
||||
|J| Fraction (high word) | Middle Word
|
||||
+-+---------------------------------+
|
||||
| Fraction (low word) | Low Word
|
||||
+-----------------------------------+
|
||||
|
||||
|
||||
- Double Precision (64-bit) - exponent biased by 1023
|
||||
|
||||
3 3222222222 211111111110000000000
|
||||
1 0987654321 098765432109876543210
|
||||
+-+----------+---------------------+
|
||||
|S| Exponent | Fraction (high) | High Word
|
||||
+-+----------+---------------------+
|
||||
| Fraction (low) | Low Word
|
||||
+----------------------------------+
|
||||
|
||||
|
||||
- Single Precision (32-bit) - exponent biased by 127
|
||||
|
||||
3 32222222 22211111111110000000000
|
||||
1 09876543 21098765432109876543210
|
||||
+-+--------+-----------------------+
|
||||
|S| Exp | Fraction |
|
||||
+-+--------+-----------------------+
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _3B2_MAU_H
|
||||
#define _3B2_MAU_H
|
||||
|
||||
#include "3b2_defs.h"
|
||||
|
||||
#define SRC_LEN_INVALID 0
|
||||
#define SRC_LEN_SINGLE 1
|
||||
#define SRC_LEN_DOUBLE 2
|
||||
#define SRC_LEN_TRIPLE 3
|
||||
|
||||
#define MAU_ASR_RC_SHIFT 22
|
||||
|
||||
#define MAU_ASR_PR 0x20u /* Partial Remainder */
|
||||
#define MAU_ASR_QS 0x40u /* Divide By Zero Sticky */
|
||||
#define MAU_ASR_US 0x80u /* Underflow Sticky */
|
||||
#define MAU_ASR_OS 0x100u /* Overflow Sticky */
|
||||
#define MAU_ASR_IS 0x200u /* Invalid Operation Sticky */
|
||||
#define MAU_ASR_PM 0x400u /* Inexact Mask */
|
||||
#define MAU_ASR_QM 0x800u /* Divide by Zero Mask */
|
||||
#define MAU_ASR_UM 0x1000u /* Underflow Mask */
|
||||
#define MAU_ASR_OM 0x2000u /* Overflow Mask */
|
||||
#define MAU_ASR_IM 0x4000u /* Invalid Operation Mask */
|
||||
|
||||
#define MAU_ASR_UO 0x10000u /* Unordered */
|
||||
#define MAU_ASR_CSC 0x20000u /* Context Switch Control */
|
||||
#define MAU_ASR_PS 0x40000u /* Inexact Sticky */
|
||||
#define MAU_ASR_IO 0x80000u /* Integer Overflow */
|
||||
#define MAU_ASR_Z 0x100000u /* Zero Flag */
|
||||
#define MAU_ASR_N 0x200000u /* Negative Flag */
|
||||
#define MAU_ASR_RC 0x400000u /* Round Control */
|
||||
|
||||
#define MAU_ASR_NTNC 0x1000000u /* Nontrapping NaN Control */
|
||||
#define MAU_ASR_ECP 0x2000000u /* Exception Condition */
|
||||
|
||||
#define MAU_ASR_RA 0x80000000u /* Result Available */
|
||||
|
||||
#define MAU_RC_RN 0 /* Round toward Nearest */
|
||||
#define MAU_RC_RP 1 /* Round toward Plus Infin. */
|
||||
#define MAU_RC_RM 2 /* Round toward Neg. Infin. */
|
||||
#define MAU_RC_RZ 3 /* Round toward Zero */
|
||||
|
||||
#define SFP_SIGN(V) (((V) >> 31) & 1)
|
||||
#define SFP_EXP(V) (((V) >> 23) & 0xff)
|
||||
#define SFP_FRAC(V) ((V) & 0x7fffff)
|
||||
|
||||
#define DFP_SIGN(V) (((V) >> 63) & 1)
|
||||
#define DFP_EXP(V) (((V) >> 52) & 0x7ff)
|
||||
#define DFP_FRAC(V) ((V) & 0xfffffffffffffull)
|
||||
|
||||
#define XFP_SIGN(V) (((V)->sign_exp >> 15) & 1)
|
||||
#define XFP_EXP(V) ((V)->sign_exp & 0x7fff)
|
||||
#define XFP_FRAC(V) ((V)->frac)
|
||||
|
||||
#define XFP_IS_NORMAL(V) ((V)->frac & 0x8000000000000000ull)
|
||||
|
||||
#define DEFAULT_XFP_NAN_SIGN_EXP 0xffff
|
||||
#define DEFAULT_XFP_NAN_FRAC 0xc000000000000000ull
|
||||
|
||||
#define SFP_IS_TRAPPING_NAN(V) (((((V) >> 22) & 0x1ff) == 0x1fe) && \
|
||||
((V) & 0x3fffff))
|
||||
#define DFP_IS_TRAPPING_NAN(V) (((((V) >> 51) & 0xfff) == 0xffe) && \
|
||||
((V) & 0x7ffffffffffffull))
|
||||
#define XFP_IS_NAN(V) ((((V)->sign_exp & 0x7fff) == 0x7fff) && \
|
||||
(t_uint64)((V)->frac << 1))
|
||||
#define XFP_IS_TRAPPING_NAN(V) ((((V)->sign_exp) & 0x7fff) && \
|
||||
((((V)->frac) & ~(0x4000000000000000ull)) << 1) && \
|
||||
(((V)->frac) == ((V)->frac & ~(0x4000000000000000ull))))
|
||||
#define PACK_DFP(SIGN,EXP,FRAC) ((((t_uint64)(SIGN))<<63) + \
|
||||
(((t_uint64)(EXP))<<52) + \
|
||||
((t_uint64)(FRAC)))
|
||||
#define PACK_SFP(SIGN,EXP,FRAC) (((uint32)(SIGN)<<31) + \
|
||||
((uint32)(EXP)<<23) + \
|
||||
((uint32)(FRAC)))
|
||||
#define PACK_XFP(SIGN,EXP,FRAC,V) do { \
|
||||
(V)->frac = (FRAC); \
|
||||
(V)->sign_exp = ((uint16)(SIGN) << 15) + (EXP); \
|
||||
} while (0)
|
||||
|
||||
#define PACK_XFP_S(SIGN,EXP,FRAC,S,V) do { \
|
||||
(V)->frac = (FRAC); \
|
||||
(V)->sign_exp = ((uint16)(SIGN) << 15) + (EXP); \
|
||||
(V)->s = (S) != 0; \
|
||||
} while (0)
|
||||
|
||||
#define MAU_RM ((RM)((mau_state.asr >> 22) & 3))
|
||||
|
||||
typedef enum {
|
||||
M_ADD = 0x02,
|
||||
M_SUB = 0x03,
|
||||
M_DIV = 0x04,
|
||||
M_REM = 0x05,
|
||||
M_MUL = 0x06,
|
||||
M_MOVE = 0x07,
|
||||
M_RDASR = 0x08,
|
||||
M_WRASR = 0x09,
|
||||
M_CMP = 0x0a,
|
||||
M_CMPE = 0x0b,
|
||||
M_ABS = 0x0c,
|
||||
M_SQRT = 0x0d,
|
||||
M_RTOI = 0x0e,
|
||||
M_FTOI = 0x0f,
|
||||
M_ITOF = 0x10,
|
||||
M_DTOF = 0x11,
|
||||
M_FTOD = 0x12,
|
||||
M_NOP = 0x13,
|
||||
M_EROF = 0x14,
|
||||
M_NEG = 0x17,
|
||||
M_LDR = 0x18,
|
||||
M_CMPS = 0x1a,
|
||||
M_CMPES = 0x1b
|
||||
} mau_opcodes;
|
||||
|
||||
typedef enum {
|
||||
M_OP3_F0_SINGLE,
|
||||
M_OP3_F1_SINGLE,
|
||||
M_OP3_F2_SINGLE,
|
||||
M_OP3_F3_SINGLE,
|
||||
M_OP3_F0_DOUBLE,
|
||||
M_OP3_F1_DOUBLE,
|
||||
M_OP3_F2_DOUBLE,
|
||||
M_OP3_F3_DOUBLE,
|
||||
M_OP3_F0_TRIPLE,
|
||||
M_OP3_F1_TRIPLE,
|
||||
M_OP3_F2_TRIPLE,
|
||||
M_OP3_F3_TRIPLE,
|
||||
M_OP3_MEM_SINGLE,
|
||||
M_OP3_MEM_DOUBLE,
|
||||
M_OP3_MEM_TRIPLE,
|
||||
M_OP3_NONE
|
||||
} op3_spec;
|
||||
|
||||
/* Specifier bytes for Operands 1 and 2 */
|
||||
typedef enum {
|
||||
M_OP_F0,
|
||||
M_OP_F1,
|
||||
M_OP_F2,
|
||||
M_OP_F3,
|
||||
M_OP_MEM_SINGLE,
|
||||
M_OP_MEM_DOUBLE,
|
||||
M_OP_MEM_TRIPLE,
|
||||
M_OP_NONE
|
||||
} op_spec;
|
||||
|
||||
/*
|
||||
* Not-a-Number Type
|
||||
*/
|
||||
typedef struct {
|
||||
t_bool sign;
|
||||
t_uint64 high;
|
||||
t_uint64 low;
|
||||
} NAN_T;
|
||||
|
||||
/*
|
||||
* Extended Precision (80 bits).
|
||||
*
|
||||
* Note that an undocumented feature of the WE32106 requires the use
|
||||
* of uint32 rather than uint16 for the sign and exponent components
|
||||
* of the struct. Although bits 80-95 are "unused", several
|
||||
* diagnostics actually expect these bits to be moved and preserved on
|
||||
* word transfers. They are ignored and discarded by math routines,
|
||||
* however.
|
||||
*
|
||||
* The 's' field holds the Sticky bit used by rounding.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32 sign_exp; /* Sign and Exponent */
|
||||
t_uint64 frac; /* Fraction/Significand/Mantissa */
|
||||
t_bool s; /* Sticky bit */
|
||||
} XFP;
|
||||
|
||||
typedef struct {
|
||||
uint32 h;
|
||||
t_uint64 l;
|
||||
} DEC;
|
||||
|
||||
/*
|
||||
* Supported rounding modes.
|
||||
*/
|
||||
typedef enum {
|
||||
ROUND_NEAREST,
|
||||
ROUND_PLUS_INF,
|
||||
ROUND_MINUS_INF,
|
||||
ROUND_ZERO
|
||||
} RM;
|
||||
|
||||
/*
|
||||
* Double Precision (64 bits)
|
||||
*/
|
||||
typedef t_uint64 DFP;
|
||||
|
||||
/*
|
||||
* Single Precision (32 bits)
|
||||
*/
|
||||
typedef uint32 SFP;
|
||||
|
||||
/*
|
||||
* MAU state
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
uint32 cmd;
|
||||
/* Exception */
|
||||
uint32 exception;
|
||||
/* Status register */
|
||||
uint32 asr;
|
||||
t_bool trapping_nan;
|
||||
/* Generate a Non-Trapping NaN */
|
||||
t_bool ntnan;
|
||||
/* Source (from broadcast) */
|
||||
uint32 src;
|
||||
/* Destination (from broadcast) */
|
||||
uint32 dst;
|
||||
uint8 opcode;
|
||||
uint8 op1;
|
||||
uint8 op2;
|
||||
uint8 op3;
|
||||
/* Data Register */
|
||||
XFP dr;
|
||||
/* Operand Registers */
|
||||
XFP f0;
|
||||
XFP f1;
|
||||
XFP f2;
|
||||
XFP f3;
|
||||
} MAU_STATE;
|
||||
|
||||
extern DEVICE mau_dev;
|
||||
|
||||
t_stat mau_reset(DEVICE *dptr);
|
||||
t_stat mau_attach(UNIT *uptr, CONST char *cptr);
|
||||
t_stat mau_detach(UNIT *uptr);
|
||||
t_stat mau_broadcast(uint32 cmd, uint32 src, uint32 dst);
|
||||
CONST char *mau_description(DEVICE *dptr);
|
||||
|
||||
#endif
|
|
@ -52,11 +52,32 @@ REG mmu_reg[] = {
|
|||
};
|
||||
|
||||
DEVICE mmu_dev = {
|
||||
"MMU", &mmu_unit, mmu_reg, NULL,
|
||||
1, 16, 8, 4, 16, 32,
|
||||
NULL, NULL, &mmu_init,
|
||||
NULL, NULL, NULL, NULL,
|
||||
DEV_DEBUG, 0, sys_deb_tab
|
||||
"MMU", /* name */
|
||||
&mmu_unit, /* units */
|
||||
mmu_reg, /* registers */
|
||||
NULL, /* modifiers */
|
||||
1, /* #units */
|
||||
16, /* address radix */
|
||||
8, /* address width */
|
||||
4, /* address incr */
|
||||
16, /* data radix */
|
||||
32, /* data width */
|
||||
NULL, /* examine routine */
|
||||
NULL, /* deposit routine */
|
||||
&mmu_init, /* reset routine */
|
||||
NULL, /* boot routine */
|
||||
NULL, /* attach routine */
|
||||
NULL, /* detach routine */
|
||||
NULL, /* context */
|
||||
DEV_DEBUG, /* flags */
|
||||
0, /* debug control flags */
|
||||
sys_deb_tab, /* debug flag names */
|
||||
NULL, /* memory size change */
|
||||
NULL, /* logical name */
|
||||
NULL, /* help routine */
|
||||
NULL, /* attach help routine */
|
||||
NULL, /* help context */
|
||||
&mmu_description /* device description */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1083,3 +1104,8 @@ void write_w(uint32 va, uint32 val)
|
|||
{
|
||||
pwrite_w(mmu_xlate_addr(va, ACC_W), val);
|
||||
}
|
||||
|
||||
CONST char *mmu_description(DEVICE *dptr)
|
||||
{
|
||||
return "WE32101";
|
||||
}
|
||||
|
|
|
@ -322,6 +322,7 @@ extern DEVICE mmu_dev;
|
|||
t_stat mmu_init(DEVICE *dptr);
|
||||
uint32 mmu_read(uint32 pa, size_t size);
|
||||
void mmu_write(uint32 pa, uint32 val, size_t size);
|
||||
CONST char *mmu_description(DEVICE *dptr);
|
||||
|
||||
/* Physical memory read/write */
|
||||
uint8 pread_b(uint32 pa);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "3b2_ctc.h"
|
||||
#include "3b2_ports.h"
|
||||
#include "3b2_ni.h"
|
||||
#include "3b2_mau.h"
|
||||
#include "3b2_sysdev.h"
|
||||
|
||||
char sim_name[] = "AT&T 3B2 Model 400";
|
||||
|
@ -53,6 +54,7 @@ extern instr *cpu_instr;
|
|||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&mmu_dev,
|
||||
&mau_dev,
|
||||
&timer_dev,
|
||||
&tod_dev,
|
||||
&nvram_dev,
|
||||
|
@ -86,6 +88,7 @@ const char *sim_stop_messages[] = {
|
|||
void full_reset()
|
||||
{
|
||||
cpu_reset(&cpu_dev);
|
||||
mau_reset(&mau_dev);
|
||||
tti_reset(&tti_dev);
|
||||
contty_reset(&contty_dev);
|
||||
iu_timer_reset(&iu_timer_dev);
|
||||
|
|
|
@ -220,6 +220,10 @@
|
|||
RelativePath="..\3B2\3b2_iu.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\3B2\3b2_mau.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\3B2\3b2_mmu.c"
|
||||
>
|
||||
|
@ -508,6 +512,10 @@
|
|||
RelativePath="..\3B2\3b2_iu.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\3B2\3b2_mau.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\3B2\3b2_mmu.h"
|
||||
>
|
||||
|
|
|
@ -328,8 +328,8 @@ ATT3B2_LIB = $(LIB_DIR)ATT3B2-$(ARCH).OLB
|
|||
ATT3B2_SOURCE = $(ATT3B2_DIR)3B2_CPU.C,$(ATT3B2_DIR)3B2_DMAC.C,\
|
||||
$(ATT3B2_DIR)3B2_ID.C,$(ATT3B2_DIR)3B2_IF.C,\
|
||||
$(ATT3B2_DIR)3B2_IO.C,$(ATT3B2_DIR)3B2_IU.C,\
|
||||
$(ATT3B2_DIR)3B2_MMU.C,$(ATT3B2_DIR)3B2_SYS.C,\
|
||||
$(ATT3B2_DIR)3B2_SYSDEV.C
|
||||
$(ATT3B2_DIR)3B2_MAU.C,$(ATT3B2_DIR)3B2_MMU.C,\
|
||||
$(ATT3B2_DIR)3B2_SYS.C,$(ATT3B2_DIR)3B2_SYSDEV.C
|
||||
ATT3B2_OPTIONS = /INCL=($(SIMH_DIR),$(ATT3B2_DIR))/DEF=($(CC_DEFS))
|
||||
|
||||
# MITS Altair Simulator Definitions.
|
||||
|
|
3
makefile
3
makefile
|
@ -1920,7 +1920,8 @@ ATT3B2 = ${ATT3B2D}/3b2_cpu.c ${ATT3B2D}/3b2_mmu.c \
|
|||
${ATT3B2D}/3b2_id.c ${ATT3B2D}/3b2_dmac.c \
|
||||
${ATT3B2D}/3b2_sys.c ${ATT3B2D}/3b2_io.c \
|
||||
${ATT3B2D}/3b2_ports.c ${ATT3B2D}/3b2_ctc.c \
|
||||
${ATT3B2D}/3b2_ni.c ${ATT3B2D}/3b2_sysdev.c
|
||||
${ATT3B2D}/3b2_ni.c ${ATT3B2D}/3b2_mau.c \
|
||||
${ATT3B2D}/3b2_sysdev.c
|
||||
ATT3B2_OPT = -DUSE_INT64 -DUSE_ADDR64 -I ${ATT3B2D} ${NETWORK_OPT}
|
||||
#
|
||||
# Build everything (not the unsupported/incomplete or experimental simulators)
|
||||
|
|
Loading…
Add table
Reference in a new issue