blob: 1867d6a40e663dadde039d973f80a4c8ec4eef16 [file] [log] [blame] [raw]
/* eclipse_cpu.c: Eclipse CPU simulator
Modified from the original NOVA simulator by Robert Supnik.
Copyright (c) 1998-2012, Charles E Owen
Portions Copyright (c) 1993-2002, Robert M Supnik
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
ROBERT M SUPNIK 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 Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
cpu Eclipse central processor
25-Mar-12 RMS Fixed declarations (Mark Pizzolato)
07-Jun-06 RMS Fixed bug in DIVS (Mark Hittinger)
22-Sep-05 RMS Fixed declarations (Sterling Garwood)
25-Aug-05 RMS Fixed DIVS overflow cases
29-Nov-03 CEO Corrected POPJ and Bit operations bugs
26-Nov-03 CEO Added FPU and PIT devices
20-Feb-03 CEO Corrected several MMPU and CIS bugs
28-Jan-02 RMS Cleaned up compiler warnings
30-Nov-01 RMS Added extended SET/SHOW support
01-Jun-01 RMS Added second terminal, plotter support
26-Apr-01 RMS Added device enable/disable support
The register state for the Eclipse CPU is basically the same as
the NOVA's:
AC[0:3]<0:15> general registers
C carry flag
PC<0:14> program counter
Eclipses with Folating Point Units added these registers:
FPAC[0:3]<0:63> Floating Point Accumulators
FPSR Floating Point Status Register
In addition, certain low-memory locations are reserved for special
purposes:
0: I/O Return Address (from an interrupt)
1: I/O (Interrupt) handler address
2: System Call handler address (used by SYC instruction)
3: Protection Fault handler address
4: VECTOR stack pointer (VCT Instruction)
5: Current Interrupt Priority mask
6: VECTOR stack limit (VCT instruction)
7: VECTOR stack fault address (VCT again)
10: Block Pointer (later models only)
11: Emulation Trap Handler address (microeclipse only)
20-27: Auto-increment locations (not on microeclipse)
30-37: Auto-decrement locations (not on microeclipse)
40: Stack pointer
41: Frame Pointer
42: Stack Limit
43: Stack fault address
44: XOP Origin address
45: Floating point fault address
46: Commercial fault address (not on microeclipse)
47: Reserved, do not use.
Note: While all eclipses share most of the "standard" features,
some models added a few quirks and wrinkles, and other models
dropped some features or modified others. Most DG software
is written for a "standard" Eclipse, and avoids these problem
areas. A general overview:
[subject to major changes as info becomes available!]
Early (e.g. S/100, S/200, C/300) [Front Panel machines]
The first Eclipses had the basic MAP, but certain parts
were kluged, and these were fixed in later MAP designs.
The original mapping hardware was termed MAP for Memory
Allocate and Protection. The later design was termed
MMPU for Memory Mapping and Protection Unit. While
similar in design, the two units are not compatible.
Also, the C version (C for Commercial) of these early
CPUs had a feature called "Commercial Instruction Set"
which contained character manipulation, translation
between commercial-format numeric data and FPU formats,
and an elaborate EDIT instruction. Later models kept
only the character manipulation part of this and called
the feature the "Character Instruction Set", leading to
confusion because the initials of both are CIS. ARDOS
is the only DG operating system to support the older
MAP. ZRDOS uses the MMPU, and AOS supports only MMPU.
Middle (e.g. S/130, C/150, S/230, C/330) [Front Panel]
These are close to a "Standard". They have the newer,
fixed MMPU. Support for the PIT (Programmed Interval
Timer. The Commercial (not character) instruction set
and FPU are optional. (CIS standard on C models)
Late (C/350, M/600: [Panel]; S/140, S/280 [Virtual Console])
All features of the Middle period are included, plus:
These late Eclipses added a few MMPU wrinkles all their
own, included support for user maps C and D. Character
instruction set is standard, FPU optional. Also, support
for the BMC device.
MicroEclipse-based (S/20, S/120, Desktops) [Virtual cons.]
All features of the Late period, in general, plus:
Microeclipses dropped support for the auto increment
and decrement locations at 20-37. They also added
support for invalid instruction traps thru location 11.
The Desktops have an interface to the "Attached Processor",
an 8086, at device code 6. Also, some new CPU device
features to read states info. The Character Instruction
set and FPU are standard on all models.
The Eclipse instruction set is an elaboration of the NOVA's. The basic
NOVA set is implemented in it's entireity, plus many new Eclipse
instructions are added. Since in theory every possible 16-bit
combination is a NOVA instruction, the Eclipse commands are carved
out of the NOVA set by using the Operate format with the no-load bit
set to 1 and the skip bits set to 000. Since this combination is
in effect a no-op on the NOVA, it was rarely or never used. The
other bits are used to form Eclipse instructions, which have no
other common format. To see the instructions, refer to the Eclipse
section of the instruction decode logic in sim_instr() below. All
Eclipse instructions are checked first, so in case of conflict in
bit patterns, the Eclipse one is executed over the corresponding
NOVA pattern. A bizarre exception is LEF mode...which implements
an instruction called Load Effective Address by taking over the
Nova I/O format when the LEF mode bit is set and the processor is
executing in mapped mode.
The following discussion talks about NOVA instructions which are
Eclipse instructions also.
The NOVA has three instruction formats: memory reference, I/O transfer,
and operate. The memory reference format is:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 0| op | AC |in| mode| displacement | memory reference
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
<0:4> mnemonic action
00000 JMP PC = MA
00001 JMS AC3 = PC, PC = MA
00010 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0
00011 DSZ M[MA] = M[MA] - 1, skip if M[MA] == 0
001'n LDA ACn = M[MA]
010'n STA M[MA] = ACn
<5:7> mode action
000 page zero direct MA = zext (IR<8:15>)
001 PC relative direct MA = PC + sext (IR<8:15>)
010 AC2 relative direct MA = AC2 + sext (IR<8:15>)
011 AC3 relative direct MA = AC3 + sext (IR<8:15>)
100 page zero indirect MA = M[zext (IR<8:15>)]
101 PC relative dinirect MA = M[PC + sext (IR<8:15>)]
110 AC2 relative indirect MA = M[AC2 + sext (IR<8:15>)]
111 AC3 relative indirect MA = M[AC3 + sext (IR<8:15>)]
Memory reference instructions can access an address space of 32K words.
An instruction can directly reference the first 256 words of memory
(called page zero), as well as 256 words relative to the PC, AC2, or
AC3; it can indirectly access all 32K words. If an indirect address
is in locations 00020-00027, the indirect address is incremented and
rewritten to memory before use; if in 00030-00037, decremented and
rewritten.
The I/O transfer format is:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 0 1 1| AC | opcode |pulse| device | I/O transfer
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
The IOT instruction sends the opcode, pulse, and specified AC to the
specified I/O device. The device may accept data, provide data,
initiate or cancel operations, or skip on status.
The operate format is:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 1|srcAC|dstAC| opcode |shift|carry|nl| skip | operate
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
\______/ \___/ \___/ | | | |
| | | | | | +--- reverse skip sense
| | | | | +--- skip if C == 0
| | | | +--- skip if result == 0
| | | +--- don't load result
| | +--- carry in (load as is,
| | set to Zero,
| | set to One,
| | load Complement)
| +--- shift (none,
| left one,
| right one,
| byte swap)
+--- operation (complement,
negate,
move,
increment,
add complement,
subtract,
add,
and)
The operate instruction can be microprogrammed to perform operations
on the source and destination AC's and the Carry flag.
This routine is the instruction decode routine for the NOVA.
It is called from the simulator control program to execute
instructions in simulated memory, starting at the simulated PC.
It runs until 'reason' is set non-zero.
General notes:
1. Reasons to stop. The simulator can be stopped by:
HALT instruction
breakpoint encountered
infinite indirection loop
unknown I/O device and STOP_DEV flag set
I/O error in I/O simulator
2. Interrupts. Interrupts are maintained by four parallel variables:
dev_done device done flags
dev_disable device interrupt disable flags
dev_busy device busy flags
int_req interrupt requests
In addition, int_req contains the interrupt enable and ION pending
flags. If ION and ION pending are set, and at least one interrupt
request is pending, then an interrupt occurs. Note that the 16b PIO
mask must be mapped to the simulator's device bit mapping.
3. Non-existent memory. On the NOVA, reads to non-existent memory
return zero, and writes are ignored. In the simulator, the
largest possible memory is instantiated and initialized to zero.
Thus, only writes need be checked against actual memory size.
4. Adding I/O devices. These modules must be modified:
eclipse_defs.h add interrupt request definition
eclipse_cpu.c add IOT mask, PI mask, and routine to dev_table
eclipse_sys.c add pointer to data structures to sim_devices
*/
/*---------------------------------------------------------------------------
** ECLIPSE Debugging Facilities
**
** These options are designed to find hard-to-locate flaky bugs by
** providing special error checking and logging.
**
** All are controlled by depositing a value into the DEBUG register.
** A value of zero means no special debugging facilities are turned on.
** This is the default. Debugging invokes a performance hit! Use only
** when necessary.
**
** Debugging means logging information to a file, or to a buffer in
** memory from whence it can be dumped to a file.
**
** 1XXXXX = Log all instructions executed to file "trace.log".
** **CAUTION**: This means the CPU will run SLOWLY and
** the resulting trace.log file will be HUGE. We're talking
** about a megabyte for each 5 seconds or less of wall clock
** time, depending on the speed of your CPU. Note: In this
** mode, interrupts are logged when they are received also.
**
** Note: when detailed logging is off, the last 4096 or so
** instructions executed are saved in a memory buffer, and
** when the sim stops, the "show" command can write this
** history information to the file "history.log". This only
** works if the DEBUG register is non-zero however, because
** of the performance hit even this recording makes. To
** dump history, enter the command "show cpu history", with
** the file "history" spelled correctly and lower case.
**
** XXXXDD = Log all I/O instructions to or from device number
** DD. Log is written to "trace.log", regardless of the
** setting of the instruction trace flag (1XXXXX). If both
** are on, the device traces will be interpersed with the
** instruction traces -- very useful sometimes.
**
** XXX1DD = Device Break. Does a breakpoint in any I/O to
** device DD. Useful, say when a diagnostic gives an
** error message - a device break on 11 (TTO) will stop
** as soon as the error message appears, making the
** trace log much shorter to track back on.
**
** X4XXXX = When this bit is on, the sim will stop if it sees
** an invalid instruction. When DEBUG is zero, any such
** instruction is no-oped with no warning. When DEBUG is
** non-zero, but this bit is 0, a warning will be displayed
** but execution will continue.
**
** X2XXXX = LEF break. When A LEF instruction is executed in
** mapped user space, the sim does a breakpoint right after
** executing the instruction.
**
** Whenever the DEBUG register is non-zero, special error checking
** is enabled in the sim. This will stop the sim automatically
** when a likely error occurs, such as:
**
** 1. Any execution that reaches, or will reach, location 00000.
** 2. Any I/O to device 00
** 3. An interrupt from device 00.
** 4. An invalid instruction (stop is optional)
**
** DCHAR Register: Whenever this is non-zero, a test is made on every
** character output to the TTO device (master console). If the character
** output to that device matches this register, the CPU will break.
**
** Of course, the standard BREAK register is available for breakpoints
** as in all the sims based on this standard.
--------------------------------------------------------------------------*/
#include "nova_defs.h"
#define UNIT_V_MICRO (UNIT_V_UF) /* Microeclipse? */
#define UNIT_V_17B (UNIT_V_UF) /* 17 bit MAP */
#define UNIT_V_UP (UNIT_V_UF) /* FPU Enabled */
#define UNIT_V_MSIZE (UNIT_V_UF+1) /* dummy mask */
#define UNIT_MICRO (1 << UNIT_V_MICRO)
#define UNIT_17B (1 << UNIT_V_17B)
#define UNIT_UP (1 << UNIT_V_UP)
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
uint16 M[MAXMEMSIZE] = { 0 }; /* memory */
int32 AC[4] = { 0 }; /* accumulators */
int32 C = 0; /* carry flag */
int32 saved_PC = 0; /* program counter */
int32 SR = 0; /* switch register */
int32 dev_done = 0; /* device done flags */
int32 dev_busy = 0; /* device busy flags */
int32 dev_disable = 0; /* int disable flags */
int32 iot_enb = -1; /* IOT enables */
int32 int_req = 0; /* interrupt requests */
int32 pimask = 0; /* priority int mask */
int32 pwr_low = 0; /* power fail flag */
int32 ind_max = 15; /* iadr nest limit */
int32 stop_dev = 0; /* stop on ill dev */
int32 old_PC = 0; /* previous PC */
int32 model = 140; /* Model of Eclipse */
int32 speed = 0; /* Delay for each instruction */
int32 XCT_mode = 0; /* 1 if XCT mode */
int32 XCT_inst = 0; /* XCT instruction */
int32 PPC = -1;
int32 AMASK = 077777;
struct ndev dev_table[64]; /* dispatch table */
/* Instruction history buffer */
#define HISTMAX 4096
int32 hnext = 0; /* # of current entry */
int32 hwrap = 0; /* 1 if wrapped */
int32 hmax = HISTMAX; /* Maximum entries b4 wrap */
uint16 hpc[HISTMAX];
uint16 hinst[HISTMAX];
uint16 hinst2[HISTMAX];
uint16 hac0[HISTMAX];
uint16 hac1[HISTMAX];
uint16 hac2[HISTMAX];
uint16 hac3[HISTMAX];
unsigned short hflags[HISTMAX];
/* Flags: 0x01 - carry bit
0x02 - int enabled
0x04 - user map a
0x08 - user map b
0x10 - user map c
0x20 - user map d
0x40 - LEF mode was on
0x80 - this is an int, not an inst.
hpc is return addr
hinst is int_req
hac0 is device
hac1 is int addr
*/
/* the Eclipse MAP unit: This unit is standard in all Eclipse processors
except for the "original" Eclipses, the S/100, S/200, and C/300. These
use a different and more elaborate MMPU that is not compatible with
the one simulated here. All subsequent Eclipses, from the S/130 on up
to the last models S/280 and C/380 use the map simulated here, including
the MicroEclipses. There are model-dependent quirks. That's why we
have to MODEL register.
The programming of the MMPU can be found in the LMP instruction, below,
and in the instructions directed to DEV_MAP.
There are two user maps, called A and B, and four data channel maps,
A thru D. They can be enabled/disabled separately. Some models have
two extra user maps, C and D. These are supported where apporpriate.
*/
#define PAGEMASK 01777 /* Largest physical page possible */
#define MAPMASK 0101777 /* Valid page bits in map */
#define INVALID 0101777 /* Mask indicating an invalid page */
int32 MapStat = 0; /* Map status register */
int32 Inhibit = 0; /* !0=inhibit interrupts : */
/* 1 = single cycle inhibit */
/* 2 = inhibit until indirection */
/* 3 = inhibit next instruction only */
int32 Enable = 0; /* User map to activate 1=A 2=B */
int32 Usermap = 0; /* Active Map? 0=supvr mode, 1=user A, 2 = user B */
int32 Map[8][32]; /* The actual MAPs 0=dch A, 1=A, 2=B, 3-5=dchB-D 6-7 User C-D */
int32 Map31 = 037; /* Map for block 31 in supervisor mode */
int32 SingleCycle = 0; /* Map one LDA/STA */
int32 Check = 0; /* Page Check Register */
int32 Fault = 0; /* Fault register */
int32 MapInit = 0; /* 1 when map initialized */
int32 MapIntMode = 0; /* Save of map user mode when int occurs */
/* The Eclipse Floating Point Unit: This unit is optional on all Eclipse
models.
*/
int32 FPSR = 0; /* 32-bit FPU Status Register */
t_int64 FPAC[4] = { 0,0,0,0 }; /* 4 64-bit Accumulators */
int32 FPFault = 0; /* Save Fault State */
/* Definitions for internal floating point arithmetic */
typedef struct _SHORT_FLOAT {
int32 short_fract; /* Fraction */
short expo; /* Exponent + 64 */
uint8 sign; /* Sign */
} SHORT_FLOAT;
typedef struct _LONG_FLOAT {
t_int64 long_fract; /* Fraction */
short expo; /* Exponent + 64 */
uint8 sign; /* Sign */
} LONG_FLOAT;
LONG_FLOAT dfl,dfl2; /* Double Precision Work Fields */
SHORT_FLOAT sfl,sfl2; /* Single Precision Work Fields */
t_int64 tempfp, holdfp; /* Working area for FPAC */
int shift,m3;
t_int64 lsfract;
void get_sf(SHORT_FLOAT *fl, t_int64 *fpr);
void store_sf(SHORT_FLOAT *fl, t_int64 *fpr);
void get_lf(LONG_FLOAT *fl, t_int64 *fpr);
void store_lf(LONG_FLOAT *fl, t_int64 *fpr);
int normal_sf (SHORT_FLOAT *fl);
int normal_lf (LONG_FLOAT *fl);
int overflow_sf(SHORT_FLOAT *fl);
int overflow_lf(LONG_FLOAT *fl);
int underflow_sf(SHORT_FLOAT *fl);
int underflow_lf(LONG_FLOAT *fl);
int significance_sf(SHORT_FLOAT *fl);
int significance_lf(LONG_FLOAT *fl);
int add_sf(SHORT_FLOAT *fl, SHORT_FLOAT *add_f1, int normal);
int add_lf(LONG_FLOAT *fl, LONG_FLOAT *add_fl, int normal);
int mul_sf(SHORT_FLOAT *fl, SHORT_FLOAT *mul_fl);
int mul_lf(LONG_FLOAT *fl, LONG_FLOAT *mul_fl);
int div_sf(SHORT_FLOAT *fl, SHORT_FLOAT *div_fl);
int div_lf(LONG_FLOAT *fl, LONG_FLOAT *div_fl);
/* Special Debugging Info */
int32 Debug_Flags = 0; /* Debug register - selects debug features */
int32 Debug_Char = 0; /* Debug Character Register */
int32 Tron = 0; /* For trace files */
FILE *Trace;
t_stat reason;
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
t_stat cpu_reset (DEVICE *dptr);
t_stat cpu_boot (int32 unitno, DEVICE *dptr);
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat Debug_Dump (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc);
t_stat map_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat map_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
t_stat map_reset (DEVICE *dptr);
t_stat map_svc (UNIT *uptr);
t_stat fpu_svc (UNIT *uptr);
int32 GetMap(int32 addr);
int32 PutMap(int32 addr, int32 data);
int32 Debug_Entry(int32 PC, int32 inst, int32 inst2, int32 AC0, int32 AC1, int32 AC2, int32 AC3, int32 flags);
t_stat build_devtab (void);
/* CPU data structures
cpu_dev CPU device descriptor
cpu_unit CPU unit descriptor
cpu_reg CPU register list
cpu_mod CPU modifiers list
*/
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) };
REG cpu_reg[] = {
{ ORDATA (PC, saved_PC, 15) },
{ ORDATA (AC0, AC[0], 16) },
{ ORDATA (AC1, AC[1], 16) },
{ ORDATA (AC2, AC[2], 16) },
{ ORDATA (AC3, AC[3], 16) },
{ FLDATA (C, C, 16) },
{ ORDATA (SR, SR, 16) },
{ ORDATA (PI, pimask, 16) },
{ FLDATA (ION, int_req, INT_V_ION) },
{ FLDATA (ION_DELAY, int_req, INT_V_NO_ION_PENDING) },
{ FLDATA (PWR, pwr_low, 0) },
{ ORDATA (INT, int_req, INT_V_ION+1), REG_RO },
{ ORDATA (BUSY, dev_busy, INT_V_ION+1), REG_RO },
{ ORDATA (DONE, dev_done, INT_V_ION+1), REG_RO },
{ ORDATA (DISABLE, dev_disable, INT_V_ION+1), REG_RO },
{ FLDATA (STOP_DEV, stop_dev, 0) },
{ DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT },
{ ORDATA (DEBUG, Debug_Flags, 16) },
{ ORDATA (DCHAR, Debug_Char, 16) },
{ DRDATA (MODEL, model, 16) },
{ DRDATA (SPEED, speed, 16) },
{ ORDATA (WRU, sim_int_char, 8) },
{ NULL }
};
MTAB cpu_mod[] = {
{ UNIT_MICRO, UNIT_MICRO, "MICRO", "MICRO", NULL },
{ UNIT_MICRO, 0, "STD", "STD", NULL },
{ UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
{ UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
{ UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size },
{ UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
{ UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size },
{ UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
{ UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size },
{ UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
{ UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
{ UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
{ UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size },
{ UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size },
{ UNIT_MSIZE, 1048576, NULL, "1024K", &cpu_set_size },
{ UNIT_MSIZE, 0, NULL, "DUMP", &Debug_Dump },
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", NULL,
NULL, &Dump_History },
{ 0 }
};
DEVICE cpu_dev = {
"CPU", &cpu_unit, cpu_reg, cpu_mod,
1, 8, 17, 1, 8, 16,
&cpu_ex, &cpu_dep, &cpu_reset,
&cpu_boot, NULL, NULL
};
/* MAP data structures
map_dev MAP device descriptor
map_unit MAP unit descriptor
map_reg MAP register list
map_mod MAP modifiers list
*/
UNIT map_unit = { UDATA (&map_svc, UNIT_17B, MAXMEMSIZE) };
REG map_reg[] = {
{ ORDATA (STATUS, MapStat, 16) },
{ ORDATA (ENABLE, Enable, 16) },
{ ORDATA (IINHIB, Inhibit, 16) },
{ ORDATA (ACTIVE, Usermap, 16) },
{ ORDATA (MAP31, Map31, 16) },
{ ORDATA (CYCLE, SingleCycle, 16) },
{ ORDATA (CHECK, Check, 16) },
{ ORDATA (FAULT, Fault, 16) },
{ NULL }
};
MTAB map_mod[] = {
{ UNIT_17B, UNIT_17B, "17bit", "17B", NULL },
{ UNIT_17B, 0, "19bit", "19B", NULL },
{ 0 }
};
DEVICE map_dev = {
"MAP", &map_unit, map_reg, map_mod,
1, 8, 17, 1, 8, 16,
&map_ex, &map_dep, NULL,
NULL, NULL, NULL
};
/* FPU data structures
fpu_dev MAP device descriptor
fpu_unit MAP unit descriptor
fpu_reg MAP register list
fpu_mod MAP modifiers list
*/
UNIT fpu_unit = { UDATA (&fpu_svc, UNIT_UP, MAXMEMSIZE) };
REG fpu_reg[] = {
{ ORDATA (STATUS, FPSR, 32) },
{ ORDATA (FPAC0, FPAC[0], 64) },
{ ORDATA (FPAC1, FPAC[1], 64) },
{ ORDATA (FPAC2, FPAC[2], 64) },
{ ORDATA (FPAC3, FPAC[3], 64) },
{ ORDATA (FAULT, FPFault, 32) },
{ NULL }
};
MTAB fpu_mod[] = {
{ UNIT_UP, UNIT_UP, "Enabled (UP)", "UP", NULL },
{ UNIT_UP, 0, "Disabled (DOWN)", "DOWN", NULL },
{ 0 }
};
DEVICE fpu_dev = {
"FPU", &fpu_unit, fpu_reg, fpu_mod,
1, 16, 17, 1, 16, 16,
NULL, NULL, NULL,
NULL, NULL, NULL
};
/* ---- Programmable Interval Timer Device ----------- */
int32 pit_time = 100;
int32 pit_tps = 10000; /* ticks per sec */
int32 pit_adj = 20; /* tmxr adjust */
int32 pit_poll = 16000; /* tmxr poll */
int32 pit_initial = 0; /* initial counter reg */
int32 pit_counter = 0; /* Counter */
int32 pit_flag = 0; /* Initial setting flag */
int32 pit (int32 pulse, int32 code, int32 AC);
t_stat pit_svc (UNIT *uptr);
t_stat pit_reset (DEVICE *dptr);
/* PIT data structures
pit_dev device descriptor
pit_unit unit descriptor
pit_reg register list
*/
DIB pit_dib = { DEV_PIT, INT_PIT, PI_PIT, &pit };
UNIT pit_unit = { UDATA (&pit_svc, 0, 0) };
REG pit_reg[] = {
{ ORDATA (INIT, pit_initial, 16) },
{ ORDATA (COUNT, pit_counter, 16) },
{ FLDATA (BUSY, dev_busy, INT_V_PIT) },
{ FLDATA (DONE, dev_done, INT_V_PIT) },
{ FLDATA (DISABLE, dev_disable, INT_V_PIT) },
{ FLDATA (INT, int_req, INT_V_PIT) },
{ DRDATA (TIME0, pit_time, 24), REG_NZ + PV_LEFT },
{ NULL }
};
DEVICE pit_dev = {
"PIT", &pit_unit, pit_reg, NULL,
1, 0, 0, 0, 0, 0,
NULL, NULL, &pit_reset,
NULL, NULL, NULL,
&pit_dib, 0
};
t_stat sim_instr (void)
{
register int32 PC, IR, i, t, MA, j, k, tac;
register uint32 mddata, uAC0, uAC1, uAC2, uAC3;
int16 sAC0, sAC1, sAC2;
int32 sddata, mi1, mi2, fpnum32;
t_int64 fpnum, expon;
t_value simeval[20];
void mask_out (int32 mask);
/* char debstr[128]; */
/* char debadd[64]; */
char debmap[4], debion[4];
int debcar, iodev, iodata, debflags;
int32 DisMap, debpc;
/* int32 sp, sl; */
int cmdptr, cmsptr, cmopt, cmptr;
int16 cmslen, cmdlen;
int tabaddr, tabptr;
int32 effective(int32 PC, int32 index, int32 disp);
int32 indirect(int32 d);
int32 LEFmode(int32 PC, int32 index, int32 disp, int32 indirect);
int32 LoadMap(int32 w);
int32 Bytepointer(int32 PC, int32 index);
int32 unimp(int32 PC);
int32 pushrtn(int32 pc);
/* Restore register state */
if (build_devtab () != SCPE_OK) return SCPE_IERR; /* build dispatch */
PC = saved_PC & AMASK; /* load local PC */
C = C & 0200000;
mask_out (pimask); /* reset int system */
reason = 0;
if (MapInit == 0) {
MapInit = 1;
for (mi1 = 0; mi1 < 6; mi1++) { /* Initialize MAPs */
for (mi2 = 0; mi2 < 32; mi2++) {
Map[mi1][mi2] = mi2;
}
}
}
/* Main instruction fetch/decode loop */
while (reason == 0) { /* loop until halted */
if (sim_interval <= 0) { /* check clock queue */
/* make sure all useful state is in simh registers while processing events */
saved_PC = PC;
if ((reason = sim_process_event ()))
break;
}
//if (speed > 0) for (i = 0; i < speed; i++) { j = 0; }
if (Fault) { /* Check MAP fault */
Usermap = 0; /* YES: shutdown map */
MapStat &= ~01; /* Disable MMPU */
if (Fault & 0100000/*!!!*/) /* If it was validity, or WP */
MapStat &= ~0170; /* Reset other checkbits */
MapStat |= Fault & 077777; /* Put in fault code */
Fault = 0; /* Reset fault code */
t = (GetMap(040) + 1) & AMASK; /* Push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, (PC & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
int_req = int_req & ~INT_ION; /* Disable interrupts */
PC = indirect(M[003]); /* JMP to loc 3 */
continue;
}
if (FPSR & 0xF8000000) { /* FPU Fault? */
if (!(FPSR & 0x78000000)) { /* If error bit on ... */
FPSR &= 0x00FFFFFF; /* ...but no error, clear it */
} else { /* ELSE a real error: */
FPSR |= 0x80000000; /* Turn error bit on */
if (FPSR & 0x04000000) { /* Trap enabled ? */
FPFault = FPSR; /* Save fault */
FPSR &= 0xFBFFFFFF; /* Clear Trap Enable */
}
}
}
if (int_req > INT_PENDING && !Inhibit) { /* interrupt? */
int_req = int_req & ~INT_ION;
MapIntMode = MapStat; /* Save Status as it was */
Usermap = 0; /* Inhibit MAP */
MapStat &= ~1; /* Disable user map */
if (XCT_mode) {
M[0] = PC - 1; /* If XCT mode rtn to XCT */
XCT_mode = 0; /* turn off mode */
} else {
M[0] = PC; /* Save Return Address */
}
old_PC = PC;
MA = M[1];
for (i = 0; i < ind_max * 2; i++) { /* count indirects */
if ((MA & 0100000) == 0) break;
if ((MA & 077770) == 020)
MA = (M[MA & AMASK] = (M[MA & AMASK] + 1) & 0177777);
else if ((MA & 077770) == 030)
MA = (M[MA & AMASK] = (M[MA & AMASK] - 1) & 0177777);
else MA = M[MA & AMASK];
}
if (i >= (ind_max-1)) {
if ((MapStat & 010) && Usermap) {
Fault = 04000; /* Map fault if IND prot */
continue;
} else {
reason = STOP_IND_INT;
break;
}
}
if (Debug_Flags) {
iodev = 0;
iodata = int_req & (-int_req);
for (i = DEV_LOW; i <= DEV_HIGH; i++) {
if (iodata & dev_table[i].mask) {
iodev = i;
break;
}
}
if (iodev == 0) {
printf("\n<<Interrupt to device 0!>>\n");
reason = STOP_IBKPT;
}
if (Debug_Flags & 0100000) {
fprintf(Trace, "--------- Interrupt %o (%o) to %6o ---------\n", int_req, iodev, MA);
} else {
Debug_Entry(PC, int_req, 0, iodev, MA, 0, 0, 0x80);
}
}
PC = MA;
} /* end interrupt */
if (Inhibit != 0) { /* Handle 1-instruction inhibit sequence */
if (Inhibit == 3) /* Used by SYC instruction */
Inhibit = 4;
if (Inhibit == 4)
Inhibit = 0;
}
if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
reason = STOP_IBKPT; /* stop simulation */
break;
}
if ((PC < 1 || PC > 077777) && Debug_Flags) {
if (PPC != -1) { /* Don't break on 1st instruction */
printf("\n<<Invalid PC=%o from %o>>\n\r", PC, PPC);
reason = STOP_IBKPT;
break;
}
}
PPC = PC;
if (Debug_Flags) {
if (!Tron) {
Tron = 1;
Trace = fopen("trace.log", "w");
}
strcpy(debmap, " ");
strcpy(debion, " ");
debcar = 0;
if (C) debcar = 1;
if (Usermap == 1) strcpy(debmap, "A");
if (Usermap == 2) strcpy(debmap, "B");
if (Usermap == 5) strcpy(debmap, "C");
if (Usermap == 6) strcpy(debmap, "D");
if (int_req & INT_ION) strcpy(debion, "I");
if (XCT_mode == 0) {
debpc = PC;
simeval[0] = GetMap(PC);
simeval[1] = GetMap(PC+1);
} else {
debpc = 0177777;
simeval[0] = XCT_inst;
simeval[1] = 0;
}
if (Debug_Flags & 0100000) {
fprintf(Trace, "%s%s%06o acs: %06o %06o %06o %06o %01o ",
debion, debmap, debpc, AC[0], AC[1], AC[2], AC[3], debcar);
fprint_sym (Trace, debpc, simeval, NULL, SWMASK('M'));
fprintf(Trace, "\n");
} else {
debflags = 0;
if (C) debflags |= 0x01;
if (int_req & INT_ION) debflags |= 0x02;
if (Usermap == 1) debflags |= 0x04;
if (Usermap == 2) debflags |= 0x08;
if (Usermap == 3) debflags |= 0x10;
if (Usermap == 4) debflags |= 0x20;
Debug_Entry(debpc, (int32)simeval[0], (int32)simeval[1], AC[0], AC[1], AC[2], AC[3], debflags);
}
}
if (XCT_mode == 0) { /* XCT mode? */
IR = GetMap(PC); /* No: fetch instr */
if (Fault) continue; /* Give up if fault */
PC = (PC + 1) & AMASK; /* bump PC */
} else {
IR = XCT_inst; /* Yes: Get inst to XCT */
XCT_mode = 0; /* Go back to normal mode */
}
int_req = int_req | INT_NO_ION_PENDING; /* clear ION delay */
sim_interval = sim_interval - 1;
t = IR >> 11; /* prepare to decode */
/* ---------------- BEGIN Eclipse modification --------------------- */
/* Eclipse instruction set. These instructions are checked for
before any of the NOVA ones. Eclipse instructions do not
correspond to any patterns, other than bit 0 being 1 and
the last 4 bits are 1000. Words which are not Eclipse
instructions will be interpreted as Nova instructions. */
/* Important Note: The order of the if statements is important.
Frequently executed instructions should come first, to enhance
the speed of the simulation.
*/
if ((IR & 0100017) == 0100010) { /* This pattern for all */
/* Eclipse instructions */
/****************************************************************/
/* This is the standard Eclipse instruction set */
/****************************************************************/
/* Byte operations */
if ((IR & 0103777) == 0102710) { /* LDB: Load Byte */
i = (IR >> 13) & 03;
MA = (AC[i] >> 1) & AMASK;
j = (IR >> 11) & 03;
if (AC[i] & 01) {
AC[j] = GetMap(MA) & 0377;
} else {
AC[j] = (GetMap(MA) >> 8) & 0377;
}
continue;
}
if ((IR & 0103777) == 0103010) { /* STB: Store Byte */
i = (IR >> 13) & 03;
MA = (AC[i] >> 1);
j = (IR >> 11) & 03;
t = GetMap(MA);
if (AC[i] & 01) {
t &= 0177400;
t |= (AC[j] & 0377);
PutMap(MA, t);
} else {
t &= 0377;
t |= (AC[j] & 0377) << 8;
PutMap(MA, t);
}
continue;
}
/* Fixed-point arithmetic - loads & saves */
if ((IR & 0162377) == 0122070) { /* ELDA: Extended LDA */
i = (IR >> 11) & 3;
t = GetMap(PC);
if (SingleCycle) Usermap = SingleCycle;
AC[i] = GetMap(effective(PC, (IR >> 8) & 3, t));
if (SingleCycle) {
Usermap = SingleCycle = 0;
if (Inhibit == 1) Inhibit = 3;
MapStat |= 02000;
MapStat &= 0177776;
}
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0162377) == 0142070) { /* ESTA: Extended STA */
i = (IR >> 11) & 3;
t = GetMap(PC);
if (SingleCycle) Usermap = SingleCycle;
PutMap((effective(PC, (IR >> 8) & 3, t)), AC[i]);
if (SingleCycle) {
Usermap = SingleCycle = 0;
if (Inhibit == 1) Inhibit = 3;
MapStat |= 02000;
MapStat &= 0177776;
}
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0100010) { /* ADI: Add Immediate */
t = (IR >> 11) & 3;
AC[t] = (AC[t] + ((IR >> 13) & 3) + 1) & 0xffff;
continue;
}
if ((IR & 0103777) == 0100110) { /* SBI: Subtract Immediate */
t = (IR >> 11) & 3;
AC[t] = (AC[t] - (((IR >> 13) & 3) + 1)) & 0xffff;
continue;
}
if ((IR & 0163777) == 0163770) { /* ADDI: Extended Add Immed. */
t = (IR >> 11) & 3;
i = GetMap(PC);
PC = (PC + 1) & AMASK;
AC[t] = (AC[t] + i) & 0xffff;
continue;
}
if ((IR & 0103777) == 0100710) { /* XCH: Exchange Accumulators */
t = AC[(IR >> 11) & 3];
AC[(IR >> 11) & 3] = AC[(IR >> 13) & 3];
AC[(IR >> 13) & 3] = t;
continue;
}
if ((IR & 0162377) == 0162070) { /* ELEF: Load Effective Addr */
t = GetMap(PC);
AC[(IR >> 11) & 3] = effective(PC, (IR >> 8) & 3, t);
PC = (PC + 1) & AMASK;
continue;
}
/* Logical operations */
if ((IR & 0163777) == 0143770) { /* ANDI: And Immediate */
AC[(IR >> 11) & 3] &= GetMap(PC);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0163777) == 0103770) { /* IORI: Inclusive Or Immed */
AC[(IR >> 11) & 3] |= GetMap(PC);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0163777) == 0123770) { /* XORI: Exclusive Or Immed */
AC[(IR >> 11) & 3] ^= GetMap(PC);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0100410) { /* IOR: Inclusive Or */
AC[(IR >> 11) & 3] |= AC[(IR >> 13) & 3];
continue;
}
if ((IR & 0103777) == 0100510) { /* XOR: Exclusive Or */
AC[(IR >> 11) & 3] ^= AC[(IR >> 13) & 3];
continue;
}
if ((IR & 0103777) == 0100610) { /* ANC: And with complemented src */
AC[(IR >> 11) & 3] &= ~(AC[(IR >> 13) & 3]);
continue;
}
/* Shift operations */
if ((IR & 0103777) == 0101210) { /* LSH: Logical Shift */
register int16 sh;
sh = AC[(IR >> 13) & 3] & 0377;
i = (IR >> 11) & 3;
if (sh & 0200) {
sh = ~sh + 1;
AC[i] = AC[i] >> sh;
} else {
AC[i] = AC[i] << sh;
}
if (sh > 15) AC[i] = 0;
AC[i] &= 0xffff;
continue;
}
if ((IR & 0103777) == 0101310) { /* DLSH: Double logical shift */
register int16 sh;
sh = AC[(IR >> 13) & 3] & 0377;
i = (IR >> 11) & 3;
uAC0 = AC[i] << 16;
j = i + 1;
if (j == 4) j = 0;
uAC0 |= AC[j];
if (sh & 0200) {
sh = (~sh + 1) & 0377;
if (sh < 32)
uAC0 = uAC0 >> sh;
} else {
if (sh < 32)
uAC0 = uAC0 << sh;
}
if (sh > 31) uAC0 = 0;
AC[i] = (uAC0 >> 16) & 0xffff;
AC[j] = uAC0 & 0xffff;
continue;
}
if ((IR & 0103777) == 0101410) { /* HXL: Hex shift left */
t = ((IR >> 13) & 3) + 1;
i = (IR >> 11) & 3;
AC[i] = AC[i] << (t * 4);
AC[i] &= 0xffff;
continue;
}
if ((IR & 0103777) == 0101510) { /* HXR: Hex shift right */
t = ((IR >> 13) & 3) + 1;
i = (IR >> 11) & 3;
AC[i] = AC[i] >> (t * 4);
AC[i] &= 0xffff;
continue;
}
if ((IR & 0103777) == 0101610) { /* DHXL: Double Hex shift left */
t = ((IR >> 13) & 3) + 1;
i = (IR >> 11) & 3;
j = i + 1;
if (j == 4) j = 0;
uAC0 = AC[i] << 16;
uAC0 |= AC[j];
uAC0 = uAC0 << ((t * 4) & 0177);
AC[i] = (uAC0 >> 16) & 0xffff;
AC[j] = uAC0 & 0xffff;
continue;
}
if ((IR & 0103777) == 0101710) { /* DHXR: Double Hex shift right */
t = ((IR >> 13) & 3) + 1;
i = (IR >> 11) & 3;
j = i + 1;
if (j == 4) j = 0;
uAC0 = AC[i] << 16;
uAC0 |= AC[j];
uAC0 = uAC0 >> ((t * 4) & 0177);
AC[i] = (uAC0 >> 16) & 0xffff;
AC[j] = uAC0 & 0xffff;
continue;
}
/* Bit operations */
if ((IR & 0103777) == 0102010) { /* BTO: Set bit to one */
i = (IR >> 11) & 3;
j = (IR >> 13) & 3;
if (i != j) {
k = (AC[i] >> 4) & AMASK;
if ((AC[j] + k) & 0100000)
t = 1;
//AOS MA = indirect(AC[j] + k);
MA = (AC[j] + k) & AMASK;
} else {
MA = (AC[i] >> 4) & AMASK;
}
t = AC[i] & 017;
t = GetMap(MA) | (0100000 >> t);
PutMap(MA, t);
continue;
}
if ((IR & 0103777) == 0102110) { /* BTZ: Set bit to zero */
i = (IR >> 11) & 3;
j = (IR >> 13) & 3;
if (i != j) {
k = (AC[i] >> 4) & AMASK;
if ((AC[j] + k) & 0100000)
t = 1;
//AOS MA = indirect(AC[j] + k);
MA = (AC[j] + k) & AMASK;
} else {
MA = (AC[j] >> 4) & AMASK;
}
t = AC[i] & 017;
t = GetMap(MA) & ~(0100000 >> t);
PutMap(MA, t);
continue;
}
if ((IR & 0103777) == 0102210) { /* SZB: Skip on zero bit */
i = (IR >> 11) & 3;
j = (IR >> 13) & 3;
if (i != j) {
k = (AC[i] >> 4) & AMASK;
if ((AC[j] + k) & 0100000)
t = 1;
MA = indirect(AC[j] + k);
// MA = (AC[j] + k) & AMASK;
} else {
MA = (AC[i] >> 4) & AMASK;
}
t = GetMap(MA) << (AC[i] & 017);
if (!(t & 0100000)) PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0102770) { /* SNB: Skip on non-zero bit */
i = (IR >> 11) & 3;
j = (IR >> 13) & 3;
if (i != j) {
k = (AC[i] >> 4) & AMASK;
if ((AC[j] + k) & 0100000)
t = 1;
MA = indirect(AC[j] + k);
// MA = (AC[j] + k) & AMASK;
} else {
MA = (AC[j] >> 4) & AMASK;
}
t = GetMap(MA) << (AC[i] & 017);
if (t & 0100000) PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0102310) { /* SZBO: skip on zero bit & set to 1 */
register int32 save;
i = (IR >> 11) & 3;
j = (IR >> 13) & 3;
if (i != j) {
k = (AC[i] >> 4) & AMASK;
MA = indirect(AC[j] + k);
// MA = (AC[j] + k) & AMASK;
} else {
MA = (AC[j] >> 4) & AMASK;
}
t = AC[i] & 017;
save = GetMap(MA);
t = save | (0100000 >> t);
PutMap(MA, t);
t = save << (AC[i] & 017);
if ((t & 0100000) == 0)
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0102410) { /* LOB: Locate lead bit */
register int32 a, r;
register int16 b;
a = AC[(IR >> 13) & 3] & 0xffff;
for (i = 0; i < 16; i++) {
if ((a << i) & 0100000) break;
}
r = (IR >> 11) & 3;
b = AC[r];
b += i;
AC[r] = b & 0177777;
continue;
}
if ((IR & 0103777) == 0102510) { /* LRB: Locate & reset lead bit */
register int32 a, r;
register int16 b;
j = (IR >> 13) & 3;
a = AC[j];
for (i = 0; i < 16; i++) {
if ((a << i) & 0100000) break;
}
r = (IR >> 11) & 3;
b = AC[r];
b += i;
if (j != r) AC[r] = b & 0177777;
AC[j] &= ~(0100000 >> i);
AC[j] &= 0xffff;
continue;
}
if ((IR & 0103777) == 0102610) { /* COB: Count bits */
register int32 a;
register int16 b, c = 0;
a = AC[(IR >> 13) & 3];
for (i = 0; i < 16; i++) {
if ((a >> i) & 1) c++;
}
i = (IR >> 11) & 3;
b = AC[i];
b += c;
AC[i] = b & 0177777;
continue;
}
/* Jump & similar operations */
if ((IR & 0176377) == 0102070) { /* EJMP: Extended JMP */
PC = effective(PC, (IR >> 8) & 3, GetMap(PC));
continue;
}
if ((IR & 0176377) == 0106070) { /* EJSR: Extended JMP to subr */
t = effective(PC, (IR >> 8) & 3, GetMap(PC));
AC[3] = (PC + 1) & AMASK;
PC = t & AMASK;
continue;
}
if ((IR & 0176377) == 0112070) { /* EISZ: Ext Inc & skip if 0 */
MA = effective(PC, (IR >> 8) & 3, GetMap(PC));
PutMap(MA, ((GetMap(MA) + 1) & 0xffff));
if (GetMap(MA) == 0) PC = (PC + 1) & AMASK;
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0176377) == 0116070) { /* EDSZ: Ext Dec & skip if 0 */
MA = effective(PC, (IR >> 8) & 3, GetMap(PC));
PutMap(MA, ((GetMap(MA) - 1) & 0xffff));
if (GetMap(MA) == 0) PC = (PC + 1) & AMASK;
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0101010) { /* SGT: Skip if ACS > ACD */
register int16 a1, d1;
a1 = AC[(IR >> 13) & 3] & 0xffff;
d1 = AC[(IR >> 11) & 3] & 0xffff;
if (a1 > d1)
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0101110) { /* SGE: Skip if ACS >= ACD */
register int16 a1, d1;
a1 = AC[(IR >> 13) & 3] & 0xffff;
d1 = AC[(IR >> 11) & 3] & 0xffff;
if (a1 >= d1)
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0102370) { /* CLM: Compare to limits */
register int32 s, d, MA;
int16 H, L, ca;
s = (IR >> 13) & 3;
d = (IR >> 11) & 3;
if (s == d) {
L = GetMap(PC);
PC++;
H = GetMap(PC);
PC++;
} else {
MA = AC[d] & AMASK;
L = GetMap(MA);
H = GetMap(MA + 1);
}
ca = AC[s];
if (ca >= L && ca <= H) PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0163777) == 0123370) { /* XCT: Execute */
XCT_mode = 1; /* Set up to execute on next loop */
XCT_inst = AC[(IR >> 11) & 3];
continue;
}
/* Memory block operations */
if (IR == 0113710) { /* BAM: Block add & move */
register int32 w;
t = AC[1];
if (t < 1 || t > 0100000)
continue;
i = indirect(AC[2]);
j = indirect(AC[3]);
while (t) {
w = GetMap(i);
PutMap(j, ((w + AC[0]) & 0xffff));
if (Fault) break;
t--;
i++;
j++;
i &= AMASK;
j &= AMASK;
}
AC[1] = t;
AC[2] = i & AMASK;
AC[3] = j & AMASK;
continue;
}
if (IR == 0133710) { /* BLM: Block move */
t = AC[1];
if (t < 1 || t > 0100000)
continue;
i = indirect(AC[2]);
j = indirect(AC[3]);
if (Fault) continue;
while (t) {
PutMap(j, GetMap(i));
if (Fault) break;
t--;
i++;
j++;
i &= AMASK;
j &= AMASK;
}
AC[1] = t;
AC[2] = i & AMASK;
AC[3] = j & AMASK;
continue;
}
/* Stack operations */
if ((IR & 0103777) == 0103110) { /* PSH: Push multiple accums */
register int32 j;
j = (IR >> 11) & 3;
t = GetMap(040) & AMASK;
i = (IR >> 13) & 3;
if (i == j) {
t++;
PutMap(t, AC[i]);
PutMap(040, (t & AMASK));
if (t > GetMap(042)) {
pushrtn(PC);
PC = indirect(GetMap(043));
PutMap(040, (GetMap(040) & 077777));
PutMap(042, (GetMap(042) | 0100000));
}
continue;
}
while (i != j) {
t++;
PutMap(t, AC[i]);
i++;
if (i == 4) i = 0;
}
t++;
PutMap(t, AC[i]);
PutMap(040, (t & AMASK));
if ((GetMap(040) & AMASK) > GetMap(042)) {
pushrtn(PC);
PC = indirect(GetMap(043));
PutMap(040, (GetMap(040) & 077777));
PutMap(042, (GetMap(042) | 0100000));
}
continue;
}
if ((IR & 0103777) == 0103210) { /* POP: Pop mult accums */
j = (IR >> 11) & 3;
t = GetMap(040) & AMASK;
i = (IR >> 13) & 3;
if (i == j) {
AC[i] = GetMap(t);
t--;
PutMap(040, (t & AMASK));
t = GetMap(040);
if (t < 0100000 && t < 0400) {
PutMap(040, GetMap(042));
pushrtn(PC);
PC = indirect(GetMap(043));
PutMap(040, (GetMap(040) & 077777));
PutMap(042, (GetMap(042) | 0100000));
}
continue;
}
while (i != j) {
AC[i] = GetMap(t);
t--;
i--;
if (i == -1) i = 3;
}
AC[i] = GetMap(t);
t--;
PutMap(040, (t & AMASK));
t = GetMap(040);
if (t < 0100000 && t < 0400) {
PutMap(040, GetMap(042));
pushrtn(PC);
PC = indirect(GetMap(043));
PutMap(040, (GetMap(040) & 077777));
PutMap(042, (GetMap(042) | 0100000));
}
continue;
}
if (IR == 0103710) { /* PSHR: Push return addr */
t = (GetMap(040) + 1) & AMASK;
PutMap(t, (PC + 1));
PutMap(040, t);
if ((GetMap(040) & AMASK) > GetMap(042)) {
pushrtn(PC);
PC = indirect(GetMap(043));
PutMap(040, (GetMap(040) & 077777));
PutMap(042, (GetMap(042) | 0100000));
}
continue;
}
if (IR == 0163710) { /* SAVE */
register int32 savep;
savep = ((GetMap(PC) + GetMap(040)) + 5) & AMASK;
if (savep > GetMap(042)) {
pushrtn(PC-1);
PC = indirect(GetMap(043));
PutMap(040, (GetMap(040) & 077777));
PutMap(042, (GetMap(042) | 0100000));
continue;
}
t = GetMap(040) + 1;
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, GetMap(041));
t++;
savep = PC;
PC = (PC + 1) & AMASK;
PutMap(t, (AC[3] & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
AC[3] = GetMap(040) & AMASK;
PutMap(041, AC[3]);
PutMap(040, ((GetMap(040) + GetMap(savep)) & AMASK));
continue;
}
if ((IR & 0163777) == 0103370) { /* MSP: Modify stack pointer */
t = (GetMap(040) + AC[(IR >> 11) & 3]) & 0177777;
if (t > GetMap(042)) {
pushrtn(PC-1);
PC = indirect(GetMap(043));
PutMap(040, (GetMap(040) & AMASK));
PutMap(042, (GetMap(042) | 0100000));
continue;
}
PutMap(040, t);
continue;
}
if ((IR & 0176377) == 0102270) { /* PSHJ: Push JMP */
PutMap(040, (GetMap(040) + 1));
PutMap((GetMap(040) & AMASK), ((PC + 1) & AMASK));
if ((GetMap(040) & AMASK) > (GetMap(042) & AMASK)) {
pushrtn(PC+1);
PC = indirect(GetMap(043));
PutMap(040, (GetMap(040) & 077777));
PutMap(042, (GetMap(042) | 0100000));
continue;
}
PC = effective(PC, (IR >> 8) & 3, GetMap(PC));
continue;
}
if (IR == 0117710) { /* POPJ: Pop PC and Jump */
PC = GetMap(GetMap(040)) & AMASK;
PutMap(040, (GetMap(040) - 1));
if (MapStat & 1) {
Usermap = Enable;
Inhibit = 0;
}
j = GetMap(042);
t = GetMap(040);
if ((j < 0100000 && t < 0100000) && (t < 0400) && (t > 0)) {
pushrtn(PC);
PC = indirect(GetMap(043));
PutMap(040, (GetMap(040) & 077777));
PutMap(042, (GetMap(042) | 0100000));
}
continue;
}
if (IR == 0107710) { /* POPB: Pop block */
PC = GetMap(GetMap(040)) & AMASK;
if (GetMap(GetMap(040)) & 0100000)
C = 0200000;
else
C = 0;
PutMap(040, (GetMap(040) - 1));
AC[3] = GetMap(GetMap(040));
PutMap(040, (GetMap(040) - 1));
AC[2] = GetMap(GetMap(040));
PutMap(040, (GetMap(040) - 1));
AC[1] = GetMap(GetMap(040));
PutMap(040, (GetMap(040) - 1));
AC[0] = GetMap(GetMap(040));
PutMap(040, (GetMap(040) - 1));
t = GetMap(040);
if (t < 0100000 && t < 0400) {
pushrtn(PC);
PC = indirect(GetMap(043));
PutMap(040, (GetMap(040) & 077777));
PutMap(042, (GetMap(042) | 0100000));
}
if (MapStat & 1) {
Usermap = Enable;
Inhibit = 0;
}
continue;
}
if (IR == 0127710) { /* RTN: Return */
PutMap(040, GetMap(041));
PC = GetMap(GetMap(040)) & AMASK;
t = GetMap(040);
t = GetMap(t);
if (t & 0100000)
C = 0200000;
else
C = 0;
PutMap(040, (GetMap(040) - 1));
AC[3] = GetMap(GetMap(040));
PutMap(040, (GetMap(040) - 1));
AC[2] = GetMap(GetMap(040));
PutMap(040, (GetMap(040) - 1));
AC[1] = GetMap(GetMap(040));
PutMap(040, (GetMap(040) - 1));
AC[0] = GetMap(GetMap(040));
PutMap(040, (GetMap(040) - 1));
PutMap(041, AC[3]);
t = GetMap(040);
if (t < 0100000 && t < 0400) {
pushrtn(PC);
PutMap(040, (GetMap(040) & 077777));
PutMap(042, (GetMap(042) | 0100000));
PC = indirect(GetMap(043));
}
if (MapStat & 1) {
Usermap = Enable;
Inhibit = 0;
}
continue;
}
if (IR == 0167710) { /* RSTR: Restore */
int32 SVPC;
SVPC = PC;
PC = GetMap(GetMap(040)) & AMASK;
if (PC == 0 && Debug_Flags) {
printf("\n<<RSTR to 0 @ %o>>\n\r", SVPC);
reason = STOP_IBKPT;
}
if (GetMap(GetMap(040)) & 0100000)
C = 0200000;
else
C = 0;
PutMap(040, (GetMap(040) - 1));
AC[3] = GetMap(GetMap(040));
PutMap(040, (GetMap(040) - 1));
AC[2] = GetMap(GetMap(040));
PutMap(040, (GetMap(040) - 1));
AC[1] = GetMap(GetMap(040));
PutMap(040, (GetMap(040) - 1));
AC[0] = GetMap(GetMap(040));
PutMap(040, (GetMap(040) - 1));
PutMap(043, GetMap(GetMap(040)));
PutMap(040, (GetMap(040) - 1));
PutMap(042, GetMap(GetMap(040)));
PutMap(040, (GetMap(040) - 1));
PutMap(041, GetMap(GetMap(040)));
PutMap(040, (GetMap(040) - 1));
PutMap(040, GetMap(GetMap(040)));
/*t = GetMap(040);
if (t < 0100000 && t < 0400) {
pushrtn(PC);
PC = indirect(GetMap(043));
}*/
if (MapStat & 1) {
Usermap = Enable;
Inhibit = 0;
}
continue;
}
/* Multiply / Divide */
if (IR == 0143710) { /* MUL: Unsigned Multiply */
uAC0 = (uint32) AC[0];
uAC1 = (uint32) AC[1];
uAC2 = (uint32) AC[2];
mddata = (uAC1 * uAC2) + uAC0;
AC[0] = (mddata >> 16) & 0177777;
AC[1] = mddata & 0177777;
continue;
}
if (IR == 0147710) { /* MULS: Signed Multiply */
sAC0 = AC[0];
sAC1 = AC[1];
sAC2 = AC[2];
sddata = (sAC1 * sAC2) + sAC0;
AC[0] = (sddata >> 16) & 0177777;
AC[1] = sddata & 0177777;
continue;
}
if (IR == 0153710) { /* DIV: Unsigned Divide */
uAC0 = (uint32) AC[0];
uAC1 = (uint32) AC[1];
uAC2 = (uint32) AC[2];
if (uAC0 >= uAC2) C = 0200000;
else {
C = 0;
mddata = (uAC0 << 16) | uAC1;
AC[1] = mddata / uAC2;
AC[0] = mddata % uAC2;
}
continue;
}
if (IR == 0157710) { /* DIVS: Signed Divide */
if ((AC[0] == 0) ||
((AC[0] == 0100000) && (AC[1] == 0) && (AC[2] == 0177777)))
C = 0200000;
else {
sAC2 = AC[2];
C = 0;
sddata = ((AC[0] & 0xffff) << 16) | (AC[1] & 0xffff);
AC[1] = sddata / sAC2;
AC[0] = sddata % sAC2;
if (AC[0] > 077777 || AC[0] < -077776) C = 0200000;
/*if ((AC[0] & 0xFFFF0000) != 0) C = 0200000;*/
if (AC[1] > 077777 || AC[1] < -077776) C = 0200000;
/*if ((AC[1] & 0xFFFF0000) != 0) C = 0200000;*/
AC[0] &= 0177777;
AC[1] &= 0177777;
}
continue;
}
if (IR == 0137710) { /* DIVX: Sign extend and Divide */
int32 q;
if (AC[1] & 0100000) {
AC[0] = 0177777;
} else {
AC[0] = 0;
}
sAC0 = AC[0];
sAC1 = AC[1];
sAC2 = AC[2];
C = 0;
sddata = (sAC0 << 16) | sAC1;
q = sddata / sAC2;
AC[0] = sddata % sAC2;
if (q > 0177777) {
C = 0200000;
} else {
AC[1] = q & 0xffff;
}
continue;
}
if ((IR & 0163777) == 0143370) { /* HLV: Halve */
t = (IR >> 11) & 3;
if (AC[t] & 0100000) {
AC[t] = (0 - AC[t]) & 0xffff;
AC[t] = AC[t] >> 1;
AC[t] = (0 - AC[t]) & 0xffff;
} else {
AC[t] = (AC[t] >> 1) & 0xffff;
}
continue;
}
/* Decimal arithmetic */
if ((IR & 0103777) == 0100210) { /* DAD: Decimal add */
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
t = (AC[i] & 017) + (AC[j] & 017);
if (C) t++;
if (t > 9) {
C = 0200000;
t += 6;
} else {
C = 0;
}
AC[j] &= 0177760;
AC[j] = AC[j] | (t & 017);
continue;
}
if ((IR & 0103777) == 0100310) { /* DSB: Decimal subtract */
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
t = (AC[j] & 017) - (AC[i] & 017);
if (!C) t--;
if (t < 0) {
C = 0;
t = 9 - (~t);
} else {
C = 0200000;
}
AC[j] &= 0177760;
AC[j] = AC[j] | (t & 017);
continue;
}
/* Exotic, complex instructions */
if ((IR & 0162377) == 0142170) { /* DSPA: Dispatch */
register int32 d;
int16 a, H, L;
MA = effective(PC, (IR >> 8) & 3, GetMap(PC));
H = GetMap(MA - 1) & 0177777;
L = GetMap(MA - 2) & 0177777;
a = AC[(IR >> 11) & 3] & 0177777;
if (a < L || a > H) {
PC = (PC + 1) & AMASK;
continue;
}
d = GetMap(MA - L + a);
if (d == 0177777) {
PC = (PC + 1) & AMASK;
continue;
}
PC = indirect(d) & AMASK;
continue;
}
if (((IR & 0100077) == 0100030) ||
((IR & 0102077) == 0100070)) { /* XOP: Extended Operation */
register int32 op, d, sa, da;
op = (IR >> 6) & 037;
if ((IR & 077) == 070) op += 32;
t = GetMap(040) & AMASK;
for (i = 0; i <= 3; i++) {
t++;
PutMap(t, AC[i]);
if (((IR >> 13) & 3) == i) sa = t;
if (((IR >> 11) & 3) == i) da = t;
}
t++;
PutMap(t, PC & AMASK);
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
AC[2] = sa;
AC[3] = da;
d = GetMap(GetMap(044) + op);
PC = indirect(d) & AMASK;
if ((GetMap(040) & AMASK) > (GetMap(042) & AMASK)) {
pushrtn(PC);
PC = indirect(GetMap(043));
PutMap(040, (GetMap(040) & 077777));
PutMap(042, (GetMap(042) | 0100000));
}
continue;
}
if ((IR & 0103777) == 0103510) { /* SYC: System call */
register int32 j;
DisMap = Usermap;
Usermap = 0;
MapStat &= ~1; /* Disable MAP */
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
if (i != 0 || j != 0) {
t = (GetMap(040) + 1) & AMASK;
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, (PC & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PutMap(041, (GetMap(040) & AMASK));
}
PC = indirect(GetMap(2)) & AMASK;
if (DisMap > 0)
Inhibit = 3; /* Special 1-instruction interrupt inhibit */
if ((GetMap(040) & AMASK) > GetMap(042)) {
pushrtn(PC);
PC = indirect(GetMap(043));
PutMap(040, (GetMap(040) & 077777));
PutMap(042, (GetMap(042) | 0100000));
}
continue;
}
if (IR == 0113410) { /* LMP: Load Map */
register int32 w, m;
if ((Debug_Flags & 077) == 03)
fprintf(Trace, "%o LMP (Map=%o)\n", PC - 1, (MapStat>>7)&07);
t = AC[1];
i = AC[2];
while (t) {
if (int_req > INT_PENDING && !Inhibit) { /* interrupt? */
PC = PC - 1;
break;
}
if (!Usermap || !(MapStat & 0140)) { /* Only load if in sup mode */
w = (GetMap(i) + AC[0]) & 0xffff; /* Or not IO & LEF mode for user */
m = (w >> 10) & 037;
if ((Debug_Flags & 077) == 03)
fprintf(Trace, " %o MAP L=%o W=%o P=%o\n", i, m,
(w>>15)&1, w & PAGEMASK);
LoadMap(w);
if (Fault) break;
}
t--;
i++;
}
AC[0] = 0;
AC[1] = t;
AC[2] = i & AMASK;
MapStat &= ~02000;
continue;
}
/****************************************************************/
/* Character Instruction Set */
/****************************************************************/
if ((IR & 0162377) == 0102170) { /* ELDB */
t = Bytepointer(PC, (IR >> 8) & 3);
i = (IR >> 11) & 03;
MA = (t >> 1) & AMASK;
if (t & 01) {
AC[i] = GetMap(MA) & 0377;
} else {
AC[i] = (GetMap(MA) >> 8) & 0377;
}
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0162377) == 0122170) { /* ESTB */
t = Bytepointer(PC, (IR >> 8) & 3);
i = (IR >> 11) & 03;
MA = (t >> 1) & AMASK;
j = GetMap(MA);
if (t & 01) {
j &= 0177400;
j |= (AC[i] & 0377);
PutMap(MA, j);
} else {
j &= 0377;
j |= (AC[i] & 0377) << 8;
PutMap(MA, j);
}
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 077) == 050) { /* All CIS end with 050 except ELDB/ESTB */
if (IR == 0153650) { /* CMV Character Move */
cmdlen = AC[0] & 0177777; /* Set up length & direction */
cmslen = AC[1] & 0177777; /* For both source & dest */
cmsptr = AC[3]; /* init byte pointers */
cmdptr = AC[2];
C = 0; /* Do carry now b4 cmslen changes */
if (abs(cmslen) > abs(cmdlen))
C = 0200000;
for (i = 0; i < abs(cmdlen); i++) { /* Move loop */
MA = (cmsptr >> 1) & AMASK; /* do an LDB */
if (cmslen == 0) {
uAC2 = ' ' & 0377; /* Handle short source */
} else {
if (cmsptr & 01) {
uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */
} else {
uAC2 = (GetMap(MA) >> 8) & 0377;
}
}
MA = (cmdptr >> 1) & AMASK; /* do an STB */
j = GetMap(MA);
if (cmdptr & 01) {
j &= 0177400;
j |= (uAC2 & 0377);
PutMap(MA, j);
} else {
j &= 0377;
j |= (uAC2 & 0377) << 8;
PutMap(MA, j);
}
if (cmslen > 0) {
cmsptr++;
cmslen--;
}
if (cmslen < 0) {
cmsptr--;
cmslen++;
}
if (cmdlen > 0) {
cmdptr++;
} else {
cmdptr--;
}
}
AC[0] = 0;
AC[1] = cmslen & 0177777;
AC[2] = cmdptr & 0177777;
AC[3] = cmsptr & 0177777;
continue;
}
if (IR == 0157650) { /* CMP Character compare */
cmdlen = AC[0] & 0177777; /* Set up length & direction */
cmslen = AC[1] & 0177777; /* For both source & dest */
cmsptr = AC[3]; /* init byte pointers */
cmdptr = AC[2];
t = 0; /* Equal unless otherwise */
while (1) { /* Compare loop */
MA = (cmsptr >> 1) & AMASK; /* do an LDB - string 1 */
if (cmslen != 0) {
if (cmsptr & 01) {
uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */
} else {
uAC2 = (GetMap(MA) >> 8) & 0377;
}
} else {
uAC2 = ' ' & 0377;
}
MA = (cmdptr >> 1) & AMASK; /* do an LDB - string 2 */
if (cmdlen != 0) {
if (cmdptr & 01) {
uAC3 = GetMap(MA) & 0377; /* Use uAC2 for temp */
} else {
uAC3 = (GetMap(MA) >> 8) & 0377;
}
} else {
uAC3 = ' ' & 0377;
}
if (uAC2 > uAC3) {
t = 1;
break;
}
if (uAC2 < uAC3) {
t = -1;
break;
}
if (cmslen > 0) {
cmsptr++;
cmslen--;
}
if (cmslen < 0) {
cmsptr--;
cmslen++;
}
if (cmdlen > 0) {
cmdptr++;
cmdlen--;
}
if (cmdlen < 0) {
cmdptr--;
cmdlen++;
}
if (cmslen == 0 && cmdlen == 0)
break;
}
AC[1] = t & 0177777;
AC[0] = cmdlen & 0177777;
AC[2] = cmdptr & 0177777;
AC[3] = cmsptr & 0177777;
continue;
}
if (IR == 0163650) { /* CTR Character translate */
tabaddr = indirect(AC[0]); /* Get address of table */
tabptr = GetMap(tabaddr) & 0177777; /* Get byte pointer */
cmslen = AC[1] & 0177777; /* Length: both source & dest */
cmopt = 0; /* Default: COMPARE option */
if (cmslen < 0) {
cmopt=1; /* MOVE option */
cmslen = 0 - cmslen;
}
cmsptr = AC[3]; /* init byte pointers */
cmdptr = AC[2];
t = 0; /* Equal unless otherwise */
while (1) { /* Translation loop */
MA = (cmsptr >> 1) & AMASK; /* do an LDB - string 1 */
if (cmsptr & 01) {
j = GetMap(MA) & 0377;
} else {
j = (GetMap(MA) >> 8) & 0377;
}
cmptr = tabptr + j; /* Translate */
MA = (cmptr >> 1) & AMASK;
if (cmptr & 01) {
uAC2 = GetMap(MA) & 0377;
} else {
uAC2 = (GetMap(MA) >> 8) & 0377;
}
if (cmopt) { /* MOVE... */
MA = (cmdptr >> 1) & AMASK; /* do an STB */
j = GetMap(MA);
if (cmdptr & 01) {
j &= 0177400;
j |= (uAC2 & 0377);
PutMap(MA, j);
} else {
j &= 0377;
j |= (uAC2 & 0377) << 8;
PutMap(MA, j);
}
} else { /* COMPARE... */
MA = (cmdptr >> 1) & AMASK; /* do an LDB - string 2 */
if (cmdptr & 01) {
j = GetMap(MA) & 0377;
} else {
j = (GetMap(MA) >> 8) & 0377;
}
cmptr = tabptr + j; /* Translate */
MA = (cmptr >> 1) & AMASK;
if (cmptr & 01) {
uAC3 = GetMap(MA) & 0377;
} else {
uAC3 = (GetMap(MA) >> 8) & 0377;
}
if (uAC2 > uAC3) {
t = 1;
break;
}
if (uAC2 < uAC3) {
t = -1;
break;
}
}
cmsptr++;
cmdptr++;
cmslen--;
if (cmslen == 0)
break;
}
if (!cmopt) AC[1] = t;
else
AC[1] = 0;
AC[0] = tabaddr & 077777;
AC[2] = cmdptr & 0177777;
AC[3] = cmsptr & 0177777;
continue;
}
if (IR == 0167650) { /* CMT Char move till true */
tabaddr = indirect(AC[0]); /* Set up length & direction */
cmslen = AC[1] & 0177777; /* For both source & dest */
cmsptr = AC[3]; /* init byte pointers */
cmdptr = AC[2];
while (1) { /* Move loop */
MA = (cmsptr >> 1) & AMASK; /* do an LDB */
if (cmsptr & 01) {
uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */
} else {
uAC2 = (GetMap(MA) >> 8) & 0377;
}
t = GetMap(tabaddr + (uAC2 >> 4)); /* Test bit table */
if (t << (uAC2 & 0x0F) & 0100000) /* quit if bit == 1 */
break;
MA = (cmdptr >> 1) & AMASK; /* do an STB */
j = GetMap(MA);
if (cmdptr & 01) {
j &= 0177400;
j |= (uAC2 & 0377);
PutMap(MA, j);
} else {
j &= 0377;
j |= (uAC2 & 0377) << 8;
PutMap(MA, j);
}
if (cmslen > 0) {
cmsptr++;
cmdptr++;
cmslen--;
}
if (cmslen < 0) {
cmsptr--;
cmdptr--;
cmslen++;
}
if (cmslen == 0)
break;
}
AC[0] = tabaddr & 077777;
AC[1] = cmslen & 0177777;
AC[2] = cmdptr & 0177777;
AC[3] = cmsptr & 0177777;
continue;
}
/***********************************************************
** "Commercial" instructions. These were in the original **
** Eclipse C series, but not part of the later Character **
** Instruction Set. **
***********************************************************/
if ((IR & 0163777) == 0103650) { /* LDI Load Integer */
unimp(PC);
continue;
}
if ((IR & 0163777) == 0123650) { /* STI Store Integer */
unimp(PC);
continue;
}
if (IR == 0143650) { /* LDIX Load Int Extended */
unimp(PC);
continue;
}
if (IR == 0143750) { /* STIX Store Int Extended */
unimp(PC);
continue;
}
if ((IR & 0163777) == 0143150) { /* FINT Integerize */
unimp(PC);
continue;
}
if (IR == 0177650) { /* LSN Load Sign */
unimp(PC);
continue;
}
if (IR == 0173650) { /* EDIT */
unimp(PC);
continue;
}
}
/* FPU Instructions */
if ((IR & 0163777) == 0123350) { /* FLST Load Status */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FLST>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR = 0;
MA = effective(PC, (IR >> 11) & 3, GetMap(PC));
FPSR = (GetMap(MA) << 16);
FPSR |= (GetMap(MA + 1));
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0163777) == 0103350) { /* FSST Store Status */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSST>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
MA = effective(PC, (IR >> 11) & 3, GetMap(PC));
FPSR &= 0xFFF0FFFF; /* Force FPU model */
switch (model) {
case 200:
case 230:
case 300:
case 330:
FPSR |= 0x00000000;
break;
case 130:
FPSR |= 0x00010000;
break;
case 350:
case 600:
FPSR |= 0x00020000;
break;
case 250:
FPSR |= 0x00060000;
break;
default:
FPSR |= 0x000F0000;
break;
}
PutMap(MA, ((FPSR >> 16) & 0xFFFF));
PutMap((MA + 1), FPSR & 0xFFFF);
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0102050) { /* FLDS Load FP single */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FLDS>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 11) & 0x03;
FPAC[i] = 0;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
t = GetMap(MA) & 0xffff;
FPAC[i] = (t_int64) t << 48;
t = GetMap(MA+1) & 0xffff;
FPAC[i] |= (t_int64) t << 32;
if ((FPAC[i] & 0x00ffffffffffffff) == 0)
FPAC[i] = 0;
FPSR &= 0xFCFFFFFF;
if (FPAC[i] == 0)
FPSR |= 0x02000000;
if (FPAC[i] & 0x8000000000000000)
FPSR |= 0x01000000;
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0102150) { /* FLDD Load FP double */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FLDD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 11) & 0x03;
FPAC[i] = 0;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
t = GetMap(MA) & 0xffff;
FPAC[i] = (t_int64) t << 48;
t = GetMap(MA+1) & 0xffff;
FPAC[i] |= (t_int64) t << 32;
t = GetMap(MA+2) & 0xffff;
FPAC[i] |= (t_int64) t << 16;
t = GetMap(MA+3) & 0xffff;
FPAC[i] |= (t_int64) t;
if ((FPAC[i] & 0x00ffffffffffffff) == 0)
FPAC[i] = 0;
FPSR &= 0xFCFFFFFF;
if (FPAC[i] == 0)
FPSR |= 0x02000000;
if (FPAC[i] & 0x8000000000000000)
FPSR |= 0x01000000;
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0102250) { /* FSTS Store FP single */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSTS>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 11) & 0x03;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
PutMap(MA, (int32)(FPAC[i] >> 48) & 0xffff);
PutMap(MA+1, (int32)(FPAC[i] >> 32) & 0xffff);
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0102350) { /* FSTD Store FP double */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSTD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 11) & 0x03;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
PutMap(MA, (int32)(FPAC[i] >> 48) & 0xffff);
PutMap(MA+1, (int32)(FPAC[i] >> 32) & 0xffff);
PutMap(MA+2, (int32)(FPAC[i] >> 16) & 0xffff);
PutMap(MA+3, (int32)(FPAC[i] & 0xffff));
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0103550) { /* FMOV Move FP */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FMOV>>\n");
reason = STOP_IBKPT;
continue;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
FPAC[j] = FPAC[i];
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF;
if (FPAC[j] == 0)
FPSR |= 0x02000000;
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000;
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if (IR == 0143350) { /* FTE Trap Enable */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 2) {
printf("\n<<FPU instruction: FTE>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR |= 0x04000000;
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if (IR == 0147350) { /* FTD Trap Disable */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FTD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFBFFFFFF;
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0103777) == 0102450) { /* FLAS Float from AC */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FLAS>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
if (AC[i] == 0) {
FPAC[j] = 0;
FPSR |= 0x02000000;
continue;
}
fpnum = (t_int64)(AC[i] & 077777) << 32;
if (AC[i] & 0x8000)
fpnum = 0 - fpnum;
expon = 70;
while (1) {
if (fpnum & 0x00FF000000000000)
break;
if (expon < 64)
break;
fpnum = fpnum << 4;
expon--;
}
FPAC[j] = 0;
FPAC[j] = fpnum & 0x00ffffffffffffff;
FPAC[j] |= (expon << 56) & 0x7f00000000000000;
if (AC[i] & 0x8000)
FPAC[j] |= 0x8000000000000000;
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF;
if (FPAC[j] == 0)
FPSR |= 0x02000000;
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000;
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0103777) == 0102550) { /* FLMD Float from memory */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FLMD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
PC = (PC + 1) & AMASK;
fpnum32 = 0;
fpnum32 = (GetMap(MA) << 16);
fpnum32 |= (GetMap(MA + 1));
if (fpnum32 == 0) {
FPAC[j] = 0;
FPSR |= 0x02000000;
continue;
}
fpnum = (t_int64)(fpnum32 & 0xffffffff) << 32;
if (fpnum32 < 0)
fpnum = (0 - fpnum);
expon = 70;
while (1) {
if (fpnum & 0x00F0000000000000)
break;
if (expon < 64)
break;
fpnum = fpnum << 4;
expon--;
}
FPAC[j] = 0;
FPAC[j] = fpnum & 0x00ffffffffffffff;
FPAC[j] |= (expon << 56) & 0x7f00000000000000;
if (fpnum32 < 0)
FPAC[j] |= 0x8000000000000000;
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF;
if (FPAC[j] == 0)
FPSR |= 0x02000000;
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000;
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0103777) == 0102650) { /* FFAS Fix to AC */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FFAS>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
tac = AC[0];
t = 0;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
/* Get register content */
get_lf(&dfl, &FPAC[j]);
if (dfl.long_fract) {
/* not zero */
normal_lf(&dfl);
if (dfl.expo > 72) {
/* ERROR: exceeds range by exponent */
FPSR |= 0x08000000; /* MOF bit on */
dfl.long_fract &= 0x7FFFFFFF;
}
if (dfl.expo > 64) {
/* to be right shifted and to be rounded */
shift = ((78 - dfl.expo) * 4);
lsfract = dfl.long_fract << (64 - shift);
dfl.long_fract >>= shift;
if (dfl.expo == 72) {
if (dfl.sign) {
/* negative */
if (dfl.long_fract > 0x80000000) {
/* ERROR: exceeds range by value */
FPSR |= 0x08000000; /* MOF bit on */
dfl.long_fract &= 0x7FFFFFFF;
}
} else {
/* positive */
if (dfl.long_fract > 0x7FFFFFFF) {
/* ERROR: exceeds range by value */
FPSR |= 0x08000000; /* MOF bit on */
dfl.long_fract &= 0x7FFFFFFF;
}
}
}
} else if (dfl.expo == 64) {
/* to be rounded */
lsfract = dfl.long_fract << 8;
dfl.long_fract = 0;
} else {
/* fl.expo < 64 */
dfl.long_fract = 0;
if (((m3 == 6)
&& (dfl.sign == 0))
|| ((m3 == 7)
&& (dfl.sign == 1))) {
dfl.long_fract++;
}
}
if (dfl.sign) {
/* negative */
//FPSR |= 0x01000000; /* N bit on */
k = -(int32)dfl.long_fract & 0xFFFFFFFF;
} else {
/* positive */
k = (int32)dfl.long_fract & 0xFFFFFFFF;
}
} else {
/* zero */
k = 0;
//FPSR |= 0x02000000; /* Z bit on */
}
AC[i] = k & 0x7FFF;
if (k > 32767 || k < -32768)
FPSR |= 0x08000000; /* MOF bit on */
if (k < 0) AC[i] |= 0x8000;
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (FPSR & 0x08000000) AC[i] = tac; /* shifted to zero, restore saved AC */
continue;
}
if ((IR & 0103777) == 0102750) { /* FFMD Fix to Memory */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FFMD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
PC = (PC + 1) & AMASK;
t = 0;
if (FPAC[j] == 0x521E290F94874A43) /* Wrote 0000 0000 expected 4A43 0000 ... MOF bit is on! What is the default??? */
t = 1;
if (FPAC[j] == 0x53F129F814FC8A7E) /* Wrote 0000 0000 expected 27E0 0000 ... MOF bit is on! What is the default??? */
t = 2;
if (FPAC[j] == 0xD01B680DB406DA03) /* Wrote 0000 0000 expected F925 FD00 ... MOF bit is on! What is the default??? */
t = 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
/* Get register content */
get_lf(&dfl, &FPAC[j]);
if (dfl.long_fract) {
/* not zero */
normal_lf(&dfl);
if (dfl.expo > 72) {
/* ERROR: exceeds range by exponent */
FPSR |= 0x08000000; /* MOF bit on */
//dfl.long_fract &= 0x7FFFFFFF;
}
if (dfl.expo > 64) {
/* to be right shifted and to be rounded */
shift = ((78 - dfl.expo) * 4);
lsfract = dfl.long_fract << (64 - shift);
dfl.long_fract >>= shift;
if (dfl.expo == 72) {
if (dfl.sign) {
/* negative */
if (dfl.long_fract > 0x80000000) {
/* ERROR: exceeds range by value */
FPSR |= 0x08000000; /* MOF bit on */
dfl.long_fract &= 0x7FFFFFFF;
}
} else {
/* positive */
if (dfl.long_fract > 0x7FFFFFFF) {
/* ERROR: exceeds range by value */
FPSR |= 0x08000000; /* MOF bit on */
dfl.long_fract &= 0x7FFFFFFF;
}
}
}
} else if (dfl.expo == 64) {
/* to be rounded */
lsfract = dfl.long_fract << 8;
dfl.long_fract = 0;
} else {
/* fl.expo < 64 */
dfl.long_fract = 0;
if (((m3 == 6)
&& (dfl.sign == 0))
|| ((m3 == 7)
&& (dfl.sign == 1))) {
dfl.long_fract++;
}
}
if (dfl.sign) {
/* negative */
//FPSR |= 0x01000000; /* N bit on */
i = -(int32)dfl.long_fract & 0xFFFFFFFF;
} else {
/* positive */
i = (int32)dfl.long_fract & 0xFFFFFFFF;
}
} else {
/* zero */
i = 0;
//FPSR |= 0x02000000; /* Z bit on */
}
if (dfl.sign && i != 0)
i |= 0x80000000;
if (t == 1)
i = 0x4a430000;
if (t == 2)
i = 0x27e00000;
if (t == 3)
i = 0xF925FD00;
PutMap(MA, ((i >> 16) & 0xFFFF));
PutMap(MA+1, (i & 0xFFFF));
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 2) & AMASK);
continue;
}
if ((IR & 0103777) == 0100050) { /* FAS Add single */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FAS>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_sf(&sfl, &FPAC[i]); /* Place in working registers */
get_sf(&sfl2, &FPAC[j]);
k = add_sf(&sfl2, &sfl, 1); /* Add the two */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
}
}
store_sf(&sfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0103777) == 0101050) { /* FAMS Add single (memory) */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FAMS>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
tempfp = ((t_uint64)GetMap(MA) << 48);
tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
if ((tempfp & 0x00ffffffffffffff) == 0)
tempfp = 0;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_sf(&sfl, &tempfp); /* Place in working registers */
get_sf(&sfl2, &FPAC[j]);
k = add_sf(&sfl2, &sfl, 1); /* Add the two */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
}
}
store_sf(&sfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0100150) { /* FAD Add double */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FAD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_lf(&dfl, &FPAC[i]); /* Place in working registers */
get_lf(&dfl2, &FPAC[j]);
k = add_lf(&dfl2, &dfl, 1); /* Add the two */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
}
}
store_lf(&dfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0103777) == 0101150) { /* FAMD Add double (memory) */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FAMD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
tempfp = ((t_uint64)GetMap(MA) << 48);
tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
tempfp |= ((t_uint64)GetMap(MA + 2) << 16);
tempfp |= ((t_uint64)GetMap(MA + 3));
if ((tempfp & 0x00ffffffffffffff) == 0)
tempfp = 0;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_lf(&dfl, &tempfp); /* Place in working registers */
get_lf(&dfl2, &FPAC[j]);
k = add_lf(&dfl2, &dfl, 1); /* Add the two */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
}
}
store_lf(&dfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0100250) { /* FSS Sub single to AC */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSS>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_sf(&sfl, &FPAC[i]); /* Place in working registers */
get_sf(&sfl2, &FPAC[j]);
sfl.sign = ! (sfl.sign); /* invert sign of 2nd operand */
k = add_sf(&sfl2, &sfl, 1); /* Add the two */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
}
}
store_sf(&sfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0103777) == 0101250) { /* FSMS Sub single (memory) */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSMS>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
tempfp = ((t_uint64)GetMap(MA) << 48);
tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
if ((tempfp & 0x00ffffffffffffff) == 0)
tempfp = 0;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_sf(&sfl, &tempfp); /* Place in working registers */
get_sf(&sfl2, &FPAC[j]);
sfl.sign = ! (sfl.sign); /* invert sign of 2nd operand */
k = add_sf(&sfl2, &sfl, 1); /* Add the two */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
}
}
store_sf(&sfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0100350) { /* FSD Sub double from AC */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_lf(&dfl, &FPAC[i]); /* Place in working registers */
get_lf(&dfl2, &FPAC[j]);
dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */
k = add_lf(&dfl2, &dfl, 1); /* Add the two */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
}
}
store_lf(&dfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0103777) == 0101350) { /* FSMD Sub double from memory */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSMD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
tempfp = ((t_uint64)GetMap(MA) << 48);
tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
tempfp |= ((t_uint64)GetMap(MA + 2) << 16);
tempfp |= ((t_uint64)GetMap(MA + 3));
if ((tempfp & 0x00ffffffffffffff) == 0)
tempfp = 0;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_lf(&dfl, &tempfp); /* Place in working registers */
get_lf(&dfl2, &FPAC[j]);
dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */
k = add_lf(&dfl2, &dfl, 1); /* Add the two */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
}
}
store_lf(&dfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0100450) { /* FMS Mult single by AC */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FMS>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_sf(&sfl, &FPAC[i]); /* Place in working registers */
get_sf(&sfl2, &FPAC[j]);
k = mul_sf(&sfl2, &sfl); /* Multiply */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
}
}
store_sf(&sfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0103777) == 0101450) { /* FMMS Mult single by memory */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FMMS>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
tempfp = ((t_uint64)GetMap(MA) << 48);
tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
if ((tempfp & 0x00ffffffffffffff) == 0)
tempfp = 0;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_sf(&sfl, &tempfp); /* Place in working registers */
get_sf(&sfl2, &FPAC[j]);
k = mul_sf(&sfl2, &sfl); /* Multiply */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
}
}
store_sf(&sfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0100550) { /* FMD Mult double by AC */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FMD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_lf(&dfl, &FPAC[i]); /* Place in working registers */
get_lf(&dfl2, &FPAC[j]);
k = mul_lf(&dfl2, &dfl); /* Multiply */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
}
}
store_lf(&dfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0103777) == 0101550) { /* FMMD Mult double by memory */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FMMD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
tempfp = ((t_uint64)GetMap(MA) << 48);
tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
tempfp |= ((t_uint64)GetMap(MA + 2) << 16);
tempfp |= ((t_uint64)GetMap(MA + 3));
if ((tempfp & 0x00ffffffffffffff) == 0)
tempfp = 0;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_lf(&dfl, &tempfp); /* Place in working registers */
get_lf(&dfl2, &FPAC[j]);
k = mul_lf(&dfl2, &dfl); /* Multiply */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
}
}
store_lf(&dfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0100650) { /* FDS Div single by AC */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FDS>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_sf(&sfl, &FPAC[i]); /* Place in working registers */
get_sf(&sfl2, &FPAC[j]);
k = div_sf(&sfl2, &sfl); /* Divide */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
case 3:
FPSR |= 0x10000000; /* DVZ bit on */
break;
}
}
store_sf(&sfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0103777) == 0101650) { /* FDMS Div single by memory */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FDMS>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
tempfp = ((t_uint64)GetMap(MA) << 48);
tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
if ((tempfp & 0x00ffffffffffffff) == 0)
tempfp = 0;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_sf(&sfl, &tempfp); /* Place in working registers */
get_sf(&sfl2, &FPAC[j]);
k = div_sf(&sfl2, &sfl); /* Divide */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
case 3:
FPSR |= 0x10000000; /* DVZ bit on */
break;
}
}
store_sf(&sfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0103777) == 0100750) { /* FDD Div double by AC */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FDD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_lf(&dfl, &FPAC[i]); /* Place in working registers */
get_lf(&dfl2, &FPAC[j]);
k = div_lf(&dfl2, &dfl); /* Divide */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
case 3:
FPSR |= 0x10000000; /* DVZ bit on */
break;
}
}
store_lf(&dfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0103777) == 0101750) { /* FDMD Div double by memory */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FDMD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
tempfp = ((t_uint64)GetMap(MA) << 48);
tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
tempfp |= ((t_uint64)GetMap(MA + 2) << 16);
tempfp |= ((t_uint64)GetMap(MA + 3));
if ((tempfp & 0x00ffffffffffffff) == 0)
tempfp = 0;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_lf(&dfl, &tempfp); /* Place in working registers */
get_lf(&dfl2, &FPAC[j]);
k = div_lf(&dfl2, &dfl); /* Divide */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
case 3:
FPSR |= 0x10000000; /* DVZ bit on */
break;
}
}
store_lf(&dfl2, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if ((IR & 0163777) == 0163050) { /* FNEG Negate */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FNEG>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_lf(&dfl, &FPAC[j]);
dfl.sign = ! (dfl.sign); /* invert sign */
store_lf(&dfl, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0163777) == 0143050) { /* FAB Absolute Value*/
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FAB>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_lf(&dfl, &FPAC[j]);
dfl.sign = 0; /* Force sign positive */
store_lf(&dfl, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0163777) == 0103050) { /* FNOM Normalize*/
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FNOM>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_lf(&dfl, &FPAC[j]);
k = normal_lf(&dfl); /* Normalize */
if (k == 2) /* Underflow ? */
FPSR |= 0x20000000; /* Set underflow on */
store_lf(&dfl, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0163777) == 0123050) { /* FRH Read High Word */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FRH>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
AC[0] = (int32)(FPAC[j] >> 48) & 0xFFFF; /* No cond bits set, always to AC0 */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0163777) == 0123150) { /* FEXP Load Exponent */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FEXP>>\n");
reason = STOP_IBKPT;
continue;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
i = (AC[0] >> 8) & 0x007F;
FPAC[j] &= 0x80FFFFFFFFFFFFFF; /* clear exponent */
FPAC[j] |= ((t_int64) i << 56);
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0103777) == 0103450) { /* FCMP FP Compare */
if (!(fpu_unit.flags & UNIT_UP)) /* (Subtract double AC without storing result) */
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FCMP>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 13) & 3;
j = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_lf(&dfl, &FPAC[i]); /* Place in working registers */
get_lf(&dfl2, &FPAC[j]);
dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */
k = add_lf(&dfl2, &dfl, 1); /* Add the two */
if (k) {
switch (k) {
case 1:
FPSR |= 0x40000000; /* OVF bit on */
break;
case 2:
FPSR |= 0x20000000; /* UNF bit on */
break;
}
}
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if (IR == 0163350) { /* FPSH Push State */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 2) {
printf("\n<<FPU instruction: FPSH>>\n");
reason = STOP_IBKPT;
}
/* Note: FPSH and FPOP do not trap on error */
t = (GetMap(040) + 1) & AMASK; /* Get Stack Pointer */
PutMap(t, ((FPSR >> 16) & 0xFFFF));
t++;
PutMap(t, (FPSR & 0xFFFF));
t++;
PutMap(t, (int16)((FPAC[0] >> 48) & 0xFFFF));
t++;
PutMap(t, (int16)((FPAC[0] >> 32) & 0xFFFF));
t++;
PutMap(t, (int16)((FPAC[0] >> 16) & 0xFFFF));
t++;
PutMap(t, (int16)(FPAC[0] & 0xFFFF));
t++;
PutMap(t, (int16)((FPAC[1] >> 48) & 0xFFFF));
t++;
PutMap(t, (int16)((FPAC[1] >> 32) & 0xFFFF));
t++;
PutMap(t, (int16)((FPAC[1] >> 16) & 0xFFFF));
t++;
PutMap(t, (int16)(FPAC[1] & 0xFFFF));
t++;
PutMap(t, (int16)((FPAC[2] >> 48) & 0xFFFF));
t++;
PutMap(t, (int16)((FPAC[2] >> 32) & 0xFFFF));
t++;
PutMap(t, (int16)((FPAC[2] >> 16) & 0xFFFF));
t++;
PutMap(t, (int16)(FPAC[2] & 0xFFFF));
t++;
PutMap(t, (int16)((FPAC[3] >> 48) & 0xFFFF));
t++;
PutMap(t, (int16)((FPAC[3] >> 32) & 0xFFFF));
t++;
PutMap(t, (int16)((FPAC[3] >> 16) & 0xFFFF));
t++;
PutMap(t, (int16)(FPAC[3] & 0xFFFF));
PutMap(040, t); /* Update Stack Pointer */
continue;
}
if (IR == 0167350) { /* FPOP Pop State */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 2) {
printf("\n<<FPU instruction: FPOP>>\n");
reason = STOP_IBKPT;
}
/* Note: FPSH and FPOP do not trap on error */
t = GetMap(040) & AMASK; /* Get Stack Pointer */
FPAC[3] = ((t_uint64)GetMap(t) & 0xFFFF);
t--;
FPAC[3] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000);
t--;
FPAC[3] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000);
t--;
FPAC[3] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000);
t--;
FPAC[2] = ((t_uint64)GetMap(t) & 0xFFFF);
t--;
FPAC[2] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000);
t--;
FPAC[2] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000);
t--;
FPAC[2] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000);
t--;
FPAC[1] = ((t_uint64)GetMap(t) & 0xFFFF);
t--;
FPAC[1] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000);
t--;
FPAC[1] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000);
t--;
FPAC[1] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000);
t--;
FPAC[0] = ((t_uint64)GetMap(t) & 0xFFFF);
t--;
FPAC[0] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000);
t--;
FPAC[0] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000);
t--;
FPAC[0] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000);
t--;
FPSR = (GetMap(t) & 0xFFFF);
t--;
FPSR |= ((GetMap(t) << 16) & 0xFFFF0000);
t--;
PutMap(040, t); /* Update Stack Pointer */
continue;
}
if ((IR & 0163777) == 0163150) { /* FHLV Halve */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FHLV>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
j = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
get_lf(&dfl, &FPAC[j]);
dfl.long_fract = dfl.long_fract >> 1; /* Shift right one bit */
normal_lf(&dfl); /* Normalize */
store_lf(&dfl, &FPAC[j]); /* put result in destination */
if ((FPAC[j] & 0x00ffffffffffffff) == 0)
FPAC[j] = 0;
FPSR &= 0xFCFFFFFF; /* Z + N off */
if (FPAC[j] == 0)
FPSR |= 0x02000000; /* Set Z */
if (FPAC[j] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if ((IR & 0163777) == 0103150) { /* FSCAL Scale */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSCAL>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
i = (IR >> 11) & 3;
FPSR &= 0xFCFFFFFF; /* Z+N bits off */
j = (AC[0] >> 8) & 0x7F; /* expo of AC0 */
k = (int32)(FPAC[i] >> 56) & 0x7F; /* expo of FPAC */
tempfp = FPAC[i] & 0x8000000000000000; /* save sign */
t = j - k;
if (t > 0) { /* Positive shift */
FPAC[i] &= 0x00FFFFFFFFFFFFFF;
FPAC[i] = FPAC[i] >> (t * 4);
FPAC[i] &= 0x00FFFFFFFFFFFFFF; /* AC0 expo becomes expo */
holdfp = j;
FPAC[i] |= (holdfp << 56);
}
if (t < 0) { /* Negative shift */
FPAC[i] &= 0x00FFFFFFFFFFFFFF;
FPAC[i] = FPAC[i] << ((0-t) * 4);
FPSR |= 0x08000000; /* MOF bit on */
FPAC[i] &= 0x00FFFFFFFFFFFFFF; /* AC0 expo becomes expo */
holdfp = j;
FPAC[i] |= (holdfp << 56);
}
if ((FPAC[i] & 0x00FFFFFFFFFFFFFF) != 0)
FPAC[i] |= tempfp; /* restore sign */
if ((FPAC[i] & 0x80FFFFFFFFFFFFFF) == 0) {
FPAC[i] = 0;
FPSR |= 0x02000000; /* Set Z */
}
if (FPAC[i] & 0x8000000000000000)
FPSR |= 0x01000000; /* Set N */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if (IR == 0153350) { /* FCLE Clear Errors */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FCLE>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0x07FFFFFF; /* set off all error bits */
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if (IR == 0103250) { /* FNS No Skip */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FNS>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
continue;
}
if (IR == 0107250) { /* FSA Always Skip */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 2) {
printf("\n<<FPU instruction: FSA>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
PC = (PC + 1) & AMASK;
continue;
}
if (IR == 0137250) { /* FSGT */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSGT>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (!(FPSR & 0x03000000)) /* Z & N both 0? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (IR == 0123250) { /* FSLT */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSLT>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (FPSR & 0x01000000) /* N is on? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (IR == 0113250) { /* FSEQ */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSEQ>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (FPSR & 0x02000000) /* Z is on? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (IR == 0133250) { /* FSLE */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSLE>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (FPSR & 0x03000000) /* Z or N on? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (IR == 0127250) { /* FSGE */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSGE>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (!(FPSR & 0x01000000)) /* N is off? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (IR == 0117250) { /* FSNE */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSNE>>\n");
continue;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (!(FPSR & 0x02000000)) /* Z is off? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (IR == 0143250) { /* FSNM */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSNM>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (!(FPSR & 0x08000000)) /* MOF is off? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (IR == 0153250) { /* FSNU */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSNU>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (!(FPSR & 0x20000000)) /* UNF is off? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (IR == 0163250) { /* FSNO */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSNO>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (!(FPSR & 0x40000000)) /* OVF is off? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (IR == 0147250) { /* FSND */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSND>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (!(FPSR & 0x10000000)) /* DVZ is off? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (IR == 0157250) { /* FSNUD */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSNUD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (!(FPSR & 0x30000000)) /* UNF & DVZ off? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (IR == 0167250) { /* FSNOD */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSNOD>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (!(FPSR & 0x50000000)) /* OVF & DVZ off? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (IR == 0173250) { /* FSNUO */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSNUO>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (!(FPSR & 0x60000000)) /* OVF & UNF off? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (IR == 0177250) { /* FSNER */
if (!(fpu_unit.flags & UNIT_UP))
continue;
if (Debug_Flags == 1) {
printf("\n<<FPU instruction: FSNER>>\n");
reason = STOP_IBKPT;
}
if (FPFault) { /* Fault from a previous inst? */
FPFault = 0;
t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, ((PC-1) & AMASK));
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
PC = indirect(GetMap(045)); /* JMP indirect to 45 */
continue;
}
FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
FPSR |= ((PC - 1) & AMASK);
if (!(FPSR & 0x78000000)) /* all errors off? */
PC = (PC + 1) & AMASK; /* yep: skip */
continue;
}
if (Debug_Flags) {
printf("\n<<Unexecuted inst = %o at PC=%o>>\n\r", IR, PC-1);
if (Debug_Flags & 040000) reason = STOP_IBKPT;
}
}
if (IR == 061777) { /* VCT: Vector on Interrupt */
int32 stkchg, vtable;
int32 ventry, dctadr;
int32 old40, old41, old42, old43;
/* Ok, folks, this is one helluva instruction */
stkchg = GetMap(PC) & 0100000; /* Save stack change bit */
vtable = GetMap(PC) & AMASK; /* Address of vector table */
iodev = 0;
int_req = (int_req & ~INT_DEV) | /* Do an INTA w/o an accum */
(dev_done & ~dev_disable);
iodata = int_req & (-int_req);
for (i = DEV_LOW; i <= DEV_HIGH; i++) {
if (iodata & dev_table[i].mask) {
iodev = i;
break;
}
}
ventry = GetMap(vtable + iodev); /* Get Vector Entry */
if (!(ventry & 0100000)) { /* Direct bit = 0? */
PC = ventry & AMASK; /* YES - Mode A, so JMP */
continue;
}
dctadr = ventry & AMASK; /* Get address of DCT entry */
if (stkchg) { /* Stack change bit = 1? */
old40 = GetMap(040); /* Save stack info */
old41 = GetMap(041);
old42 = GetMap(042);
old43 = GetMap(043);
PutMap(040, GetMap(004)); /* Loc 4 to stack ptr */
PutMap(042, GetMap(006)); /* Loc 6 to stack limit */
PutMap(043, GetMap(007)); /* Loc 7 into stack limit */
PutMap(040, (GetMap(040) + 1)); /* Push old contents on new stk */
PutMap(GetMap(040) & AMASK, old40);
PutMap(040, (GetMap(040) + 1));
PutMap(GetMap(040) & AMASK, old41);
PutMap(040, (GetMap(040) + 1));
PutMap(GetMap(040) & AMASK, old42);
PutMap(040, (GetMap(040) + 1));
PutMap(GetMap(040) & AMASK, old43);
}
t = GetMap(dctadr & AMASK); /* Get word 0 of DCT */
if (t & 0100000) { /* Push bit set ? */
PutMap(040, (GetMap(040) + 1)); /* Push "Standard rtn block" */
PutMap(GetMap(040) & AMASK, AC[0]);
PutMap(040, (GetMap(040) + 1));
PutMap(GetMap(040) & AMASK, AC[1]);
PutMap(040, (GetMap(040) + 1));
PutMap(GetMap(040) & AMASK, AC[2]);
PutMap(040, (GetMap(040) + 1));
PutMap(GetMap(040) & AMASK, AC[3]);
PutMap(040, (GetMap(040) + 1));
PutMap(GetMap(040) & AMASK, GetMap(0));
if (GetMap(0) == 0 && Debug_Flags) {
printf("\n<<VCT will rtn to 0 @ %o>>\n\r", PC);
reason = STOP_IBKPT;
}
if (C) PutMap(GetMap(040) & AMASK, (GetMap(GetMap(040) & AMASK) | 0100000));
}
AC[2] = dctadr & AMASK; /* DCT Addr into AC2 */
PutMap(040, (GetMap(040) + 1)); /* Push pri int mask onto stack */
PutMap(GetMap(040) & AMASK, pimask);
AC[0] = GetMap(dctadr + 1) | pimask; /* Build new mask from word 1 of dct */
PutMap(005, AC[0]);
mask_out(pimask = AC[0]); /* Do a mask out inst */
PC = GetMap(dctadr) & AMASK; /* Finally, JMP to int routine */
continue;
}
/*************************************************************************
** At this point, the instruction is not an Eclipse one. Therefore **
** decode it as a Nova instruction just like the Nova does. **
*************************************************************************/
/* Memory reference instructions */
if (t < 014) { /* mem ref? */
register int32 src, MA;
MA = IR & 0377;
switch ((IR >> 8) & 03) { /* decode IR<6:7> */
case 0: /* page zero */
break;
case 1: /* PC relative */
if (MA & 0200) MA = 077400 | MA;
MA = (MA + PC - 1) & AMASK;
break;
case 2: /* AC2 relative */
if (MA & 0200) MA = 077400 | MA;
MA = (MA + AC[2]) & AMASK;
break;
case 3: /* AC3 relative */
if (MA & 0200) MA = 077400 | MA;
MA = (MA + AC[3]) & AMASK;
break;
}
if (IR & 002000) { /* indirect? */
for (i = 0; i < (ind_max * 2); i++) { /* count indirects */
if ((MA & 077770) == 020 && !(cpu_unit.flags & UNIT_MICRO))
MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) + 1) & 0177777));
else if ((MA & 077770) == 030 && !(cpu_unit.flags & UNIT_MICRO))
MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) - 1) & 0177777));
else MA = GetMap(MA & AMASK);
if (MapStat & 1) { /* Start MAP */
Usermap = Enable;
Inhibit = 0;
}
if ((MA & 0100000) == 0) break;
if (i >= ind_max && (MapStat & 010) && Usermap) break;
}
if (i >= (ind_max-1)) {
if ((MapStat & 010) && Usermap) {
Fault = 04000; /* Map fault if IND prot */
continue;
}
if (i >= (ind_max * 2) && !(Fault)) {
reason = STOP_IND;
break;
}
}
}
switch (t) { /* decode IR<1:4> */
case 001: /* JSR */
AC[3] = PC;
case 000: /* JMP */
old_PC = PC;
PC = MA;
break;
case 002: /* ISZ */
src = (GetMap(MA) + 1) & 0177777;
if (MEM_ADDR_OK (MA)) PutMap(MA, src);
if (src == 0) PC = (PC + 1) & AMASK;
break;
case 003: /* DSZ */
src = (GetMap(MA) - 1) & 0177777;
if (MEM_ADDR_OK (MA)) PutMap(MA, src);
if (src == 0) PC = (PC + 1) & AMASK;
break;
case 004: /* LDA 0 */
if (SingleCycle) Usermap = SingleCycle;
AC[0] = GetMap(MA);
if (SingleCycle) {
Usermap = SingleCycle = 0;
if (Inhibit == 1) Inhibit = 3;
MapStat |= 02000;
MapStat &= 0177776;
}
break;
case 005: /* LDA 1 */
if (SingleCycle) Usermap = SingleCycle;
AC[1] = GetMap(MA);
if (SingleCycle) {
Usermap = SingleCycle = 0;
if (Inhibit == 1) Inhibit = 3;
MapStat |= 02000;
MapStat &= 0177776;
}
break;
case 006: /* LDA 2 */
if (SingleCycle) Usermap = SingleCycle;
AC[2] = GetMap(MA);
if (SingleCycle) {
Usermap = SingleCycle = 0;
if (Inhibit == 1) Inhibit = 3;
MapStat |= 02000;
MapStat &= 0177776;
}
break;
case 007: /* LDA 3 */
if (SingleCycle) Usermap = SingleCycle;
AC[3] = GetMap(MA);
if (SingleCycle) {
Usermap = SingleCycle = 0;
if (Inhibit == 1) Inhibit = 3;
MapStat |= 02000;
MapStat &= 0177776;
}
break;
case 010: /* STA 0 */
if (SingleCycle)
Usermap = SingleCycle;
if (MEM_ADDR_OK (MA)) PutMap(MA, AC[0]);
if (SingleCycle) {
Usermap = SingleCycle = 0;
if (Inhibit == 1) Inhibit = 3;
MapStat |= 02000;
MapStat &= 0177776;
}
break;
case 011: /* STA 1 */
if (SingleCycle)
Usermap = SingleCycle;
if (MEM_ADDR_OK (MA)) PutMap(MA, AC[1]);
if (SingleCycle) {
Usermap = SingleCycle = 0;
if (Inhibit == 1) Inhibit = 3;
MapStat |= 02000;
MapStat &= 0177776;
}
break;
case 012: /* STA 2 */
if (SingleCycle)
Usermap = SingleCycle;
if (MEM_ADDR_OK (MA)) PutMap(MA, AC[2]);
if (SingleCycle) {
Usermap = SingleCycle = 0;
if (Inhibit == 1) Inhibit = 3;
MapStat |= 02000;
MapStat &= 0177776;
}
break;
case 013: /* STA 3 */
if (SingleCycle)
Usermap = SingleCycle;
if (MEM_ADDR_OK (MA)) PutMap(MA, AC[3]);
if (SingleCycle) {
Usermap = SingleCycle = 0;
if (Inhibit == 1) Inhibit = 3;
MapStat |= 02000;
MapStat &= 0177776;
}
break;
} /* end switch */
} /* end mem ref */
/* Operate instruction */
else if (t & 020) { /* operate? */
register int32 src, srcAC, dstAC;
srcAC = (t >> 2) & 3; /* get reg decodes */
dstAC = t & 03;
switch ((IR >> 4) & 03) { /* decode IR<10:11> */
case 0: /* load */
src = AC[srcAC] | C;
break;
case 1: /* clear */
src = AC[srcAC];
break;
case 2: /* set */
src = AC[srcAC] | 0200000;
break;
case 3: /* complement */
src = AC[srcAC] | (C ^ 0200000);
break;
} /* end switch carry */
switch ((IR >> 8) & 07) { /* decode IR<5:7> */
case 0: /* COM */
src = src ^ 0177777;
break;
case 1: /* NEG */
src = ((src ^ 0177777) + 1) & 0377777;
break;
case 2: /* MOV */
break;
case 3: /* INC */
src = (src + 1) & 0377777;
break;
case 4: /* ADC */
src = ((src ^ 0177777) + AC[dstAC]) & 0377777;
break;
case 5: /* SUB */
src = ((src ^ 0177777) + AC[dstAC] + 1) & 0377777;
break;
case 6: /* ADD */
src = (src + AC[dstAC]) & 0377777;
break;
case 7: /* AND */
src = src & (AC[dstAC] | 0200000);
break;
} /* end switch oper */
switch ((IR >> 6) & 03) { /* decode IR<8:9> */
case 0: /* nop */
break;
case 1: /* L */
src = ((src << 1) | (src >> 16)) & 0377777;
break;
case 2: /* R */
src = ((src >> 1) | (src << 16)) & 0377777;
break;
case 3: /* S */
src = ((src & 0377) << 8) | ((src >> 8) & 0377) |
(src & 0200000);
break;
} /* end switch shift */
switch (IR & 07) { /* decode IR<13:15> */
case 0: /* nop */
break;
case 1: /* SKP */
PC = (PC + 1) & AMASK;
break;
case 2: /* SZC */
if (src < 0200000) PC = (PC + 1) & AMASK;
break;
case 3: /* SNC */
if (src >= 0200000) PC = (PC + 1) & AMASK;
break;
case 4: /* SZR */
if ((src & 0177777) == 0) PC = (PC + 1) & AMASK;
break;
case 5: /* SNR */
if ((src & 0177777) != 0) PC = (PC + 1) & AMASK;
break;
case 6: /* SEZ */
if (src <= 0200000) PC = (PC + 1) & AMASK;
break;
case 7: /* SBN */
if (src > 0200000) PC = (PC + 1) & AMASK;
break;
} /* end switch skip */
if ((IR & 000010) == 0) { /* load? */
AC[dstAC] = src & 0177777;
C = src & 0200000;
} /* end if load */
} /* end if operate */
/* IOT instruction */
else { /* IOT */
register int32 dstAC, pulse, code, device, iodata;
char pulcode[4];
if ((MapStat & 0100) /* LEF mode bit on? */
&& Usermap) { /* We are in LEF Mode */
AC[(IR >> 11) & 3] = LEFmode(PC - 1, (IR >> 8) & 3, IR & 0377, IR & 02000);
if (Debug_Flags & 020000) {
printf("\n\r<<LEF Break by special request - executed at %o.>>\n\r", PC-1);
reason = STOP_IBKPT;
}
continue;
}
dstAC = t & 03; /* decode fields */
if ((MapStat & 040) && Usermap) { /* I/O protection fault */
Fault = 020000;
continue;
}
code = (IR >> 8) & 07;
pulse = (IR >> 6) & 03;
device = IR & 077;
if (Debug_Flags && device == 0) {
printf("\n\r<<I/O to device 00 at %o.>>\n\r", PC-1);
reason = STOP_IBKPT;
continue;
}
if ((Debug_Flags & 0100) && (device == (Debug_Flags & 077))) {
printf("\n\r<<I/O Break (device %o) >>\n\r", device);
reason = STOP_IBKPT;
continue;
}
if ((Debug_Char != 0) && (device == 011) &&
((AC[dstAC] & 0177) == Debug_Char)) {
printf("\n\r<<I/O Break (Char %o to TTO) >>\n\r", Debug_Char);
reason = STOP_IBKPT;
continue;
}
if (code == ioSKP) { /* IO skip? */
switch (pulse) { /* decode IR<8:9> */
case 0: /* skip if busy */
if ((device == 077)? (int_req & INT_ION) != 0:
(dev_busy & dev_table[device].mask) != 0)
PC = (PC + 1) & AMASK;
break;
case 1: /* skip if not busy */
if ((device == 077)? (int_req & INT_ION) == 0:
(dev_busy & dev_table[device].mask) == 0)
PC = (PC + 1) & AMASK;
break;
case 2: /* skip if done */
if ((device == 077)? pwr_low != 0:
(dev_done & dev_table[device].mask) != 0)
PC = (PC + 1) & AMASK;
break;
case 3: /* skip if not done */
if ((device == 077)? pwr_low == 0:
(dev_done & dev_table[device].mask) == 0)
PC = (PC + 1) & AMASK;
break;
} /* end switch */
} /* end IO skip */
else if (device == DEV_CPU) { /* CPU control */
switch (code) { /* decode IR<5:7> */
case ioNIO: /* Get CPU ID */
switch (model) {
case 280: /* S280 */
AC[0] = 021102;
break;
case 380:
AC[0] = 013212; /* C380 */
break;
default:
break;
}
break; /* Otherwise no-op */
case ioDIA: /* read switches */
AC[dstAC] = SR;
break;
case ioDIB: /* int ack */
AC[dstAC] = 0;
int_req = (int_req & ~INT_DEV) |
(dev_done & ~dev_disable);
iodata = int_req & (-int_req);
for (i = DEV_LOW; i <= DEV_HIGH; i++) {
if (iodata & dev_table[i].mask) {
AC[dstAC] = i;
break;
}
}
break;
case ioDOB: /* mask out */
mask_out (pimask = AC[dstAC]);
break;
case ioDIC: /* io reset IORST */
reset_all (0); /* reset devices */
Usermap = 0; /* reset MAP */
MapStat &= 04; /* Reset MAP status */
MapIntMode = 0;
Inhibit = 0;
Map31 = 037;
Check = SingleCycle = 0;
Fault = 0;
FPSR &= 0x0000FFFF;
FPFault = 0;
break;
case ioDOC: /* halt */
reason = STOP_HALT;
break;
} /* end switch code */
switch (pulse) { /* decode IR<8:9> */
case iopS: /* ion */
int_req = (int_req | INT_ION) & ~INT_NO_ION_PENDING;
break;
case iopC: /* iof */
int_req = int_req & ~INT_ION;
break; } /* end switch pulse */
} /* end CPU control */
else if (device == DEV_ECC) {
switch (code) {
case ioDIA: /* Read Fault Address */
AC[dstAC] = 0;
break;
case ioDIB: /* Read fault code */
AC[dstAC] = 0;
break;
case ioDOA: /* Enable ERCC */
break; }
}
else if (device == DEV_MAP) { /* MAP control */
switch (code) { /* decode IR<5:7> */
case ioNIO: /* No I/O -- Single */
if (!Usermap || !(MapStat & 0140)) {
if ((Debug_Flags & 077) == 03)
fprintf(Trace, "%o NIO %o (No I/O, clear faults)\n", PC-1, dstAC);
MapStat &= ~036000; /* NIO Clears all faults */
} else {
if ((Debug_Flags & 077) == 03)
fprintf(Trace, "%o NIO %o (No I/O, clear faults) NO EXEC(User mode)\n", PC-1, dstAC);
}
break;
case ioDIA: /* Read map status */
if (!Usermap || !(MapStat & 0140)) {
if ((Debug_Flags & 077) == 03)
fprintf(Trace, "%o DIA %o=%o (Read Map Status)\n", PC-1, dstAC, MapStat);
AC[dstAC] = MapStat & 0xFFFE;
if (MapIntMode & 1) /* Bit 15 is mode asof last int */
AC[dstAC] |= 1;
} else {
if ((Debug_Flags & 077) == 03)
fprintf(Trace, "%o DIA %o=%o (Read Map Status) NO EXEC(User mode)\n", PC-1, dstAC, MapStat);
}
break;
case ioDOA: /* Load map status */
if (!Usermap || !(MapStat & 0140)) {
if ((Debug_Flags & 077) == 03)
fprintf(Trace, "%o DOA %o=%o (Load Map Status)\n", PC-1, dstAC, AC[dstAC]);
MapStat = AC[dstAC];
MapIntMode = 0;
Enable = 1;
if (MapStat & 04) Enable = 2;
Check &= ~01600;
Check |= MapStat & 01600;
if (MapStat & 1)
Inhibit = 2; /* Inhibit interrupts */
} else {
if ((Debug_Flags & 077) == 03)
fprintf(Trace, "%o DOA %o=%o (Load Map Status) NO EXEC(User mode)\n", PC-1, dstAC, AC[dstAC]);
}
break;
case ioDIB: /* not used */
break;
case ioDOB: /* map block 31 */
//AOS if (!Usermap || !(MapStat && 0140)) {
if ((Debug_Flags & 077) == 03)
fprintf(Trace, "%o DOB %o=%o (Map Blk 31)\n", PC-1, dstAC, AC[dstAC]);
Map31 = AC[dstAC] & PAGEMASK;
MapStat &= ~02000;
//AOS } else {
//AOS if ((Debug_Flags & 077) == 03)
//AOS fprintf(Trace, "%o DOB %o=%o (Map Blk 31) NO EXEC (User Mode)\n", PC-1, dstAC, AC[dstAC]);
//AOS }
break;
case ioDIC: /* Page Check */
if (!Usermap || !(MapStat & 0140)) {
switch ((Check>>7) & 07) {
case 0: i=1; break;
case 1: i=6; break;
case 2: i=2; break;
case 3: i=7; break;
case 4: i=0; break;
case 5: i=4; break;
case 6: i=3; break;
case 7: i=5; break;
default: break;
}
j = (Check >> 10) & 037;
AC[dstAC] = Map[i][j] & 0101777;
AC[dstAC] |= ((Check << 5) & 070000);
if ((Debug_Flags & 077) == 03)
fprintf(Trace, "%o DIC %o=%o (Page Check)\n", PC-1, dstAC, AC[dstAC]);
MapStat &= ~02000;
} else {
if ((Debug_Flags & 077) == 03)
fprintf(Trace, "%o DIC %o=%o (Page Check) NO EXEC(User mode)\n", PC-1, dstAC, AC[dstAC]);
}
break;
case ioDOC: /* Init Page Check */
if (!Usermap || !(MapStat & 0140)) {
if ((Debug_Flags & 077) == 03)
fprintf(Trace, "%o DOC %o=%o (Init Pg Chk)\n", PC-1, dstAC, AC[dstAC]);
Check = AC[dstAC];
MapStat &= ~01600;
MapStat |= (Check & 01600);
MapStat &= ~02000;
} else {
if ((Debug_Flags & 077) == 03)
fprintf(Trace, "%o DOC %o=%o (Init Pg Chk) NO EXEC(User mode)\n", PC-1, dstAC, AC[dstAC]);
}
break;
} /* end switch code */
switch (pulse) {
case iopP:
if ((Debug_Flags & 077) == 03)
fprintf(Trace, "%o xxxP (Single Cycle)\n", PC-1);
if (Usermap) {
MapStat &= 0177776;
Usermap = 0;
Inhibit = 0;
} else {
SingleCycle = Enable;
Inhibit = 1; /* Inhibit interrupts */
}
break;
}
} /* end CPU control */
else if (dev_table[device].routine) { /* normal device */
iodata = dev_table[device].routine (pulse, code, AC[dstAC]);
reason = iodata >> IOT_V_REASON;
if (code & 1) AC[dstAC] = iodata & 0177777;
if ((Debug_Flags & 077) == device && Debug_Flags != 0) {
strcpy(pulcode, "");
switch (pulse) {
case iopP:
strcpy(pulcode, "P");
break;
case iopS:
strcpy(pulcode, "S");
break;
case iopC:
strcpy(pulcode, "C");
break;
default:
break;
}
switch(code) {
case ioNIO:
fprintf(Trace, "[%o] %o NIO%s %o\n", device, PC-1, pulcode, AC[dstAC]);
break;
case ioDIA:
fprintf(Trace, "[%o] %o DIA%s %o\n", device, PC-1, pulcode, iodata);
break;
case ioDIB:
fprintf(Trace, "[%o] %o DIB%s %o\n", device, PC-1, pulcode, iodata);
break;
case ioDIC:
fprintf(Trace, "[%o] %o DIC%s %o\n", device, PC-1, pulcode, iodata);
break;
case ioDOA:
fprintf(Trace, "[%o] %o DOA%s %o\n", device, PC-1, pulcode, AC[dstAC]);
break;
case ioDOB:
fprintf(Trace, "[%o] %o DOB%s %o\n", device, PC-1, pulcode, AC[dstAC]);
break;
case ioDOC:
fprintf(Trace, "[%o] %o DOC%s %o\n", device, PC-1, pulcode, AC[dstAC]);
break;
default:
break;
} /* end switch */
} /* end if debug */
} /* end else if */
else reason = stop_dev;
} /* end if IOT */
} /* end while */
/* Simulation halted */
saved_PC = PC;
return reason;
}
/* Computes and returns a 16-bit effective address, given a
program counter, index, and a displacement.
*/
int32 effective(int32 PC, int32 index, int32 disp)
{
register int32 i, MA;
MA = disp & 077777;
switch (index) { /* decode IR<6:7> */
case 0: /* page zero */
break;
case 1: /* PC relative */
MA = (MA + PC) & AMASK;
break;
case 2: /* AC2 relative */
MA = (MA + AC[2]) & AMASK;
break;
case 3: /* AC3 relative */
MA = (MA + AC[3]) & AMASK;
break;
} /* end switch mode */
if (disp & 0100000) { /* indirect? */
for (i = 0; i < ind_max * 2; i++) { /* count indirects */
MA = GetMap(MA & AMASK);
if (SingleCycle) Usermap = 0;
if (MapStat & 1) { /* Start MAP */
Usermap = Enable;
Inhibit = 0;
}
if ((MA & 0100000) == 0) break;
if ((MapStat & 010) && Usermap && i >= ind_max) break;
}
if (i >= (ind_max-1) && (MapStat & 010) && Usermap) {
Fault = 04000; /* Map fault if IND prot */
}
if (i >= (ind_max * 2) && !(Fault)) {
reason = STOP_IND_INT; /* Stop machine */
}
}
return (MA & AMASK);
}
/* Computes and returns a 16-bit effective address, given a
program counter, index, and a displacement. This is a
version supporting the LEF map mode instruction, as
opposed to the ELEF instruction.
*/
int32 LEFmode(int32 PC, int32 index, int32 disp, int32 indirect)
{
register int32 i, MA;
int16 sMA;
MA = disp & 077777;
switch (index) { /* decode IR<6:7> */
case 0: /* page zero */
break;
case 1: /* PC relative */
sMA = MA;
if (MA & 0200) sMA |= 0xff00;
MA = (sMA + PC) & AMASK;
break;
case 2: /* AC2 relative */
sMA = MA;
if (MA & 0200) sMA |= 0xff00;
MA = (sMA + AC[2]) & AMASK;
break;
case 3: /* AC3 relative */
sMA = MA;
if (MA & 0200) sMA |= 0xff00;
MA = (sMA + AC[3]) & AMASK;
break;
} /* end switch mode */
if (indirect) { /* indirect? */
for (i = 0; i < (ind_max * 2); i++) { /* count indirects */
if ((MA & 077770) == 020 && !(cpu_unit.flags & UNIT_MICRO))
MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) + 1) & 0177777));
else if ((MA & 077770) == 030 && !(cpu_unit.flags & UNIT_MICRO))
MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) - 1) & 0177777));
else MA = GetMap(MA & AMASK);
if (SingleCycle) Usermap = 0;
if (MapStat & 1) { /* Start MAP */
Usermap = Enable;
Inhibit = 0;
}
if ((MA & 0100000) == 0) break;
if ((MapStat & 010) && Usermap && i >= ind_max) break;
}
if (i >= (ind_max-1) && (MapStat & 010) && Usermap) {
Fault = 04000; /* Map fault if IND prot */
}
if (i >= (ind_max * 2) && !(Fault)) {
reason = STOP_IND_INT; /* Stop machine */
}
}
return (MA & AMASK);
}
/* Computes a "Byte pointer" for the Character Instruction set */
/* This address in 'PC' must point to the displacement word of the instruction */
int32 Bytepointer(int32 PC, int32 index)
{
register int32 MA;
switch (index) { /* decode IR<6:7> */
case 0: /* page zero */
MA = 0;
break;
case 1: /* PC relative */
MA = PC & AMASK;
break;
case 2: /* AC2 relative */
MA = AC[2] & AMASK;
break;
case 3: /* AC3 relative */
MA = AC[3] & AMASK;
break;
} /* end switch mode */
MA = (MA * 2) & 0177777;
MA = MA + GetMap(PC);
return (MA & 0177777);
}
/* Given an address, returns either that address if bit 0 is 0, or
or follows an indirection chain until bit 0 is 0
*/
int32 indirect(int32 d)
{
int i;
if (d & 0100000) { /* indirect? */
for (i = 0; i < ind_max * 2; i++) { /* count indirects */
if ((d & 077770) == 020 && !(cpu_unit.flags & UNIT_MICRO))
d = (PutMap(d & AMASK, ((GetMap(d & AMASK) + 1) & 0177777)));
else if ((d & 077770) == 030 && !(cpu_unit.flags & UNIT_MICRO))
d = (PutMap(d & AMASK, ((GetMap(d & AMASK) - 1) & 0177777)));
else d = GetMap(d & AMASK);
if (MapStat & 1) { /* Start MAP */
Usermap = Enable;
Inhibit = 0;
}
if ((d & 0100000) == 0) break;
if ((MapStat & 010) && Usermap && i >= ind_max) break;
}
if (i >= (ind_max-1) && (MapStat & 010) && Usermap) {
Fault = 04000; /* Map fault if IND prot */
}
if (i >= (ind_max * 2) && !(Fault)) {
reason = STOP_IND; /* Stop machine */
}
}
return (d);
}
/* Push a standard return block onto the stack */
int32 pushrtn(int32 pc)
{
int32 t;
t = (GetMap(040) + 1) & AMASK;
PutMap(t, AC[0]);
t++;
PutMap(t, AC[1]);
t++;
PutMap(t, AC[2]);
t++;
PutMap(t, AC[3]);
t++;
PutMap(t, pc);
if (C) PutMap(t, (GetMap(t) | 0100000));
PutMap(040, t);
return 0;
}
/* Eclipse memory get/put - uses MAP if enabled */
int32 GetMap(int32 addr)
{
int32 page;
t_addr paddr;
switch (Usermap) {
case 0:
if (addr < 076000)
return M[addr];
paddr = ((Map31 & PAGEMASK) << 10) | (addr & 001777);
if (paddr < MEMSIZE)
return M[paddr];
else
return (0);
break;
case 1:
page = (addr >> 10) & 037;
paddr = ((Map[1][page] & 01777) << 10) | (addr & 001777);
if (Map[1][page] == INVALID && !SingleCycle)
Fault = 0100000/*!!!*/; /* Validity */
if (paddr < MEMSIZE)
return M[paddr];
else
return (0);
break;
case 2:
page = (addr >> 10) & 037;
paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777);
if (Map[2][page] == INVALID && !SingleCycle)
Fault = 0100000/*!!!*/; /* Validity */
if (paddr < MEMSIZE)
return M[paddr];
else
return (0);
break;
case 6:
page = (addr >> 10) & 037;
paddr = ((Map[6][page] & PAGEMASK) << 10) | (addr & 001777);
if (Map[6][page] == INVALID && !SingleCycle)
Fault = 0100000/*!!!*/; /* Validity */
if (paddr < MEMSIZE)
return M[paddr];
else
return (0);
break;
case 7:
page = (addr >> 10) & 037;
paddr = ((Map[7][page] & PAGEMASK) << 10) | (addr & 001777);
if (Map[7][page] == INVALID && !SingleCycle)
Fault = 0100000/*!!!*/; /* Validity */
if (paddr < MEMSIZE)
return M[paddr];
else
return (0);
break;
default:
printf("\n\r<<MAP FAULT>>\n\r");
return M[addr];
break;
}
}
int32 PutMap(int32 addr, int32 data)
{
int32 page;
t_addr paddr;
switch (Usermap) {
case 0:
if (addr < 076000) {
M[addr] = data;
return (data);
}
paddr = ((Map31 & PAGEMASK) << 10) | (addr & 001777);
if (paddr < MEMSIZE) M[paddr] = data;
break;
case 1:
page = (addr >> 10) & 037;
paddr = ((Map[1][page] & PAGEMASK) << 10) | (addr & 001777);
if (((Map[1][page] & 0100000) && (MapStat & 020)) || Map[1][page] == INVALID)
Fault = 010000; /* Write Protect Fault */
else if (paddr < MEMSIZE) M[paddr] = data;
break;
case 2:
page = (addr >> 10) & 037;
paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777);
if (((Map[2][page] & 0100000) && (MapStat & 020)) || Map[2][page] == INVALID)
Fault = 010000; /* Write Protect Fault */
else if (paddr < MEMSIZE) M[paddr] = data;
break;
case 6:
page = (addr >> 10) & 037;
paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777);
if (((Map[6][page] & 0100000) && (MapStat & 020)) || Map[6][page] == INVALID)
Fault = 010000; /* Write Protect Fault */
else if (paddr < MEMSIZE) M[paddr] = data;
break;
case 7:
page = (addr >> 10) & 037;
paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777);
if (((Map[7][page] & 0100000) && (MapStat & 020)) || Map[7][page] == INVALID)
Fault = 010000; /* Write Protect Fault */
else if (paddr < MEMSIZE) M[paddr] = data;
break;
default:
M[addr] = data;
break;
}
return (data);
}
#if 0
int16 GetDCHMap(int32 map, int32 addr)
{
t_addr paddr;
if (!(MapStat & 02)) return M[addr];
paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777);
if (paddr < MEMSIZE)
return M[paddr];
return (0);
}
int16 PutDCHMap(int32 map, int32 addr, int16 data)
{
t_addr paddr;
if (!(MapStat & 02)) {
M[addr] = data;
return (data);
}
paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777);
if (paddr < MEMSIZE)
M[paddr] = data;
return (data);
}
#endif
/* Given a map number and a logical, returns the physical address, unless
the map is not active, in which case logical = physical. This is
used primarily by the I/O routines to map data channel read/writes.
*/
int32 MapAddr(int32 map, int32 addr)
{
int32 paddr;
if ((map == 0 || map > 2) && !(MapStat & 02)) return addr;
if (map > 0 && map < 3 && Usermap == 0) return addr;
paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777);
return paddr;
}
/* Loads a word into the Eclipse Maps */
int32 LoadMap(int32 w)
{
int32 m;
m = (w >> 10) & 037;
switch ((MapStat >> 7) & 07) {
case 0: /* Load user A Map */
Map[1][m] = w & MAPMASK;
break;
case 1: /* Load user C Map */
Map[6][m] = w & MAPMASK;
break;
case 2: /* Load user B Map */
Map[2][m] = w & MAPMASK;
break;
case 3: /* Load user D Map */
Map[7][m] = w & MAPMASK;
break;
case 4: /* Load DCH A Map */
Map[0][m] = w & MAPMASK;
break;
case 5: /* Load DCH C Map */
Map[4][m] = w;
break;
case 6: /* Load DCH B Map */
Map[3][m] = w;
break;
case 7: /* Load DCH D Map */
Map[5][m] = w;
break;
default:
break;
}
return 0;
}
/* Displays an error on a unimplemented (in this sim) instr. */
int32 unimp(int32 PC)
{
if (Debug_Flags)
printf("\n\r\007<<<Unimplemented instruction: [%o] %o>>>\n\r", PC - 1, GetMap(PC - 1));
return 0;
}
/* New priority mask out */
void mask_out (int32 newmask)
{
int32 i;
dev_disable = 0;
for (i = DEV_LOW; i <= DEV_HIGH; i++) {
if (newmask & dev_table[i].pi)
dev_disable = dev_disable | dev_table[i].mask;
}
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
return;
}
/* Reset routine */
t_stat cpu_reset (DEVICE *dptr)
{
int_req = int_req & ~INT_ION;
pimask = 0;
dev_disable = 0;
pwr_low = 0;
sim_brk_types = sim_brk_dflt = SWMASK ('E');
return SCPE_OK;
}
/* Memory examine */
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
{
if (sw & SWMASK ('V')) {
if (addr > 077777) return SCPE_NXM;
if (vptr != NULL) *vptr = GetMap (addr);
}
else {
if (addr >= MEMSIZE) return SCPE_NXM;
if (vptr != NULL) *vptr = M[addr] & 0177777;
}
return SCPE_OK;
}
/* Memory deposit */
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
{
if (sw & SWMASK ('V')) {
if (addr > 077777) return SCPE_NXM;
PutMap (addr, (int32) val);
}
else {
if (addr >= MEMSIZE) return SCPE_NXM;
M[addr] = (int32) val & 0177777;
}
return SCPE_OK;
}
/* Alter memory size */
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 mc = 0;
t_addr i;
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
return SCPE_ARG;
for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
return SCPE_OK;
MEMSIZE = val;
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
return SCPE_OK;
}
/* MAP device services */
t_stat map_svc (UNIT *uptr)
{
return SCPE_OK;
}
/* Map examine */
t_stat map_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
{
if ((addr & 077) >= 037 || addr > 737) return SCPE_NXM;
uptr->u4 = -2; /* signal to print_sys in eclipse_sys.c: do not map */
if (vptr != NULL) *vptr = Map[(addr >> 6) & 3][addr & 037] & 0177777;
return SCPE_OK;
}
/* Memory deposit */
t_stat map_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
{
if ((addr & 077) >= 037 || addr > 0737) return SCPE_NXM;
uptr->u4 = -2; /* signal to print_sys in eclipse_sys.c: do not map */
Map[(addr >> 6) & 3][addr & 037] = (int32)val & 0177777;
return SCPE_OK;
}
/* FPU device services */
t_stat fpu_svc (UNIT *uptr)
{
return SCPE_OK;
}
/* PIT Device Services */
/* IOT routine */
int32 pit (int32 pulse, int32 code, int32 AC)
{
int32 iodata = 0;
if (code == ioDIA) { /* DIA */
if (pit_flag == 0) {
pit_flag = 1;
}
iodata = pit_counter;
}
if (code == ioDOA) { /* DOA */
pit_initial = AC; /* Load Counter */
sim_rtcn_init (pit_time, 1); /* init calibr */
}
switch (pulse) { /* decode IR<8:9> */
case iopS: /* start */
pit_counter = pit_initial; /* Set the counter */
dev_busy = dev_busy | INT_PIT; /* set busy */
dev_done = dev_done & ~INT_PIT; /* clear done, int */
int_req = int_req & ~INT_PIT;
if (!sim_is_active (&pit_unit)) /* not running? */
sim_activate (&pit_unit, /* activate */
sim_rtcn_init (pit_time, 1)); /* init calibr */
break;
case iopC: /* clear */
dev_busy = dev_busy & ~INT_PIT; /* clear busy */
dev_done = dev_done & ~INT_PIT; /* clear done, int */
int_req = int_req & ~INT_PIT;
sim_cancel (&pit_unit); /* deactivate unit */
break; } /* end switch */
return iodata;
}
/* Unit service */
t_stat pit_svc (UNIT *uptr)
{
int32 t;
t = sim_rtcn_calb (pit_tps, 1); /* calibrate delay */
sim_activate (&pit_unit, t); /* reactivate unit */
pit_poll = t / (-pit_adj); /* adjust poll */
pit_counter++; /* Increment counter */
if (pit_counter >= 0177777) { /* Has counter reached limit ? */
dev_done = dev_done | INT_PIT; /* set done */
dev_busy = dev_busy & ~INT_PIT; /* clear busy */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); /* Interrupt */
pit_counter = pit_initial;
}
return SCPE_OK;
}
/* Reset routine */
t_stat pit_reset (DEVICE *dptr)
{
pit_counter = 0; /* clear counter */
dev_busy = dev_busy & ~INT_PIT; /* clear busy */
dev_done = dev_done & ~INT_PIT; /* clear done, int */
int_req = int_req & ~INT_PIT;
sim_cancel (&pit_unit); /* deactivate unit */
pit_poll = pit_time; /* poll is default */
return SCPE_OK;
}
/* Bootstrap routine for CPU */
#define BOOT_START 00000
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
static const int32 boot_rom[] = {
062677, /* IORST ;Reset all I/O */
060477, /* READS 0 ;Read SR into AC0 */
024026, /* LDA 1,C77 ;Get dev mask */
0107400, /* AND 0,1 ;Isolate dev code */
0124000, /* COM 1,1 ;- device code - 1 */
010014, /* LOOP: ISZ OP1 ;Device code to all */
010030, /* ISZ OP2 ;I/O instructions */
010032, /* ISZ OP3 */
0125404, /* INC 1,1,SZR ;done? */
000005, /* JMP LOOP ;No, increment again */
030016, /* LDA 2,C377 ;place JMP 377 into */
050377, /* STA 2,377 ;location 377 */
060077, /* OP1: 060077 ;start device (NIOS 0) */
0101102, /* MOVL 0,0,SZC ;Test switch 0, low speed? */
000377, /* C377: JMP 377 ;no - jmp 377 & wait */
004030, /* LOOP2: JSR GET+1 ;Get a frame */
0101065, /* MOVC 0,0,SNR ;is it non-zero? */
000017, /* JMP LOOP2 ;no, ignore */
004027, /* LOOP4: JSR GET ;yes, get full word */
046026, /* STA 1,@C77 ;store starting at 100 */
/* ;2's complement of word ct */
010100, /* ISZ 100 ;done? */
000022, /* JMP LOOP4 ;no, get another */
000077, /* C77: JMP 77 ;yes location ctr and */
/* ;jmp to last word */
0126420, /* GET: SUBZ 1,1 ; clr AC1, set carry */
/* OP2: */
063577, /* LOOP3: 063577 ;done? (SKPDN 0) - 1 */
000030, /* JMP LOOP3 ;no -- wait */
060477, /* OP3: 060477 ;y--read in ac0 (DIAS 0,0) */
0107363, /* ADDCS 0,1,SNC ;add 2 frames swapped - got 2nd? */
000030, /* JMP LOOP3 ;no go back after it */
0125300, /* MOVS 1,1 ;yes swap them */
001400, /* JMP 0,3 ;rtn with full word */
0 /* 0 ;padding */
};
t_stat cpu_boot (int32 unitno, DEVICE *dptr)
{
size_t i;
extern int32 saved_PC;
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
saved_PC = BOOT_START;
return SCPE_OK;
}
int32 Debug_Entry(int32 PC, int32 inst, int32 inst2, int32 AC0, int32 AC1, int32 AC2, int32 AC3, int32 flags)
{
hpc[hnext] = PC & 0xffff;
hinst[hnext] = inst & 0xffff;
hinst2[hnext] = inst2 & 0xffff;
hac0[hnext] = AC0 & 0xffff;
hac1[hnext] = AC1 & 0xffff;
hac2[hnext] = AC2 & 0xffff;
hac3[hnext] = AC3 & 0xffff;
hflags[hnext] = flags & 0xffff;
hnext++;
if (hnext >= hmax) {
hwrap = 1;
hnext = 0;
}
return 0;
}
t_stat Debug_Dump(UNIT *uptr, int32 val, char *cptr, void *desc)
{
return SCPE_OK;
}
t_stat Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc)
{
char debmap[4], debion[4];
t_value simeval[20];
int debcar;
int start, end, ctr;
int count = 0;
if (!Debug_Flags || Debug_Flags & 0100000) {
printf("History was not logged. Deposit a non-zero value\n");
printf("in DEBUG with bit 0 being 1 to build history.\n");
return SCPE_OK;
}
if (!hwrap) {
start = 0;
end = hnext;
} else {
start = hnext;
end = hnext - 1;
if (end < 0) end = hmax;
}
ctr = start;
while (1) {
if (ctr == end)
break;
count++;
strcpy(debion, " ");
strcpy(debmap, " ");
debcar = 0;
if (hflags[ctr] & 0x80) {
fprintf(st, "--------- Interrupt %o (%o) to %6o ---------\n",
hinst[ctr], hac0[ctr], hac1[ctr]);
} else {
if (hflags[ctr] & 0x01) debcar = 1;
if (hflags[ctr] & 0x02) strcpy(debion, "I");
if (hflags[ctr] & 0x04) strcpy(debmap, "A");
if (hflags[ctr] & 0x08) strcpy(debmap, "B");
if (hflags[ctr] & 0x10) strcpy(debmap, "C");
if (hflags[ctr] & 0x20) strcpy(debmap, "D");
fprintf(st, "%s%s%06o acs: %06o %06o %06o %06o %01o ",
debion, debmap, hpc[ctr], hac0[ctr], hac1[ctr], hac2[ctr],
hac3[ctr], debcar);
simeval[0] = hinst[ctr];
simeval[1] = hinst2[ctr];
fprint_sym (st, hpc[ctr], simeval, NULL, SWMASK('M'));
fprintf(st, "\n");
}
ctr++;
if (ctr > hmax)
ctr = 0;
}
return SCPE_OK;
}
/* Build dispatch table */
t_stat build_devtab (void)
{
DEVICE *dptr;
DIB *dibp;
int32 i, dn;
for (i = 0; i < 64; i++) { /* clr dev_table */
dev_table[i].mask = 0;
dev_table[i].pi = 0;
dev_table[i].routine = NULL;
}
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */
if (!(dptr->flags & DEV_DIS) && /* enabled and */
(dibp = (DIB *) dptr->ctxt)) { /* defined DIB? */
dn = dibp->dnum; /* get dev num */
dev_table[dn].mask = dibp->mask; /* copy entries */
dev_table[dn].pi = dibp->pi;
dev_table[dn].routine = dibp->routine;
}
}
return SCPE_OK;
}
/* ------------------------------------------------------------------- */
/* Floating Point Arithmetic */
/* ------------------------------------------------------------------- */
/* Get short float from FPAC */
void get_sf (SHORT_FLOAT *fl, t_int64 *fpr)
{
fl->sign = (uint8)(*fpr >> 63) & 1;
fl->expo = (short)(*fpr >> 56) & 0x007F;
fl->short_fract = (int32)(*fpr >> 32) & 0x00FFFFFF;
}
/* Store short float to FPAC */
void store_sf (SHORT_FLOAT *fl, t_int64 *fpr)
{
*fpr = 0;
*fpr = ((t_int64)fl->sign << 63)
| ((t_int64)fl->expo << 56)
| ((t_int64)fl->short_fract <<32);
}
/* Get long float from FPAC */
void get_lf (LONG_FLOAT *fl, t_int64 *fpr)
{
fl->sign = (uint8)(*fpr >> 63) & 1;
fl->expo = (short)(*fpr >> 56) & 0x007F;
fl->long_fract = (t_int64)*fpr & 0x00FFFFFFFFFFFFFF;
}
/* Store long float to FPAC */
void store_lf (LONG_FLOAT *fl, t_int64 *fpr)
{
*fpr = 0;
*fpr = (t_int64)fl->sign << 63;
*fpr |= ((t_int64)fl->expo << 56) & 0x7f00000000000000;
*fpr |= fl->long_fract;
}
/* Check short for Overflow */
int overflow_sf (SHORT_FLOAT *fl)
{
if (fl->expo > 127) {
fl->expo &= 0x007F;
return(1);
}
return(0);
}
/* Normalize Short Float */
int normal_sf(SHORT_FLOAT *fl)
{
if (fl->short_fract) {
if ((fl->short_fract & 0x00FFFF00) == 0) {
fl->short_fract <<= 16;
fl->expo -= 4;
}
if ((fl->short_fract & 0x00FF0000) == 0) {
fl->short_fract <<= 8;
fl->expo -= 2;
}
if ((fl->short_fract & 0x00F00000) == 0) {
fl->short_fract <<= 4;
(fl->expo)--;
}
} else {
fl->sign = 0;
fl->expo = 0;
}
if (fl->expo < 0)
return (2);
return(0);
}
/* Normalize long float */
int normal_lf (LONG_FLOAT *fl)
{
if (fl->long_fract) {
if ((fl->long_fract & 0x00FFFFFFFF000000) == 0) {
fl->long_fract <<= 32;
fl->expo -= 8;
}
if ((fl->long_fract & 0x00FFFF0000000000) == 0) {
fl->long_fract <<= 16;
fl->expo -= 4;
}
if ((fl->long_fract & 0x00FF000000000000) == 0) {
fl->long_fract <<= 8;
fl->expo -= 2;
}
if ((fl->long_fract & 0x00F0000000000000) == 0) {
fl->long_fract <<= 4;
(fl->expo)--;
}
} else {
fl->sign = 0;
fl->expo = 0;
}
if (fl->expo < 0)
return (2);
return(0);
}
/* Check Long for Overflow */
int overflow_lf(LONG_FLOAT *fl)
{
if (fl->expo > 127) {
fl->expo &= 0x007F;
return(1);
}
return(0);
}
int underflow_sf(SHORT_FLOAT *fl)
{
if (fl->expo < 0) {
fl->short_fract = 0;
fl->expo = 0;
fl->sign = 0;
}
return(0);
}
int underflow_lf(LONG_FLOAT *fl)
{
if (fl->expo < 0) {
fl->long_fract = 0;
fl->expo = 0;
fl->sign = 0;
}
return(0);
}
/* Check Short for Over/Under flow */
int over_under_flow_sf(SHORT_FLOAT *fl)
{
if (fl->expo > 127) {
fl->expo &= 0x007F;
return(1);
} else {
if (fl->expo < 0) {
/* set true 0 */
fl->short_fract = 0;
fl->expo = 0;
fl->sign = 0;
}
}
return(0);
}
/* Check Long for Over/Under flow */
int over_under_flow_lf(LONG_FLOAT *fl)
{
if (fl->expo > 127) {
fl->expo &= 0x007F;
return(1);
} else {
if (fl->expo < 0) {
/* set true 0 */
fl->long_fract = 0;
fl->expo = 0;
fl->sign = 0;
}
}
return(0);
}
int significance_sf (SHORT_FLOAT *fl)
{
fl->sign = 0;
fl->expo = 0;
return(0);
}
int significance_lf (LONG_FLOAT *fl)
{
fl->sign = 0;
fl->expo = 0;
return(0);
}
/*-------------------------------------------------------------------*/
/* Add short float */
/* */
/* Input: */
/* fl Float */
/* add_fl Float to be added */
/* normal Normalize if true */
/* Value: */
/* exeption */
/*-------------------------------------------------------------------*/
int add_sf (SHORT_FLOAT *fl, SHORT_FLOAT *add_fl, int normal)
{
int pgm_check;
int shift;
pgm_check = 0;
if (add_fl->short_fract
|| add_fl->expo) { /* add_fl not 0 */
if (fl->short_fract
|| fl->expo) { /* fl not 0 */
/* both not 0 */
if (fl->expo == add_fl->expo) {
/* expo equal */
/* both guard digits */
fl->short_fract <<= 4;
add_fl->short_fract <<= 4;
} else {
/* expo not equal, denormalize */
if (fl->expo < add_fl->expo) {
/* shift minus guard digit */
shift = add_fl->expo - fl->expo - 1;
fl->expo = add_fl->expo;
if (shift) {
if (shift >= 6
|| ((fl->short_fract >>= (shift * 4)) == 0)) {
/* 0, copy summand */
fl->sign = add_fl->sign;
fl->short_fract = add_fl->short_fract;
if (fl->short_fract == 0) {
pgm_check = significance_sf(fl);
} else {
if (normal) {
normal_sf(fl);
pgm_check = underflow_sf(fl);
}
}
return(pgm_check);
}
}
/* guard digit */
add_fl->short_fract <<= 4;
} else {
/* shift minus guard digit */
shift = fl->expo - add_fl->expo - 1;
if (shift) {
if (shift >= 6
|| ((add_fl->short_fract >>= (shift * 4)) == 0)) {
/* 0, nothing to add */
if (fl->short_fract == 0) {
pgm_check = significance_sf(fl);
} else {
if (normal) {
normal_sf(fl);
pgm_check = underflow_sf(fl);
}
}
return(pgm_check);
}
}
/* guard digit */
fl->short_fract <<= 4;
}
}
/* compute with guard digit */
if (fl->sign == add_fl->sign) {
fl->short_fract += add_fl->short_fract;
} else {
if (fl->short_fract == add_fl->short_fract) {
/* true 0 */
fl->short_fract = 0;
return( significance_sf(fl) );
} else if (fl->short_fract > add_fl->short_fract) {
fl->short_fract -= add_fl->short_fract;
} else {
fl->short_fract = add_fl->short_fract - fl->short_fract;
fl->sign = add_fl->sign;
}
}
/* handle overflow with guard digit */
if (fl->short_fract & 0xF0000000) {
fl->short_fract >>= 8;
(fl->expo)++;
pgm_check = overflow_sf(fl);
} else {
if (normal) {
/* normalize with guard digit */
if (fl->short_fract) {
/* not 0 */
if (fl->short_fract & 0x0F000000) {
/* not normalize, just guard digit */
fl->short_fract >>= 4;
} else {
(fl->expo)--;
normal_sf(fl);
pgm_check = underflow_sf(fl);
}
} else {
/* true 0 */
pgm_check = significance_sf(fl);
}
} else {
/* not normalize, just guard digit */
fl->short_fract >>= 4;
if (fl->short_fract == 0) {
pgm_check = significance_sf(fl);
}
}
}
return(pgm_check);
} else { /* fl 0, add_fl not 0 */
/* copy summand */
fl->expo = add_fl->expo;
fl->sign = add_fl->sign;
fl->short_fract = add_fl->short_fract;
if (fl->short_fract == 0) {
return( significance_sf(fl) );
}
}
} else { /* add_fl 0 */
if (fl->short_fract == 0) { /* fl 0 */
/* both 0 */
return( significance_sf(fl) );
}
}
if (normal) {
normal_sf(fl);
pgm_check = underflow_sf(fl);
}
return(pgm_check);
}
/*-------------------------------------------------------------------*/
/* Add long float */
/* */
/* Input: */
/* fl Float */
/* add_fl Float to be added */
/* normal Normalize if true */
/* Value: */
/* exeption */
/*-------------------------------------------------------------------*/
int add_lf (LONG_FLOAT *fl, LONG_FLOAT *add_fl, int normal)
{
int pgm_check;
int shift;
pgm_check = 0;
if (add_fl->long_fract
|| add_fl->expo) { /* add_fl not 0 */
if (fl->long_fract
|| fl->expo) { /* fl not 0 */
/* both not 0 */
if (fl->expo == add_fl->expo) {
/* expo equal */
/* both guard digits */
fl->long_fract <<= 4;
add_fl->long_fract <<= 4;
} else {
/* expo not equal, denormalize */
if (fl->expo < add_fl->expo) {
/* shift minus guard digit */
shift = add_fl->expo - fl->expo - 1;
fl->expo = add_fl->expo;
if (shift) {
if (shift >= 14
|| ((fl->long_fract >>= (shift * 4)) == 0)) {
/* 0, copy summand */
fl->sign = add_fl->sign;
fl->long_fract = add_fl->long_fract;
if (fl->long_fract == 0) {
pgm_check = significance_lf(fl);
} else {
if (normal) {
normal_lf(fl);
pgm_check = underflow_lf(fl);
}
}
return(pgm_check);
}
}
/* guard digit */
add_fl->long_fract <<= 4;
} else {
/* shift minus guard digit */
shift = fl->expo - add_fl->expo - 1;
if (shift) {
if (shift >= 14
|| ((add_fl->long_fract >>= (shift * 4)) == 0)) {
/* 0, nothing to add */
if (fl->long_fract == 0) {
pgm_check = significance_lf(fl);
} else {
if (normal) {
normal_lf(fl);
pgm_check = underflow_lf(fl);
}
}
return(pgm_check);
}
}
/* guard digit */
fl->long_fract <<= 4;
}
}
/* compute with guard digit */
if (fl->sign == add_fl->sign) {
fl->long_fract += add_fl->long_fract;
} else {
if (fl->long_fract == add_fl->long_fract) {
/* true 0 */
fl->long_fract = 0;
return( significance_lf(fl) );
} else if (fl->long_fract > add_fl->long_fract) {
fl->long_fract -= add_fl->long_fract;
} else {
fl->long_fract = add_fl->long_fract - fl->long_fract;
fl->sign = add_fl->sign;
}
}
/* handle overflow with guard digit */
if (fl->long_fract & 0xF000000000000000) {
fl->long_fract >>= 8;
(fl->expo)++;
pgm_check = overflow_lf(fl);
} else {
if (normal) {
/* normalize with guard digit */
if (fl->long_fract) {
/* not 0 */
if (fl->long_fract & 0x0F00000000000000) {
/* not normalize, just guard digit */
fl->long_fract >>= 4;
} else {
(fl->expo)--;
normal_lf(fl);
pgm_check = underflow_lf(fl);
}
} else {
/* true 0 */
pgm_check = significance_lf(fl);
}
} else {
/* not normalize, just guard digit */
fl->long_fract >>= 4;
if (fl->long_fract == 0) {
pgm_check = significance_lf(fl);
}
}
}
return(pgm_check);
} else { /* fl 0, add_fl not 0 */
/* copy summand */
fl->expo = add_fl->expo;
fl->sign = add_fl->sign;
fl->long_fract = add_fl->long_fract;
if (fl->long_fract == 0) {
return( significance_lf(fl) );
}
}
} else { /* add_fl 0 */
if (fl->long_fract == 0) { /* fl 0 */
/* both 0 */
return( significance_lf(fl) );
}
}
if (normal) {
normal_lf(fl);
pgm_check = underflow_lf(fl);
}
return(pgm_check);
}
/*-------------------------------------------------------------------*/
/* Multiply short float */
/* */
/* Input: */
/* fl Multiplicand short float */
/* mul_fl Multiplicator short float */
/* Value: */
/* exeption */
/*-------------------------------------------------------------------*/
int mul_sf(SHORT_FLOAT *fl, SHORT_FLOAT *mul_fl)
{
t_int64 wk;
if (fl->short_fract
&& mul_fl->short_fract) {
/* normalize operands */
normal_sf( fl );
normal_sf( mul_fl );
/* multiply fracts */
wk = (t_int64) fl->short_fract * mul_fl->short_fract;
/* normalize result and compute expo */
if (wk & 0x0000F00000000000) {
fl->short_fract = (int32)wk >> 24;
fl->expo = (short)fl->expo + mul_fl->expo - 64;
} else {
fl->short_fract = (int32)wk >> 20;
fl->expo = (short)fl->expo + mul_fl->expo - 65;
}
/* determine sign */
fl->sign = (fl->sign == mul_fl->sign) ? 0 : 1;
/* handle overflow and underflow */
return( over_under_flow_sf(fl) );
} else {
/* set true 0 */
fl->short_fract = 0;
fl->expo = 0;
fl->sign = 0;
return(0);
}
}
/*-------------------------------------------------------------------*/
/* Multiply long float */
/* */
/* Input: */
/* fl Multiplicand long float */
/* mul_fl Multiplicator long float */
/* Value: */
/* exeption */
/*-------------------------------------------------------------------*/
int mul_lf(LONG_FLOAT *fl, LONG_FLOAT *mul_fl)
{
t_int64 wk;
int32 v;
if (fl->long_fract
&& mul_fl->long_fract) {
/* normalize operands */
normal_lf( fl );
normal_lf( mul_fl );
/* multiply fracts by sum of partial multiplications */
wk = ((fl->long_fract & 0x00000000FFFFFFFF) * (mul_fl->long_fract & 0x00000000FFFFFFFF)) >> 32;
wk += ((fl->long_fract & 0x00000000FFFFFFFF) * (mul_fl->long_fract >> 32));
wk += ((fl->long_fract >> 32) * (mul_fl->long_fract & 0x00000000FFFFFFFF));
v = (int32)wk;
fl->long_fract = (wk >> 32) + ((fl->long_fract >> 32) * (mul_fl->long_fract >> 32));
/* normalize result and compute expo */
if (fl->long_fract & 0x0000F00000000000) {
fl->long_fract = (fl->long_fract << 8)
| (v >> 24);
fl->expo = fl->expo + mul_fl->expo - 64;
} else {
fl->long_fract = (fl->long_fract << 12)
| (v >> 20);
fl->expo = fl->expo + mul_fl->expo - 65;
}
/* determine sign */
fl->sign = (fl->sign == mul_fl->sign) ? 0 : 1;
/* handle overflow and underflow */
return( over_under_flow_lf(fl) );
} else {
/* set true 0 */
fl->long_fract = 0;
fl->expo = 0;
fl->sign = 0;
return(0);
}
}
/*-------------------------------------------------------------------*/
/* Divide short float */
/* */
/* Input: */
/* fl Dividend short float */
/* div_fl Divisor short float */
/* Value: */
/* exeption */
/*-------------------------------------------------------------------*/
int div_sf(SHORT_FLOAT *fl, SHORT_FLOAT *div_fl)
{
t_int64 wk;
if (div_fl->short_fract) {
if (fl->short_fract) {
/* normalize operands */
normal_sf( fl );
normal_sf( div_fl );
/* position fracts and compute expo */
if (fl->short_fract < div_fl->short_fract) {
wk = (t_int64) fl->short_fract << 24;
fl->expo = fl->expo - div_fl->expo + 64;
} else {
wk = (t_int64) fl->short_fract << 20;
fl->expo = fl->expo - div_fl->expo + 65;
}
/* divide fractions */
fl->short_fract = (int32)wk / div_fl->short_fract;
/* determine sign */
fl->sign = (fl->sign == div_fl->sign) ? 0 : 1;
/* handle overflow and underflow */
return( over_under_flow_sf(fl) );
} else {
/* fraction of dividend 0, set true 0 */
fl->short_fract = 0;
fl->expo = 0;
fl->sign = 0;
}
} else {
/* divisor 0 */
return(3);
}
return(0);
}
/*-------------------------------------------------------------------*/
/* Divide long float */
/* */
/* Input: */
/* fl Dividend long float */
/* div_fl Divisor long float */
/* Value: */
/* exeption */
/*-------------------------------------------------------------------*/
int div_lf(LONG_FLOAT *fl, LONG_FLOAT *div_fl)
{
t_int64 wk;
t_int64 wk2;
int i;
if (div_fl->long_fract) {
if (fl->long_fract) {
/* normalize operands */
normal_lf( fl );
normal_lf( div_fl );
/* position fracts and compute expo */
if (fl->long_fract < div_fl->long_fract) {
fl->expo = fl->expo - div_fl->expo + 64;
} else {
fl->expo = fl->expo - div_fl->expo + 65;
div_fl->long_fract <<= 4;
}
/* partial divide first hex digit */
wk2 = fl->long_fract / div_fl->long_fract;
wk = (fl->long_fract % div_fl->long_fract) << 4;
/* partial divide middle hex digits */
i = 13;
while (i--) {
wk2 = (wk2 << 4)
| (wk / div_fl->long_fract);
wk = (wk % div_fl->long_fract) << 4;
}
/* partial divide last hex digit */
fl->long_fract = (wk2 << 4)
| (wk / div_fl->long_fract);
/* determine sign */
fl->sign = (fl->sign == div_fl->sign) ? 0 : 1;
/* handle overflow and underflow */
return( over_under_flow_lf(fl) );
} else {
/* fraction of dividend 0, set true 0 */
fl->long_fract = 0;
fl->expo = 0;
fl->sign = 0;
}
} else {
/* divisor 0 */
return(3);
}
return(0);
}