1 /* eclipse_cpu.c: Eclipse CPU simulator
3 Modified from the original NOVA simulator by Robert Supnik.
5 Copyright (c) 1998-2006, Charles E Owen
6 Portions Copyright (c) 1993-2002, Robert M Supnik
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 and/or sell copies of the Software, and to permit persons to whom the
13 Software is furnished to do so, subject to the following conditions:
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 Except as contained in this notice, the name of Robert M Supnik shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings
27 in this Software without prior written authorization from Robert M Supnik.
29 cpu Eclipse central processor
31 07-Jun-06 RMS Fixed bug in DIVS (found by Mark Hittinger)
32 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
33 25-Aug-05 RMS Fixed DIVS overflow cases
34 29-Nov-03 CEO Corrected POPJ and Bit operations bugs
35 26-Nov-03 CEO Added FPU and PIT devices
36 20-Feb-03 CEO Corrected several MMPU and CIS bugs
37 28-Jan-02 RMS Cleaned up compiler warnings
38 30-Nov-01 RMS Added extended SET/SHOW support
39 01-Jun-01 RMS Added second terminal, plotter support
40 26-Apr-01 RMS Added device enable/disable support
42 The register state for the Eclipse CPU is basically the same as
45 AC[0:3]<0:15> general registers
47 PC<0:14> program counter
49 Eclipses with Folating Point Units added these registers:
51 FPAC[0:3]<0:63> Floating Point Accumulators
52 FPSR Floating Point Status Register
54 In addition, certain low-memory locations are reserved for special
57 0: I/O Return Address (from an interrupt)
58 1: I/O (Interrupt) handler address
59 2: System Call handler address (used by SYC instruction)
60 3: Protection Fault handler address
61 4: VECTOR stack pointer (VCT Instruction)
62 5: Current Interrupt Priority mask
63 6: VECTOR stack limit (VCT instruction)
64 7: VECTOR stack fault address (VCT again)
65 10: Block Pointer (later models only)
66 11: Emulation Trap Handler address (microeclipse only)
67 20-27: Auto-increment locations (not on microeclipse)
68 30-37: Auto-decrement locations (not on microeclipse)
72 43: Stack fault address
73 44: XOP Origin address
74 45: Floating point fault address
75 46: Commercial fault address (not on microeclipse)
76 47: Reserved, do not use.
78 Note: While all eclipses share most of the "standard" features,
79 some models added a few quirks and wrinkles, and other models
80 dropped some features or modified others. Most DG software
81 is written for a "standard" Eclipse, and avoids these problem
82 areas. A general overview:
84 [subject to major changes as info becomes available!]
86 Early (e.g. S/100, S/200, C/300) [Front Panel machines]
88 The first Eclipses had the basic MAP, but certain parts
89 were kluged, and these were fixed in later MAP designs.
90 The original mapping hardware was termed MAP for Memory
91 Allocate and Protection. The later design was termed
92 MMPU for Memory Mapping and Protection Unit. While
93 similar in design, the two units are not compatible.
94 Also, the C version (C for Commercial) of these early
95 CPUs had a feature called "Commercial Instruction Set"
96 which contained character manipulation, translation
97 between commercial-format numeric data and FPU formats,
98 and an elaborate EDIT instruction. Later models kept
99 only the character manipulation part of this and called
100 the feature the "Character Instruction Set", leading to
101 confusion because the initials of both are CIS. ARDOS
102 is the only DG operating system to support the older
103 MAP. ZRDOS uses the MMPU, and AOS supports only MMPU.
105 Middle (e.g. S/130, C/150, S/230, C/330) [Front Panel]
107 These are close to a "Standard". They have the newer,
108 fixed MMPU. Support for the PIT (Programmed Interval
109 Timer. The Commercial (not character) instruction set
110 and FPU are optional. (CIS standard on C models)
112 Late (C/350, M/600: [Panel]; S/140, S/280 [Virtual Console])
114 All features of the Middle period are included, plus:
115 These late Eclipses added a few MMPU wrinkles all their
116 own, included support for user maps C and D. Character
117 instruction set is standard, FPU optional. Also, support
120 MicroEclipse-based (S/20, S/120, Desktops) [Virtual cons.]
122 All features of the Late period, in general, plus:
123 Microeclipses dropped support for the auto increment
124 and decrement locations at 20-37. They also added
125 support for invalid instruction traps thru location 11.
126 The Desktops have an interface to the "Attached Processor",
127 an 8086, at device code 6. Also, some new CPU device
128 features to read states info. The Character Instruction
129 set and FPU are standard on all models.
131 The Eclipse instruction set is an elaboration of the NOVA's. The basic
132 NOVA set is implemented in it's entireity, plus many new Eclipse
133 instructions are added. Since in theory every possible 16-bit
134 combination is a NOVA instruction, the Eclipse commands are carved
135 out of the NOVA set by using the Operate format with the no-load bit
136 set to 1 and the skip bits set to 000. Since this combination is
137 in effect a no-op on the NOVA, it was rarely or never used. The
138 other bits are used to form Eclipse instructions, which have no
139 other common format. To see the instructions, refer to the Eclipse
140 section of the instruction decode logic in sim_instr() below. All
141 Eclipse instructions are checked first, so in case of conflict in
142 bit patterns, the Eclipse one is executed over the corresponding
143 NOVA pattern. A bizarre exception is LEF mode...which implements
144 an instruction called Load Effective Address by taking over the
145 Nova I/O format when the LEF mode bit is set and the processor is
146 executing in mapped mode.
148 The following discussion talks about NOVA instructions which are
149 Eclipse instructions also.
151 The NOVA has three instruction formats: memory reference, I/O transfer,
152 and operate. The memory reference format is:
154 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
155 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
156 | 0| op | AC |in| mode| displacement | memory reference
157 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
159 <0:4> mnemonic action
162 00001 JMS AC3 = PC, PC = MA
163 00010 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0
164 00011 DSZ M[MA] = M[MA] - 1, skip if M[MA] == 0
165 001'n LDA ACn = M[MA]
166 010'n STA M[MA] = ACn
170 000 page zero direct MA = zext (IR<8:15>)
171 001 PC relative direct MA = PC + sext (IR<8:15>)
172 010 AC2 relative direct MA = AC2 + sext (IR<8:15>)
173 011 AC3 relative direct MA = AC3 + sext (IR<8:15>)
174 100 page zero indirect MA = M[zext (IR<8:15>)]
175 101 PC relative dinirect MA = M[PC + sext (IR<8:15>)]
176 110 AC2 relative indirect MA = M[AC2 + sext (IR<8:15>)]
177 111 AC3 relative indirect MA = M[AC3 + sext (IR<8:15>)]
179 Memory reference instructions can access an address space of 32K words.
180 An instruction can directly reference the first 256 words of memory
181 (called page zero), as well as 256 words relative to the PC, AC2, or
182 AC3; it can indirectly access all 32K words. If an indirect address
183 is in locations 00020-00027, the indirect address is incremented and
184 rewritten to memory before use; if in 00030-00037, decremented and
187 The I/O transfer format is:
189 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
190 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
191 | 0 1 1| AC | opcode |pulse| device | I/O transfer
192 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
194 The IOT instruction sends the opcode, pulse, and specified AC to the
195 specified I/O device. The device may accept data, provide data,
196 initiate or cancel operations, or skip on status.
198 The operate format is:
200 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
201 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
202 | 1|srcAC|dstAC| opcode |shift|carry|nl| skip | operate
203 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
204 \______/ \___/ \___/ | | | |
205 | | | | | | +--- reverse skip sense
206 | | | | | +--- skip if C == 0
207 | | | | +--- skip if result == 0
208 | | | +--- don't load result
209 | | +--- carry in (load as is,
217 +--- operation (complement,
226 The operate instruction can be microprogrammed to perform operations
227 on the source and destination AC's and the Carry flag.
229 This routine is the instruction decode routine for the NOVA.
230 It is called from the simulator control program to execute
231 instructions in simulated memory, starting at the simulated PC.
232 It runs until 'reason' is set non-zero.
236 1. Reasons to stop. The simulator can be stopped by:
239 breakpoint encountered
240 infinite indirection loop
241 unknown I/O device and STOP_DEV flag set
242 I/O error in I/O simulator
244 2. Interrupts. Interrupts are maintained by four parallel variables:
246 dev_done device done flags
247 dev_disable device interrupt disable flags
248 dev_busy device busy flags
249 int_req interrupt requests
251 In addition, int_req contains the interrupt enable and ION pending
252 flags. If ION and ION pending are set, and at least one interrupt
253 request is pending, then an interrupt occurs. Note that the 16b PIO
254 mask must be mapped to the simulator's device bit mapping.
256 3. Non-existent memory. On the NOVA, reads to non-existent memory
257 return zero, and writes are ignored. In the simulator, the
258 largest possible memory is instantiated and initialized to zero.
259 Thus, only writes need be checked against actual memory size.
261 4. Adding I/O devices. These modules must be modified:
263 eclipse_defs.h add interrupt request definition
264 eclipse_cpu.c add IOT mask, PI mask, and routine to dev_table
265 eclipse_sys.c add pointer to data structures to sim_devices
268 /*---------------------------------------------------------------------------
269 ** ECLIPSE Debugging Facilities
271 ** These options are designed to find hard-to-locate flaky bugs by
272 ** providing special error checking and logging.
274 ** All are controlled by depositing a value into the DEBUG register.
275 ** A value of zero means no special debugging facilities are turned on.
276 ** This is the default. Debugging invokes a performance hit! Use only
279 ** Debugging means logging information to a file, or to a buffer in
280 ** memory from whence it can be dumped to a file.
282 ** 1XXXXX = Log all instructions executed to file "trace.log".
283 ** **CAUTION**: This means the CPU will run SLOWLY and
284 ** the resulting trace.log file will be HUGE. We're talking
285 ** about a megabyte for each 5 seconds or less of wall clock
286 ** time, depending on the speed of your CPU. Note: In this
287 ** mode, interrupts are logged when they are received also.
289 ** Note: when detailed logging is off, the last 4096 or so
290 ** instructions executed are saved in a memory buffer, and
291 ** when the sim stops, the "show" command can write this
292 ** history information to the file "history.log". This only
293 ** works if the DEBUG register is non-zero however, because
294 ** of the performance hit even this recording makes. To
295 ** dump history, enter the command "show cpu history", with
296 ** the file "history" spelled correctly and lower case.
298 ** XXXXDD = Log all I/O instructions to or from device number
299 ** DD. Log is written to "trace.log", regardless of the
300 ** setting of the instruction trace flag (1XXXXX). If both
301 ** are on, the device traces will be interpersed with the
302 ** instruction traces -- very useful sometimes.
304 ** XXX1DD = Device Break. Does a breakpoint in any I/O to
305 ** device DD. Useful, say when a diagnostic gives an
306 ** error message - a device break on 11 (TTO) will stop
307 ** as soon as the error message appears, making the
308 ** trace log much shorter to track back on.
310 ** X4XXXX = When this bit is on, the sim will stop if it sees
311 ** an invalid instruction. When DEBUG is zero, any such
312 ** instruction is no-oped with no warning. When DEBUG is
313 ** non-zero, but this bit is 0, a warning will be displayed
314 ** but execution will continue.
316 ** X2XXXX = LEF break. When A LEF instruction is executed in
317 ** mapped user space, the sim does a breakpoint right after
318 ** executing the instruction.
320 ** Whenever the DEBUG register is non-zero, special error checking
321 ** is enabled in the sim. This will stop the sim automatically
322 ** when a likely error occurs, such as:
324 ** 1. Any execution that reaches, or will reach, location 00000.
325 ** 2. Any I/O to device 00
326 ** 3. An interrupt from device 00.
327 ** 4. An invalid instruction (stop is optional)
329 ** DCHAR Register: Whenever this is non-zero, a test is made on every
330 ** character output to the TTO device (master console). If the character
331 ** output to that device matches this register, the CPU will break.
333 ** Of course, the standard BREAK register is available for breakpoints
334 ** as in all the sims based on this standard.
335 --------------------------------------------------------------------------*/
337 #include "nova_defs.h"
339 #define UNIT_V_MICRO (UNIT_V_UF) /* Microeclipse? */
340 #define UNIT_V_17B (UNIT_V_UF) /* 17 bit MAP */
341 #define UNIT_V_UP (UNIT_V_UF) /* FPU Enabled */
342 #define UNIT_V_MSIZE (UNIT_V_UF+1) /* dummy mask */
343 #define UNIT_MICRO (1 << UNIT_V_MICRO)
344 #define UNIT_17B (1 << UNIT_V_17B)
345 #define UNIT_UP (1 << UNIT_V_UP)
346 #define UNIT_MSIZE (1 << UNIT_V_MSIZE)
348 uint16 M
[MAXMEMSIZE
] = { 0 }; /* memory */
349 int32 AC
[4] = { 0 }; /* accumulators */
350 int32 C
= 0; /* carry flag */
351 int32 saved_PC
= 0; /* program counter */
352 int32 SR
= 0; /* switch register */
353 int32 dev_done
= 0; /* device done flags */
354 int32 dev_busy
= 0; /* device busy flags */
355 int32 dev_disable
= 0; /* int disable flags */
356 int32 iot_enb
= -1; /* IOT enables */
357 int32 int_req
= 0; /* interrupt requests */
358 int32 pimask
= 0; /* priority int mask */
359 int32 pwr_low
= 0; /* power fail flag */
360 int32 ind_max
= 15; /* iadr nest limit */
361 int32 stop_dev
= 0; /* stop on ill dev */
362 int32 old_PC
= 0; /* previous PC */
363 int32 model
= 140; /* Model of Eclipse */
364 int32 speed
= 0; /* Delay for each instruction */
366 int32 XCT_mode
= 0; /* 1 if XCT mode */
367 int32 XCT_inst
= 0; /* XCT instruction */
369 int32 AMASK
= 077777;
371 struct ndev dev_table
[64]; /* dispatch table */
373 /* Instruction history buffer */
377 int32 hnext
= 0; /* # of current entry */
378 int32 hwrap
= 0; /* 1 if wrapped */
379 int32 hmax
= HISTMAX
; /* Maximum entries b4 wrap */
381 uint16 hinst
[HISTMAX
];
382 uint16 hinst2
[HISTMAX
];
383 uint16 hac0
[HISTMAX
];
384 uint16 hac1
[HISTMAX
];
385 uint16 hac2
[HISTMAX
];
386 uint16 hac3
[HISTMAX
];
387 unsigned short hflags
[HISTMAX
];
389 /* Flags: 0x01 - carry bit
395 0x40 - LEF mode was on
396 0x80 - this is an int, not an inst.
405 /* the Eclipse MAP unit: This unit is standard in all Eclipse processors
406 except for the "original" Eclipses, the S/100, S/200, and C/300. These
407 use a different and more elaborate MMPU that is not compatible with
408 the one simulated here. All subsequent Eclipses, from the S/130 on up
409 to the last models S/280 and C/380 use the map simulated here, including
410 the MicroEclipses. There are model-dependent quirks. That's why we
411 have to MODEL register.
413 The programming of the MMPU can be found in the LMP instruction, below,
414 and in the instructions directed to DEV_MAP.
416 There are two user maps, called A and B, and four data channel maps,
417 A thru D. They can be enabled/disabled separately. Some models have
418 two extra user maps, C and D. These are supported where apporpriate.
422 #define PAGEMASK 01777 /* Largest physical page possible */
423 #define MAPMASK 0101777 /* Valid page bits in map */
424 #define INVALID 0101777 /* Mask indicating an invalid page */
425 int32 MapStat
= 0; /* Map status register */
426 int32 Inhibit
= 0; /* !0=inhibit interrupts : */
427 /* 1 = single cycle inhibit */
428 /* 2 = inhibit until indirection */
429 /* 3 = inhibit next instruction only */
430 int32 Enable
= 0; /* User map to activate 1=A 2=B */
431 int32 Usermap
= 0; /* Active Map? 0=supvr mode, 1=user A, 2 = user B */
432 int32 Map
[8][32]; /* The actual MAPs 0=dch A, 1=A, 2=B, 3-5=dchB-D 6-7 User C-D */
433 int32 Map31
= 037; /* Map for block 31 in supervisor mode */
434 int32 SingleCycle
= 0; /* Map one LDA/STA */
435 int32 Check
= 0; /* Page Check Register */
436 int32 Fault
= 0; /* Fault register */
437 int32 MapInit
= 0; /* 1 when map initialized */
438 int32 MapIntMode
= 0; /* Save of map user mode when int occurs */
440 /* The Eclipse Floating Point Unit: This unit is optional on all Eclipse
444 int32 FPSR
= 0; /* 32-bit FPU Status Register */
445 t_int64 FPAC
[4] = { 0,0,0,0 }; /* 4 64-bit Accumulators */
446 int32 FPFault
= 0; /* Save Fault State */
448 /* Definitions for internal floating point arithmetic */
450 typedef struct _SHORT_FLOAT
{
451 int32 short_fract
; /* Fraction */
452 short expo
; /* Exponent + 64 */
453 uint8 sign
; /* Sign */
456 typedef struct _LONG_FLOAT
{
457 t_int64 long_fract
; /* Fraction */
458 short expo
; /* Exponent + 64 */
459 uint8 sign
; /* Sign */
462 LONG_FLOAT dfl
,dfl2
; /* Double Precision Work Fields */
463 SHORT_FLOAT sfl
,sfl2
; /* Single Precision Work Fields */
464 t_int64 tempfp
, holdfp
; /* Working area for FPAC */
468 void get_sf(SHORT_FLOAT
*fl
, t_int64
*fpr
);
469 void store_sf(SHORT_FLOAT
*fl
, t_int64
*fpr
);
470 void get_lf(LONG_FLOAT
*fl
, t_int64
*fpr
);
471 void store_lf(LONG_FLOAT
*fl
, t_int64
*fpr
);
472 int normal_sf (SHORT_FLOAT
*fl
);
473 int normal_lf (LONG_FLOAT
*fl
);
474 int overflow_sf(SHORT_FLOAT
*fl
);
475 int overflow_lf(LONG_FLOAT
*fl
);
476 int underflow_sf(SHORT_FLOAT
*fl
);
477 int underflow_lf(LONG_FLOAT
*fl
);
478 int significance_sf(SHORT_FLOAT
*fl
);
479 int significance_lf(LONG_FLOAT
*fl
);
480 int add_sf(SHORT_FLOAT
*fl
, SHORT_FLOAT
*add_f1
, int normal
);
481 int add_lf(LONG_FLOAT
*fl
, LONG_FLOAT
*add_fl
, int normal
);
482 int mul_sf(SHORT_FLOAT
*fl
, SHORT_FLOAT
*mul_fl
);
483 int mul_lf(LONG_FLOAT
*fl
, LONG_FLOAT
*mul_fl
);
484 int div_sf(SHORT_FLOAT
*fl
, SHORT_FLOAT
*div_fl
);
485 int div_lf(LONG_FLOAT
*fl
, LONG_FLOAT
*div_fl
);
487 /* Special Debugging Info */
489 int32 Debug_Flags
= 0; /* Debug register - selects debug features */
490 int32 Debug_Char
= 0; /* Debug Character Register */
492 int32 Tron
= 0; /* For trace files */
497 extern int32 sim_int_char
;
498 extern uint32 sim_brk_types
, sim_brk_dflt
, sim_brk_summ
; /* breakpoint info */
499 extern DEVICE
*sim_devices
[];
501 t_stat
cpu_ex (t_value
*vptr
, t_addr addr
, UNIT
*uptr
, int32 sw
);
502 t_stat
cpu_dep (t_value val
, t_addr addr
, UNIT
*uptr
, int32 sw
);
503 t_stat
cpu_reset (DEVICE
*dptr
);
504 t_stat
cpu_boot (int32 unitno
, DEVICE
*dptr
);
505 t_stat
cpu_set_size (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
506 t_stat
Debug_Dump (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
507 t_stat
Dump_History (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
508 t_stat
map_ex (t_value
*vptr
, t_addr addr
, UNIT
*uptr
, int32 sw
);
509 t_stat
map_dep (t_value val
, t_addr addr
, UNIT
*uptr
, int32 sw
);
510 t_stat
map_reset (DEVICE
*dptr
);
511 t_stat
map_svc (UNIT
*uptr
);
512 t_stat
fpu_svc (UNIT
*uptr
);
513 int32
GetMap(int32 addr
);
514 int32
PutMap(int32 addr
, int32 data
);
515 int32
Debug_Entry(int32 PC
, int32 inst
, int32 inst2
, int32 AC0
, int32 AC1
, int32 AC2
, int32 AC3
, int32 flags
);
516 t_stat
build_devtab (void);
518 extern t_stat
fprint_sym (FILE *of
, t_addr addr
, t_value
*val
,
519 UNIT
*uptr
, int32 sw
);
521 /* CPU data structures
523 cpu_dev CPU device descriptor
524 cpu_unit CPU unit descriptor
525 cpu_reg CPU register list
526 cpu_mod CPU modifiers list
529 UNIT cpu_unit
= { UDATA (NULL
, UNIT_FIX
+ UNIT_BINK
, MAXMEMSIZE
) };
532 { ORDATA (PC
, saved_PC
, 15) },
533 { ORDATA (AC0
, AC
[0], 16) },
534 { ORDATA (AC1
, AC
[1], 16) },
535 { ORDATA (AC2
, AC
[2], 16) },
536 { ORDATA (AC3
, AC
[3], 16) },
537 { FLDATA (C
, C
, 16) },
538 { ORDATA (SR
, SR
, 16) },
539 { ORDATA (PI
, pimask
, 16) },
540 { FLDATA (ION
, int_req
, INT_V_ION
) },
541 { FLDATA (ION_DELAY
, int_req
, INT_V_NO_ION_PENDING
) },
542 { FLDATA (PWR
, pwr_low
, 0) },
543 { ORDATA (INT
, int_req
, INT_V_ION
+1), REG_RO
},
544 { ORDATA (BUSY
, dev_busy
, INT_V_ION
+1), REG_RO
},
545 { ORDATA (DONE
, dev_done
, INT_V_ION
+1), REG_RO
},
546 { ORDATA (DISABLE
, dev_disable
, INT_V_ION
+1), REG_RO
},
547 { FLDATA (STOP_DEV
, stop_dev
, 0) },
548 { DRDATA (INDMAX
, ind_max
, 16), REG_NZ
+ PV_LEFT
},
549 { ORDATA (DEBUG
, Debug_Flags
, 16) },
550 { ORDATA (DCHAR
, Debug_Char
, 16) },
551 { DRDATA (MODEL
, model
, 16) },
552 { DRDATA (SPEED
, speed
, 16) },
553 { ORDATA (WRU
, sim_int_char
, 8) },
558 { UNIT_MICRO
, UNIT_MICRO
, "MICRO", "MICRO", NULL
},
559 { UNIT_MICRO
, 0, "STD", "STD", NULL
},
560 { UNIT_MSIZE
, 4096, NULL
, "4K", &cpu_set_size
},
561 { UNIT_MSIZE
, 8192, NULL
, "8K", &cpu_set_size
},
562 { UNIT_MSIZE
, 12288, NULL
, "12K", &cpu_set_size
},
563 { UNIT_MSIZE
, 16384, NULL
, "16K", &cpu_set_size
},
564 { UNIT_MSIZE
, 20480, NULL
, "20K", &cpu_set_size
},
565 { UNIT_MSIZE
, 24576, NULL
, "24K", &cpu_set_size
},
566 { UNIT_MSIZE
, 28672, NULL
, "28K", &cpu_set_size
},
567 { UNIT_MSIZE
, 32768, NULL
, "32K", &cpu_set_size
},
568 { UNIT_MSIZE
, 65536, NULL
, "64K", &cpu_set_size
},
569 { UNIT_MSIZE
, 131072, NULL
, "128K", &cpu_set_size
},
570 { UNIT_MSIZE
, 262144, NULL
, "256K", &cpu_set_size
},
571 { UNIT_MSIZE
, 524288, NULL
, "512K", &cpu_set_size
},
572 { UNIT_MSIZE
, 1048576, NULL
, "1024K", &cpu_set_size
},
573 { UNIT_MSIZE
, 0, NULL
, "DUMP", &Debug_Dump
},
574 { MTAB_XTD
|MTAB_VDV
|MTAB_NMO
, 0, "HISTORY", NULL
,
575 NULL
, &Dump_History
},
580 "CPU", &cpu_unit
, cpu_reg
, cpu_mod
,
582 &cpu_ex
, &cpu_dep
, &cpu_reset
,
583 &cpu_boot
, NULL
, NULL
586 /* MAP data structures
588 map_dev MAP device descriptor
589 map_unit MAP unit descriptor
590 map_reg MAP register list
591 map_mod MAP modifiers list
594 UNIT map_unit
= { UDATA (&map_svc
, UNIT_17B
, MAXMEMSIZE
) };
597 { ORDATA (STATUS
, MapStat
, 16) },
598 { ORDATA (ENABLE
, Enable
, 16) },
599 { ORDATA (IINHIB
, Inhibit
, 16) },
600 { ORDATA (ACTIVE
, Usermap
, 16) },
601 { ORDATA (MAP31
, Map31
, 16) },
602 { ORDATA (CYCLE
, SingleCycle
, 16) },
603 { ORDATA (CHECK
, Check
, 16) },
604 { ORDATA (FAULT
, Fault
, 16) },
609 { UNIT_17B
, UNIT_17B
, "17bit", "17B", NULL
},
610 { UNIT_17B
, 0, "19bit", "19B", NULL
},
615 "MAP", &map_unit
, map_reg
, map_mod
,
617 &map_ex
, &map_dep
, NULL
,
621 /* FPU data structures
623 fpu_dev MAP device descriptor
624 fpu_unit MAP unit descriptor
625 fpu_reg MAP register list
626 fpu_mod MAP modifiers list
629 UNIT fpu_unit
= { UDATA (&fpu_svc
, UNIT_UP
, MAXMEMSIZE
) };
632 { ORDATA (STATUS
, FPSR
, 32) },
633 { ORDATA (FPAC0
, FPAC
[0], 64) },
634 { ORDATA (FPAC1
, FPAC
[1], 64) },
635 { ORDATA (FPAC2
, FPAC
[2], 64) },
636 { ORDATA (FPAC3
, FPAC
[3], 64) },
637 { ORDATA (FAULT
, FPFault
, 32) },
642 { UNIT_UP
, UNIT_UP
, "Enabled (UP)", "UP", NULL
},
643 { UNIT_UP
, 0, "Disabled (DOWN)", "DOWN", NULL
},
648 "FPU", &fpu_unit
, fpu_reg
, fpu_mod
,
649 1, 16, 17, 1, 16, 16,
655 /* ---- Programmable Interval Timer Device ----------- */
657 int32 pit_time
= 100;
658 int32 pit_tps
= 10000; /* ticks per sec */
659 int32 pit_adj
= 20; /* tmxr adjust */
660 int32 pit_poll
= 16000; /* tmxr poll */
661 int32 pit_initial
= 0; /* initial counter reg */
662 int32 pit_counter
= 0; /* Counter */
663 int32 pit_flag
= 0; /* Initial setting flag */
665 int32
pit (int32 pulse
, int32 code
, int32 AC
);
666 t_stat
pit_svc (UNIT
*uptr
);
667 t_stat
pit_reset (DEVICE
*dptr
);
669 /* PIT data structures
671 pit_dev device descriptor
672 pit_unit unit descriptor
673 pit_reg register list
676 DIB pit_dib
= { DEV_PIT
, INT_PIT
, PI_PIT
, &pit
};
678 UNIT pit_unit
= { UDATA (&pit_svc
, 0, 0) };
681 { ORDATA (INIT
, pit_initial
, 16) },
682 { ORDATA (COUNT
, pit_counter
, 16) },
683 { FLDATA (BUSY
, dev_busy
, INT_V_PIT
) },
684 { FLDATA (DONE
, dev_done
, INT_V_PIT
) },
685 { FLDATA (DISABLE
, dev_disable
, INT_V_PIT
) },
686 { FLDATA (INT
, int_req
, INT_V_PIT
) },
687 { DRDATA (TIME0
, pit_time
, 24), REG_NZ
+ PV_LEFT
},
692 "PIT", &pit_unit
, pit_reg
, NULL
,
694 NULL
, NULL
, &pit_reset
,
699 t_stat
sim_instr (void)
701 extern int32 sim_interval
;
702 register int32 PC
, IR
, i
, t
, MA
, j
, k
, tac
;
703 register uint32 mddata
, uAC0
, uAC1
, uAC2
, uAC3
;
704 int16 sAC0
, sAC1
, sAC2
;
705 int32 sddata
, mi1
, mi2
, fpnum32
;
706 t_int64 fpnum
, expon
;
708 void mask_out (int32 mask
);
709 /* char debstr[128]; */
710 /* char debadd[64]; */
711 char debmap
[4], debion
[4];
712 int debcar
, iodev
, iodata
, debflags
;
715 int cmdptr
, cmsptr
, cmopt
, cmptr
;
716 int16 cmslen
, cmdlen
;
718 int32
effective(int32 PC
, int32 index
, int32 disp
);
719 int32
indirect(int32 d
);
720 int32
LEFmode(int32 PC
, int32 index
, int32 disp
, int32 indirect
);
721 int32
LoadMap(int32 w
);
722 int32
Bytepointer(int32 PC
, int32 index
);
723 int32
unimp(int32 PC
);
724 int32
pushrtn(int32 pc
);
726 /* Restore register state */
728 if (build_devtab () != SCPE_OK
) return SCPE_IERR
; /* build dispatch */
729 PC
= saved_PC
& AMASK
; /* load local PC */
731 mask_out (pimask
); /* reset int system */
735 for (mi1
= 0; mi1
< 6; mi1
++) { /* Initialize MAPs */
736 for (mi2
= 0; mi2
< 32; mi2
++) {
742 /* Main instruction fetch/decode loop */
744 while (reason
== 0) { /* loop until halted */
745 if (sim_interval
<= 0) { /* check clock queue */
746 if (reason
= sim_process_event ())
750 //if (speed > 0) for (i = 0; i < speed; i++) { j = 0; }
752 if (Fault
) { /* Check MAP fault */
753 Usermap
= 0; /* YES: shutdown map */
754 MapStat
&= ~01; /* Disable MMPU */
755 if (Fault
& 0100000/*!!!*/) /* If it was validity, or WP */
756 MapStat
&= ~0170; /* Reset other checkbits */
757 MapStat
|= Fault
& 077777; /* Put in fault code */
758 Fault
= 0; /* Reset fault code */
759 t
= (GetMap(040) + 1) & AMASK
; /* Push rtn block */
768 PutMap(t
, (PC
& AMASK
));
769 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
771 int_req
= int_req
& ~INT_ION
; /* Disable interrupts */
772 PC
= indirect(M
[003]); /* JMP to loc 3 */
776 if (FPSR
& 0xF8000000) { /* FPU Fault? */
777 if (!(FPSR
& 0x78000000)) { /* If error bit on ... */
778 FPSR
&= 0x00FFFFFF; /* ...but no error, clear it */
779 } else { /* ELSE a real error: */
780 FPSR
|= 0x80000000; /* Turn error bit on */
781 if (FPSR
& 0x04000000) { /* Trap enabled ? */
782 FPFault
= FPSR
; /* Save fault */
783 FPSR
&= 0xFBFFFFFF; /* Clear Trap Enable */
788 if (int_req
> INT_PENDING
&& !Inhibit
) { /* interrupt? */
789 int_req
= int_req
& ~INT_ION
;
790 MapIntMode
= MapStat
; /* Save Status as it was */
791 Usermap
= 0; /* Inhibit MAP */
792 MapStat
&= ~1; /* Disable user map */
794 M
[0] = PC
- 1; /* If XCT mode rtn to XCT */
795 XCT_mode
= 0; /* turn off mode */
797 M
[0] = PC
; /* Save Return Address */
801 for (i
= 0; i
< ind_max
* 2; i
++) { /* count indirects */
802 if ((MA
& 0100000) == 0) break;
803 if ((MA
& 077770) == 020)
804 MA
= (M
[MA
& AMASK
] = (M
[MA
& AMASK
] + 1) & 0177777);
805 else if ((MA
& 077770) == 030)
806 MA
= (M
[MA
& AMASK
] = (M
[MA
& AMASK
] - 1) & 0177777);
807 else MA
= M
[MA
& AMASK
];
809 if (i
>= (ind_max
-1)) {
810 if ((MapStat
& 010) && Usermap
) {
811 Fault
= 04000; /* Map fault if IND prot */
814 reason
= STOP_IND_INT
;
820 iodata
= int_req
& (-int_req
);
821 for (i
= DEV_LOW
; i
<= DEV_HIGH
; i
++) {
822 if (iodata
& dev_table
[i
].mask
) {
828 printf("\n<<Interrupt to device 0!>>\n");
831 if (Debug_Flags
& 0100000) {
832 fprintf(Trace
, "--------- Interrupt %o (%o) to %6o ---------\n", int_req
, iodev
, MA
);
834 Debug_Entry(PC
, int_req
, 0, iodev
, MA
, 0, 0, 0x80);
838 } /* end interrupt */
840 if (Inhibit
!= 0) { /* Handle 1-instruction inhibit sequence */
841 if (Inhibit
== 3) /* Used by SYC instruction */
847 if (sim_brk_summ
&& sim_brk_test (PC
, SWMASK ('E'))) { /* breakpoint? */
848 reason
= STOP_IBKPT
; /* stop simulation */
852 if ((PC
< 1 || PC
> 077777) && Debug_Flags
) {
853 if (PPC
!= -1) { /* Don't break on 1st instruction */
854 printf("\n<<Invalid PC=%o from %o>>\n\r", PC
, PPC
);
865 Trace
= fopen("trace.log", "w");
871 if (Usermap
== 1) strcpy(debmap
, "A");
872 if (Usermap
== 2) strcpy(debmap
, "B");
873 if (Usermap
== 5) strcpy(debmap
, "C");
874 if (Usermap
== 6) strcpy(debmap
, "D");
875 if (int_req
& INT_ION
) strcpy(debion
, "I");
878 simeval
[0] = GetMap(PC
);
879 simeval
[1] = GetMap(PC
+1);
882 simeval
[0] = XCT_inst
;
885 if (Debug_Flags
& 0100000) {
886 fprintf(Trace
, "%s%s%06o acs: %06o %06o %06o %06o %01o ",
887 debion
, debmap
, debpc
, AC
[0], AC
[1], AC
[2], AC
[3], debcar
);
888 fprint_sym (Trace
, debpc
, simeval
, NULL
, SWMASK('M'));
889 fprintf(Trace
, "\n");
892 if (C
) debflags
|= 0x01;
893 if (int_req
& INT_ION
) debflags
|= 0x02;
894 if (Usermap
== 1) debflags
|= 0x04;
895 if (Usermap
== 2) debflags
|= 0x08;
896 if (Usermap
== 3) debflags
|= 0x10;
897 if (Usermap
== 4) debflags
|= 0x20;
898 Debug_Entry(debpc
, (int32
)simeval
[0], (int32
)simeval
[1], AC
[0], AC
[1], AC
[2], AC
[3], debflags
);
902 if (XCT_mode
== 0) { /* XCT mode? */
903 IR
= GetMap(PC
); /* No: fetch instr */
904 if (Fault
) continue; /* Give up if fault */
905 PC
= (PC
+ 1) & AMASK
; /* bump PC */
907 IR
= XCT_inst
; /* Yes: Get inst to XCT */
908 XCT_mode
= 0; /* Go back to normal mode */
910 int_req
= int_req
| INT_NO_ION_PENDING
; /* clear ION delay */
911 sim_interval
= sim_interval
- 1;
912 t
= IR
>> 11; /* prepare to decode */
914 /* ---------------- BEGIN Eclipse modification --------------------- */
916 /* Eclipse instruction set. These instructions are checked for
917 before any of the NOVA ones. Eclipse instructions do not
918 correspond to any patterns, other than bit 0 being 1 and
919 the last 4 bits are 1000. Words which are not Eclipse
920 instructions will be interpreted as Nova instructions. */
922 /* Important Note: The order of the if statements is important.
923 Frequently executed instructions should come first, to enhance
924 the speed of the simulation.
927 if ((IR
& 0100017) == 0100010) { /* This pattern for all */
928 /* Eclipse instructions */
930 /****************************************************************/
931 /* This is the standard Eclipse instruction set */
932 /****************************************************************/
934 /* Byte operations */
936 if ((IR
& 0103777) == 0102710) { /* LDB: Load Byte */
938 MA
= (AC
[i
] >> 1) & AMASK
;
941 AC
[j
] = GetMap(MA
) & 0377;
943 AC
[j
] = (GetMap(MA
) >> 8) & 0377;
947 if ((IR
& 0103777) == 0103010) { /* STB: Store Byte */
958 t
|= (AC
[j
] & 0377) << 8;
964 /* Fixed-point arithmetic - loads & saves */
966 if ((IR
& 0162377) == 0122070) { /* ELDA: Extended LDA */
969 if (SingleCycle
) Usermap
= SingleCycle
;
970 AC
[i
] = GetMap(effective(PC
, (IR
>> 8) & 3, t
));
972 Usermap
= SingleCycle
= 0;
973 if (Inhibit
== 1) Inhibit
= 3;
977 PC
= (PC
+ 1) & AMASK
;
980 if ((IR
& 0162377) == 0142070) { /* ESTA: Extended STA */
983 if (SingleCycle
) Usermap
= SingleCycle
;
984 PutMap((effective(PC
, (IR
>> 8) & 3, t
)), AC
[i
]);
986 Usermap
= SingleCycle
= 0;
987 if (Inhibit
== 1) Inhibit
= 3;
991 PC
= (PC
+ 1) & AMASK
;
994 if ((IR
& 0103777) == 0100010) { /* ADI: Add Immediate */
996 AC
[t
] = (AC
[t
] + ((IR
>> 13) & 3) + 1) & 0xffff;
999 if ((IR
& 0103777) == 0100110) { /* SBI: Subtract Immediate */
1001 AC
[t
] = (AC
[t
] - (((IR
>> 13) & 3) + 1)) & 0xffff;
1004 if ((IR
& 0163777) == 0163770) { /* ADDI: Extended Add Immed. */
1007 PC
= (PC
+ 1) & AMASK
;
1008 AC
[t
] = (AC
[t
] + i
) & 0xffff;
1011 if ((IR
& 0103777) == 0100710) { /* XCH: Exchange Accumulators */
1012 t
= AC
[(IR
>> 11) & 3];
1013 AC
[(IR
>> 11) & 3] = AC
[(IR
>> 13) & 3];
1014 AC
[(IR
>> 13) & 3] = t
;
1017 if ((IR
& 0162377) == 0162070) { /* ELEF: Load Effective Addr */
1019 AC
[(IR
>> 11) & 3] = effective(PC
, (IR
>> 8) & 3, t
);
1020 PC
= (PC
+ 1) & AMASK
;
1024 /* Logical operations */
1026 if ((IR
& 0163777) == 0143770) { /* ANDI: And Immediate */
1027 AC
[(IR
>> 11) & 3] &= GetMap(PC
);
1028 PC
= (PC
+ 1) & AMASK
;
1031 if ((IR
& 0163777) == 0103770) { /* IORI: Inclusive Or Immed */
1032 AC
[(IR
>> 11) & 3] |= GetMap(PC
);
1033 PC
= (PC
+ 1) & AMASK
;
1036 if ((IR
& 0163777) == 0123770) { /* XORI: Exclusive Or Immed */
1037 AC
[(IR
>> 11) & 3] ^= GetMap(PC
);
1038 PC
= (PC
+ 1) & AMASK
;
1041 if ((IR
& 0103777) == 0100410) { /* IOR: Inclusive Or */
1042 AC
[(IR
>> 11) & 3] |= AC
[(IR
>> 13) & 3];
1045 if ((IR
& 0103777) == 0100510) { /* XOR: Exclusive Or */
1046 AC
[(IR
>> 11) & 3] ^= AC
[(IR
>> 13) & 3];
1049 if ((IR
& 0103777) == 0100610) { /* ANC: And with complemented src */
1050 AC
[(IR
>> 11) & 3] &= ~(AC
[(IR
>> 13) & 3]);
1054 /* Shift operations */
1056 if ((IR
& 0103777) == 0101210) { /* LSH: Logical Shift */
1058 sh
= AC
[(IR
>> 13) & 3] & 0377;
1062 AC
[i
] = AC
[i
] >> sh
;
1064 AC
[i
] = AC
[i
] << sh
;
1066 if (sh
> 15) AC
[i
] = 0;
1070 if ((IR
& 0103777) == 0101310) { /* DLSH: Double logical shift */
1072 sh
= AC
[(IR
>> 13) & 3] & 0377;
1079 sh
= (~sh
+ 1) & 0377;
1086 if (sh
> 31) uAC0
= 0;
1087 AC
[i
] = (uAC0
>> 16) & 0xffff;
1088 AC
[j
] = uAC0
& 0xffff;
1091 if ((IR
& 0103777) == 0101410) { /* HXL: Hex shift left */
1092 t
= ((IR
>> 13) & 3) + 1;
1094 AC
[i
] = AC
[i
] << (t
* 4);
1098 if ((IR
& 0103777) == 0101510) { /* HXR: Hex shift right */
1099 t
= ((IR
>> 13) & 3) + 1;
1101 AC
[i
] = AC
[i
] >> (t
* 4);
1105 if ((IR
& 0103777) == 0101610) { /* DHXL: Double Hex shift left */
1106 t
= ((IR
>> 13) & 3) + 1;
1112 uAC0
= uAC0
<< ((t
* 4) & 0177);
1113 AC
[i
] = (uAC0
>> 16) & 0xffff;
1114 AC
[j
] = uAC0
& 0xffff;
1117 if ((IR
& 0103777) == 0101710) { /* DHXR: Double Hex shift right */
1118 t
= ((IR
>> 13) & 3) + 1;
1124 uAC0
= uAC0
>> ((t
* 4) & 0177);
1125 AC
[i
] = (uAC0
>> 16) & 0xffff;
1126 AC
[j
] = uAC0
& 0xffff;
1130 /* Bit operations */
1132 if ((IR
& 0103777) == 0102010) { /* BTO: Set bit to one */
1136 k
= (AC
[i
] >> 4) & AMASK
;
1137 if ((AC
[j
] + k
) & 0100000)
1139 //AOS MA = indirect(AC[j] + k);
1140 MA
= (AC
[j
] + k
) & AMASK
;
1142 MA
= (AC
[i
] >> 4) & AMASK
;
1145 t
= GetMap(MA
) | (0100000 >> t
);
1149 if ((IR
& 0103777) == 0102110) { /* BTZ: Set bit to zero */
1153 k
= (AC
[i
] >> 4) & AMASK
;
1154 if ((AC
[j
] + k
) & 0100000)
1156 //AOS MA = indirect(AC[j] + k);
1157 MA
= (AC
[j
] + k
) & AMASK
;
1159 MA
= (AC
[j
] >> 4) & AMASK
;
1162 t
= GetMap(MA
) & ~(0100000 >> t
);
1166 if ((IR
& 0103777) == 0102210) { /* SZB: Skip on zero bit */
1170 k
= (AC
[i
] >> 4) & AMASK
;
1171 if ((AC
[j
] + k
) & 0100000)
1173 MA
= indirect(AC
[j
] + k
);
1174 // MA = (AC[j] + k) & AMASK;
1176 MA
= (AC
[i
] >> 4) & AMASK
;
1178 t
= GetMap(MA
) << (AC
[i
] & 017);
1179 if (!(t
& 0100000)) PC
= (PC
+ 1) & AMASK
;
1182 if ((IR
& 0103777) == 0102770) { /* SNB: Skip on non-zero bit */
1186 k
= (AC
[i
] >> 4) & AMASK
;
1187 if ((AC
[j
] + k
) & 0100000)
1189 MA
= indirect(AC
[j
] + k
);
1190 // MA = (AC[j] + k) & AMASK;
1192 MA
= (AC
[j
] >> 4) & AMASK
;
1194 t
= GetMap(MA
) << (AC
[i
] & 017);
1195 if (t
& 0100000) PC
= (PC
+ 1) & AMASK
;
1198 if ((IR
& 0103777) == 0102310) { /* SZBO: skip on zero bit & set to 1 */
1199 register int32 save
;
1203 k
= (AC
[i
] >> 4) & AMASK
;
1204 MA
= indirect(AC
[j
] + k
);
1205 // MA = (AC[j] + k) & AMASK;
1207 MA
= (AC
[j
] >> 4) & AMASK
;
1211 t
= save
| (0100000 >> t
);
1213 t
= save
<< (AC
[i
] & 017);
1214 if ((t
& 0100000) == 0)
1215 PC
= (PC
+ 1) & AMASK
;
1218 if ((IR
& 0103777) == 0102410) { /* LOB: Locate lead bit */
1219 register int32 a
, r
;
1221 a
= AC
[(IR
>> 13) & 3] & 0xffff;
1222 for (i
= 0; i
< 16; i
++) {
1223 if ((a
<< i
) & 0100000) break;
1228 AC
[r
] = b
& 0177777;
1231 if ((IR
& 0103777) == 0102510) { /* LRB: Locate & reset lead bit */
1232 register int32 a
, r
;
1236 for (i
= 0; i
< 16; i
++) {
1237 if ((a
<< i
) & 0100000) break;
1242 if (j
!= r
) AC
[r
] = b
& 0177777;
1243 AC
[j
] &= ~(0100000 >> i
);
1247 if ((IR
& 0103777) == 0102610) { /* COB: Count bits */
1249 register int16 b
, c
= 0;
1250 a
= AC
[(IR
>> 13) & 3];
1251 for (i
= 0; i
< 16; i
++) {
1252 if ((a
>> i
) & 1) c
++;
1257 AC
[i
] = b
& 0177777;
1261 /* Jump & similar operations */
1263 if ((IR
& 0176377) == 0102070) { /* EJMP: Extended JMP */
1264 PC
= effective(PC
, (IR
>> 8) & 3, GetMap(PC
));
1267 if ((IR
& 0176377) == 0106070) { /* EJSR: Extended JMP to subr */
1268 t
= effective(PC
, (IR
>> 8) & 3, GetMap(PC
));
1269 AC
[3] = (PC
+ 1) & AMASK
;
1273 if ((IR
& 0176377) == 0112070) { /* EISZ: Ext Inc & skip if 0 */
1274 MA
= effective(PC
, (IR
>> 8) & 3, GetMap(PC
));
1275 PutMap(MA
, ((GetMap(MA
) + 1) & 0xffff));
1276 if (GetMap(MA
) == 0) PC
= (PC
+ 1) & AMASK
;
1277 PC
= (PC
+ 1) & AMASK
;
1280 if ((IR
& 0176377) == 0116070) { /* EDSZ: Ext Dec & skip if 0 */
1281 MA
= effective(PC
, (IR
>> 8) & 3, GetMap(PC
));
1282 PutMap(MA
, ((GetMap(MA
) - 1) & 0xffff));
1283 if (GetMap(MA
) == 0) PC
= (PC
+ 1) & AMASK
;
1284 PC
= (PC
+ 1) & AMASK
;
1287 if ((IR
& 0103777) == 0101010) { /* SGT: Skip if ACS > ACD */
1288 register int16 a1
, d1
;
1289 a1
= AC
[(IR
>> 13) & 3] & 0xffff;
1290 d1
= AC
[(IR
>> 11) & 3] & 0xffff;
1292 PC
= (PC
+ 1) & AMASK
;
1295 if ((IR
& 0103777) == 0101110) { /* SGE: Skip if ACS >= ACD */
1296 register int16 a1
, d1
;
1297 a1
= AC
[(IR
>> 13) & 3] & 0xffff;
1298 d1
= AC
[(IR
>> 11) & 3] & 0xffff;
1300 PC
= (PC
+ 1) & AMASK
;
1303 if ((IR
& 0103777) == 0102370) { /* CLM: Compare to limits */
1304 register int32 s
, d
, MA
;
1319 if (ca
>= L
&& ca
<= H
) PC
= (PC
+ 1) & AMASK
;
1322 if ((IR
& 0163777) == 0123370) { /* XCT: Execute */
1323 XCT_mode
= 1; /* Set up to execute on next loop */
1324 XCT_inst
= AC
[(IR
>> 11) & 3];
1328 /* Memory block operations */
1330 if (IR
== 0113710) { /* BAM: Block add & move */
1333 if (t
< 1 || t
> 0100000)
1335 i
= indirect(AC
[2]);
1336 j
= indirect(AC
[3]);
1339 PutMap(j
, ((w
+ AC
[0]) & 0xffff));
1352 if (IR
== 0133710) { /* BLM: Block move */
1354 if (t
< 1 || t
> 0100000)
1356 i
= indirect(AC
[2]);
1357 j
= indirect(AC
[3]);
1358 if (Fault
) continue;
1360 PutMap(j
, GetMap(i
));
1374 /* Stack operations */
1376 if ((IR
& 0103777) == 0103110) { /* PSH: Push multiple accums */
1379 t
= GetMap(040) & AMASK
;
1384 PutMap(040, (t
& AMASK
));
1385 if (t
> GetMap(042)) {
1387 PC
= indirect(GetMap(043));
1388 PutMap(040, (GetMap(040) & 077777));
1389 PutMap(042, (GetMap(042) | 0100000));
1401 PutMap(040, (t
& AMASK
));
1402 if ((GetMap(040) & AMASK
) > GetMap(042)) {
1404 PC
= indirect(GetMap(043));
1405 PutMap(040, (GetMap(040) & 077777));
1406 PutMap(042, (GetMap(042) | 0100000));
1410 if ((IR
& 0103777) == 0103210) { /* POP: Pop mult accums */
1412 t
= GetMap(040) & AMASK
;
1417 PutMap(040, (t
& AMASK
));
1419 if (t
< 0100000 && t
< 0400) {
1420 PutMap(040, GetMap(042));
1422 PC
= indirect(GetMap(043));
1423 PutMap(040, (GetMap(040) & 077777));
1424 PutMap(042, (GetMap(042) | 0100000));
1436 PutMap(040, (t
& AMASK
));
1438 if (t
< 0100000 && t
< 0400) {
1439 PutMap(040, GetMap(042));
1441 PC
= indirect(GetMap(043));
1442 PutMap(040, (GetMap(040) & 077777));
1443 PutMap(042, (GetMap(042) | 0100000));
1447 if (IR
== 0103710) { /* PSHR: Push return addr */
1448 t
= (GetMap(040) + 1) & AMASK
;
1449 PutMap(t
, (PC
+ 1));
1451 if ((GetMap(040) & AMASK
) > GetMap(042)) {
1453 PC
= indirect(GetMap(043));
1454 PutMap(040, (GetMap(040) & 077777));
1455 PutMap(042, (GetMap(042) | 0100000));
1459 if (IR
== 0163710) { /* SAVE */
1460 register int32 savep
;
1461 savep
= ((GetMap(PC
) + GetMap(040)) + 5) & AMASK
;
1462 if (savep
> GetMap(042)) {
1464 PC
= indirect(GetMap(043));
1465 PutMap(040, (GetMap(040) & 077777));
1466 PutMap(042, (GetMap(042) | 0100000));
1469 t
= GetMap(040) + 1;
1476 PutMap(t
, GetMap(041));
1479 PC
= (PC
+ 1) & AMASK
;
1480 PutMap(t
, (AC
[3] & AMASK
));
1481 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
1483 AC
[3] = GetMap(040) & AMASK
;
1485 PutMap(040, ((GetMap(040) + GetMap(savep
)) & AMASK
));
1488 if ((IR
& 0163777) == 0103370) { /* MSP: Modify stack pointer */
1489 t
= (GetMap(040) + AC
[(IR
>> 11) & 3]) & 0177777;
1490 if (t
> GetMap(042)) {
1492 PC
= indirect(GetMap(043));
1493 PutMap(040, (GetMap(040) & AMASK
));
1494 PutMap(042, (GetMap(042) | 0100000));
1500 if ((IR
& 0176377) == 0102270) { /* PSHJ: Push JMP */
1501 PutMap(040, (GetMap(040) + 1));
1502 PutMap((GetMap(040) & AMASK
), ((PC
+ 1) & AMASK
));
1503 if ((GetMap(040) & AMASK
) > (GetMap(042) & AMASK
)) {
1505 PC
= indirect(GetMap(043));
1506 PutMap(040, (GetMap(040) & 077777));
1507 PutMap(042, (GetMap(042) | 0100000));
1510 PC
= effective(PC
, (IR
>> 8) & 3, GetMap(PC
));
1513 if (IR
== 0117710) { /* POPJ: Pop PC and Jump */
1514 PC
= GetMap(GetMap(040)) & AMASK
;
1515 PutMap(040, (GetMap(040) - 1));
1522 if ((j
< 0100000 && t
< 0100000) && (t
< 0400) && (t
> 0)) {
1524 PC
= indirect(GetMap(043));
1525 PutMap(040, (GetMap(040) & 077777));
1526 PutMap(042, (GetMap(042) | 0100000));
1530 if (IR
== 0107710) { /* POPB: Pop block */
1531 PC
= GetMap(GetMap(040)) & AMASK
;
1532 if (GetMap(GetMap(040)) & 0100000)
1536 PutMap(040, (GetMap(040) - 1));
1537 AC
[3] = GetMap(GetMap(040));
1538 PutMap(040, (GetMap(040) - 1));
1539 AC
[2] = GetMap(GetMap(040));
1540 PutMap(040, (GetMap(040) - 1));
1541 AC
[1] = GetMap(GetMap(040));
1542 PutMap(040, (GetMap(040) - 1));
1543 AC
[0] = GetMap(GetMap(040));
1544 PutMap(040, (GetMap(040) - 1));
1546 if (t
< 0100000 && t
< 0400) {
1548 PC
= indirect(GetMap(043));
1549 PutMap(040, (GetMap(040) & 077777));
1550 PutMap(042, (GetMap(042) | 0100000));
1558 if (IR
== 0127710) { /* RTN: Return */
1559 PutMap(040, GetMap(041));
1560 PC
= GetMap(GetMap(040)) & AMASK
;
1567 PutMap(040, (GetMap(040) - 1));
1568 AC
[3] = GetMap(GetMap(040));
1569 PutMap(040, (GetMap(040) - 1));
1570 AC
[2] = GetMap(GetMap(040));
1571 PutMap(040, (GetMap(040) - 1));
1572 AC
[1] = GetMap(GetMap(040));
1573 PutMap(040, (GetMap(040) - 1));
1574 AC
[0] = GetMap(GetMap(040));
1575 PutMap(040, (GetMap(040) - 1));
1578 if (t
< 0100000 && t
< 0400) {
1580 PutMap(040, (GetMap(040) & 077777));
1581 PutMap(042, (GetMap(042) | 0100000));
1582 PC
= indirect(GetMap(043));
1590 if (IR
== 0167710) { /* RSTR: Restore */
1594 PC
= GetMap(GetMap(040)) & AMASK
;
1595 if (PC
== 0 && Debug_Flags
) {
1596 printf("\n<<RSTR to 0 @ %o>>\n\r", SVPC
);
1597 reason
= STOP_IBKPT
;
1599 if (GetMap(GetMap(040)) & 0100000)
1603 PutMap(040, (GetMap(040) - 1));
1604 AC
[3] = GetMap(GetMap(040));
1605 PutMap(040, (GetMap(040) - 1));
1606 AC
[2] = GetMap(GetMap(040));
1607 PutMap(040, (GetMap(040) - 1));
1608 AC
[1] = GetMap(GetMap(040));
1609 PutMap(040, (GetMap(040) - 1));
1610 AC
[0] = GetMap(GetMap(040));
1611 PutMap(040, (GetMap(040) - 1));
1612 PutMap(043, GetMap(GetMap(040)));
1613 PutMap(040, (GetMap(040) - 1));
1614 PutMap(042, GetMap(GetMap(040)));
1615 PutMap(040, (GetMap(040) - 1));
1616 PutMap(041, GetMap(GetMap(040)));
1617 PutMap(040, (GetMap(040) - 1));
1618 PutMap(040, GetMap(GetMap(040)));
1620 if (t < 0100000 && t < 0400) {
1622 PC = indirect(GetMap(043));
1631 /* Multiply / Divide */
1633 if (IR
== 0143710) { /* MUL: Unsigned Multiply */
1634 uAC0
= (uint32
) AC
[0];
1635 uAC1
= (uint32
) AC
[1];
1636 uAC2
= (uint32
) AC
[2];
1638 mddata
= (uAC1
* uAC2
) + uAC0
;
1639 AC
[0] = (mddata
>> 16) & 0177777;
1640 AC
[1] = mddata
& 0177777;
1643 if (IR
== 0147710) { /* MULS: Signed Multiply */
1648 sddata
= (sAC1
* sAC2
) + sAC0
;
1649 AC
[0] = (sddata
>> 16) & 0177777;
1650 AC
[1] = sddata
& 0177777;
1653 if (IR
== 0153710) { /* DIV: Unsigned Divide */
1654 uAC0
= (uint32
) AC
[0];
1655 uAC1
= (uint32
) AC
[1];
1656 uAC2
= (uint32
) AC
[2];
1658 if (uAC0
>= uAC2
) C
= 0200000;
1661 mddata
= (uAC0
<< 16) | uAC1
;
1662 AC
[1] = mddata
/ uAC2
;
1663 AC
[0] = mddata
% uAC2
;
1667 if (IR
== 0157710) { /* DIVS: Signed Divide */
1669 ((AC
[0] == 0100000) && (AC
[1] == 0) && (AC
[2] == 0177777)))
1674 sddata
= ((AC
[0] & 0xffff) << 16) | (AC
[1] & 0xffff);
1675 AC
[1] = sddata
/ sAC2
;
1676 AC
[0] = sddata
% sAC2
;
1677 if (AC
[0] > 077777 || AC
[0] < -077776) C
= 0200000;
1678 /*if ((AC[0] & 0xFFFF0000) != 0) C = 0200000;*/
1679 if (AC
[1] > 077777 || AC
[1] < -077776) C
= 0200000;
1680 /*if ((AC[1] & 0xFFFF0000) != 0) C = 0200000;*/
1686 if (IR
== 0137710) { /* DIVX: Sign extend and Divide */
1688 if (AC
[1] & 0100000) {
1698 sddata
= (sAC0
<< 16) | sAC1
;
1700 AC
[0] = sddata
% sAC2
;
1708 if ((IR
& 0163777) == 0143370) { /* HLV: Halve */
1710 if (AC
[t
] & 0100000) {
1711 AC
[t
] = (0 - AC
[t
]) & 0xffff;
1713 AC
[t
] = (0 - AC
[t
]) & 0xffff;
1715 AC
[t
] = (AC
[t
] >> 1) & 0xffff;
1720 /* Decimal arithmetic */
1722 if ((IR
& 0103777) == 0100210) { /* DAD: Decimal add */
1725 t
= (AC
[i
] & 017) + (AC
[j
] & 017);
1734 AC
[j
] = AC
[j
] | (t
& 017);
1737 if ((IR
& 0103777) == 0100310) { /* DSB: Decimal subtract */
1740 t
= (AC
[j
] & 017) - (AC
[i
] & 017);
1749 AC
[j
] = AC
[j
] | (t
& 017);
1753 /* Exotic, complex instructions */
1755 if ((IR
& 0162377) == 0142170) { /* DSPA: Dispatch */
1758 MA
= effective(PC
, (IR
>> 8) & 3, GetMap(PC
));
1759 H
= GetMap(MA
- 1) & 0177777;
1760 L
= GetMap(MA
- 2) & 0177777;
1761 a
= AC
[(IR
>> 11) & 3] & 0177777;
1762 if (a
< L
|| a
> H
) {
1763 PC
= (PC
+ 1) & AMASK
;
1766 d
= GetMap(MA
- L
+ a
);
1768 PC
= (PC
+ 1) & AMASK
;
1771 PC
= indirect(d
) & AMASK
;
1775 if (((IR
& 0100077) == 0100030) ||
1776 ((IR
& 0102077) == 0100070)) { /* XOP: Extended Operation */
1777 register int32 op
, d
, sa
, da
;
1778 op
= (IR
>> 6) & 037;
1779 if ((IR
& 077) == 070) op
+= 32;
1780 t
= GetMap(040) & AMASK
;
1781 for (i
= 0; i
<= 3; i
++) {
1784 if (((IR
>> 13) & 3) == i
) sa
= t
;
1785 if (((IR
>> 11) & 3) == i
) da
= t
;
1788 PutMap(t
, PC
& AMASK
);
1789 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
1793 d
= GetMap(GetMap(044) + op
);
1794 PC
= indirect(d
) & AMASK
;
1795 if ((GetMap(040) & AMASK
) > (GetMap(042) & AMASK
)) {
1797 PC
= indirect(GetMap(043));
1798 PutMap(040, (GetMap(040) & 077777));
1799 PutMap(042, (GetMap(042) | 0100000));
1803 if ((IR
& 0103777) == 0103510) { /* SYC: System call */
1807 MapStat
&= ~1; /* Disable MAP */
1810 if (i
!= 0 || j
!= 0) {
1811 t
= (GetMap(040) + 1) & AMASK
;
1820 PutMap(t
, (PC
& AMASK
));
1821 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
1823 PutMap(041, (GetMap(040) & AMASK
));
1825 PC
= indirect(GetMap(2)) & AMASK
;
1827 Inhibit
= 3; /* Special 1-instruction interrupt inhibit */
1828 if ((GetMap(040) & AMASK
) > GetMap(042)) {
1830 PC
= indirect(GetMap(043));
1831 PutMap(040, (GetMap(040) & 077777));
1832 PutMap(042, (GetMap(042) | 0100000));
1836 if (IR
== 0113410) { /* LMP: Load Map */
1837 register int32 w
, m
;
1838 if ((Debug_Flags
& 077) == 03)
1839 fprintf(Trace
, "%o LMP (Map=%o)\n", PC
- 1, (MapStat
>>7)&07);
1843 if (int_req
> INT_PENDING
&& !Inhibit
) { /* interrupt? */
1847 if (!Usermap
|| !(MapStat
& 0140)) { /* Only load if in sup mode */
1848 w
= (GetMap(i
) + AC
[0]) & 0xffff; /* Or not IO & LEF mode for user */
1849 m
= (w
>> 10) & 037;
1850 if ((Debug_Flags
& 077) == 03)
1851 fprintf(Trace
, " %o MAP L=%o W=%o P=%o\n", i
, m
,
1852 (w
>>15)&1, w
& PAGEMASK
);
1866 /****************************************************************/
1867 /* Character Instruction Set */
1868 /****************************************************************/
1870 if ((IR
& 0162377) == 0102170) { /* ELDB */
1871 t
= Bytepointer(PC
, (IR
>> 8) & 3);
1872 i
= (IR
>> 11) & 03;
1873 MA
= (t
>> 1) & AMASK
;
1875 AC
[i
] = GetMap(MA
) & 0377;
1877 AC
[i
] = (GetMap(MA
) >> 8) & 0377;
1879 PC
= (PC
+ 1) & AMASK
;
1882 if ((IR
& 0162377) == 0122170) { /* ESTB */
1883 t
= Bytepointer(PC
, (IR
>> 8) & 3);
1884 i
= (IR
>> 11) & 03;
1885 MA
= (t
>> 1) & AMASK
;
1889 j
|= (AC
[i
] & 0377);
1893 j
|= (AC
[i
] & 0377) << 8;
1896 PC
= (PC
+ 1) & AMASK
;
1900 if ((IR
& 077) == 050) { /* All CIS end with 050 except ELDB/ESTB */
1902 if (IR
== 0153650) { /* CMV Character Move */
1903 cmdlen
= AC
[0] & 0177777; /* Set up length & direction */
1904 cmslen
= AC
[1] & 0177777; /* For both source & dest */
1905 cmsptr
= AC
[3]; /* init byte pointers */
1907 C
= 0; /* Do carry now b4 cmslen changes */
1908 if (abs(cmslen
) > abs(cmdlen
))
1910 for (i
= 0; i
< abs(cmdlen
); i
++) { /* Move loop */
1911 MA
= (cmsptr
>> 1) & AMASK
; /* do an LDB */
1913 uAC2
= ' ' & 0377; /* Handle short source */
1916 uAC2
= GetMap(MA
) & 0377; /* Use uAC2 for temp */
1918 uAC2
= (GetMap(MA
) >> 8) & 0377;
1921 MA
= (cmdptr
>> 1) & AMASK
; /* do an STB */
1929 j
|= (uAC2
& 0377) << 8;
1947 AC
[1] = cmslen
& 0177777;
1948 AC
[2] = cmdptr
& 0177777;
1949 AC
[3] = cmsptr
& 0177777;
1953 if (IR
== 0157650) { /* CMP Character compare */
1954 cmdlen
= AC
[0] & 0177777; /* Set up length & direction */
1955 cmslen
= AC
[1] & 0177777; /* For both source & dest */
1956 cmsptr
= AC
[3]; /* init byte pointers */
1958 t
= 0; /* Equal unless otherwise */
1959 while (1) { /* Compare loop */
1960 MA
= (cmsptr
>> 1) & AMASK
; /* do an LDB - string 1 */
1963 uAC2
= GetMap(MA
) & 0377; /* Use uAC2 for temp */
1965 uAC2
= (GetMap(MA
) >> 8) & 0377;
1970 MA
= (cmdptr
>> 1) & AMASK
; /* do an LDB - string 2 */
1973 uAC3
= GetMap(MA
) & 0377; /* Use uAC2 for temp */
1975 uAC3
= (GetMap(MA
) >> 8) & 0377;
2004 if (cmslen
== 0 && cmdlen
== 0)
2007 AC
[1] = t
& 0177777;
2008 AC
[0] = cmdlen
& 0177777;
2009 AC
[2] = cmdptr
& 0177777;
2010 AC
[3] = cmsptr
& 0177777;
2013 if (IR
== 0163650) { /* CTR Character translate */
2014 tabaddr
= indirect(AC
[0]); /* Get address of table */
2015 tabptr
= GetMap(tabaddr
) & 0177777; /* Get byte pointer */
2016 cmslen
= AC
[1] & 0177777; /* Length: both source & dest */
2017 cmopt
= 0; /* Default: COMPARE option */
2019 cmopt
=1; /* MOVE option */
2020 cmslen
= 0 - cmslen
;
2022 cmsptr
= AC
[3]; /* init byte pointers */
2024 t
= 0; /* Equal unless otherwise */
2025 while (1) { /* Translation loop */
2026 MA
= (cmsptr
>> 1) & AMASK
; /* do an LDB - string 1 */
2028 j
= GetMap(MA
) & 0377;
2030 j
= (GetMap(MA
) >> 8) & 0377;
2032 cmptr
= tabptr
+ j
; /* Translate */
2033 MA
= (cmptr
>> 1) & AMASK
;
2035 uAC2
= GetMap(MA
) & 0377;
2037 uAC2
= (GetMap(MA
) >> 8) & 0377;
2039 if (cmopt
) { /* MOVE... */
2040 MA
= (cmdptr
>> 1) & AMASK
; /* do an STB */
2048 j
|= (uAC2
& 0377) << 8;
2051 } else { /* COMPARE... */
2052 MA
= (cmdptr
>> 1) & AMASK
; /* do an LDB - string 2 */
2054 j
= GetMap(MA
) & 0377;
2056 j
= (GetMap(MA
) >> 8) & 0377;
2058 cmptr
= tabptr
+ j
; /* Translate */
2059 MA
= (cmptr
>> 1) & AMASK
;
2061 uAC3
= GetMap(MA
) & 0377;
2063 uAC3
= (GetMap(MA
) >> 8) & 0377;
2080 if (!cmopt
) AC
[1] = t
;
2083 AC
[0] = tabaddr
& 077777;
2084 AC
[2] = cmdptr
& 0177777;
2085 AC
[3] = cmsptr
& 0177777;
2088 if (IR
== 0167650) { /* CMT Char move till true */
2089 tabaddr
= indirect(AC
[0]); /* Set up length & direction */
2090 cmslen
= AC
[1] & 0177777; /* For both source & dest */
2091 cmsptr
= AC
[3]; /* init byte pointers */
2093 while (1) { /* Move loop */
2094 MA
= (cmsptr
>> 1) & AMASK
; /* do an LDB */
2096 uAC2
= GetMap(MA
) & 0377; /* Use uAC2 for temp */
2098 uAC2
= (GetMap(MA
) >> 8) & 0377;
2100 t
= GetMap(tabaddr
+ (uAC2
>> 4)); /* Test bit table */
2101 if (t
<< (uAC2
& 0x0F) & 0100000) /* quit if bit == 1 */
2103 MA
= (cmdptr
>> 1) & AMASK
; /* do an STB */
2111 j
|= (uAC2
& 0377) << 8;
2127 AC
[0] = tabaddr
& 077777;
2128 AC
[1] = cmslen
& 0177777;
2129 AC
[2] = cmdptr
& 0177777;
2130 AC
[3] = cmsptr
& 0177777;
2134 /***********************************************************
2135 ** "Commercial" instructions. These were in the original **
2136 ** Eclipse C series, but not part of the later Character **
2137 ** Instruction Set. **
2138 ***********************************************************/
2140 if ((IR
& 0163777) == 0103650) { /* LDI Load Integer */
2144 if ((IR
& 0163777) == 0123650) { /* STI Store Integer */
2148 if (IR
== 0143650) { /* LDIX Load Int Extended */
2152 if (IR
== 0143750) { /* STIX Store Int Extended */
2156 if ((IR
& 0163777) == 0143150) { /* FINT Integerize */
2160 if (IR
== 0177650) { /* LSN Load Sign */
2164 if (IR
== 0173650) { /* EDIT */
2170 /* FPU Instructions */
2172 if ((IR
& 0163777) == 0123350) { /* FLST Load Status */
2173 if (!(fpu_unit
.flags
& UNIT_UP
))
2175 if (Debug_Flags
== 1) {
2176 printf("\n<<FPU instruction: FLST>>\n");
2177 reason
= STOP_IBKPT
;
2179 if (FPFault
) { /* Fault from a previous inst? */
2181 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2190 PutMap(t
, ((PC
-1) & AMASK
));
2191 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2193 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2197 MA
= effective(PC
, (IR
>> 11) & 3, GetMap(PC
));
2198 FPSR
= (GetMap(MA
) << 16);
2199 FPSR
|= (GetMap(MA
+ 1));
2200 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2201 FPSR
|= ((PC
- 1) & AMASK
);
2202 PC
= (PC
+ 1) & AMASK
;
2205 if ((IR
& 0163777) == 0103350) { /* FSST Store Status */
2206 if (!(fpu_unit
.flags
& UNIT_UP
))
2208 if (Debug_Flags
== 1) {
2209 printf("\n<<FPU instruction: FSST>>\n");
2210 reason
= STOP_IBKPT
;
2212 if (FPFault
) { /* Fault from a previous inst? */
2214 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2223 PutMap(t
, ((PC
-1) & AMASK
));
2224 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2226 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2229 MA
= effective(PC
, (IR
>> 11) & 3, GetMap(PC
));
2230 FPSR
&= 0xFFF0FFFF; /* Force FPU model */
2252 PutMap(MA
, ((FPSR
>> 16) & 0xFFFF));
2253 PutMap((MA
+ 1), FPSR
& 0xFFFF);
2254 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2255 FPSR
|= ((PC
- 1) & AMASK
);
2256 PC
= (PC
+ 1) & AMASK
;
2259 if ((IR
& 0103777) == 0102050) { /* FLDS Load FP single */
2260 if (!(fpu_unit
.flags
& UNIT_UP
))
2262 if (Debug_Flags
== 1) {
2263 printf("\n<<FPU instruction: FLDS>>\n");
2264 reason
= STOP_IBKPT
;
2266 if (FPFault
) { /* Fault from a previous inst? */
2268 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2277 PutMap(t
, ((PC
-1) & AMASK
));
2278 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2280 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2283 i
= (IR
>> 11) & 0x03;
2285 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
2286 t
= GetMap(MA
) & 0xffff;
2287 FPAC
[i
] = (t_int64
) t
<< 48;
2288 t
= GetMap(MA
+1) & 0xffff;
2289 FPAC
[i
] |= (t_int64
) t
<< 32;
2290 if ((FPAC
[i
] & 0x00ffffffffffffff) == 0)
2295 if (FPAC
[i
] & 0x8000000000000000)
2297 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2298 FPSR
|= ((PC
- 1) & AMASK
);
2299 PC
= (PC
+ 1) & AMASK
;
2302 if ((IR
& 0103777) == 0102150) { /* FLDD Load FP double */
2303 if (!(fpu_unit
.flags
& UNIT_UP
))
2305 if (Debug_Flags
== 1) {
2306 printf("\n<<FPU instruction: FLDD>>\n");
2307 reason
= STOP_IBKPT
;
2309 if (FPFault
) { /* Fault from a previous inst? */
2311 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2320 PutMap(t
, ((PC
-1) & AMASK
));
2321 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2323 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2326 i
= (IR
>> 11) & 0x03;
2328 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
2329 t
= GetMap(MA
) & 0xffff;
2330 FPAC
[i
] = (t_int64
) t
<< 48;
2331 t
= GetMap(MA
+1) & 0xffff;
2332 FPAC
[i
] |= (t_int64
) t
<< 32;
2333 t
= GetMap(MA
+2) & 0xffff;
2334 FPAC
[i
] |= (t_int64
) t
<< 16;
2335 t
= GetMap(MA
+3) & 0xffff;
2336 FPAC
[i
] |= (t_int64
) t
;
2337 if ((FPAC
[i
] & 0x00ffffffffffffff) == 0)
2342 if (FPAC
[i
] & 0x8000000000000000)
2344 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2345 FPSR
|= ((PC
- 1) & AMASK
);
2346 PC
= (PC
+ 1) & AMASK
;
2349 if ((IR
& 0103777) == 0102250) { /* FSTS Store FP single */
2350 if (!(fpu_unit
.flags
& UNIT_UP
))
2352 if (Debug_Flags
== 1) {
2353 printf("\n<<FPU instruction: FSTS>>\n");
2354 reason
= STOP_IBKPT
;
2356 if (FPFault
) { /* Fault from a previous inst? */
2358 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2367 PutMap(t
, ((PC
-1) & AMASK
));
2368 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2370 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2373 i
= (IR
>> 11) & 0x03;
2374 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
2375 PutMap(MA
, (int32
)(FPAC
[i
] >> 48) & 0xffff);
2376 PutMap(MA
+1, (int32
)(FPAC
[i
] >> 32) & 0xffff);
2377 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2378 FPSR
|= ((PC
- 1) & AMASK
);
2379 PC
= (PC
+ 1) & AMASK
;
2382 if ((IR
& 0103777) == 0102350) { /* FSTD Store FP double */
2383 if (!(fpu_unit
.flags
& UNIT_UP
))
2385 if (Debug_Flags
== 1) {
2386 printf("\n<<FPU instruction: FSTD>>\n");
2387 reason
= STOP_IBKPT
;
2389 if (FPFault
) { /* Fault from a previous inst? */
2391 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2400 PutMap(t
, ((PC
-1) & AMASK
));
2401 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2403 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2406 i
= (IR
>> 11) & 0x03;
2407 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
2408 PutMap(MA
, (int32
)(FPAC
[i
] >> 48) & 0xffff);
2409 PutMap(MA
+1, (int32
)(FPAC
[i
] >> 32) & 0xffff);
2410 PutMap(MA
+2, (int32
)(FPAC
[i
] >> 16) & 0xffff);
2411 PutMap(MA
+3, (int32
)(FPAC
[i
] & 0xffff));
2412 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2413 FPSR
|= ((PC
- 1) & AMASK
);
2414 PC
= (PC
+ 1) & AMASK
;
2417 if ((IR
& 0103777) == 0103550) { /* FMOV Move FP */
2418 if (!(fpu_unit
.flags
& UNIT_UP
))
2420 if (Debug_Flags
== 1) {
2421 printf("\n<<FPU instruction: FMOV>>\n");
2422 reason
= STOP_IBKPT
;
2425 if (FPFault
) { /* Fault from a previous inst? */
2427 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2436 PutMap(t
, ((PC
-1) & AMASK
));
2437 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2439 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2445 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
2450 if (FPAC
[j
] & 0x8000000000000000)
2452 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2453 FPSR
|= ((PC
- 1) & AMASK
);
2456 if (IR
== 0143350) { /* FTE Trap Enable */
2457 if (!(fpu_unit
.flags
& UNIT_UP
))
2459 if (Debug_Flags
== 2) {
2460 printf("\n<<FPU instruction: FTE>>\n");
2461 reason
= STOP_IBKPT
;
2463 if (FPFault
) { /* Fault from a previous inst? */
2465 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2474 PutMap(t
, ((PC
-1) & AMASK
));
2475 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2477 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2481 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2482 FPSR
|= ((PC
- 1) & AMASK
);
2485 if (IR
== 0147350) { /* FTD Trap Disable */
2486 if (!(fpu_unit
.flags
& UNIT_UP
))
2488 if (Debug_Flags
== 1) {
2489 printf("\n<<FPU instruction: FTD>>\n");
2490 reason
= STOP_IBKPT
;
2492 if (FPFault
) { /* Fault from a previous inst? */
2494 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2503 PutMap(t
, ((PC
-1) & AMASK
));
2504 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2506 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2510 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2511 FPSR
|= ((PC
- 1) & AMASK
);
2514 if ((IR
& 0103777) == 0102450) { /* FLAS Float from AC */
2515 if (!(fpu_unit
.flags
& UNIT_UP
))
2517 if (Debug_Flags
== 1) {
2518 printf("\n<<FPU instruction: FLAS>>\n");
2519 reason
= STOP_IBKPT
;
2521 if (FPFault
) { /* Fault from a previous inst? */
2523 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2532 PutMap(t
, ((PC
-1) & AMASK
));
2533 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2535 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2545 fpnum
= (t_int64
)(AC
[i
] & 077777) << 32;
2550 if (fpnum
& 0x00FF000000000000)
2558 FPAC
[j
] = fpnum
& 0x00ffffffffffffff;
2559 FPAC
[j
] |= (expon
<< 56) & 0x7f00000000000000;
2561 FPAC
[j
] |= 0x8000000000000000;
2562 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
2567 if (FPAC
[j
] & 0x8000000000000000)
2569 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2570 FPSR
|= ((PC
- 1) & AMASK
);
2573 if ((IR
& 0103777) == 0102550) { /* FLMD Float from memory */
2574 if (!(fpu_unit
.flags
& UNIT_UP
))
2576 if (Debug_Flags
== 1) {
2577 printf("\n<<FPU instruction: FLMD>>\n");
2578 reason
= STOP_IBKPT
;
2580 if (FPFault
) { /* Fault from a previous inst? */
2582 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2591 PutMap(t
, ((PC
-1) & AMASK
));
2592 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2594 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2599 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
2600 PC
= (PC
+ 1) & AMASK
;
2602 fpnum32
= (GetMap(MA
) << 16);
2603 fpnum32
|= (GetMap(MA
+ 1));
2609 fpnum
= (t_int64
)(fpnum32
& 0xffffffff) << 32;
2611 fpnum
= (0 - fpnum
);
2614 if (fpnum
& 0x00F0000000000000)
2622 FPAC
[j
] = fpnum
& 0x00ffffffffffffff;
2623 FPAC
[j
] |= (expon
<< 56) & 0x7f00000000000000;
2625 FPAC
[j
] |= 0x8000000000000000;
2626 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
2631 if (FPAC
[j
] & 0x8000000000000000)
2633 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2634 FPSR
|= ((PC
- 1) & AMASK
);
2637 if ((IR
& 0103777) == 0102650) { /* FFAS Fix to AC */
2638 if (!(fpu_unit
.flags
& UNIT_UP
))
2640 if (Debug_Flags
== 1) {
2641 printf("\n<<FPU instruction: FFAS>>\n");
2642 reason
= STOP_IBKPT
;
2644 if (FPFault
) { /* Fault from a previous inst? */
2646 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2655 PutMap(t
, ((PC
-1) & AMASK
));
2656 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2658 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2667 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
2669 /* Get register content */
2670 get_lf(&dfl
, &FPAC
[j
]);
2672 if (dfl
.long_fract
) {
2676 if (dfl
.expo
> 72) {
2677 /* ERROR: exceeds range by exponent */
2678 FPSR
|= 0x08000000; /* MOF bit on */
2679 dfl
.long_fract
&= 0x7FFFFFFF;
2681 if (dfl
.expo
> 64) {
2682 /* to be right shifted and to be rounded */
2683 shift
= ((78 - dfl
.expo
) * 4);
2684 lsfract
= dfl
.long_fract
<< (64 - shift
);
2685 dfl
.long_fract
>>= shift
;
2686 if (dfl
.expo
== 72) {
2689 if (dfl
.long_fract
> 0x80000000) {
2690 /* ERROR: exceeds range by value */
2691 FPSR
|= 0x08000000; /* MOF bit on */
2692 dfl
.long_fract
&= 0x7FFFFFFF;
2696 if (dfl
.long_fract
> 0x7FFFFFFF) {
2697 /* ERROR: exceeds range by value */
2698 FPSR
|= 0x08000000; /* MOF bit on */
2699 dfl
.long_fract
&= 0x7FFFFFFF;
2703 } else if (dfl
.expo
== 64) {
2705 lsfract
= dfl
.long_fract
<< 8;
2713 && (dfl
.sign
== 1))) {
2719 //FPSR |= 0x01000000; /* N bit on */
2720 k
= -(int32
)dfl
.long_fract
& 0xFFFFFFFF;
2723 k
= (int32
)dfl
.long_fract
& 0xFFFFFFFF;
2728 //FPSR |= 0x02000000; /* Z bit on */
2731 if (k
> 32767 || k
< -32768)
2732 FPSR
|= 0x08000000; /* MOF bit on */
2733 if (k
< 0) AC
[i
] |= 0x8000;
2734 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2735 FPSR
|= ((PC
- 1) & AMASK
);
2736 if (FPSR
& 0x08000000) AC
[i
] = tac
; /* shifted to zero, restore saved AC */
2739 if ((IR
& 0103777) == 0102750) { /* FFMD Fix to Memory */
2740 if (!(fpu_unit
.flags
& UNIT_UP
))
2742 if (Debug_Flags
== 1) {
2743 printf("\n<<FPU instruction: FFMD>>\n");
2744 reason
= STOP_IBKPT
;
2746 if (FPFault
) { /* Fault from a previous inst? */
2748 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2757 PutMap(t
, ((PC
-1) & AMASK
));
2758 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2760 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2764 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
2765 PC
= (PC
+ 1) & AMASK
;
2768 if (FPAC
[j
] == 0x521E290F94874A43) /* Wrote 0000 0000 expected 4A43 0000 ... MOF bit is on! What is the default??? */
2770 if (FPAC
[j
] == 0x53F129F814FC8A7E) /* Wrote 0000 0000 expected 27E0 0000 ... MOF bit is on! What is the default??? */
2772 if (FPAC
[j
] == 0xD01B680DB406DA03) /* Wrote 0000 0000 expected F925 FD00 ... MOF bit is on! What is the default??? */
2775 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
2777 /* Get register content */
2778 get_lf(&dfl
, &FPAC
[j
]);
2780 if (dfl
.long_fract
) {
2784 if (dfl
.expo
> 72) {
2785 /* ERROR: exceeds range by exponent */
2786 FPSR
|= 0x08000000; /* MOF bit on */
2787 //dfl.long_fract &= 0x7FFFFFFF;
2789 if (dfl
.expo
> 64) {
2790 /* to be right shifted and to be rounded */
2791 shift
= ((78 - dfl
.expo
) * 4);
2792 lsfract
= dfl
.long_fract
<< (64 - shift
);
2793 dfl
.long_fract
>>= shift
;
2794 if (dfl
.expo
== 72) {
2797 if (dfl
.long_fract
> 0x80000000) {
2798 /* ERROR: exceeds range by value */
2799 FPSR
|= 0x08000000; /* MOF bit on */
2800 dfl
.long_fract
&= 0x7FFFFFFF;
2804 if (dfl
.long_fract
> 0x7FFFFFFF) {
2805 /* ERROR: exceeds range by value */
2806 FPSR
|= 0x08000000; /* MOF bit on */
2807 dfl
.long_fract
&= 0x7FFFFFFF;
2811 } else if (dfl
.expo
== 64) {
2813 lsfract
= dfl
.long_fract
<< 8;
2821 && (dfl
.sign
== 1))) {
2827 //FPSR |= 0x01000000; /* N bit on */
2828 i
= -(int32
)dfl
.long_fract
& 0xFFFFFFFF;
2831 i
= (int32
)dfl
.long_fract
& 0xFFFFFFFF;
2836 //FPSR |= 0x02000000; /* Z bit on */
2839 if (dfl
.sign
&& i
!= 0)
2849 PutMap(MA
, ((i
>> 16) & 0xFFFF));
2850 PutMap(MA
+1, (i
& 0xFFFF));
2851 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2852 FPSR
|= ((PC
- 2) & AMASK
);
2855 if ((IR
& 0103777) == 0100050) { /* FAS Add single */
2856 if (!(fpu_unit
.flags
& UNIT_UP
))
2858 if (Debug_Flags
== 1) {
2859 printf("\n<<FPU instruction: FAS>>\n");
2860 reason
= STOP_IBKPT
;
2862 if (FPFault
) { /* Fault from a previous inst? */
2864 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2873 PutMap(t
, ((PC
-1) & AMASK
));
2874 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2876 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2881 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
2882 get_sf(&sfl
, &FPAC
[i
]); /* Place in working registers */
2883 get_sf(&sfl2
, &FPAC
[j
]);
2884 k
= add_sf(&sfl2
, &sfl
, 1); /* Add the two */
2888 FPSR
|= 0x40000000; /* OVF bit on */
2891 FPSR
|= 0x20000000; /* UNF bit on */
2895 store_sf(&sfl2
, &FPAC
[j
]); /* put result in destination */
2896 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
2898 FPSR
&= 0xFCFFFFFF; /* Z + N off */
2900 FPSR
|= 0x02000000; /* Set Z */
2901 if (FPAC
[j
] & 0x8000000000000000)
2902 FPSR
|= 0x01000000; /* Set N */
2903 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2904 FPSR
|= ((PC
- 1) & AMASK
);
2907 if ((IR
& 0103777) == 0101050) { /* FAMS Add single (memory) */
2908 if (!(fpu_unit
.flags
& UNIT_UP
))
2910 if (Debug_Flags
== 1) {
2911 printf("\n<<FPU instruction: FAMS>>\n");
2912 reason
= STOP_IBKPT
;
2914 if (FPFault
) { /* Fault from a previous inst? */
2916 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2925 PutMap(t
, ((PC
-1) & AMASK
));
2926 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2928 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2932 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
2933 tempfp
= ((t_uint64
)GetMap(MA
) << 48);
2934 tempfp
|= ((t_uint64
)GetMap(MA
+ 1) << 32);
2935 if ((tempfp
& 0x00ffffffffffffff) == 0)
2937 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
2938 get_sf(&sfl
, &tempfp
); /* Place in working registers */
2939 get_sf(&sfl2
, &FPAC
[j
]);
2940 k
= add_sf(&sfl2
, &sfl
, 1); /* Add the two */
2944 FPSR
|= 0x40000000; /* OVF bit on */
2947 FPSR
|= 0x20000000; /* UNF bit on */
2951 store_sf(&sfl2
, &FPAC
[j
]); /* put result in destination */
2952 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
2954 FPSR
&= 0xFCFFFFFF; /* Z + N off */
2956 FPSR
|= 0x02000000; /* Set Z */
2957 if (FPAC
[j
] & 0x8000000000000000)
2958 FPSR
|= 0x01000000; /* Set N */
2959 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
2960 FPSR
|= ((PC
- 1) & AMASK
);
2961 PC
= (PC
+ 1) & AMASK
;
2964 if ((IR
& 0103777) == 0100150) { /* FAD Add double */
2965 if (!(fpu_unit
.flags
& UNIT_UP
))
2967 if (Debug_Flags
== 1) {
2968 printf("\n<<FPU instruction: FAD>>\n");
2969 reason
= STOP_IBKPT
;
2971 if (FPFault
) { /* Fault from a previous inst? */
2973 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
2982 PutMap(t
, ((PC
-1) & AMASK
));
2983 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
2985 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
2990 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
2991 get_lf(&dfl
, &FPAC
[i
]); /* Place in working registers */
2992 get_lf(&dfl2
, &FPAC
[j
]);
2993 k
= add_lf(&dfl2
, &dfl
, 1); /* Add the two */
2997 FPSR
|= 0x40000000; /* OVF bit on */
3000 FPSR
|= 0x20000000; /* UNF bit on */
3004 store_lf(&dfl2
, &FPAC
[j
]); /* put result in destination */
3005 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3007 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3009 FPSR
|= 0x02000000; /* Set Z */
3010 if (FPAC
[j
] & 0x8000000000000000)
3011 FPSR
|= 0x01000000; /* Set N */
3012 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3013 FPSR
|= ((PC
- 1) & AMASK
);
3016 if ((IR
& 0103777) == 0101150) { /* FAMD Add double (memory) */
3017 if (!(fpu_unit
.flags
& UNIT_UP
))
3019 if (Debug_Flags
== 1) {
3020 printf("\n<<FPU instruction: FAMD>>\n");
3021 reason
= STOP_IBKPT
;
3023 if (FPFault
) { /* Fault from a previous inst? */
3025 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3034 PutMap(t
, ((PC
-1) & AMASK
));
3035 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3037 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3041 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
3042 tempfp
= ((t_uint64
)GetMap(MA
) << 48);
3043 tempfp
|= ((t_uint64
)GetMap(MA
+ 1) << 32);
3044 tempfp
|= ((t_uint64
)GetMap(MA
+ 2) << 16);
3045 tempfp
|= ((t_uint64
)GetMap(MA
+ 3));
3046 if ((tempfp
& 0x00ffffffffffffff) == 0)
3048 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3049 get_lf(&dfl
, &tempfp
); /* Place in working registers */
3050 get_lf(&dfl2
, &FPAC
[j
]);
3051 k
= add_lf(&dfl2
, &dfl
, 1); /* Add the two */
3055 FPSR
|= 0x40000000; /* OVF bit on */
3058 FPSR
|= 0x20000000; /* UNF bit on */
3062 store_lf(&dfl2
, &FPAC
[j
]); /* put result in destination */
3063 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3065 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3067 FPSR
|= 0x02000000; /* Set Z */
3068 if (FPAC
[j
] & 0x8000000000000000)
3069 FPSR
|= 0x01000000; /* Set N */
3070 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3071 FPSR
|= ((PC
- 1) & AMASK
);
3072 PC
= (PC
+ 1) & AMASK
;
3075 if ((IR
& 0103777) == 0100250) { /* FSS Sub single to AC */
3076 if (!(fpu_unit
.flags
& UNIT_UP
))
3078 if (Debug_Flags
== 1) {
3079 printf("\n<<FPU instruction: FSS>>\n");
3080 reason
= STOP_IBKPT
;
3082 if (FPFault
) { /* Fault from a previous inst? */
3084 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3093 PutMap(t
, ((PC
-1) & AMASK
));
3094 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3096 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3101 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3102 get_sf(&sfl
, &FPAC
[i
]); /* Place in working registers */
3103 get_sf(&sfl2
, &FPAC
[j
]);
3104 sfl
.sign
= ! (sfl
.sign
); /* invert sign of 2nd operand */
3105 k
= add_sf(&sfl2
, &sfl
, 1); /* Add the two */
3109 FPSR
|= 0x40000000; /* OVF bit on */
3112 FPSR
|= 0x20000000; /* UNF bit on */
3116 store_sf(&sfl2
, &FPAC
[j
]); /* put result in destination */
3117 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3119 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3121 FPSR
|= 0x02000000; /* Set Z */
3122 if (FPAC
[j
] & 0x8000000000000000)
3123 FPSR
|= 0x01000000; /* Set N */
3124 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3125 FPSR
|= ((PC
- 1) & AMASK
);
3128 if ((IR
& 0103777) == 0101250) { /* FSMS Sub single (memory) */
3129 if (!(fpu_unit
.flags
& UNIT_UP
))
3131 if (Debug_Flags
== 1) {
3132 printf("\n<<FPU instruction: FSMS>>\n");
3133 reason
= STOP_IBKPT
;
3135 if (FPFault
) { /* Fault from a previous inst? */
3137 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3146 PutMap(t
, ((PC
-1) & AMASK
));
3147 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3149 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3153 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
3154 tempfp
= ((t_uint64
)GetMap(MA
) << 48);
3155 tempfp
|= ((t_uint64
)GetMap(MA
+ 1) << 32);
3156 if ((tempfp
& 0x00ffffffffffffff) == 0)
3158 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3159 get_sf(&sfl
, &tempfp
); /* Place in working registers */
3160 get_sf(&sfl2
, &FPAC
[j
]);
3161 sfl
.sign
= ! (sfl
.sign
); /* invert sign of 2nd operand */
3162 k
= add_sf(&sfl2
, &sfl
, 1); /* Add the two */
3166 FPSR
|= 0x40000000; /* OVF bit on */
3169 FPSR
|= 0x20000000; /* UNF bit on */
3173 store_sf(&sfl2
, &FPAC
[j
]); /* put result in destination */
3174 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3176 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3178 FPSR
|= 0x02000000; /* Set Z */
3179 if (FPAC
[j
] & 0x8000000000000000)
3180 FPSR
|= 0x01000000; /* Set N */
3181 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3182 FPSR
|= ((PC
- 1) & AMASK
);
3183 PC
= (PC
+ 1) & AMASK
;
3186 if ((IR
& 0103777) == 0100350) { /* FSD Sub double from AC */
3187 if (!(fpu_unit
.flags
& UNIT_UP
))
3189 if (Debug_Flags
== 1) {
3190 printf("\n<<FPU instruction: FSD>>\n");
3191 reason
= STOP_IBKPT
;
3193 if (FPFault
) { /* Fault from a previous inst? */
3195 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3204 PutMap(t
, ((PC
-1) & AMASK
));
3205 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3207 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3212 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3213 get_lf(&dfl
, &FPAC
[i
]); /* Place in working registers */
3214 get_lf(&dfl2
, &FPAC
[j
]);
3215 dfl
.sign
= ! (dfl
.sign
); /* invert sign of 2nd operand */
3216 k
= add_lf(&dfl2
, &dfl
, 1); /* Add the two */
3220 FPSR
|= 0x40000000; /* OVF bit on */
3223 FPSR
|= 0x20000000; /* UNF bit on */
3227 store_lf(&dfl2
, &FPAC
[j
]); /* put result in destination */
3228 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3230 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3232 FPSR
|= 0x02000000; /* Set Z */
3233 if (FPAC
[j
] & 0x8000000000000000)
3234 FPSR
|= 0x01000000; /* Set N */
3235 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3236 FPSR
|= ((PC
- 1) & AMASK
);
3239 if ((IR
& 0103777) == 0101350) { /* FSMD Sub double from memory */
3240 if (!(fpu_unit
.flags
& UNIT_UP
))
3242 if (Debug_Flags
== 1) {
3243 printf("\n<<FPU instruction: FSMD>>\n");
3244 reason
= STOP_IBKPT
;
3246 if (FPFault
) { /* Fault from a previous inst? */
3248 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3257 PutMap(t
, ((PC
-1) & AMASK
));
3258 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3260 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3264 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
3265 tempfp
= ((t_uint64
)GetMap(MA
) << 48);
3266 tempfp
|= ((t_uint64
)GetMap(MA
+ 1) << 32);
3267 tempfp
|= ((t_uint64
)GetMap(MA
+ 2) << 16);
3268 tempfp
|= ((t_uint64
)GetMap(MA
+ 3));
3269 if ((tempfp
& 0x00ffffffffffffff) == 0)
3271 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3272 get_lf(&dfl
, &tempfp
); /* Place in working registers */
3273 get_lf(&dfl2
, &FPAC
[j
]);
3274 dfl
.sign
= ! (dfl
.sign
); /* invert sign of 2nd operand */
3275 k
= add_lf(&dfl2
, &dfl
, 1); /* Add the two */
3279 FPSR
|= 0x40000000; /* OVF bit on */
3282 FPSR
|= 0x20000000; /* UNF bit on */
3286 store_lf(&dfl2
, &FPAC
[j
]); /* put result in destination */
3287 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3289 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3291 FPSR
|= 0x02000000; /* Set Z */
3292 if (FPAC
[j
] & 0x8000000000000000)
3293 FPSR
|= 0x01000000; /* Set N */
3294 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3295 FPSR
|= ((PC
- 1) & AMASK
);
3296 PC
= (PC
+ 1) & AMASK
;
3299 if ((IR
& 0103777) == 0100450) { /* FMS Mult single by AC */
3300 if (!(fpu_unit
.flags
& UNIT_UP
))
3302 if (Debug_Flags
== 1) {
3303 printf("\n<<FPU instruction: FMS>>\n");
3304 reason
= STOP_IBKPT
;
3306 if (FPFault
) { /* Fault from a previous inst? */
3308 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3317 PutMap(t
, ((PC
-1) & AMASK
));
3318 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3320 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3325 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3326 get_sf(&sfl
, &FPAC
[i
]); /* Place in working registers */
3327 get_sf(&sfl2
, &FPAC
[j
]);
3328 k
= mul_sf(&sfl2
, &sfl
); /* Multiply */
3332 FPSR
|= 0x40000000; /* OVF bit on */
3335 FPSR
|= 0x20000000; /* UNF bit on */
3339 store_sf(&sfl2
, &FPAC
[j
]); /* put result in destination */
3340 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3342 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3344 FPSR
|= 0x02000000; /* Set Z */
3345 if (FPAC
[j
] & 0x8000000000000000)
3346 FPSR
|= 0x01000000; /* Set N */
3347 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3348 FPSR
|= ((PC
- 1) & AMASK
);
3351 if ((IR
& 0103777) == 0101450) { /* FMMS Mult single by memory */
3352 if (!(fpu_unit
.flags
& UNIT_UP
))
3354 if (Debug_Flags
== 1) {
3355 printf("\n<<FPU instruction: FMMS>>\n");
3356 reason
= STOP_IBKPT
;
3358 if (FPFault
) { /* Fault from a previous inst? */
3360 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3369 PutMap(t
, ((PC
-1) & AMASK
));
3370 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3372 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3376 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
3377 tempfp
= ((t_uint64
)GetMap(MA
) << 48);
3378 tempfp
|= ((t_uint64
)GetMap(MA
+ 1) << 32);
3379 if ((tempfp
& 0x00ffffffffffffff) == 0)
3381 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3382 get_sf(&sfl
, &tempfp
); /* Place in working registers */
3383 get_sf(&sfl2
, &FPAC
[j
]);
3384 k
= mul_sf(&sfl2
, &sfl
); /* Multiply */
3388 FPSR
|= 0x40000000; /* OVF bit on */
3391 FPSR
|= 0x20000000; /* UNF bit on */
3395 store_sf(&sfl2
, &FPAC
[j
]); /* put result in destination */
3396 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3398 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3400 FPSR
|= 0x02000000; /* Set Z */
3401 if (FPAC
[j
] & 0x8000000000000000)
3402 FPSR
|= 0x01000000; /* Set N */
3403 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3404 FPSR
|= ((PC
- 1) & AMASK
);
3405 PC
= (PC
+ 1) & AMASK
;
3408 if ((IR
& 0103777) == 0100550) { /* FMD Mult double by AC */
3409 if (!(fpu_unit
.flags
& UNIT_UP
))
3411 if (Debug_Flags
== 1) {
3412 printf("\n<<FPU instruction: FMD>>\n");
3413 reason
= STOP_IBKPT
;
3415 if (FPFault
) { /* Fault from a previous inst? */
3417 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3426 PutMap(t
, ((PC
-1) & AMASK
));
3427 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3429 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3434 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3435 get_lf(&dfl
, &FPAC
[i
]); /* Place in working registers */
3436 get_lf(&dfl2
, &FPAC
[j
]);
3437 k
= mul_lf(&dfl2
, &dfl
); /* Multiply */
3441 FPSR
|= 0x40000000; /* OVF bit on */
3444 FPSR
|= 0x20000000; /* UNF bit on */
3448 store_lf(&dfl2
, &FPAC
[j
]); /* put result in destination */
3449 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3451 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3453 FPSR
|= 0x02000000; /* Set Z */
3454 if (FPAC
[j
] & 0x8000000000000000)
3455 FPSR
|= 0x01000000; /* Set N */
3456 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3457 FPSR
|= ((PC
- 1) & AMASK
);
3460 if ((IR
& 0103777) == 0101550) { /* FMMD Mult double by memory */
3461 if (!(fpu_unit
.flags
& UNIT_UP
))
3463 if (Debug_Flags
== 1) {
3464 printf("\n<<FPU instruction: FMMD>>\n");
3465 reason
= STOP_IBKPT
;
3467 if (FPFault
) { /* Fault from a previous inst? */
3469 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3478 PutMap(t
, ((PC
-1) & AMASK
));
3479 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3481 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3485 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
3486 tempfp
= ((t_uint64
)GetMap(MA
) << 48);
3487 tempfp
|= ((t_uint64
)GetMap(MA
+ 1) << 32);
3488 tempfp
|= ((t_uint64
)GetMap(MA
+ 2) << 16);
3489 tempfp
|= ((t_uint64
)GetMap(MA
+ 3));
3490 if ((tempfp
& 0x00ffffffffffffff) == 0)
3492 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3493 get_lf(&dfl
, &tempfp
); /* Place in working registers */
3494 get_lf(&dfl2
, &FPAC
[j
]);
3495 k
= mul_lf(&dfl2
, &dfl
); /* Multiply */
3499 FPSR
|= 0x40000000; /* OVF bit on */
3502 FPSR
|= 0x20000000; /* UNF bit on */
3506 store_lf(&dfl2
, &FPAC
[j
]); /* put result in destination */
3507 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3509 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3511 FPSR
|= 0x02000000; /* Set Z */
3512 if (FPAC
[j
] & 0x8000000000000000)
3513 FPSR
|= 0x01000000; /* Set N */
3514 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3515 FPSR
|= ((PC
- 1) & AMASK
);
3516 PC
= (PC
+ 1) & AMASK
;
3519 if ((IR
& 0103777) == 0100650) { /* FDS Div single by AC */
3520 if (!(fpu_unit
.flags
& UNIT_UP
))
3522 if (Debug_Flags
== 1) {
3523 printf("\n<<FPU instruction: FDS>>\n");
3524 reason
= STOP_IBKPT
;
3526 if (FPFault
) { /* Fault from a previous inst? */
3528 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3537 PutMap(t
, ((PC
-1) & AMASK
));
3538 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3540 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3545 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3546 get_sf(&sfl
, &FPAC
[i
]); /* Place in working registers */
3547 get_sf(&sfl2
, &FPAC
[j
]);
3548 k
= div_sf(&sfl2
, &sfl
); /* Divide */
3552 FPSR
|= 0x40000000; /* OVF bit on */
3555 FPSR
|= 0x20000000; /* UNF bit on */
3558 FPSR
|= 0x10000000; /* DVZ bit on */
3562 store_sf(&sfl2
, &FPAC
[j
]); /* put result in destination */
3563 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3565 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3567 FPSR
|= 0x02000000; /* Set Z */
3568 if (FPAC
[j
] & 0x8000000000000000)
3569 FPSR
|= 0x01000000; /* Set N */
3570 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3571 FPSR
|= ((PC
- 1) & AMASK
);
3574 if ((IR
& 0103777) == 0101650) { /* FDMS Div single by memory */
3575 if (!(fpu_unit
.flags
& UNIT_UP
))
3577 if (Debug_Flags
== 1) {
3578 printf("\n<<FPU instruction: FDMS>>\n");
3579 reason
= STOP_IBKPT
;
3581 if (FPFault
) { /* Fault from a previous inst? */
3583 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3592 PutMap(t
, ((PC
-1) & AMASK
));
3593 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3595 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3599 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
3600 tempfp
= ((t_uint64
)GetMap(MA
) << 48);
3601 tempfp
|= ((t_uint64
)GetMap(MA
+ 1) << 32);
3602 if ((tempfp
& 0x00ffffffffffffff) == 0)
3604 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3605 get_sf(&sfl
, &tempfp
); /* Place in working registers */
3606 get_sf(&sfl2
, &FPAC
[j
]);
3607 k
= div_sf(&sfl2
, &sfl
); /* Divide */
3611 FPSR
|= 0x40000000; /* OVF bit on */
3614 FPSR
|= 0x20000000; /* UNF bit on */
3617 FPSR
|= 0x10000000; /* DVZ bit on */
3621 store_sf(&sfl2
, &FPAC
[j
]); /* put result in destination */
3622 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3624 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3626 FPSR
|= 0x02000000; /* Set Z */
3627 if (FPAC
[j
] & 0x8000000000000000)
3628 FPSR
|= 0x01000000; /* Set N */
3629 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3630 FPSR
|= ((PC
- 1) & AMASK
);
3631 PC
= (PC
+ 1) & AMASK
;
3634 if ((IR
& 0103777) == 0100650) { /* FDD Div double by AC */
3635 if (!(fpu_unit
.flags
& UNIT_UP
))
3637 if (Debug_Flags
== 1) {
3638 printf("\n<<FPU instruction: FDD>>\n");
3639 reason
= STOP_IBKPT
;
3641 if (FPFault
) { /* Fault from a previous inst? */
3643 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3652 PutMap(t
, ((PC
-1) & AMASK
));
3653 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3655 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3660 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3661 get_lf(&dfl
, &FPAC
[i
]); /* Place in working registers */
3662 get_lf(&dfl2
, &FPAC
[j
]);
3663 k
= div_lf(&dfl2
, &dfl
); /* Divide */
3667 FPSR
|= 0x40000000; /* OVF bit on */
3670 FPSR
|= 0x20000000; /* UNF bit on */
3673 FPSR
|= 0x10000000; /* DVZ bit on */
3677 store_lf(&dfl2
, &FPAC
[j
]); /* put result in destination */
3678 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3680 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3682 FPSR
|= 0x02000000; /* Set Z */
3683 if (FPAC
[j
] & 0x8000000000000000)
3684 FPSR
|= 0x01000000; /* Set N */
3685 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3686 FPSR
|= ((PC
- 1) & AMASK
);
3689 if ((IR
& 0103777) == 0101650) { /* FDMD Div double by memory */
3690 if (!(fpu_unit
.flags
& UNIT_UP
))
3692 if (Debug_Flags
== 1) {
3693 printf("\n<<FPU instruction: FDMD>>\n");
3694 reason
= STOP_IBKPT
;
3696 if (FPFault
) { /* Fault from a previous inst? */
3698 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3707 PutMap(t
, ((PC
-1) & AMASK
));
3708 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3710 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3714 MA
= effective(PC
, (IR
>> 13) & 3, GetMap(PC
));
3715 tempfp
= ((t_uint64
)GetMap(MA
) << 48);
3716 tempfp
|= ((t_uint64
)GetMap(MA
+ 1) << 32);
3717 tempfp
|= ((t_uint64
)GetMap(MA
+ 2) << 16);
3718 tempfp
|= ((t_uint64
)GetMap(MA
+ 3));
3719 if ((tempfp
& 0x00ffffffffffffff) == 0)
3721 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3722 get_lf(&dfl
, &tempfp
); /* Place in working registers */
3723 get_lf(&dfl2
, &FPAC
[j
]);
3724 k
= div_lf(&dfl2
, &dfl
); /* Divide */
3728 FPSR
|= 0x40000000; /* OVF bit on */
3731 FPSR
|= 0x20000000; /* UNF bit on */
3734 FPSR
|= 0x10000000; /* DVZ bit on */
3738 store_lf(&dfl2
, &FPAC
[j
]); /* put result in destination */
3739 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3741 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3743 FPSR
|= 0x02000000; /* Set Z */
3744 if (FPAC
[j
] & 0x8000000000000000)
3745 FPSR
|= 0x01000000; /* Set N */
3746 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3747 FPSR
|= ((PC
- 1) & AMASK
);
3748 PC
= (PC
+ 1) & AMASK
;
3751 if ((IR
& 0163777) == 0163050) { /* FNEG Negate */
3752 if (!(fpu_unit
.flags
& UNIT_UP
))
3754 if (Debug_Flags
== 1) {
3755 printf("\n<<FPU instruction: FNEG>>\n");
3756 reason
= STOP_IBKPT
;
3758 if (FPFault
) { /* Fault from a previous inst? */
3760 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3769 PutMap(t
, ((PC
-1) & AMASK
));
3770 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3772 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3776 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3777 get_lf(&dfl
, &FPAC
[j
]);
3778 dfl
.sign
= ! (dfl
.sign
); /* invert sign */
3779 store_lf(&dfl
, &FPAC
[j
]); /* put result in destination */
3780 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3782 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3784 FPSR
|= 0x02000000; /* Set Z */
3785 if (FPAC
[j
] & 0x8000000000000000)
3786 FPSR
|= 0x01000000; /* Set N */
3787 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3788 FPSR
|= ((PC
- 1) & AMASK
);
3791 if ((IR
& 0163777) == 0143050) { /* FAB Absolute Value*/
3792 if (!(fpu_unit
.flags
& UNIT_UP
))
3794 if (Debug_Flags
== 1) {
3795 printf("\n<<FPU instruction: FAB>>\n");
3796 reason
= STOP_IBKPT
;
3798 if (FPFault
) { /* Fault from a previous inst? */
3800 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3809 PutMap(t
, ((PC
-1) & AMASK
));
3810 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3812 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3816 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3817 get_lf(&dfl
, &FPAC
[j
]);
3818 dfl
.sign
= 0; /* Force sign positive */
3819 store_lf(&dfl
, &FPAC
[j
]); /* put result in destination */
3820 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3822 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3824 FPSR
|= 0x02000000; /* Set Z */
3825 if (FPAC
[j
] & 0x8000000000000000)
3826 FPSR
|= 0x01000000; /* Set N */
3827 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3828 FPSR
|= ((PC
- 1) & AMASK
);
3831 if ((IR
& 0163777) == 0103050) { /* FNOM Normalize*/
3832 if (!(fpu_unit
.flags
& UNIT_UP
))
3834 if (Debug_Flags
== 1) {
3835 printf("\n<<FPU instruction: FNOM>>\n");
3836 reason
= STOP_IBKPT
;
3838 if (FPFault
) { /* Fault from a previous inst? */
3840 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3849 PutMap(t
, ((PC
-1) & AMASK
));
3850 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3852 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3856 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3857 get_lf(&dfl
, &FPAC
[j
]);
3858 k
= normal_lf(&dfl
); /* Normalize */
3859 if (k
== 2) /* Underflow ? */
3860 FPSR
|= 0x20000000; /* Set underflow on */
3861 store_lf(&dfl
, &FPAC
[j
]); /* put result in destination */
3862 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3864 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3866 FPSR
|= 0x02000000; /* Set Z */
3867 if (FPAC
[j
] & 0x8000000000000000)
3868 FPSR
|= 0x01000000; /* Set N */
3869 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3870 FPSR
|= ((PC
- 1) & AMASK
);
3873 if ((IR
& 0163777) == 0123050) { /* FRH Read High Word */
3874 if (!(fpu_unit
.flags
& UNIT_UP
))
3876 if (Debug_Flags
== 1) {
3877 printf("\n<<FPU instruction: FRH>>\n");
3878 reason
= STOP_IBKPT
;
3880 if (FPFault
) { /* Fault from a previous inst? */
3882 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3891 PutMap(t
, ((PC
-1) & AMASK
));
3892 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3894 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3898 AC
[0] = (int32
)(FPAC
[j
] >> 48) & 0xFFFF; /* No cond bits set, always to AC0 */
3899 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3900 FPSR
|= ((PC
- 1) & AMASK
);
3903 if ((IR
& 0163777) == 0123150) { /* FEXP Load Exponent */
3904 if (!(fpu_unit
.flags
& UNIT_UP
))
3906 if (Debug_Flags
== 1) {
3907 printf("\n<<FPU instruction: FEXP>>\n");
3908 reason
= STOP_IBKPT
;
3911 if (FPFault
) { /* Fault from a previous inst? */
3913 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3922 PutMap(t
, ((PC
-1) & AMASK
));
3923 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3925 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3929 i
= (AC
[0] >> 8) & 0x007F;
3930 FPAC
[j
] &= 0x80FFFFFFFFFFFFFF; /* clear exponent */
3931 FPAC
[j
] |= ((t_int64
) i
<< 56);
3932 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3935 FPSR
|= 0x02000000; /* Set Z */
3936 if (FPAC
[j
] & 0x8000000000000000)
3937 FPSR
|= 0x01000000; /* Set N */
3938 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3939 FPSR
|= ((PC
- 1) & AMASK
);
3942 if ((IR
& 0103777) == 0103450) { /* FCMP FP Compare */
3943 if (!(fpu_unit
.flags
& UNIT_UP
)) /* (Subtract double AC without storing result) */
3945 if (Debug_Flags
== 1) {
3946 printf("\n<<FPU instruction: FCMP>>\n");
3947 reason
= STOP_IBKPT
;
3949 if (FPFault
) { /* Fault from a previous inst? */
3951 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
3960 PutMap(t
, ((PC
-1) & AMASK
));
3961 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
3963 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
3968 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
3969 get_lf(&dfl
, &FPAC
[i
]); /* Place in working registers */
3970 get_lf(&dfl2
, &FPAC
[j
]);
3971 dfl
.sign
= ! (dfl
.sign
); /* invert sign of 2nd operand */
3972 k
= add_lf(&dfl2
, &dfl
, 1); /* Add the two */
3976 FPSR
|= 0x40000000; /* OVF bit on */
3979 FPSR
|= 0x20000000; /* UNF bit on */
3983 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
3985 FPSR
&= 0xFCFFFFFF; /* Z + N off */
3987 FPSR
|= 0x02000000; /* Set Z */
3988 if (FPAC
[j
] & 0x8000000000000000)
3989 FPSR
|= 0x01000000; /* Set N */
3990 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
3991 FPSR
|= ((PC
- 1) & AMASK
);
3994 if (IR
== 0163350) { /* FPSH Push State */
3995 if (!(fpu_unit
.flags
& UNIT_UP
))
3997 if (Debug_Flags
== 2) {
3998 printf("\n<<FPU instruction: FPSH>>\n");
3999 reason
= STOP_IBKPT
;
4001 /* Note: FPSH and FPOP do not trap on error */
4002 t
= (GetMap(040) + 1) & AMASK
; /* Get Stack Pointer */
4003 PutMap(t
, ((FPSR
>> 16) & 0xFFFF));
4005 PutMap(t
, (FPSR
& 0xFFFF));
4007 PutMap(t
, (int16
)((FPAC
[0] >> 48) & 0xFFFF));
4009 PutMap(t
, (int16
)((FPAC
[0] >> 32) & 0xFFFF));
4011 PutMap(t
, (int16
)((FPAC
[0] >> 16) & 0xFFFF));
4013 PutMap(t
, (int16
)(FPAC
[0] & 0xFFFF));
4015 PutMap(t
, (int16
)((FPAC
[1] >> 48) & 0xFFFF));
4017 PutMap(t
, (int16
)((FPAC
[1] >> 32) & 0xFFFF));
4019 PutMap(t
, (int16
)((FPAC
[1] >> 16) & 0xFFFF));
4021 PutMap(t
, (int16
)(FPAC
[1] & 0xFFFF));
4023 PutMap(t
, (int16
)((FPAC
[2] >> 48) & 0xFFFF));
4025 PutMap(t
, (int16
)((FPAC
[2] >> 32) & 0xFFFF));
4027 PutMap(t
, (int16
)((FPAC
[2] >> 16) & 0xFFFF));
4029 PutMap(t
, (int16
)(FPAC
[2] & 0xFFFF));
4031 PutMap(t
, (int16
)((FPAC
[3] >> 48) & 0xFFFF));
4033 PutMap(t
, (int16
)((FPAC
[3] >> 32) & 0xFFFF));
4035 PutMap(t
, (int16
)((FPAC
[3] >> 16) & 0xFFFF));
4037 PutMap(t
, (int16
)(FPAC
[3] & 0xFFFF));
4038 PutMap(040, t
); /* Update Stack Pointer */
4041 if (IR
== 0167350) { /* FPOP Pop State */
4042 if (!(fpu_unit
.flags
& UNIT_UP
))
4044 if (Debug_Flags
== 2) {
4045 printf("\n<<FPU instruction: FPOP>>\n");
4046 reason
= STOP_IBKPT
;
4048 /* Note: FPSH and FPOP do not trap on error */
4049 t
= GetMap(040) & AMASK
; /* Get Stack Pointer */
4050 FPAC
[3] = ((t_uint64
)GetMap(t
) & 0xFFFF);
4052 FPAC
[3] |= (((t_uint64
)GetMap(t
) << 16) & 0xFFFF0000);
4054 FPAC
[3] |= (((t_uint64
)GetMap(t
) << 32) & 0xFFFF00000000);
4056 FPAC
[3] |= (((t_uint64
)GetMap(t
) << 48) & 0xFFFF000000000000);
4058 FPAC
[2] = ((t_uint64
)GetMap(t
) & 0xFFFF);
4060 FPAC
[2] |= (((t_uint64
)GetMap(t
) << 16) & 0xFFFF0000);
4062 FPAC
[2] |= (((t_uint64
)GetMap(t
) << 32) & 0xFFFF00000000);
4064 FPAC
[2] |= (((t_uint64
)GetMap(t
) << 48) & 0xFFFF000000000000);
4066 FPAC
[1] = ((t_uint64
)GetMap(t
) & 0xFFFF);
4068 FPAC
[1] |= (((t_uint64
)GetMap(t
) << 16) & 0xFFFF0000);
4070 FPAC
[1] |= (((t_uint64
)GetMap(t
) << 32) & 0xFFFF00000000);
4072 FPAC
[1] |= (((t_uint64
)GetMap(t
) << 48) & 0xFFFF000000000000);
4074 FPAC
[0] = ((t_uint64
)GetMap(t
) & 0xFFFF);
4076 FPAC
[0] |= (((t_uint64
)GetMap(t
) << 16) & 0xFFFF0000);
4078 FPAC
[0] |= (((t_uint64
)GetMap(t
) << 32) & 0xFFFF00000000);
4080 FPAC
[0] |= (((t_uint64
)GetMap(t
) << 48) & 0xFFFF000000000000);
4082 FPSR
= (GetMap(t
) & 0xFFFF);
4084 FPSR
|= ((GetMap(t
) << 16) & 0xFFFF0000);
4086 PutMap(040, t
); /* Update Stack Pointer */
4089 if ((IR
& 0163777) == 0163150) { /* FHLV Halve */
4090 if (!(fpu_unit
.flags
& UNIT_UP
))
4092 if (Debug_Flags
== 1) {
4093 printf("\n<<FPU instruction: FHLV>>\n");
4094 reason
= STOP_IBKPT
;
4096 if (FPFault
) { /* Fault from a previous inst? */
4098 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4107 PutMap(t
, ((PC
-1) & AMASK
));
4108 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4110 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4114 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
4115 get_lf(&dfl
, &FPAC
[j
]);
4116 dfl
.long_fract
= dfl
.long_fract
>> 1; /* Shift right one bit */
4117 normal_lf(&dfl
); /* Normalize */
4118 store_lf(&dfl
, &FPAC
[j
]); /* put result in destination */
4119 if ((FPAC
[j
] & 0x00ffffffffffffff) == 0)
4121 FPSR
&= 0xFCFFFFFF; /* Z + N off */
4123 FPSR
|= 0x02000000; /* Set Z */
4124 if (FPAC
[j
] & 0x8000000000000000)
4125 FPSR
|= 0x01000000; /* Set N */
4126 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4127 FPSR
|= ((PC
- 1) & AMASK
);
4130 if ((IR
& 0163777) == 0103150) { /* FSCAL Scale */
4131 if (!(fpu_unit
.flags
& UNIT_UP
))
4133 if (Debug_Flags
== 1) {
4134 printf("\n<<FPU instruction: FSCAL>>\n");
4135 reason
= STOP_IBKPT
;
4137 if (FPFault
) { /* Fault from a previous inst? */
4139 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4148 PutMap(t
, ((PC
-1) & AMASK
));
4149 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4151 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4155 FPSR
&= 0xFCFFFFFF; /* Z+N bits off */
4156 j
= (AC
[0] >> 8) & 0x7F; /* expo of AC0 */
4157 k
= (int32
)(FPAC
[i
] >> 56) & 0x7F; /* expo of FPAC */
4158 tempfp
= FPAC
[i
] & 0x8000000000000000; /* save sign */
4160 if (t
> 0) { /* Positive shift */
4161 FPAC
[i
] &= 0x00FFFFFFFFFFFFFF;
4162 FPAC
[i
] = FPAC
[i
] >> (t
* 4);
4163 FPAC
[i
] &= 0x00FFFFFFFFFFFFFF; /* AC0 expo becomes expo */
4165 FPAC
[i
] |= (holdfp
<< 56);
4167 if (t
< 0) { /* Negative shift */
4168 FPAC
[i
] &= 0x00FFFFFFFFFFFFFF;
4169 FPAC
[i
] = FPAC
[i
] << ((0-t
) * 4);
4170 FPSR
|= 0x08000000; /* MOF bit on */
4171 FPAC
[i
] &= 0x00FFFFFFFFFFFFFF; /* AC0 expo becomes expo */
4173 FPAC
[i
] |= (holdfp
<< 56);
4175 if ((FPAC
[i
] & 0x00FFFFFFFFFFFFFF) != 0)
4176 FPAC
[i
] |= tempfp
; /* restore sign */
4177 if ((FPAC
[i
] & 0x80FFFFFFFFFFFFFF) == 0) {
4179 FPSR
|= 0x02000000; /* Set Z */
4181 if (FPAC
[i
] & 0x8000000000000000)
4182 FPSR
|= 0x01000000; /* Set N */
4183 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4184 FPSR
|= ((PC
- 1) & AMASK
);
4187 if (IR
== 0153350) { /* FCLE Clear Errors */
4188 if (!(fpu_unit
.flags
& UNIT_UP
))
4190 if (Debug_Flags
== 1) {
4191 printf("\n<<FPU instruction: FCLE>>\n");
4192 reason
= STOP_IBKPT
;
4194 if (FPFault
) { /* Fault from a previous inst? */
4196 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4205 PutMap(t
, ((PC
-1) & AMASK
));
4206 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4208 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4211 FPSR
&= 0x07FFFFFF; /* set off all error bits */
4212 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4213 FPSR
|= ((PC
- 1) & AMASK
);
4216 if (IR
== 0103250) { /* FNS No Skip */
4217 if (!(fpu_unit
.flags
& UNIT_UP
))
4219 if (Debug_Flags
== 1) {
4220 printf("\n<<FPU instruction: FNS>>\n");
4221 reason
= STOP_IBKPT
;
4223 if (FPFault
) { /* Fault from a previous inst? */
4225 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4234 PutMap(t
, ((PC
-1) & AMASK
));
4235 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4237 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4240 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4241 FPSR
|= ((PC
- 1) & AMASK
);
4244 if (IR
== 0107250) { /* FSA Always Skip */
4245 if (!(fpu_unit
.flags
& UNIT_UP
))
4247 if (Debug_Flags
== 2) {
4248 printf("\n<<FPU instruction: FSA>>\n");
4249 reason
= STOP_IBKPT
;
4251 if (FPFault
) { /* Fault from a previous inst? */
4253 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4262 PutMap(t
, ((PC
-1) & AMASK
));
4263 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4265 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4268 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4269 FPSR
|= ((PC
- 1) & AMASK
);
4270 PC
= (PC
+ 1) & AMASK
;
4273 if (IR
== 0137250) { /* FSGT */
4274 if (!(fpu_unit
.flags
& UNIT_UP
))
4276 if (Debug_Flags
== 1) {
4277 printf("\n<<FPU instruction: FSGT>>\n");
4278 reason
= STOP_IBKPT
;
4280 if (FPFault
) { /* Fault from a previous inst? */
4282 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4291 PutMap(t
, ((PC
-1) & AMASK
));
4292 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4294 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4297 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4298 FPSR
|= ((PC
- 1) & AMASK
);
4299 if (!(FPSR
& 0x03000000)) /* Z & N both 0? */
4300 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4303 if (IR
== 0123250) { /* FSLT */
4304 if (!(fpu_unit
.flags
& UNIT_UP
))
4306 if (Debug_Flags
== 1) {
4307 printf("\n<<FPU instruction: FSLT>>\n");
4308 reason
= STOP_IBKPT
;
4310 if (FPFault
) { /* Fault from a previous inst? */
4312 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4321 PutMap(t
, ((PC
-1) & AMASK
));
4322 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4324 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4327 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4328 FPSR
|= ((PC
- 1) & AMASK
);
4329 if (FPSR
& 0x01000000) /* N is on? */
4330 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4333 if (IR
== 0113250) { /* FSEQ */
4334 if (!(fpu_unit
.flags
& UNIT_UP
))
4336 if (Debug_Flags
== 1) {
4337 printf("\n<<FPU instruction: FSEQ>>\n");
4338 reason
= STOP_IBKPT
;
4340 if (FPFault
) { /* Fault from a previous inst? */
4342 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4351 PutMap(t
, ((PC
-1) & AMASK
));
4352 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4354 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4357 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4358 FPSR
|= ((PC
- 1) & AMASK
);
4359 if (FPSR
& 0x02000000) /* Z is on? */
4360 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4363 if (IR
== 0133250) { /* FSLE */
4364 if (!(fpu_unit
.flags
& UNIT_UP
))
4366 if (Debug_Flags
== 1) {
4367 printf("\n<<FPU instruction: FSLE>>\n");
4368 reason
= STOP_IBKPT
;
4370 if (FPFault
) { /* Fault from a previous inst? */
4372 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4381 PutMap(t
, ((PC
-1) & AMASK
));
4382 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4384 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4387 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4388 FPSR
|= ((PC
- 1) & AMASK
);
4389 if (FPSR
& 0x03000000) /* Z or N on? */
4390 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4393 if (IR
== 0127250) { /* FSGE */
4394 if (!(fpu_unit
.flags
& UNIT_UP
))
4396 if (Debug_Flags
== 1) {
4397 printf("\n<<FPU instruction: FSGE>>\n");
4398 reason
= STOP_IBKPT
;
4400 if (FPFault
) { /* Fault from a previous inst? */
4402 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4411 PutMap(t
, ((PC
-1) & AMASK
));
4412 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4414 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4417 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4418 FPSR
|= ((PC
- 1) & AMASK
);
4419 if (!(FPSR
& 0x01000000)) /* N is off? */
4420 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4423 if (IR
== 0117250) { /* FSNE */
4424 if (!(fpu_unit
.flags
& UNIT_UP
))
4426 if (Debug_Flags
== 1) {
4427 printf("\n<<FPU instruction: FSNE>>\n");
4430 if (FPFault
) { /* Fault from a previous inst? */
4432 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4441 PutMap(t
, ((PC
-1) & AMASK
));
4442 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4444 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4447 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4448 FPSR
|= ((PC
- 1) & AMASK
);
4449 if (!(FPSR
& 0x02000000)) /* Z is off? */
4450 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4453 if (IR
== 0143250) { /* FSNM */
4454 if (!(fpu_unit
.flags
& UNIT_UP
))
4456 if (Debug_Flags
== 1) {
4457 printf("\n<<FPU instruction: FSNM>>\n");
4458 reason
= STOP_IBKPT
;
4460 if (FPFault
) { /* Fault from a previous inst? */
4462 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4471 PutMap(t
, ((PC
-1) & AMASK
));
4472 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4474 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4477 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4478 FPSR
|= ((PC
- 1) & AMASK
);
4479 if (!(FPSR
& 0x08000000)) /* MOF is off? */
4480 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4483 if (IR
== 0153250) { /* FSNU */
4484 if (!(fpu_unit
.flags
& UNIT_UP
))
4486 if (Debug_Flags
== 1) {
4487 printf("\n<<FPU instruction: FSNU>>\n");
4488 reason
= STOP_IBKPT
;
4490 if (FPFault
) { /* Fault from a previous inst? */
4492 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4501 PutMap(t
, ((PC
-1) & AMASK
));
4502 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4504 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4507 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4508 FPSR
|= ((PC
- 1) & AMASK
);
4509 if (!(FPSR
& 0x20000000)) /* UNF is off? */
4510 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4513 if (IR
== 0163250) { /* FSNO */
4514 if (!(fpu_unit
.flags
& UNIT_UP
))
4516 if (Debug_Flags
== 1) {
4517 printf("\n<<FPU instruction: FSNO>>\n");
4518 reason
= STOP_IBKPT
;
4520 if (FPFault
) { /* Fault from a previous inst? */
4522 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4531 PutMap(t
, ((PC
-1) & AMASK
));
4532 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4534 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4537 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4538 FPSR
|= ((PC
- 1) & AMASK
);
4539 if (!(FPSR
& 0x40000000)) /* OVF is off? */
4540 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4543 if (IR
== 0147250) { /* FSND */
4544 if (!(fpu_unit
.flags
& UNIT_UP
))
4546 if (Debug_Flags
== 1) {
4547 printf("\n<<FPU instruction: FSND>>\n");
4548 reason
= STOP_IBKPT
;
4550 if (FPFault
) { /* Fault from a previous inst? */
4552 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4561 PutMap(t
, ((PC
-1) & AMASK
));
4562 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4564 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4567 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4568 FPSR
|= ((PC
- 1) & AMASK
);
4569 if (!(FPSR
& 0x10000000)) /* DVZ is off? */
4570 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4573 if (IR
== 0157250) { /* FSNUD */
4574 if (!(fpu_unit
.flags
& UNIT_UP
))
4576 if (Debug_Flags
== 1) {
4577 printf("\n<<FPU instruction: FSNUD>>\n");
4578 reason
= STOP_IBKPT
;
4580 if (FPFault
) { /* Fault from a previous inst? */
4582 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4591 PutMap(t
, ((PC
-1) & AMASK
));
4592 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4594 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4597 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4598 FPSR
|= ((PC
- 1) & AMASK
);
4599 if (!(FPSR
& 0x30000000)) /* UNF & DVZ off? */
4600 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4603 if (IR
== 0167250) { /* FSNOD */
4604 if (!(fpu_unit
.flags
& UNIT_UP
))
4606 if (Debug_Flags
== 1) {
4607 printf("\n<<FPU instruction: FSNOD>>\n");
4608 reason
= STOP_IBKPT
;
4610 if (FPFault
) { /* Fault from a previous inst? */
4612 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4621 PutMap(t
, ((PC
-1) & AMASK
));
4622 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4624 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4627 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4628 FPSR
|= ((PC
- 1) & AMASK
);
4629 if (!(FPSR
& 0x50000000)) /* OVF & DVZ off? */
4630 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4633 if (IR
== 0173250) { /* FSNUO */
4634 if (!(fpu_unit
.flags
& UNIT_UP
))
4636 if (Debug_Flags
== 1) {
4637 printf("\n<<FPU instruction: FSNUO>>\n");
4638 reason
= STOP_IBKPT
;
4640 if (FPFault
) { /* Fault from a previous inst? */
4642 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4651 PutMap(t
, ((PC
-1) & AMASK
));
4652 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4654 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4657 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4658 FPSR
|= ((PC
- 1) & AMASK
);
4659 if (!(FPSR
& 0x60000000)) /* OVF & UNF off? */
4660 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4663 if (IR
== 0177250) { /* FSNER */
4664 if (!(fpu_unit
.flags
& UNIT_UP
))
4666 if (Debug_Flags
== 1) {
4667 printf("\n<<FPU instruction: FSNER>>\n");
4668 reason
= STOP_IBKPT
;
4670 if (FPFault
) { /* Fault from a previous inst? */
4672 t
= (GetMap(040) + 1) & AMASK
; /* Yes: push rtn block */
4681 PutMap(t
, ((PC
-1) & AMASK
));
4682 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
4684 PC
= indirect(GetMap(045)); /* JMP indirect to 45 */
4687 FPSR
&= 0xFFFF0000; /* Success: put addr in FPSR */
4688 FPSR
|= ((PC
- 1) & AMASK
);
4689 if (!(FPSR
& 0x78000000)) /* all errors off? */
4690 PC
= (PC
+ 1) & AMASK
; /* yep: skip */
4695 printf("\n<<Unexecuted inst = %o at PC=%o>>\n\r", IR
, PC
-1);
4696 if (Debug_Flags
& 040000) reason
= STOP_IBKPT
;
4700 if (IR
== 061777) { /* VCT: Vector on Interrupt */
4701 int32 stkchg
, vtable
;
4702 int32 ventry
, dctadr
;
4703 int32 old40
, old41
, old42
, old43
;
4705 /* Ok, folks, this is one helluva instruction */
4707 stkchg
= GetMap(PC
) & 0100000; /* Save stack change bit */
4708 vtable
= GetMap(PC
) & AMASK
; /* Address of vector table */
4711 int_req
= (int_req
& ~INT_DEV
) | /* Do an INTA w/o an accum */
4712 (dev_done
& ~dev_disable
);
4713 iodata
= int_req
& (-int_req
);
4714 for (i
= DEV_LOW
; i
<= DEV_HIGH
; i
++) {
4715 if (iodata
& dev_table
[i
].mask
) {
4721 ventry
= GetMap(vtable
+ iodev
); /* Get Vector Entry */
4723 if (!(ventry
& 0100000)) { /* Direct bit = 0? */
4724 PC
= ventry
& AMASK
; /* YES - Mode A, so JMP */
4728 dctadr
= ventry
& AMASK
; /* Get address of DCT entry */
4730 if (stkchg
) { /* Stack change bit = 1? */
4731 old40
= GetMap(040); /* Save stack info */
4732 old41
= GetMap(041);
4733 old42
= GetMap(042);
4734 old43
= GetMap(043);
4735 PutMap(040, GetMap(004)); /* Loc 4 to stack ptr */
4736 PutMap(042, GetMap(006)); /* Loc 6 to stack limit */
4737 PutMap(043, GetMap(007)); /* Loc 7 into stack limit */
4738 PutMap(040, (GetMap(040) + 1)); /* Push old contents on new stk */
4739 PutMap(GetMap(040) & AMASK
, old40
);
4740 PutMap(040, (GetMap(040) + 1));
4741 PutMap(GetMap(040) & AMASK
, old41
);
4742 PutMap(040, (GetMap(040) + 1));
4743 PutMap(GetMap(040) & AMASK
, old42
);
4744 PutMap(040, (GetMap(040) + 1));
4745 PutMap(GetMap(040) & AMASK
, old43
);
4748 t
= GetMap(dctadr
& AMASK
); /* Get word 0 of DCT */
4750 if (t
& 0100000) { /* Push bit set ? */
4751 PutMap(040, (GetMap(040) + 1)); /* Push "Standard rtn block" */
4752 PutMap(GetMap(040) & AMASK
, AC
[0]);
4753 PutMap(040, (GetMap(040) + 1));
4754 PutMap(GetMap(040) & AMASK
, AC
[1]);
4755 PutMap(040, (GetMap(040) + 1));
4756 PutMap(GetMap(040) & AMASK
, AC
[2]);
4757 PutMap(040, (GetMap(040) + 1));
4758 PutMap(GetMap(040) & AMASK
, AC
[3]);
4759 PutMap(040, (GetMap(040) + 1));
4760 PutMap(GetMap(040) & AMASK
, GetMap(0));
4761 if (GetMap(0) == 0 && Debug_Flags
) {
4762 printf("\n<<VCT will rtn to 0 @ %o>>\n\r", PC
);
4763 reason
= STOP_IBKPT
;
4765 if (C
) PutMap(GetMap(040) & AMASK
, (GetMap(GetMap(040) & AMASK
) | 0100000));
4768 AC
[2] = dctadr
& AMASK
; /* DCT Addr into AC2 */
4770 PutMap(040, (GetMap(040) + 1)); /* Push pri int mask onto stack */
4771 PutMap(GetMap(040) & AMASK
, pimask
);
4773 AC
[0] = GetMap(dctadr
+ 1) | pimask
; /* Build new mask from word 1 of dct */
4776 mask_out(pimask
= AC
[0]); /* Do a mask out inst */
4778 PC
= GetMap(dctadr
) & AMASK
; /* Finally, JMP to int routine */
4783 /*************************************************************************
4784 ** At this point, the instruction is not an Eclipse one. Therefore **
4785 ** decode it as a Nova instruction just like the Nova does. **
4786 *************************************************************************/
4788 /* Memory reference instructions */
4790 if (t
< 014) { /* mem ref? */
4791 register int32 src
, MA
;
4794 switch ((IR
>> 8) & 03) { /* decode IR<6:7> */
4795 case 0: /* page zero */
4797 case 1: /* PC relative */
4798 if (MA
& 0200) MA
= 077400 | MA
;
4799 MA
= (MA
+ PC
- 1) & AMASK
;
4801 case 2: /* AC2 relative */
4802 if (MA
& 0200) MA
= 077400 | MA
;
4803 MA
= (MA
+ AC
[2]) & AMASK
;
4805 case 3: /* AC3 relative */
4806 if (MA
& 0200) MA
= 077400 | MA
;
4807 MA
= (MA
+ AC
[3]) & AMASK
;
4810 if (IR
& 002000) { /* indirect? */
4811 for (i
= 0; i
< (ind_max
* 2); i
++) { /* count indirects */
4812 if ((MA
& 077770) == 020 && !(cpu_unit
.flags
& UNIT_MICRO
))
4813 MA
= (PutMap(MA
& AMASK
, (GetMap(MA
& AMASK
) + 1) & 0177777));
4814 else if ((MA
& 077770) == 030 && !(cpu_unit
.flags
& UNIT_MICRO
))
4815 MA
= (PutMap(MA
& AMASK
, (GetMap(MA
& AMASK
) - 1) & 0177777));
4816 else MA
= GetMap(MA
& AMASK
);
4817 if (MapStat
& 1) { /* Start MAP */
4821 if ((MA
& 0100000) == 0) break;
4822 if (i
>= ind_max
&& (MapStat
& 010) && Usermap
) break;
4824 if (i
>= (ind_max
-1)) {
4825 if ((MapStat
& 010) && Usermap
) {
4826 Fault
= 04000; /* Map fault if IND prot */
4829 if (i
>= (ind_max
* 2) && !(Fault
)) {
4836 switch (t
) { /* decode IR<1:4> */
4844 src
= (GetMap(MA
) + 1) & 0177777;
4845 if (MEM_ADDR_OK (MA
)) PutMap(MA
, src
);
4846 if (src
== 0) PC
= (PC
+ 1) & AMASK
;
4849 src
= (GetMap(MA
) - 1) & 0177777;
4850 if (MEM_ADDR_OK (MA
)) PutMap(MA
, src
);
4851 if (src
== 0) PC
= (PC
+ 1) & AMASK
;
4853 case 004: /* LDA 0 */
4854 if (SingleCycle
) Usermap
= SingleCycle
;
4857 Usermap
= SingleCycle
= 0;
4858 if (Inhibit
== 1) Inhibit
= 3;
4863 case 005: /* LDA 1 */
4864 if (SingleCycle
) Usermap
= SingleCycle
;
4867 Usermap
= SingleCycle
= 0;
4868 if (Inhibit
== 1) Inhibit
= 3;
4873 case 006: /* LDA 2 */
4874 if (SingleCycle
) Usermap
= SingleCycle
;
4877 Usermap
= SingleCycle
= 0;
4878 if (Inhibit
== 1) Inhibit
= 3;
4883 case 007: /* LDA 3 */
4884 if (SingleCycle
) Usermap
= SingleCycle
;
4887 Usermap
= SingleCycle
= 0;
4888 if (Inhibit
== 1) Inhibit
= 3;
4893 case 010: /* STA 0 */
4895 Usermap
= SingleCycle
;
4896 if (MEM_ADDR_OK (MA
)) PutMap(MA
, AC
[0]);
4898 Usermap
= SingleCycle
= 0;
4899 if (Inhibit
== 1) Inhibit
= 3;
4904 case 011: /* STA 1 */
4906 Usermap
= SingleCycle
;
4907 if (MEM_ADDR_OK (MA
)) PutMap(MA
, AC
[1]);
4909 Usermap
= SingleCycle
= 0;
4910 if (Inhibit
== 1) Inhibit
= 3;
4915 case 012: /* STA 2 */
4917 Usermap
= SingleCycle
;
4918 if (MEM_ADDR_OK (MA
)) PutMap(MA
, AC
[2]);
4920 Usermap
= SingleCycle
= 0;
4921 if (Inhibit
== 1) Inhibit
= 3;
4926 case 013: /* STA 3 */
4928 Usermap
= SingleCycle
;
4929 if (MEM_ADDR_OK (MA
)) PutMap(MA
, AC
[3]);
4931 Usermap
= SingleCycle
= 0;
4932 if (Inhibit
== 1) Inhibit
= 3;
4940 /* Operate instruction */
4942 else if (t
& 020) { /* operate? */
4943 register int32 src
, srcAC
, dstAC
;
4945 srcAC
= (t
>> 2) & 3; /* get reg decodes */
4947 switch ((IR
>> 4) & 03) { /* decode IR<10:11> */
4949 src
= AC
[srcAC
] | C
;
4955 src
= AC
[srcAC
] | 0200000;
4957 case 3: /* complement */
4958 src
= AC
[srcAC
] | (C
^ 0200000);
4960 } /* end switch carry */
4962 switch ((IR
>> 8) & 07) { /* decode IR<5:7> */
4964 src
= src
^ 0177777;
4967 src
= ((src
^ 0177777) + 1) & 0377777;
4972 src
= (src
+ 1) & 0377777;
4975 src
= ((src
^ 0177777) + AC
[dstAC
]) & 0377777;
4978 src
= ((src
^ 0177777) + AC
[dstAC
] + 1) & 0377777;
4981 src
= (src
+ AC
[dstAC
]) & 0377777;
4984 src
= src
& (AC
[dstAC
] | 0200000);
4986 } /* end switch oper */
4988 switch ((IR
>> 6) & 03) { /* decode IR<8:9> */
4992 src
= ((src
<< 1) | (src
>> 16)) & 0377777;
4995 src
= ((src
>> 1) | (src
<< 16)) & 0377777;
4998 src
= ((src
& 0377) << 8) | ((src
>> 8) & 0377) |
5001 } /* end switch shift */
5003 switch (IR
& 07) { /* decode IR<13:15> */
5007 PC
= (PC
+ 1) & AMASK
;
5010 if (src
< 0200000) PC
= (PC
+ 1) & AMASK
;
5013 if (src
>= 0200000) PC
= (PC
+ 1) & AMASK
;
5016 if ((src
& 0177777) == 0) PC
= (PC
+ 1) & AMASK
;
5019 if ((src
& 0177777) != 0) PC
= (PC
+ 1) & AMASK
;
5022 if (src
<= 0200000) PC
= (PC
+ 1) & AMASK
;
5025 if (src
> 0200000) PC
= (PC
+ 1) & AMASK
;
5027 } /* end switch skip */
5028 if ((IR
& 000010) == 0) { /* load? */
5029 AC
[dstAC
] = src
& 0177777;
5032 } /* end if operate */
5034 /* IOT instruction */
5037 register int32 dstAC
, pulse
, code
, device
, iodata
;
5040 if ((MapStat
& 0100) /* LEF mode bit on? */
5041 && Usermap
) { /* We are in LEF Mode */
5042 AC
[(IR
>> 11) & 3] = LEFmode(PC
- 1, (IR
>> 8) & 3, IR
& 0377, IR
& 02000);
5043 if (Debug_Flags
& 020000) {
5044 printf("\n\r<<LEF Break by special request - executed at %o.>>\n\r", PC
-1);
5045 reason
= STOP_IBKPT
;
5050 dstAC
= t
& 03; /* decode fields */
5051 if ((MapStat
& 040) && Usermap
) { /* I/O protection fault */
5055 code
= (IR
>> 8) & 07;
5056 pulse
= (IR
>> 6) & 03;
5058 if (Debug_Flags
&& device
== 0) {
5059 printf("\n\r<<I/O to device 00 at %o.>>\n\r", PC
-1);
5060 reason
= STOP_IBKPT
;
5063 if ((Debug_Flags
& 0100) && (device
== (Debug_Flags
& 077))) {
5064 printf("\n\r<<I/O Break (device %o) >>\n\r", device
);
5065 reason
= STOP_IBKPT
;
5068 if ((Debug_Char
!= 0) && (device
== 011) &&
5069 ((AC
[dstAC
] & 0177) == Debug_Char
)) {
5070 printf("\n\r<<I/O Break (Char %o to TTO) >>\n\r", Debug_Char
);
5071 reason
= STOP_IBKPT
;
5074 if (code
== ioSKP
) { /* IO skip? */
5075 switch (pulse
) { /* decode IR<8:9> */
5076 case 0: /* skip if busy */
5077 if ((device
== 077)? (int_req
& INT_ION
) != 0:
5078 (dev_busy
& dev_table
[device
].mask
) != 0)
5079 PC
= (PC
+ 1) & AMASK
;
5081 case 1: /* skip if not busy */
5082 if ((device
== 077)? (int_req
& INT_ION
) == 0:
5083 (dev_busy
& dev_table
[device
].mask
) == 0)
5084 PC
= (PC
+ 1) & AMASK
;
5086 case 2: /* skip if done */
5087 if ((device
== 077)? pwr_low
!= 0:
5088 (dev_done
& dev_table
[device
].mask
) != 0)
5089 PC
= (PC
+ 1) & AMASK
;
5091 case 3: /* skip if not done */
5092 if ((device
== 077)? pwr_low
== 0:
5093 (dev_done
& dev_table
[device
].mask
) == 0)
5094 PC
= (PC
+ 1) & AMASK
;
5099 else if (device
== DEV_CPU
) { /* CPU control */
5100 switch (code
) { /* decode IR<5:7> */
5101 case ioNIO
: /* Get CPU ID */
5103 case 280: /* S280 */
5107 AC
[0] = 013212; /* C380 */
5112 break; /* Otherwise no-op */
5113 case ioDIA
: /* read switches */
5116 case ioDIB
: /* int ack */
5118 int_req
= (int_req
& ~INT_DEV
) |
5119 (dev_done
& ~dev_disable
);
5120 iodata
= int_req
& (-int_req
);
5121 for (i
= DEV_LOW
; i
<= DEV_HIGH
; i
++) {
5122 if (iodata
& dev_table
[i
].mask
) {
5128 case ioDOB
: /* mask out */
5129 mask_out (pimask
= AC
[dstAC
]);
5131 case ioDIC
: /* io reset IORST */
5132 reset_all (0); /* reset devices */
5133 Usermap
= 0; /* reset MAP */
5134 MapStat
&= 04; /* Reset MAP status */
5138 Check
= SingleCycle
= 0;
5143 case ioDOC
: /* halt */
5146 } /* end switch code */
5148 switch (pulse
) { /* decode IR<8:9> */
5149 case iopS
: /* ion */
5150 int_req
= (int_req
| INT_ION
) & ~INT_NO_ION_PENDING
;
5152 case iopC
: /* iof */
5153 int_req
= int_req
& ~INT_ION
;
5154 break; } /* end switch pulse */
5155 } /* end CPU control */
5157 else if (device
== DEV_ECC
) {
5159 case ioDIA
: /* Read Fault Address */
5162 case ioDIB
: /* Read fault code */
5165 case ioDOA
: /* Enable ERCC */
5169 else if (device
== DEV_MAP
) { /* MAP control */
5170 switch (code
) { /* decode IR<5:7> */
5171 case ioNIO
: /* No I/O -- Single */
5172 if (!Usermap
|| !(MapStat
& 0140)) {
5173 if ((Debug_Flags
& 077) == 03)
5174 fprintf(Trace
, "%o NIO %o (No I/O, clear faults)\n", PC
-1, dstAC
);
5175 MapStat
&= ~036000; /* NIO Clears all faults */
5177 if ((Debug_Flags
& 077) == 03)
5178 fprintf(Trace
, "%o NIO %o (No I/O, clear faults) NO EXEC(User mode)\n", PC
-1, dstAC
);
5181 case ioDIA
: /* Read map status */
5182 if (!Usermap
|| !(MapStat
& 0140)) {
5183 if ((Debug_Flags
& 077) == 03)
5184 fprintf(Trace
, "%o DIA %o=%o (Read Map Status)\n", PC
-1, dstAC
, MapStat
);
5185 AC
[dstAC
] = MapStat
& 0xFFFE;
5186 if (MapIntMode
& 1) /* Bit 15 is mode asof last int */
5189 if ((Debug_Flags
& 077) == 03)
5190 fprintf(Trace
, "%o DIA %o=%o (Read Map Status) NO EXEC(User mode)\n", PC
-1, dstAC
, MapStat
);
5193 case ioDOA
: /* Load map status */
5194 if (!Usermap
|| !(MapStat
& 0140)) {
5195 if ((Debug_Flags
& 077) == 03)
5196 fprintf(Trace
, "%o DOA %o=%o (Load Map Status)\n", PC
-1, dstAC
, AC
[dstAC
]);
5197 MapStat
= AC
[dstAC
];
5200 if (MapStat
& 04) Enable
= 2;
5202 Check
|= MapStat
& 01600;
5204 Inhibit
= 2; /* Inhibit interrupts */
5206 if ((Debug_Flags
& 077) == 03)
5207 fprintf(Trace
, "%o DOA %o=%o (Load Map Status) NO EXEC(User mode)\n", PC
-1, dstAC
, AC
[dstAC
]);
5210 case ioDIB
: /* not used */
5212 case ioDOB
: /* map block 31 */
5213 //AOS if (!Usermap || !(MapStat && 0140)) {
5214 if ((Debug_Flags
& 077) == 03)
5215 fprintf(Trace
, "%o DOB %o=%o (Map Blk 31)\n", PC
-1, dstAC
, AC
[dstAC
]);
5216 Map31
= AC
[dstAC
] & PAGEMASK
;
5219 //AOS if ((Debug_Flags & 077) == 03)
5220 //AOS fprintf(Trace, "%o DOB %o=%o (Map Blk 31) NO EXEC (User Mode)\n", PC-1, dstAC, AC[dstAC]);
5223 case ioDIC
: /* Page Check */
5224 if (!Usermap
|| !(MapStat
& 0140)) {
5225 switch ((Check
>>7) & 07) {
5236 j
= (Check
>> 10) & 037;
5237 AC
[dstAC
] = Map
[i
][j
] & 0101777;
5238 AC
[dstAC
] |= ((Check
<< 5) & 070000);
5239 if ((Debug_Flags
& 077) == 03)
5240 fprintf(Trace
, "%o DIC %o=%o (Page Check)\n", PC
-1, dstAC
, AC
[dstAC
]);
5243 if ((Debug_Flags
& 077) == 03)
5244 fprintf(Trace
, "%o DIC %o=%o (Page Check) NO EXEC(User mode)\n", PC
-1, dstAC
, AC
[dstAC
]);
5247 case ioDOC
: /* Init Page Check */
5248 if (!Usermap
|| !(MapStat
& 0140)) {
5249 if ((Debug_Flags
& 077) == 03)
5250 fprintf(Trace
, "%o DOC %o=%o (Init Pg Chk)\n", PC
-1, dstAC
, AC
[dstAC
]);
5253 MapStat
|= (Check
& 01600);
5256 if ((Debug_Flags
& 077) == 03)
5257 fprintf(Trace
, "%o DOC %o=%o (Init Pg Chk) NO EXEC(User mode)\n", PC
-1, dstAC
, AC
[dstAC
]);
5260 } /* end switch code */
5264 if ((Debug_Flags
& 077) == 03)
5265 fprintf(Trace
, "%o xxxP (Single Cycle)\n", PC
-1);
5271 SingleCycle
= Enable
;
5272 Inhibit
= 1; /* Inhibit interrupts */
5276 } /* end CPU control */
5277 else if (dev_table
[device
].routine
) { /* normal device */
5278 iodata
= dev_table
[device
].routine (pulse
, code
, AC
[dstAC
]);
5279 reason
= iodata
>> IOT_V_REASON
;
5280 if (code
& 1) AC
[dstAC
] = iodata
& 0177777;
5281 if ((Debug_Flags
& 077) == device
&& Debug_Flags
!= 0) {
5282 strcpy(pulcode
, "");
5285 strcpy(pulcode
, "P");
5288 strcpy(pulcode
, "S");
5291 strcpy(pulcode
, "C");
5298 fprintf(Trace
, "[%o] %o NIO%s %o\n", device
, PC
-1, pulcode
, AC
[dstAC
]);
5301 fprintf(Trace
, "[%o] %o DIA%s %o\n", device
, PC
-1, pulcode
, iodata
);
5304 fprintf(Trace
, "[%o] %o DIB%s %o\n", device
, PC
-1, pulcode
, iodata
);
5307 fprintf(Trace
, "[%o] %o DIC%s %o\n", device
, PC
-1, pulcode
, iodata
);
5310 fprintf(Trace
, "[%o] %o DOA%s %o\n", device
, PC
-1, pulcode
, AC
[dstAC
]);
5313 fprintf(Trace
, "[%o] %o DOB%s %o\n", device
, PC
-1, pulcode
, AC
[dstAC
]);
5316 fprintf(Trace
, "[%o] %o DOC%s %o\n", device
, PC
-1, pulcode
, AC
[dstAC
]);
5321 } /* end if debug */
5323 else reason
= stop_dev
;
5327 /* Simulation halted */
5333 /* Computes and returns a 16-bit effective address, given a
5334 program counter, index, and a displacement.
5337 int32
effective(int32 PC
, int32 index
, int32 disp
)
5339 register int32 i
, MA
;
5342 switch (index
) { /* decode IR<6:7> */
5343 case 0: /* page zero */
5345 case 1: /* PC relative */
5346 MA
= (MA
+ PC
) & AMASK
;
5348 case 2: /* AC2 relative */
5349 MA
= (MA
+ AC
[2]) & AMASK
;
5351 case 3: /* AC3 relative */
5352 MA
= (MA
+ AC
[3]) & AMASK
;
5354 } /* end switch mode */
5356 if (disp
& 0100000) { /* indirect? */
5357 for (i
= 0; i
< ind_max
* 2; i
++) { /* count indirects */
5358 MA
= GetMap(MA
& AMASK
);
5359 if (SingleCycle
) Usermap
= 0;
5360 if (MapStat
& 1) { /* Start MAP */
5364 if ((MA
& 0100000) == 0) break;
5365 if ((MapStat
& 010) && Usermap
&& i
>= ind_max
) break;
5367 if (i
>= (ind_max
-1) && (MapStat
& 010) && Usermap
) {
5368 Fault
= 04000; /* Map fault if IND prot */
5370 if (i
>= (ind_max
* 2) && !(Fault
)) {
5371 reason
= STOP_IND_INT
; /* Stop machine */
5374 return (MA
& AMASK
);
5377 /* Computes and returns a 16-bit effective address, given a
5378 program counter, index, and a displacement. This is a
5379 version supporting the LEF map mode instruction, as
5380 opposed to the ELEF instruction.
5383 int32
LEFmode(int32 PC
, int32 index
, int32 disp
, int32 indirect
)
5385 register int32 i
, MA
;
5389 switch (index
) { /* decode IR<6:7> */
5390 case 0: /* page zero */
5392 case 1: /* PC relative */
5394 if (MA
& 0200) sMA
|= 0xff00;
5395 MA
= (sMA
+ PC
) & AMASK
;
5397 case 2: /* AC2 relative */
5399 if (MA
& 0200) sMA
|= 0xff00;
5400 MA
= (sMA
+ AC
[2]) & AMASK
;
5402 case 3: /* AC3 relative */
5404 if (MA
& 0200) sMA
|= 0xff00;
5405 MA
= (sMA
+ AC
[3]) & AMASK
;
5407 } /* end switch mode */
5409 if (indirect
) { /* indirect? */
5410 for (i
= 0; i
< (ind_max
* 2); i
++) { /* count indirects */
5411 if ((MA
& 077770) == 020 && !(cpu_unit
.flags
& UNIT_MICRO
))
5412 MA
= (PutMap(MA
& AMASK
, (GetMap(MA
& AMASK
) + 1) & 0177777));
5413 else if ((MA
& 077770) == 030 && !(cpu_unit
.flags
& UNIT_MICRO
))
5414 MA
= (PutMap(MA
& AMASK
, (GetMap(MA
& AMASK
) - 1) & 0177777));
5415 else MA
= GetMap(MA
& AMASK
);
5416 if (SingleCycle
) Usermap
= 0;
5417 if (MapStat
& 1) { /* Start MAP */
5421 if ((MA
& 0100000) == 0) break;
5422 if ((MapStat
& 010) && Usermap
&& i
>= ind_max
) break;
5424 if (i
>= (ind_max
-1) && (MapStat
& 010) && Usermap
) {
5425 Fault
= 04000; /* Map fault if IND prot */
5427 if (i
>= (ind_max
* 2) && !(Fault
)) {
5428 reason
= STOP_IND_INT
; /* Stop machine */
5431 return (MA
& AMASK
);
5434 /* Computes a "Byte pointer" for the Character Instruction set */
5435 /* This address in 'PC' must point to the displacement word of the instruction */
5437 int32
Bytepointer(int32 PC
, int32 index
)
5441 switch (index
) { /* decode IR<6:7> */
5442 case 0: /* page zero */
5445 case 1: /* PC relative */
5448 case 2: /* AC2 relative */
5451 case 3: /* AC3 relative */
5454 } /* end switch mode */
5455 MA
= (MA
* 2) & 0177777;
5456 MA
= MA
+ GetMap(PC
);
5457 return (MA
& 0177777);
5460 /* Given an address, returns either that address if bit 0 is 0, or
5461 or follows an indirection chain until bit 0 is 0
5464 int32
indirect(int32 d
)
5468 if (d
& 0100000) { /* indirect? */
5469 for (i
= 0; i
< ind_max
* 2; i
++) { /* count indirects */
5470 if ((d
& 077770) == 020 && !(cpu_unit
.flags
& UNIT_MICRO
))
5471 d
= (PutMap(d
& AMASK
, ((GetMap(d
& AMASK
) + 1) & 0177777)));
5472 else if ((d
& 077770) == 030 && !(cpu_unit
.flags
& UNIT_MICRO
))
5473 d
= (PutMap(d
& AMASK
, ((GetMap(d
& AMASK
) - 1) & 0177777)));
5474 else d
= GetMap(d
& AMASK
);
5475 if (MapStat
& 1) { /* Start MAP */
5479 if ((d
& 0100000) == 0) break;
5480 if ((MapStat
& 010) && Usermap
&& i
>= ind_max
) break;
5482 if (i
>= (ind_max
-1) && (MapStat
& 010) && Usermap
) {
5483 Fault
= 04000; /* Map fault if IND prot */
5485 if (i
>= (ind_max
* 2) && !(Fault
)) {
5486 reason
= STOP_IND
; /* Stop machine */
5492 /* Push a standard return block onto the stack */
5494 int32
pushrtn(int32 pc
)
5498 t
= (GetMap(040) + 1) & AMASK
;
5508 if (C
) PutMap(t
, (GetMap(t
) | 0100000));
5513 /* Eclipse memory get/put - uses MAP if enabled */
5515 int32
GetMap(int32 addr
)
5524 paddr
= ((Map31
& PAGEMASK
) << 10) | (addr
& 001777);
5525 if (paddr
< MEMSIZE
)
5531 page
= (addr
>> 10) & 037;
5532 paddr
= ((Map
[1][page
] & 01777) << 10) | (addr
& 001777);
5533 if (Map
[1][page
] == INVALID
&& !SingleCycle
)
5534 Fault
= 0100000/*!!!*/; /* Validity */
5535 if (paddr
< MEMSIZE
)
5541 page
= (addr
>> 10) & 037;
5542 paddr
= ((Map
[2][page
] & PAGEMASK
) << 10) | (addr
& 001777);
5543 if (Map
[2][page
] == INVALID
&& !SingleCycle
)
5544 Fault
= 0100000/*!!!*/; /* Validity */
5545 if (paddr
< MEMSIZE
)
5551 page
= (addr
>> 10) & 037;
5552 paddr
= ((Map
[6][page
] & PAGEMASK
) << 10) | (addr
& 001777);
5553 if (Map
[6][page
] == INVALID
&& !SingleCycle
)
5554 Fault
= 0100000/*!!!*/; /* Validity */
5555 if (paddr
< MEMSIZE
)
5561 page
= (addr
>> 10) & 037;
5562 paddr
= ((Map
[7][page
] & PAGEMASK
) << 10) | (addr
& 001777);
5563 if (Map
[7][page
] == INVALID
&& !SingleCycle
)
5564 Fault
= 0100000/*!!!*/; /* Validity */
5565 if (paddr
< MEMSIZE
)
5571 printf("\n\r<<MAP FAULT>>\n\r");
5577 int32
PutMap(int32 addr
, int32 data
)
5584 if (addr
< 076000) {
5588 paddr
= ((Map31
& PAGEMASK
) << 10) | (addr
& 001777);
5589 if (paddr
< MEMSIZE
) M
[paddr
] = data
;
5592 page
= (addr
>> 10) & 037;
5593 paddr
= ((Map
[1][page
] & PAGEMASK
) << 10) | (addr
& 001777);
5594 if (((Map
[1][page
] & 0100000) && (MapStat
& 020)) || Map
[1][page
] == INVALID
)
5595 Fault
= 010000; /* Write Protect Fault */
5596 else if (paddr
< MEMSIZE
) M
[paddr
] = data
;
5599 page
= (addr
>> 10) & 037;
5600 paddr
= ((Map
[2][page
] & PAGEMASK
) << 10) | (addr
& 001777);
5601 if (((Map
[2][page
] & 0100000) && (MapStat
& 020)) || Map
[2][page
] == INVALID
)
5602 Fault
= 010000; /* Write Protect Fault */
5603 else if (paddr
< MEMSIZE
) M
[paddr
] = data
;
5606 page
= (addr
>> 10) & 037;
5607 paddr
= ((Map
[2][page
] & PAGEMASK
) << 10) | (addr
& 001777);
5608 if (((Map
[6][page
] & 0100000) && (MapStat
& 020)) || Map
[6][page
] == INVALID
)
5609 Fault
= 010000; /* Write Protect Fault */
5610 else if (paddr
< MEMSIZE
) M
[paddr
] = data
;
5613 page
= (addr
>> 10) & 037;
5614 paddr
= ((Map
[2][page
] & PAGEMASK
) << 10) | (addr
& 001777);
5615 if (((Map
[7][page
] & 0100000) && (MapStat
& 020)) || Map
[7][page
] == INVALID
)
5616 Fault
= 010000; /* Write Protect Fault */
5617 else if (paddr
< MEMSIZE
) M
[paddr
] = data
;
5627 int16
GetDCHMap(int32 map
, int32 addr
)
5630 if (!(MapStat
& 02)) return M
[addr
];
5631 paddr
= ((Map
[map
][(addr
>> 10) & 037] & PAGEMASK
) << 10) | (addr
& 001777);
5632 if (paddr
< MEMSIZE
)
5637 int16
PutDCHMap(int32 map
, int32 addr
, int16 data
)
5640 if (!(MapStat
& 02)) {
5644 paddr
= ((Map
[map
][(addr
>> 10) & 037] & PAGEMASK
) << 10) | (addr
& 001777);
5645 if (paddr
< MEMSIZE
)
5651 /* Given a map number and a logical, returns the physical address, unless
5652 the map is not active, in which case logical = physical. This is
5653 used primarily by the I/O routines to map data channel read/writes.
5656 int32
MapAddr(int32 map
, int32 addr
)
5659 if ((map
== 0 || map
> 2) && !(MapStat
& 02)) return addr
;
5660 if (map
> 0 && map
< 3 && Usermap
== 0) return addr
;
5661 paddr
= ((Map
[map
][(addr
>> 10) & 037] & PAGEMASK
) << 10) | (addr
& 001777);
5665 /* Loads a word into the Eclipse Maps */
5667 int32
LoadMap(int32 w
)
5671 m
= (w
>> 10) & 037;
5672 switch ((MapStat
>> 7) & 07) {
5673 case 0: /* Load user A Map */
5674 Map
[1][m
] = w
& MAPMASK
;
5676 case 1: /* Load user C Map */
5677 Map
[6][m
] = w
& MAPMASK
;
5679 case 2: /* Load user B Map */
5680 Map
[2][m
] = w
& MAPMASK
;
5682 case 3: /* Load user D Map */
5683 Map
[7][m
] = w
& MAPMASK
;
5685 case 4: /* Load DCH A Map */
5686 Map
[0][m
] = w
& MAPMASK
;
5688 case 5: /* Load DCH C Map */
5691 case 6: /* Load DCH B Map */
5694 case 7: /* Load DCH D Map */
5703 /* Displays an error on a unimplemented (in this sim) instr. */
5705 int32
unimp(int32 PC
)
5708 printf("\n\r\007<<<Unimplemented instruction: [%o] %o>>>\n\r", PC
- 1, GetMap(PC
- 1));
5712 /* New priority mask out */
5714 void mask_out (int32 newmask
)
5719 for (i
= DEV_LOW
; i
<= DEV_HIGH
; i
++) {
5720 if (newmask
& dev_table
[i
].pi
)
5721 dev_disable
= dev_disable
| dev_table
[i
].mask
;
5723 int_req
= (int_req
& ~INT_DEV
) | (dev_done
& ~dev_disable
);
5729 t_stat
cpu_reset (DEVICE
*dptr
)
5731 int_req
= int_req
& ~INT_ION
;
5735 sim_brk_types
= sim_brk_dflt
= SWMASK ('E');
5739 /* Memory examine */
5741 t_stat
cpu_ex (t_value
*vptr
, t_addr addr
, UNIT
*uptr
, int32 sw
)
5743 if (sw
& SWMASK ('V')) {
5744 if (addr
> 077777) return SCPE_NXM
;
5745 if (vptr
!= NULL
) *vptr
= GetMap (addr
);
5748 if (addr
>= MEMSIZE
) return SCPE_NXM
;
5749 if (vptr
!= NULL
) *vptr
= M
[addr
] & 0177777;
5754 /* Memory deposit */
5756 t_stat
cpu_dep (t_value val
, t_addr addr
, UNIT
*uptr
, int32 sw
)
5758 if (sw
& SWMASK ('V')) {
5759 if (addr
> 077777) return SCPE_NXM
;
5760 PutMap (addr
, (int32
) val
);
5763 if (addr
>= MEMSIZE
) return SCPE_NXM
;
5764 M
[addr
] = (int32
) val
& 0177777;
5769 /* Alter memory size */
5771 t_stat
cpu_set_size (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
5776 if ((val
<= 0) || (val
> MAXMEMSIZE
) || ((val
& 07777) != 0))
5778 for (i
= val
; i
< MEMSIZE
; i
++) mc
= mc
| M
[i
];
5779 if ((mc
!= 0) && (!get_yn ("Really truncate memory [N]?", FALSE
)))
5782 for (i
= MEMSIZE
; i
< MAXMEMSIZE
; i
++) M
[i
] = 0;
5786 /* MAP device services */
5788 t_stat
map_svc (UNIT
*uptr
)
5795 t_stat
map_ex (t_value
*vptr
, t_addr addr
, UNIT
*uptr
, int32 sw
)
5797 if ((addr
& 077) >= 037 || addr
> 737) return SCPE_NXM
;
5798 uptr
->u4
= -2; /* signal to print_sys in eclipse_sys.c: do not map */
5799 if (vptr
!= NULL
) *vptr
= Map
[(addr
>> 6) & 3][addr
& 037] & 0177777;
5803 /* Memory deposit */
5805 t_stat
map_dep (t_value val
, t_addr addr
, UNIT
*uptr
, int32 sw
)
5807 if ((addr
& 077) >= 037 || addr
> 0737) return SCPE_NXM
;
5808 uptr
->u4
= -2; /* signal to print_sys in eclipse_sys.c: do not map */
5809 Map
[(addr
>> 6) & 3][addr
& 037] = (int32
)val
& 0177777;
5813 /* FPU device services */
5815 t_stat
fpu_svc (UNIT
*uptr
)
5820 /* PIT Device Services */
5824 int32
pit (int32 pulse
, int32 code
, int32 AC
)
5828 if (code
== ioDIA
) { /* DIA */
5829 if (pit_flag
== 0) {
5832 iodata
= pit_counter
;
5834 if (code
== ioDOA
) { /* DOA */
5835 pit_initial
= AC
; /* Load Counter */
5836 sim_rtcn_init (pit_time
, 1); /* init calibr */
5838 switch (pulse
) { /* decode IR<8:9> */
5839 case iopS
: /* start */
5840 pit_counter
= pit_initial
; /* Set the counter */
5841 dev_busy
= dev_busy
| INT_PIT
; /* set busy */
5842 dev_done
= dev_done
& ~INT_PIT
; /* clear done, int */
5843 int_req
= int_req
& ~INT_PIT
;
5844 if (!sim_is_active (&pit_unit
)) /* not running? */
5845 sim_activate (&pit_unit
, /* activate */
5846 sim_rtcn_init (pit_time
, 1)); /* init calibr */
5848 case iopC
: /* clear */
5849 dev_busy
= dev_busy
& ~INT_PIT
; /* clear busy */
5850 dev_done
= dev_done
& ~INT_PIT
; /* clear done, int */
5851 int_req
= int_req
& ~INT_PIT
;
5852 sim_cancel (&pit_unit
); /* deactivate unit */
5853 break; } /* end switch */
5859 t_stat
pit_svc (UNIT
*uptr
)
5862 t
= sim_rtcn_calb (pit_tps
, 1); /* calibrate delay */
5863 sim_activate (&pit_unit
, t
); /* reactivate unit */
5864 pit_poll
= t
/ (-pit_adj
); /* adjust poll */
5865 pit_counter
++; /* Increment counter */
5866 if (pit_counter
>= 0177777) { /* Has counter reached limit ? */
5867 dev_done
= dev_done
| INT_PIT
; /* set done */
5868 dev_busy
= dev_busy
& ~INT_PIT
; /* clear busy */
5869 int_req
= (int_req
& ~INT_DEV
) | (dev_done
& ~dev_disable
); /* Interrupt */
5870 pit_counter
= pit_initial
;
5877 t_stat
pit_reset (DEVICE
*dptr
)
5879 pit_counter
= 0; /* clear counter */
5880 dev_busy
= dev_busy
& ~INT_PIT
; /* clear busy */
5881 dev_done
= dev_done
& ~INT_PIT
; /* clear done, int */
5882 int_req
= int_req
& ~INT_PIT
;
5883 sim_cancel (&pit_unit
); /* deactivate unit */
5884 pit_poll
= pit_time
; /* poll is default */
5888 /* Bootstrap routine for CPU */
5890 #define BOOT_START 00000
5891 #define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
5893 static const int32 boot_rom
[] = {
5895 062677, /* IORST ;Reset all I/O */
5896 060477, /* READS 0 ;Read SR into AC0 */
5897 024026, /* LDA 1,C77 ;Get dev mask */
5898 0107400, /* AND 0,1 ;Isolate dev code */
5899 0124000, /* COM 1,1 ;- device code - 1 */
5900 010014, /* LOOP: ISZ OP1 ;Device code to all */
5901 010030, /* ISZ OP2 ;I/O instructions */
5902 010032, /* ISZ OP3 */
5903 0125404, /* INC 1,1,SZR ;done? */
5904 000005, /* JMP LOOP ;No, increment again */
5905 030016, /* LDA 2,C377 ;place JMP 377 into */
5906 050377, /* STA 2,377 ;location 377 */
5907 060077, /* OP1: 060077 ;start device (NIOS 0) */
5908 0101102, /* MOVL 0,0,SZC ;Test switch 0, low speed? */
5909 000377, /* C377: JMP 377 ;no - jmp 377 & wait */
5910 004030, /* LOOP2: JSR GET+1 ;Get a frame */
5911 0101065, /* MOVC 0,0,SNR ;is it non-zero? */
5912 000017, /* JMP LOOP2 ;no, ignore */
5913 004027, /* LOOP4: JSR GET ;yes, get full word */
5914 046026, /* STA 1,@C77 ;store starting at 100 */
5915 /* ;2's complement of word ct */
5916 010100, /* ISZ 100 ;done? */
5917 000022, /* JMP LOOP4 ;no, get another */
5918 000077, /* C77: JMP 77 ;yes location ctr and */
5919 /* ;jmp to last word */
5920 0126420, /* GET: SUBZ 1,1 ; clr AC1, set carry */
5922 063577, /* LOOP3: 063577 ;done? (SKPDN 0) - 1 */
5923 000030, /* JMP LOOP3 ;no -- wait */
5924 060477, /* OP3: 060477 ;y--read in ac0 (DIAS 0,0) */
5925 0107363, /* ADDCS 0,1,SNC ;add 2 frames swapped - got 2nd? */
5926 000030, /* JMP LOOP3 ;no go back after it */
5927 0125300, /* MOVS 1,1 ;yes swap them */
5928 001400, /* JMP 0,3 ;rtn with full word */
5932 t_stat
cpu_boot (int32 unitno
, DEVICE
*dptr
)
5935 extern int32 saved_PC
;
5937 for (i
= 0; i
< BOOT_LEN
; i
++) M
[BOOT_START
+ i
] = boot_rom
[i
];
5938 saved_PC
= BOOT_START
;
5942 int32
Debug_Entry(int32 PC
, int32 inst
, int32 inst2
, int32 AC0
, int32 AC1
, int32 AC2
, int32 AC3
, int32 flags
)
5944 hpc
[hnext
] = PC
& 0xffff;
5945 hinst
[hnext
] = inst
& 0xffff;
5946 hinst2
[hnext
] = inst2
& 0xffff;
5947 hac0
[hnext
] = AC0
& 0xffff;
5948 hac1
[hnext
] = AC1
& 0xffff;
5949 hac2
[hnext
] = AC2
& 0xffff;
5950 hac3
[hnext
] = AC3
& 0xffff;
5951 hflags
[hnext
] = flags
& 0xffff;
5953 if (hnext
>= hmax
) {
5960 int32
Debug_Dump(UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
5965 int32
Dump_History (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
5967 char debmap
[4], debion
[4];
5968 t_value simeval
[20];
5970 int start
, end
, ctr
;
5973 if (!Debug_Flags
|| Debug_Flags
& 0100000) {
5974 printf("History was not logged. Deposit a non-zero value\n");
5975 printf("in DEBUG with bit 0 being 1 to build history.\n");
5984 if (end
< 0) end
= hmax
;
5991 strcpy(debion
, " ");
5992 strcpy(debmap
, " ");
5994 if (hflags
[ctr
] & 0x80) {
5995 fprintf(st
, "--------- Interrupt %o (%o) to %6o ---------\n",
5996 hinst
[ctr
], hac0
[ctr
], hac1
[ctr
]);
5998 if (hflags
[ctr
] & 0x01) debcar
= 1;
5999 if (hflags
[ctr
] & 0x02) strcpy(debion
, "I");
6000 if (hflags
[ctr
] & 0x04) strcpy(debmap
, "A");
6001 if (hflags
[ctr
] & 0x08) strcpy(debmap
, "B");
6002 if (hflags
[ctr
] & 0x10) strcpy(debmap
, "C");
6003 if (hflags
[ctr
] & 0x20) strcpy(debmap
, "D");
6004 fprintf(st
, "%s%s%06o acs: %06o %06o %06o %06o %01o ",
6005 debion
, debmap
, hpc
[ctr
], hac0
[ctr
], hac1
[ctr
], hac2
[ctr
],
6007 simeval
[0] = hinst
[ctr
];
6008 simeval
[1] = hinst2
[ctr
];
6009 fprint_sym (st
, hpc
[ctr
], simeval
, NULL
, SWMASK('M'));
6019 /* Build dispatch table */
6021 t_stat
build_devtab (void)
6027 for (i
= 0; i
< 64; i
++) { /* clr dev_table */
6028 dev_table
[i
].mask
= 0;
6029 dev_table
[i
].pi
= 0;
6030 dev_table
[i
].routine
= NULL
;
6032 for (i
= 0; (dptr
= sim_devices
[i
]) != NULL
; i
++) { /* loop thru dev */
6033 if (!(dptr
->flags
& DEV_DIS
) && /* enabled and */
6034 (dibp
= (DIB
*) dptr
->ctxt
)) { /* defined DIB? */
6035 dn
= dibp
->dnum
; /* get dev num */
6036 dev_table
[dn
].mask
= dibp
->mask
; /* copy entries */
6037 dev_table
[dn
].pi
= dibp
->pi
;
6038 dev_table
[dn
].routine
= dibp
->routine
;
6044 /* ------------------------------------------------------------------- */
6045 /* Floating Point Arithmetic */
6046 /* ------------------------------------------------------------------- */
6049 /* Get short float from FPAC */
6051 void get_sf (SHORT_FLOAT
*fl
, t_int64
*fpr
)
6053 fl
->sign
= (uint8
)(*fpr
>> 63) & 1;
6054 fl
->expo
= (short)(*fpr
>> 56) & 0x007F;
6055 fl
->short_fract
= (int32
)(*fpr
>> 32) & 0x00FFFFFF;
6058 /* Store short float to FPAC */
6060 void store_sf (SHORT_FLOAT
*fl
, t_int64
*fpr
)
6063 *fpr
= ((t_int64
)fl
->sign
<< 63)
6064 | ((t_int64
)fl
->expo
<< 56)
6065 | ((t_int64
)fl
->short_fract
<<32);
6068 /* Get long float from FPAC */
6070 void get_lf (LONG_FLOAT
*fl
, t_int64
*fpr
)
6072 fl
->sign
= (uint8
)(*fpr
>> 63) & 1;
6073 fl
->expo
= (short)(*fpr
>> 56) & 0x007F;
6074 fl
->long_fract
= (t_int64
)*fpr
& 0x00FFFFFFFFFFFFFF;
6078 /* Store long float to FPAC */
6080 void store_lf (LONG_FLOAT
*fl
, t_int64
*fpr
)
6083 *fpr
= (t_int64
)fl
->sign
<< 63;
6084 *fpr
|= ((t_int64
)fl
->expo
<< 56) & 0x7f00000000000000;
6085 *fpr
|= fl
->long_fract
;
6089 /* Check short for Overflow */
6091 int overflow_sf (SHORT_FLOAT
*fl
)
6093 if (fl
->expo
> 127) {
6101 /* Normalize Short Float */
6103 int normal_sf(SHORT_FLOAT
*fl
)
6105 if (fl
->short_fract
) {
6106 if ((fl
->short_fract
& 0x00FFFF00) == 0) {
6107 fl
->short_fract
<<= 16;
6110 if ((fl
->short_fract
& 0x00FF0000) == 0) {
6111 fl
->short_fract
<<= 8;
6114 if ((fl
->short_fract
& 0x00F00000) == 0) {
6115 fl
->short_fract
<<= 4;
6127 /* Normalize long float */
6129 int normal_lf (LONG_FLOAT
*fl
)
6131 if (fl
->long_fract
) {
6132 if ((fl
->long_fract
& 0x00FFFFFFFF000000) == 0) {
6133 fl
->long_fract
<<= 32;
6136 if ((fl
->long_fract
& 0x00FFFF0000000000) == 0) {
6137 fl
->long_fract
<<= 16;
6140 if ((fl
->long_fract
& 0x00FF000000000000) == 0) {
6141 fl
->long_fract
<<= 8;
6144 if ((fl
->long_fract
& 0x00F0000000000000) == 0) {
6145 fl
->long_fract
<<= 4;
6157 /* Check Long for Overflow */
6159 int overflow_lf(LONG_FLOAT
*fl
)
6161 if (fl
->expo
> 127) {
6169 int underflow_sf(SHORT_FLOAT
*fl
)
6172 fl
->short_fract
= 0;
6181 int underflow_lf(LONG_FLOAT
*fl
)
6191 /* Check Short for Over/Under flow */
6193 int over_under_flow_sf(SHORT_FLOAT
*fl
)
6195 if (fl
->expo
> 127) {
6201 fl
->short_fract
= 0;
6210 /* Check Long for Over/Under flow */
6212 int over_under_flow_lf(LONG_FLOAT
*fl
)
6214 if (fl
->expo
> 127) {
6229 int significance_sf (SHORT_FLOAT
*fl
)
6237 int significance_lf (LONG_FLOAT
*fl
)
6246 /*-------------------------------------------------------------------*/
6247 /* Add short float */
6251 /* add_fl Float to be added */
6252 /* normal Normalize if true */
6255 /*-------------------------------------------------------------------*/
6256 int add_sf (SHORT_FLOAT
*fl
, SHORT_FLOAT
*add_fl
, int normal
)
6262 if (add_fl
->short_fract
6263 || add_fl
->expo
) { /* add_fl not 0 */
6265 || fl
->expo
) { /* fl not 0 */
6268 if (fl
->expo
== add_fl
->expo
) {
6271 /* both guard digits */
6272 fl
->short_fract
<<= 4;
6273 add_fl
->short_fract
<<= 4;
6275 /* expo not equal, denormalize */
6277 if (fl
->expo
< add_fl
->expo
) {
6278 /* shift minus guard digit */
6279 shift
= add_fl
->expo
- fl
->expo
- 1;
6280 fl
->expo
= add_fl
->expo
;
6284 || ((fl
->short_fract
>>= (shift
* 4)) == 0)) {
6285 /* 0, copy summand */
6287 fl
->sign
= add_fl
->sign
;
6288 fl
->short_fract
= add_fl
->short_fract
;
6290 if (fl
->short_fract
== 0) {
6291 pgm_check
= significance_sf(fl
);
6295 pgm_check
= underflow_sf(fl
);
6302 add_fl
->short_fract
<<= 4;
6304 /* shift minus guard digit */
6305 shift
= fl
->expo
- add_fl
->expo
- 1;
6309 || ((add_fl
->short_fract
>>= (shift
* 4)) == 0)) {
6310 /* 0, nothing to add */
6312 if (fl
->short_fract
== 0) {
6313 pgm_check
= significance_sf(fl
);
6317 pgm_check
= underflow_sf(fl
);
6324 fl
->short_fract
<<= 4;
6328 /* compute with guard digit */
6329 if (fl
->sign
== add_fl
->sign
) {
6330 fl
->short_fract
+= add_fl
->short_fract
;
6332 if (fl
->short_fract
== add_fl
->short_fract
) {
6335 fl
->short_fract
= 0;
6336 return( significance_sf(fl
) );
6338 } else if (fl
->short_fract
> add_fl
->short_fract
) {
6339 fl
->short_fract
-= add_fl
->short_fract
;
6341 fl
->short_fract
= add_fl
->short_fract
- fl
->short_fract
;
6342 fl
->sign
= add_fl
->sign
;
6346 /* handle overflow with guard digit */
6347 if (fl
->short_fract
& 0xF0000000) {
6348 fl
->short_fract
>>= 8;
6350 pgm_check
= overflow_sf(fl
);
6354 /* normalize with guard digit */
6355 if (fl
->short_fract
) {
6358 if (fl
->short_fract
& 0x0F000000) {
6359 /* not normalize, just guard digit */
6360 fl
->short_fract
>>= 4;
6364 pgm_check
= underflow_sf(fl
);
6369 pgm_check
= significance_sf(fl
);
6372 /* not normalize, just guard digit */
6373 fl
->short_fract
>>= 4;
6374 if (fl
->short_fract
== 0) {
6375 pgm_check
= significance_sf(fl
);
6380 } else { /* fl 0, add_fl not 0 */
6383 fl
->expo
= add_fl
->expo
;
6384 fl
->sign
= add_fl
->sign
;
6385 fl
->short_fract
= add_fl
->short_fract
;
6386 if (fl
->short_fract
== 0) {
6387 return( significance_sf(fl
) );
6390 } else { /* add_fl 0 */
6391 if (fl
->short_fract
== 0) { /* fl 0 */
6394 return( significance_sf(fl
) );
6399 pgm_check
= underflow_sf(fl
);
6406 /*-------------------------------------------------------------------*/
6407 /* Add long float */
6411 /* add_fl Float to be added */
6412 /* normal Normalize if true */
6415 /*-------------------------------------------------------------------*/
6416 int add_lf (LONG_FLOAT
*fl
, LONG_FLOAT
*add_fl
, int normal
)
6422 if (add_fl
->long_fract
6423 || add_fl
->expo
) { /* add_fl not 0 */
6425 || fl
->expo
) { /* fl not 0 */
6428 if (fl
->expo
== add_fl
->expo
) {
6431 /* both guard digits */
6432 fl
->long_fract
<<= 4;
6433 add_fl
->long_fract
<<= 4;
6435 /* expo not equal, denormalize */
6437 if (fl
->expo
< add_fl
->expo
) {
6438 /* shift minus guard digit */
6439 shift
= add_fl
->expo
- fl
->expo
- 1;
6440 fl
->expo
= add_fl
->expo
;
6444 || ((fl
->long_fract
>>= (shift
* 4)) == 0)) {
6445 /* 0, copy summand */
6447 fl
->sign
= add_fl
->sign
;
6448 fl
->long_fract
= add_fl
->long_fract
;
6450 if (fl
->long_fract
== 0) {
6451 pgm_check
= significance_lf(fl
);
6455 pgm_check
= underflow_lf(fl
);
6462 add_fl
->long_fract
<<= 4;
6464 /* shift minus guard digit */
6465 shift
= fl
->expo
- add_fl
->expo
- 1;
6469 || ((add_fl
->long_fract
>>= (shift
* 4)) == 0)) {
6470 /* 0, nothing to add */
6472 if (fl
->long_fract
== 0) {
6473 pgm_check
= significance_lf(fl
);
6477 pgm_check
= underflow_lf(fl
);
6484 fl
->long_fract
<<= 4;
6488 /* compute with guard digit */
6489 if (fl
->sign
== add_fl
->sign
) {
6490 fl
->long_fract
+= add_fl
->long_fract
;
6492 if (fl
->long_fract
== add_fl
->long_fract
) {
6496 return( significance_lf(fl
) );
6498 } else if (fl
->long_fract
> add_fl
->long_fract
) {
6499 fl
->long_fract
-= add_fl
->long_fract
;
6501 fl
->long_fract
= add_fl
->long_fract
- fl
->long_fract
;
6502 fl
->sign
= add_fl
->sign
;
6506 /* handle overflow with guard digit */
6507 if (fl
->long_fract
& 0xF000000000000000) {
6508 fl
->long_fract
>>= 8;
6510 pgm_check
= overflow_lf(fl
);
6514 /* normalize with guard digit */
6515 if (fl
->long_fract
) {
6518 if (fl
->long_fract
& 0x0F00000000000000) {
6519 /* not normalize, just guard digit */
6520 fl
->long_fract
>>= 4;
6524 pgm_check
= underflow_lf(fl
);
6529 pgm_check
= significance_lf(fl
);
6532 /* not normalize, just guard digit */
6533 fl
->long_fract
>>= 4;
6534 if (fl
->long_fract
== 0) {
6535 pgm_check
= significance_lf(fl
);
6540 } else { /* fl 0, add_fl not 0 */
6543 fl
->expo
= add_fl
->expo
;
6544 fl
->sign
= add_fl
->sign
;
6545 fl
->long_fract
= add_fl
->long_fract
;
6546 if (fl
->long_fract
== 0) {
6547 return( significance_lf(fl
) );
6550 } else { /* add_fl 0 */
6551 if (fl
->long_fract
== 0) { /* fl 0 */
6554 return( significance_lf(fl
) );
6559 pgm_check
= underflow_lf(fl
);
6565 /*-------------------------------------------------------------------*/
6566 /* Multiply short float */
6569 /* fl Multiplicand short float */
6570 /* mul_fl Multiplicator short float */
6573 /*-------------------------------------------------------------------*/
6575 int mul_sf(SHORT_FLOAT
*fl
, SHORT_FLOAT
*mul_fl
)
6580 && mul_fl
->short_fract
) {
6581 /* normalize operands */
6583 normal_sf( mul_fl
);
6585 /* multiply fracts */
6586 wk
= (t_int64
) fl
->short_fract
* mul_fl
->short_fract
;
6588 /* normalize result and compute expo */
6589 if (wk
& 0x0000F00000000000) {
6590 fl
->short_fract
= (int32
)wk
>> 24;
6591 fl
->expo
= (short)fl
->expo
+ mul_fl
->expo
- 64;
6593 fl
->short_fract
= (int32
)wk
>> 20;
6594 fl
->expo
= (short)fl
->expo
+ mul_fl
->expo
- 65;
6597 /* determine sign */
6598 fl
->sign
= (fl
->sign
== mul_fl
->sign
) ? 0 : 1;
6600 /* handle overflow and underflow */
6601 return( over_under_flow_sf(fl
) );
6605 fl
->short_fract
= 0;
6614 /*-------------------------------------------------------------------*/
6615 /* Multiply long float */
6618 /* fl Multiplicand long float */
6619 /* mul_fl Multiplicator long float */
6622 /*-------------------------------------------------------------------*/
6623 int mul_lf(LONG_FLOAT
*fl
, LONG_FLOAT
*mul_fl
)
6629 && mul_fl
->long_fract
) {
6630 /* normalize operands */
6632 normal_lf( mul_fl
);
6634 /* multiply fracts by sum of partial multiplications */
6635 wk
= ((fl
->long_fract
& 0x00000000FFFFFFFF) * (mul_fl
->long_fract
& 0x00000000FFFFFFFF)) >> 32;
6637 wk
+= ((fl
->long_fract
& 0x00000000FFFFFFFF) * (mul_fl
->long_fract
>> 32));
6638 wk
+= ((fl
->long_fract
>> 32) * (mul_fl
->long_fract
& 0x00000000FFFFFFFF));
6641 fl
->long_fract
= (wk
>> 32) + ((fl
->long_fract
>> 32) * (mul_fl
->long_fract
>> 32));
6643 /* normalize result and compute expo */
6644 if (fl
->long_fract
& 0x0000F00000000000) {
6645 fl
->long_fract
= (fl
->long_fract
<< 8)
6647 fl
->expo
= fl
->expo
+ mul_fl
->expo
- 64;
6649 fl
->long_fract
= (fl
->long_fract
<< 12)
6651 fl
->expo
= fl
->expo
+ mul_fl
->expo
- 65;
6654 /* determine sign */
6655 fl
->sign
= (fl
->sign
== mul_fl
->sign
) ? 0 : 1;
6657 /* handle overflow and underflow */
6658 return( over_under_flow_lf(fl
) );
6671 /*-------------------------------------------------------------------*/
6672 /* Divide short float */
6675 /* fl Dividend short float */
6676 /* div_fl Divisor short float */
6679 /*-------------------------------------------------------------------*/
6680 int div_sf(SHORT_FLOAT
*fl
, SHORT_FLOAT
*div_fl
)
6684 if (div_fl
->short_fract
) {
6685 if (fl
->short_fract
) {
6686 /* normalize operands */
6688 normal_sf( div_fl
);
6690 /* position fracts and compute expo */
6691 if (fl
->short_fract
< div_fl
->short_fract
) {
6692 wk
= (t_int64
) fl
->short_fract
<< 24;
6693 fl
->expo
= fl
->expo
- div_fl
->expo
+ 64;
6695 wk
= (t_int64
) fl
->short_fract
<< 20;
6696 fl
->expo
= fl
->expo
- div_fl
->expo
+ 65;
6698 /* divide fractions */
6699 fl
->short_fract
= (int32
)wk
/ div_fl
->short_fract
;
6701 /* determine sign */
6702 fl
->sign
= (fl
->sign
== div_fl
->sign
) ? 0 : 1;
6704 /* handle overflow and underflow */
6705 return( over_under_flow_sf(fl
) );
6707 /* fraction of dividend 0, set true 0 */
6709 fl
->short_fract
= 0;
6723 /*-------------------------------------------------------------------*/
6724 /* Divide long float */
6727 /* fl Dividend long float */
6728 /* div_fl Divisor long float */
6731 /*-------------------------------------------------------------------*/
6732 int div_lf(LONG_FLOAT
*fl
, LONG_FLOAT
*div_fl
)
6738 if (div_fl
->long_fract
) {
6739 if (fl
->long_fract
) {
6740 /* normalize operands */
6742 normal_lf( div_fl
);
6744 /* position fracts and compute expo */
6745 if (fl
->long_fract
< div_fl
->long_fract
) {
6746 fl
->expo
= fl
->expo
- div_fl
->expo
+ 64;
6748 fl
->expo
= fl
->expo
- div_fl
->expo
+ 65;
6749 div_fl
->long_fract
<<= 4;
6752 /* partial divide first hex digit */
6753 wk2
= fl
->long_fract
/ div_fl
->long_fract
;
6754 wk
= (fl
->long_fract
% div_fl
->long_fract
) << 4;
6756 /* partial divide middle hex digits */
6760 | (wk
/ div_fl
->long_fract
);
6761 wk
= (wk
% div_fl
->long_fract
) << 4;
6764 /* partial divide last hex digit */
6765 fl
->long_fract
= (wk2
<< 4)
6766 | (wk
/ div_fl
->long_fract
);
6768 /* determine sign */
6769 fl
->sign
= (fl
->sign
== div_fl
->sign
) ? 0 : 1;
6771 /* handle overflow and underflow */
6772 return( over_under_flow_lf(fl
) );
6774 /* fraction of dividend 0, set true 0 */