2531 lines
122 KiB
C
2531 lines
122 KiB
C
/* hp2100_cpu5.c: HP 1000 EMA, VIS, and SIGNAL microcode simulator
|
|
|
|
Copyright (c) 2007-2008, Holger Veit
|
|
Copyright (c) 2006-2019, J. David Bryan
|
|
|
|
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 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 authors 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 authors.
|
|
|
|
CPU5 Extended Memory Array, Vector Instruction Set, and SIGNAL/1000
|
|
instructions
|
|
|
|
23-Jan-19 JDB Moved fmt_ab from hp2100_cpu1.c
|
|
02-Aug-18 JDB Moved VMA dispatcher to hp2100_cpu7.c
|
|
Moved VIS dispatcher from hp2100_cpu7.c
|
|
30-Jul-18 JDB Renamed "dms_[rw]map" to "meu_read_map", "meu_write_map"
|
|
07-Sep-17 JDB Replaced "uint16" casts with "HP_WORD" for A/B assignments
|
|
15-Jul-17 JDB Replaced "vma_resolve" with "resolve"
|
|
26-Jun-17 JDB Replaced SEXT with SEXT16
|
|
06-Jun-17 HV Fixed bug in cpu_vma_lbp "last suit + 1" handler
|
|
31-Jan-17 JDB Revised to use tprintf and TRACE_OPND for debugging
|
|
26-Jan-17 JDB Removed debug parameters from ema_* routines
|
|
24-Jan-17 JDB Replaced ReadIO, WriteIO with ReadS/U, WriteS/U
|
|
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
|
|
24-Dec-14 JDB Added casts for explicit downward conversions
|
|
17-Dec-12 JDB Fixed cpu_vma_mapte to return FALSE if not a VMA program
|
|
09-May-12 JDB Separated assignments from conditional expressions
|
|
23-Mar-12 JDB Added sign extension for dim count in "ema_resolve"
|
|
28-Dec-11 JDB Eliminated unused variable in "vis_vset"
|
|
11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h
|
|
05-Sep-08 JDB Removed option-present tests (now in UIG dispatchers)
|
|
30-Jul-08 JDB Redefined ABORT to pass address, moved def to hp2100_cpu.h
|
|
26-Jun-08 JDB Rewrote device I/O to model backplane signals
|
|
01-May-08 HV Fixed mapping bug in "ema_emap"
|
|
21-Apr-08 JDB Added EMA support from Holger
|
|
25-Nov-07 JDB Added TF fix from Holger
|
|
07-Nov-07 HV VMACK diagnostic tests 1...32 passed
|
|
19-Oct-07 JDB Corrected $LOC operand profile to OP_CCCACC
|
|
03-Oct-07 HV Moved RTE-6/VM instrs from hp2100_cpu0.c
|
|
26-Sep-06 JDB Created
|
|
|
|
Primary references:
|
|
- HP 1000 M/E/F-Series Computers Technical Reference Handbook
|
|
(5955-0282, March 1980)
|
|
- HP 1000 M/E/F-Series Computers Engineering and Reference Documentation
|
|
(92851-90001, March 1981)
|
|
- Macro/1000 Reference Manual
|
|
(92059-90001, December 1992)
|
|
|
|
|
|
The RTE-IV and RTE-IVB Extended Memory Array instructions and the RTE-6/VM
|
|
Virtual Memory Area instructions were added to accelerate the logical-to-
|
|
physical address translations and array subscript calculations of programs
|
|
running under the RTE-IV (HP product number 92067A), RTE-IVB (92068A), and
|
|
RTE-6/VM (92084A) operating systems. Microcode was available for the E- and
|
|
F-Series; the M-Series used software equivalents.
|
|
|
|
Both EMA and VMA opcodes reside in the range 105240-105257, so only one or
|
|
the other could be installed in a given system. This did not present a
|
|
difficulty, as VMA was a superset of EMA. The EMA encodings are:
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 0 1 0 | 1 0 0 | 0 0 0 | .EMIO
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| buffer size address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| array table address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| last subscript address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
: ... :
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| first subscript address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
: return location if error : P+n
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
: return location if buffer is mapped : P+n+1
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
|
|
The .EMIO instruction maps a buffer of the indicated size and starting at the
|
|
indicated array location into memory. It ensures that the buffer is entirely
|
|
within the logical address space in preparation for an I/O operation.
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 0 1 0 | 1 0 0 | 0 0 1 | MMAP
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| relative page count from EMA start to segment start address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| page count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
The MMAP instruction maps a sequence of physical memory pages into the
|
|
mapping segment area of a program's logical address space. The A-register
|
|
value on return indicates the success or failure of the request.
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 0 1 0 | 1 0 0 | 0 1 0 | emtst
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
The emtst instruction is used to determine if the EMA firmware has been
|
|
installed. If it is executed in single-step mode, it sets S to 102077 (HLT
|
|
77B). It executes as NOP from a running program.
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 0 1 0 | 1 0 1 | 1 1 1 | .EMAP
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| array address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| array table address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| last subscript address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
: ... :
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| first subscript address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
: return location if error : P+n
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
: return location if page is mapped : P+n+1
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
|
|
The .EMAP instruction resolves an array access into the memory address of the
|
|
referenced element. If the array is in EMA, it also maps the element into
|
|
the mapping segment.
|
|
|
|
|
|
|
|
The Vector Instruction Set (VIS) provides instructions that operate on
|
|
one-dimensional arrays of floating-point values. Both single- and
|
|
double-precision operations are supported. VIS uses the F-Series
|
|
floating-point processor to handle the floating-point math, so the firmware
|
|
is supported only on that machine.
|
|
|
|
Instructions use IR bit 11 to select single- or double-precision format. The
|
|
double-precision instruction names begin with "D" (e.g., DVADD vs. VADD).
|
|
Most VIS instructions are two words in length, with a sub-opcode immediately
|
|
following the primary opcode.
|
|
|
|
The two-word instructions are interruptible. the firmware sets bit 15 of the
|
|
second word to 1 to indicate that the instruction has been interrupted. This
|
|
allows the instruction to resume at the correct point in the vector
|
|
operation. Bit 15 is set to 0 before exiting for instruction completion.
|
|
|
|
The .ESEG instruction behaves slightly differently when invoked with the
|
|
105475 opcode. The microcode source calls it a .VPRG instruction, but the
|
|
only difference is that it sets the MSEG start and size to 0 and 32,
|
|
respectively, instead of obtaining them from the ID extension. In all other
|
|
respects, the instructions are identical.
|
|
|
|
The .ERES, .VSET, and test instructions do not test bit 11, so they will be
|
|
invoked with either the 101xxx or 105xxx forms. The 101xxx forms are
|
|
canonical for the first two, while the 105xxx form is canonical for the
|
|
self-test instruction.
|
|
|
|
The VIS encodings are:
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 0 0 0 | (D)VADD
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | 0 0 0 | P | 0 0 | 0 0 0 | 0 0 0 | 0 | P | 0 |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 3 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 3 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 0 0 0 | (D)VSUB
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | 0 0 0 | P | 0 0 | 0 0 0 | 0 1 0 | 0 | P | 0 |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 3 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 3 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 0 0 0 | (D)VMPY
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | 0 0 0 | P | 0 0 | 0 0 0 | 1 0 0 | 0 | P | 0 |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 3 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 3 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 0 0 0 | (D)VDIV
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | 0 0 0 | P | 0 0 | 0 0 0 | 1 1 0 | 0 | P | 0 |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 3 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 3 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 0 0 0 | (D)VSAD
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | 0 0 0 | P | 0 0 | 1 0 0 | 0 0 0 | 0 | P | 0 |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| scalar address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 0 0 0 | (D)VSSB
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | 0 0 0 | P | 0 0 | 1 0 0 | 0 1 0 | 0 | P | 0 |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| scalar address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 0 0 0 | (D)VSMY
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | 0 0 0 | P | 0 0 | 1 0 0 | 1 0 0 | 0 | P | 0 |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| scalar address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 0 0 0 | (D)VSDV
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | 0 0 0 | P | 0 0 | 1 0 0 | 1 1 0 | 0 | P | 0 |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| scalar address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 0 0 1 | (D)VPIV
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | - - - - - - - - - - - - - - - |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| scalar address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 3 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 3 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 0 1 0 | (D)VABS
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | - - - - - - - - - - - - - - - |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 0 1 1 | (D)VSUM
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | - - - - - - - - - - - - - - - |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| scalar address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 1 0 0 | (D)VNRM
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | - - - - - - - - - - - - - - - |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| scalar address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 1 0 1 | (D)VDOT
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | - - - - - - - - - - - - - - - |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| scalar address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 1 1 0 | (D)VMAX
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | - - - - - - - - - - - - - - - |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| result address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 0 | 1 1 1 | (D)VMAB
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | - - - - - - - - - - - - - - - |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| result address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 1 | 0 0 0 | (D)VMIN
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | - - - - - - - - - - - - - - - |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| result address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 1 | 0 0 1 | (D)VMIB
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | - - - - - - - - - - - - - - - |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| result address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 1 | 0 1 0 | (D)VMOV
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | - - - - - - - - - - - - - - - |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | P | 0 1 | 1 0 0 | 1 1 1 | 0 1 1 | (D)VSWP
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 0 | - - - - - - - - - - - - - - - |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| increment 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| element count address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 0 0 1 | 1 0 0 | 1 1 1 | 1 0 0 | .ERES
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| array address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| array table address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| last subscript address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
: ... :
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| first subscript address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
: return location if error : P+n
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
: return location if page is mapped : P+n+1
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 0 0 1 | 1 0 0 | 1 1 1 | 1 0 1 | .ESEG
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| array table address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
: return location if error : P+3
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
: return location if page is mapped : P+4
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 0 0 1 | 1 0 0 | 1 1 1 | 1 1 0 | .VSET
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| input vector address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| output vector address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| map table address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| scalar count |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector count |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| elements per page count |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
: return location if error : P+8
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
: return location if setup is hard : P+9
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
: return location if setup is easy : P+10
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 0 0 | 1 1 1 | 1 1 1 | test
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
: return location if the firmware is not installed : P+1
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
: return location if the firmware is installed : P+2
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
|
|
The test instruction is used to determine if the VIS firmware has been
|
|
installed. It sets X to the firmware revision code, S to 102077 (HLT 77B)
|
|
and skips the next instruction if the microcode is present.
|
|
|
|
|
|
|
|
The SIGNAL/1000 instructions provide fast Fourier transforms and complex
|
|
arithmetic. They utilize the F-Series floating-point processor and the
|
|
Vector Instruction Set, so the firmware is supported only on the F-Series
|
|
CPU.
|
|
|
|
The SIGNAL encodings are:
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 0 | 0 0 0 | BITRV
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| array base address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| index bitmap address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| count of index bits address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 0 | 0 0 1 | BTRFY
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| complex vector address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| real part address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| imaginary part address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| node address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| maximum length address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 0 | 0 1 0 | UNSCR
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| real part address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| imaginary part address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| index 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| index 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 0 | 0 1 1 | PRSCR
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| vector address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| real part address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| imaginary part address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| index 1 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| index 2 address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 0 | 1 0 0 | BITR1
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| real array base address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| imaginary array base address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| index bitmap address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| count of index bits address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 0 | 1 0 1 | BTRF1
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| real vector part address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| imaginary vector part address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| real part address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| imaginary part address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| node address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| maximum length address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 0 | 1 1 0 | .CADD
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| result address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| augend address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| addend address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 0 | 1 1 1 | .CSUB
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| result address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| minuend address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| subtrahend address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 1 | 0 0 0 | .CMPY
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| result address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| multiplicand address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| multiplier address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 1 | 0 0 1 | .CDIV
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| result address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| dividend address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| divisor address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 1 | 0 1 0 | CONJG
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| result address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| argument address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 1 | 0 1 1 | ..CCM
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| argument address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 1 | 1 0 0 | AIMAG
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| operand address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 1 | 1 0 1 | CMPLX
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| return address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| result address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| real part address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| imaginary part address |
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
|
|
|
|
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
| 1 | 0 0 0 | 1 0 1 | 1 1 0 | 0 0 1 | 1 1 1 | test
|
|
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
|
: return location if the firmware is not installed : P+1
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
: return location if the firmware is installed : P+2
|
|
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
|
|
|
The test instruction is used to determine if the SIGNAL firmware has been
|
|
installed. It sets X to the firmware revision code, S to 102077 (HLT 77B)
|
|
and skips the next instruction if the microcode is present.
|
|
|
|
|
|
Implementation notes:
|
|
|
|
1. As the VIS and SIGNAL firmware uses the F-Series Floating-Point
|
|
Processor, and the FPP simulator requires 64-bit integer support, VIS and
|
|
SIGNAL also require 64-bit support.
|
|
*/
|
|
|
|
|
|
|
|
#include "hp2100_defs.h"
|
|
#include "hp2100_cpu.h"
|
|
#include "hp2100_cpu_dmm.h"
|
|
#include "hp2100_cpu_fp.h"
|
|
|
|
|
|
|
|
/* Paging constants */
|
|
|
|
#define MSEG_MASK 0076000u
|
|
|
|
|
|
/* RTE base page addresses */
|
|
|
|
static const HP_WORD idx = 0001645u;
|
|
static const HP_WORD xeqt = 0001717u;
|
|
static const HP_WORD umaps = 0003740u;
|
|
|
|
|
|
/* VIS operand accessors */
|
|
|
|
#define GET_MSIGN(op) ((op)->fpk [0] & D16_SIGN)
|
|
|
|
|
|
/* SIGNAL operand address accessors */
|
|
|
|
#define RE(x) (x + 0)
|
|
#define IM(x) (x + 2)
|
|
|
|
|
|
/* EMA utility structure declarations */
|
|
|
|
typedef struct ema4 {
|
|
uint32 mseg; /* logical start of MSEG */
|
|
uint32 msegsz; /* size of std mseg in pgs */
|
|
uint32 pgoff; /* pg # in EMA containing element */
|
|
uint32 offs; /* offset into page of element */
|
|
uint32 msoff; /* total offset to element in MSEG */
|
|
uint32 emasz; /* size of ema in pgs */
|
|
uint32 msegno; /* # of std mseg */
|
|
uint32 ipgs; /* # of pgs to start of MSEG */
|
|
uint32 npgs; /* # of pgs needed */
|
|
uint32 spmseg; /* first phys pg of MSEG */
|
|
} EMA4;
|
|
|
|
|
|
/* EMA local utility routine declarations */
|
|
|
|
static t_stat ema_emap (uint32* rtn, uint32 abase, uint32 dtbl, uint32 atbl);
|
|
static t_stat ema_emio (uint32* rtn, uint32 bufl, uint32 dtbl, uint32 atbl);
|
|
static t_stat ema_mmap (uint32 ipage, uint32 npgs);
|
|
|
|
static t_bool ema_resolve (uint32 dtbl, uint32 atbl, uint32* sum);
|
|
static t_bool ema_emas (uint32 dtbl, uint32 atbl, EMA4* e);
|
|
static t_bool ema_emat (EMA4* e);
|
|
static t_bool ema_mmap01 (EMA4* e);
|
|
static t_bool ema_mmap02 (EMA4* e);
|
|
|
|
static const char *fmt_ab (t_bool success);
|
|
|
|
|
|
#if defined (HAVE_INT64) /* int64 support available */
|
|
|
|
/* VIS local utility routine declarations */
|
|
|
|
static void vis_svop (uint32 subcode, OPS op, OPSIZE opsize);
|
|
static void vis_vvop (uint32 subcode, OPS op, OPSIZE opsize);
|
|
static void vis_abs (OP* in, OPSIZE opsize);
|
|
static void vis_minmax (OPS op, OPSIZE opsize, t_bool domax, t_bool doabs);
|
|
static void vis_vpiv (OPS op, OPSIZE opsize);
|
|
static void vis_vabs (OPS op, OPSIZE opsize);
|
|
static void vis_trunc (OP* out, OP in);
|
|
static void vis_vsmnm (OPS op, OPSIZE opsize, t_bool doabs);
|
|
static void vis_vdot (OPS op, OPSIZE opsize);
|
|
static void vis_movswp (OPS op, OPSIZE opsize, t_bool doswp);
|
|
|
|
static t_stat vis_eres (HP_WORD *rtn, uint32 dtbl, uint32 atbl);
|
|
static t_stat vis_eseg (HP_WORD *rtn, uint32 tbl);
|
|
static t_stat vis_vset (HP_WORD *rtn, OPS op);
|
|
|
|
|
|
/* SIGNAL local utility routine declarations */
|
|
|
|
static void sig_caddsub (uint16 addsub, OPS op);
|
|
static void sig_btrfy (uint32 re, uint32 im, OP wr, OP wi, uint32 k, uint32 n2);
|
|
static void sig_bitrev (uint32 re, uint32 im, uint32 idx, uint32 log2n, int sz);
|
|
static OP sig_scadd (uint16 oper, t_bool addh, OP a, OP b);
|
|
static void sig_cmul (OP *r, OP *i, OP a, OP b, OP c, OP d);
|
|
|
|
#endif /* int64 conditional */
|
|
|
|
|
|
|
|
/* Global instruction executors */
|
|
|
|
|
|
/* RTE-IV Extended Memory Array instructions.
|
|
|
|
The RTE-IV operating system (HP product number 92067A) introduced the
|
|
Extended Memory Area (EMA) instructions. EMA provided a mappable data area
|
|
up to one megaword in size. These three instructions accelerated data
|
|
accesses to variables stored in EMA partitions. Support was limited to
|
|
E/F-Series machines; M-Series machines used software equivalents.
|
|
|
|
Option implementation by CPU was as follows:
|
|
|
|
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
|
------ ------ ------ ------ ------ ------ ------
|
|
N/A N/A N/A N/A N/A 92067A 92067A
|
|
|
|
The routines are mapped to instruction codes as follows:
|
|
|
|
Instr. 1000-E/F Description
|
|
------ -------- ----------------------------------------------
|
|
.EMIO 105240 EMA I/O
|
|
MMAP 105241 Map physical to logical memory
|
|
emtst 105242 [self test]
|
|
.EMAP 105257 Resolve array element address
|
|
|
|
Additional references:
|
|
- RTE-IVB Programmer's Reference Manual (92068-90004, December 1983).
|
|
- RTE-IVB Technical Specifications (92068-90013, January 1980).
|
|
|
|
|
|
Implemenation notes:
|
|
|
|
1. RTE-IV EMA and RTE-6 VMA instructions share the same address space, so a
|
|
given machine can run one or the other, but not both.
|
|
|
|
2. The EMA diagnostic (92067-16013) reports bogus MMAP failures if it is
|
|
not loaded at the start of its partition (e.g., because of a LOADR "LO"
|
|
command). The "ICMPS" map comparison check in the diagnostic assumes
|
|
that the starting page of the program's partition contains the first
|
|
instruction of the program and prints "MMAP ERROR" if it does not.
|
|
*/
|
|
|
|
static const OP_PAT op_ema[16] = {
|
|
OP_AKA, OP_AKK, OP_N, OP_N, /* .EMIO MMAP [test] --- */
|
|
OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */
|
|
OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */
|
|
OP_N, OP_N, OP_N, OP_AAA /* --- --- --- .EMAP */
|
|
};
|
|
|
|
t_stat cpu_rte_ema (void)
|
|
{
|
|
t_stat reason = SCPE_OK;
|
|
OPS op;
|
|
OP_PAT pattern;
|
|
uint32 entry, rtn;
|
|
|
|
entry = IR & 017; /* mask to entry point */
|
|
pattern = op_ema[entry]; /* get operand pattern */
|
|
|
|
if (pattern != OP_N) {
|
|
reason = cpu_ops (pattern, op); /* get instruction operands */
|
|
if (reason != SCPE_OK) /* evaluation failed? */
|
|
return reason; /* return reason for failure */
|
|
}
|
|
|
|
switch (entry) { /* decode IR<3:0> */
|
|
case 000: /* .EMIO 105240 (OP_A) */
|
|
rtn = op[0].word;
|
|
reason = ema_emio(&rtn, op[1].word,
|
|
op[2].word, PR); /* handle the EMIO instruction */
|
|
PR = rtn;
|
|
|
|
tprintf (cpu_dev, TRACE_OPND, OPND_FORMAT " return location is P+%u (%s)\n",
|
|
PR, IR, PR - err_PR, fmt_ab (PR - op[0].word));
|
|
break;
|
|
|
|
case 001: /* .MMAP 105241 (OP_AKK) */
|
|
reason = ema_mmap(op[1].word, op[2].word); /* handle the MMAP instruction */
|
|
break;
|
|
|
|
case 002: /* emtst 105242 (OP_N) */
|
|
/* effectively, this code just returns without error:
|
|
* real microcode will set S register to 102077B when in single step mode */
|
|
if (sim_step == 1)
|
|
SR = 0102077;
|
|
break;
|
|
|
|
case 017: /* .EMAP 105247 (OP_A) */
|
|
rtn = op[0].word; /* error return */
|
|
reason = ema_emap(&rtn, op[1].word,
|
|
op[2].word, PR); /* handle the EMAP instruction */
|
|
PR = rtn;
|
|
|
|
tprintf (cpu_dev, TRACE_OPND, OPND_FORMAT " return location is P+%u (%s)\n",
|
|
PR, IR, PR - err_PR, fmt_ab (PR - op[0].word));
|
|
break;
|
|
|
|
default: /* others unimplemented */
|
|
reason = STOP (cpu_ss_unimpl);
|
|
}
|
|
|
|
return reason;
|
|
}
|
|
|
|
|
|
#if defined (HAVE_INT64) /* int64 support available */
|
|
|
|
/* Vector Instruction Set.
|
|
|
|
The VIS provides instructions that operate on one-dimensional arrays of
|
|
floating-point values. Both single- and double-precision operations are
|
|
supported. VIS uses the F-Series floating-point processor to handle the
|
|
floating-point math.
|
|
|
|
Option implementation by CPU was as follows:
|
|
|
|
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
|
------ ------ ------ ------ ------ ------ ------
|
|
N/A N/A N/A N/A N/A N/A 12824A
|
|
|
|
The routines are mapped to instruction codes as follows:
|
|
|
|
Single-Precision Double-Precision
|
|
Instr. Opcode Subcod Instr. Opcode Subcod Description
|
|
------ ------ ------ ------ ------ ------ -----------------------------
|
|
VADD 101460 000000 DVADD 105460 004002 Vector add
|
|
VSUB 101460 000020 DVSUB 105460 004022 Vector subtract
|
|
VMPY 101460 000040 DVMPY 105460 004042 Vector multiply
|
|
VDIV 101460 000060 DVDIV 105460 004062 Vector divide
|
|
VSAD 101460 000400 DVSAD 105460 004402 Scalar-vector add
|
|
VSSB 101460 000420 DVSSB 105460 004422 Scalar-vector subtract
|
|
VSMY 101460 000440 DVSMY 105460 004442 Scalar-vector multiply
|
|
VSDV 101460 000460 DVSDV 105460 004462 Scalar-vector divide
|
|
VPIV 101461 0xxxxx DVPIV 105461 0xxxxx Vector pivot
|
|
VABS 101462 0xxxxx DVABS 105462 0xxxxx Vector absolute value
|
|
VSUM 101463 0xxxxx DVSUM 105463 0xxxxx Vector sum
|
|
VNRM 101464 0xxxxx DVNRM 105464 0xxxxx Vector norm
|
|
VDOT 101465 0xxxxx DVDOT 105465 0xxxxx Vector dot product
|
|
VMAX 101466 0xxxxx DVMAX 105466 0xxxxx Vector maximum value
|
|
VMAB 101467 0xxxxx DVMAB 105467 0xxxxx Vector maximum absolute value
|
|
VMIN 101470 0xxxxx DVMIN 105470 0xxxxx Vector minimum value
|
|
VMIB 101471 0xxxxx DVMIB 105471 0xxxxx Vector minimum absolute value
|
|
VMOV 101472 0xxxxx DVMOV 105472 0xxxxx Vector move
|
|
VSWP 101473 0xxxxx DVSWP 105473 0xxxxx Vector swap
|
|
.ERES 101474 -- -- -- -- Resolve array element address
|
|
.ESEG 101475 -- .VPRG 105475 -- Load MSEG maps
|
|
.VSET 101476 -- -- -- -- Vector setup
|
|
-- -- -- [test] 105477 -- [self test]
|
|
|
|
Instructions use IR bit 11 to select single- or double-precision format. The
|
|
double-precision instruction names begin with "D" (e.g., DVADD vs. VADD).
|
|
Most VIS instructions are two words in length, with a sub-opcode immediately
|
|
following the primary opcode.
|
|
|
|
Additional references:
|
|
- 12824A Vector Instruction Set User's Manual (12824-90001, June 1979).
|
|
- VIS Microcode Source (12824-18059, revision 3).
|
|
|
|
|
|
Implementation notes:
|
|
|
|
1. The .VECT (101460) and .DVCT (105460) opcodes preface a single- or
|
|
double-precision arithmetic operation that is determined by the
|
|
sub-opcode value. The remainder of the dual-precision sub-opcode values
|
|
are "don't care," except for requiring a zero in bit 15.
|
|
|
|
2. The VIS uses the hardware FPP of the F-Series. FPP malfunctions are
|
|
detected by the VIS firmware and are indicated by a memory-protect
|
|
violation and setting the overflow flag. Under simulation,
|
|
malfunctions cannot occur.
|
|
*/
|
|
|
|
static const OP_PAT op_vis [16] = {
|
|
OP_N, OP_AAKAKAKK, OP_AKAKK, OP_AAKK, /* .VECT VPIV VABS VSUM */
|
|
OP_AAKK, OP_AAKAKK, OP_AAKK, OP_AAKK, /* VNRM VDOT VMAX VMAB */
|
|
OP_AAKK, OP_AAKK, OP_AKAKK, OP_AKAKK, /* VMIN VMIB VMOV VSWP */
|
|
OP_AA, OP_A, OP_AAACCC, OP_N /* .ERES .ESEG .VSET [test] */
|
|
};
|
|
|
|
static const t_bool op_ftnret [16] = {
|
|
FALSE, TRUE, TRUE, TRUE,
|
|
TRUE, TRUE, TRUE, TRUE,
|
|
TRUE, TRUE, TRUE, TRUE,
|
|
FALSE, TRUE, TRUE, FALSE,
|
|
};
|
|
|
|
t_stat cpu_vis (void)
|
|
{
|
|
static const char * const difficulty [2] = { "hard", "easy" };
|
|
|
|
t_stat reason = SCPE_OK;
|
|
OPS op;
|
|
OP_PAT pattern;
|
|
OPSIZE opsize;
|
|
uint32 entry, subcode;
|
|
HP_WORD rtn = 0;
|
|
|
|
opsize = (IR & 004000) ? fp_t : fp_f; /* double or single precision */
|
|
entry = IR & 017; /* mask to entry point */
|
|
pattern = op_vis [entry];
|
|
|
|
if (entry == 0) { /* retrieve sub opcode */
|
|
subcode = ReadW (PR); /* get it */
|
|
|
|
if (subcode & 0100000) /* special property of ucode */
|
|
subcode = AR; /* for reentry */
|
|
|
|
PR = (PR + 1) & LA_MASK; /* bump to real argument list */
|
|
pattern = (subcode & 0400) ? OP_AAKAKK : OP_AKAKAKK; /* scalar or vector operation */
|
|
}
|
|
|
|
if (pattern != OP_N) {
|
|
if (op_ftnret [entry]) { /* most VIS instrs ignore RTN addr */
|
|
rtn = ReadW (PR); /* get it */
|
|
PR = (PR + 1) & LA_MASK; /* move to next argument */
|
|
}
|
|
|
|
reason = cpu_ops (pattern, op); /* get instruction operands */
|
|
|
|
if (reason != SCPE_OK) /* evaluation failed? */
|
|
return reason; /* return reason for failure */
|
|
}
|
|
|
|
switch (entry) { /* decode IR<3:0> */
|
|
|
|
case 000: /* .VECT (OP_special) */
|
|
if (subcode & 0400)
|
|
vis_svop(subcode,op,opsize); /* scalar/vector op */
|
|
else
|
|
vis_vvop(subcode,op,opsize); /* vector/vector op */
|
|
break;
|
|
|
|
case 001: /* VPIV (OP_(A)AAKAKAKK) */
|
|
vis_vpiv(op,opsize);
|
|
break;
|
|
|
|
case 002: /* VABS (OP_(A)AKAKK) */
|
|
vis_vabs(op,opsize);
|
|
break;
|
|
|
|
case 003: /* VSUM (OP_(A)AAKK) */
|
|
vis_vsmnm(op,opsize,FALSE);
|
|
break;
|
|
|
|
case 004: /* VNRM (OP_(A)AAKK) */
|
|
vis_vsmnm(op,opsize,TRUE);
|
|
break;
|
|
|
|
case 005: /* VDOT (OP_(A)AAKAKK) */
|
|
vis_vdot(op,opsize);
|
|
break;
|
|
|
|
case 006: /* VMAX (OP_(A)AAKK) */
|
|
vis_minmax(op,opsize,TRUE,FALSE);
|
|
break;
|
|
|
|
case 007: /* VMAB (OP_(A)AAKK) */
|
|
vis_minmax(op,opsize,TRUE,TRUE);
|
|
break;
|
|
|
|
case 010: /* VMIN (OP_(A)AAKK) */
|
|
vis_minmax(op,opsize,FALSE,FALSE);
|
|
break;
|
|
|
|
case 011: /* VMIB (OP_(A)AAKK) */
|
|
vis_minmax(op,opsize,FALSE,TRUE);
|
|
break;
|
|
|
|
case 012: /* VMOV (OP_(A)AKAKK) */
|
|
vis_movswp(op,opsize,FALSE);
|
|
break;
|
|
|
|
case 013: /* VSWP (OP_(A)AKAKK) */
|
|
vis_movswp(op,opsize,TRUE);
|
|
break;
|
|
|
|
case 014: /* .ERES (OP_(A)AA) */
|
|
PR = rtn;
|
|
reason = vis_eres(&PR,op[2].word,PR); /* handle the ERES instruction */
|
|
|
|
tprintf (cpu_dev, TRACE_OPND, OPND_FORMAT " return location is P+%u (%s)\n",
|
|
PR, IR, PR - err_PR, fmt_ab (PR - rtn));
|
|
break;
|
|
|
|
case 015: /* .ESEG (OP_(A)A) */
|
|
PR = rtn;
|
|
reason = vis_eseg(&PR, op[0].word); /* handle the ESEG instruction */
|
|
|
|
tprintf (cpu_dev, TRACE_OPND, OPND_FORMAT " return location is P+%u (%s)\n",
|
|
PR, IR, PR - err_PR, fmt_ab (PR - rtn));
|
|
break;
|
|
|
|
case 016: /* .VSET (OP_(A)AAACCC) */
|
|
PR = rtn;
|
|
reason = vis_vset(&PR,op);
|
|
|
|
tprintf (cpu_dev, TRACE_OPND, OPND_FORMAT " return location is P+%u (%s)\n",
|
|
PR, IR, PR - err_PR,
|
|
(PR == rtn
|
|
? fmt_ab (0)
|
|
: difficulty [PR - rtn - 1]));
|
|
break;
|
|
|
|
case 017: /* [test] (OP_N) */
|
|
XR = 3; /* firmware revision */
|
|
SR = 0102077; /* test passed code */
|
|
PR = (PR + 1) & LA_MASK; /* P+2 return for firmware w/VIS */
|
|
break;
|
|
|
|
default: /* others unimplemented */
|
|
reason = STOP (cpu_ss_unimpl);
|
|
}
|
|
|
|
return reason;
|
|
}
|
|
|
|
|
|
/* SIGNAL/1000 Instructions
|
|
|
|
The SIGNAL/1000 instructions provide fast Fourier transforms and complex
|
|
arithmetic. They utilize the F-Series floating-point processor and the
|
|
Vector Instruction Set.
|
|
|
|
Option implementation by CPU was as follows:
|
|
|
|
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
|
------ ------ ------ ------ ------ ------ ------
|
|
N/A N/A N/A N/A N/A N/A 92835A
|
|
|
|
The routines are mapped to instruction codes as follows:
|
|
|
|
Instr. 1000-F Description
|
|
------ ------ ----------------------------------------------
|
|
BITRV 105600 Bit reversal
|
|
BTRFY 105601 Butterfly algorithm
|
|
UNSCR 105602 Unscramble for phasor MPY
|
|
PRSCR 105603 Unscramble for phasor MPY
|
|
BITR1 105604 Swap two elements in array (alternate format)
|
|
BTRF1 105605 Butterfly algorithm (alternate format)
|
|
.CADD 105606 Complex number addition
|
|
.CSUB 105607 Complex number subtraction
|
|
.CMPY 105610 Complex number multiplication
|
|
.CDIV 105611 Complex number division
|
|
CONJG 105612 Complex conjugate
|
|
..CCM 105613 Complex complement
|
|
AIMAG 105614 Return imaginary part
|
|
CMPLX 105615 Form complex number
|
|
[nop] 105616 [no operation]
|
|
[test] 105617 [self test]
|
|
|
|
Notes:
|
|
|
|
1. SIGNAL/1000 ROM data are available from Bitsavers.
|
|
|
|
Additional references (documents unavailable):
|
|
- HP Signal/1000 User Reference and Installation Manual (92835-90002).
|
|
- SIGNAL/1000 Microcode Source (92835-18075, revision 2).
|
|
*/
|
|
|
|
static const OP_PAT op_signal [16] = {
|
|
OP_AAKK, OP_AAFFKK, OP_AAFFKK, OP_AAFFKK, /* BITRV BTRFY UNSCR PRSCR */
|
|
OP_AAAKK, OP_AAAFFKK, OP_AAA, OP_AAA, /* BITR1 BTRF1 .CADD .CSUB */
|
|
OP_AAA, OP_AAA, OP_AAA, OP_A, /* .CMPY .CDIV CONJG ..CCM */
|
|
OP_AA, OP_AAFF, OP_N, OP_N /* AIMAG CMPLX --- [test]*/
|
|
};
|
|
|
|
t_stat cpu_signal (void)
|
|
{
|
|
t_stat reason = SCPE_OK;
|
|
OPS op;
|
|
OP a,b,c,d,p1,p2,p3,p4,m1,m2,wr,wi;
|
|
uint32 entry, v, idx1, idx2;
|
|
int32 exc, exd;
|
|
|
|
entry = IR & 017; /* mask to entry point */
|
|
|
|
if (op_signal [entry] != OP_N) {
|
|
reason = cpu_ops (op_signal [entry], op); /* get instruction operands */
|
|
if (reason != SCPE_OK) /* evaluation failed? */
|
|
return reason; /* return reason for failure */
|
|
}
|
|
|
|
switch (entry) { /* decode IR<3:0> */
|
|
case 000: /* BITRV (OP_AAKK) */
|
|
/* BITRV
|
|
* bit reversal for FFT
|
|
* JSB BITRV
|
|
* DEF ret(,I) return address
|
|
* DEF vect,I base address of array
|
|
* DEF idx,I index bitmap to be reversed (one-based)
|
|
* DEF nbits,I number of bits of index
|
|
*
|
|
* Given a complex*8 vector of nbits (power of 2), this calculates:
|
|
* swap( vect[idx], vect[rev(idx)]) where rev(i) is the bitreversed value of i */
|
|
sig_bitrev(op[1].word, op[1].word+2, op[2].word-1, op[3].word, 4);
|
|
PR = op[0].word & LA_MASK;
|
|
break;
|
|
|
|
case 001: /* BTRFY (OP_AAFFKK) */
|
|
/* BTRFY - butterfly operation
|
|
* JSB BTRFY
|
|
* DEF ret(,I) return address
|
|
* DEF vect(,I) complex*8 vector
|
|
* DEF wr,I real part of W
|
|
* DEF wi,I imag part of W
|
|
* DEF node,I index of 1st op (1 based)
|
|
* DEF lmax,I offset to 2nd op (0 based) */
|
|
sig_btrfy(op[1].word, op[1].word+2,
|
|
op[2], op[3],
|
|
2*(op[4].word-1), 2*op[5].word);
|
|
PR = op[0].word & LA_MASK;
|
|
break;
|
|
|
|
case 002: /* UNSCR (OP_AAFFKK) */
|
|
/* UNSCR unscramble for phasor MPY
|
|
* JSB UNSCR
|
|
* DEF ret(,I)
|
|
* DEF vector,I
|
|
* DEF WR
|
|
* DEF WI
|
|
* DEF idx1,I
|
|
* DEF idx2,I */
|
|
v = op[1].word;
|
|
idx1 = 2 * (op[4].word - 1);
|
|
idx2 = 2 * (op[5].word - 1);
|
|
wr = op[2]; /* read WR */
|
|
wi = op[3]; /* read WI */
|
|
p1 = ReadOp(RE(v + idx1), fp_f); /* S1 VR[idx1] */
|
|
p2 = ReadOp(RE(v + idx2), fp_f); /* S2 VR[idx2] */
|
|
p3 = ReadOp(IM(v + idx1), fp_f); /* S9 VI[idx1] */
|
|
p4 = ReadOp(IM(v + idx2), fp_f); /* S10 VI[idx2] */
|
|
c = sig_scadd(000, TRUE, p3, p4); /* S5,6 0.5*(p3+p4) */
|
|
d = sig_scadd(020, TRUE, p2, p1); /* S7,8 0.5*(p2-p1) */
|
|
sig_cmul(&m1, &m2, wr, wi, c, d); /* (WR,WI) * (c,d) */
|
|
c = sig_scadd(000, TRUE, p1, p2); /* 0.5*(p1+p2) */
|
|
d = sig_scadd(020, TRUE, p3, p4); /* 0.5*(p3-p4) */
|
|
(void)fp_exec(000, &p1, c, m1); /* VR[idx1] := 0.5*(p1+p2) + real(W*(c,d)) */
|
|
WriteOp(RE(v + idx1), p1, fp_f);
|
|
(void)fp_exec(000, &p2, d, m2); /* VI[idx1] := 0.5*(p3-p4) + imag(W*(c,d)) */
|
|
WriteOp(IM(v + idx1), p2, fp_f);
|
|
(void)fp_exec(020, &p1, c, m1); /* VR[idx2] := 0.5*(p1+p2) - imag(W*(c,d)) */
|
|
WriteOp(RE(v + idx2), p1, fp_f);
|
|
(void)fp_exec(020, &p2, d, m2); /* VI[idx2] := 0.5*(p3-p4) - imag(W*(c,d)) */
|
|
WriteOp(IM(v + idx2), p2, fp_f);
|
|
PR = op[0].word & LA_MASK;
|
|
break;
|
|
|
|
case 003: /* PRSCR (OP_AAFFKK) */
|
|
/* PRSCR unscramble for phasor MPY
|
|
* JSB PRSCR
|
|
* DEF ret(,I)
|
|
* DEF vector,I
|
|
* DEF WR
|
|
* DEF WI
|
|
* DEF idx1,I
|
|
* DEF idx2,I */
|
|
v = op[1].word;
|
|
idx1 = 2 * (op[4].word - 1);
|
|
idx2 = 2 * (op[5].word - 1);
|
|
wr = op[2]; /* read WR */
|
|
wi = op[3]; /* read WI */
|
|
p1 = ReadOp(RE(v + idx1), fp_f); /* VR[idx1] */
|
|
p2 = ReadOp(RE(v + idx2), fp_f); /* VR[idx2] */
|
|
p3 = ReadOp(IM(v + idx1), fp_f); /* VI[idx1] */
|
|
p4 = ReadOp(IM(v + idx2), fp_f); /* VI[idx2] */
|
|
c = sig_scadd(020, FALSE, p1, p2); /* p1-p2 */
|
|
d = sig_scadd(000, FALSE, p3, p4); /* p3+p4 */
|
|
sig_cmul(&m1,&m2, wr, wi, c, d); /* (WR,WI) * (c,d) */
|
|
c = sig_scadd(000, FALSE, p1, p2); /* p1+p2 */
|
|
d = sig_scadd(020, FALSE, p3,p4); /* p3-p4 */
|
|
(void)fp_exec(020, &p1, c, m2); /* VR[idx1] := (p1-p2) - imag(W*(c,d)) */
|
|
WriteOp(RE(v + idx1), p1, fp_f);
|
|
(void)fp_exec(000, &p2, d, m1); /* VI[idx1] := (p3-p4) + real(W*(c,d)) */
|
|
WriteOp(IM(v + idx1), p2, fp_f);
|
|
(void)fp_exec(000, &p1, c, m2); /* VR[idx2] := (p1+p2) + imag(W*(c,d)) */
|
|
WriteOp(RE(v + idx2), p1, fp_f);
|
|
(void)fp_exec(020, &p2, m1, d); /* VI[idx2] := imag(W*(c,d)) - (p3-p4) */
|
|
WriteOp(IM(v + idx2), p2, fp_f);
|
|
PR = op[0].word & LA_MASK;
|
|
break;
|
|
|
|
case 004: /* BITR1 (OP_AAAKK) */
|
|
/* BITR1
|
|
* bit reversal for FFT, alternative version
|
|
* JSB BITR1
|
|
* DEF ret(,I) return address if already swapped
|
|
* DEF revect,I base address of real vect
|
|
* DEF imvect,I base address of imag vect
|
|
* DEF idx,I index bitmap to be reversed (one-based)
|
|
* DEF nbits,I number of bits of index
|
|
*
|
|
* Given a complex*8 vector of nbits (power of 2), this calculates:
|
|
* swap( vect[idx], vect[rev(idx)]) where rev(i) is the bitreversed value of i
|
|
*
|
|
* difference to BITRV is that BITRV uses complex*8, and BITR1 uses separate real*4
|
|
* vectors for Real and Imag parts */
|
|
sig_bitrev(op[1].word, op[2].word, op[3].word-1, op[4].word, 2);
|
|
PR = op[0].word & LA_MASK;
|
|
break;
|
|
|
|
|
|
case 005: /* BTRF1 (OP_AAAFFKK) */
|
|
/* BTRF1 - butterfly operation with real*4 vectors
|
|
* JSB BTRF1
|
|
* DEF ret(,I) return address
|
|
* DEF rvect,I real part of vector
|
|
* DEF ivect,I imag part of vector
|
|
* DEF wr,I real part of W
|
|
* DEF wi,I imag part of W
|
|
* DEF node,I index (1 based)
|
|
* DEF lmax,I index (0 based) */
|
|
sig_btrfy(op[1].word, op[2].word,
|
|
op[3], op[4],
|
|
op[5].word-1, op[6].word);
|
|
PR = op[0].word & LA_MASK;
|
|
break;
|
|
|
|
case 006: /* .CADD (OP_AAA) */
|
|
/* .CADD Complex addition
|
|
* JSB .CADD
|
|
* DEF result,I
|
|
* DEF oprd1,I
|
|
* DEF oprd2,I
|
|
* complex addition is: (a+bi) + (c+di) => (a+c) + (b+d)i */
|
|
sig_caddsub(000,op);
|
|
break;
|
|
|
|
case 007: /* .CSUB (OP_AAA) */
|
|
/* .CSUB Complex subtraction
|
|
* JSB .CSUB
|
|
* DEF result,I
|
|
* DEF oprd1,I
|
|
* DEF oprd2,I
|
|
* complex subtraction is: (a+bi) - (c+di) => (a - c) + (b - d)i */
|
|
sig_caddsub(020,op);
|
|
break;
|
|
|
|
case 010: /* .CMUL (OP_AAA) */
|
|
/* .CMPY Complex multiplication
|
|
* call:
|
|
* JSB .CMPY
|
|
* DEF result,I
|
|
* DEF oprd1,I
|
|
* DEF oprd2,I
|
|
* complex multiply is: (a+bi)*(c+di) => (ac-bd) + (ad+bc)i */
|
|
a = ReadOp(RE(op[1].word), fp_f); /* read 1st op */
|
|
b = ReadOp(IM(op[1].word), fp_f);
|
|
c = ReadOp(RE(op[2].word), fp_f); /* read 2nd op */
|
|
d = ReadOp(IM(op[2].word), fp_f);
|
|
sig_cmul(&p1, &p2, a, b, c, d);
|
|
WriteOp(RE(op[0].word), p1, fp_f); /* write real result */
|
|
WriteOp(IM(op[0].word), p2, fp_f); /* write imag result */
|
|
break;
|
|
|
|
case 011: /* .CDIV (OP_AAA) */
|
|
/* .CDIV Complex division
|
|
* call:
|
|
* JSB .CDIV
|
|
* DEF result,I
|
|
* DEF oprd1,I
|
|
* DEF oprd2,I
|
|
* complex division is: (a+bi)/(c+di) => ((ac+bd) + (bc-ad)i)/(c^2+d^2) */
|
|
a = ReadOp(RE(op[1].word), fp_f); /* read 1st op */
|
|
b = ReadOp(IM(op[1].word), fp_f);
|
|
c = ReadOp(RE(op[2].word), fp_f); /* read 2nd op */
|
|
d = ReadOp(IM(op[2].word), fp_f);
|
|
(void)fp_unpack (NULL, &exc, c, fp_f); /* get exponents */
|
|
(void)fp_unpack (NULL, &exd, d, fp_f);
|
|
if (exc < exd) { /* ensure c/d < 1 */
|
|
p1 = a; a = c; c = p1; /* swap dividend and divisor */
|
|
p1 = b; b = d; d = p1;
|
|
}
|
|
(void)fp_exec(060, &p1, d, c); /* p1,accu := d/c */
|
|
(void)fp_exec(044, ACCUM, d, NOP); /* ACCUM := dd/c */
|
|
(void)fp_exec(004, &p2, c, NOP); /* p2 := c + dd/c */
|
|
(void)fp_exec(040, ACCUM, b, p1); /* ACCUM := bd/c */
|
|
(void)fp_exec(004, ACCUM, a, NOP); /* ACCUM := a + bd/c */
|
|
(void)fp_exec(070, &p3, NOP, p2); /* p3 := (a+bd/c)/(c+dd/c) == (ac+bd)/(cc+dd) */
|
|
WriteOp(RE(op[0].word), p3, fp_f); /* Write real result */
|
|
(void)fp_exec(040, ACCUM, a, p1); /* ACCUM := ad/c */
|
|
(void)fp_exec(030, ACCUM, NOP, b); /* ACCUM := ad/c - b */
|
|
if (exd < exc) { /* was not swapped? */
|
|
(void)fp_exec(024, ACCUM, ZERO, NOP); /* ACCUM := -ACCUM */
|
|
}
|
|
(void)fp_exec(070, &p3, NOP, p2); /* p3 := (b-ad/c)/(c+dd/c) == (bc-ad)/cc+dd) */
|
|
WriteOp(IM(op[0].word), p3, fp_f); /* Write imag result */
|
|
break;
|
|
|
|
case 012: /* CONJG (OP_AAA) */
|
|
/* CONJG build A-Bi from A+Bi
|
|
* call:
|
|
* JSB CONJG
|
|
* DEF RTN
|
|
* DEF res,I result
|
|
* DEF arg,I input argument */
|
|
a = ReadOp(RE(op[2].word), fp_f); /* read real */
|
|
b = ReadOp(IM(op[2].word), fp_f); /* read imag */
|
|
(void)fp_pcom(&b, fp_f); /* negate imag */
|
|
WriteOp(RE(op[1].word), a, fp_f); /* write real */
|
|
WriteOp(IM(op[1].word), b, fp_f); /* write imag */
|
|
break;
|
|
|
|
case 013: /* ..CCM (OP_A) */
|
|
/* ..CCM complement complex
|
|
* call
|
|
* JSB ..CCM
|
|
* DEF arg
|
|
* build (-RE,-IM)
|
|
*/
|
|
v = op[0].word;
|
|
a = ReadOp(RE(v), fp_f); /* read real */
|
|
b = ReadOp(IM(v), fp_f); /* read imag */
|
|
(void)fp_pcom(&a, fp_f); /* negate real */
|
|
(void)fp_pcom(&b, fp_f); /* negate imag */
|
|
WriteOp(RE(v), a, fp_f); /* write real */
|
|
WriteOp(IM(v), b, fp_f); /* write imag */
|
|
break;
|
|
|
|
case 014: /* AIMAG (OP_AA) */
|
|
/* AIMAG return the imaginary part in AB
|
|
* JSB AIMAG
|
|
* DEF *+2
|
|
* DEF cplx(,I)
|
|
* returns: AB imaginary part of complex number */
|
|
a = ReadOp(IM(op[1].word), fp_f); /* read imag */
|
|
AR = a.fpk[0]; /* move MSB to A */
|
|
BR = a.fpk[1]; /* move LSB to B */
|
|
break;
|
|
|
|
case 015: /* CMPLX (OP_AFF) */
|
|
/* CMPLX form a complex number
|
|
* JSB CMPLX
|
|
* DEF *+4
|
|
* DEF result,I complex number
|
|
* DEF repart,I real value
|
|
* DEF impart,I imaginary value */
|
|
WriteOp(RE(op[1].word), op[2], fp_f); /* write real part */
|
|
WriteOp(IM(op[1].word), op[3], fp_f); /* write imag part */
|
|
break;
|
|
|
|
case 017: /* [slftst] (OP_N) */
|
|
XR = 2; /* firmware revision */
|
|
SR = 0102077; /* test passed code */
|
|
PR = (PR + 1) & LA_MASK; /* P+2 return for firmware w/SIGNAL1000 */
|
|
break;
|
|
|
|
case 016: /* invalid */
|
|
default: /* others unimplemented */
|
|
reason = STOP (cpu_ss_unimpl);
|
|
}
|
|
|
|
return reason;
|
|
}
|
|
|
|
#endif /* int64 conditional */
|
|
|
|
|
|
|
|
/* EMA local utility routines */
|
|
|
|
|
|
/* .EMAP microcode routine, resolves both EMA/non-EMA calls
|
|
* Call:
|
|
* OCT 105257B
|
|
* DEF RTN error return (rtn), good return is rtn+1
|
|
* DEF ARRAY[,I] array base (abase)
|
|
* DEF TABLE[,I] array declaration (dtbl)
|
|
* DEF A(N)[,I] actual subscripts (atbl)
|
|
* DEF A(N-1)[,I]
|
|
* ...
|
|
* DEF A(2)[,I]
|
|
* DEF A(1)[,I]
|
|
* RTN EQU * error return A="15", B="EM"
|
|
* RTN+1 EQU *+1 good return B=logical address
|
|
*
|
|
* TABLE DEC # # dimensions
|
|
* DEC -L(N)
|
|
* DEC D(N-1)
|
|
* DEC -L(N-1) lower bound (n-1)st dim
|
|
* DEC D(N-2) (n-2)st dim
|
|
* ...
|
|
* DEC D(1) 1st dim
|
|
* DEC -L(1) lower bound 1st dim
|
|
* DEC # # words/element
|
|
* OFFSET 1 EMA Low
|
|
* OFFSET 2 EMA High
|
|
*/
|
|
|
|
static t_stat ema_emap(uint32* rtn,uint32 abase,uint32 dtbl,uint32 atbl)
|
|
{
|
|
uint32 xidex, eqt, idext0, idext1;
|
|
int32 sub, ndim, sz;
|
|
uint32 offs, pgoff, emasz, phys, msgn, mseg, sum, pg0, pg1, act, low, usz;
|
|
|
|
xidex = ReadU (idx); /* read ID Extension */
|
|
if (xidex) { /* is EMA declared? */
|
|
idext1 = ReadWA(xidex+1); /* get word 1 of idext */
|
|
mseg = (idext1 >> 1) & MSEG_MASK; /* get logical start MSEG */
|
|
if (abase >= mseg) { /* EMA reference? */
|
|
if (!ema_resolve(dtbl,atbl,&sum)) /* calculate subscript */
|
|
goto em15;
|
|
offs = sum & 01777; /* address offset within page */
|
|
pgoff = sum >> 10; /* ema offset in pages */
|
|
if (pgoff > 1023) goto em15; /* overflow? */
|
|
eqt = ReadU (xeqt);
|
|
emasz = ReadWA(eqt+28) & 01777; /* EMA size in pages */
|
|
phys = idext1 & 01777; /* physical start pg of EMA */
|
|
if (pgoff > emasz) goto em15; /* outside EMA range? */
|
|
|
|
msgn = mseg >> 10; /* get # of 1st MSEG reg */
|
|
phys += pgoff;
|
|
|
|
pg0 = meu_read_map(User_Map,0); /* read base page map# */
|
|
pg1 = meu_read_map(User_Map,1); /* save map# 1 */
|
|
meu_write_map(User_Map,1,pg0); /* map #0 into reg #1 */
|
|
|
|
WriteU (umaps + msgn, phys); /* store 1st mapped pg in user map */
|
|
meu_write_map(User_Map, msgn, phys); /* and set the map register */
|
|
phys = (pgoff+1)==emasz ? 0140000 : phys+1; /* protect 2nd map if end of EMA */
|
|
WriteU (umaps + msgn + 1, phys); /* store 2nd mapped pg in user map */
|
|
meu_write_map(User_Map, msgn+1, phys); /* and set the map register */
|
|
|
|
meu_write_map(User_Map,1,pg1); /* restore map #1 */
|
|
|
|
idext0 = ReadWA(xidex+0) | 0100000; /* set NS flag in id extension */
|
|
WriteS (xidex + 0, idext0); /* save back value */
|
|
AR = 0; /* was successful */
|
|
BR = (HP_WORD) (mseg + offs); /* calculate log address */
|
|
(*rtn)++; /* return via good exit */
|
|
return SCPE_OK;
|
|
}
|
|
} /* not EMA reference */
|
|
ndim = ReadW(dtbl++);
|
|
if (ndim<0) goto em15; /* negative dimensions */
|
|
sum = 0; /* accu for index calc */
|
|
while (ndim > 0) {
|
|
MR = ReadW (atbl++); /* fetch address of A(N) */
|
|
cpu_resolve_indirects (FALSE); /* resolve indirects (uninterruptible) */
|
|
act = ReadW(MR); /* A(N) */
|
|
low = ReadW(dtbl++); /* -L(N) */
|
|
sub = SEXT16(act) + SEXT16(low); /* subscript */
|
|
if (sub & 0xffff8000) goto em15; /* overflow? */
|
|
sum += sub; /* accumulate */
|
|
usz = ReadW(dtbl++);
|
|
sz = SEXT16(usz);
|
|
if (sz < 0) goto em15;
|
|
sum *= sz; /* and multiply with sz of dimension */
|
|
if (sum & 0xffff8000) goto em15; /* overflow? */
|
|
ndim--;
|
|
}
|
|
BR = (HP_WORD) (abase + sum); /* add displacement */
|
|
(*rtn)++; /* return via good exit */
|
|
return SCPE_OK;
|
|
|
|
em15: /* error condition */
|
|
AR=0x3135; /* AR = '15' */
|
|
BR=0x454d; /* BR = 'EM' */
|
|
return SCPE_OK; /* return via unmodified e->rtn */
|
|
}
|
|
|
|
|
|
/* .EMIO microcode routine, resolves element addr for EMA array
|
|
* and maps the appropriate map segment
|
|
*
|
|
* Call:
|
|
* OCT 105250B
|
|
* DEF RTN error return (rtn), good return is rtn+1
|
|
* DEF BUFLEN length of buffer in words (bufl)
|
|
* DEF TABLE[,I] array declaration (dtbl)
|
|
* DEF A(N)[,I] actual subscripts (atbl)
|
|
* DEF A(N-1)[,I]
|
|
* ...
|
|
* DEF A(2)[,I]
|
|
* DEF A(1)[,I]
|
|
* RTN EQU * error return A="15", B="EM"
|
|
* RTN+1 EQU *+1 good return B=logical address
|
|
*
|
|
* TABLE DEC # # dimensions
|
|
* DEC -L(N)
|
|
* DEC D(N-1)
|
|
* DEC -L(N-1) lower bound (n-1)st dim
|
|
* DEC D(N-2) (n-2)st dim
|
|
* ...
|
|
* DEC D(1) 1st dim
|
|
* DEC -L(1) lower bound 1st dim
|
|
* DEC # # words/element
|
|
* OFFSET 1 EMA Low
|
|
* OFFSET 2 EMA High
|
|
*/
|
|
|
|
static t_stat ema_emio(uint32* rtn,uint32 bufl,uint32 dtbl,uint32 atbl)
|
|
{
|
|
uint32 xidex, idext1;
|
|
uint32 mseg, bufpgs, npgs;
|
|
EMA4 ema4, *e = &ema4;
|
|
|
|
xidex = ReadU (idx); /* read ID extension */
|
|
if (bufl & D16_SIGN || /* buffer length negative? */
|
|
xidex==0) goto em16; /* no EMA declared? */
|
|
|
|
idext1 = ReadWA(xidex+1); /* |logstrt mseg|d|physstrt ema| */
|
|
mseg = (idext1 >> 1) & MSEG_MASK; /* get logical start MSEG */
|
|
if (!ema_emas(dtbl,atbl,e)) goto em16; /* resolve address */
|
|
bufpgs = (bufl + e->offs) >> 10; /* # of pgs reqd for buffer */
|
|
if ((bufl + e->offs) & 01777) bufpgs++; /* S11 add 1 if not at pg boundary */
|
|
if ((bufpgs + e->pgoff) > e->emasz) goto em16; /* exceeds EMA limit? */
|
|
npgs = (e->msoff + bufl) >> 10; /* # of pgs reqd for MSEG */
|
|
if ((e->msoff + bufl) & 01777) npgs++; /* add 1 if not at pg boundary */
|
|
if (npgs < e->msegsz) {
|
|
e->mseg = mseg; /* logical stat of MSEG */
|
|
if (!ema_emat(e)) goto em16; /* do a std mapping */
|
|
} else {
|
|
BR = (HP_WORD) (mseg + e->offs); /* logical start of buffer */
|
|
e->npgs = bufpgs; /* S5 # pgs required */
|
|
e->ipgs = e->pgoff; /* S6 page offset to reqd pg */
|
|
if (!ema_mmap02(e)) goto em16; /* do nonstd mapping */
|
|
}
|
|
(*rtn)++; /* return via good exit */
|
|
return SCPE_OK;
|
|
|
|
em16: /* error condition */
|
|
AR=0x3136; /* AR = '16' */
|
|
BR=0x454d; /* BR = 'EM' */
|
|
return SCPE_OK; /* return via unmodified rtn */
|
|
}
|
|
|
|
|
|
/* Map a sequence of physical memory pages into the mapping segment */
|
|
|
|
static t_stat ema_mmap(uint32 ipage,uint32 npgs)
|
|
{
|
|
uint32 xidex;
|
|
EMA4 ema4, *e = &ema4;
|
|
|
|
e->ipgs = ipage; /* S6 set the arguments */
|
|
e->npgs = npgs; /* S5 */
|
|
|
|
AR = 0;
|
|
xidex = ReadU (idx);
|
|
if ((ipage & D16_SIGN) || /* negative page displacement? */
|
|
(npgs & D16_SIGN) || /* negative # of pages? */
|
|
xidex == 0 || /* no EMA? */
|
|
!ema_mmap02(e)) /* mapping failed? */
|
|
AR = 0177777; /* return with error */
|
|
return SCPE_OK; /* leave */
|
|
}
|
|
|
|
|
|
/* calculate the 32 bit EMA subscript for an array */
|
|
|
|
static t_bool ema_resolve(uint32 dtbl,uint32 atbl,uint32* sum)
|
|
{
|
|
int32 sub, sz, ndim;
|
|
uint32 base, udim, usz, act, low;
|
|
|
|
udim = ReadW(dtbl++); /* # dimensions */
|
|
ndim = SEXT16(udim); /* sign extend */
|
|
if (ndim < 0) return FALSE; /* invalid? */
|
|
|
|
*sum = 0; /* accu for index calc */
|
|
while (ndim > 0) {
|
|
MR = ReadW (atbl++); /* fetch address of A(N) */
|
|
cpu_resolve_indirects (FALSE); /* resolve indirects (uninterruptible) */
|
|
act = ReadW(MR); /* A(N) */
|
|
low = ReadW(dtbl++); /* -L(N) */
|
|
sub = SEXT16(act) + SEXT16(low); /* subscript */
|
|
if (sub & 0xffff8000) return FALSE; /* overflow? */
|
|
*sum += sub; /* accumulate */
|
|
usz = ReadW(dtbl++);
|
|
sz = SEXT16(usz);
|
|
if (sz < 0) return FALSE;
|
|
*sum *= sz;
|
|
if (*sum > (512*1024)) return FALSE; /* overflow? */
|
|
ndim--;
|
|
}
|
|
base = (ReadW(dtbl+1)<<16) | (ReadW(dtbl) & 0xffff); /* base of array in EMA */
|
|
if (base & 0x8000000) return FALSE;
|
|
*sum += base; /* calculate address into EMA */
|
|
if (*sum & 0xf8000000) return FALSE; /* overflow? */
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static t_bool ema_emas(uint32 dtbl,uint32 atbl,EMA4* e)
|
|
{
|
|
uint32 xidex, eqt;
|
|
uint32 sum, msegsz,pgoff,offs,emasz,msegno,msoff,ipgs;
|
|
|
|
if (!ema_resolve(dtbl,atbl,&sum)) return FALSE; /* calculate 32 bit index */
|
|
|
|
xidex = ReadU (idx); /* read ID extension */
|
|
msegsz = ReadWA(xidex+0) & 037; /* S5 # pgs for std MSEG */
|
|
pgoff = sum >> 10; /* S2 page containing element */
|
|
offs = sum & 01777; /* S6 offset in page to element */
|
|
if (pgoff > 1023) return FALSE; /* overflow? */
|
|
eqt = ReadU (xeqt);
|
|
emasz = ReadWA(eqt+28) & 01777; /* S EMA size in pages */
|
|
if (pgoff > emasz) return FALSE; /* outside EMA? */
|
|
msegno = pgoff / msegsz; /* S4 # of MSEG */
|
|
msoff = pgoff % msegsz; /* offset within MSEG in pgs */
|
|
ipgs = pgoff - msoff; /* S7 # pgs to start of MSEG */
|
|
msoff = msoff << 10; /* offset within MSEG in words */
|
|
msoff += offs; /* S1 offset to element in words */
|
|
|
|
e->msegsz = msegsz; /* return calculated data */
|
|
e->pgoff = pgoff;
|
|
e->offs = offs;
|
|
e->emasz = emasz;
|
|
e->msegno = msegno;
|
|
e->ipgs = ipgs;
|
|
e->msoff = msoff;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static t_bool ema_emat(EMA4* e)
|
|
{
|
|
uint32 xidex,idext0;
|
|
uint32 curmseg,phys,msnum,lastpgs;
|
|
|
|
xidex = ReadU (idx); /* read ID extension */
|
|
idext0 = ReadWA(xidex+0); /* get current segment */
|
|
curmseg = idext0 >> 5;
|
|
if ((idext0 & 0100000) || /* was nonstd MSEG? */
|
|
curmseg != e->msegno) { /* or different MSEG last time? */
|
|
phys = ReadWA(xidex+1) & 01777; /* physical start pg of EMA */
|
|
e->spmseg = phys + e->ipgs; /* physical start pg of MSEG */
|
|
msnum = e->emasz / e->msegsz; /* find last MSEG# */
|
|
lastpgs = e->emasz % e->msegsz; /* #pgs in last MSEG */
|
|
if (lastpgs==0) msnum--; /* adjust # of last MSEG */
|
|
e->npgs = msnum==e->msegno ? lastpgs : e->msegsz; /* for last MSEG, only map available pgs */
|
|
if (!ema_mmap01(e)) return FALSE; /* map npgs pages at ipgs */
|
|
}
|
|
BR = (HP_WORD) (e->mseg + e->msoff); /* return address of element */
|
|
return TRUE; /* and everything done */
|
|
}
|
|
|
|
|
|
static t_bool ema_mmap01(EMA4* e)
|
|
{
|
|
uint32 xidex,idext0, pg, pg0, pg1, i;
|
|
|
|
uint32 base = e->mseg >> 10; /* get the # of first MSEG DMS reg */
|
|
xidex = ReadU (idx); /* get ID extension */
|
|
idext0 = ReadWA(xidex+1);
|
|
|
|
if (e->npgs==0) return FALSE; /* no pages to map? */
|
|
if ((e->npgs+1+e->ipgs) <= e->emasz) e->npgs++; /* actually map npgs+1 pgs */
|
|
|
|
/* locations 1740...1777 of user base page contain the map entries we need.
|
|
* They are normally hidden by BP fence, therefore they have to be accessed by
|
|
* another fence-less map register. uCode uses #1, macro code uses $DVCT (==2)
|
|
*/
|
|
pg0 = meu_read_map(User_Map,0); /* read base page map# */
|
|
pg1 = meu_read_map(User_Map,1); /* save map# 1 */
|
|
meu_write_map(User_Map,1,pg0); /* map #0 into reg #1 */
|
|
for (i=0; (base+i)<32; i++) {
|
|
pg = i<e->npgs ? e->spmseg : 0140000; /* write protect if outside */
|
|
WriteU (umaps + base + i, pg); /* copy pg to user map */
|
|
/* printf("MAP val %d to reg %d (addr=%o)\n",pg,base+i,umaps+base+i); */
|
|
meu_write_map(User_Map, base+i, pg); /* set DMS reg */
|
|
e->spmseg++;
|
|
}
|
|
meu_write_map(User_Map,1,pg1); /* restore map #1 */
|
|
|
|
xidex = ReadU (idx); /* get ID extension */
|
|
idext0 = ReadWA(xidex+0);
|
|
if (e->msegno == 0xffff) /* non std mseg */
|
|
idext0 |= 0x8000; /* set nonstd marker */
|
|
else
|
|
idext0 = (idext0 & 037) | (e->msegno<<5); /* set new current mseg# */
|
|
WriteS (xidex, idext0); /* save back value */
|
|
AR = 0; /* was successful */
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static t_bool ema_mmap02(EMA4* e)
|
|
{
|
|
uint32 xidex, eqt, idext1;
|
|
uint32 mseg,phys,spmseg,emasz,msegsz,msegno;
|
|
|
|
xidex = ReadU (idx); /* get ID extension */
|
|
msegsz = ReadWA(xidex+0) & 037; /* P size of std MSEG */
|
|
idext1 = ReadWA(xidex+1);
|
|
mseg = (idext1 >> 1) & MSEG_MASK; /* S9 get logical start MSEG */
|
|
phys = idext1 & 01777; /* S phys start of EMA */
|
|
spmseg = phys + e->ipgs; /* S7 phys pg# of MSEG */
|
|
msegno = e->ipgs / msegsz;
|
|
if ((e->ipgs % msegsz) != 0) /* non std MSEG? */
|
|
msegno = 0xffff; /* S4 yes, set marker */
|
|
if (e->npgs > msegsz) return FALSE; /* map more pages than MSEG sz? */
|
|
eqt = ReadU (xeqt);
|
|
emasz = ReadWA(eqt+28) & 01777; /* B EMA size in pages */
|
|
if ((e->ipgs+e->npgs) > emasz) return FALSE; /* outside EMA? */
|
|
if ((e->ipgs+msegsz) > emasz) /* if MSEG overlaps end of EMA */
|
|
e->npgs = emasz - e->ipgs; /* only map until end of EMA */
|
|
|
|
e->emasz = emasz; /* copy arguments */
|
|
e->msegsz = msegsz;
|
|
e->msegno = msegno;
|
|
e->spmseg = spmseg;
|
|
e->mseg = mseg;
|
|
return ema_mmap01(e);
|
|
}
|
|
|
|
|
|
/* Format an error code in the A and B registers.
|
|
|
|
This routine conditionally formats the contents of the A and B registers into
|
|
an error message. If the supplied "success" flag is 0, the A and B registers
|
|
contain a four-character error code (e.g., "EM82"), with the leading
|
|
characters in the B register. The characters are moved into the error
|
|
message, and a pointer to the message is returned. If "success" is non-zero,
|
|
then a pointer to the message reporting normal execution is returned.
|
|
|
|
The routine is typically called from an instructio executor during operand
|
|
tracing.
|
|
*/
|
|
|
|
static const char *fmt_ab (t_bool success)
|
|
{
|
|
static const char good [] = "normal";
|
|
static char error [] = "error ....";
|
|
|
|
if (success) /* if the instruction succeeded */
|
|
return good; /* then report a normal completion */
|
|
|
|
else { /* otherwise */
|
|
error [6] = UPPER_BYTE (BR); /* format the */
|
|
error [7] = LOWER_BYTE (BR); /* error code */
|
|
error [8] = UPPER_BYTE (AR); /* into the */
|
|
error [9] = LOWER_BYTE (AR); /* error message */
|
|
|
|
return error; /* report an abnormal completion */
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#if defined (HAVE_INT64) /* int64 support available */
|
|
|
|
/* VIS local utility routines */
|
|
|
|
|
|
/* handle the scalar/vector base ops */
|
|
|
|
static void vis_svop(uint32 subcode, OPS op, OPSIZE opsize)
|
|
{
|
|
OP v1,v2;
|
|
int16 delta = opsize==fp_f ? 2 : 4;
|
|
OP s = ReadOp(op[0].word,opsize);
|
|
uint32 v1addr = op[1].word;
|
|
int16 ix1 = INT16(op[2].word) * delta;
|
|
uint32 v2addr = op[3].word;
|
|
int16 ix2 = INT16(op[4].word) * delta;
|
|
int16 i, n = INT16(op[5].word);
|
|
uint16 fpuop = (uint16) (subcode & 060) | (opsize==fp_f ? 0 : 2);
|
|
|
|
if (n <= 0) return;
|
|
for (i=0; i<n; i++) {
|
|
v1 = ReadOp(v1addr, opsize);
|
|
(void)fp_exec(fpuop, &v2, s ,v1);
|
|
WriteOp(v2addr, v2, opsize);
|
|
v1addr += ix1;
|
|
v2addr += ix2;
|
|
}
|
|
}
|
|
|
|
|
|
/* handle the vector/vector base ops */
|
|
|
|
static void vis_vvop(uint32 subcode, OPS op,OPSIZE opsize)
|
|
{
|
|
OP v1,v2,v3;
|
|
int16 delta = opsize==fp_f ? 2 : 4;
|
|
uint32 v1addr = op[0].word;
|
|
int32 ix1 = INT16(op[1].word) * delta;
|
|
uint32 v2addr = op[2].word;
|
|
int32 ix2 = INT16(op[3].word) * delta;
|
|
uint32 v3addr = op[4].word;
|
|
int32 ix3 = INT16(op[5].word) * delta;
|
|
int16 i, n = INT16(op[6].word);
|
|
uint16 fpuop = (uint16) (subcode & 060) | (opsize==fp_f ? 0 : 2);
|
|
|
|
if (n <= 0) return;
|
|
for (i=0; i<n; i++) {
|
|
v1 = ReadOp(v1addr, opsize);
|
|
v2 = ReadOp(v2addr, opsize);
|
|
(void)fp_exec(fpuop, &v3, v1 ,v2);
|
|
WriteOp(v3addr, v3, opsize);
|
|
v1addr += ix1;
|
|
v2addr += ix2;
|
|
v3addr += ix3;
|
|
}
|
|
}
|
|
|
|
|
|
static void vis_abs(OP* in, OPSIZE opsize)
|
|
{
|
|
uint32 sign = GET_MSIGN(in); /* get sign */
|
|
if (sign) (void)fp_pcom(in, opsize); /* if negative, make positive */
|
|
}
|
|
|
|
|
|
static void vis_minmax(OPS op,OPSIZE opsize,t_bool domax,t_bool doabs)
|
|
{
|
|
OP v1,vmxmn,res;
|
|
int16 delta = opsize==fp_f ? 2 : 4;
|
|
uint32 mxmnaddr = op[0].word;
|
|
uint32 v1addr = op[1].word;
|
|
int16 ix1 = INT16(op[2].word) * delta;
|
|
int16 n = INT16(op[3].word);
|
|
int16 i,mxmn,sign;
|
|
uint16 subop = 020 | (opsize==fp_f ? 0 : 2);
|
|
|
|
if (n <= 0) return;
|
|
mxmn = 0; /* index of maxmin element */
|
|
vmxmn = ReadOp(v1addr,opsize); /* initialize with first element */
|
|
if (doabs) vis_abs(&vmxmn,opsize); /* ABS(v[1]) if requested */
|
|
|
|
for (i = 0; i<n; i++) {
|
|
v1 = ReadOp(v1addr,opsize); /* get v[i] */
|
|
if (doabs) vis_abs(&v1,opsize); /* build ABS(v[i]) if requested */
|
|
(void)fp_exec(subop,&res,vmxmn,v1); /* subtract vmxmn - v1[i] */
|
|
sign = GET_MSIGN(&res); /* !=0 if vmxmn < v1[i] */
|
|
if ((domax && sign) || /* new max value found */
|
|
(!domax && !sign)) { /* new min value found */
|
|
mxmn = i;
|
|
vmxmn = v1; /* save the new max/min value */
|
|
}
|
|
v1addr += ix1; /* point to next element */
|
|
}
|
|
res.word = mxmn+1; /* adjust to one-based FTN array */
|
|
WriteOp(mxmnaddr, res, in_s); /* save result */
|
|
}
|
|
|
|
|
|
static void vis_vpiv(OPS op, OPSIZE opsize)
|
|
{
|
|
OP s,v1,v2,v3;
|
|
int16 delta = opsize==fp_f ? 2 : 4;
|
|
uint32 saddr = op[0].word;
|
|
uint32 v1addr = op[1].word;
|
|
int16 ix1 = INT16(op[2].word) * delta;
|
|
uint32 v2addr = op[3].word;
|
|
int16 ix2 = INT16(op[4].word) * delta;
|
|
uint32 v3addr = op[5].word;
|
|
int16 ix3 = INT16(op[6].word) * delta;
|
|
int16 i, n = INT16(op[7].word);
|
|
int16 oplen = opsize==fp_f ? 0 : 2;
|
|
|
|
if (n <= 0) return;
|
|
s = ReadOp(saddr,opsize);
|
|
/* calculates v3[k] = s * v1[i] + v2[j] for incrementing i,j,k */
|
|
for (i=0; i<n; i++) {
|
|
v1 = ReadOp(v1addr, opsize);
|
|
(void)fp_exec(040+oplen, ACCUM, s ,v1); /* ACCU := s*v1 */
|
|
v2 = ReadOp(v2addr, opsize);
|
|
(void)fp_exec(004+oplen,&v3,v2,NOP); /* v3 := v2 + s*v1 */
|
|
WriteOp(v3addr, v3, opsize); /* write result */
|
|
v1addr += ix1; /* forward to next array elements */
|
|
v2addr += ix2;
|
|
v3addr += ix3;
|
|
}
|
|
}
|
|
|
|
|
|
static void vis_vabs(OPS op, OPSIZE opsize)
|
|
{
|
|
OP v1;
|
|
int16 delta = opsize==fp_f ? 2 : 4;
|
|
uint32 v1addr = op[0].word;
|
|
int16 ix1 = INT16(op[1].word) * delta;
|
|
uint32 v2addr = op[2].word;
|
|
int32 ix2 = INT16(op[3].word) * delta;
|
|
int16 i,n = INT16(op[4].word);
|
|
|
|
if (n <= 0) return;
|
|
/* calculates v2[j] = ABS(v1[i]) for incrementing i,j */
|
|
for (i=0; i<n; i++) {
|
|
v1 = ReadOp(v1addr, opsize);
|
|
vis_abs(&v1,opsize); /* make absolute value */
|
|
WriteOp(v2addr, v1, opsize); /* write result */
|
|
v1addr += ix1; /* forward to next array elements */
|
|
v2addr += ix2;
|
|
}
|
|
}
|
|
|
|
|
|
static void vis_trunc(OP* out, OP in)
|
|
{
|
|
/* Note there is fp_trun(), but this doesn't seem to do the same conversion
|
|
* as the original code does */
|
|
out->fpk[0] = in.fpk[0];
|
|
out->fpk[1] = (in.fpk[1] & 0177400) | (in.fpk[3] & 0377);
|
|
}
|
|
|
|
|
|
static void vis_vsmnm(OPS op,OPSIZE opsize,t_bool doabs)
|
|
{
|
|
uint16 fpuop;
|
|
OP v1,sumnrm = ZERO;
|
|
int16 delta = opsize==fp_f ? 2 : 4;
|
|
uint32 saddr = op[0].word;
|
|
uint32 v1addr = op[1].word;
|
|
int16 ix1 = INT16(op[2].word) * delta;
|
|
int16 i,n = INT16(op[3].word);
|
|
|
|
if (n <= 0) return;
|
|
/* calculates sumnrm = sumnrm + DBLE(v1[i]) resp DBLE(ABS(v1[i])) for incrementing i */
|
|
for (i=0; i<n; i++) {
|
|
v1 = ReadOp(v1addr, opsize);
|
|
if (opsize==fp_f) (void)fp_cvt(&v1,fp_f,fp_t); /* cvt to DBLE(v1) */
|
|
fpuop = (doabs && GET_MSIGN(&v1)) ? 022 : 002; /* use subtract for NRM && V1<0 */
|
|
(void)fp_exec(fpuop,&sumnrm, sumnrm, v1); /* accumulate */
|
|
v1addr += ix1; /* forward to next array elements */
|
|
}
|
|
if (opsize==fp_f)
|
|
(void)vis_trunc(&sumnrm,sumnrm); /* truncate to SNGL(sumnrm) */
|
|
WriteOp(saddr, sumnrm, opsize); /* write result */
|
|
}
|
|
|
|
|
|
static void vis_vdot(OPS op,OPSIZE opsize)
|
|
{
|
|
OP v1,v2,dot = ZERO;
|
|
int16 delta = opsize==fp_f ? 2 : 4;
|
|
uint32 daddr = op[0].word;
|
|
uint32 v1addr = op[1].word;
|
|
int16 ix1 = INT16(op[2].word) * delta;
|
|
uint32 v2addr = op[3].word;
|
|
int16 ix2 = INT16(op[4].word) * delta;
|
|
int16 i,n = INT16(op[5].word);
|
|
|
|
if (n <= 0) return;
|
|
/* calculates dot = dot + v1[i]*v2[j] for incrementing i,j */
|
|
for (i=0; i<n; i++) {
|
|
v1 = ReadOp(v1addr, opsize);
|
|
if (opsize==fp_f) (void)fp_cvt(&v1,fp_f,fp_t); /* cvt to DBLE(v1) */
|
|
v2 = ReadOp(v2addr, opsize);
|
|
if (opsize==fp_f) (void)fp_cvt(&v2,fp_f,fp_t); /* cvt to DBLE(v2) */
|
|
(void)fp_exec(042,ACCUM, v1, v2); /* ACCU := v1 * v2 */
|
|
(void)fp_exec(006,&dot,dot,NOP); /* dot := dot + v1*v2 */
|
|
v1addr += ix1; /* forward to next array elements */
|
|
v2addr += ix2;
|
|
}
|
|
if (opsize==fp_f)
|
|
(void)vis_trunc(&dot,dot); /* truncate to SNGL(sumnrm) */
|
|
WriteOp(daddr, dot, opsize); /* write result */
|
|
}
|
|
|
|
|
|
static void vis_movswp(OPS op, OPSIZE opsize, t_bool doswp)
|
|
{
|
|
OP v1,v2;
|
|
int16 delta = opsize==fp_f ? 2 : 4;
|
|
uint32 v1addr = op[0].word;
|
|
int16 ix1 = INT16(op[1].word) * delta;
|
|
uint32 v2addr = op[2].word;
|
|
int16 ix2 = INT16(op[3].word) * delta;
|
|
int16 i,n = INT16(op[4].word);
|
|
|
|
if (n <= 0) return;
|
|
for (i=0; i<n; i++) {
|
|
v1 = ReadOp(v1addr, opsize);
|
|
v2 = ReadOp(v2addr, opsize);
|
|
WriteOp(v2addr, v1, opsize); /* v2 := v1 */
|
|
if (doswp) WriteOp(v1addr, v2, opsize); /* v1 := v2 */
|
|
v1addr += ix1; /* forward to next array elements */
|
|
v2addr += ix2;
|
|
}
|
|
}
|
|
|
|
|
|
/* implementation of VIS RTE-IVB EMA support
|
|
* .ERES microcode routine, resolves only EMA addresses
|
|
* Call:
|
|
* .OCT 101474B
|
|
* DEF RTN error return (rtn), good return is rtn+1
|
|
* DEF DUMMY dummy argument for compatibility with .EMAP
|
|
* DEF TABLE[,I] array declaration (dtbl)
|
|
* DEF A(N)[,I] actual subscripts (atbl)
|
|
* DEF A(N-1)[,I]
|
|
* ...
|
|
* DEF A(2)[,I]
|
|
* DEF A(1)[,I]
|
|
* RTN EQU * error return A="20", B="EM"
|
|
* RTN+1 EQU *+1 good return B=logical address
|
|
*
|
|
* TABLE DEC # # dimensions
|
|
* DEC -L(N)
|
|
* DEC D(N-1)
|
|
* DEC -L(N-1) lower bound (n-1)st dim
|
|
* DEC D(N-2) (n-2)st dim
|
|
* ...
|
|
* DEC D(1) 1st dim
|
|
* DEC -L(1) lower bound 1st dim
|
|
* DEC # # words/element
|
|
* OFFSET 1 EMA Low
|
|
* OFFSET 2 EMA High
|
|
*/
|
|
|
|
static t_stat vis_eres(HP_WORD *rtn,uint32 dtbl,uint32 atbl)
|
|
{
|
|
uint32 sum;
|
|
if (ema_resolve(dtbl,atbl,&sum)) { /* calculate subscript */
|
|
AR = sum & 0xffff;
|
|
BR = sum >> 16;
|
|
if (!(BR & D16_SIGN)) { /* no overflow? */
|
|
(*rtn)++; /* return via good exit */
|
|
return SCPE_OK;
|
|
}
|
|
}
|
|
AR = 0x3230; /* error condition: */
|
|
BR = 0x454d; /* AR = '20', BR = 'EM' */
|
|
return SCPE_OK; /* return via unmodified rtn */
|
|
}
|
|
|
|
|
|
/* implementation of VIS RTE-IVB EMA support
|
|
* .ESEG microcode routine
|
|
* Call:
|
|
* LDA FIRST first map to set
|
|
* LDB N # of maps to set
|
|
* .OCT 101475B/105475B
|
|
* DEF RTN ptr to return
|
|
* DEF TABLE map table
|
|
* RTN EQU * error return A="21", B="EM"
|
|
* RTN+1 EQU *+1 good return B=logical address
|
|
*
|
|
* load maps FIRST to FIRST+N from TABLE, with FIRST = FIRST + LOG_START MSEG
|
|
* update map table in base page. Set LOG_START MSEG=0 if opcode==105475
|
|
*/
|
|
|
|
static t_stat vis_eseg(HP_WORD* rtn, uint32 tbl)
|
|
{
|
|
uint32 xidex,eqt,idext0,idext1;
|
|
uint32 msegsz,phys,msegn,last,emasz,pg0,pg1,pg,i,lp;
|
|
|
|
if ((BR & D16_SIGN) || BR==0) goto em21; /* #maps not positive? */
|
|
xidex = ReadU (idx); /* read ID extension */
|
|
if (xidex==0) goto em21;
|
|
idext0 = ReadWA(xidex+0); /* get 1st word idext */
|
|
msegsz = idext0 & 037; /* S7 MSEG size */
|
|
WriteS (xidex + 0, idext0 | 0100000); /* enforce nonstd MSEG */
|
|
idext1 = ReadWA(xidex+1); /* get 2nd word idext */
|
|
phys = idext1 & 01777; /* S5 phys start of EMA */
|
|
msegn = (idext1 >> 11) & 037; /* S9 get logical start MSEG# */
|
|
if (IR & 04000) { /* opcode == 105475? (.VPRG) */
|
|
msegn = 0; /* log start = 0 */
|
|
msegsz = 32; /* size = full range */
|
|
}
|
|
last = AR-1 + BR; /* last page */
|
|
if (last > msegsz) goto em21; /* too many? error */
|
|
eqt = ReadU (xeqt);
|
|
emasz = (ReadWA(eqt+28) & 01777) - 1; /* S6 EMA size in pages */
|
|
|
|
/* locations 1740...1777 of user base page contain the map entries we need.
|
|
* They are normally hidden by BP fence, therefore they have to be accessed by
|
|
* another fence-less map register. uCode uses #1 temporarily */
|
|
pg0 = meu_read_map(User_Map,0); /* read map #0 */
|
|
pg1 = meu_read_map(User_Map,1); /* save map #1 */
|
|
meu_write_map(User_Map,1,pg0); /* copy #0 into reg #1 */
|
|
lp = AR + msegn; /* first */
|
|
for (i=0; i<BR; i++) { /* loop over N entries */
|
|
pg = ReadW(tbl++); /* get value from table */
|
|
if ((pg & D16_SIGN) || pg > emasz) pg |= 0140000; /* write protect if outside */
|
|
pg += phys; /* adjust into EMA page range */
|
|
WriteU (umaps + lp + i, pg); /* copy pg to user map */
|
|
/* printf("MAP val %oB to reg %d (addr=%oB)\n",pg,lp+i,umaps+lp+i); */
|
|
meu_write_map(User_Map, lp+i, pg); /* set DMS reg */
|
|
}
|
|
meu_write_map(User_Map,1,pg1); /* restore map #1 */
|
|
O = 0; /* clear overflow */
|
|
(*rtn)++; /* return via good exit */
|
|
return SCPE_OK;
|
|
|
|
em21:
|
|
AR = 0x3231; /* error condition: */
|
|
BR = 0x454d; /* AR = '21', BR = 'EM' */
|
|
return SCPE_OK; /* return via unmodified rtn */
|
|
}
|
|
|
|
|
|
/* implementation of VIS RTE-IVB EMA support
|
|
* .VSET microcode routine
|
|
* Call:
|
|
* .OCT 101476B
|
|
* DEF RTN return address
|
|
* DEF VIN input vector
|
|
* DEF VOUT output vector
|
|
* DEF MAPS
|
|
* OCT #SCALARS
|
|
* OCT #VECTORS
|
|
* OCT K 1024/(#words/element)
|
|
* RTN EQU * error return (B,A) = "VI22"
|
|
* RTN+1 EQU *+1 hard return, A = K/IMAX
|
|
* RTN+2 EQU *+2 easy return, A = 0, B = 2* #VCTRS
|
|
*/
|
|
|
|
static t_stat vis_vset(HP_WORD* rtn, OPS op)
|
|
{
|
|
HP_WORD vin = op[0].word; /* S1 */
|
|
HP_WORD vout = op[1].word; /* S2 */
|
|
HP_WORD maps = op[2].word; /* S3 */
|
|
HP_WORD scalars = op[3].word; /* S4 */
|
|
HP_WORD vectors = op[4].word; /* S5 */
|
|
HP_WORD k = op[5].word; /* S6 */
|
|
uint32 imax = 0; /* imax S11*/
|
|
uint32 xidex, idext1, mseg, addr, i;
|
|
t_bool negflag = FALSE;
|
|
|
|
for (i=0; i<scalars; i++) { /* copy scalars */
|
|
XR = ReadW(vin++);
|
|
WriteW(vout++, XR);
|
|
}
|
|
xidex = ReadU (idx); /* get ID extension */
|
|
if (xidex==0) goto vi22; /* NO EMA? error */
|
|
idext1 = ReadWA(xidex+1);
|
|
mseg = (idext1 >> 1) & MSEG_MASK; /* S9 get logical start MSEG */
|
|
|
|
for (i=0; i<vectors; i++) { /* copy vector addresses */
|
|
MR = ReadW(vin++);
|
|
cpu_resolve_indirects (FALSE); /* resolve indirects (uninterruptible) */
|
|
addr = ReadW(MR) & 0177777; /* LSB */
|
|
addr |= (ReadW(MR+1)<<16); /* MSB, build address */
|
|
WriteW(vout++, mseg + (addr & 01777)); /* build and write log addr of vector */
|
|
addr = (addr >> 10) & 0xffff; /* get page */
|
|
WriteW(maps++, addr); /* save page# */
|
|
WriteW(maps++, addr+1); /* save next page# as well */
|
|
|
|
MR = ReadW(vin++); /* get index into Y */
|
|
cpu_resolve_indirects (FALSE); /* resolve indirects (uninterruptible) */
|
|
YR = ReadW(MR); /* get index value */
|
|
WriteW(vout++, MR); /* copy address of index */
|
|
if (YR & D16_SIGN) { /* index is negative */
|
|
negflag = TRUE; /* mark a negative index (HARD) */
|
|
YR = NEG16 (YR); /* make index positive */
|
|
}
|
|
if (imax < YR) imax = YR; /* set maximum index */
|
|
mseg += 04000; /* incr mseg address by 2 more pages */
|
|
}
|
|
MR = ReadW(vin); /* get N index into Y */
|
|
cpu_resolve_indirects (FALSE); /* resolve indirects (uninterruptible) */
|
|
YR = ReadW(MR);
|
|
WriteW(vout++, MR); vin++; /* copy address of N */
|
|
|
|
if (imax==0) goto easy; /* easy case */
|
|
AR = (HP_WORD) (k / imax); AR++; /* calculate K/IMAX */
|
|
if (negflag) goto hard; /* had a negative index? */
|
|
if (YR > AR) goto hard;
|
|
|
|
easy:
|
|
(*rtn)++; /* return via exit 2 */
|
|
AR = 0;
|
|
|
|
hard:
|
|
(*rtn)++; /* return via exit 1 */
|
|
BR = 2 * op[4].word; /* B = 2* vectors */
|
|
return SCPE_OK;
|
|
|
|
vi22: /* error condition */
|
|
AR=0x3232; /* AR = '22' */
|
|
BR=0x5649; /* BR = 'VI' */
|
|
return SCPE_OK; /* return via unmodified e->rtn */
|
|
}
|
|
|
|
|
|
|
|
/* SIGNAL local utility routines */
|
|
|
|
|
|
/* complex addition helper */
|
|
|
|
static void sig_caddsub(uint16 addsub,OPS op)
|
|
{
|
|
OP a,b,c,d,p1,p2;
|
|
|
|
a = ReadOp(RE(op[1].word), fp_f); /* read 1st op */
|
|
b = ReadOp(IM(op[1].word), fp_f);
|
|
c = ReadOp(RE(op[2].word), fp_f); /* read 2nd op */
|
|
d = ReadOp(IM(op[2].word), fp_f);
|
|
(void)fp_exec(addsub,&p1, a, c); /* add real */
|
|
(void)fp_exec(addsub,&p2, b, d); /* add imag */
|
|
WriteOp(RE(op[0].word), p1, fp_f); /* write result */
|
|
WriteOp(IM(op[0].word), p2, fp_f); /* write result */
|
|
}
|
|
|
|
|
|
/* butterfly operation helper */
|
|
/*
|
|
* v(k)-------->o-->o----> v(k)
|
|
* \ /
|
|
* x
|
|
* / \
|
|
* v(k+N/2)---->o-->o----> v(k+N/2)
|
|
* Wn -1
|
|
*
|
|
*/
|
|
|
|
static void sig_btrfy(uint32 re,uint32 im,OP wr,OP wi,uint32 k, uint32 n2)
|
|
{
|
|
OP p1,p2,p3,p4;
|
|
OP v1r = ReadOp(re+k, fp_f); /* read v1 */
|
|
OP v1i = ReadOp(im+k, fp_f);
|
|
OP v2r = ReadOp(re+k+n2, fp_f); /* read v2 */
|
|
OP v2i = ReadOp(im+k+n2, fp_f);
|
|
|
|
/* (p1,p2) := cmul(w,v2) */
|
|
(void)fp_exec(040, &p1, wr, v2r); /* S7,8 p1 := wr*v2r */
|
|
(void)fp_exec(040, ACCUM, wi, v2i); /* ACCUM := wi*v2i */
|
|
(void)fp_exec(024, &p1, p1, NOP); /* S7,S8 p1 := wr*v2r-wi*v2i ==real(w*v2) */
|
|
(void)fp_exec(040, &p2, wi, v2r); /* S9,10 p2 := wi*v2r */
|
|
(void)fp_exec(040, ACCUM, wr, v2i); /* ACCUM := wr*v2i */
|
|
(void)fp_exec(004, &p2, p2, NOP); /* S9,10 p2 := wi*v2r+wr*v2i ==imag(w*v2) */
|
|
/* v2 := v1 - (p1,p2) */
|
|
(void)fp_exec(020, &p3, v1r, p1); /* v2r := v1r-real(w*v2) */
|
|
(void)fp_exec(020, &p4, v1i, p2); /* v2i := v1i-imag(w*v2) */
|
|
WriteOp(re+k+n2, p3, fp_f); /* write v2r */
|
|
WriteOp(im+k+n2, p4, fp_f); /* write v2i */
|
|
/* v1 := v1 + (p1,p2) */
|
|
(void)fp_exec(0, &p3, v1r, p1); /* v1r := v1r+real(w*v2) */
|
|
(void)fp_exec(0, &p4, v1i, p2); /* v1i := v1i+imag(w*v2) */
|
|
WriteOp(re+k, p3, fp_f); /* write v1r */
|
|
WriteOp(im+k, p4, fp_f); /* write v1i */
|
|
O = 0;
|
|
}
|
|
|
|
|
|
/* helper for bit reversal
|
|
* idx is 0-based already */
|
|
|
|
static void sig_bitrev(uint32 re,uint32 im, uint32 idx, uint32 log2n, int sz)
|
|
{
|
|
uint32 i, org=idx, rev = 0;
|
|
OP v1r,v1i,v2r,v2i;
|
|
|
|
for (i=0; i<log2n; i++) { /* swap bits of idx */
|
|
rev = (rev<<1) | (org & 1); /* into rev */
|
|
org >>= 1;
|
|
}
|
|
|
|
if (rev < idx) return; /* avoid swapping same pair twice in loop */
|
|
|
|
idx *= sz; /* adjust for element size */
|
|
rev *= sz; /* (REAL*4 vs COMPLEX*8) */
|
|
|
|
v1r = ReadOp(re+idx, fp_f); /* read 1st element */
|
|
v1i = ReadOp(im+idx, fp_f);
|
|
v2r = ReadOp(re+rev, fp_f); /* read 2nd element */
|
|
v2i = ReadOp(im+rev, fp_f);
|
|
WriteOp(re+idx, v2r, fp_f); /* swap elements */
|
|
WriteOp(im+idx, v2i, fp_f);
|
|
WriteOp(re+rev, v1r, fp_f);
|
|
WriteOp(im+rev, v1i, fp_f);
|
|
}
|
|
|
|
|
|
/* helper for PRSCR/UNSCR */
|
|
|
|
static OP sig_scadd(uint16 oper,t_bool addh, OP a, OP b)
|
|
{
|
|
OP r;
|
|
static const OP plus_half = { { 0040000, 0000000 } }; /* DEC +0.5 */
|
|
|
|
(void)fp_exec(oper,&r,a,b); /* calculate r := a +/- b */
|
|
if (addh) (void)fp_exec(044,&r,plus_half,NOP); /* if addh set, multiply by 0.5 */
|
|
return r;
|
|
}
|
|
|
|
|
|
/* complex multiply helper */
|
|
|
|
static void sig_cmul(OP *r, OP *i, OP a, OP b, OP c, OP d)
|
|
{
|
|
OP p;
|
|
(void)fp_exec(040, &p , a, c); /* p := ac */
|
|
(void)fp_exec(040, ACCUM, b, d); /* ACCUM := bd */
|
|
(void)fp_exec(024, r, p , NOP); /* real := ac-bd */
|
|
(void)fp_exec(040, &p, a, d); /* p := ad */
|
|
(void)fp_exec(040, ACCUM, b, c); /* ACCUM := bc */
|
|
(void)fp_exec(004, i, p, NOP); /* imag := ad+bc */
|
|
}
|
|
|
|
#endif /* int64 conditional */
|