1 /* eclipse_cpu.c: Eclipse CPU simulator
2
3 Modified from the original NOVA simulator by Robert Supnik.
4
5 Copyright (c) 1998-2012, Charles E Owen
6 Portions Copyright (c) 1993-2002, Robert M Supnik
7
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:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
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.
24
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.
28
29 cpu Eclipse central processor
30
31 25-Mar-12 RMS Fixed declarations (Mark Pizzolato)
32 07-Jun-06 RMS Fixed bug in DIVS (Mark Hittinger)
33 22-Sep-05 RMS Fixed declarations (Sterling Garwood)
34 25-Aug-05 RMS Fixed DIVS overflow cases
35 29-Nov-03 CEO Corrected POPJ and Bit operations bugs
36 26-Nov-03 CEO Added FPU and PIT devices
37 20-Feb-03 CEO Corrected several MMPU and CIS bugs
38 28-Jan-02 RMS Cleaned up compiler warnings
39 30-Nov-01 RMS Added extended SET/SHOW support
40 01-Jun-01 RMS Added second terminal, plotter support
41 26-Apr-01 RMS Added device enable/disable support
42
43 The register state for the Eclipse CPU is basically the same as
44 the NOVA's:
45
46 AC[0:3]<0:15> general registers
47 C carry flag
48 PC<0:14> program counter
49
50 Eclipses with Folating Point Units added these registers:
51
52 FPAC[0:3]<0:63> Floating Point Accumulators
53 FPSR Floating Point Status Register
54
55 In addition, certain low-memory locations are reserved for special
56 purposes:
57
58 0: I/O Return Address (from an interrupt)
59 1: I/O (Interrupt) handler address
60 2: System Call handler address (used by SYC instruction)
61 3: Protection Fault handler address
62 4: VECTOR stack pointer (VCT Instruction)
63 5: Current Interrupt Priority mask
64 6: VECTOR stack limit (VCT instruction)
65 7: VECTOR stack fault address (VCT again)
66 10: Block Pointer (later models only)
67 11: Emulation Trap Handler address (microeclipse only)
68 20-27: Auto-increment locations (not on microeclipse)
69 30-37: Auto-decrement locations (not on microeclipse)
70 40: Stack pointer
71 41: Frame Pointer
72 42: Stack Limit
73 43: Stack fault address
74 44: XOP Origin address
75 45: Floating point fault address
76 46: Commercial fault address (not on microeclipse)
77 47: Reserved, do not use.
78
79 Note: While all eclipses share most of the "standard" features,
80 some models added a few quirks and wrinkles, and other models
81 dropped some features or modified others. Most DG software
82 is written for a "standard" Eclipse, and avoids these problem
83 areas. A general overview:
84
85 [subject to major changes as info becomes available!]
86
87 Early (e.g. S/100, S/200, C/300) [Front Panel machines]
88
89 The first Eclipses had the basic MAP, but certain parts
90 were kluged, and these were fixed in later MAP designs.
91 The original mapping hardware was termed MAP for Memory
92 Allocate and Protection. The later design was termed
93 MMPU for Memory Mapping and Protection Unit. While
94 similar in design, the two units are not compatible.
95 Also, the C version (C for Commercial) of these early
96 CPUs had a feature called "Commercial Instruction Set"
97 which contained character manipulation, translation
98 between commercial-format numeric data and FPU formats,
99 and an elaborate EDIT instruction. Later models kept
100 only the character manipulation part of this and called
101 the feature the "Character Instruction Set", leading to
102 confusion because the initials of both are CIS. ARDOS
103 is the only DG operating system to support the older
104 MAP. ZRDOS uses the MMPU, and AOS supports only MMPU.
105
106 Middle (e.g. S/130, C/150, S/230, C/330) [Front Panel]
107
108 These are close to a "Standard". They have the newer,
109 fixed MMPU. Support for the PIT (Programmed Interval
110 Timer. The Commercial (not character) instruction set
111 and FPU are optional. (CIS standard on C models)
112
113 Late (C/350, M/600: [Panel]; S/140, S/280 [Virtual Console])
114
115 All features of the Middle period are included, plus:
116 These late Eclipses added a few MMPU wrinkles all their
117 own, included support for user maps C and D. Character
118 instruction set is standard, FPU optional. Also, support
119 for the BMC device.
120
121 MicroEclipse-based (S/20, S/120, Desktops) [Virtual cons.]
122
123 All features of the Late period, in general, plus:
124 Microeclipses dropped support for the auto increment
125 and decrement locations at 20-37. They also added
126 support for invalid instruction traps thru location 11.
127 The Desktops have an interface to the "Attached Processor",
128 an 8086, at device code 6. Also, some new CPU device
129 features to read states info. The Character Instruction
130 set and FPU are standard on all models.
131
132 The Eclipse instruction set is an elaboration of the NOVA's. The basic
133 NOVA set is implemented in it's entireity, plus many new Eclipse
134 instructions are added. Since in theory every possible 16-bit
135 combination is a NOVA instruction, the Eclipse commands are carved
136 out of the NOVA set by using the Operate format with the no-load bit
137 set to 1 and the skip bits set to 000. Since this combination is
138 in effect a no-op on the NOVA, it was rarely or never used. The
139 other bits are used to form Eclipse instructions, which have no
140 other common format. To see the instructions, refer to the Eclipse
141 section of the instruction decode logic in sim_instr() below. All
142 Eclipse instructions are checked first, so in case of conflict in
143 bit patterns, the Eclipse one is executed over the corresponding
144 NOVA pattern. A bizarre exception is LEF mode...which implements
145 an instruction called Load Effective Address by taking over the
146 Nova I/O format when the LEF mode bit is set and the processor is
147 executing in mapped mode.
148
149 The following discussion talks about NOVA instructions which are
150 Eclipse instructions also.
151
152 The NOVA has three instruction formats: memory reference, I/O transfer,
153 and operate. The memory reference format is:
154
155 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
156 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
157 | 0| op | AC |in| mode| displacement | memory reference
158 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
159
160 <0:4> mnemonic action
161
162 00000 JMP PC = MA
163 00001 JMS AC3 = PC, PC = MA
164 00010 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0
165 00011 DSZ M[MA] = M[MA] - 1, skip if M[MA] == 0
166 001'n LDA ACn = M[MA]
167 010'n STA M[MA] = ACn
168
169 <5:7> mode action
170
171 000 page zero direct MA = zext (IR<8:15>)
172 001 PC relative direct MA = PC + sext (IR<8:15>)
173 010 AC2 relative direct MA = AC2 + sext (IR<8:15>)
174 011 AC3 relative direct MA = AC3 + sext (IR<8:15>)
175 100 page zero indirect MA = M[zext (IR<8:15>)]
176 101 PC relative dinirect MA = M[PC + sext (IR<8:15>)]
177 110 AC2 relative indirect MA = M[AC2 + sext (IR<8:15>)]
178 111 AC3 relative indirect MA = M[AC3 + sext (IR<8:15>)]
179
180 Memory reference instructions can access an address space of 32K words.
181 An instruction can directly reference the first 256 words of memory
182 (called page zero), as well as 256 words relative to the PC, AC2, or
183 AC3; it can indirectly access all 32K words. If an indirect address
184 is in locations 00020-00027, the indirect address is incremented and
185 rewritten to memory before use; if in 00030-00037, decremented and
186 rewritten.
187
188 The I/O transfer format is:
189
190 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
191 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
192 | 0 1 1| AC | opcode |pulse| device | I/O transfer
193 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
194
195 The IOT instruction sends the opcode, pulse, and specified AC to the
196 specified I/O device. The device may accept data, provide data,
197 initiate or cancel operations, or skip on status.
198
199 The operate format is:
200
201 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
202 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
203 | 1|srcAC|dstAC| opcode |shift|carry|nl| skip | operate
204 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
205 \______/ \___/ \___/ | | | |
206 | | | | | | +--- reverse skip sense
207 | | | | | +--- skip if C == 0
208 | | | | +--- skip if result == 0
209 | | | +--- don't load result
210 | | +--- carry in (load as is,
211 | | set to Zero,
212 | | set to One,
213 | | load Complement)
214 | +--- shift (none,
215 | left one,
216 | right one,
217 | byte swap)
218 +--- operation (complement,
219 negate,
220 move,
221 increment,
222 add complement,
223 subtract,
224 add,
225 and)
226
227 The operate instruction can be microprogrammed to perform operations
228 on the source and destination AC's and the Carry flag.
229
230 This routine is the instruction decode routine for the NOVA.
231 It is called from the simulator control program to execute
232 instructions in simulated memory, starting at the simulated PC.
233 It runs until 'reason' is set non-zero.
234
235 General notes:
236
237 1. Reasons to stop. The simulator can be stopped by:
238
239 HALT instruction
240 breakpoint encountered
241 infinite indirection loop
242 unknown I/O device and STOP_DEV flag set
243 I/O error in I/O simulator
244
245 2. Interrupts. Interrupts are maintained by four parallel variables:
246
247 dev_done device done flags
248 dev_disable device interrupt disable flags
249 dev_busy device busy flags
250 int_req interrupt requests
251
252 In addition, int_req contains the interrupt enable and ION pending
253 flags. If ION and ION pending are set, and at least one interrupt
254 request is pending, then an interrupt occurs. Note that the 16b PIO
255 mask must be mapped to the simulator's device bit mapping.
256
257 3. Non-existent memory. On the NOVA, reads to non-existent memory
258 return zero, and writes are ignored. In the simulator, the
259 largest possible memory is instantiated and initialized to zero.
260 Thus, only writes need be checked against actual memory size.
261
262 4. Adding I/O devices. These modules must be modified:
263
264 eclipse_defs.h add interrupt request definition
265 eclipse_cpu.c add IOT mask, PI mask, and routine to dev_table
266 eclipse_sys.c add pointer to data structures to sim_devices
267 */
268
269 /*---------------------------------------------------------------------------
270 ** ECLIPSE Debugging Facilities
271 **
272 ** These options are designed to find hard-to-locate flaky bugs by
273 ** providing special error checking and logging.
274 **
275 ** All are controlled by depositing a value into the DEBUG register.
276 ** A value of zero means no special debugging facilities are turned on.
277 ** This is the default. Debugging invokes a performance hit! Use only
278 ** when necessary.
279 **
280 ** Debugging means logging information to a file, or to a buffer in
281 ** memory from whence it can be dumped to a file.
282 **
283 ** 1XXXXX = Log all instructions executed to file "trace.log".
284 ** **CAUTION**: This means the CPU will run SLOWLY and
285 ** the resulting trace.log file will be HUGE. We're talking
286 ** about a megabyte for each 5 seconds or less of wall clock
287 ** time, depending on the speed of your CPU. Note: In this
288 ** mode, interrupts are logged when they are received also.
289 **
290 ** Note: when detailed logging is off, the last 4096 or so
291 ** instructions executed are saved in a memory buffer, and
292 ** when the sim stops, the "show" command can write this
293 ** history information to the file "history.log". This only
294 ** works if the DEBUG register is non-zero however, because
295 ** of the performance hit even this recording makes. To
296 ** dump history, enter the command "show cpu history", with
297 ** the file "history" spelled correctly and lower case.
298 **
299 ** XXXXDD = Log all I/O instructions to or from device number
300 ** DD. Log is written to "trace.log", regardless of the
301 ** setting of the instruction trace flag (1XXXXX). If both
302 ** are on, the device traces will be interpersed with the
303 ** instruction traces -- very useful sometimes.
304 **
305 ** XXX1DD = Device Break. Does a breakpoint in any I/O to
306 ** device DD. Useful, say when a diagnostic gives an
307 ** error message - a device break on 11 (TTO) will stop
308 ** as soon as the error message appears, making the
309 ** trace log much shorter to track back on.
310 **
311 ** X4XXXX = When this bit is on, the sim will stop if it sees
312 ** an invalid instruction. When DEBUG is zero, any such
313 ** instruction is no-oped with no warning. When DEBUG is
314 ** non-zero, but this bit is 0, a warning will be displayed
315 ** but execution will continue.
316 **
317 ** X2XXXX = LEF break. When A LEF instruction is executed in
318 ** mapped user space, the sim does a breakpoint right after
319 ** executing the instruction.
320 **
321 ** Whenever the DEBUG register is non-zero, special error checking
322 ** is enabled in the sim. This will stop the sim automatically
323 ** when a likely error occurs, such as:
324 **
325 ** 1. Any execution that reaches, or will reach, location 00000.
326 ** 2. Any I/O to device 00
327 ** 3. An interrupt from device 00.
328 ** 4. An invalid instruction (stop is optional)
329 **
330 ** DCHAR Register: Whenever this is non-zero, a test is made on every
331 ** character output to the TTO device (master console). If the character
332 ** output to that device matches this register, the CPU will break.
333 **
334 ** Of course, the standard BREAK register is available for breakpoints
335 ** as in all the sims based on this standard.
336 --------------------------------------------------------------------------*/
337
338 #include "nova_defs.h"
339
340 #define UNIT_V_MICRO (UNIT_V_UF) /* Microeclipse? */
341 #define UNIT_V_17B (UNIT_V_UF) /* 17 bit MAP */
342 #define UNIT_V_UP (UNIT_V_UF) /* FPU Enabled */
343 #define UNIT_V_MSIZE (UNIT_V_UF+1) /* dummy mask */
344 #define UNIT_MICRO (1 << UNIT_V_MICRO)
345 #define UNIT_17B (1 << UNIT_V_17B)
346 #define UNIT_UP (1 << UNIT_V_UP)
347 #define UNIT_MSIZE (1 << UNIT_V_MSIZE)
348
349 uint16 M[MAXMEMSIZE] = { 0 }; /* memory */
350 int32 AC[4] = { 0 }; /* accumulators */
351 int32 C = 0; /* carry flag */
352 int32 saved_PC = 0; /* program counter */
353 int32 SR = 0; /* switch register */
354 int32 dev_done = 0; /* device done flags */
355 int32 dev_busy = 0; /* device busy flags */
356 int32 dev_disable = 0; /* int disable flags */
357 int32 iot_enb = -1; /* IOT enables */
358 int32 int_req = 0; /* interrupt requests */
359 int32 pimask = 0; /* priority int mask */
360 int32 pwr_low = 0; /* power fail flag */
361 int32 ind_max = 15; /* iadr nest limit */
362 int32 stop_dev = 0; /* stop on ill dev */
363 int32 old_PC = 0; /* previous PC */
364 int32 model = 140; /* Model of Eclipse */
365 int32 speed = 0; /* Delay for each instruction */
366
367 int32 XCT_mode = 0; /* 1 if XCT mode */
368 int32 XCT_inst = 0; /* XCT instruction */
369 int32 PPC = -1;
370 int32 AMASK = 077777;
371
372 struct ndev dev_table[64]; /* dispatch table */
373
374 /* Instruction history buffer */
375
376 #define HISTMAX 4096
377
378 int32 hnext = 0; /* # of current entry */
379 int32 hwrap = 0; /* 1 if wrapped */
380 int32 hmax = HISTMAX; /* Maximum entries b4 wrap */
381 uint16 hpc[HISTMAX];
382 uint16 hinst[HISTMAX];
383 uint16 hinst2[HISTMAX];
384 uint16 hac0[HISTMAX];
385 uint16 hac1[HISTMAX];
386 uint16 hac2[HISTMAX];
387 uint16 hac3[HISTMAX];
388 unsigned short hflags[HISTMAX];
389
390 /* Flags: 0x01 - carry bit
391 0x02 - int enabled
392 0x04 - user map a
393 0x08 - user map b
394 0x10 - user map c
395 0x20 - user map d
396 0x40 - LEF mode was on
397 0x80 - this is an int, not an inst.
398 hpc is return addr
399 hinst is int_req
400 hac0 is device
401 hac1 is int addr
402 */
403
404
405
406 /* the Eclipse MAP unit: This unit is standard in all Eclipse processors
407 except for the "original" Eclipses, the S/100, S/200, and C/300. These
408 use a different and more elaborate MMPU that is not compatible with
409 the one simulated here. All subsequent Eclipses, from the S/130 on up
410 to the last models S/280 and C/380 use the map simulated here, including
411 the MicroEclipses. There are model-dependent quirks. That's why we
412 have to MODEL register.
413
414 The programming of the MMPU can be found in the LMP instruction, below,
415 and in the instructions directed to DEV_MAP.
416
417 There are two user maps, called A and B, and four data channel maps,
418 A thru D. They can be enabled/disabled separately. Some models have
419 two extra user maps, C and D. These are supported where apporpriate.
420
421 */
422
423 #define PAGEMASK 01777 /* Largest physical page possible */
424 #define MAPMASK 0101777 /* Valid page bits in map */
425 #define INVALID 0101777 /* Mask indicating an invalid page */
426 int32 MapStat = 0; /* Map status register */
427 int32 Inhibit = 0; /* !0=inhibit interrupts : */
428 /* 1 = single cycle inhibit */
429 /* 2 = inhibit until indirection */
430 /* 3 = inhibit next instruction only */
431 int32 Enable = 0; /* User map to activate 1=A 2=B */
432 int32 Usermap = 0; /* Active Map? 0=supvr mode, 1=user A, 2 = user B */
433 int32 Map[8][32]; /* The actual MAPs 0=dch A, 1=A, 2=B, 3-5=dchB-D 6-7 User C-D */
434 int32 Map31 = 037; /* Map for block 31 in supervisor mode */
435 int32 SingleCycle = 0; /* Map one LDA/STA */
436 int32 Check = 0; /* Page Check Register */
437 int32 Fault = 0; /* Fault register */
438 int32 MapInit = 0; /* 1 when map initialized */
439 int32 MapIntMode = 0; /* Save of map user mode when int occurs */
440
441 /* The Eclipse Floating Point Unit: This unit is optional on all Eclipse
442 models.
443 */
444
445 int32 FPSR = 0; /* 32-bit FPU Status Register */
446 t_int64 FPAC[4] = { 0,0,0,0 }; /* 4 64-bit Accumulators */
447 int32 FPFault = 0; /* Save Fault State */
448
449 /* Definitions for internal floating point arithmetic */
450
451 typedef struct _SHORT_FLOAT {
452 int32 short_fract; /* Fraction */
453 short expo; /* Exponent + 64 */
454 uint8 sign; /* Sign */
455 } SHORT_FLOAT;
456
457 typedef struct _LONG_FLOAT {
458 t_int64 long_fract; /* Fraction */
459 short expo; /* Exponent + 64 */
460 uint8 sign; /* Sign */
461 } LONG_FLOAT;
462
463 LONG_FLOAT dfl,dfl2; /* Double Precision Work Fields */
464 SHORT_FLOAT sfl,sfl2; /* Single Precision Work Fields */
465 t_int64 tempfp, holdfp; /* Working area for FPAC */
466 int shift,m3;
467 t_int64 lsfract;
468
469 void get_sf(SHORT_FLOAT *fl, t_int64 *fpr);
470 void store_sf(SHORT_FLOAT *fl, t_int64 *fpr);
471 void get_lf(LONG_FLOAT *fl, t_int64 *fpr);
472 void store_lf(LONG_FLOAT *fl, t_int64 *fpr);
473 int normal_sf (SHORT_FLOAT *fl);
474 int normal_lf (LONG_FLOAT *fl);
475 int overflow_sf(SHORT_FLOAT *fl);
476 int overflow_lf(LONG_FLOAT *fl);
477 int underflow_sf(SHORT_FLOAT *fl);
478 int underflow_lf(LONG_FLOAT *fl);
479 int significance_sf(SHORT_FLOAT *fl);
480 int significance_lf(LONG_FLOAT *fl);
481 int add_sf(SHORT_FLOAT *fl, SHORT_FLOAT *add_f1, int normal);
482 int add_lf(LONG_FLOAT *fl, LONG_FLOAT *add_fl, int normal);
483 int mul_sf(SHORT_FLOAT *fl, SHORT_FLOAT *mul_fl);
484 int mul_lf(LONG_FLOAT *fl, LONG_FLOAT *mul_fl);
485 int div_sf(SHORT_FLOAT *fl, SHORT_FLOAT *div_fl);
486 int div_lf(LONG_FLOAT *fl, LONG_FLOAT *div_fl);
487
488 /* Special Debugging Info */
489
490 int32 Debug_Flags = 0; /* Debug register - selects debug features */
491 int32 Debug_Char = 0; /* Debug Character Register */
492
493 int32 Tron = 0; /* For trace files */
494 FILE *Trace;
495
496
497 t_stat reason;
498 extern int32 sim_int_char;
499 extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
500 extern DEVICE *sim_devices[];
501
502 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
503 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
504 t_stat cpu_reset (DEVICE *dptr);
505 t_stat cpu_boot (int32 unitno, DEVICE *dptr);
506 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
507 t_stat Debug_Dump (UNIT *uptr, int32 val, char *cptr, void *desc);
508 t_stat Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc);
509 t_stat map_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
510 t_stat map_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
511 t_stat map_reset (DEVICE *dptr);
512 t_stat map_svc (UNIT *uptr);
513 t_stat fpu_svc (UNIT *uptr);
514 int32 GetMap(int32 addr);
515 int32 PutMap(int32 addr, int32 data);
516 int32 Debug_Entry(int32 PC, int32 inst, int32 inst2, int32 AC0, int32 AC1, int32 AC2, int32 AC3, int32 flags);
517 t_stat build_devtab (void);
518
519 extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
520 UNIT *uptr, int32 sw);
521
522 /* CPU data structures
523
524 cpu_dev CPU device descriptor
525 cpu_unit CPU unit descriptor
526 cpu_reg CPU register list
527 cpu_mod CPU modifiers list
528 */
529
530 UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) };
531
532 REG cpu_reg[] = {
533 { ORDATA (PC, saved_PC, 15) },
534 { ORDATA (AC0, AC[0], 16) },
535 { ORDATA (AC1, AC[1], 16) },
536 { ORDATA (AC2, AC[2], 16) },
537 { ORDATA (AC3, AC[3], 16) },
538 { FLDATA (C, C, 16) },
539 { ORDATA (SR, SR, 16) },
540 { ORDATA (PI, pimask, 16) },
541 { FLDATA (ION, int_req, INT_V_ION) },
542 { FLDATA (ION_DELAY, int_req, INT_V_NO_ION_PENDING) },
543 { FLDATA (PWR, pwr_low, 0) },
544 { ORDATA (INT, int_req, INT_V_ION+1), REG_RO },
545 { ORDATA (BUSY, dev_busy, INT_V_ION+1), REG_RO },
546 { ORDATA (DONE, dev_done, INT_V_ION+1), REG_RO },
547 { ORDATA (DISABLE, dev_disable, INT_V_ION+1), REG_RO },
548 { FLDATA (STOP_DEV, stop_dev, 0) },
549 { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT },
550 { ORDATA (DEBUG, Debug_Flags, 16) },
551 { ORDATA (DCHAR, Debug_Char, 16) },
552 { DRDATA (MODEL, model, 16) },
553 { DRDATA (SPEED, speed, 16) },
554 { ORDATA (WRU, sim_int_char, 8) },
555 { NULL }
556 };
557
558 MTAB cpu_mod[] = {
559 { UNIT_MICRO, UNIT_MICRO, "MICRO", "MICRO", NULL },
560 { UNIT_MICRO, 0, "STD", "STD", NULL },
561 { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
562 { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
563 { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size },
564 { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
565 { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size },
566 { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
567 { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size },
568 { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
569 { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
570 { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
571 { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size },
572 { UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size },
573 { UNIT_MSIZE, 1048576, NULL, "1024K", &cpu_set_size },
574 { UNIT_MSIZE, 0, NULL, "DUMP", &Debug_Dump },
575 { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", NULL,
576 NULL, &Dump_History },
577 { 0 }
578 };
579
580 DEVICE cpu_dev = {
581 "CPU", &cpu_unit, cpu_reg, cpu_mod,
582 1, 8, 17, 1, 8, 16,
583 &cpu_ex, &cpu_dep, &cpu_reset,
584 &cpu_boot, NULL, NULL
585 };
586
587 /* MAP data structures
588
589 map_dev MAP device descriptor
590 map_unit MAP unit descriptor
591 map_reg MAP register list
592 map_mod MAP modifiers list
593 */
594
595 UNIT map_unit = { UDATA (&map_svc, UNIT_17B, MAXMEMSIZE) };
596
597 REG map_reg[] = {
598 { ORDATA (STATUS, MapStat, 16) },
599 { ORDATA (ENABLE, Enable, 16) },
600 { ORDATA (IINHIB, Inhibit, 16) },
601 { ORDATA (ACTIVE, Usermap, 16) },
602 { ORDATA (MAP31, Map31, 16) },
603 { ORDATA (CYCLE, SingleCycle, 16) },
604 { ORDATA (CHECK, Check, 16) },
605 { ORDATA (FAULT, Fault, 16) },
606 { NULL }
607 };
608
609 MTAB map_mod[] = {
610 { UNIT_17B, UNIT_17B, "17bit", "17B", NULL },
611 { UNIT_17B, 0, "19bit", "19B", NULL },
612 { 0 }
613 };
614
615 DEVICE map_dev = {
616 "MAP", &map_unit, map_reg, map_mod,
617 1, 8, 17, 1, 8, 16,
618 &map_ex, &map_dep, NULL,
619 NULL, NULL, NULL
620 };
621
622 /* FPU data structures
623
624 fpu_dev MAP device descriptor
625 fpu_unit MAP unit descriptor
626 fpu_reg MAP register list
627 fpu_mod MAP modifiers list
628 */
629
630 UNIT fpu_unit = { UDATA (&fpu_svc, UNIT_UP, MAXMEMSIZE) };
631
632 REG fpu_reg[] = {
633 { ORDATA (STATUS, FPSR, 32) },
634 { ORDATA (FPAC0, FPAC[0], 64) },
635 { ORDATA (FPAC1, FPAC[1], 64) },
636 { ORDATA (FPAC2, FPAC[2], 64) },
637 { ORDATA (FPAC3, FPAC[3], 64) },
638 { ORDATA (FAULT, FPFault, 32) },
639 { NULL }
640 };
641
642 MTAB fpu_mod[] = {
643 { UNIT_UP, UNIT_UP, "Enabled (UP)", "UP", NULL },
644 { UNIT_UP, 0, "Disabled (DOWN)", "DOWN", NULL },
645 { 0 }
646 };
647
648 DEVICE fpu_dev = {
649 "FPU", &fpu_unit, fpu_reg, fpu_mod,
650 1, 16, 17, 1, 16, 16,
651 NULL, NULL, NULL,
652 NULL, NULL, NULL
653 };
654
655
656 /* ---- Programmable Interval Timer Device ----------- */
657
658 int32 pit_time = 100;
659 int32 pit_tps = 10000; /* ticks per sec */
660 int32 pit_adj = 20; /* tmxr adjust */
661 int32 pit_poll = 16000; /* tmxr poll */
662 int32 pit_initial = 0; /* initial counter reg */
663 int32 pit_counter = 0; /* Counter */
664 int32 pit_flag = 0; /* Initial setting flag */
665
666 int32 pit (int32 pulse, int32 code, int32 AC);
667 t_stat pit_svc (UNIT *uptr);
668 t_stat pit_reset (DEVICE *dptr);
669
670 /* PIT data structures
671
672 pit_dev device descriptor
673 pit_unit unit descriptor
674 pit_reg register list
675 */
676
677 DIB pit_dib = { DEV_PIT, INT_PIT, PI_PIT, &pit };
678
679 UNIT pit_unit = { UDATA (&pit_svc, 0, 0) };
680
681 REG pit_reg[] = {
682 { ORDATA (INIT, pit_initial, 16) },
683 { ORDATA (COUNT, pit_counter, 16) },
684 { FLDATA (BUSY, dev_busy, INT_V_PIT) },
685 { FLDATA (DONE, dev_done, INT_V_PIT) },
686 { FLDATA (DISABLE, dev_disable, INT_V_PIT) },
687 { FLDATA (INT, int_req, INT_V_PIT) },
688 { DRDATA (TIME0, pit_time, 24), REG_NZ + PV_LEFT },
689 { NULL }
690 };
691
692 DEVICE pit_dev = {
693 "PIT", &pit_unit, pit_reg, NULL,
694 1, 0, 0, 0, 0, 0,
695 NULL, NULL, &pit_reset,
696 NULL, NULL, NULL,
697 &pit_dib, 0
698 };
699
sim_instr(void)700 t_stat sim_instr (void)
701 {
702 extern int32 sim_interval;
703 register int32 PC, IR, i, t, MA, j, k, tac;
704 register uint32 mddata, uAC0, uAC1, uAC2, uAC3;
705 int16 sAC0, sAC1, sAC2;
706 int32 sddata, mi1, mi2, fpnum32;
707 t_int64 fpnum, expon;
708 t_value simeval[20];
709 void mask_out (int32 mask);
710 /* char debstr[128]; */
711 /* char debadd[64]; */
712 char debmap[4], debion[4];
713 int debcar, iodev, iodata, debflags;
714 int32 DisMap, debpc;
715 /* int32 sp, sl; */
716 int cmdptr, cmsptr, cmopt, cmptr;
717 int16 cmslen, cmdlen;
718 int tabaddr, tabptr;
719 int32 effective(int32 PC, int32 index, int32 disp);
720 int32 indirect(int32 d);
721 int32 LEFmode(int32 PC, int32 index, int32 disp, int32 indirect);
722 int32 LoadMap(int32 w);
723 int32 Bytepointer(int32 PC, int32 index);
724 int32 unimp(int32 PC);
725 int32 pushrtn(int32 pc);
726
727 /* Restore register state */
728
729 if (build_devtab () != SCPE_OK) return SCPE_IERR; /* build dispatch */
730 PC = saved_PC & AMASK; /* load local PC */
731 C = C & 0200000;
732 mask_out (pimask); /* reset int system */
733 reason = 0;
734 if (MapInit == 0) {
735 MapInit = 1;
736 for (mi1 = 0; mi1 < 6; mi1++) { /* Initialize MAPs */
737 for (mi2 = 0; mi2 < 32; mi2++) {
738 Map[mi1][mi2] = mi2;
739 }
740 }
741 }
742
743 /* Main instruction fetch/decode loop */
744
745 while (reason == 0) { /* loop until halted */
746 if (sim_interval <= 0) { /* check clock queue */
747 if ((reason = sim_process_event ()))
748 break;
749 }
750
751 //if (speed > 0) for (i = 0; i < speed; i++) { j = 0; }
752
753 if (Fault) { /* Check MAP fault */
754 Usermap = 0; /* YES: shutdown map */
755 MapStat &= ~01; /* Disable MMPU */
756 if (Fault & 0100000/*!!!*/) /* If it was validity, or WP */
757 MapStat &= ~0170; /* Reset other checkbits */
758 MapStat |= Fault & 077777; /* Put in fault code */
759 Fault = 0; /* Reset fault code */
760 t = (GetMap(040) + 1) & AMASK; /* Push rtn block */
761 PutMap(t, AC[0]);
762 t++;
763 PutMap(t, AC[1]);
764 t++;
765 PutMap(t, AC[2]);
766 t++;
767 PutMap(t, AC[3]);
768 t++;
769 PutMap(t, (PC & AMASK));
770 if (C) PutMap(t, (GetMap(t) | 0100000));
771 PutMap(040, t);
772 int_req = int_req & ~INT_ION; /* Disable interrupts */
773 PC = indirect(M[003]); /* JMP to loc 3 */
774 continue;
775 }
776
777 if (FPSR & 0xF8000000) { /* FPU Fault? */
778 if (!(FPSR & 0x78000000)) { /* If error bit on ... */
779 FPSR &= 0x00FFFFFF; /* ...but no error, clear it */
780 } else { /* ELSE a real error: */
781 FPSR |= 0x80000000; /* Turn error bit on */
782 if (FPSR & 0x04000000) { /* Trap enabled ? */
783 FPFault = FPSR; /* Save fault */
784 FPSR &= 0xFBFFFFFF; /* Clear Trap Enable */
785 }
786 }
787 }
788
789 if (int_req > INT_PENDING && !Inhibit) { /* interrupt? */
790 int_req = int_req & ~INT_ION;
791 MapIntMode = MapStat; /* Save Status as it was */
792 Usermap = 0; /* Inhibit MAP */
793 MapStat &= ~1; /* Disable user map */
794 if (XCT_mode) {
795 M[0] = PC - 1; /* If XCT mode rtn to XCT */
796 XCT_mode = 0; /* turn off mode */
797 } else {
798 M[0] = PC; /* Save Return Address */
799 }
800 old_PC = PC;
801 MA = M[1];
802 for (i = 0; i < ind_max * 2; i++) { /* count indirects */
803 if ((MA & 0100000) == 0) break;
804 if ((MA & 077770) == 020)
805 MA = (M[MA & AMASK] = (M[MA & AMASK] + 1) & 0177777);
806 else if ((MA & 077770) == 030)
807 MA = (M[MA & AMASK] = (M[MA & AMASK] - 1) & 0177777);
808 else MA = M[MA & AMASK];
809 }
810 if (i >= (ind_max-1)) {
811 if ((MapStat & 010) && Usermap) {
812 Fault = 04000; /* Map fault if IND prot */
813 continue;
814 } else {
815 reason = STOP_IND_INT;
816 break;
817 }
818 }
819 if (Debug_Flags) {
820 iodev = 0;
821 iodata = int_req & (-int_req);
822 for (i = DEV_LOW; i <= DEV_HIGH; i++) {
823 if (iodata & dev_table[i].mask) {
824 iodev = i;
825 break;
826 }
827 }
828 if (iodev == 0) {
829 printf("\n<<Interrupt to device 0!>>\n");
830 reason = STOP_IBKPT;
831 }
832 if (Debug_Flags & 0100000) {
833 fprintf(Trace, "--------- Interrupt %o (%o) to %6o ---------\n", int_req, iodev, MA);
834 } else {
835 Debug_Entry(PC, int_req, 0, iodev, MA, 0, 0, 0x80);
836 }
837 }
838 PC = MA;
839 } /* end interrupt */
840
841 if (Inhibit != 0) { /* Handle 1-instruction inhibit sequence */
842 if (Inhibit == 3) /* Used by SYC instruction */
843 Inhibit = 4;
844 if (Inhibit == 4)
845 Inhibit = 0;
846 }
847
848 if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
849 reason = STOP_IBKPT; /* stop simulation */
850 break;
851 }
852
853 if ((PC < 1 || PC > 077777) && Debug_Flags) {
854 if (PPC != -1) { /* Don't break on 1st instruction */
855 printf("\n<<Invalid PC=%o from %o>>\n\r", PC, PPC);
856 reason = STOP_IBKPT;
857 break;
858 }
859 }
860
861 PPC = PC;
862
863 if (Debug_Flags) {
864 if (!Tron) {
865 Tron = 1;
866 Trace = fopen("trace.log", "w");
867 }
868 strcpy(debmap, " ");
869 strcpy(debion, " ");
870 debcar = 0;
871 if (C) debcar = 1;
872 if (Usermap == 1) strcpy(debmap, "A");
873 if (Usermap == 2) strcpy(debmap, "B");
874 if (Usermap == 5) strcpy(debmap, "C");
875 if (Usermap == 6) strcpy(debmap, "D");
876 if (int_req & INT_ION) strcpy(debion, "I");
877 if (XCT_mode == 0) {
878 debpc = PC;
879 simeval[0] = GetMap(PC);
880 simeval[1] = GetMap(PC+1);
881 } else {
882 debpc = 0177777;
883 simeval[0] = XCT_inst;
884 simeval[1] = 0;
885 }
886 if (Debug_Flags & 0100000) {
887 fprintf(Trace, "%s%s%06o acs: %06o %06o %06o %06o %01o ",
888 debion, debmap, debpc, AC[0], AC[1], AC[2], AC[3], debcar);
889 fprint_sym (Trace, debpc, simeval, NULL, SWMASK('M'));
890 fprintf(Trace, "\n");
891 } else {
892 debflags = 0;
893 if (C) debflags |= 0x01;
894 if (int_req & INT_ION) debflags |= 0x02;
895 if (Usermap == 1) debflags |= 0x04;
896 if (Usermap == 2) debflags |= 0x08;
897 if (Usermap == 3) debflags |= 0x10;
898 if (Usermap == 4) debflags |= 0x20;
899 Debug_Entry(debpc, (int32)simeval[0], (int32)simeval[1], AC[0], AC[1], AC[2], AC[3], debflags);
900 }
901 }
902
903 if (XCT_mode == 0) { /* XCT mode? */
904 IR = GetMap(PC); /* No: fetch instr */
905 if (Fault) continue; /* Give up if fault */
906 PC = (PC + 1) & AMASK; /* bump PC */
907 } else {
908 IR = XCT_inst; /* Yes: Get inst to XCT */
909 XCT_mode = 0; /* Go back to normal mode */
910 }
911 int_req = int_req | INT_NO_ION_PENDING; /* clear ION delay */
912 sim_interval = sim_interval - 1;
913 t = IR >> 11; /* prepare to decode */
914
915 /* ---------------- BEGIN Eclipse modification --------------------- */
916
917 /* Eclipse instruction set. These instructions are checked for
918 before any of the NOVA ones. Eclipse instructions do not
919 correspond to any patterns, other than bit 0 being 1 and
920 the last 4 bits are 1000. Words which are not Eclipse
921 instructions will be interpreted as Nova instructions. */
922
923 /* Important Note: The order of the if statements is important.
924 Frequently executed instructions should come first, to enhance
925 the speed of the simulation.
926 */
927
928 if ((IR & 0100017) == 0100010) { /* This pattern for all */
929 /* Eclipse instructions */
930
931 /****************************************************************/
932 /* This is the standard Eclipse instruction set */
933 /****************************************************************/
934
935 /* Byte operations */
936
937 if ((IR & 0103777) == 0102710) { /* LDB: Load Byte */
938 i = (IR >> 13) & 03;
939 MA = (AC[i] >> 1) & AMASK;
940 j = (IR >> 11) & 03;
941 if (AC[i] & 01) {
942 AC[j] = GetMap(MA) & 0377;
943 } else {
944 AC[j] = (GetMap(MA) >> 8) & 0377;
945 }
946 continue;
947 }
948 if ((IR & 0103777) == 0103010) { /* STB: Store Byte */
949 i = (IR >> 13) & 03;
950 MA = (AC[i] >> 1);
951 j = (IR >> 11) & 03;
952 t = GetMap(MA);
953 if (AC[i] & 01) {
954 t &= 0177400;
955 t |= (AC[j] & 0377);
956 PutMap(MA, t);
957 } else {
958 t &= 0377;
959 t |= (AC[j] & 0377) << 8;
960 PutMap(MA, t);
961 }
962 continue;
963 }
964
965 /* Fixed-point arithmetic - loads & saves */
966
967 if ((IR & 0162377) == 0122070) { /* ELDA: Extended LDA */
968 i = (IR >> 11) & 3;
969 t = GetMap(PC);
970 if (SingleCycle) Usermap = SingleCycle;
971 AC[i] = GetMap(effective(PC, (IR >> 8) & 3, t));
972 if (SingleCycle) {
973 Usermap = SingleCycle = 0;
974 if (Inhibit == 1) Inhibit = 3;
975 MapStat |= 02000;
976 MapStat &= 0177776;
977 }
978 PC = (PC + 1) & AMASK;
979 continue;
980 }
981 if ((IR & 0162377) == 0142070) { /* ESTA: Extended STA */
982 i = (IR >> 11) & 3;
983 t = GetMap(PC);
984 if (SingleCycle) Usermap = SingleCycle;
985 PutMap((effective(PC, (IR >> 8) & 3, t)), AC[i]);
986 if (SingleCycle) {
987 Usermap = SingleCycle = 0;
988 if (Inhibit == 1) Inhibit = 3;
989 MapStat |= 02000;
990 MapStat &= 0177776;
991 }
992 PC = (PC + 1) & AMASK;
993 continue;
994 }
995 if ((IR & 0103777) == 0100010) { /* ADI: Add Immediate */
996 t = (IR >> 11) & 3;
997 AC[t] = (AC[t] + ((IR >> 13) & 3) + 1) & 0xffff;
998 continue;
999 }
1000 if ((IR & 0103777) == 0100110) { /* SBI: Subtract Immediate */
1001 t = (IR >> 11) & 3;
1002 AC[t] = (AC[t] - (((IR >> 13) & 3) + 1)) & 0xffff;
1003 continue;
1004 }
1005 if ((IR & 0163777) == 0163770) { /* ADDI: Extended Add Immed. */
1006 t = (IR >> 11) & 3;
1007 i = GetMap(PC);
1008 PC = (PC + 1) & AMASK;
1009 AC[t] = (AC[t] + i) & 0xffff;
1010 continue;
1011 }
1012 if ((IR & 0103777) == 0100710) { /* XCH: Exchange Accumulators */
1013 t = AC[(IR >> 11) & 3];
1014 AC[(IR >> 11) & 3] = AC[(IR >> 13) & 3];
1015 AC[(IR >> 13) & 3] = t;
1016 continue;
1017 }
1018 if ((IR & 0162377) == 0162070) { /* ELEF: Load Effective Addr */
1019 t = GetMap(PC);
1020 AC[(IR >> 11) & 3] = effective(PC, (IR >> 8) & 3, t);
1021 PC = (PC + 1) & AMASK;
1022 continue;
1023 }
1024
1025 /* Logical operations */
1026
1027 if ((IR & 0163777) == 0143770) { /* ANDI: And Immediate */
1028 AC[(IR >> 11) & 3] &= GetMap(PC);
1029 PC = (PC + 1) & AMASK;
1030 continue;
1031 }
1032 if ((IR & 0163777) == 0103770) { /* IORI: Inclusive Or Immed */
1033 AC[(IR >> 11) & 3] |= GetMap(PC);
1034 PC = (PC + 1) & AMASK;
1035 continue;
1036 }
1037 if ((IR & 0163777) == 0123770) { /* XORI: Exclusive Or Immed */
1038 AC[(IR >> 11) & 3] ^= GetMap(PC);
1039 PC = (PC + 1) & AMASK;
1040 continue;
1041 }
1042 if ((IR & 0103777) == 0100410) { /* IOR: Inclusive Or */
1043 AC[(IR >> 11) & 3] |= AC[(IR >> 13) & 3];
1044 continue;
1045 }
1046 if ((IR & 0103777) == 0100510) { /* XOR: Exclusive Or */
1047 AC[(IR >> 11) & 3] ^= AC[(IR >> 13) & 3];
1048 continue;
1049 }
1050 if ((IR & 0103777) == 0100610) { /* ANC: And with complemented src */
1051 AC[(IR >> 11) & 3] &= ~(AC[(IR >> 13) & 3]);
1052 continue;
1053 }
1054
1055 /* Shift operations */
1056
1057 if ((IR & 0103777) == 0101210) { /* LSH: Logical Shift */
1058 register int16 sh;
1059 sh = AC[(IR >> 13) & 3] & 0377;
1060 i = (IR >> 11) & 3;
1061 if (sh & 0200) {
1062 sh = ~sh + 1;
1063 AC[i] = AC[i] >> sh;
1064 } else {
1065 AC[i] = AC[i] << sh;
1066 }
1067 if (sh > 15) AC[i] = 0;
1068 AC[i] &= 0xffff;
1069 continue;
1070 }
1071 if ((IR & 0103777) == 0101310) { /* DLSH: Double logical shift */
1072 register int16 sh;
1073 sh = AC[(IR >> 13) & 3] & 0377;
1074 i = (IR >> 11) & 3;
1075 uAC0 = AC[i] << 16;
1076 j = i + 1;
1077 if (j == 4) j = 0;
1078 uAC0 |= AC[j];
1079 if (sh & 0200) {
1080 sh = (~sh + 1) & 0377;
1081 if (sh < 32)
1082 uAC0 = uAC0 >> sh;
1083 } else {
1084 if (sh < 32)
1085 uAC0 = uAC0 << sh;
1086 }
1087 if (sh > 31) uAC0 = 0;
1088 AC[i] = (uAC0 >> 16) & 0xffff;
1089 AC[j] = uAC0 & 0xffff;
1090 continue;
1091 }
1092 if ((IR & 0103777) == 0101410) { /* HXL: Hex shift left */
1093 t = ((IR >> 13) & 3) + 1;
1094 i = (IR >> 11) & 3;
1095 AC[i] = AC[i] << (t * 4);
1096 AC[i] &= 0xffff;
1097 continue;
1098 }
1099 if ((IR & 0103777) == 0101510) { /* HXR: Hex shift right */
1100 t = ((IR >> 13) & 3) + 1;
1101 i = (IR >> 11) & 3;
1102 AC[i] = AC[i] >> (t * 4);
1103 AC[i] &= 0xffff;
1104 continue;
1105 }
1106 if ((IR & 0103777) == 0101610) { /* DHXL: Double Hex shift left */
1107 t = ((IR >> 13) & 3) + 1;
1108 i = (IR >> 11) & 3;
1109 j = i + 1;
1110 if (j == 4) j = 0;
1111 uAC0 = AC[i] << 16;
1112 uAC0 |= AC[j];
1113 uAC0 = uAC0 << ((t * 4) & 0177);
1114 AC[i] = (uAC0 >> 16) & 0xffff;
1115 AC[j] = uAC0 & 0xffff;
1116 continue;
1117 }
1118 if ((IR & 0103777) == 0101710) { /* DHXR: Double Hex shift right */
1119 t = ((IR >> 13) & 3) + 1;
1120 i = (IR >> 11) & 3;
1121 j = i + 1;
1122 if (j == 4) j = 0;
1123 uAC0 = AC[i] << 16;
1124 uAC0 |= AC[j];
1125 uAC0 = uAC0 >> ((t * 4) & 0177);
1126 AC[i] = (uAC0 >> 16) & 0xffff;
1127 AC[j] = uAC0 & 0xffff;
1128 continue;
1129 }
1130
1131 /* Bit operations */
1132
1133 if ((IR & 0103777) == 0102010) { /* BTO: Set bit to one */
1134 i = (IR >> 11) & 3;
1135 j = (IR >> 13) & 3;
1136 if (i != j) {
1137 k = (AC[i] >> 4) & AMASK;
1138 if ((AC[j] + k) & 0100000)
1139 t = 1;
1140 //AOS MA = indirect(AC[j] + k);
1141 MA = (AC[j] + k) & AMASK;
1142 } else {
1143 MA = (AC[i] >> 4) & AMASK;
1144 }
1145 t = AC[i] & 017;
1146 t = GetMap(MA) | (0100000 >> t);
1147 PutMap(MA, t);
1148 continue;
1149 }
1150 if ((IR & 0103777) == 0102110) { /* BTZ: Set bit to zero */
1151 i = (IR >> 11) & 3;
1152 j = (IR >> 13) & 3;
1153 if (i != j) {
1154 k = (AC[i] >> 4) & AMASK;
1155 if ((AC[j] + k) & 0100000)
1156 t = 1;
1157 //AOS MA = indirect(AC[j] + k);
1158 MA = (AC[j] + k) & AMASK;
1159 } else {
1160 MA = (AC[j] >> 4) & AMASK;
1161 }
1162 t = AC[i] & 017;
1163 t = GetMap(MA) & ~(0100000 >> t);
1164 PutMap(MA, t);
1165 continue;
1166 }
1167 if ((IR & 0103777) == 0102210) { /* SZB: Skip on zero bit */
1168 i = (IR >> 11) & 3;
1169 j = (IR >> 13) & 3;
1170 if (i != j) {
1171 k = (AC[i] >> 4) & AMASK;
1172 if ((AC[j] + k) & 0100000)
1173 t = 1;
1174 MA = indirect(AC[j] + k);
1175 // MA = (AC[j] + k) & AMASK;
1176 } else {
1177 MA = (AC[i] >> 4) & AMASK;
1178 }
1179 t = GetMap(MA) << (AC[i] & 017);
1180 if (!(t & 0100000)) PC = (PC + 1) & AMASK;
1181 continue;
1182 }
1183 if ((IR & 0103777) == 0102770) { /* SNB: Skip on non-zero bit */
1184 i = (IR >> 11) & 3;
1185 j = (IR >> 13) & 3;
1186 if (i != j) {
1187 k = (AC[i] >> 4) & AMASK;
1188 if ((AC[j] + k) & 0100000)
1189 t = 1;
1190 MA = indirect(AC[j] + k);
1191 // MA = (AC[j] + k) & AMASK;
1192 } else {
1193 MA = (AC[j] >> 4) & AMASK;
1194 }
1195 t = GetMap(MA) << (AC[i] & 017);
1196 if (t & 0100000) PC = (PC + 1) & AMASK;
1197 continue;
1198 }
1199 if ((IR & 0103777) == 0102310) { /* SZBO: skip on zero bit & set to 1 */
1200 register int32 save;
1201 i = (IR >> 11) & 3;
1202 j = (IR >> 13) & 3;
1203 if (i != j) {
1204 k = (AC[i] >> 4) & AMASK;
1205 MA = indirect(AC[j] + k);
1206 // MA = (AC[j] + k) & AMASK;
1207 } else {
1208 MA = (AC[j] >> 4) & AMASK;
1209 }
1210 t = AC[i] & 017;
1211 save = GetMap(MA);
1212 t = save | (0100000 >> t);
1213 PutMap(MA, t);
1214 t = save << (AC[i] & 017);
1215 if ((t & 0100000) == 0)
1216 PC = (PC + 1) & AMASK;
1217 continue;
1218 }
1219 if ((IR & 0103777) == 0102410) { /* LOB: Locate lead bit */
1220 register int32 a, r;
1221 register int16 b;
1222 a = AC[(IR >> 13) & 3] & 0xffff;
1223 for (i = 0; i < 16; i++) {
1224 if ((a << i) & 0100000) break;
1225 }
1226 r = (IR >> 11) & 3;
1227 b = AC[r];
1228 b += i;
1229 AC[r] = b & 0177777;
1230 continue;
1231 }
1232 if ((IR & 0103777) == 0102510) { /* LRB: Locate & reset lead bit */
1233 register int32 a, r;
1234 register int16 b;
1235 j = (IR >> 13) & 3;
1236 a = AC[j];
1237 for (i = 0; i < 16; i++) {
1238 if ((a << i) & 0100000) break;
1239 }
1240 r = (IR >> 11) & 3;
1241 b = AC[r];
1242 b += i;
1243 if (j != r) AC[r] = b & 0177777;
1244 AC[j] &= ~(0100000 >> i);
1245 AC[j] &= 0xffff;
1246 continue;
1247 }
1248 if ((IR & 0103777) == 0102610) { /* COB: Count bits */
1249 register int32 a;
1250 register int16 b, c = 0;
1251 a = AC[(IR >> 13) & 3];
1252 for (i = 0; i < 16; i++) {
1253 if ((a >> i) & 1) c++;
1254 }
1255 i = (IR >> 11) & 3;
1256 b = AC[i];
1257 b += c;
1258 AC[i] = b & 0177777;
1259 continue;
1260 }
1261
1262 /* Jump & similar operations */
1263
1264 if ((IR & 0176377) == 0102070) { /* EJMP: Extended JMP */
1265 PC = effective(PC, (IR >> 8) & 3, GetMap(PC));
1266 continue;
1267 }
1268 if ((IR & 0176377) == 0106070) { /* EJSR: Extended JMP to subr */
1269 t = effective(PC, (IR >> 8) & 3, GetMap(PC));
1270 AC[3] = (PC + 1) & AMASK;
1271 PC = t & AMASK;
1272 continue;
1273 }
1274 if ((IR & 0176377) == 0112070) { /* EISZ: Ext Inc & skip if 0 */
1275 MA = effective(PC, (IR >> 8) & 3, GetMap(PC));
1276 PutMap(MA, ((GetMap(MA) + 1) & 0xffff));
1277 if (GetMap(MA) == 0) PC = (PC + 1) & AMASK;
1278 PC = (PC + 1) & AMASK;
1279 continue;
1280 }
1281 if ((IR & 0176377) == 0116070) { /* EDSZ: Ext Dec & skip if 0 */
1282 MA = effective(PC, (IR >> 8) & 3, GetMap(PC));
1283 PutMap(MA, ((GetMap(MA) - 1) & 0xffff));
1284 if (GetMap(MA) == 0) PC = (PC + 1) & AMASK;
1285 PC = (PC + 1) & AMASK;
1286 continue;
1287 }
1288 if ((IR & 0103777) == 0101010) { /* SGT: Skip if ACS > ACD */
1289 register int16 a1, d1;
1290 a1 = AC[(IR >> 13) & 3] & 0xffff;
1291 d1 = AC[(IR >> 11) & 3] & 0xffff;
1292 if (a1 > d1)
1293 PC = (PC + 1) & AMASK;
1294 continue;
1295 }
1296 if ((IR & 0103777) == 0101110) { /* SGE: Skip if ACS >= ACD */
1297 register int16 a1, d1;
1298 a1 = AC[(IR >> 13) & 3] & 0xffff;
1299 d1 = AC[(IR >> 11) & 3] & 0xffff;
1300 if (a1 >= d1)
1301 PC = (PC + 1) & AMASK;
1302 continue;
1303 }
1304 if ((IR & 0103777) == 0102370) { /* CLM: Compare to limits */
1305 register int32 s, d, MA;
1306 int16 H, L, ca;
1307 s = (IR >> 13) & 3;
1308 d = (IR >> 11) & 3;
1309 if (s == d) {
1310 L = GetMap(PC);
1311 PC++;
1312 H = GetMap(PC);
1313 PC++;
1314 } else {
1315 MA = AC[d] & AMASK;
1316 L = GetMap(MA);
1317 H = GetMap(MA + 1);
1318 }
1319 ca = AC[s];
1320 if (ca >= L && ca <= H) PC = (PC + 1) & AMASK;
1321 continue;
1322 }
1323 if ((IR & 0163777) == 0123370) { /* XCT: Execute */
1324 XCT_mode = 1; /* Set up to execute on next loop */
1325 XCT_inst = AC[(IR >> 11) & 3];
1326 continue;
1327 }
1328
1329 /* Memory block operations */
1330
1331 if (IR == 0113710) { /* BAM: Block add & move */
1332 register int32 w;
1333 t = AC[1];
1334 if (t < 1 || t > 0100000)
1335 continue;
1336 i = indirect(AC[2]);
1337 j = indirect(AC[3]);
1338 while (t) {
1339 w = GetMap(i);
1340 PutMap(j, ((w + AC[0]) & 0xffff));
1341 if (Fault) break;
1342 t--;
1343 i++;
1344 j++;
1345 i &= AMASK;
1346 j &= AMASK;
1347 }
1348 AC[1] = t;
1349 AC[2] = i & AMASK;
1350 AC[3] = j & AMASK;
1351 continue;
1352 }
1353 if (IR == 0133710) { /* BLM: Block move */
1354 t = AC[1];
1355 if (t < 1 || t > 0100000)
1356 continue;
1357 i = indirect(AC[2]);
1358 j = indirect(AC[3]);
1359 if (Fault) continue;
1360 while (t) {
1361 PutMap(j, GetMap(i));
1362 if (Fault) break;
1363 t--;
1364 i++;
1365 j++;
1366 i &= AMASK;
1367 j &= AMASK;
1368 }
1369 AC[1] = t;
1370 AC[2] = i & AMASK;
1371 AC[3] = j & AMASK;
1372 continue;
1373 }
1374
1375 /* Stack operations */
1376
1377 if ((IR & 0103777) == 0103110) { /* PSH: Push multiple accums */
1378 register int32 j;
1379 j = (IR >> 11) & 3;
1380 t = GetMap(040) & AMASK;
1381 i = (IR >> 13) & 3;
1382 if (i == j) {
1383 t++;
1384 PutMap(t, AC[i]);
1385 PutMap(040, (t & AMASK));
1386 if (t > GetMap(042)) {
1387 pushrtn(PC);
1388 PC = indirect(GetMap(043));
1389 PutMap(040, (GetMap(040) & 077777));
1390 PutMap(042, (GetMap(042) | 0100000));
1391 }
1392 continue;
1393 }
1394 while (i != j) {
1395 t++;
1396 PutMap(t, AC[i]);
1397 i++;
1398 if (i == 4) i = 0;
1399 }
1400 t++;
1401 PutMap(t, AC[i]);
1402 PutMap(040, (t & AMASK));
1403 if ((GetMap(040) & AMASK) > GetMap(042)) {
1404 pushrtn(PC);
1405 PC = indirect(GetMap(043));
1406 PutMap(040, (GetMap(040) & 077777));
1407 PutMap(042, (GetMap(042) | 0100000));
1408 }
1409 continue;
1410 }
1411 if ((IR & 0103777) == 0103210) { /* POP: Pop mult accums */
1412 j = (IR >> 11) & 3;
1413 t = GetMap(040) & AMASK;
1414 i = (IR >> 13) & 3;
1415 if (i == j) {
1416 AC[i] = GetMap(t);
1417 t--;
1418 PutMap(040, (t & AMASK));
1419 t = GetMap(040);
1420 if (t < 0100000 && t < 0400) {
1421 PutMap(040, GetMap(042));
1422 pushrtn(PC);
1423 PC = indirect(GetMap(043));
1424 PutMap(040, (GetMap(040) & 077777));
1425 PutMap(042, (GetMap(042) | 0100000));
1426 }
1427 continue;
1428 }
1429 while (i != j) {
1430 AC[i] = GetMap(t);
1431 t--;
1432 i--;
1433 if (i == -1) i = 3;
1434 }
1435 AC[i] = GetMap(t);
1436 t--;
1437 PutMap(040, (t & AMASK));
1438 t = GetMap(040);
1439 if (t < 0100000 && t < 0400) {
1440 PutMap(040, GetMap(042));
1441 pushrtn(PC);
1442 PC = indirect(GetMap(043));
1443 PutMap(040, (GetMap(040) & 077777));
1444 PutMap(042, (GetMap(042) | 0100000));
1445 }
1446 continue;
1447 }
1448 if (IR == 0103710) { /* PSHR: Push return addr */
1449 t = (GetMap(040) + 1) & AMASK;
1450 PutMap(t, (PC + 1));
1451 PutMap(040, t);
1452 if ((GetMap(040) & AMASK) > GetMap(042)) {
1453 pushrtn(PC);
1454 PC = indirect(GetMap(043));
1455 PutMap(040, (GetMap(040) & 077777));
1456 PutMap(042, (GetMap(042) | 0100000));
1457 }
1458 continue;
1459 }
1460 if (IR == 0163710) { /* SAVE */
1461 register int32 savep;
1462 savep = ((GetMap(PC) + GetMap(040)) + 5) & AMASK;
1463 if (savep > GetMap(042)) {
1464 pushrtn(PC-1);
1465 PC = indirect(GetMap(043));
1466 PutMap(040, (GetMap(040) & 077777));
1467 PutMap(042, (GetMap(042) | 0100000));
1468 continue;
1469 }
1470 t = GetMap(040) + 1;
1471 PutMap(t, AC[0]);
1472 t++;
1473 PutMap(t, AC[1]);
1474 t++;
1475 PutMap(t, AC[2]);
1476 t++;
1477 PutMap(t, GetMap(041));
1478 t++;
1479 savep = PC;
1480 PC = (PC + 1) & AMASK;
1481 PutMap(t, (AC[3] & AMASK));
1482 if (C) PutMap(t, (GetMap(t) | 0100000));
1483 PutMap(040, t);
1484 AC[3] = GetMap(040) & AMASK;
1485 PutMap(041, AC[3]);
1486 PutMap(040, ((GetMap(040) + GetMap(savep)) & AMASK));
1487 continue;
1488 }
1489 if ((IR & 0163777) == 0103370) { /* MSP: Modify stack pointer */
1490 t = (GetMap(040) + AC[(IR >> 11) & 3]) & 0177777;
1491 if (t > GetMap(042)) {
1492 pushrtn(PC-1);
1493 PC = indirect(GetMap(043));
1494 PutMap(040, (GetMap(040) & AMASK));
1495 PutMap(042, (GetMap(042) | 0100000));
1496 continue;
1497 }
1498 PutMap(040, t);
1499 continue;
1500 }
1501 if ((IR & 0176377) == 0102270) { /* PSHJ: Push JMP */
1502 PutMap(040, (GetMap(040) + 1));
1503 PutMap((GetMap(040) & AMASK), ((PC + 1) & AMASK));
1504 if ((GetMap(040) & AMASK) > (GetMap(042) & AMASK)) {
1505 pushrtn(PC+1);
1506 PC = indirect(GetMap(043));
1507 PutMap(040, (GetMap(040) & 077777));
1508 PutMap(042, (GetMap(042) | 0100000));
1509 continue;
1510 }
1511 PC = effective(PC, (IR >> 8) & 3, GetMap(PC));
1512 continue;
1513 }
1514 if (IR == 0117710) { /* POPJ: Pop PC and Jump */
1515 PC = GetMap(GetMap(040)) & AMASK;
1516 PutMap(040, (GetMap(040) - 1));
1517 if (MapStat & 1) {
1518 Usermap = Enable;
1519 Inhibit = 0;
1520 }
1521 j = GetMap(042);
1522 t = GetMap(040);
1523 if ((j < 0100000 && t < 0100000) && (t < 0400) && (t > 0)) {
1524 pushrtn(PC);
1525 PC = indirect(GetMap(043));
1526 PutMap(040, (GetMap(040) & 077777));
1527 PutMap(042, (GetMap(042) | 0100000));
1528 }
1529 continue;
1530 }
1531 if (IR == 0107710) { /* POPB: Pop block */
1532 PC = GetMap(GetMap(040)) & AMASK;
1533 if (GetMap(GetMap(040)) & 0100000)
1534 C = 0200000;
1535 else
1536 C = 0;
1537 PutMap(040, (GetMap(040) - 1));
1538 AC[3] = GetMap(GetMap(040));
1539 PutMap(040, (GetMap(040) - 1));
1540 AC[2] = GetMap(GetMap(040));
1541 PutMap(040, (GetMap(040) - 1));
1542 AC[1] = GetMap(GetMap(040));
1543 PutMap(040, (GetMap(040) - 1));
1544 AC[0] = GetMap(GetMap(040));
1545 PutMap(040, (GetMap(040) - 1));
1546 t = GetMap(040);
1547 if (t < 0100000 && t < 0400) {
1548 pushrtn(PC);
1549 PC = indirect(GetMap(043));
1550 PutMap(040, (GetMap(040) & 077777));
1551 PutMap(042, (GetMap(042) | 0100000));
1552 }
1553 if (MapStat & 1) {
1554 Usermap = Enable;
1555 Inhibit = 0;
1556 }
1557 continue;
1558 }
1559 if (IR == 0127710) { /* RTN: Return */
1560 PutMap(040, GetMap(041));
1561 PC = GetMap(GetMap(040)) & AMASK;
1562 t = GetMap(040);
1563 t = GetMap(t);
1564 if (t & 0100000)
1565 C = 0200000;
1566 else
1567 C = 0;
1568 PutMap(040, (GetMap(040) - 1));
1569 AC[3] = GetMap(GetMap(040));
1570 PutMap(040, (GetMap(040) - 1));
1571 AC[2] = GetMap(GetMap(040));
1572 PutMap(040, (GetMap(040) - 1));
1573 AC[1] = GetMap(GetMap(040));
1574 PutMap(040, (GetMap(040) - 1));
1575 AC[0] = GetMap(GetMap(040));
1576 PutMap(040, (GetMap(040) - 1));
1577 PutMap(041, AC[3]);
1578 t = GetMap(040);
1579 if (t < 0100000 && t < 0400) {
1580 pushrtn(PC);
1581 PutMap(040, (GetMap(040) & 077777));
1582 PutMap(042, (GetMap(042) | 0100000));
1583 PC = indirect(GetMap(043));
1584 }
1585 if (MapStat & 1) {
1586 Usermap = Enable;
1587 Inhibit = 0;
1588 }
1589 continue;
1590 }
1591 if (IR == 0167710) { /* RSTR: Restore */
1592 int32 SVPC;
1593
1594 SVPC = PC;
1595 PC = GetMap(GetMap(040)) & AMASK;
1596 if (PC == 0 && Debug_Flags) {
1597 printf("\n<<RSTR to 0 @ %o>>\n\r", SVPC);
1598 reason = STOP_IBKPT;
1599 }
1600 if (GetMap(GetMap(040)) & 0100000)
1601 C = 0200000;
1602 else
1603 C = 0;
1604 PutMap(040, (GetMap(040) - 1));
1605 AC[3] = GetMap(GetMap(040));
1606 PutMap(040, (GetMap(040) - 1));
1607 AC[2] = GetMap(GetMap(040));
1608 PutMap(040, (GetMap(040) - 1));
1609 AC[1] = GetMap(GetMap(040));
1610 PutMap(040, (GetMap(040) - 1));
1611 AC[0] = GetMap(GetMap(040));
1612 PutMap(040, (GetMap(040) - 1));
1613 PutMap(043, GetMap(GetMap(040)));
1614 PutMap(040, (GetMap(040) - 1));
1615 PutMap(042, GetMap(GetMap(040)));
1616 PutMap(040, (GetMap(040) - 1));
1617 PutMap(041, GetMap(GetMap(040)));
1618 PutMap(040, (GetMap(040) - 1));
1619 PutMap(040, GetMap(GetMap(040)));
1620 /*t = GetMap(040);
1621 if (t < 0100000 && t < 0400) {
1622 pushrtn(PC);
1623 PC = indirect(GetMap(043));
1624 }*/
1625 if (MapStat & 1) {
1626 Usermap = Enable;
1627 Inhibit = 0;
1628 }
1629 continue;
1630 }
1631
1632 /* Multiply / Divide */
1633
1634 if (IR == 0143710) { /* MUL: Unsigned Multiply */
1635 uAC0 = (uint32) AC[0];
1636 uAC1 = (uint32) AC[1];
1637 uAC2 = (uint32) AC[2];
1638
1639 mddata = (uAC1 * uAC2) + uAC0;
1640 AC[0] = (mddata >> 16) & 0177777;
1641 AC[1] = mddata & 0177777;
1642 continue;
1643 }
1644 if (IR == 0147710) { /* MULS: Signed Multiply */
1645 sAC0 = AC[0];
1646 sAC1 = AC[1];
1647 sAC2 = AC[2];
1648
1649 sddata = (sAC1 * sAC2) + sAC0;
1650 AC[0] = (sddata >> 16) & 0177777;
1651 AC[1] = sddata & 0177777;
1652 continue;
1653 }
1654 if (IR == 0153710) { /* DIV: Unsigned Divide */
1655 uAC0 = (uint32) AC[0];
1656 uAC1 = (uint32) AC[1];
1657 uAC2 = (uint32) AC[2];
1658
1659 if (uAC0 >= uAC2) C = 0200000;
1660 else {
1661 C = 0;
1662 mddata = (uAC0 << 16) | uAC1;
1663 AC[1] = mddata / uAC2;
1664 AC[0] = mddata % uAC2;
1665 }
1666 continue;
1667 }
1668 if (IR == 0157710) { /* DIVS: Signed Divide */
1669 if ((AC[0] == 0) ||
1670 ((AC[0] == 0100000) && (AC[1] == 0) && (AC[2] == 0177777)))
1671 C = 0200000;
1672 else {
1673 sAC2 = AC[2];
1674 C = 0;
1675 sddata = ((AC[0] & 0xffff) << 16) | (AC[1] & 0xffff);
1676 AC[1] = sddata / sAC2;
1677 AC[0] = sddata % sAC2;
1678 if (AC[0] > 077777 || AC[0] < -077776) C = 0200000;
1679 /*if ((AC[0] & 0xFFFF0000) != 0) C = 0200000;*/
1680 if (AC[1] > 077777 || AC[1] < -077776) C = 0200000;
1681 /*if ((AC[1] & 0xFFFF0000) != 0) C = 0200000;*/
1682 AC[0] &= 0177777;
1683 AC[1] &= 0177777;
1684 }
1685 continue;
1686 }
1687 if (IR == 0137710) { /* DIVX: Sign extend and Divide */
1688 int32 q;
1689 if (AC[1] & 0100000) {
1690 AC[0] = 0177777;
1691 } else {
1692 AC[0] = 0;
1693 }
1694 sAC0 = AC[0];
1695 sAC1 = AC[1];
1696 sAC2 = AC[2];
1697
1698 C = 0;
1699 sddata = (sAC0 << 16) | sAC1;
1700 q = sddata / sAC2;
1701 AC[0] = sddata % sAC2;
1702 if (q > 0177777) {
1703 C = 0200000;
1704 } else {
1705 AC[1] = q & 0xffff;
1706 }
1707 continue;
1708 }
1709 if ((IR & 0163777) == 0143370) { /* HLV: Halve */
1710 t = (IR >> 11) & 3;
1711 if (AC[t] & 0100000) {
1712 AC[t] = (0 - AC[t]) & 0xffff;
1713 AC[t] = AC[t] >> 1;
1714 AC[t] = (0 - AC[t]) & 0xffff;
1715 } else {
1716 AC[t] = (AC[t] >> 1) & 0xffff;
1717 }
1718 continue;
1719 }
1720
1721 /* Decimal arithmetic */
1722
1723 if ((IR & 0103777) == 0100210) { /* DAD: Decimal add */
1724 i = (IR >> 13) & 3;
1725 j = (IR >> 11) & 3;
1726 t = (AC[i] & 017) + (AC[j] & 017);
1727 if (C) t++;
1728 if (t > 9) {
1729 C = 0200000;
1730 t += 6;
1731 } else {
1732 C = 0;
1733 }
1734 AC[j] &= 0177760;
1735 AC[j] = AC[j] | (t & 017);
1736 continue;
1737 }
1738 if ((IR & 0103777) == 0100310) { /* DSB: Decimal subtract */
1739 i = (IR >> 13) & 3;
1740 j = (IR >> 11) & 3;
1741 t = (AC[j] & 017) - (AC[i] & 017);
1742 if (!C) t--;
1743 if (t < 0) {
1744 C = 0;
1745 t = 9 - (~t);
1746 } else {
1747 C = 0200000;
1748 }
1749 AC[j] &= 0177760;
1750 AC[j] = AC[j] | (t & 017);
1751 continue;
1752 }
1753
1754 /* Exotic, complex instructions */
1755
1756 if ((IR & 0162377) == 0142170) { /* DSPA: Dispatch */
1757 register int32 d;
1758 int16 a, H, L;
1759 MA = effective(PC, (IR >> 8) & 3, GetMap(PC));
1760 H = GetMap(MA - 1) & 0177777;
1761 L = GetMap(MA - 2) & 0177777;
1762 a = AC[(IR >> 11) & 3] & 0177777;
1763 if (a < L || a > H) {
1764 PC = (PC + 1) & AMASK;
1765 continue;
1766 }
1767 d = GetMap(MA - L + a);
1768 if (d == 0177777) {
1769 PC = (PC + 1) & AMASK;
1770 continue;
1771 }
1772 PC = indirect(d) & AMASK;
1773 continue;
1774 }
1775
1776 if (((IR & 0100077) == 0100030) ||
1777 ((IR & 0102077) == 0100070)) { /* XOP: Extended Operation */
1778 register int32 op, d, sa, da;
1779 op = (IR >> 6) & 037;
1780 if ((IR & 077) == 070) op += 32;
1781 t = GetMap(040) & AMASK;
1782 for (i = 0; i <= 3; i++) {
1783 t++;
1784 PutMap(t, AC[i]);
1785 if (((IR >> 13) & 3) == i) sa = t;
1786 if (((IR >> 11) & 3) == i) da = t;
1787 }
1788 t++;
1789 PutMap(t, PC & AMASK);
1790 if (C) PutMap(t, (GetMap(t) | 0100000));
1791 PutMap(040, t);
1792 AC[2] = sa;
1793 AC[3] = da;
1794 d = GetMap(GetMap(044) + op);
1795 PC = indirect(d) & AMASK;
1796 if ((GetMap(040) & AMASK) > (GetMap(042) & AMASK)) {
1797 pushrtn(PC);
1798 PC = indirect(GetMap(043));
1799 PutMap(040, (GetMap(040) & 077777));
1800 PutMap(042, (GetMap(042) | 0100000));
1801 }
1802 continue;
1803 }
1804 if ((IR & 0103777) == 0103510) { /* SYC: System call */
1805 register int32 j;
1806 DisMap = Usermap;
1807 Usermap = 0;
1808 MapStat &= ~1; /* Disable MAP */
1809 i = (IR >> 13) & 3;
1810 j = (IR >> 11) & 3;
1811 if (i != 0 || j != 0) {
1812 t = (GetMap(040) + 1) & AMASK;
1813 PutMap(t, AC[0]);
1814 t++;
1815 PutMap(t, AC[1]);
1816 t++;
1817 PutMap(t, AC[2]);
1818 t++;
1819 PutMap(t, AC[3]);
1820 t++;
1821 PutMap(t, (PC & AMASK));
1822 if (C) PutMap(t, (GetMap(t) | 0100000));
1823 PutMap(040, t);
1824 PutMap(041, (GetMap(040) & AMASK));
1825 }
1826 PC = indirect(GetMap(2)) & AMASK;
1827 if (DisMap > 0)
1828 Inhibit = 3; /* Special 1-instruction interrupt inhibit */
1829 if ((GetMap(040) & AMASK) > GetMap(042)) {
1830 pushrtn(PC);
1831 PC = indirect(GetMap(043));
1832 PutMap(040, (GetMap(040) & 077777));
1833 PutMap(042, (GetMap(042) | 0100000));
1834 }
1835 continue;
1836 }
1837 if (IR == 0113410) { /* LMP: Load Map */
1838 register int32 w, m;
1839 if ((Debug_Flags & 077) == 03)
1840 fprintf(Trace, "%o LMP (Map=%o)\n", PC - 1, (MapStat>>7)&07);
1841 t = AC[1];
1842 i = AC[2];
1843 while (t) {
1844 if (int_req > INT_PENDING && !Inhibit) { /* interrupt? */
1845 PC = PC - 1;
1846 break;
1847 }
1848 if (!Usermap || !(MapStat & 0140)) { /* Only load if in sup mode */
1849 w = (GetMap(i) + AC[0]) & 0xffff; /* Or not IO & LEF mode for user */
1850 m = (w >> 10) & 037;
1851 if ((Debug_Flags & 077) == 03)
1852 fprintf(Trace, " %o MAP L=%o W=%o P=%o\n", i, m,
1853 (w>>15)&1, w & PAGEMASK);
1854 LoadMap(w);
1855 if (Fault) break;
1856 }
1857 t--;
1858 i++;
1859 }
1860 AC[0] = 0;
1861 AC[1] = t;
1862 AC[2] = i & AMASK;
1863 MapStat &= ~02000;
1864 continue;
1865 }
1866
1867 /****************************************************************/
1868 /* Character Instruction Set */
1869 /****************************************************************/
1870
1871 if ((IR & 0162377) == 0102170) { /* ELDB */
1872 t = Bytepointer(PC, (IR >> 8) & 3);
1873 i = (IR >> 11) & 03;
1874 MA = (t >> 1) & AMASK;
1875 if (t & 01) {
1876 AC[i] = GetMap(MA) & 0377;
1877 } else {
1878 AC[i] = (GetMap(MA) >> 8) & 0377;
1879 }
1880 PC = (PC + 1) & AMASK;
1881 continue;
1882 }
1883 if ((IR & 0162377) == 0122170) { /* ESTB */
1884 t = Bytepointer(PC, (IR >> 8) & 3);
1885 i = (IR >> 11) & 03;
1886 MA = (t >> 1) & AMASK;
1887 j = GetMap(MA);
1888 if (t & 01) {
1889 j &= 0177400;
1890 j |= (AC[i] & 0377);
1891 PutMap(MA, j);
1892 } else {
1893 j &= 0377;
1894 j |= (AC[i] & 0377) << 8;
1895 PutMap(MA, j);
1896 }
1897 PC = (PC + 1) & AMASK;
1898 continue;
1899 }
1900
1901 if ((IR & 077) == 050) { /* All CIS end with 050 except ELDB/ESTB */
1902
1903 if (IR == 0153650) { /* CMV Character Move */
1904 cmdlen = AC[0] & 0177777; /* Set up length & direction */
1905 cmslen = AC[1] & 0177777; /* For both source & dest */
1906 cmsptr = AC[3]; /* init byte pointers */
1907 cmdptr = AC[2];
1908 C = 0; /* Do carry now b4 cmslen changes */
1909 if (abs(cmslen) > abs(cmdlen))
1910 C = 0200000;
1911 for (i = 0; i < abs(cmdlen); i++) { /* Move loop */
1912 MA = (cmsptr >> 1) & AMASK; /* do an LDB */
1913 if (cmslen == 0) {
1914 uAC2 = ' ' & 0377; /* Handle short source */
1915 } else {
1916 if (cmsptr & 01) {
1917 uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */
1918 } else {
1919 uAC2 = (GetMap(MA) >> 8) & 0377;
1920 }
1921 }
1922 MA = (cmdptr >> 1) & AMASK; /* do an STB */
1923 j = GetMap(MA);
1924 if (cmdptr & 01) {
1925 j &= 0177400;
1926 j |= (uAC2 & 0377);
1927 PutMap(MA, j);
1928 } else {
1929 j &= 0377;
1930 j |= (uAC2 & 0377) << 8;
1931 PutMap(MA, j);
1932 }
1933 if (cmslen > 0) {
1934 cmsptr++;
1935 cmslen--;
1936 }
1937 if (cmslen < 0) {
1938 cmsptr--;
1939 cmslen++;
1940 }
1941 if (cmdlen > 0) {
1942 cmdptr++;
1943 } else {
1944 cmdptr--;
1945 }
1946 }
1947 AC[0] = 0;
1948 AC[1] = cmslen & 0177777;
1949 AC[2] = cmdptr & 0177777;
1950 AC[3] = cmsptr & 0177777;
1951 continue;
1952 }
1953
1954 if (IR == 0157650) { /* CMP Character compare */
1955 cmdlen = AC[0] & 0177777; /* Set up length & direction */
1956 cmslen = AC[1] & 0177777; /* For both source & dest */
1957 cmsptr = AC[3]; /* init byte pointers */
1958 cmdptr = AC[2];
1959 t = 0; /* Equal unless otherwise */
1960 while (1) { /* Compare loop */
1961 MA = (cmsptr >> 1) & AMASK; /* do an LDB - string 1 */
1962 if (cmslen != 0) {
1963 if (cmsptr & 01) {
1964 uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */
1965 } else {
1966 uAC2 = (GetMap(MA) >> 8) & 0377;
1967 }
1968 } else {
1969 uAC2 = ' ' & 0377;
1970 }
1971 MA = (cmdptr >> 1) & AMASK; /* do an LDB - string 2 */
1972 if (cmdlen != 0) {
1973 if (cmdptr & 01) {
1974 uAC3 = GetMap(MA) & 0377; /* Use uAC2 for temp */
1975 } else {
1976 uAC3 = (GetMap(MA) >> 8) & 0377;
1977 }
1978 } else {
1979 uAC3 = ' ' & 0377;
1980 }
1981 if (uAC2 > uAC3) {
1982 t = 1;
1983 break;
1984 }
1985 if (uAC2 < uAC3) {
1986 t = -1;
1987 break;
1988 }
1989 if (cmslen > 0) {
1990 cmsptr++;
1991 cmslen--;
1992 }
1993 if (cmslen < 0) {
1994 cmsptr--;
1995 cmslen++;
1996 }
1997 if (cmdlen > 0) {
1998 cmdptr++;
1999 cmdlen--;
2000 }
2001 if (cmdlen < 0) {
2002 cmdptr--;
2003 cmdlen++;
2004 }
2005 if (cmslen == 0 && cmdlen == 0)
2006 break;
2007 }
2008 AC[1] = t & 0177777;
2009 AC[0] = cmdlen & 0177777;
2010 AC[2] = cmdptr & 0177777;
2011 AC[3] = cmsptr & 0177777;
2012 continue;
2013 }
2014 if (IR == 0163650) { /* CTR Character translate */
2015 tabaddr = indirect(AC[0]); /* Get address of table */
2016 tabptr = GetMap(tabaddr) & 0177777; /* Get byte pointer */
2017 cmslen = AC[1] & 0177777; /* Length: both source & dest */
2018 cmopt = 0; /* Default: COMPARE option */
2019 if (cmslen < 0) {
2020 cmopt=1; /* MOVE option */
2021 cmslen = 0 - cmslen;
2022 }
2023 cmsptr = AC[3]; /* init byte pointers */
2024 cmdptr = AC[2];
2025 t = 0; /* Equal unless otherwise */
2026 while (1) { /* Translation loop */
2027 MA = (cmsptr >> 1) & AMASK; /* do an LDB - string 1 */
2028 if (cmsptr & 01) {
2029 j = GetMap(MA) & 0377;
2030 } else {
2031 j = (GetMap(MA) >> 8) & 0377;
2032 }
2033 cmptr = tabptr + j; /* Translate */
2034 MA = (cmptr >> 1) & AMASK;
2035 if (cmptr & 01) {
2036 uAC2 = GetMap(MA) & 0377;
2037 } else {
2038 uAC2 = (GetMap(MA) >> 8) & 0377;
2039 }
2040 if (cmopt) { /* MOVE... */
2041 MA = (cmdptr >> 1) & AMASK; /* do an STB */
2042 j = GetMap(MA);
2043 if (cmdptr & 01) {
2044 j &= 0177400;
2045 j |= (uAC2 & 0377);
2046 PutMap(MA, j);
2047 } else {
2048 j &= 0377;
2049 j |= (uAC2 & 0377) << 8;
2050 PutMap(MA, j);
2051 }
2052 } else { /* COMPARE... */
2053 MA = (cmdptr >> 1) & AMASK; /* do an LDB - string 2 */
2054 if (cmdptr & 01) {
2055 j = GetMap(MA) & 0377;
2056 } else {
2057 j = (GetMap(MA) >> 8) & 0377;
2058 }
2059 cmptr = tabptr + j; /* Translate */
2060 MA = (cmptr >> 1) & AMASK;
2061 if (cmptr & 01) {
2062 uAC3 = GetMap(MA) & 0377;
2063 } else {
2064 uAC3 = (GetMap(MA) >> 8) & 0377;
2065 }
2066 if (uAC2 > uAC3) {
2067 t = 1;
2068 break;
2069 }
2070 if (uAC2 < uAC3) {
2071 t = -1;
2072 break;
2073 }
2074 }
2075 cmsptr++;
2076 cmdptr++;
2077 cmslen--;
2078 if (cmslen == 0)
2079 break;
2080 }
2081 if (!cmopt) AC[1] = t;
2082 else
2083 AC[1] = 0;
2084 AC[0] = tabaddr & 077777;
2085 AC[2] = cmdptr & 0177777;
2086 AC[3] = cmsptr & 0177777;
2087 continue;
2088 }
2089 if (IR == 0167650) { /* CMT Char move till true */
2090 tabaddr = indirect(AC[0]); /* Set up length & direction */
2091 cmslen = AC[1] & 0177777; /* For both source & dest */
2092 cmsptr = AC[3]; /* init byte pointers */
2093 cmdptr = AC[2];
2094 while (1) { /* Move loop */
2095 MA = (cmsptr >> 1) & AMASK; /* do an LDB */
2096 if (cmsptr & 01) {
2097 uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */
2098 } else {
2099 uAC2 = (GetMap(MA) >> 8) & 0377;
2100 }
2101 t = GetMap(tabaddr + (uAC2 >> 4)); /* Test bit table */
2102 if (t << (uAC2 & 0x0F) & 0100000) /* quit if bit == 1 */
2103 break;
2104 MA = (cmdptr >> 1) & AMASK; /* do an STB */
2105 j = GetMap(MA);
2106 if (cmdptr & 01) {
2107 j &= 0177400;
2108 j |= (uAC2 & 0377);
2109 PutMap(MA, j);
2110 } else {
2111 j &= 0377;
2112 j |= (uAC2 & 0377) << 8;
2113 PutMap(MA, j);
2114 }
2115 if (cmslen > 0) {
2116 cmsptr++;
2117 cmdptr++;
2118 cmslen--;
2119 }
2120 if (cmslen < 0) {
2121 cmsptr--;
2122 cmdptr--;
2123 cmslen++;
2124 }
2125 if (cmslen == 0)
2126 break;
2127 }
2128 AC[0] = tabaddr & 077777;
2129 AC[1] = cmslen & 0177777;
2130 AC[2] = cmdptr & 0177777;
2131 AC[3] = cmsptr & 0177777;
2132 continue;
2133 }
2134
2135 /***********************************************************
2136 ** "Commercial" instructions. These were in the original **
2137 ** Eclipse C series, but not part of the later Character **
2138 ** Instruction Set. **
2139 ***********************************************************/
2140
2141 if ((IR & 0163777) == 0103650) { /* LDI Load Integer */
2142 unimp(PC);
2143 continue;
2144 }
2145 if ((IR & 0163777) == 0123650) { /* STI Store Integer */
2146 unimp(PC);
2147 continue;
2148 }
2149 if (IR == 0143650) { /* LDIX Load Int Extended */
2150 unimp(PC);
2151 continue;
2152 }
2153 if (IR == 0143750) { /* STIX Store Int Extended */
2154 unimp(PC);
2155 continue;
2156 }
2157 if ((IR & 0163777) == 0143150) { /* FINT Integerize */
2158 unimp(PC);
2159 continue;
2160 }
2161 if (IR == 0177650) { /* LSN Load Sign */
2162 unimp(PC);
2163 continue;
2164 }
2165 if (IR == 0173650) { /* EDIT */
2166 unimp(PC);
2167 continue;
2168 }
2169 }
2170
2171 /* FPU Instructions */
2172
2173 if ((IR & 0163777) == 0123350) { /* FLST Load Status */
2174 if (!(fpu_unit.flags & UNIT_UP))
2175 continue;
2176 if (Debug_Flags == 1) {
2177 printf("\n<<FPU instruction: FLST>>\n");
2178 reason = STOP_IBKPT;
2179 }
2180 if (FPFault) { /* Fault from a previous inst? */
2181 FPFault = 0;
2182 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2183 PutMap(t, AC[0]);
2184 t++;
2185 PutMap(t, AC[1]);
2186 t++;
2187 PutMap(t, AC[2]);
2188 t++;
2189 PutMap(t, AC[3]);
2190 t++;
2191 PutMap(t, ((PC-1) & AMASK));
2192 if (C) PutMap(t, (GetMap(t) | 0100000));
2193 PutMap(040, t);
2194 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2195 continue;
2196 }
2197 FPSR = 0;
2198 MA = effective(PC, (IR >> 11) & 3, GetMap(PC));
2199 FPSR = (GetMap(MA) << 16);
2200 FPSR |= (GetMap(MA + 1));
2201 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2202 FPSR |= ((PC - 1) & AMASK);
2203 PC = (PC + 1) & AMASK;
2204 continue;
2205 }
2206 if ((IR & 0163777) == 0103350) { /* FSST Store Status */
2207 if (!(fpu_unit.flags & UNIT_UP))
2208 continue;
2209 if (Debug_Flags == 1) {
2210 printf("\n<<FPU instruction: FSST>>\n");
2211 reason = STOP_IBKPT;
2212 }
2213 if (FPFault) { /* Fault from a previous inst? */
2214 FPFault = 0;
2215 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2216 PutMap(t, AC[0]);
2217 t++;
2218 PutMap(t, AC[1]);
2219 t++;
2220 PutMap(t, AC[2]);
2221 t++;
2222 PutMap(t, AC[3]);
2223 t++;
2224 PutMap(t, ((PC-1) & AMASK));
2225 if (C) PutMap(t, (GetMap(t) | 0100000));
2226 PutMap(040, t);
2227 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2228 continue;
2229 }
2230 MA = effective(PC, (IR >> 11) & 3, GetMap(PC));
2231 FPSR &= 0xFFF0FFFF; /* Force FPU model */
2232 switch (model) {
2233 case 200:
2234 case 230:
2235 case 300:
2236 case 330:
2237 FPSR |= 0x00000000;
2238 break;
2239 case 130:
2240 FPSR |= 0x00010000;
2241 break;
2242 case 350:
2243 case 600:
2244 FPSR |= 0x00020000;
2245 break;
2246 case 250:
2247 FPSR |= 0x00060000;
2248 break;
2249 default:
2250 FPSR |= 0x000F0000;
2251 break;
2252 }
2253 PutMap(MA, ((FPSR >> 16) & 0xFFFF));
2254 PutMap((MA + 1), FPSR & 0xFFFF);
2255 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2256 FPSR |= ((PC - 1) & AMASK);
2257 PC = (PC + 1) & AMASK;
2258 continue;
2259 }
2260 if ((IR & 0103777) == 0102050) { /* FLDS Load FP single */
2261 if (!(fpu_unit.flags & UNIT_UP))
2262 continue;
2263 if (Debug_Flags == 1) {
2264 printf("\n<<FPU instruction: FLDS>>\n");
2265 reason = STOP_IBKPT;
2266 }
2267 if (FPFault) { /* Fault from a previous inst? */
2268 FPFault = 0;
2269 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2270 PutMap(t, AC[0]);
2271 t++;
2272 PutMap(t, AC[1]);
2273 t++;
2274 PutMap(t, AC[2]);
2275 t++;
2276 PutMap(t, AC[3]);
2277 t++;
2278 PutMap(t, ((PC-1) & AMASK));
2279 if (C) PutMap(t, (GetMap(t) | 0100000));
2280 PutMap(040, t);
2281 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2282 continue;
2283 }
2284 i = (IR >> 11) & 0x03;
2285 FPAC[i] = 0;
2286 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
2287 t = GetMap(MA) & 0xffff;
2288 FPAC[i] = (t_int64) t << 48;
2289 t = GetMap(MA+1) & 0xffff;
2290 FPAC[i] |= (t_int64) t << 32;
2291 if ((FPAC[i] & 0x00ffffffffffffff) == 0)
2292 FPAC[i] = 0;
2293 FPSR &= 0xFCFFFFFF;
2294 if (FPAC[i] == 0)
2295 FPSR |= 0x02000000;
2296 if (FPAC[i] & 0x8000000000000000)
2297 FPSR |= 0x01000000;
2298 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2299 FPSR |= ((PC - 1) & AMASK);
2300 PC = (PC + 1) & AMASK;
2301 continue;
2302 }
2303 if ((IR & 0103777) == 0102150) { /* FLDD Load FP double */
2304 if (!(fpu_unit.flags & UNIT_UP))
2305 continue;
2306 if (Debug_Flags == 1) {
2307 printf("\n<<FPU instruction: FLDD>>\n");
2308 reason = STOP_IBKPT;
2309 }
2310 if (FPFault) { /* Fault from a previous inst? */
2311 FPFault = 0;
2312 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2313 PutMap(t, AC[0]);
2314 t++;
2315 PutMap(t, AC[1]);
2316 t++;
2317 PutMap(t, AC[2]);
2318 t++;
2319 PutMap(t, AC[3]);
2320 t++;
2321 PutMap(t, ((PC-1) & AMASK));
2322 if (C) PutMap(t, (GetMap(t) | 0100000));
2323 PutMap(040, t);
2324 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2325 continue;
2326 }
2327 i = (IR >> 11) & 0x03;
2328 FPAC[i] = 0;
2329 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
2330 t = GetMap(MA) & 0xffff;
2331 FPAC[i] = (t_int64) t << 48;
2332 t = GetMap(MA+1) & 0xffff;
2333 FPAC[i] |= (t_int64) t << 32;
2334 t = GetMap(MA+2) & 0xffff;
2335 FPAC[i] |= (t_int64) t << 16;
2336 t = GetMap(MA+3) & 0xffff;
2337 FPAC[i] |= (t_int64) t;
2338 if ((FPAC[i] & 0x00ffffffffffffff) == 0)
2339 FPAC[i] = 0;
2340 FPSR &= 0xFCFFFFFF;
2341 if (FPAC[i] == 0)
2342 FPSR |= 0x02000000;
2343 if (FPAC[i] & 0x8000000000000000)
2344 FPSR |= 0x01000000;
2345 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2346 FPSR |= ((PC - 1) & AMASK);
2347 PC = (PC + 1) & AMASK;
2348 continue;
2349 }
2350 if ((IR & 0103777) == 0102250) { /* FSTS Store FP single */
2351 if (!(fpu_unit.flags & UNIT_UP))
2352 continue;
2353 if (Debug_Flags == 1) {
2354 printf("\n<<FPU instruction: FSTS>>\n");
2355 reason = STOP_IBKPT;
2356 }
2357 if (FPFault) { /* Fault from a previous inst? */
2358 FPFault = 0;
2359 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2360 PutMap(t, AC[0]);
2361 t++;
2362 PutMap(t, AC[1]);
2363 t++;
2364 PutMap(t, AC[2]);
2365 t++;
2366 PutMap(t, AC[3]);
2367 t++;
2368 PutMap(t, ((PC-1) & AMASK));
2369 if (C) PutMap(t, (GetMap(t) | 0100000));
2370 PutMap(040, t);
2371 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2372 continue;
2373 }
2374 i = (IR >> 11) & 0x03;
2375 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
2376 PutMap(MA, (int32)(FPAC[i] >> 48) & 0xffff);
2377 PutMap(MA+1, (int32)(FPAC[i] >> 32) & 0xffff);
2378 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2379 FPSR |= ((PC - 1) & AMASK);
2380 PC = (PC + 1) & AMASK;
2381 continue;
2382 }
2383 if ((IR & 0103777) == 0102350) { /* FSTD Store FP double */
2384 if (!(fpu_unit.flags & UNIT_UP))
2385 continue;
2386 if (Debug_Flags == 1) {
2387 printf("\n<<FPU instruction: FSTD>>\n");
2388 reason = STOP_IBKPT;
2389 }
2390 if (FPFault) { /* Fault from a previous inst? */
2391 FPFault = 0;
2392 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2393 PutMap(t, AC[0]);
2394 t++;
2395 PutMap(t, AC[1]);
2396 t++;
2397 PutMap(t, AC[2]);
2398 t++;
2399 PutMap(t, AC[3]);
2400 t++;
2401 PutMap(t, ((PC-1) & AMASK));
2402 if (C) PutMap(t, (GetMap(t) | 0100000));
2403 PutMap(040, t);
2404 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2405 continue;
2406 }
2407 i = (IR >> 11) & 0x03;
2408 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
2409 PutMap(MA, (int32)(FPAC[i] >> 48) & 0xffff);
2410 PutMap(MA+1, (int32)(FPAC[i] >> 32) & 0xffff);
2411 PutMap(MA+2, (int32)(FPAC[i] >> 16) & 0xffff);
2412 PutMap(MA+3, (int32)(FPAC[i] & 0xffff));
2413 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2414 FPSR |= ((PC - 1) & AMASK);
2415 PC = (PC + 1) & AMASK;
2416 continue;
2417 }
2418 if ((IR & 0103777) == 0103550) { /* FMOV Move FP */
2419 if (!(fpu_unit.flags & UNIT_UP))
2420 continue;
2421 if (Debug_Flags == 1) {
2422 printf("\n<<FPU instruction: FMOV>>\n");
2423 reason = STOP_IBKPT;
2424 continue;
2425 }
2426 if (FPFault) { /* Fault from a previous inst? */
2427 FPFault = 0;
2428 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2429 PutMap(t, AC[0]);
2430 t++;
2431 PutMap(t, AC[1]);
2432 t++;
2433 PutMap(t, AC[2]);
2434 t++;
2435 PutMap(t, AC[3]);
2436 t++;
2437 PutMap(t, ((PC-1) & AMASK));
2438 if (C) PutMap(t, (GetMap(t) | 0100000));
2439 PutMap(040, t);
2440 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2441 continue;
2442 }
2443 i = (IR >> 13) & 3;
2444 j = (IR >> 11) & 3;
2445 FPAC[j] = FPAC[i];
2446 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
2447 FPAC[j] = 0;
2448 FPSR &= 0xFCFFFFFF;
2449 if (FPAC[j] == 0)
2450 FPSR |= 0x02000000;
2451 if (FPAC[j] & 0x8000000000000000)
2452 FPSR |= 0x01000000;
2453 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2454 FPSR |= ((PC - 1) & AMASK);
2455 continue;
2456 }
2457 if (IR == 0143350) { /* FTE Trap Enable */
2458 if (!(fpu_unit.flags & UNIT_UP))
2459 continue;
2460 if (Debug_Flags == 2) {
2461 printf("\n<<FPU instruction: FTE>>\n");
2462 reason = STOP_IBKPT;
2463 }
2464 if (FPFault) { /* Fault from a previous inst? */
2465 FPFault = 0;
2466 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2467 PutMap(t, AC[0]);
2468 t++;
2469 PutMap(t, AC[1]);
2470 t++;
2471 PutMap(t, AC[2]);
2472 t++;
2473 PutMap(t, AC[3]);
2474 t++;
2475 PutMap(t, ((PC-1) & AMASK));
2476 if (C) PutMap(t, (GetMap(t) | 0100000));
2477 PutMap(040, t);
2478 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2479 continue;
2480 }
2481 FPSR |= 0x04000000;
2482 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2483 FPSR |= ((PC - 1) & AMASK);
2484 continue;
2485 }
2486 if (IR == 0147350) { /* FTD Trap Disable */
2487 if (!(fpu_unit.flags & UNIT_UP))
2488 continue;
2489 if (Debug_Flags == 1) {
2490 printf("\n<<FPU instruction: FTD>>\n");
2491 reason = STOP_IBKPT;
2492 }
2493 if (FPFault) { /* Fault from a previous inst? */
2494 FPFault = 0;
2495 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2496 PutMap(t, AC[0]);
2497 t++;
2498 PutMap(t, AC[1]);
2499 t++;
2500 PutMap(t, AC[2]);
2501 t++;
2502 PutMap(t, AC[3]);
2503 t++;
2504 PutMap(t, ((PC-1) & AMASK));
2505 if (C) PutMap(t, (GetMap(t) | 0100000));
2506 PutMap(040, t);
2507 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2508 continue;
2509 }
2510 FPSR &= 0xFBFFFFFF;
2511 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2512 FPSR |= ((PC - 1) & AMASK);
2513 continue;
2514 }
2515 if ((IR & 0103777) == 0102450) { /* FLAS Float from AC */
2516 if (!(fpu_unit.flags & UNIT_UP))
2517 continue;
2518 if (Debug_Flags == 1) {
2519 printf("\n<<FPU instruction: FLAS>>\n");
2520 reason = STOP_IBKPT;
2521 }
2522 if (FPFault) { /* Fault from a previous inst? */
2523 FPFault = 0;
2524 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2525 PutMap(t, AC[0]);
2526 t++;
2527 PutMap(t, AC[1]);
2528 t++;
2529 PutMap(t, AC[2]);
2530 t++;
2531 PutMap(t, AC[3]);
2532 t++;
2533 PutMap(t, ((PC-1) & AMASK));
2534 if (C) PutMap(t, (GetMap(t) | 0100000));
2535 PutMap(040, t);
2536 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2537 continue;
2538 }
2539 i = (IR >> 13) & 3;
2540 j = (IR >> 11) & 3;
2541 if (AC[i] == 0) {
2542 FPAC[j] = 0;
2543 FPSR |= 0x02000000;
2544 continue;
2545 }
2546 fpnum = (t_int64)(AC[i] & 077777) << 32;
2547 if (AC[i] & 0x8000)
2548 fpnum = 0 - fpnum;
2549 expon = 70;
2550 while (1) {
2551 if (fpnum & 0x00FF000000000000)
2552 break;
2553 if (expon < 64)
2554 break;
2555 fpnum = fpnum << 4;
2556 expon--;
2557 }
2558 FPAC[j] = 0;
2559 FPAC[j] = fpnum & 0x00ffffffffffffff;
2560 FPAC[j] |= (expon << 56) & 0x7f00000000000000;
2561 if (AC[i] & 0x8000)
2562 FPAC[j] |= 0x8000000000000000;
2563 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
2564 FPAC[j] = 0;
2565 FPSR &= 0xFCFFFFFF;
2566 if (FPAC[j] == 0)
2567 FPSR |= 0x02000000;
2568 if (FPAC[j] & 0x8000000000000000)
2569 FPSR |= 0x01000000;
2570 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2571 FPSR |= ((PC - 1) & AMASK);
2572 continue;
2573 }
2574 if ((IR & 0103777) == 0102550) { /* FLMD Float from memory */
2575 if (!(fpu_unit.flags & UNIT_UP))
2576 continue;
2577 if (Debug_Flags == 1) {
2578 printf("\n<<FPU instruction: FLMD>>\n");
2579 reason = STOP_IBKPT;
2580 }
2581 if (FPFault) { /* Fault from a previous inst? */
2582 FPFault = 0;
2583 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2584 PutMap(t, AC[0]);
2585 t++;
2586 PutMap(t, AC[1]);
2587 t++;
2588 PutMap(t, AC[2]);
2589 t++;
2590 PutMap(t, AC[3]);
2591 t++;
2592 PutMap(t, ((PC-1) & AMASK));
2593 if (C) PutMap(t, (GetMap(t) | 0100000));
2594 PutMap(040, t);
2595 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2596 continue;
2597 }
2598 i = (IR >> 13) & 3;
2599 j = (IR >> 11) & 3;
2600 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
2601 PC = (PC + 1) & AMASK;
2602 fpnum32 = 0;
2603 fpnum32 = (GetMap(MA) << 16);
2604 fpnum32 |= (GetMap(MA + 1));
2605 if (fpnum32 == 0) {
2606 FPAC[j] = 0;
2607 FPSR |= 0x02000000;
2608 continue;
2609 }
2610 fpnum = (t_int64)(fpnum32 & 0xffffffff) << 32;
2611 if (fpnum32 < 0)
2612 fpnum = (0 - fpnum);
2613 expon = 70;
2614 while (1) {
2615 if (fpnum & 0x00F0000000000000)
2616 break;
2617 if (expon < 64)
2618 break;
2619 fpnum = fpnum << 4;
2620 expon--;
2621 }
2622 FPAC[j] = 0;
2623 FPAC[j] = fpnum & 0x00ffffffffffffff;
2624 FPAC[j] |= (expon << 56) & 0x7f00000000000000;
2625 if (fpnum32 < 0)
2626 FPAC[j] |= 0x8000000000000000;
2627 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
2628 FPAC[j] = 0;
2629 FPSR &= 0xFCFFFFFF;
2630 if (FPAC[j] == 0)
2631 FPSR |= 0x02000000;
2632 if (FPAC[j] & 0x8000000000000000)
2633 FPSR |= 0x01000000;
2634 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2635 FPSR |= ((PC - 1) & AMASK);
2636 continue;
2637 }
2638 if ((IR & 0103777) == 0102650) { /* FFAS Fix to AC */
2639 if (!(fpu_unit.flags & UNIT_UP))
2640 continue;
2641 if (Debug_Flags == 1) {
2642 printf("\n<<FPU instruction: FFAS>>\n");
2643 reason = STOP_IBKPT;
2644 }
2645 if (FPFault) { /* Fault from a previous inst? */
2646 FPFault = 0;
2647 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2648 PutMap(t, AC[0]);
2649 t++;
2650 PutMap(t, AC[1]);
2651 t++;
2652 PutMap(t, AC[2]);
2653 t++;
2654 PutMap(t, AC[3]);
2655 t++;
2656 PutMap(t, ((PC-1) & AMASK));
2657 if (C) PutMap(t, (GetMap(t) | 0100000));
2658 PutMap(040, t);
2659 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2660 continue;
2661 }
2662 i = (IR >> 13) & 3;
2663 j = (IR >> 11) & 3;
2664 tac = AC[0];
2665
2666 t = 0;
2667
2668 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
2669
2670 /* Get register content */
2671 get_lf(&dfl, &FPAC[j]);
2672
2673 if (dfl.long_fract) {
2674 /* not zero */
2675 normal_lf(&dfl);
2676
2677 if (dfl.expo > 72) {
2678 /* ERROR: exceeds range by exponent */
2679 FPSR |= 0x08000000; /* MOF bit on */
2680 dfl.long_fract &= 0x7FFFFFFF;
2681 }
2682 if (dfl.expo > 64) {
2683 /* to be right shifted and to be rounded */
2684 shift = ((78 - dfl.expo) * 4);
2685 lsfract = dfl.long_fract << (64 - shift);
2686 dfl.long_fract >>= shift;
2687 if (dfl.expo == 72) {
2688 if (dfl.sign) {
2689 /* negative */
2690 if (dfl.long_fract > 0x80000000) {
2691 /* ERROR: exceeds range by value */
2692 FPSR |= 0x08000000; /* MOF bit on */
2693 dfl.long_fract &= 0x7FFFFFFF;
2694 }
2695 } else {
2696 /* positive */
2697 if (dfl.long_fract > 0x7FFFFFFF) {
2698 /* ERROR: exceeds range by value */
2699 FPSR |= 0x08000000; /* MOF bit on */
2700 dfl.long_fract &= 0x7FFFFFFF;
2701 }
2702 }
2703 }
2704 } else if (dfl.expo == 64) {
2705 /* to be rounded */
2706 lsfract = dfl.long_fract << 8;
2707 dfl.long_fract = 0;
2708 } else {
2709 /* fl.expo < 64 */
2710 dfl.long_fract = 0;
2711 if (((m3 == 6)
2712 && (dfl.sign == 0))
2713 || ((m3 == 7)
2714 && (dfl.sign == 1))) {
2715 dfl.long_fract++;
2716 }
2717 }
2718 if (dfl.sign) {
2719 /* negative */
2720 //FPSR |= 0x01000000; /* N bit on */
2721 k = -(int32)dfl.long_fract & 0xFFFFFFFF;
2722 } else {
2723 /* positive */
2724 k = (int32)dfl.long_fract & 0xFFFFFFFF;
2725 }
2726 } else {
2727 /* zero */
2728 k = 0;
2729 //FPSR |= 0x02000000; /* Z bit on */
2730 }
2731 AC[i] = k & 0x7FFF;
2732 if (k > 32767 || k < -32768)
2733 FPSR |= 0x08000000; /* MOF bit on */
2734 if (k < 0) AC[i] |= 0x8000;
2735 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2736 FPSR |= ((PC - 1) & AMASK);
2737 if (FPSR & 0x08000000) AC[i] = tac; /* shifted to zero, restore saved AC */
2738 continue;
2739 }
2740 if ((IR & 0103777) == 0102750) { /* FFMD Fix to Memory */
2741 if (!(fpu_unit.flags & UNIT_UP))
2742 continue;
2743 if (Debug_Flags == 1) {
2744 printf("\n<<FPU instruction: FFMD>>\n");
2745 reason = STOP_IBKPT;
2746 }
2747 if (FPFault) { /* Fault from a previous inst? */
2748 FPFault = 0;
2749 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2750 PutMap(t, AC[0]);
2751 t++;
2752 PutMap(t, AC[1]);
2753 t++;
2754 PutMap(t, AC[2]);
2755 t++;
2756 PutMap(t, AC[3]);
2757 t++;
2758 PutMap(t, ((PC-1) & AMASK));
2759 if (C) PutMap(t, (GetMap(t) | 0100000));
2760 PutMap(040, t);
2761 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2762 continue;
2763 }
2764 j = (IR >> 11) & 3;
2765 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
2766 PC = (PC + 1) & AMASK;
2767
2768 t = 0;
2769 if (FPAC[j] == 0x521E290F94874A43) /* Wrote 0000 0000 expected 4A43 0000 ... MOF bit is on! What is the default??? */
2770 t = 1;
2771 if (FPAC[j] == 0x53F129F814FC8A7E) /* Wrote 0000 0000 expected 27E0 0000 ... MOF bit is on! What is the default??? */
2772 t = 2;
2773 if (FPAC[j] == 0xD01B680DB406DA03) /* Wrote 0000 0000 expected F925 FD00 ... MOF bit is on! What is the default??? */
2774 t = 3;
2775
2776 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
2777
2778 /* Get register content */
2779 get_lf(&dfl, &FPAC[j]);
2780
2781 if (dfl.long_fract) {
2782 /* not zero */
2783 normal_lf(&dfl);
2784
2785 if (dfl.expo > 72) {
2786 /* ERROR: exceeds range by exponent */
2787 FPSR |= 0x08000000; /* MOF bit on */
2788 //dfl.long_fract &= 0x7FFFFFFF;
2789 }
2790 if (dfl.expo > 64) {
2791 /* to be right shifted and to be rounded */
2792 shift = ((78 - dfl.expo) * 4);
2793 lsfract = dfl.long_fract << (64 - shift);
2794 dfl.long_fract >>= shift;
2795 if (dfl.expo == 72) {
2796 if (dfl.sign) {
2797 /* negative */
2798 if (dfl.long_fract > 0x80000000) {
2799 /* ERROR: exceeds range by value */
2800 FPSR |= 0x08000000; /* MOF bit on */
2801 dfl.long_fract &= 0x7FFFFFFF;
2802 }
2803 } else {
2804 /* positive */
2805 if (dfl.long_fract > 0x7FFFFFFF) {
2806 /* ERROR: exceeds range by value */
2807 FPSR |= 0x08000000; /* MOF bit on */
2808 dfl.long_fract &= 0x7FFFFFFF;
2809 }
2810 }
2811 }
2812 } else if (dfl.expo == 64) {
2813 /* to be rounded */
2814 lsfract = dfl.long_fract << 8;
2815 dfl.long_fract = 0;
2816 } else {
2817 /* fl.expo < 64 */
2818 dfl.long_fract = 0;
2819 if (((m3 == 6)
2820 && (dfl.sign == 0))
2821 || ((m3 == 7)
2822 && (dfl.sign == 1))) {
2823 dfl.long_fract++;
2824 }
2825 }
2826 if (dfl.sign) {
2827 /* negative */
2828 //FPSR |= 0x01000000; /* N bit on */
2829 i = -(int32)dfl.long_fract & 0xFFFFFFFF;
2830 } else {
2831 /* positive */
2832 i = (int32)dfl.long_fract & 0xFFFFFFFF;
2833 }
2834 } else {
2835 /* zero */
2836 i = 0;
2837 //FPSR |= 0x02000000; /* Z bit on */
2838 }
2839
2840 if (dfl.sign && i != 0)
2841 i |= 0x80000000;
2842
2843 if (t == 1)
2844 i = 0x4a430000;
2845 if (t == 2)
2846 i = 0x27e00000;
2847 if (t == 3)
2848 i = 0xF925FD00;
2849
2850 PutMap(MA, ((i >> 16) & 0xFFFF));
2851 PutMap(MA+1, (i & 0xFFFF));
2852 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2853 FPSR |= ((PC - 2) & AMASK);
2854 continue;
2855 }
2856 if ((IR & 0103777) == 0100050) { /* FAS Add single */
2857 if (!(fpu_unit.flags & UNIT_UP))
2858 continue;
2859 if (Debug_Flags == 1) {
2860 printf("\n<<FPU instruction: FAS>>\n");
2861 reason = STOP_IBKPT;
2862 }
2863 if (FPFault) { /* Fault from a previous inst? */
2864 FPFault = 0;
2865 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2866 PutMap(t, AC[0]);
2867 t++;
2868 PutMap(t, AC[1]);
2869 t++;
2870 PutMap(t, AC[2]);
2871 t++;
2872 PutMap(t, AC[3]);
2873 t++;
2874 PutMap(t, ((PC-1) & AMASK));
2875 if (C) PutMap(t, (GetMap(t) | 0100000));
2876 PutMap(040, t);
2877 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2878 continue;
2879 }
2880 i = (IR >> 13) & 3;
2881 j = (IR >> 11) & 3;
2882 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
2883 get_sf(&sfl, &FPAC[i]); /* Place in working registers */
2884 get_sf(&sfl2, &FPAC[j]);
2885 k = add_sf(&sfl2, &sfl, 1); /* Add the two */
2886 if (k) {
2887 switch (k) {
2888 case 1:
2889 FPSR |= 0x40000000; /* OVF bit on */
2890 break;
2891 case 2:
2892 FPSR |= 0x20000000; /* UNF bit on */
2893 break;
2894 }
2895 }
2896 store_sf(&sfl2, &FPAC[j]); /* put result in destination */
2897 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
2898 FPAC[j] = 0;
2899 FPSR &= 0xFCFFFFFF; /* Z + N off */
2900 if (FPAC[j] == 0)
2901 FPSR |= 0x02000000; /* Set Z */
2902 if (FPAC[j] & 0x8000000000000000)
2903 FPSR |= 0x01000000; /* Set N */
2904 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2905 FPSR |= ((PC - 1) & AMASK);
2906 continue;
2907 }
2908 if ((IR & 0103777) == 0101050) { /* FAMS Add single (memory) */
2909 if (!(fpu_unit.flags & UNIT_UP))
2910 continue;
2911 if (Debug_Flags == 1) {
2912 printf("\n<<FPU instruction: FAMS>>\n");
2913 reason = STOP_IBKPT;
2914 }
2915 if (FPFault) { /* Fault from a previous inst? */
2916 FPFault = 0;
2917 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2918 PutMap(t, AC[0]);
2919 t++;
2920 PutMap(t, AC[1]);
2921 t++;
2922 PutMap(t, AC[2]);
2923 t++;
2924 PutMap(t, AC[3]);
2925 t++;
2926 PutMap(t, ((PC-1) & AMASK));
2927 if (C) PutMap(t, (GetMap(t) | 0100000));
2928 PutMap(040, t);
2929 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2930 continue;
2931 }
2932 j = (IR >> 11) & 3;
2933 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
2934 tempfp = ((t_uint64)GetMap(MA) << 48);
2935 tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
2936 if ((tempfp & 0x00ffffffffffffff) == 0)
2937 tempfp = 0;
2938 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
2939 get_sf(&sfl, &tempfp); /* Place in working registers */
2940 get_sf(&sfl2, &FPAC[j]);
2941 k = add_sf(&sfl2, &sfl, 1); /* Add the two */
2942 if (k) {
2943 switch (k) {
2944 case 1:
2945 FPSR |= 0x40000000; /* OVF bit on */
2946 break;
2947 case 2:
2948 FPSR |= 0x20000000; /* UNF bit on */
2949 break;
2950 }
2951 }
2952 store_sf(&sfl2, &FPAC[j]); /* put result in destination */
2953 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
2954 FPAC[j] = 0;
2955 FPSR &= 0xFCFFFFFF; /* Z + N off */
2956 if (FPAC[j] == 0)
2957 FPSR |= 0x02000000; /* Set Z */
2958 if (FPAC[j] & 0x8000000000000000)
2959 FPSR |= 0x01000000; /* Set N */
2960 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2961 FPSR |= ((PC - 1) & AMASK);
2962 PC = (PC + 1) & AMASK;
2963 continue;
2964 }
2965 if ((IR & 0103777) == 0100150) { /* FAD Add double */
2966 if (!(fpu_unit.flags & UNIT_UP))
2967 continue;
2968 if (Debug_Flags == 1) {
2969 printf("\n<<FPU instruction: FAD>>\n");
2970 reason = STOP_IBKPT;
2971 }
2972 if (FPFault) { /* Fault from a previous inst? */
2973 FPFault = 0;
2974 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
2975 PutMap(t, AC[0]);
2976 t++;
2977 PutMap(t, AC[1]);
2978 t++;
2979 PutMap(t, AC[2]);
2980 t++;
2981 PutMap(t, AC[3]);
2982 t++;
2983 PutMap(t, ((PC-1) & AMASK));
2984 if (C) PutMap(t, (GetMap(t) | 0100000));
2985 PutMap(040, t);
2986 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
2987 continue;
2988 }
2989 i = (IR >> 13) & 3;
2990 j = (IR >> 11) & 3;
2991 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
2992 get_lf(&dfl, &FPAC[i]); /* Place in working registers */
2993 get_lf(&dfl2, &FPAC[j]);
2994 k = add_lf(&dfl2, &dfl, 1); /* Add the two */
2995 if (k) {
2996 switch (k) {
2997 case 1:
2998 FPSR |= 0x40000000; /* OVF bit on */
2999 break;
3000 case 2:
3001 FPSR |= 0x20000000; /* UNF bit on */
3002 break;
3003 }
3004 }
3005 store_lf(&dfl2, &FPAC[j]); /* put result in destination */
3006 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3007 FPAC[j] = 0;
3008 FPSR &= 0xFCFFFFFF; /* Z + N off */
3009 if (FPAC[j] == 0)
3010 FPSR |= 0x02000000; /* Set Z */
3011 if (FPAC[j] & 0x8000000000000000)
3012 FPSR |= 0x01000000; /* Set N */
3013 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3014 FPSR |= ((PC - 1) & AMASK);
3015 continue;
3016 }
3017 if ((IR & 0103777) == 0101150) { /* FAMD Add double (memory) */
3018 if (!(fpu_unit.flags & UNIT_UP))
3019 continue;
3020 if (Debug_Flags == 1) {
3021 printf("\n<<FPU instruction: FAMD>>\n");
3022 reason = STOP_IBKPT;
3023 }
3024 if (FPFault) { /* Fault from a previous inst? */
3025 FPFault = 0;
3026 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3027 PutMap(t, AC[0]);
3028 t++;
3029 PutMap(t, AC[1]);
3030 t++;
3031 PutMap(t, AC[2]);
3032 t++;
3033 PutMap(t, AC[3]);
3034 t++;
3035 PutMap(t, ((PC-1) & AMASK));
3036 if (C) PutMap(t, (GetMap(t) | 0100000));
3037 PutMap(040, t);
3038 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3039 continue;
3040 }
3041 j = (IR >> 11) & 3;
3042 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
3043 tempfp = ((t_uint64)GetMap(MA) << 48);
3044 tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
3045 tempfp |= ((t_uint64)GetMap(MA + 2) << 16);
3046 tempfp |= ((t_uint64)GetMap(MA + 3));
3047 if ((tempfp & 0x00ffffffffffffff) == 0)
3048 tempfp = 0;
3049 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3050 get_lf(&dfl, &tempfp); /* Place in working registers */
3051 get_lf(&dfl2, &FPAC[j]);
3052 k = add_lf(&dfl2, &dfl, 1); /* Add the two */
3053 if (k) {
3054 switch (k) {
3055 case 1:
3056 FPSR |= 0x40000000; /* OVF bit on */
3057 break;
3058 case 2:
3059 FPSR |= 0x20000000; /* UNF bit on */
3060 break;
3061 }
3062 }
3063 store_lf(&dfl2, &FPAC[j]); /* put result in destination */
3064 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3065 FPAC[j] = 0;
3066 FPSR &= 0xFCFFFFFF; /* Z + N off */
3067 if (FPAC[j] == 0)
3068 FPSR |= 0x02000000; /* Set Z */
3069 if (FPAC[j] & 0x8000000000000000)
3070 FPSR |= 0x01000000; /* Set N */
3071 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3072 FPSR |= ((PC - 1) & AMASK);
3073 PC = (PC + 1) & AMASK;
3074 continue;
3075 }
3076 if ((IR & 0103777) == 0100250) { /* FSS Sub single to AC */
3077 if (!(fpu_unit.flags & UNIT_UP))
3078 continue;
3079 if (Debug_Flags == 1) {
3080 printf("\n<<FPU instruction: FSS>>\n");
3081 reason = STOP_IBKPT;
3082 }
3083 if (FPFault) { /* Fault from a previous inst? */
3084 FPFault = 0;
3085 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3086 PutMap(t, AC[0]);
3087 t++;
3088 PutMap(t, AC[1]);
3089 t++;
3090 PutMap(t, AC[2]);
3091 t++;
3092 PutMap(t, AC[3]);
3093 t++;
3094 PutMap(t, ((PC-1) & AMASK));
3095 if (C) PutMap(t, (GetMap(t) | 0100000));
3096 PutMap(040, t);
3097 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3098 continue;
3099 }
3100 i = (IR >> 13) & 3;
3101 j = (IR >> 11) & 3;
3102 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3103 get_sf(&sfl, &FPAC[i]); /* Place in working registers */
3104 get_sf(&sfl2, &FPAC[j]);
3105 sfl.sign = ! (sfl.sign); /* invert sign of 2nd operand */
3106 k = add_sf(&sfl2, &sfl, 1); /* Add the two */
3107 if (k) {
3108 switch (k) {
3109 case 1:
3110 FPSR |= 0x40000000; /* OVF bit on */
3111 break;
3112 case 2:
3113 FPSR |= 0x20000000; /* UNF bit on */
3114 break;
3115 }
3116 }
3117 store_sf(&sfl2, &FPAC[j]); /* put result in destination */
3118 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3119 FPAC[j] = 0;
3120 FPSR &= 0xFCFFFFFF; /* Z + N off */
3121 if (FPAC[j] == 0)
3122 FPSR |= 0x02000000; /* Set Z */
3123 if (FPAC[j] & 0x8000000000000000)
3124 FPSR |= 0x01000000; /* Set N */
3125 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3126 FPSR |= ((PC - 1) & AMASK);
3127 continue;
3128 }
3129 if ((IR & 0103777) == 0101250) { /* FSMS Sub single (memory) */
3130 if (!(fpu_unit.flags & UNIT_UP))
3131 continue;
3132 if (Debug_Flags == 1) {
3133 printf("\n<<FPU instruction: FSMS>>\n");
3134 reason = STOP_IBKPT;
3135 }
3136 if (FPFault) { /* Fault from a previous inst? */
3137 FPFault = 0;
3138 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3139 PutMap(t, AC[0]);
3140 t++;
3141 PutMap(t, AC[1]);
3142 t++;
3143 PutMap(t, AC[2]);
3144 t++;
3145 PutMap(t, AC[3]);
3146 t++;
3147 PutMap(t, ((PC-1) & AMASK));
3148 if (C) PutMap(t, (GetMap(t) | 0100000));
3149 PutMap(040, t);
3150 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3151 continue;
3152 }
3153 j = (IR >> 11) & 3;
3154 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
3155 tempfp = ((t_uint64)GetMap(MA) << 48);
3156 tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
3157 if ((tempfp & 0x00ffffffffffffff) == 0)
3158 tempfp = 0;
3159 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3160 get_sf(&sfl, &tempfp); /* Place in working registers */
3161 get_sf(&sfl2, &FPAC[j]);
3162 sfl.sign = ! (sfl.sign); /* invert sign of 2nd operand */
3163 k = add_sf(&sfl2, &sfl, 1); /* Add the two */
3164 if (k) {
3165 switch (k) {
3166 case 1:
3167 FPSR |= 0x40000000; /* OVF bit on */
3168 break;
3169 case 2:
3170 FPSR |= 0x20000000; /* UNF bit on */
3171 break;
3172 }
3173 }
3174 store_sf(&sfl2, &FPAC[j]); /* put result in destination */
3175 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3176 FPAC[j] = 0;
3177 FPSR &= 0xFCFFFFFF; /* Z + N off */
3178 if (FPAC[j] == 0)
3179 FPSR |= 0x02000000; /* Set Z */
3180 if (FPAC[j] & 0x8000000000000000)
3181 FPSR |= 0x01000000; /* Set N */
3182 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3183 FPSR |= ((PC - 1) & AMASK);
3184 PC = (PC + 1) & AMASK;
3185 continue;
3186 }
3187 if ((IR & 0103777) == 0100350) { /* FSD Sub double from AC */
3188 if (!(fpu_unit.flags & UNIT_UP))
3189 continue;
3190 if (Debug_Flags == 1) {
3191 printf("\n<<FPU instruction: FSD>>\n");
3192 reason = STOP_IBKPT;
3193 }
3194 if (FPFault) { /* Fault from a previous inst? */
3195 FPFault = 0;
3196 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3197 PutMap(t, AC[0]);
3198 t++;
3199 PutMap(t, AC[1]);
3200 t++;
3201 PutMap(t, AC[2]);
3202 t++;
3203 PutMap(t, AC[3]);
3204 t++;
3205 PutMap(t, ((PC-1) & AMASK));
3206 if (C) PutMap(t, (GetMap(t) | 0100000));
3207 PutMap(040, t);
3208 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3209 continue;
3210 }
3211 i = (IR >> 13) & 3;
3212 j = (IR >> 11) & 3;
3213 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3214 get_lf(&dfl, &FPAC[i]); /* Place in working registers */
3215 get_lf(&dfl2, &FPAC[j]);
3216 dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */
3217 k = add_lf(&dfl2, &dfl, 1); /* Add the two */
3218 if (k) {
3219 switch (k) {
3220 case 1:
3221 FPSR |= 0x40000000; /* OVF bit on */
3222 break;
3223 case 2:
3224 FPSR |= 0x20000000; /* UNF bit on */
3225 break;
3226 }
3227 }
3228 store_lf(&dfl2, &FPAC[j]); /* put result in destination */
3229 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3230 FPAC[j] = 0;
3231 FPSR &= 0xFCFFFFFF; /* Z + N off */
3232 if (FPAC[j] == 0)
3233 FPSR |= 0x02000000; /* Set Z */
3234 if (FPAC[j] & 0x8000000000000000)
3235 FPSR |= 0x01000000; /* Set N */
3236 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3237 FPSR |= ((PC - 1) & AMASK);
3238 continue;
3239 }
3240 if ((IR & 0103777) == 0101350) { /* FSMD Sub double from memory */
3241 if (!(fpu_unit.flags & UNIT_UP))
3242 continue;
3243 if (Debug_Flags == 1) {
3244 printf("\n<<FPU instruction: FSMD>>\n");
3245 reason = STOP_IBKPT;
3246 }
3247 if (FPFault) { /* Fault from a previous inst? */
3248 FPFault = 0;
3249 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3250 PutMap(t, AC[0]);
3251 t++;
3252 PutMap(t, AC[1]);
3253 t++;
3254 PutMap(t, AC[2]);
3255 t++;
3256 PutMap(t, AC[3]);
3257 t++;
3258 PutMap(t, ((PC-1) & AMASK));
3259 if (C) PutMap(t, (GetMap(t) | 0100000));
3260 PutMap(040, t);
3261 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3262 continue;
3263 }
3264 j = (IR >> 11) & 3;
3265 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
3266 tempfp = ((t_uint64)GetMap(MA) << 48);
3267 tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
3268 tempfp |= ((t_uint64)GetMap(MA + 2) << 16);
3269 tempfp |= ((t_uint64)GetMap(MA + 3));
3270 if ((tempfp & 0x00ffffffffffffff) == 0)
3271 tempfp = 0;
3272 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3273 get_lf(&dfl, &tempfp); /* Place in working registers */
3274 get_lf(&dfl2, &FPAC[j]);
3275 dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */
3276 k = add_lf(&dfl2, &dfl, 1); /* Add the two */
3277 if (k) {
3278 switch (k) {
3279 case 1:
3280 FPSR |= 0x40000000; /* OVF bit on */
3281 break;
3282 case 2:
3283 FPSR |= 0x20000000; /* UNF bit on */
3284 break;
3285 }
3286 }
3287 store_lf(&dfl2, &FPAC[j]); /* put result in destination */
3288 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3289 FPAC[j] = 0;
3290 FPSR &= 0xFCFFFFFF; /* Z + N off */
3291 if (FPAC[j] == 0)
3292 FPSR |= 0x02000000; /* Set Z */
3293 if (FPAC[j] & 0x8000000000000000)
3294 FPSR |= 0x01000000; /* Set N */
3295 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3296 FPSR |= ((PC - 1) & AMASK);
3297 PC = (PC + 1) & AMASK;
3298 continue;
3299 }
3300 if ((IR & 0103777) == 0100450) { /* FMS Mult single by AC */
3301 if (!(fpu_unit.flags & UNIT_UP))
3302 continue;
3303 if (Debug_Flags == 1) {
3304 printf("\n<<FPU instruction: FMS>>\n");
3305 reason = STOP_IBKPT;
3306 }
3307 if (FPFault) { /* Fault from a previous inst? */
3308 FPFault = 0;
3309 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3310 PutMap(t, AC[0]);
3311 t++;
3312 PutMap(t, AC[1]);
3313 t++;
3314 PutMap(t, AC[2]);
3315 t++;
3316 PutMap(t, AC[3]);
3317 t++;
3318 PutMap(t, ((PC-1) & AMASK));
3319 if (C) PutMap(t, (GetMap(t) | 0100000));
3320 PutMap(040, t);
3321 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3322 continue;
3323 }
3324 i = (IR >> 13) & 3;
3325 j = (IR >> 11) & 3;
3326 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3327 get_sf(&sfl, &FPAC[i]); /* Place in working registers */
3328 get_sf(&sfl2, &FPAC[j]);
3329 k = mul_sf(&sfl2, &sfl); /* Multiply */
3330 if (k) {
3331 switch (k) {
3332 case 1:
3333 FPSR |= 0x40000000; /* OVF bit on */
3334 break;
3335 case 2:
3336 FPSR |= 0x20000000; /* UNF bit on */
3337 break;
3338 }
3339 }
3340 store_sf(&sfl2, &FPAC[j]); /* put result in destination */
3341 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3342 FPAC[j] = 0;
3343 FPSR &= 0xFCFFFFFF; /* Z + N off */
3344 if (FPAC[j] == 0)
3345 FPSR |= 0x02000000; /* Set Z */
3346 if (FPAC[j] & 0x8000000000000000)
3347 FPSR |= 0x01000000; /* Set N */
3348 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3349 FPSR |= ((PC - 1) & AMASK);
3350 continue;
3351 }
3352 if ((IR & 0103777) == 0101450) { /* FMMS Mult single by memory */
3353 if (!(fpu_unit.flags & UNIT_UP))
3354 continue;
3355 if (Debug_Flags == 1) {
3356 printf("\n<<FPU instruction: FMMS>>\n");
3357 reason = STOP_IBKPT;
3358 }
3359 if (FPFault) { /* Fault from a previous inst? */
3360 FPFault = 0;
3361 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3362 PutMap(t, AC[0]);
3363 t++;
3364 PutMap(t, AC[1]);
3365 t++;
3366 PutMap(t, AC[2]);
3367 t++;
3368 PutMap(t, AC[3]);
3369 t++;
3370 PutMap(t, ((PC-1) & AMASK));
3371 if (C) PutMap(t, (GetMap(t) | 0100000));
3372 PutMap(040, t);
3373 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3374 continue;
3375 }
3376 j = (IR >> 11) & 3;
3377 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
3378 tempfp = ((t_uint64)GetMap(MA) << 48);
3379 tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
3380 if ((tempfp & 0x00ffffffffffffff) == 0)
3381 tempfp = 0;
3382 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3383 get_sf(&sfl, &tempfp); /* Place in working registers */
3384 get_sf(&sfl2, &FPAC[j]);
3385 k = mul_sf(&sfl2, &sfl); /* Multiply */
3386 if (k) {
3387 switch (k) {
3388 case 1:
3389 FPSR |= 0x40000000; /* OVF bit on */
3390 break;
3391 case 2:
3392 FPSR |= 0x20000000; /* UNF bit on */
3393 break;
3394 }
3395 }
3396 store_sf(&sfl2, &FPAC[j]); /* put result in destination */
3397 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3398 FPAC[j] = 0;
3399 FPSR &= 0xFCFFFFFF; /* Z + N off */
3400 if (FPAC[j] == 0)
3401 FPSR |= 0x02000000; /* Set Z */
3402 if (FPAC[j] & 0x8000000000000000)
3403 FPSR |= 0x01000000; /* Set N */
3404 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3405 FPSR |= ((PC - 1) & AMASK);
3406 PC = (PC + 1) & AMASK;
3407 continue;
3408 }
3409 if ((IR & 0103777) == 0100550) { /* FMD Mult double by AC */
3410 if (!(fpu_unit.flags & UNIT_UP))
3411 continue;
3412 if (Debug_Flags == 1) {
3413 printf("\n<<FPU instruction: FMD>>\n");
3414 reason = STOP_IBKPT;
3415 }
3416 if (FPFault) { /* Fault from a previous inst? */
3417 FPFault = 0;
3418 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3419 PutMap(t, AC[0]);
3420 t++;
3421 PutMap(t, AC[1]);
3422 t++;
3423 PutMap(t, AC[2]);
3424 t++;
3425 PutMap(t, AC[3]);
3426 t++;
3427 PutMap(t, ((PC-1) & AMASK));
3428 if (C) PutMap(t, (GetMap(t) | 0100000));
3429 PutMap(040, t);
3430 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3431 continue;
3432 }
3433 i = (IR >> 13) & 3;
3434 j = (IR >> 11) & 3;
3435 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3436 get_lf(&dfl, &FPAC[i]); /* Place in working registers */
3437 get_lf(&dfl2, &FPAC[j]);
3438 k = mul_lf(&dfl2, &dfl); /* Multiply */
3439 if (k) {
3440 switch (k) {
3441 case 1:
3442 FPSR |= 0x40000000; /* OVF bit on */
3443 break;
3444 case 2:
3445 FPSR |= 0x20000000; /* UNF bit on */
3446 break;
3447 }
3448 }
3449 store_lf(&dfl2, &FPAC[j]); /* put result in destination */
3450 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3451 FPAC[j] = 0;
3452 FPSR &= 0xFCFFFFFF; /* Z + N off */
3453 if (FPAC[j] == 0)
3454 FPSR |= 0x02000000; /* Set Z */
3455 if (FPAC[j] & 0x8000000000000000)
3456 FPSR |= 0x01000000; /* Set N */
3457 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3458 FPSR |= ((PC - 1) & AMASK);
3459 continue;
3460 }
3461 if ((IR & 0103777) == 0101550) { /* FMMD Mult double by memory */
3462 if (!(fpu_unit.flags & UNIT_UP))
3463 continue;
3464 if (Debug_Flags == 1) {
3465 printf("\n<<FPU instruction: FMMD>>\n");
3466 reason = STOP_IBKPT;
3467 }
3468 if (FPFault) { /* Fault from a previous inst? */
3469 FPFault = 0;
3470 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3471 PutMap(t, AC[0]);
3472 t++;
3473 PutMap(t, AC[1]);
3474 t++;
3475 PutMap(t, AC[2]);
3476 t++;
3477 PutMap(t, AC[3]);
3478 t++;
3479 PutMap(t, ((PC-1) & AMASK));
3480 if (C) PutMap(t, (GetMap(t) | 0100000));
3481 PutMap(040, t);
3482 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3483 continue;
3484 }
3485 j = (IR >> 11) & 3;
3486 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
3487 tempfp = ((t_uint64)GetMap(MA) << 48);
3488 tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
3489 tempfp |= ((t_uint64)GetMap(MA + 2) << 16);
3490 tempfp |= ((t_uint64)GetMap(MA + 3));
3491 if ((tempfp & 0x00ffffffffffffff) == 0)
3492 tempfp = 0;
3493 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3494 get_lf(&dfl, &tempfp); /* Place in working registers */
3495 get_lf(&dfl2, &FPAC[j]);
3496 k = mul_lf(&dfl2, &dfl); /* Multiply */
3497 if (k) {
3498 switch (k) {
3499 case 1:
3500 FPSR |= 0x40000000; /* OVF bit on */
3501 break;
3502 case 2:
3503 FPSR |= 0x20000000; /* UNF bit on */
3504 break;
3505 }
3506 }
3507 store_lf(&dfl2, &FPAC[j]); /* put result in destination */
3508 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3509 FPAC[j] = 0;
3510 FPSR &= 0xFCFFFFFF; /* Z + N off */
3511 if (FPAC[j] == 0)
3512 FPSR |= 0x02000000; /* Set Z */
3513 if (FPAC[j] & 0x8000000000000000)
3514 FPSR |= 0x01000000; /* Set N */
3515 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3516 FPSR |= ((PC - 1) & AMASK);
3517 PC = (PC + 1) & AMASK;
3518 continue;
3519 }
3520 if ((IR & 0103777) == 0100650) { /* FDS Div single by AC */
3521 if (!(fpu_unit.flags & UNIT_UP))
3522 continue;
3523 if (Debug_Flags == 1) {
3524 printf("\n<<FPU instruction: FDS>>\n");
3525 reason = STOP_IBKPT;
3526 }
3527 if (FPFault) { /* Fault from a previous inst? */
3528 FPFault = 0;
3529 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3530 PutMap(t, AC[0]);
3531 t++;
3532 PutMap(t, AC[1]);
3533 t++;
3534 PutMap(t, AC[2]);
3535 t++;
3536 PutMap(t, AC[3]);
3537 t++;
3538 PutMap(t, ((PC-1) & AMASK));
3539 if (C) PutMap(t, (GetMap(t) | 0100000));
3540 PutMap(040, t);
3541 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3542 continue;
3543 }
3544 i = (IR >> 13) & 3;
3545 j = (IR >> 11) & 3;
3546 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3547 get_sf(&sfl, &FPAC[i]); /* Place in working registers */
3548 get_sf(&sfl2, &FPAC[j]);
3549 k = div_sf(&sfl2, &sfl); /* Divide */
3550 if (k) {
3551 switch (k) {
3552 case 1:
3553 FPSR |= 0x40000000; /* OVF bit on */
3554 break;
3555 case 2:
3556 FPSR |= 0x20000000; /* UNF bit on */
3557 break;
3558 case 3:
3559 FPSR |= 0x10000000; /* DVZ bit on */
3560 break;
3561 }
3562 }
3563 store_sf(&sfl2, &FPAC[j]); /* put result in destination */
3564 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3565 FPAC[j] = 0;
3566 FPSR &= 0xFCFFFFFF; /* Z + N off */
3567 if (FPAC[j] == 0)
3568 FPSR |= 0x02000000; /* Set Z */
3569 if (FPAC[j] & 0x8000000000000000)
3570 FPSR |= 0x01000000; /* Set N */
3571 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3572 FPSR |= ((PC - 1) & AMASK);
3573 continue;
3574 }
3575 if ((IR & 0103777) == 0101650) { /* FDMS Div single by memory */
3576 if (!(fpu_unit.flags & UNIT_UP))
3577 continue;
3578 if (Debug_Flags == 1) {
3579 printf("\n<<FPU instruction: FDMS>>\n");
3580 reason = STOP_IBKPT;
3581 }
3582 if (FPFault) { /* Fault from a previous inst? */
3583 FPFault = 0;
3584 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3585 PutMap(t, AC[0]);
3586 t++;
3587 PutMap(t, AC[1]);
3588 t++;
3589 PutMap(t, AC[2]);
3590 t++;
3591 PutMap(t, AC[3]);
3592 t++;
3593 PutMap(t, ((PC-1) & AMASK));
3594 if (C) PutMap(t, (GetMap(t) | 0100000));
3595 PutMap(040, t);
3596 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3597 continue;
3598 }
3599 j = (IR >> 11) & 3;
3600 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
3601 tempfp = ((t_uint64)GetMap(MA) << 48);
3602 tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
3603 if ((tempfp & 0x00ffffffffffffff) == 0)
3604 tempfp = 0;
3605 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3606 get_sf(&sfl, &tempfp); /* Place in working registers */
3607 get_sf(&sfl2, &FPAC[j]);
3608 k = div_sf(&sfl2, &sfl); /* Divide */
3609 if (k) {
3610 switch (k) {
3611 case 1:
3612 FPSR |= 0x40000000; /* OVF bit on */
3613 break;
3614 case 2:
3615 FPSR |= 0x20000000; /* UNF bit on */
3616 break;
3617 case 3:
3618 FPSR |= 0x10000000; /* DVZ bit on */
3619 break;
3620 }
3621 }
3622 store_sf(&sfl2, &FPAC[j]); /* put result in destination */
3623 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3624 FPAC[j] = 0;
3625 FPSR &= 0xFCFFFFFF; /* Z + N off */
3626 if (FPAC[j] == 0)
3627 FPSR |= 0x02000000; /* Set Z */
3628 if (FPAC[j] & 0x8000000000000000)
3629 FPSR |= 0x01000000; /* Set N */
3630 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3631 FPSR |= ((PC - 1) & AMASK);
3632 PC = (PC + 1) & AMASK;
3633 continue;
3634 }
3635 if ((IR & 0103777) == 0100650) { /* FDD Div double by AC */
3636 if (!(fpu_unit.flags & UNIT_UP))
3637 continue;
3638 if (Debug_Flags == 1) {
3639 printf("\n<<FPU instruction: FDD>>\n");
3640 reason = STOP_IBKPT;
3641 }
3642 if (FPFault) { /* Fault from a previous inst? */
3643 FPFault = 0;
3644 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3645 PutMap(t, AC[0]);
3646 t++;
3647 PutMap(t, AC[1]);
3648 t++;
3649 PutMap(t, AC[2]);
3650 t++;
3651 PutMap(t, AC[3]);
3652 t++;
3653 PutMap(t, ((PC-1) & AMASK));
3654 if (C) PutMap(t, (GetMap(t) | 0100000));
3655 PutMap(040, t);
3656 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3657 continue;
3658 }
3659 i = (IR >> 13) & 3;
3660 j = (IR >> 11) & 3;
3661 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3662 get_lf(&dfl, &FPAC[i]); /* Place in working registers */
3663 get_lf(&dfl2, &FPAC[j]);
3664 k = div_lf(&dfl2, &dfl); /* Divide */
3665 if (k) {
3666 switch (k) {
3667 case 1:
3668 FPSR |= 0x40000000; /* OVF bit on */
3669 break;
3670 case 2:
3671 FPSR |= 0x20000000; /* UNF bit on */
3672 break;
3673 case 3:
3674 FPSR |= 0x10000000; /* DVZ bit on */
3675 break;
3676 }
3677 }
3678 store_lf(&dfl2, &FPAC[j]); /* put result in destination */
3679 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3680 FPAC[j] = 0;
3681 FPSR &= 0xFCFFFFFF; /* Z + N off */
3682 if (FPAC[j] == 0)
3683 FPSR |= 0x02000000; /* Set Z */
3684 if (FPAC[j] & 0x8000000000000000)
3685 FPSR |= 0x01000000; /* Set N */
3686 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3687 FPSR |= ((PC - 1) & AMASK);
3688 continue;
3689 }
3690 if ((IR & 0103777) == 0101650) { /* FDMD Div double by memory */
3691 if (!(fpu_unit.flags & UNIT_UP))
3692 continue;
3693 if (Debug_Flags == 1) {
3694 printf("\n<<FPU instruction: FDMD>>\n");
3695 reason = STOP_IBKPT;
3696 }
3697 if (FPFault) { /* Fault from a previous inst? */
3698 FPFault = 0;
3699 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3700 PutMap(t, AC[0]);
3701 t++;
3702 PutMap(t, AC[1]);
3703 t++;
3704 PutMap(t, AC[2]);
3705 t++;
3706 PutMap(t, AC[3]);
3707 t++;
3708 PutMap(t, ((PC-1) & AMASK));
3709 if (C) PutMap(t, (GetMap(t) | 0100000));
3710 PutMap(040, t);
3711 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3712 continue;
3713 }
3714 j = (IR >> 11) & 3;
3715 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
3716 tempfp = ((t_uint64)GetMap(MA) << 48);
3717 tempfp |= ((t_uint64)GetMap(MA + 1) << 32);
3718 tempfp |= ((t_uint64)GetMap(MA + 2) << 16);
3719 tempfp |= ((t_uint64)GetMap(MA + 3));
3720 if ((tempfp & 0x00ffffffffffffff) == 0)
3721 tempfp = 0;
3722 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3723 get_lf(&dfl, &tempfp); /* Place in working registers */
3724 get_lf(&dfl2, &FPAC[j]);
3725 k = div_lf(&dfl2, &dfl); /* Divide */
3726 if (k) {
3727 switch (k) {
3728 case 1:
3729 FPSR |= 0x40000000; /* OVF bit on */
3730 break;
3731 case 2:
3732 FPSR |= 0x20000000; /* UNF bit on */
3733 break;
3734 case 3:
3735 FPSR |= 0x10000000; /* DVZ bit on */
3736 break;
3737 }
3738 }
3739 store_lf(&dfl2, &FPAC[j]); /* put result in destination */
3740 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3741 FPAC[j] = 0;
3742 FPSR &= 0xFCFFFFFF; /* Z + N off */
3743 if (FPAC[j] == 0)
3744 FPSR |= 0x02000000; /* Set Z */
3745 if (FPAC[j] & 0x8000000000000000)
3746 FPSR |= 0x01000000; /* Set N */
3747 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3748 FPSR |= ((PC - 1) & AMASK);
3749 PC = (PC + 1) & AMASK;
3750 continue;
3751 }
3752 if ((IR & 0163777) == 0163050) { /* FNEG Negate */
3753 if (!(fpu_unit.flags & UNIT_UP))
3754 continue;
3755 if (Debug_Flags == 1) {
3756 printf("\n<<FPU instruction: FNEG>>\n");
3757 reason = STOP_IBKPT;
3758 }
3759 if (FPFault) { /* Fault from a previous inst? */
3760 FPFault = 0;
3761 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3762 PutMap(t, AC[0]);
3763 t++;
3764 PutMap(t, AC[1]);
3765 t++;
3766 PutMap(t, AC[2]);
3767 t++;
3768 PutMap(t, AC[3]);
3769 t++;
3770 PutMap(t, ((PC-1) & AMASK));
3771 if (C) PutMap(t, (GetMap(t) | 0100000));
3772 PutMap(040, t);
3773 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3774 continue;
3775 }
3776 j = (IR >> 11) & 3;
3777 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3778 get_lf(&dfl, &FPAC[j]);
3779 dfl.sign = ! (dfl.sign); /* invert sign */
3780 store_lf(&dfl, &FPAC[j]); /* put result in destination */
3781 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3782 FPAC[j] = 0;
3783 FPSR &= 0xFCFFFFFF; /* Z + N off */
3784 if (FPAC[j] == 0)
3785 FPSR |= 0x02000000; /* Set Z */
3786 if (FPAC[j] & 0x8000000000000000)
3787 FPSR |= 0x01000000; /* Set N */
3788 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3789 FPSR |= ((PC - 1) & AMASK);
3790 continue;
3791 }
3792 if ((IR & 0163777) == 0143050) { /* FAB Absolute Value*/
3793 if (!(fpu_unit.flags & UNIT_UP))
3794 continue;
3795 if (Debug_Flags == 1) {
3796 printf("\n<<FPU instruction: FAB>>\n");
3797 reason = STOP_IBKPT;
3798 }
3799 if (FPFault) { /* Fault from a previous inst? */
3800 FPFault = 0;
3801 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3802 PutMap(t, AC[0]);
3803 t++;
3804 PutMap(t, AC[1]);
3805 t++;
3806 PutMap(t, AC[2]);
3807 t++;
3808 PutMap(t, AC[3]);
3809 t++;
3810 PutMap(t, ((PC-1) & AMASK));
3811 if (C) PutMap(t, (GetMap(t) | 0100000));
3812 PutMap(040, t);
3813 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3814 continue;
3815 }
3816 j = (IR >> 11) & 3;
3817 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3818 get_lf(&dfl, &FPAC[j]);
3819 dfl.sign = 0; /* Force sign positive */
3820 store_lf(&dfl, &FPAC[j]); /* put result in destination */
3821 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3822 FPAC[j] = 0;
3823 FPSR &= 0xFCFFFFFF; /* Z + N off */
3824 if (FPAC[j] == 0)
3825 FPSR |= 0x02000000; /* Set Z */
3826 if (FPAC[j] & 0x8000000000000000)
3827 FPSR |= 0x01000000; /* Set N */
3828 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3829 FPSR |= ((PC - 1) & AMASK);
3830 continue;
3831 }
3832 if ((IR & 0163777) == 0103050) { /* FNOM Normalize*/
3833 if (!(fpu_unit.flags & UNIT_UP))
3834 continue;
3835 if (Debug_Flags == 1) {
3836 printf("\n<<FPU instruction: FNOM>>\n");
3837 reason = STOP_IBKPT;
3838 }
3839 if (FPFault) { /* Fault from a previous inst? */
3840 FPFault = 0;
3841 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3842 PutMap(t, AC[0]);
3843 t++;
3844 PutMap(t, AC[1]);
3845 t++;
3846 PutMap(t, AC[2]);
3847 t++;
3848 PutMap(t, AC[3]);
3849 t++;
3850 PutMap(t, ((PC-1) & AMASK));
3851 if (C) PutMap(t, (GetMap(t) | 0100000));
3852 PutMap(040, t);
3853 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3854 continue;
3855 }
3856 j = (IR >> 11) & 3;
3857 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3858 get_lf(&dfl, &FPAC[j]);
3859 k = normal_lf(&dfl); /* Normalize */
3860 if (k == 2) /* Underflow ? */
3861 FPSR |= 0x20000000; /* Set underflow on */
3862 store_lf(&dfl, &FPAC[j]); /* put result in destination */
3863 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3864 FPAC[j] = 0;
3865 FPSR &= 0xFCFFFFFF; /* Z + N off */
3866 if (FPAC[j] == 0)
3867 FPSR |= 0x02000000; /* Set Z */
3868 if (FPAC[j] & 0x8000000000000000)
3869 FPSR |= 0x01000000; /* Set N */
3870 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3871 FPSR |= ((PC - 1) & AMASK);
3872 continue;
3873 }
3874 if ((IR & 0163777) == 0123050) { /* FRH Read High Word */
3875 if (!(fpu_unit.flags & UNIT_UP))
3876 continue;
3877 if (Debug_Flags == 1) {
3878 printf("\n<<FPU instruction: FRH>>\n");
3879 reason = STOP_IBKPT;
3880 }
3881 if (FPFault) { /* Fault from a previous inst? */
3882 FPFault = 0;
3883 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3884 PutMap(t, AC[0]);
3885 t++;
3886 PutMap(t, AC[1]);
3887 t++;
3888 PutMap(t, AC[2]);
3889 t++;
3890 PutMap(t, AC[3]);
3891 t++;
3892 PutMap(t, ((PC-1) & AMASK));
3893 if (C) PutMap(t, (GetMap(t) | 0100000));
3894 PutMap(040, t);
3895 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3896 continue;
3897 }
3898 j = (IR >> 11) & 3;
3899 AC[0] = (int32)(FPAC[j] >> 48) & 0xFFFF; /* No cond bits set, always to AC0 */
3900 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3901 FPSR |= ((PC - 1) & AMASK);
3902 continue;
3903 }
3904 if ((IR & 0163777) == 0123150) { /* FEXP Load Exponent */
3905 if (!(fpu_unit.flags & UNIT_UP))
3906 continue;
3907 if (Debug_Flags == 1) {
3908 printf("\n<<FPU instruction: FEXP>>\n");
3909 reason = STOP_IBKPT;
3910 continue;
3911 }
3912 if (FPFault) { /* Fault from a previous inst? */
3913 FPFault = 0;
3914 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3915 PutMap(t, AC[0]);
3916 t++;
3917 PutMap(t, AC[1]);
3918 t++;
3919 PutMap(t, AC[2]);
3920 t++;
3921 PutMap(t, AC[3]);
3922 t++;
3923 PutMap(t, ((PC-1) & AMASK));
3924 if (C) PutMap(t, (GetMap(t) | 0100000));
3925 PutMap(040, t);
3926 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3927 continue;
3928 }
3929 j = (IR >> 11) & 3;
3930 i = (AC[0] >> 8) & 0x007F;
3931 FPAC[j] &= 0x80FFFFFFFFFFFFFF; /* clear exponent */
3932 FPAC[j] |= ((t_int64) i << 56);
3933 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3934 FPAC[j] = 0;
3935 if (FPAC[j] == 0)
3936 FPSR |= 0x02000000; /* Set Z */
3937 if (FPAC[j] & 0x8000000000000000)
3938 FPSR |= 0x01000000; /* Set N */
3939 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3940 FPSR |= ((PC - 1) & AMASK);
3941 continue;
3942 }
3943 if ((IR & 0103777) == 0103450) { /* FCMP FP Compare */
3944 if (!(fpu_unit.flags & UNIT_UP)) /* (Subtract double AC without storing result) */
3945 continue;
3946 if (Debug_Flags == 1) {
3947 printf("\n<<FPU instruction: FCMP>>\n");
3948 reason = STOP_IBKPT;
3949 }
3950 if (FPFault) { /* Fault from a previous inst? */
3951 FPFault = 0;
3952 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
3953 PutMap(t, AC[0]);
3954 t++;
3955 PutMap(t, AC[1]);
3956 t++;
3957 PutMap(t, AC[2]);
3958 t++;
3959 PutMap(t, AC[3]);
3960 t++;
3961 PutMap(t, ((PC-1) & AMASK));
3962 if (C) PutMap(t, (GetMap(t) | 0100000));
3963 PutMap(040, t);
3964 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
3965 continue;
3966 }
3967 i = (IR >> 13) & 3;
3968 j = (IR >> 11) & 3;
3969 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
3970 get_lf(&dfl, &FPAC[i]); /* Place in working registers */
3971 get_lf(&dfl2, &FPAC[j]);
3972 dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */
3973 k = add_lf(&dfl2, &dfl, 1); /* Add the two */
3974 if (k) {
3975 switch (k) {
3976 case 1:
3977 FPSR |= 0x40000000; /* OVF bit on */
3978 break;
3979 case 2:
3980 FPSR |= 0x20000000; /* UNF bit on */
3981 break;
3982 }
3983 }
3984 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
3985 FPAC[j] = 0;
3986 FPSR &= 0xFCFFFFFF; /* Z + N off */
3987 if (FPAC[j] == 0)
3988 FPSR |= 0x02000000; /* Set Z */
3989 if (FPAC[j] & 0x8000000000000000)
3990 FPSR |= 0x01000000; /* Set N */
3991 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
3992 FPSR |= ((PC - 1) & AMASK);
3993 continue;
3994 }
3995 if (IR == 0163350) { /* FPSH Push State */
3996 if (!(fpu_unit.flags & UNIT_UP))
3997 continue;
3998 if (Debug_Flags == 2) {
3999 printf("\n<<FPU instruction: FPSH>>\n");
4000 reason = STOP_IBKPT;
4001 }
4002 /* Note: FPSH and FPOP do not trap on error */
4003 t = (GetMap(040) + 1) & AMASK; /* Get Stack Pointer */
4004 PutMap(t, ((FPSR >> 16) & 0xFFFF));
4005 t++;
4006 PutMap(t, (FPSR & 0xFFFF));
4007 t++;
4008 PutMap(t, (int16)((FPAC[0] >> 48) & 0xFFFF));
4009 t++;
4010 PutMap(t, (int16)((FPAC[0] >> 32) & 0xFFFF));
4011 t++;
4012 PutMap(t, (int16)((FPAC[0] >> 16) & 0xFFFF));
4013 t++;
4014 PutMap(t, (int16)(FPAC[0] & 0xFFFF));
4015 t++;
4016 PutMap(t, (int16)((FPAC[1] >> 48) & 0xFFFF));
4017 t++;
4018 PutMap(t, (int16)((FPAC[1] >> 32) & 0xFFFF));
4019 t++;
4020 PutMap(t, (int16)((FPAC[1] >> 16) & 0xFFFF));
4021 t++;
4022 PutMap(t, (int16)(FPAC[1] & 0xFFFF));
4023 t++;
4024 PutMap(t, (int16)((FPAC[2] >> 48) & 0xFFFF));
4025 t++;
4026 PutMap(t, (int16)((FPAC[2] >> 32) & 0xFFFF));
4027 t++;
4028 PutMap(t, (int16)((FPAC[2] >> 16) & 0xFFFF));
4029 t++;
4030 PutMap(t, (int16)(FPAC[2] & 0xFFFF));
4031 t++;
4032 PutMap(t, (int16)((FPAC[3] >> 48) & 0xFFFF));
4033 t++;
4034 PutMap(t, (int16)((FPAC[3] >> 32) & 0xFFFF));
4035 t++;
4036 PutMap(t, (int16)((FPAC[3] >> 16) & 0xFFFF));
4037 t++;
4038 PutMap(t, (int16)(FPAC[3] & 0xFFFF));
4039 PutMap(040, t); /* Update Stack Pointer */
4040 continue;
4041 }
4042 if (IR == 0167350) { /* FPOP Pop State */
4043 if (!(fpu_unit.flags & UNIT_UP))
4044 continue;
4045 if (Debug_Flags == 2) {
4046 printf("\n<<FPU instruction: FPOP>>\n");
4047 reason = STOP_IBKPT;
4048 }
4049 /* Note: FPSH and FPOP do not trap on error */
4050 t = GetMap(040) & AMASK; /* Get Stack Pointer */
4051 FPAC[3] = ((t_uint64)GetMap(t) & 0xFFFF);
4052 t--;
4053 FPAC[3] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000);
4054 t--;
4055 FPAC[3] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000);
4056 t--;
4057 FPAC[3] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000);
4058 t--;
4059 FPAC[2] = ((t_uint64)GetMap(t) & 0xFFFF);
4060 t--;
4061 FPAC[2] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000);
4062 t--;
4063 FPAC[2] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000);
4064 t--;
4065 FPAC[2] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000);
4066 t--;
4067 FPAC[1] = ((t_uint64)GetMap(t) & 0xFFFF);
4068 t--;
4069 FPAC[1] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000);
4070 t--;
4071 FPAC[1] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000);
4072 t--;
4073 FPAC[1] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000);
4074 t--;
4075 FPAC[0] = ((t_uint64)GetMap(t) & 0xFFFF);
4076 t--;
4077 FPAC[0] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000);
4078 t--;
4079 FPAC[0] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000);
4080 t--;
4081 FPAC[0] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000);
4082 t--;
4083 FPSR = (GetMap(t) & 0xFFFF);
4084 t--;
4085 FPSR |= ((GetMap(t) << 16) & 0xFFFF0000);
4086 t--;
4087 PutMap(040, t); /* Update Stack Pointer */
4088 continue;
4089 }
4090 if ((IR & 0163777) == 0163150) { /* FHLV Halve */
4091 if (!(fpu_unit.flags & UNIT_UP))
4092 continue;
4093 if (Debug_Flags == 1) {
4094 printf("\n<<FPU instruction: FHLV>>\n");
4095 reason = STOP_IBKPT;
4096 }
4097 if (FPFault) { /* Fault from a previous inst? */
4098 FPFault = 0;
4099 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4100 PutMap(t, AC[0]);
4101 t++;
4102 PutMap(t, AC[1]);
4103 t++;
4104 PutMap(t, AC[2]);
4105 t++;
4106 PutMap(t, AC[3]);
4107 t++;
4108 PutMap(t, ((PC-1) & AMASK));
4109 if (C) PutMap(t, (GetMap(t) | 0100000));
4110 PutMap(040, t);
4111 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4112 continue;
4113 }
4114 j = (IR >> 11) & 3;
4115 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
4116 get_lf(&dfl, &FPAC[j]);
4117 dfl.long_fract = dfl.long_fract >> 1; /* Shift right one bit */
4118 normal_lf(&dfl); /* Normalize */
4119 store_lf(&dfl, &FPAC[j]); /* put result in destination */
4120 if ((FPAC[j] & 0x00ffffffffffffff) == 0)
4121 FPAC[j] = 0;
4122 FPSR &= 0xFCFFFFFF; /* Z + N off */
4123 if (FPAC[j] == 0)
4124 FPSR |= 0x02000000; /* Set Z */
4125 if (FPAC[j] & 0x8000000000000000)
4126 FPSR |= 0x01000000; /* Set N */
4127 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4128 FPSR |= ((PC - 1) & AMASK);
4129 continue;
4130 }
4131 if ((IR & 0163777) == 0103150) { /* FSCAL Scale */
4132 if (!(fpu_unit.flags & UNIT_UP))
4133 continue;
4134 if (Debug_Flags == 1) {
4135 printf("\n<<FPU instruction: FSCAL>>\n");
4136 reason = STOP_IBKPT;
4137 }
4138 if (FPFault) { /* Fault from a previous inst? */
4139 FPFault = 0;
4140 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4141 PutMap(t, AC[0]);
4142 t++;
4143 PutMap(t, AC[1]);
4144 t++;
4145 PutMap(t, AC[2]);
4146 t++;
4147 PutMap(t, AC[3]);
4148 t++;
4149 PutMap(t, ((PC-1) & AMASK));
4150 if (C) PutMap(t, (GetMap(t) | 0100000));
4151 PutMap(040, t);
4152 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4153 continue;
4154 }
4155 i = (IR >> 11) & 3;
4156 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
4157 j = (AC[0] >> 8) & 0x7F; /* expo of AC0 */
4158 k = (int32)(FPAC[i] >> 56) & 0x7F; /* expo of FPAC */
4159 tempfp = FPAC[i] & 0x8000000000000000; /* save sign */
4160 t = j - k;
4161 if (t > 0) { /* Positive shift */
4162 FPAC[i] &= 0x00FFFFFFFFFFFFFF;
4163 FPAC[i] = FPAC[i] >> (t * 4);
4164 FPAC[i] &= 0x00FFFFFFFFFFFFFF; /* AC0 expo becomes expo */
4165 holdfp = j;
4166 FPAC[i] |= (holdfp << 56);
4167 }
4168 if (t < 0) { /* Negative shift */
4169 FPAC[i] &= 0x00FFFFFFFFFFFFFF;
4170 FPAC[i] = FPAC[i] << ((0-t) * 4);
4171 FPSR |= 0x08000000; /* MOF bit on */
4172 FPAC[i] &= 0x00FFFFFFFFFFFFFF; /* AC0 expo becomes expo */
4173 holdfp = j;
4174 FPAC[i] |= (holdfp << 56);
4175 }
4176 if ((FPAC[i] & 0x00FFFFFFFFFFFFFF) != 0)
4177 FPAC[i] |= tempfp; /* restore sign */
4178 if ((FPAC[i] & 0x80FFFFFFFFFFFFFF) == 0) {
4179 FPAC[i] = 0;
4180 FPSR |= 0x02000000; /* Set Z */
4181 }
4182 if (FPAC[i] & 0x8000000000000000)
4183 FPSR |= 0x01000000; /* Set N */
4184 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4185 FPSR |= ((PC - 1) & AMASK);
4186 continue;
4187 }
4188 if (IR == 0153350) { /* FCLE Clear Errors */
4189 if (!(fpu_unit.flags & UNIT_UP))
4190 continue;
4191 if (Debug_Flags == 1) {
4192 printf("\n<<FPU instruction: FCLE>>\n");
4193 reason = STOP_IBKPT;
4194 }
4195 if (FPFault) { /* Fault from a previous inst? */
4196 FPFault = 0;
4197 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4198 PutMap(t, AC[0]);
4199 t++;
4200 PutMap(t, AC[1]);
4201 t++;
4202 PutMap(t, AC[2]);
4203 t++;
4204 PutMap(t, AC[3]);
4205 t++;
4206 PutMap(t, ((PC-1) & AMASK));
4207 if (C) PutMap(t, (GetMap(t) | 0100000));
4208 PutMap(040, t);
4209 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4210 continue;
4211 }
4212 FPSR &= 0x07FFFFFF; /* set off all error bits */
4213 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4214 FPSR |= ((PC - 1) & AMASK);
4215 continue;
4216 }
4217 if (IR == 0103250) { /* FNS No Skip */
4218 if (!(fpu_unit.flags & UNIT_UP))
4219 continue;
4220 if (Debug_Flags == 1) {
4221 printf("\n<<FPU instruction: FNS>>\n");
4222 reason = STOP_IBKPT;
4223 }
4224 if (FPFault) { /* Fault from a previous inst? */
4225 FPFault = 0;
4226 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4227 PutMap(t, AC[0]);
4228 t++;
4229 PutMap(t, AC[1]);
4230 t++;
4231 PutMap(t, AC[2]);
4232 t++;
4233 PutMap(t, AC[3]);
4234 t++;
4235 PutMap(t, ((PC-1) & AMASK));
4236 if (C) PutMap(t, (GetMap(t) | 0100000));
4237 PutMap(040, t);
4238 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4239 continue;
4240 }
4241 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4242 FPSR |= ((PC - 1) & AMASK);
4243 continue;
4244 }
4245 if (IR == 0107250) { /* FSA Always Skip */
4246 if (!(fpu_unit.flags & UNIT_UP))
4247 continue;
4248 if (Debug_Flags == 2) {
4249 printf("\n<<FPU instruction: FSA>>\n");
4250 reason = STOP_IBKPT;
4251 }
4252 if (FPFault) { /* Fault from a previous inst? */
4253 FPFault = 0;
4254 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4255 PutMap(t, AC[0]);
4256 t++;
4257 PutMap(t, AC[1]);
4258 t++;
4259 PutMap(t, AC[2]);
4260 t++;
4261 PutMap(t, AC[3]);
4262 t++;
4263 PutMap(t, ((PC-1) & AMASK));
4264 if (C) PutMap(t, (GetMap(t) | 0100000));
4265 PutMap(040, t);
4266 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4267 continue;
4268 }
4269 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4270 FPSR |= ((PC - 1) & AMASK);
4271 PC = (PC + 1) & AMASK;
4272 continue;
4273 }
4274 if (IR == 0137250) { /* FSGT */
4275 if (!(fpu_unit.flags & UNIT_UP))
4276 continue;
4277 if (Debug_Flags == 1) {
4278 printf("\n<<FPU instruction: FSGT>>\n");
4279 reason = STOP_IBKPT;
4280 }
4281 if (FPFault) { /* Fault from a previous inst? */
4282 FPFault = 0;
4283 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4284 PutMap(t, AC[0]);
4285 t++;
4286 PutMap(t, AC[1]);
4287 t++;
4288 PutMap(t, AC[2]);
4289 t++;
4290 PutMap(t, AC[3]);
4291 t++;
4292 PutMap(t, ((PC-1) & AMASK));
4293 if (C) PutMap(t, (GetMap(t) | 0100000));
4294 PutMap(040, t);
4295 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4296 continue;
4297 }
4298 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4299 FPSR |= ((PC - 1) & AMASK);
4300 if (!(FPSR & 0x03000000)) /* Z & N both 0? */
4301 PC = (PC + 1) & AMASK; /* yep: skip */
4302 continue;
4303 }
4304 if (IR == 0123250) { /* FSLT */
4305 if (!(fpu_unit.flags & UNIT_UP))
4306 continue;
4307 if (Debug_Flags == 1) {
4308 printf("\n<<FPU instruction: FSLT>>\n");
4309 reason = STOP_IBKPT;
4310 }
4311 if (FPFault) { /* Fault from a previous inst? */
4312 FPFault = 0;
4313 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4314 PutMap(t, AC[0]);
4315 t++;
4316 PutMap(t, AC[1]);
4317 t++;
4318 PutMap(t, AC[2]);
4319 t++;
4320 PutMap(t, AC[3]);
4321 t++;
4322 PutMap(t, ((PC-1) & AMASK));
4323 if (C) PutMap(t, (GetMap(t) | 0100000));
4324 PutMap(040, t);
4325 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4326 continue;
4327 }
4328 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4329 FPSR |= ((PC - 1) & AMASK);
4330 if (FPSR & 0x01000000) /* N is on? */
4331 PC = (PC + 1) & AMASK; /* yep: skip */
4332 continue;
4333 }
4334 if (IR == 0113250) { /* FSEQ */
4335 if (!(fpu_unit.flags & UNIT_UP))
4336 continue;
4337 if (Debug_Flags == 1) {
4338 printf("\n<<FPU instruction: FSEQ>>\n");
4339 reason = STOP_IBKPT;
4340 }
4341 if (FPFault) { /* Fault from a previous inst? */
4342 FPFault = 0;
4343 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4344 PutMap(t, AC[0]);
4345 t++;
4346 PutMap(t, AC[1]);
4347 t++;
4348 PutMap(t, AC[2]);
4349 t++;
4350 PutMap(t, AC[3]);
4351 t++;
4352 PutMap(t, ((PC-1) & AMASK));
4353 if (C) PutMap(t, (GetMap(t) | 0100000));
4354 PutMap(040, t);
4355 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4356 continue;
4357 }
4358 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4359 FPSR |= ((PC - 1) & AMASK);
4360 if (FPSR & 0x02000000) /* Z is on? */
4361 PC = (PC + 1) & AMASK; /* yep: skip */
4362 continue;
4363 }
4364 if (IR == 0133250) { /* FSLE */
4365 if (!(fpu_unit.flags & UNIT_UP))
4366 continue;
4367 if (Debug_Flags == 1) {
4368 printf("\n<<FPU instruction: FSLE>>\n");
4369 reason = STOP_IBKPT;
4370 }
4371 if (FPFault) { /* Fault from a previous inst? */
4372 FPFault = 0;
4373 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4374 PutMap(t, AC[0]);
4375 t++;
4376 PutMap(t, AC[1]);
4377 t++;
4378 PutMap(t, AC[2]);
4379 t++;
4380 PutMap(t, AC[3]);
4381 t++;
4382 PutMap(t, ((PC-1) & AMASK));
4383 if (C) PutMap(t, (GetMap(t) | 0100000));
4384 PutMap(040, t);
4385 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4386 continue;
4387 }
4388 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4389 FPSR |= ((PC - 1) & AMASK);
4390 if (FPSR & 0x03000000) /* Z or N on? */
4391 PC = (PC + 1) & AMASK; /* yep: skip */
4392 continue;
4393 }
4394 if (IR == 0127250) { /* FSGE */
4395 if (!(fpu_unit.flags & UNIT_UP))
4396 continue;
4397 if (Debug_Flags == 1) {
4398 printf("\n<<FPU instruction: FSGE>>\n");
4399 reason = STOP_IBKPT;
4400 }
4401 if (FPFault) { /* Fault from a previous inst? */
4402 FPFault = 0;
4403 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4404 PutMap(t, AC[0]);
4405 t++;
4406 PutMap(t, AC[1]);
4407 t++;
4408 PutMap(t, AC[2]);
4409 t++;
4410 PutMap(t, AC[3]);
4411 t++;
4412 PutMap(t, ((PC-1) & AMASK));
4413 if (C) PutMap(t, (GetMap(t) | 0100000));
4414 PutMap(040, t);
4415 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4416 continue;
4417 }
4418 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4419 FPSR |= ((PC - 1) & AMASK);
4420 if (!(FPSR & 0x01000000)) /* N is off? */
4421 PC = (PC + 1) & AMASK; /* yep: skip */
4422 continue;
4423 }
4424 if (IR == 0117250) { /* FSNE */
4425 if (!(fpu_unit.flags & UNIT_UP))
4426 continue;
4427 if (Debug_Flags == 1) {
4428 printf("\n<<FPU instruction: FSNE>>\n");
4429 continue;
4430 }
4431 if (FPFault) { /* Fault from a previous inst? */
4432 FPFault = 0;
4433 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4434 PutMap(t, AC[0]);
4435 t++;
4436 PutMap(t, AC[1]);
4437 t++;
4438 PutMap(t, AC[2]);
4439 t++;
4440 PutMap(t, AC[3]);
4441 t++;
4442 PutMap(t, ((PC-1) & AMASK));
4443 if (C) PutMap(t, (GetMap(t) | 0100000));
4444 PutMap(040, t);
4445 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4446 continue;
4447 }
4448 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4449 FPSR |= ((PC - 1) & AMASK);
4450 if (!(FPSR & 0x02000000)) /* Z is off? */
4451 PC = (PC + 1) & AMASK; /* yep: skip */
4452 continue;
4453 }
4454 if (IR == 0143250) { /* FSNM */
4455 if (!(fpu_unit.flags & UNIT_UP))
4456 continue;
4457 if (Debug_Flags == 1) {
4458 printf("\n<<FPU instruction: FSNM>>\n");
4459 reason = STOP_IBKPT;
4460 }
4461 if (FPFault) { /* Fault from a previous inst? */
4462 FPFault = 0;
4463 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4464 PutMap(t, AC[0]);
4465 t++;
4466 PutMap(t, AC[1]);
4467 t++;
4468 PutMap(t, AC[2]);
4469 t++;
4470 PutMap(t, AC[3]);
4471 t++;
4472 PutMap(t, ((PC-1) & AMASK));
4473 if (C) PutMap(t, (GetMap(t) | 0100000));
4474 PutMap(040, t);
4475 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4476 continue;
4477 }
4478 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4479 FPSR |= ((PC - 1) & AMASK);
4480 if (!(FPSR & 0x08000000)) /* MOF is off? */
4481 PC = (PC + 1) & AMASK; /* yep: skip */
4482 continue;
4483 }
4484 if (IR == 0153250) { /* FSNU */
4485 if (!(fpu_unit.flags & UNIT_UP))
4486 continue;
4487 if (Debug_Flags == 1) {
4488 printf("\n<<FPU instruction: FSNU>>\n");
4489 reason = STOP_IBKPT;
4490 }
4491 if (FPFault) { /* Fault from a previous inst? */
4492 FPFault = 0;
4493 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4494 PutMap(t, AC[0]);
4495 t++;
4496 PutMap(t, AC[1]);
4497 t++;
4498 PutMap(t, AC[2]);
4499 t++;
4500 PutMap(t, AC[3]);
4501 t++;
4502 PutMap(t, ((PC-1) & AMASK));
4503 if (C) PutMap(t, (GetMap(t) | 0100000));
4504 PutMap(040, t);
4505 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4506 continue;
4507 }
4508 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4509 FPSR |= ((PC - 1) & AMASK);
4510 if (!(FPSR & 0x20000000)) /* UNF is off? */
4511 PC = (PC + 1) & AMASK; /* yep: skip */
4512 continue;
4513 }
4514 if (IR == 0163250) { /* FSNO */
4515 if (!(fpu_unit.flags & UNIT_UP))
4516 continue;
4517 if (Debug_Flags == 1) {
4518 printf("\n<<FPU instruction: FSNO>>\n");
4519 reason = STOP_IBKPT;
4520 }
4521 if (FPFault) { /* Fault from a previous inst? */
4522 FPFault = 0;
4523 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4524 PutMap(t, AC[0]);
4525 t++;
4526 PutMap(t, AC[1]);
4527 t++;
4528 PutMap(t, AC[2]);
4529 t++;
4530 PutMap(t, AC[3]);
4531 t++;
4532 PutMap(t, ((PC-1) & AMASK));
4533 if (C) PutMap(t, (GetMap(t) | 0100000));
4534 PutMap(040, t);
4535 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4536 continue;
4537 }
4538 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4539 FPSR |= ((PC - 1) & AMASK);
4540 if (!(FPSR & 0x40000000)) /* OVF is off? */
4541 PC = (PC + 1) & AMASK; /* yep: skip */
4542 continue;
4543 }
4544 if (IR == 0147250) { /* FSND */
4545 if (!(fpu_unit.flags & UNIT_UP))
4546 continue;
4547 if (Debug_Flags == 1) {
4548 printf("\n<<FPU instruction: FSND>>\n");
4549 reason = STOP_IBKPT;
4550 }
4551 if (FPFault) { /* Fault from a previous inst? */
4552 FPFault = 0;
4553 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4554 PutMap(t, AC[0]);
4555 t++;
4556 PutMap(t, AC[1]);
4557 t++;
4558 PutMap(t, AC[2]);
4559 t++;
4560 PutMap(t, AC[3]);
4561 t++;
4562 PutMap(t, ((PC-1) & AMASK));
4563 if (C) PutMap(t, (GetMap(t) | 0100000));
4564 PutMap(040, t);
4565 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4566 continue;
4567 }
4568 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4569 FPSR |= ((PC - 1) & AMASK);
4570 if (!(FPSR & 0x10000000)) /* DVZ is off? */
4571 PC = (PC + 1) & AMASK; /* yep: skip */
4572 continue;
4573 }
4574 if (IR == 0157250) { /* FSNUD */
4575 if (!(fpu_unit.flags & UNIT_UP))
4576 continue;
4577 if (Debug_Flags == 1) {
4578 printf("\n<<FPU instruction: FSNUD>>\n");
4579 reason = STOP_IBKPT;
4580 }
4581 if (FPFault) { /* Fault from a previous inst? */
4582 FPFault = 0;
4583 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4584 PutMap(t, AC[0]);
4585 t++;
4586 PutMap(t, AC[1]);
4587 t++;
4588 PutMap(t, AC[2]);
4589 t++;
4590 PutMap(t, AC[3]);
4591 t++;
4592 PutMap(t, ((PC-1) & AMASK));
4593 if (C) PutMap(t, (GetMap(t) | 0100000));
4594 PutMap(040, t);
4595 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4596 continue;
4597 }
4598 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4599 FPSR |= ((PC - 1) & AMASK);
4600 if (!(FPSR & 0x30000000)) /* UNF & DVZ off? */
4601 PC = (PC + 1) & AMASK; /* yep: skip */
4602 continue;
4603 }
4604 if (IR == 0167250) { /* FSNOD */
4605 if (!(fpu_unit.flags & UNIT_UP))
4606 continue;
4607 if (Debug_Flags == 1) {
4608 printf("\n<<FPU instruction: FSNOD>>\n");
4609 reason = STOP_IBKPT;
4610 }
4611 if (FPFault) { /* Fault from a previous inst? */
4612 FPFault = 0;
4613 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4614 PutMap(t, AC[0]);
4615 t++;
4616 PutMap(t, AC[1]);
4617 t++;
4618 PutMap(t, AC[2]);
4619 t++;
4620 PutMap(t, AC[3]);
4621 t++;
4622 PutMap(t, ((PC-1) & AMASK));
4623 if (C) PutMap(t, (GetMap(t) | 0100000));
4624 PutMap(040, t);
4625 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4626 continue;
4627 }
4628 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4629 FPSR |= ((PC - 1) & AMASK);
4630 if (!(FPSR & 0x50000000)) /* OVF & DVZ off? */
4631 PC = (PC + 1) & AMASK; /* yep: skip */
4632 continue;
4633 }
4634 if (IR == 0173250) { /* FSNUO */
4635 if (!(fpu_unit.flags & UNIT_UP))
4636 continue;
4637 if (Debug_Flags == 1) {
4638 printf("\n<<FPU instruction: FSNUO>>\n");
4639 reason = STOP_IBKPT;
4640 }
4641 if (FPFault) { /* Fault from a previous inst? */
4642 FPFault = 0;
4643 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4644 PutMap(t, AC[0]);
4645 t++;
4646 PutMap(t, AC[1]);
4647 t++;
4648 PutMap(t, AC[2]);
4649 t++;
4650 PutMap(t, AC[3]);
4651 t++;
4652 PutMap(t, ((PC-1) & AMASK));
4653 if (C) PutMap(t, (GetMap(t) | 0100000));
4654 PutMap(040, t);
4655 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4656 continue;
4657 }
4658 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4659 FPSR |= ((PC - 1) & AMASK);
4660 if (!(FPSR & 0x60000000)) /* OVF & UNF off? */
4661 PC = (PC + 1) & AMASK; /* yep: skip */
4662 continue;
4663 }
4664 if (IR == 0177250) { /* FSNER */
4665 if (!(fpu_unit.flags & UNIT_UP))
4666 continue;
4667 if (Debug_Flags == 1) {
4668 printf("\n<<FPU instruction: FSNER>>\n");
4669 reason = STOP_IBKPT;
4670 }
4671 if (FPFault) { /* Fault from a previous inst? */
4672 FPFault = 0;
4673 t = (GetMap(040) + 1) & AMASK; /* Yes: push rtn block */
4674 PutMap(t, AC[0]);
4675 t++;
4676 PutMap(t, AC[1]);
4677 t++;
4678 PutMap(t, AC[2]);
4679 t++;
4680 PutMap(t, AC[3]);
4681 t++;
4682 PutMap(t, ((PC-1) & AMASK));
4683 if (C) PutMap(t, (GetMap(t) | 0100000));
4684 PutMap(040, t);
4685 PC = indirect(GetMap(045)); /* JMP indirect to 45 */
4686 continue;
4687 }
4688 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
4689 FPSR |= ((PC - 1) & AMASK);
4690 if (!(FPSR & 0x78000000)) /* all errors off? */
4691 PC = (PC + 1) & AMASK; /* yep: skip */
4692 continue;
4693 }
4694
4695 if (Debug_Flags) {
4696 printf("\n<<Unexecuted inst = %o at PC=%o>>\n\r", IR, PC-1);
4697 if (Debug_Flags & 040000) reason = STOP_IBKPT;
4698 }
4699 }
4700
4701 if (IR == 061777) { /* VCT: Vector on Interrupt */
4702 int32 stkchg, vtable;
4703 int32 ventry, dctadr;
4704 int32 old40, old41, old42, old43;
4705
4706 /* Ok, folks, this is one helluva instruction */
4707
4708 stkchg = GetMap(PC) & 0100000; /* Save stack change bit */
4709 vtable = GetMap(PC) & AMASK; /* Address of vector table */
4710
4711 iodev = 0;
4712 int_req = (int_req & ~INT_DEV) | /* Do an INTA w/o an accum */
4713 (dev_done & ~dev_disable);
4714 iodata = int_req & (-int_req);
4715 for (i = DEV_LOW; i <= DEV_HIGH; i++) {
4716 if (iodata & dev_table[i].mask) {
4717 iodev = i;
4718 break;
4719 }
4720 }
4721
4722 ventry = GetMap(vtable + iodev); /* Get Vector Entry */
4723
4724 if (!(ventry & 0100000)) { /* Direct bit = 0? */
4725 PC = ventry & AMASK; /* YES - Mode A, so JMP */
4726 continue;
4727 }
4728
4729 dctadr = ventry & AMASK; /* Get address of DCT entry */
4730
4731 if (stkchg) { /* Stack change bit = 1? */
4732 old40 = GetMap(040); /* Save stack info */
4733 old41 = GetMap(041);
4734 old42 = GetMap(042);
4735 old43 = GetMap(043);
4736 PutMap(040, GetMap(004)); /* Loc 4 to stack ptr */
4737 PutMap(042, GetMap(006)); /* Loc 6 to stack limit */
4738 PutMap(043, GetMap(007)); /* Loc 7 into stack limit */
4739 PutMap(040, (GetMap(040) + 1)); /* Push old contents on new stk */
4740 PutMap(GetMap(040) & AMASK, old40);
4741 PutMap(040, (GetMap(040) + 1));
4742 PutMap(GetMap(040) & AMASK, old41);
4743 PutMap(040, (GetMap(040) + 1));
4744 PutMap(GetMap(040) & AMASK, old42);
4745 PutMap(040, (GetMap(040) + 1));
4746 PutMap(GetMap(040) & AMASK, old43);
4747 }
4748
4749 t = GetMap(dctadr & AMASK); /* Get word 0 of DCT */
4750
4751 if (t & 0100000) { /* Push bit set ? */
4752 PutMap(040, (GetMap(040) + 1)); /* Push "Standard rtn block" */
4753 PutMap(GetMap(040) & AMASK, AC[0]);
4754 PutMap(040, (GetMap(040) + 1));
4755 PutMap(GetMap(040) & AMASK, AC[1]);
4756 PutMap(040, (GetMap(040) + 1));
4757 PutMap(GetMap(040) & AMASK, AC[2]);
4758 PutMap(040, (GetMap(040) + 1));
4759 PutMap(GetMap(040) & AMASK, AC[3]);
4760 PutMap(040, (GetMap(040) + 1));
4761 PutMap(GetMap(040) & AMASK, GetMap(0));
4762 if (GetMap(0) == 0 && Debug_Flags) {
4763 printf("\n<<VCT will rtn to 0 @ %o>>\n\r", PC);
4764 reason = STOP_IBKPT;
4765 }
4766 if (C) PutMap(GetMap(040) & AMASK, (GetMap(GetMap(040) & AMASK) | 0100000));
4767 }
4768
4769 AC[2] = dctadr & AMASK; /* DCT Addr into AC2 */
4770
4771 PutMap(040, (GetMap(040) + 1)); /* Push pri int mask onto stack */
4772 PutMap(GetMap(040) & AMASK, pimask);
4773
4774 AC[0] = GetMap(dctadr + 1) | pimask; /* Build new mask from word 1 of dct */
4775 PutMap(005, AC[0]);
4776
4777 mask_out(pimask = AC[0]); /* Do a mask out inst */
4778
4779 PC = GetMap(dctadr) & AMASK; /* Finally, JMP to int routine */
4780
4781 continue;
4782 }
4783
4784 /*************************************************************************
4785 ** At this point, the instruction is not an Eclipse one. Therefore **
4786 ** decode it as a Nova instruction just like the Nova does. **
4787 *************************************************************************/
4788
4789 /* Memory reference instructions */
4790
4791 if (t < 014) { /* mem ref? */
4792 register int32 src, MA;
4793
4794 MA = IR & 0377;
4795 switch ((IR >> 8) & 03) { /* decode IR<6:7> */
4796 case 0: /* page zero */
4797 break;
4798 case 1: /* PC relative */
4799 if (MA & 0200) MA = 077400 | MA;
4800 MA = (MA + PC - 1) & AMASK;
4801 break;
4802 case 2: /* AC2 relative */
4803 if (MA & 0200) MA = 077400 | MA;
4804 MA = (MA + AC[2]) & AMASK;
4805 break;
4806 case 3: /* AC3 relative */
4807 if (MA & 0200) MA = 077400 | MA;
4808 MA = (MA + AC[3]) & AMASK;
4809 break;
4810 }
4811 if (IR & 002000) { /* indirect? */
4812 for (i = 0; i < (ind_max * 2); i++) { /* count indirects */
4813 if ((MA & 077770) == 020 && !(cpu_unit.flags & UNIT_MICRO))
4814 MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) + 1) & 0177777));
4815 else if ((MA & 077770) == 030 && !(cpu_unit.flags & UNIT_MICRO))
4816 MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) - 1) & 0177777));
4817 else MA = GetMap(MA & AMASK);
4818 if (MapStat & 1) { /* Start MAP */
4819 Usermap = Enable;
4820 Inhibit = 0;
4821 }
4822 if ((MA & 0100000) == 0) break;
4823 if (i >= ind_max && (MapStat & 010) && Usermap) break;
4824 }
4825 if (i >= (ind_max-1)) {
4826 if ((MapStat & 010) && Usermap) {
4827 Fault = 04000; /* Map fault if IND prot */
4828 continue;
4829 }
4830 if (i >= (ind_max * 2) && !(Fault)) {
4831 reason = STOP_IND;
4832 break;
4833 }
4834 }
4835 }
4836
4837 switch (t) { /* decode IR<1:4> */
4838 case 001: /* JSR */
4839 AC[3] = PC;
4840 case 000: /* JMP */
4841 old_PC = PC;
4842 PC = MA;
4843 break;
4844 case 002: /* ISZ */
4845 src = (GetMap(MA) + 1) & 0177777;
4846 if (MEM_ADDR_OK (MA)) PutMap(MA, src);
4847 if (src == 0) PC = (PC + 1) & AMASK;
4848 break;
4849 case 003: /* DSZ */
4850 src = (GetMap(MA) - 1) & 0177777;
4851 if (MEM_ADDR_OK (MA)) PutMap(MA, src);
4852 if (src == 0) PC = (PC + 1) & AMASK;
4853 break;
4854 case 004: /* LDA 0 */
4855 if (SingleCycle) Usermap = SingleCycle;
4856 AC[0] = GetMap(MA);
4857 if (SingleCycle) {
4858 Usermap = SingleCycle = 0;
4859 if (Inhibit == 1) Inhibit = 3;
4860 MapStat |= 02000;
4861 MapStat &= 0177776;
4862 }
4863 break;
4864 case 005: /* LDA 1 */
4865 if (SingleCycle) Usermap = SingleCycle;
4866 AC[1] = GetMap(MA);
4867 if (SingleCycle) {
4868 Usermap = SingleCycle = 0;
4869 if (Inhibit == 1) Inhibit = 3;
4870 MapStat |= 02000;
4871 MapStat &= 0177776;
4872 }
4873 break;
4874 case 006: /* LDA 2 */
4875 if (SingleCycle) Usermap = SingleCycle;
4876 AC[2] = GetMap(MA);
4877 if (SingleCycle) {
4878 Usermap = SingleCycle = 0;
4879 if (Inhibit == 1) Inhibit = 3;
4880 MapStat |= 02000;
4881 MapStat &= 0177776;
4882 }
4883 break;
4884 case 007: /* LDA 3 */
4885 if (SingleCycle) Usermap = SingleCycle;
4886 AC[3] = GetMap(MA);
4887 if (SingleCycle) {
4888 Usermap = SingleCycle = 0;
4889 if (Inhibit == 1) Inhibit = 3;
4890 MapStat |= 02000;
4891 MapStat &= 0177776;
4892 }
4893 break;
4894 case 010: /* STA 0 */
4895 if (SingleCycle)
4896 Usermap = SingleCycle;
4897 if (MEM_ADDR_OK (MA)) PutMap(MA, AC[0]);
4898 if (SingleCycle) {
4899 Usermap = SingleCycle = 0;
4900 if (Inhibit == 1) Inhibit = 3;
4901 MapStat |= 02000;
4902 MapStat &= 0177776;
4903 }
4904 break;
4905 case 011: /* STA 1 */
4906 if (SingleCycle)
4907 Usermap = SingleCycle;
4908 if (MEM_ADDR_OK (MA)) PutMap(MA, AC[1]);
4909 if (SingleCycle) {
4910 Usermap = SingleCycle = 0;
4911 if (Inhibit == 1) Inhibit = 3;
4912 MapStat |= 02000;
4913 MapStat &= 0177776;
4914 }
4915 break;
4916 case 012: /* STA 2 */
4917 if (SingleCycle)
4918 Usermap = SingleCycle;
4919 if (MEM_ADDR_OK (MA)) PutMap(MA, AC[2]);
4920 if (SingleCycle) {
4921 Usermap = SingleCycle = 0;
4922 if (Inhibit == 1) Inhibit = 3;
4923 MapStat |= 02000;
4924 MapStat &= 0177776;
4925 }
4926 break;
4927 case 013: /* STA 3 */
4928 if (SingleCycle)
4929 Usermap = SingleCycle;
4930 if (MEM_ADDR_OK (MA)) PutMap(MA, AC[3]);
4931 if (SingleCycle) {
4932 Usermap = SingleCycle = 0;
4933 if (Inhibit == 1) Inhibit = 3;
4934 MapStat |= 02000;
4935 MapStat &= 0177776;
4936 }
4937 break;
4938 } /* end switch */
4939 } /* end mem ref */
4940
4941 /* Operate instruction */
4942
4943 else if (t & 020) { /* operate? */
4944 register int32 src, srcAC, dstAC;
4945
4946 srcAC = (t >> 2) & 3; /* get reg decodes */
4947 dstAC = t & 03;
4948 switch ((IR >> 4) & 03) { /* decode IR<10:11> */
4949 case 0: /* load */
4950 src = AC[srcAC] | C;
4951 break;
4952 case 1: /* clear */
4953 src = AC[srcAC];
4954 break;
4955 case 2: /* set */
4956 src = AC[srcAC] | 0200000;
4957 break;
4958 case 3: /* complement */
4959 src = AC[srcAC] | (C ^ 0200000);
4960 break;
4961 } /* end switch carry */
4962
4963 switch ((IR >> 8) & 07) { /* decode IR<5:7> */
4964 case 0: /* COM */
4965 src = src ^ 0177777;
4966 break;
4967 case 1: /* NEG */
4968 src = ((src ^ 0177777) + 1) & 0377777;
4969 break;
4970 case 2: /* MOV */
4971 break;
4972 case 3: /* INC */
4973 src = (src + 1) & 0377777;
4974 break;
4975 case 4: /* ADC */
4976 src = ((src ^ 0177777) + AC[dstAC]) & 0377777;
4977 break;
4978 case 5: /* SUB */
4979 src = ((src ^ 0177777) + AC[dstAC] + 1) & 0377777;
4980 break;
4981 case 6: /* ADD */
4982 src = (src + AC[dstAC]) & 0377777;
4983 break;
4984 case 7: /* AND */
4985 src = src & (AC[dstAC] | 0200000);
4986 break;
4987 } /* end switch oper */
4988
4989 switch ((IR >> 6) & 03) { /* decode IR<8:9> */
4990 case 0: /* nop */
4991 break;
4992 case 1: /* L */
4993 src = ((src << 1) | (src >> 16)) & 0377777;
4994 break;
4995 case 2: /* R */
4996 src = ((src >> 1) | (src << 16)) & 0377777;
4997 break;
4998 case 3: /* S */
4999 src = ((src & 0377) << 8) | ((src >> 8) & 0377) |
5000 (src & 0200000);
5001 break;
5002 } /* end switch shift */
5003
5004 switch (IR & 07) { /* decode IR<13:15> */
5005 case 0: /* nop */
5006 break;
5007 case 1: /* SKP */
5008 PC = (PC + 1) & AMASK;
5009 break;
5010 case 2: /* SZC */
5011 if (src < 0200000) PC = (PC + 1) & AMASK;
5012 break;
5013 case 3: /* SNC */
5014 if (src >= 0200000) PC = (PC + 1) & AMASK;
5015 break;
5016 case 4: /* SZR */
5017 if ((src & 0177777) == 0) PC = (PC + 1) & AMASK;
5018 break;
5019 case 5: /* SNR */
5020 if ((src & 0177777) != 0) PC = (PC + 1) & AMASK;
5021 break;
5022 case 6: /* SEZ */
5023 if (src <= 0200000) PC = (PC + 1) & AMASK;
5024 break;
5025 case 7: /* SBN */
5026 if (src > 0200000) PC = (PC + 1) & AMASK;
5027 break;
5028 } /* end switch skip */
5029 if ((IR & 000010) == 0) { /* load? */
5030 AC[dstAC] = src & 0177777;
5031 C = src & 0200000;
5032 } /* end if load */
5033 } /* end if operate */
5034
5035 /* IOT instruction */
5036
5037 else { /* IOT */
5038 register int32 dstAC, pulse, code, device, iodata;
5039 char pulcode[4];
5040
5041 if ((MapStat & 0100) /* LEF mode bit on? */
5042 && Usermap) { /* We are in LEF Mode */
5043 AC[(IR >> 11) & 3] = LEFmode(PC - 1, (IR >> 8) & 3, IR & 0377, IR & 02000);
5044 if (Debug_Flags & 020000) {
5045 printf("\n\r<<LEF Break by special request - executed at %o.>>\n\r", PC-1);
5046 reason = STOP_IBKPT;
5047 }
5048 continue;
5049 }
5050
5051 dstAC = t & 03; /* decode fields */
5052 if ((MapStat & 040) && Usermap) { /* I/O protection fault */
5053 Fault = 020000;
5054 continue;
5055 }
5056 code = (IR >> 8) & 07;
5057 pulse = (IR >> 6) & 03;
5058 device = IR & 077;
5059 if (Debug_Flags && device == 0) {
5060 printf("\n\r<<I/O to device 00 at %o.>>\n\r", PC-1);
5061 reason = STOP_IBKPT;
5062 continue;
5063 }
5064 if ((Debug_Flags & 0100) && (device == (Debug_Flags & 077))) {
5065 printf("\n\r<<I/O Break (device %o) >>\n\r", device);
5066 reason = STOP_IBKPT;
5067 continue;
5068 }
5069 if ((Debug_Char != 0) && (device == 011) &&
5070 ((AC[dstAC] & 0177) == Debug_Char)) {
5071 printf("\n\r<<I/O Break (Char %o to TTO) >>\n\r", Debug_Char);
5072 reason = STOP_IBKPT;
5073 continue;
5074 }
5075 if (code == ioSKP) { /* IO skip? */
5076 switch (pulse) { /* decode IR<8:9> */
5077 case 0: /* skip if busy */
5078 if ((device == 077)? (int_req & INT_ION) != 0:
5079 (dev_busy & dev_table[device].mask) != 0)
5080 PC = (PC + 1) & AMASK;
5081 break;
5082 case 1: /* skip if not busy */
5083 if ((device == 077)? (int_req & INT_ION) == 0:
5084 (dev_busy & dev_table[device].mask) == 0)
5085 PC = (PC + 1) & AMASK;
5086 break;
5087 case 2: /* skip if done */
5088 if ((device == 077)? pwr_low != 0:
5089 (dev_done & dev_table[device].mask) != 0)
5090 PC = (PC + 1) & AMASK;
5091 break;
5092 case 3: /* skip if not done */
5093 if ((device == 077)? pwr_low == 0:
5094 (dev_done & dev_table[device].mask) == 0)
5095 PC = (PC + 1) & AMASK;
5096 break;
5097 } /* end switch */
5098 } /* end IO skip */
5099
5100 else if (device == DEV_CPU) { /* CPU control */
5101 switch (code) { /* decode IR<5:7> */
5102 case ioNIO: /* Get CPU ID */
5103 switch (model) {
5104 case 280: /* S280 */
5105 AC[0] = 021102;
5106 break;
5107 case 380:
5108 AC[0] = 013212; /* C380 */
5109 break;
5110 default:
5111 break;
5112 }
5113 break; /* Otherwise no-op */
5114 case ioDIA: /* read switches */
5115 AC[dstAC] = SR;
5116 break;
5117 case ioDIB: /* int ack */
5118 AC[dstAC] = 0;
5119 int_req = (int_req & ~INT_DEV) |
5120 (dev_done & ~dev_disable);
5121 iodata = int_req & (-int_req);
5122 for (i = DEV_LOW; i <= DEV_HIGH; i++) {
5123 if (iodata & dev_table[i].mask) {
5124 AC[dstAC] = i;
5125 break;
5126 }
5127 }
5128 break;
5129 case ioDOB: /* mask out */
5130 mask_out (pimask = AC[dstAC]);
5131 break;
5132 case ioDIC: /* io reset IORST */
5133 reset_all (0); /* reset devices */
5134 Usermap = 0; /* reset MAP */
5135 MapStat &= 04; /* Reset MAP status */
5136 MapIntMode = 0;
5137 Inhibit = 0;
5138 Map31 = 037;
5139 Check = SingleCycle = 0;
5140 Fault = 0;
5141 FPSR &= 0x0000FFFF;
5142 FPFault = 0;
5143 break;
5144 case ioDOC: /* halt */
5145 reason = STOP_HALT;
5146 break;
5147 } /* end switch code */
5148
5149 switch (pulse) { /* decode IR<8:9> */
5150 case iopS: /* ion */
5151 int_req = (int_req | INT_ION) & ~INT_NO_ION_PENDING;
5152 break;
5153 case iopC: /* iof */
5154 int_req = int_req & ~INT_ION;
5155 break; } /* end switch pulse */
5156 } /* end CPU control */
5157
5158 else if (device == DEV_ECC) {
5159 switch (code) {
5160 case ioDIA: /* Read Fault Address */
5161 AC[dstAC] = 0;
5162 break;
5163 case ioDIB: /* Read fault code */
5164 AC[dstAC] = 0;
5165 break;
5166 case ioDOA: /* Enable ERCC */
5167 break; }
5168 }
5169
5170 else if (device == DEV_MAP) { /* MAP control */
5171 switch (code) { /* decode IR<5:7> */
5172 case ioNIO: /* No I/O -- Single */
5173 if (!Usermap || !(MapStat & 0140)) {
5174 if ((Debug_Flags & 077) == 03)
5175 fprintf(Trace, "%o NIO %o (No I/O, clear faults)\n", PC-1, dstAC);
5176 MapStat &= ~036000; /* NIO Clears all faults */
5177 } else {
5178 if ((Debug_Flags & 077) == 03)
5179 fprintf(Trace, "%o NIO %o (No I/O, clear faults) NO EXEC(User mode)\n", PC-1, dstAC);
5180 }
5181 break;
5182 case ioDIA: /* Read map status */
5183 if (!Usermap || !(MapStat & 0140)) {
5184 if ((Debug_Flags & 077) == 03)
5185 fprintf(Trace, "%o DIA %o=%o (Read Map Status)\n", PC-1, dstAC, MapStat);
5186 AC[dstAC] = MapStat & 0xFFFE;
5187 if (MapIntMode & 1) /* Bit 15 is mode asof last int */
5188 AC[dstAC] |= 1;
5189 } else {
5190 if ((Debug_Flags & 077) == 03)
5191 fprintf(Trace, "%o DIA %o=%o (Read Map Status) NO EXEC(User mode)\n", PC-1, dstAC, MapStat);
5192 }
5193 break;
5194 case ioDOA: /* Load map status */
5195 if (!Usermap || !(MapStat & 0140)) {
5196 if ((Debug_Flags & 077) == 03)
5197 fprintf(Trace, "%o DOA %o=%o (Load Map Status)\n", PC-1, dstAC, AC[dstAC]);
5198 MapStat = AC[dstAC];
5199 MapIntMode = 0;
5200 Enable = 1;
5201 if (MapStat & 04) Enable = 2;
5202 Check &= ~01600;
5203 Check |= MapStat & 01600;
5204 if (MapStat & 1)
5205 Inhibit = 2; /* Inhibit interrupts */
5206 } else {
5207 if ((Debug_Flags & 077) == 03)
5208 fprintf(Trace, "%o DOA %o=%o (Load Map Status) NO EXEC(User mode)\n", PC-1, dstAC, AC[dstAC]);
5209 }
5210 break;
5211 case ioDIB: /* not used */
5212 break;
5213 case ioDOB: /* map block 31 */
5214 //AOS if (!Usermap || !(MapStat && 0140)) {
5215 if ((Debug_Flags & 077) == 03)
5216 fprintf(Trace, "%o DOB %o=%o (Map Blk 31)\n", PC-1, dstAC, AC[dstAC]);
5217 Map31 = AC[dstAC] & PAGEMASK;
5218 MapStat &= ~02000;
5219 //AOS } else {
5220 //AOS if ((Debug_Flags & 077) == 03)
5221 //AOS fprintf(Trace, "%o DOB %o=%o (Map Blk 31) NO EXEC (User Mode)\n", PC-1, dstAC, AC[dstAC]);
5222 //AOS }
5223 break;
5224 case ioDIC: /* Page Check */
5225 if (!Usermap || !(MapStat & 0140)) {
5226 switch ((Check>>7) & 07) {
5227 case 0: i=1; break;
5228 case 1: i=6; break;
5229 case 2: i=2; break;
5230 case 3: i=7; break;
5231 case 4: i=0; break;
5232 case 5: i=4; break;
5233 case 6: i=3; break;
5234 case 7: i=5; break;
5235 default: break;
5236 }
5237 j = (Check >> 10) & 037;
5238 AC[dstAC] = Map[i][j] & 0101777;
5239 AC[dstAC] |= ((Check << 5) & 070000);
5240 if ((Debug_Flags & 077) == 03)
5241 fprintf(Trace, "%o DIC %o=%o (Page Check)\n", PC-1, dstAC, AC[dstAC]);
5242 MapStat &= ~02000;
5243 } else {
5244 if ((Debug_Flags & 077) == 03)
5245 fprintf(Trace, "%o DIC %o=%o (Page Check) NO EXEC(User mode)\n", PC-1, dstAC, AC[dstAC]);
5246 }
5247 break;
5248 case ioDOC: /* Init Page Check */
5249 if (!Usermap || !(MapStat & 0140)) {
5250 if ((Debug_Flags & 077) == 03)
5251 fprintf(Trace, "%o DOC %o=%o (Init Pg Chk)\n", PC-1, dstAC, AC[dstAC]);
5252 Check = AC[dstAC];
5253 MapStat &= ~01600;
5254 MapStat |= (Check & 01600);
5255 MapStat &= ~02000;
5256 } else {
5257 if ((Debug_Flags & 077) == 03)
5258 fprintf(Trace, "%o DOC %o=%o (Init Pg Chk) NO EXEC(User mode)\n", PC-1, dstAC, AC[dstAC]);
5259 }
5260 break;
5261 } /* end switch code */
5262
5263 switch (pulse) {
5264 case iopP:
5265 if ((Debug_Flags & 077) == 03)
5266 fprintf(Trace, "%o xxxP (Single Cycle)\n", PC-1);
5267 if (Usermap) {
5268 MapStat &= 0177776;
5269 Usermap = 0;
5270 Inhibit = 0;
5271 } else {
5272 SingleCycle = Enable;
5273 Inhibit = 1; /* Inhibit interrupts */
5274 }
5275 break;
5276 }
5277 } /* end CPU control */
5278 else if (dev_table[device].routine) { /* normal device */
5279 iodata = dev_table[device].routine (pulse, code, AC[dstAC]);
5280 reason = iodata >> IOT_V_REASON;
5281 if (code & 1) AC[dstAC] = iodata & 0177777;
5282 if ((Debug_Flags & 077) == device && Debug_Flags != 0) {
5283 strcpy(pulcode, "");
5284 switch (pulse) {
5285 case iopP:
5286 strcpy(pulcode, "P");
5287 break;
5288 case iopS:
5289 strcpy(pulcode, "S");
5290 break;
5291 case iopC:
5292 strcpy(pulcode, "C");
5293 break;
5294 default:
5295 break;
5296 }
5297 switch(code) {
5298 case ioNIO:
5299 fprintf(Trace, "[%o] %o NIO%s %o\n", device, PC-1, pulcode, AC[dstAC]);
5300 break;
5301 case ioDIA:
5302 fprintf(Trace, "[%o] %o DIA%s %o\n", device, PC-1, pulcode, iodata);
5303 break;
5304 case ioDIB:
5305 fprintf(Trace, "[%o] %o DIB%s %o\n", device, PC-1, pulcode, iodata);
5306 break;
5307 case ioDIC:
5308 fprintf(Trace, "[%o] %o DIC%s %o\n", device, PC-1, pulcode, iodata);
5309 break;
5310 case ioDOA:
5311 fprintf(Trace, "[%o] %o DOA%s %o\n", device, PC-1, pulcode, AC[dstAC]);
5312 break;
5313 case ioDOB:
5314 fprintf(Trace, "[%o] %o DOB%s %o\n", device, PC-1, pulcode, AC[dstAC]);
5315 break;
5316 case ioDOC:
5317 fprintf(Trace, "[%o] %o DOC%s %o\n", device, PC-1, pulcode, AC[dstAC]);
5318 break;
5319 default:
5320 break;
5321 } /* end switch */
5322 } /* end if debug */
5323 } /* end else if */
5324 else reason = stop_dev;
5325 } /* end if IOT */
5326 } /* end while */
5327
5328 /* Simulation halted */
5329
5330 saved_PC = PC;
5331 return reason;
5332 }
5333
5334 /* Computes and returns a 16-bit effective address, given a
5335 program counter, index, and a displacement.
5336 */
5337
effective(int32 PC,int32 index,int32 disp)5338 int32 effective(int32 PC, int32 index, int32 disp)
5339 {
5340 register int32 i, MA;
5341
5342 MA = disp & 077777;
5343 switch (index) { /* decode IR<6:7> */
5344 case 0: /* page zero */
5345 break;
5346 case 1: /* PC relative */
5347 MA = (MA + PC) & AMASK;
5348 break;
5349 case 2: /* AC2 relative */
5350 MA = (MA + AC[2]) & AMASK;
5351 break;
5352 case 3: /* AC3 relative */
5353 MA = (MA + AC[3]) & AMASK;
5354 break;
5355 } /* end switch mode */
5356
5357 if (disp & 0100000) { /* indirect? */
5358 for (i = 0; i < ind_max * 2; i++) { /* count indirects */
5359 MA = GetMap(MA & AMASK);
5360 if (SingleCycle) Usermap = 0;
5361 if (MapStat & 1) { /* Start MAP */
5362 Usermap = Enable;
5363 Inhibit = 0;
5364 }
5365 if ((MA & 0100000) == 0) break;
5366 if ((MapStat & 010) && Usermap && i >= ind_max) break;
5367 }
5368 if (i >= (ind_max-1) && (MapStat & 010) && Usermap) {
5369 Fault = 04000; /* Map fault if IND prot */
5370 }
5371 if (i >= (ind_max * 2) && !(Fault)) {
5372 reason = STOP_IND_INT; /* Stop machine */
5373 }
5374 }
5375 return (MA & AMASK);
5376 }
5377
5378 /* Computes and returns a 16-bit effective address, given a
5379 program counter, index, and a displacement. This is a
5380 version supporting the LEF map mode instruction, as
5381 opposed to the ELEF instruction.
5382 */
5383
LEFmode(int32 PC,int32 index,int32 disp,int32 indirect)5384 int32 LEFmode(int32 PC, int32 index, int32 disp, int32 indirect)
5385 {
5386 register int32 i, MA;
5387 int16 sMA;
5388
5389 MA = disp & 077777;
5390 switch (index) { /* decode IR<6:7> */
5391 case 0: /* page zero */
5392 break;
5393 case 1: /* PC relative */
5394 sMA = MA;
5395 if (MA & 0200) sMA |= 0xff00;
5396 MA = (sMA + PC) & AMASK;
5397 break;
5398 case 2: /* AC2 relative */
5399 sMA = MA;
5400 if (MA & 0200) sMA |= 0xff00;
5401 MA = (sMA + AC[2]) & AMASK;
5402 break;
5403 case 3: /* AC3 relative */
5404 sMA = MA;
5405 if (MA & 0200) sMA |= 0xff00;
5406 MA = (sMA + AC[3]) & AMASK;
5407 break;
5408 } /* end switch mode */
5409
5410 if (indirect) { /* indirect? */
5411 for (i = 0; i < (ind_max * 2); i++) { /* count indirects */
5412 if ((MA & 077770) == 020 && !(cpu_unit.flags & UNIT_MICRO))
5413 MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) + 1) & 0177777));
5414 else if ((MA & 077770) == 030 && !(cpu_unit.flags & UNIT_MICRO))
5415 MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) - 1) & 0177777));
5416 else MA = GetMap(MA & AMASK);
5417 if (SingleCycle) Usermap = 0;
5418 if (MapStat & 1) { /* Start MAP */
5419 Usermap = Enable;
5420 Inhibit = 0;
5421 }
5422 if ((MA & 0100000) == 0) break;
5423 if ((MapStat & 010) && Usermap && i >= ind_max) break;
5424 }
5425 if (i >= (ind_max-1) && (MapStat & 010) && Usermap) {
5426 Fault = 04000; /* Map fault if IND prot */
5427 }
5428 if (i >= (ind_max * 2) && !(Fault)) {
5429 reason = STOP_IND_INT; /* Stop machine */
5430 }
5431 }
5432 return (MA & AMASK);
5433 }
5434
5435 /* Computes a "Byte pointer" for the Character Instruction set */
5436 /* This address in 'PC' must point to the displacement word of the instruction */
5437
Bytepointer(int32 PC,int32 index)5438 int32 Bytepointer(int32 PC, int32 index)
5439 {
5440 register int32 MA;
5441
5442 switch (index) { /* decode IR<6:7> */
5443 case 0: /* page zero */
5444 MA = 0;
5445 break;
5446 case 1: /* PC relative */
5447 MA = PC & AMASK;
5448 break;
5449 case 2: /* AC2 relative */
5450 MA = AC[2] & AMASK;
5451 break;
5452 case 3: /* AC3 relative */
5453 MA = AC[3] & AMASK;
5454 break;
5455 } /* end switch mode */
5456 MA = (MA * 2) & 0177777;
5457 MA = MA + GetMap(PC);
5458 return (MA & 0177777);
5459 }
5460
5461 /* Given an address, returns either that address if bit 0 is 0, or
5462 or follows an indirection chain until bit 0 is 0
5463 */
5464
indirect(int32 d)5465 int32 indirect(int32 d)
5466 {
5467 int i;
5468
5469 if (d & 0100000) { /* indirect? */
5470 for (i = 0; i < ind_max * 2; i++) { /* count indirects */
5471 if ((d & 077770) == 020 && !(cpu_unit.flags & UNIT_MICRO))
5472 d = (PutMap(d & AMASK, ((GetMap(d & AMASK) + 1) & 0177777)));
5473 else if ((d & 077770) == 030 && !(cpu_unit.flags & UNIT_MICRO))
5474 d = (PutMap(d & AMASK, ((GetMap(d & AMASK) - 1) & 0177777)));
5475 else d = GetMap(d & AMASK);
5476 if (MapStat & 1) { /* Start MAP */
5477 Usermap = Enable;
5478 Inhibit = 0;
5479 }
5480 if ((d & 0100000) == 0) break;
5481 if ((MapStat & 010) && Usermap && i >= ind_max) break;
5482 }
5483 if (i >= (ind_max-1) && (MapStat & 010) && Usermap) {
5484 Fault = 04000; /* Map fault if IND prot */
5485 }
5486 if (i >= (ind_max * 2) && !(Fault)) {
5487 reason = STOP_IND; /* Stop machine */
5488 }
5489 }
5490 return (d);
5491 }
5492
5493 /* Push a standard return block onto the stack */
5494
pushrtn(int32 pc)5495 int32 pushrtn(int32 pc)
5496 {
5497 int32 t;
5498
5499 t = (GetMap(040) + 1) & AMASK;
5500 PutMap(t, AC[0]);
5501 t++;
5502 PutMap(t, AC[1]);
5503 t++;
5504 PutMap(t, AC[2]);
5505 t++;
5506 PutMap(t, AC[3]);
5507 t++;
5508 PutMap(t, pc);
5509 if (C) PutMap(t, (GetMap(t) | 0100000));
5510 PutMap(040, t);
5511 return 0;
5512 }
5513
5514 /* Eclipse memory get/put - uses MAP if enabled */
5515
GetMap(int32 addr)5516 int32 GetMap(int32 addr)
5517 {
5518 int32 page;
5519 t_addr paddr;
5520
5521 switch (Usermap) {
5522 case 0:
5523 if (addr < 076000)
5524 return M[addr];
5525 paddr = ((Map31 & PAGEMASK) << 10) | (addr & 001777);
5526 if (paddr < MEMSIZE)
5527 return M[paddr];
5528 else
5529 return (0);
5530 break;
5531 case 1:
5532 page = (addr >> 10) & 037;
5533 paddr = ((Map[1][page] & 01777) << 10) | (addr & 001777);
5534 if (Map[1][page] == INVALID && !SingleCycle)
5535 Fault = 0100000/*!!!*/; /* Validity */
5536 if (paddr < MEMSIZE)
5537 return M[paddr];
5538 else
5539 return (0);
5540 break;
5541 case 2:
5542 page = (addr >> 10) & 037;
5543 paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777);
5544 if (Map[2][page] == INVALID && !SingleCycle)
5545 Fault = 0100000/*!!!*/; /* Validity */
5546 if (paddr < MEMSIZE)
5547 return M[paddr];
5548 else
5549 return (0);
5550 break;
5551 case 6:
5552 page = (addr >> 10) & 037;
5553 paddr = ((Map[6][page] & PAGEMASK) << 10) | (addr & 001777);
5554 if (Map[6][page] == INVALID && !SingleCycle)
5555 Fault = 0100000/*!!!*/; /* Validity */
5556 if (paddr < MEMSIZE)
5557 return M[paddr];
5558 else
5559 return (0);
5560 break;
5561 case 7:
5562 page = (addr >> 10) & 037;
5563 paddr = ((Map[7][page] & PAGEMASK) << 10) | (addr & 001777);
5564 if (Map[7][page] == INVALID && !SingleCycle)
5565 Fault = 0100000/*!!!*/; /* Validity */
5566 if (paddr < MEMSIZE)
5567 return M[paddr];
5568 else
5569 return (0);
5570 break;
5571 default:
5572 printf("\n\r<<MAP FAULT>>\n\r");
5573 return M[addr];
5574 break;
5575 }
5576 }
5577
PutMap(int32 addr,int32 data)5578 int32 PutMap(int32 addr, int32 data)
5579 {
5580 int32 page;
5581 t_addr paddr;
5582
5583 switch (Usermap) {
5584 case 0:
5585 if (addr < 076000) {
5586 M[addr] = data;
5587 return (data);
5588 }
5589 paddr = ((Map31 & PAGEMASK) << 10) | (addr & 001777);
5590 if (paddr < MEMSIZE) M[paddr] = data;
5591 break;
5592 case 1:
5593 page = (addr >> 10) & 037;
5594 paddr = ((Map[1][page] & PAGEMASK) << 10) | (addr & 001777);
5595 if (((Map[1][page] & 0100000) && (MapStat & 020)) || Map[1][page] == INVALID)
5596 Fault = 010000; /* Write Protect Fault */
5597 else if (paddr < MEMSIZE) M[paddr] = data;
5598 break;
5599 case 2:
5600 page = (addr >> 10) & 037;
5601 paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777);
5602 if (((Map[2][page] & 0100000) && (MapStat & 020)) || Map[2][page] == INVALID)
5603 Fault = 010000; /* Write Protect Fault */
5604 else if (paddr < MEMSIZE) M[paddr] = data;
5605 break;
5606 case 6:
5607 page = (addr >> 10) & 037;
5608 paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777);
5609 if (((Map[6][page] & 0100000) && (MapStat & 020)) || Map[6][page] == INVALID)
5610 Fault = 010000; /* Write Protect Fault */
5611 else if (paddr < MEMSIZE) M[paddr] = data;
5612 break;
5613 case 7:
5614 page = (addr >> 10) & 037;
5615 paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777);
5616 if (((Map[7][page] & 0100000) && (MapStat & 020)) || Map[7][page] == INVALID)
5617 Fault = 010000; /* Write Protect Fault */
5618 else if (paddr < MEMSIZE) M[paddr] = data;
5619 break;
5620 default:
5621 M[addr] = data;
5622 break;
5623 }
5624 return (data);
5625 }
5626
5627 #if 0
5628 int16 GetDCHMap(int32 map, int32 addr)
5629 {
5630 t_addr paddr;
5631 if (!(MapStat & 02)) return M[addr];
5632 paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777);
5633 if (paddr < MEMSIZE)
5634 return M[paddr];
5635 return (0);
5636 }
5637
5638 int16 PutDCHMap(int32 map, int32 addr, int16 data)
5639 {
5640 t_addr paddr;
5641 if (!(MapStat & 02)) {
5642 M[addr] = data;
5643 return (data);
5644 }
5645 paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777);
5646 if (paddr < MEMSIZE)
5647 M[paddr] = data;
5648 return (data);
5649 }
5650 #endif
5651
5652 /* Given a map number and a logical, returns the physical address, unless
5653 the map is not active, in which case logical = physical. This is
5654 used primarily by the I/O routines to map data channel read/writes.
5655 */
5656
MapAddr(int32 map,int32 addr)5657 int32 MapAddr(int32 map, int32 addr)
5658 {
5659 int32 paddr;
5660 if ((map == 0 || map > 2) && !(MapStat & 02)) return addr;
5661 if (map > 0 && map < 3 && Usermap == 0) return addr;
5662 paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777);
5663 return paddr;
5664 }
5665
5666 /* Loads a word into the Eclipse Maps */
5667
LoadMap(int32 w)5668 int32 LoadMap(int32 w)
5669 {
5670 int32 m;
5671
5672 m = (w >> 10) & 037;
5673 switch ((MapStat >> 7) & 07) {
5674 case 0: /* Load user A Map */
5675 Map[1][m] = w & MAPMASK;
5676 break;
5677 case 1: /* Load user C Map */
5678 Map[6][m] = w & MAPMASK;
5679 break;
5680 case 2: /* Load user B Map */
5681 Map[2][m] = w & MAPMASK;
5682 break;
5683 case 3: /* Load user D Map */
5684 Map[7][m] = w & MAPMASK;
5685 break;
5686 case 4: /* Load DCH A Map */
5687 Map[0][m] = w & MAPMASK;
5688 break;
5689 case 5: /* Load DCH C Map */
5690 Map[4][m] = w;
5691 break;
5692 case 6: /* Load DCH B Map */
5693 Map[3][m] = w;
5694 break;
5695 case 7: /* Load DCH D Map */
5696 Map[5][m] = w;
5697 break;
5698 default:
5699 break;
5700 }
5701 return 0;
5702 }
5703
5704 /* Displays an error on a unimplemented (in this sim) instr. */
5705
unimp(int32 PC)5706 int32 unimp(int32 PC)
5707 {
5708 if (Debug_Flags)
5709 printf("\n\r\007<<<Unimplemented instruction: [%o] %o>>>\n\r", PC - 1, GetMap(PC - 1));
5710 return 0;
5711 }
5712
5713 /* New priority mask out */
5714
mask_out(int32 newmask)5715 void mask_out (int32 newmask)
5716 {
5717 int32 i;
5718
5719 dev_disable = 0;
5720 for (i = DEV_LOW; i <= DEV_HIGH; i++) {
5721 if (newmask & dev_table[i].pi)
5722 dev_disable = dev_disable | dev_table[i].mask;
5723 }
5724 int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
5725 return;
5726 }
5727
5728 /* Reset routine */
5729
cpu_reset(DEVICE * dptr)5730 t_stat cpu_reset (DEVICE *dptr)
5731 {
5732 int_req = int_req & ~INT_ION;
5733 pimask = 0;
5734 dev_disable = 0;
5735 pwr_low = 0;
5736 sim_brk_types = sim_brk_dflt = SWMASK ('E');
5737 return SCPE_OK;
5738 }
5739
5740 /* Memory examine */
5741
cpu_ex(t_value * vptr,t_addr addr,UNIT * uptr,int32 sw)5742 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
5743 {
5744 if (sw & SWMASK ('V')) {
5745 if (addr > 077777) return SCPE_NXM;
5746 if (vptr != NULL) *vptr = GetMap (addr);
5747 }
5748 else {
5749 if (addr >= MEMSIZE) return SCPE_NXM;
5750 if (vptr != NULL) *vptr = M[addr] & 0177777;
5751 }
5752 return SCPE_OK;
5753 }
5754
5755 /* Memory deposit */
5756
cpu_dep(t_value val,t_addr addr,UNIT * uptr,int32 sw)5757 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
5758 {
5759 if (sw & SWMASK ('V')) {
5760 if (addr > 077777) return SCPE_NXM;
5761 PutMap (addr, (int32) val);
5762 }
5763 else {
5764 if (addr >= MEMSIZE) return SCPE_NXM;
5765 M[addr] = (int32) val & 0177777;
5766 }
5767 return SCPE_OK;
5768 }
5769
5770 /* Alter memory size */
5771
cpu_set_size(UNIT * uptr,int32 val,char * cptr,void * desc)5772 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
5773 {
5774 int32 mc = 0;
5775 t_addr i;
5776
5777 if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
5778 return SCPE_ARG;
5779 for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
5780 if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
5781 return SCPE_OK;
5782 MEMSIZE = val;
5783 for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
5784 return SCPE_OK;
5785 }
5786
5787 /* MAP device services */
5788
map_svc(UNIT * uptr)5789 t_stat map_svc (UNIT *uptr)
5790 {
5791 return SCPE_OK;
5792 }
5793
5794 /* Map examine */
5795
map_ex(t_value * vptr,t_addr addr,UNIT * uptr,int32 sw)5796 t_stat map_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
5797 {
5798 if ((addr & 077) >= 037 || addr > 737) return SCPE_NXM;
5799 uptr->u4 = -2; /* signal to print_sys in eclipse_sys.c: do not map */
5800 if (vptr != NULL) *vptr = Map[(addr >> 6) & 3][addr & 037] & 0177777;
5801 return SCPE_OK;
5802 }
5803
5804 /* Memory deposit */
5805
map_dep(t_value val,t_addr addr,UNIT * uptr,int32 sw)5806 t_stat map_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
5807 {
5808 if ((addr & 077) >= 037 || addr > 0737) return SCPE_NXM;
5809 uptr->u4 = -2; /* signal to print_sys in eclipse_sys.c: do not map */
5810 Map[(addr >> 6) & 3][addr & 037] = (int32)val & 0177777;
5811 return SCPE_OK;
5812 }
5813
5814 /* FPU device services */
5815
fpu_svc(UNIT * uptr)5816 t_stat fpu_svc (UNIT *uptr)
5817 {
5818 return SCPE_OK;
5819 }
5820
5821 /* PIT Device Services */
5822
5823 /* IOT routine */
5824
pit(int32 pulse,int32 code,int32 AC)5825 int32 pit (int32 pulse, int32 code, int32 AC)
5826 {
5827 int32 iodata = 0;
5828
5829 if (code == ioDIA) { /* DIA */
5830 if (pit_flag == 0) {
5831 pit_flag = 1;
5832 }
5833 iodata = pit_counter;
5834 }
5835 if (code == ioDOA) { /* DOA */
5836 pit_initial = AC; /* Load Counter */
5837 sim_rtcn_init (pit_time, 1); /* init calibr */
5838 }
5839 switch (pulse) { /* decode IR<8:9> */
5840 case iopS: /* start */
5841 pit_counter = pit_initial; /* Set the counter */
5842 dev_busy = dev_busy | INT_PIT; /* set busy */
5843 dev_done = dev_done & ~INT_PIT; /* clear done, int */
5844 int_req = int_req & ~INT_PIT;
5845 if (!sim_is_active (&pit_unit)) /* not running? */
5846 sim_activate (&pit_unit, /* activate */
5847 sim_rtcn_init (pit_time, 1)); /* init calibr */
5848 break;
5849 case iopC: /* clear */
5850 dev_busy = dev_busy & ~INT_PIT; /* clear busy */
5851 dev_done = dev_done & ~INT_PIT; /* clear done, int */
5852 int_req = int_req & ~INT_PIT;
5853 sim_cancel (&pit_unit); /* deactivate unit */
5854 break; } /* end switch */
5855 return iodata;
5856 }
5857
5858 /* Unit service */
5859
pit_svc(UNIT * uptr)5860 t_stat pit_svc (UNIT *uptr)
5861 {
5862 int32 t;
5863 t = sim_rtcn_calb (pit_tps, 1); /* calibrate delay */
5864 sim_activate (&pit_unit, t); /* reactivate unit */
5865 pit_poll = t / (-pit_adj); /* adjust poll */
5866 pit_counter++; /* Increment counter */
5867 if (pit_counter >= 0177777) { /* Has counter reached limit ? */
5868 dev_done = dev_done | INT_PIT; /* set done */
5869 dev_busy = dev_busy & ~INT_PIT; /* clear busy */
5870 int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); /* Interrupt */
5871 pit_counter = pit_initial;
5872 }
5873 return SCPE_OK;
5874 }
5875
5876 /* Reset routine */
5877
pit_reset(DEVICE * dptr)5878 t_stat pit_reset (DEVICE *dptr)
5879 {
5880 pit_counter = 0; /* clear counter */
5881 dev_busy = dev_busy & ~INT_PIT; /* clear busy */
5882 dev_done = dev_done & ~INT_PIT; /* clear done, int */
5883 int_req = int_req & ~INT_PIT;
5884 sim_cancel (&pit_unit); /* deactivate unit */
5885 pit_poll = pit_time; /* poll is default */
5886 return SCPE_OK;
5887 }
5888
5889 /* Bootstrap routine for CPU */
5890
5891 #define BOOT_START 00000
5892 #define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
5893
5894 static const int32 boot_rom[] = {
5895
5896 062677, /* IORST ;Reset all I/O */
5897 060477, /* READS 0 ;Read SR into AC0 */
5898 024026, /* LDA 1,C77 ;Get dev mask */
5899 0107400, /* AND 0,1 ;Isolate dev code */
5900 0124000, /* COM 1,1 ;- device code - 1 */
5901 010014, /* LOOP: ISZ OP1 ;Device code to all */
5902 010030, /* ISZ OP2 ;I/O instructions */
5903 010032, /* ISZ OP3 */
5904 0125404, /* INC 1,1,SZR ;done? */
5905 000005, /* JMP LOOP ;No, increment again */
5906 030016, /* LDA 2,C377 ;place JMP 377 into */
5907 050377, /* STA 2,377 ;location 377 */
5908 060077, /* OP1: 060077 ;start device (NIOS 0) */
5909 0101102, /* MOVL 0,0,SZC ;Test switch 0, low speed? */
5910 000377, /* C377: JMP 377 ;no - jmp 377 & wait */
5911 004030, /* LOOP2: JSR GET+1 ;Get a frame */
5912 0101065, /* MOVC 0,0,SNR ;is it non-zero? */
5913 000017, /* JMP LOOP2 ;no, ignore */
5914 004027, /* LOOP4: JSR GET ;yes, get full word */
5915 046026, /* STA 1,@C77 ;store starting at 100 */
5916 /* ;2's complement of word ct */
5917 010100, /* ISZ 100 ;done? */
5918 000022, /* JMP LOOP4 ;no, get another */
5919 000077, /* C77: JMP 77 ;yes location ctr and */
5920 /* ;jmp to last word */
5921 0126420, /* GET: SUBZ 1,1 ; clr AC1, set carry */
5922 /* OP2: */
5923 063577, /* LOOP3: 063577 ;done? (SKPDN 0) - 1 */
5924 000030, /* JMP LOOP3 ;no -- wait */
5925 060477, /* OP3: 060477 ;y--read in ac0 (DIAS 0,0) */
5926 0107363, /* ADDCS 0,1,SNC ;add 2 frames swapped - got 2nd? */
5927 000030, /* JMP LOOP3 ;no go back after it */
5928 0125300, /* MOVS 1,1 ;yes swap them */
5929 001400, /* JMP 0,3 ;rtn with full word */
5930 0 /* 0 ;padding */
5931 };
5932
cpu_boot(int32 unitno,DEVICE * dptr)5933 t_stat cpu_boot (int32 unitno, DEVICE *dptr)
5934 {
5935 int32 i;
5936 extern int32 saved_PC;
5937
5938 for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
5939 saved_PC = BOOT_START;
5940 return SCPE_OK;
5941 }
5942
Debug_Entry(int32 PC,int32 inst,int32 inst2,int32 AC0,int32 AC1,int32 AC2,int32 AC3,int32 flags)5943 int32 Debug_Entry(int32 PC, int32 inst, int32 inst2, int32 AC0, int32 AC1, int32 AC2, int32 AC3, int32 flags)
5944 {
5945 hpc[hnext] = PC & 0xffff;
5946 hinst[hnext] = inst & 0xffff;
5947 hinst2[hnext] = inst2 & 0xffff;
5948 hac0[hnext] = AC0 & 0xffff;
5949 hac1[hnext] = AC1 & 0xffff;
5950 hac2[hnext] = AC2 & 0xffff;
5951 hac3[hnext] = AC3 & 0xffff;
5952 hflags[hnext] = flags & 0xffff;
5953 hnext++;
5954 if (hnext >= hmax) {
5955 hwrap = 1;
5956 hnext = 0;
5957 }
5958 return 0;
5959 }
5960
Debug_Dump(UNIT * uptr,int32 val,char * cptr,void * desc)5961 t_stat Debug_Dump(UNIT *uptr, int32 val, char *cptr, void *desc)
5962 {
5963 return SCPE_OK;
5964 }
5965
Dump_History(FILE * st,UNIT * uptr,int32 val,void * desc)5966 t_stat Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc)
5967 {
5968 char debmap[4], debion[4];
5969 t_value simeval[20];
5970 int debcar;
5971 int start, end, ctr;
5972 int count = 0;
5973
5974 if (!Debug_Flags || Debug_Flags & 0100000) {
5975 printf("History was not logged. Deposit a non-zero value\n");
5976 printf("in DEBUG with bit 0 being 1 to build history.\n");
5977 return SCPE_OK;
5978 }
5979 if (!hwrap) {
5980 start = 0;
5981 end = hnext;
5982 } else {
5983 start = hnext;
5984 end = hnext - 1;
5985 if (end < 0) end = hmax;
5986 }
5987 ctr = start;
5988 while (1) {
5989 if (ctr == end)
5990 break;
5991 count++;
5992 strcpy(debion, " ");
5993 strcpy(debmap, " ");
5994 debcar = 0;
5995 if (hflags[ctr] & 0x80) {
5996 fprintf(st, "--------- Interrupt %o (%o) to %6o ---------\n",
5997 hinst[ctr], hac0[ctr], hac1[ctr]);
5998 } else {
5999 if (hflags[ctr] & 0x01) debcar = 1;
6000 if (hflags[ctr] & 0x02) strcpy(debion, "I");
6001 if (hflags[ctr] & 0x04) strcpy(debmap, "A");
6002 if (hflags[ctr] & 0x08) strcpy(debmap, "B");
6003 if (hflags[ctr] & 0x10) strcpy(debmap, "C");
6004 if (hflags[ctr] & 0x20) strcpy(debmap, "D");
6005 fprintf(st, "%s%s%06o acs: %06o %06o %06o %06o %01o ",
6006 debion, debmap, hpc[ctr], hac0[ctr], hac1[ctr], hac2[ctr],
6007 hac3[ctr], debcar);
6008 simeval[0] = hinst[ctr];
6009 simeval[1] = hinst2[ctr];
6010 fprint_sym (st, hpc[ctr], simeval, NULL, SWMASK('M'));
6011 fprintf(st, "\n");
6012 }
6013 ctr++;
6014 if (ctr > hmax)
6015 ctr = 0;
6016 }
6017 return SCPE_OK;
6018 }
6019
6020 /* Build dispatch table */
6021
build_devtab(void)6022 t_stat build_devtab (void)
6023 {
6024 DEVICE *dptr;
6025 DIB *dibp;
6026 int32 i, dn;
6027
6028 for (i = 0; i < 64; i++) { /* clr dev_table */
6029 dev_table[i].mask = 0;
6030 dev_table[i].pi = 0;
6031 dev_table[i].routine = NULL;
6032 }
6033 for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */
6034 if (!(dptr->flags & DEV_DIS) && /* enabled and */
6035 (dibp = (DIB *) dptr->ctxt)) { /* defined DIB? */
6036 dn = dibp->dnum; /* get dev num */
6037 dev_table[dn].mask = dibp->mask; /* copy entries */
6038 dev_table[dn].pi = dibp->pi;
6039 dev_table[dn].routine = dibp->routine;
6040 }
6041 }
6042 return SCPE_OK;
6043 }
6044
6045 /* ------------------------------------------------------------------- */
6046 /* Floating Point Arithmetic */
6047 /* ------------------------------------------------------------------- */
6048
6049
6050 /* Get short float from FPAC */
6051
get_sf(SHORT_FLOAT * fl,t_int64 * fpr)6052 void get_sf (SHORT_FLOAT *fl, t_int64 *fpr)
6053 {
6054 fl->sign = (uint8)(*fpr >> 63) & 1;
6055 fl->expo = (short)(*fpr >> 56) & 0x007F;
6056 fl->short_fract = (int32)(*fpr >> 32) & 0x00FFFFFF;
6057 }
6058
6059 /* Store short float to FPAC */
6060
store_sf(SHORT_FLOAT * fl,t_int64 * fpr)6061 void store_sf (SHORT_FLOAT *fl, t_int64 *fpr)
6062 {
6063 *fpr = 0;
6064 *fpr = ((t_int64)fl->sign << 63)
6065 | ((t_int64)fl->expo << 56)
6066 | ((t_int64)fl->short_fract <<32);
6067 }
6068
6069 /* Get long float from FPAC */
6070
get_lf(LONG_FLOAT * fl,t_int64 * fpr)6071 void get_lf (LONG_FLOAT *fl, t_int64 *fpr)
6072 {
6073 fl->sign = (uint8)(*fpr >> 63) & 1;
6074 fl->expo = (short)(*fpr >> 56) & 0x007F;
6075 fl->long_fract = (t_int64)*fpr & 0x00FFFFFFFFFFFFFF;
6076
6077 }
6078
6079 /* Store long float to FPAC */
6080
store_lf(LONG_FLOAT * fl,t_int64 * fpr)6081 void store_lf (LONG_FLOAT *fl, t_int64 *fpr)
6082 {
6083 *fpr = 0;
6084 *fpr = (t_int64)fl->sign << 63;
6085 *fpr |= ((t_int64)fl->expo << 56) & 0x7f00000000000000;
6086 *fpr |= fl->long_fract;
6087 }
6088
6089
6090 /* Check short for Overflow */
6091
overflow_sf(SHORT_FLOAT * fl)6092 int overflow_sf (SHORT_FLOAT *fl)
6093 {
6094 if (fl->expo > 127) {
6095 fl->expo &= 0x007F;
6096 return(1);
6097 }
6098 return(0);
6099
6100 }
6101
6102 /* Normalize Short Float */
6103
normal_sf(SHORT_FLOAT * fl)6104 int normal_sf(SHORT_FLOAT *fl)
6105 {
6106 if (fl->short_fract) {
6107 if ((fl->short_fract & 0x00FFFF00) == 0) {
6108 fl->short_fract <<= 16;
6109 fl->expo -= 4;
6110 }
6111 if ((fl->short_fract & 0x00FF0000) == 0) {
6112 fl->short_fract <<= 8;
6113 fl->expo -= 2;
6114 }
6115 if ((fl->short_fract & 0x00F00000) == 0) {
6116 fl->short_fract <<= 4;
6117 (fl->expo)--;
6118 }
6119 } else {
6120 fl->sign = 0;
6121 fl->expo = 0;
6122 }
6123 if (fl->expo < 0)
6124 return (2);
6125 return(0);
6126 }
6127
6128 /* Normalize long float */
6129
normal_lf(LONG_FLOAT * fl)6130 int normal_lf (LONG_FLOAT *fl)
6131 {
6132 if (fl->long_fract) {
6133 if ((fl->long_fract & 0x00FFFFFFFF000000) == 0) {
6134 fl->long_fract <<= 32;
6135 fl->expo -= 8;
6136 }
6137 if ((fl->long_fract & 0x00FFFF0000000000) == 0) {
6138 fl->long_fract <<= 16;
6139 fl->expo -= 4;
6140 }
6141 if ((fl->long_fract & 0x00FF000000000000) == 0) {
6142 fl->long_fract <<= 8;
6143 fl->expo -= 2;
6144 }
6145 if ((fl->long_fract & 0x00F0000000000000) == 0) {
6146 fl->long_fract <<= 4;
6147 (fl->expo)--;
6148 }
6149 } else {
6150 fl->sign = 0;
6151 fl->expo = 0;
6152 }
6153 if (fl->expo < 0)
6154 return (2);
6155 return(0);
6156 }
6157
6158 /* Check Long for Overflow */
6159
overflow_lf(LONG_FLOAT * fl)6160 int overflow_lf(LONG_FLOAT *fl)
6161 {
6162 if (fl->expo > 127) {
6163 fl->expo &= 0x007F;
6164 return(1);
6165 }
6166 return(0);
6167
6168 }
6169
underflow_sf(SHORT_FLOAT * fl)6170 int underflow_sf(SHORT_FLOAT *fl)
6171 {
6172 if (fl->expo < 0) {
6173 fl->short_fract = 0;
6174 fl->expo = 0;
6175 fl->sign = 0;
6176 }
6177 return(0);
6178
6179 }
6180
6181
underflow_lf(LONG_FLOAT * fl)6182 int underflow_lf(LONG_FLOAT *fl)
6183 {
6184 if (fl->expo < 0) {
6185 fl->long_fract = 0;
6186 fl->expo = 0;
6187 fl->sign = 0;
6188 }
6189 return(0);
6190 }
6191
6192 /* Check Short for Over/Under flow */
6193
over_under_flow_sf(SHORT_FLOAT * fl)6194 int over_under_flow_sf(SHORT_FLOAT *fl)
6195 {
6196 if (fl->expo > 127) {
6197 fl->expo &= 0x007F;
6198 return(1);
6199 } else {
6200 if (fl->expo < 0) {
6201 /* set true 0 */
6202 fl->short_fract = 0;
6203 fl->expo = 0;
6204 fl->sign = 0;
6205 }
6206 }
6207 return(0);
6208
6209 }
6210
6211 /* Check Long for Over/Under flow */
6212
over_under_flow_lf(LONG_FLOAT * fl)6213 int over_under_flow_lf(LONG_FLOAT *fl)
6214 {
6215 if (fl->expo > 127) {
6216 fl->expo &= 0x007F;
6217 return(1);
6218 } else {
6219 if (fl->expo < 0) {
6220 /* set true 0 */
6221 fl->long_fract = 0;
6222 fl->expo = 0;
6223 fl->sign = 0;
6224 }
6225 }
6226 return(0);
6227
6228 }
6229
significance_sf(SHORT_FLOAT * fl)6230 int significance_sf (SHORT_FLOAT *fl)
6231 {
6232 fl->sign = 0;
6233 fl->expo = 0;
6234 return(0);
6235
6236 }
6237
significance_lf(LONG_FLOAT * fl)6238 int significance_lf (LONG_FLOAT *fl)
6239 {
6240 fl->sign = 0;
6241 fl->expo = 0;
6242 return(0);
6243
6244 }
6245
6246
6247 /*-------------------------------------------------------------------*/
6248 /* Add short float */
6249 /* */
6250 /* Input: */
6251 /* fl Float */
6252 /* add_fl Float to be added */
6253 /* normal Normalize if true */
6254 /* Value: */
6255 /* exeption */
6256 /*-------------------------------------------------------------------*/
add_sf(SHORT_FLOAT * fl,SHORT_FLOAT * add_fl,int normal)6257 int add_sf (SHORT_FLOAT *fl, SHORT_FLOAT *add_fl, int normal)
6258 {
6259 int pgm_check;
6260 int shift;
6261
6262 pgm_check = 0;
6263 if (add_fl->short_fract
6264 || add_fl->expo) { /* add_fl not 0 */
6265 if (fl->short_fract
6266 || fl->expo) { /* fl not 0 */
6267 /* both not 0 */
6268
6269 if (fl->expo == add_fl->expo) {
6270 /* expo equal */
6271
6272 /* both guard digits */
6273 fl->short_fract <<= 4;
6274 add_fl->short_fract <<= 4;
6275 } else {
6276 /* expo not equal, denormalize */
6277
6278 if (fl->expo < add_fl->expo) {
6279 /* shift minus guard digit */
6280 shift = add_fl->expo - fl->expo - 1;
6281 fl->expo = add_fl->expo;
6282
6283 if (shift) {
6284 if (shift >= 6
6285 || ((fl->short_fract >>= (shift * 4)) == 0)) {
6286 /* 0, copy summand */
6287
6288 fl->sign = add_fl->sign;
6289 fl->short_fract = add_fl->short_fract;
6290
6291 if (fl->short_fract == 0) {
6292 pgm_check = significance_sf(fl);
6293 } else {
6294 if (normal) {
6295 normal_sf(fl);
6296 pgm_check = underflow_sf(fl);
6297 }
6298 }
6299 return(pgm_check);
6300 }
6301 }
6302 /* guard digit */
6303 add_fl->short_fract <<= 4;
6304 } else {
6305 /* shift minus guard digit */
6306 shift = fl->expo - add_fl->expo - 1;
6307
6308 if (shift) {
6309 if (shift >= 6
6310 || ((add_fl->short_fract >>= (shift * 4)) == 0)) {
6311 /* 0, nothing to add */
6312
6313 if (fl->short_fract == 0) {
6314 pgm_check = significance_sf(fl);
6315 } else {
6316 if (normal) {
6317 normal_sf(fl);
6318 pgm_check = underflow_sf(fl);
6319 }
6320 }
6321 return(pgm_check);
6322 }
6323 }
6324 /* guard digit */
6325 fl->short_fract <<= 4;
6326 }
6327 }
6328
6329 /* compute with guard digit */
6330 if (fl->sign == add_fl->sign) {
6331 fl->short_fract += add_fl->short_fract;
6332 } else {
6333 if (fl->short_fract == add_fl->short_fract) {
6334 /* true 0 */
6335
6336 fl->short_fract = 0;
6337 return( significance_sf(fl) );
6338
6339 } else if (fl->short_fract > add_fl->short_fract) {
6340 fl->short_fract -= add_fl->short_fract;
6341 } else {
6342 fl->short_fract = add_fl->short_fract - fl->short_fract;
6343 fl->sign = add_fl->sign;
6344 }
6345 }
6346
6347 /* handle overflow with guard digit */
6348 if (fl->short_fract & 0xF0000000) {
6349 fl->short_fract >>= 8;
6350 (fl->expo)++;
6351 pgm_check = overflow_sf(fl);
6352 } else {
6353
6354 if (normal) {
6355 /* normalize with guard digit */
6356 if (fl->short_fract) {
6357 /* not 0 */
6358
6359 if (fl->short_fract & 0x0F000000) {
6360 /* not normalize, just guard digit */
6361 fl->short_fract >>= 4;
6362 } else {
6363 (fl->expo)--;
6364 normal_sf(fl);
6365 pgm_check = underflow_sf(fl);
6366 }
6367 } else {
6368 /* true 0 */
6369
6370 pgm_check = significance_sf(fl);
6371 }
6372 } else {
6373 /* not normalize, just guard digit */
6374 fl->short_fract >>= 4;
6375 if (fl->short_fract == 0) {
6376 pgm_check = significance_sf(fl);
6377 }
6378 }
6379 }
6380 return(pgm_check);
6381 } else { /* fl 0, add_fl not 0 */
6382 /* copy summand */
6383
6384 fl->expo = add_fl->expo;
6385 fl->sign = add_fl->sign;
6386 fl->short_fract = add_fl->short_fract;
6387 if (fl->short_fract == 0) {
6388 return( significance_sf(fl) );
6389 }
6390 }
6391 } else { /* add_fl 0 */
6392 if (fl->short_fract == 0) { /* fl 0 */
6393 /* both 0 */
6394
6395 return( significance_sf(fl) );
6396 }
6397 }
6398 if (normal) {
6399 normal_sf(fl);
6400 pgm_check = underflow_sf(fl);
6401 }
6402 return(pgm_check);
6403
6404 }
6405
6406
6407 /*-------------------------------------------------------------------*/
6408 /* Add long float */
6409 /* */
6410 /* Input: */
6411 /* fl Float */
6412 /* add_fl Float to be added */
6413 /* normal Normalize if true */
6414 /* Value: */
6415 /* exeption */
6416 /*-------------------------------------------------------------------*/
add_lf(LONG_FLOAT * fl,LONG_FLOAT * add_fl,int normal)6417 int add_lf (LONG_FLOAT *fl, LONG_FLOAT *add_fl, int normal)
6418 {
6419 int pgm_check;
6420 int shift;
6421
6422 pgm_check = 0;
6423 if (add_fl->long_fract
6424 || add_fl->expo) { /* add_fl not 0 */
6425 if (fl->long_fract
6426 || fl->expo) { /* fl not 0 */
6427 /* both not 0 */
6428
6429 if (fl->expo == add_fl->expo) {
6430 /* expo equal */
6431
6432 /* both guard digits */
6433 fl->long_fract <<= 4;
6434 add_fl->long_fract <<= 4;
6435 } else {
6436 /* expo not equal, denormalize */
6437
6438 if (fl->expo < add_fl->expo) {
6439 /* shift minus guard digit */
6440 shift = add_fl->expo - fl->expo - 1;
6441 fl->expo = add_fl->expo;
6442
6443 if (shift) {
6444 if (shift >= 14
6445 || ((fl->long_fract >>= (shift * 4)) == 0)) {
6446 /* 0, copy summand */
6447
6448 fl->sign = add_fl->sign;
6449 fl->long_fract = add_fl->long_fract;
6450
6451 if (fl->long_fract == 0) {
6452 pgm_check = significance_lf(fl);
6453 } else {
6454 if (normal) {
6455 normal_lf(fl);
6456 pgm_check = underflow_lf(fl);
6457 }
6458 }
6459 return(pgm_check);
6460 }
6461 }
6462 /* guard digit */
6463 add_fl->long_fract <<= 4;
6464 } else {
6465 /* shift minus guard digit */
6466 shift = fl->expo - add_fl->expo - 1;
6467
6468 if (shift) {
6469 if (shift >= 14
6470 || ((add_fl->long_fract >>= (shift * 4)) == 0)) {
6471 /* 0, nothing to add */
6472
6473 if (fl->long_fract == 0) {
6474 pgm_check = significance_lf(fl);
6475 } else {
6476 if (normal) {
6477 normal_lf(fl);
6478 pgm_check = underflow_lf(fl);
6479 }
6480 }
6481 return(pgm_check);
6482 }
6483 }
6484 /* guard digit */
6485 fl->long_fract <<= 4;
6486 }
6487 }
6488
6489 /* compute with guard digit */
6490 if (fl->sign == add_fl->sign) {
6491 fl->long_fract += add_fl->long_fract;
6492 } else {
6493 if (fl->long_fract == add_fl->long_fract) {
6494 /* true 0 */
6495
6496 fl->long_fract = 0;
6497 return( significance_lf(fl) );
6498
6499 } else if (fl->long_fract > add_fl->long_fract) {
6500 fl->long_fract -= add_fl->long_fract;
6501 } else {
6502 fl->long_fract = add_fl->long_fract - fl->long_fract;
6503 fl->sign = add_fl->sign;
6504 }
6505 }
6506
6507 /* handle overflow with guard digit */
6508 if (fl->long_fract & 0xF000000000000000) {
6509 fl->long_fract >>= 8;
6510 (fl->expo)++;
6511 pgm_check = overflow_lf(fl);
6512 } else {
6513
6514 if (normal) {
6515 /* normalize with guard digit */
6516 if (fl->long_fract) {
6517 /* not 0 */
6518
6519 if (fl->long_fract & 0x0F00000000000000) {
6520 /* not normalize, just guard digit */
6521 fl->long_fract >>= 4;
6522 } else {
6523 (fl->expo)--;
6524 normal_lf(fl);
6525 pgm_check = underflow_lf(fl);
6526 }
6527 } else {
6528 /* true 0 */
6529
6530 pgm_check = significance_lf(fl);
6531 }
6532 } else {
6533 /* not normalize, just guard digit */
6534 fl->long_fract >>= 4;
6535 if (fl->long_fract == 0) {
6536 pgm_check = significance_lf(fl);
6537 }
6538 }
6539 }
6540 return(pgm_check);
6541 } else { /* fl 0, add_fl not 0 */
6542 /* copy summand */
6543
6544 fl->expo = add_fl->expo;
6545 fl->sign = add_fl->sign;
6546 fl->long_fract = add_fl->long_fract;
6547 if (fl->long_fract == 0) {
6548 return( significance_lf(fl) );
6549 }
6550 }
6551 } else { /* add_fl 0 */
6552 if (fl->long_fract == 0) { /* fl 0 */
6553 /* both 0 */
6554
6555 return( significance_lf(fl) );
6556 }
6557 }
6558 if (normal) {
6559 normal_lf(fl);
6560 pgm_check = underflow_lf(fl);
6561 }
6562 return(pgm_check);
6563
6564 }
6565
6566 /*-------------------------------------------------------------------*/
6567 /* Multiply short float */
6568 /* */
6569 /* Input: */
6570 /* fl Multiplicand short float */
6571 /* mul_fl Multiplicator short float */
6572 /* Value: */
6573 /* exeption */
6574 /*-------------------------------------------------------------------*/
6575
mul_sf(SHORT_FLOAT * fl,SHORT_FLOAT * mul_fl)6576 int mul_sf(SHORT_FLOAT *fl, SHORT_FLOAT *mul_fl)
6577 {
6578 t_int64 wk;
6579
6580 if (fl->short_fract
6581 && mul_fl->short_fract) {
6582 /* normalize operands */
6583 normal_sf( fl );
6584 normal_sf( mul_fl );
6585
6586 /* multiply fracts */
6587 wk = (t_int64) fl->short_fract * mul_fl->short_fract;
6588
6589 /* normalize result and compute expo */
6590 if (wk & 0x0000F00000000000) {
6591 fl->short_fract = (int32)wk >> 24;
6592 fl->expo = (short)fl->expo + mul_fl->expo - 64;
6593 } else {
6594 fl->short_fract = (int32)wk >> 20;
6595 fl->expo = (short)fl->expo + mul_fl->expo - 65;
6596 }
6597
6598 /* determine sign */
6599 fl->sign = (fl->sign == mul_fl->sign) ? 0 : 1;
6600
6601 /* handle overflow and underflow */
6602 return( over_under_flow_sf(fl) );
6603 } else {
6604 /* set true 0 */
6605
6606 fl->short_fract = 0;
6607 fl->expo = 0;
6608 fl->sign = 0;
6609 return(0);
6610 }
6611
6612 }
6613
6614
6615 /*-------------------------------------------------------------------*/
6616 /* Multiply long float */
6617 /* */
6618 /* Input: */
6619 /* fl Multiplicand long float */
6620 /* mul_fl Multiplicator long float */
6621 /* Value: */
6622 /* exeption */
6623 /*-------------------------------------------------------------------*/
mul_lf(LONG_FLOAT * fl,LONG_FLOAT * mul_fl)6624 int mul_lf(LONG_FLOAT *fl, LONG_FLOAT *mul_fl)
6625 {
6626 t_int64 wk;
6627 int32 v;
6628
6629 if (fl->long_fract
6630 && mul_fl->long_fract) {
6631 /* normalize operands */
6632 normal_lf( fl );
6633 normal_lf( mul_fl );
6634
6635 /* multiply fracts by sum of partial multiplications */
6636 wk = ((fl->long_fract & 0x00000000FFFFFFFF) * (mul_fl->long_fract & 0x00000000FFFFFFFF)) >> 32;
6637
6638 wk += ((fl->long_fract & 0x00000000FFFFFFFF) * (mul_fl->long_fract >> 32));
6639 wk += ((fl->long_fract >> 32) * (mul_fl->long_fract & 0x00000000FFFFFFFF));
6640 v = (int32)wk;
6641
6642 fl->long_fract = (wk >> 32) + ((fl->long_fract >> 32) * (mul_fl->long_fract >> 32));
6643
6644 /* normalize result and compute expo */
6645 if (fl->long_fract & 0x0000F00000000000) {
6646 fl->long_fract = (fl->long_fract << 8)
6647 | (v >> 24);
6648 fl->expo = fl->expo + mul_fl->expo - 64;
6649 } else {
6650 fl->long_fract = (fl->long_fract << 12)
6651 | (v >> 20);
6652 fl->expo = fl->expo + mul_fl->expo - 65;
6653 }
6654
6655 /* determine sign */
6656 fl->sign = (fl->sign == mul_fl->sign) ? 0 : 1;
6657
6658 /* handle overflow and underflow */
6659 return( over_under_flow_lf(fl) );
6660 } else {
6661 /* set true 0 */
6662
6663 fl->long_fract = 0;
6664 fl->expo = 0;
6665 fl->sign = 0;
6666 return(0);
6667 }
6668
6669 }
6670
6671
6672 /*-------------------------------------------------------------------*/
6673 /* Divide short float */
6674 /* */
6675 /* Input: */
6676 /* fl Dividend short float */
6677 /* div_fl Divisor short float */
6678 /* Value: */
6679 /* exeption */
6680 /*-------------------------------------------------------------------*/
div_sf(SHORT_FLOAT * fl,SHORT_FLOAT * div_fl)6681 int div_sf(SHORT_FLOAT *fl, SHORT_FLOAT *div_fl)
6682 {
6683 t_int64 wk;
6684
6685 if (div_fl->short_fract) {
6686 if (fl->short_fract) {
6687 /* normalize operands */
6688 normal_sf( fl );
6689 normal_sf( div_fl );
6690
6691 /* position fracts and compute expo */
6692 if (fl->short_fract < div_fl->short_fract) {
6693 wk = (t_int64) fl->short_fract << 24;
6694 fl->expo = fl->expo - div_fl->expo + 64;
6695 } else {
6696 wk = (t_int64) fl->short_fract << 20;
6697 fl->expo = fl->expo - div_fl->expo + 65;
6698 }
6699 /* divide fractions */
6700 fl->short_fract = (int32)wk / div_fl->short_fract;
6701
6702 /* determine sign */
6703 fl->sign = (fl->sign == div_fl->sign) ? 0 : 1;
6704
6705 /* handle overflow and underflow */
6706 return( over_under_flow_sf(fl) );
6707 } else {
6708 /* fraction of dividend 0, set true 0 */
6709
6710 fl->short_fract = 0;
6711 fl->expo = 0;
6712 fl->sign = 0;
6713 }
6714 } else {
6715 /* divisor 0 */
6716
6717 return(3);
6718 }
6719 return(0);
6720
6721 }
6722
6723
6724 /*-------------------------------------------------------------------*/
6725 /* Divide long float */
6726 /* */
6727 /* Input: */
6728 /* fl Dividend long float */
6729 /* div_fl Divisor long float */
6730 /* Value: */
6731 /* exeption */
6732 /*-------------------------------------------------------------------*/
div_lf(LONG_FLOAT * fl,LONG_FLOAT * div_fl)6733 int div_lf(LONG_FLOAT *fl, LONG_FLOAT *div_fl)
6734 {
6735 t_int64 wk;
6736 t_int64 wk2;
6737 int i;
6738
6739 if (div_fl->long_fract) {
6740 if (fl->long_fract) {
6741 /* normalize operands */
6742 normal_lf( fl );
6743 normal_lf( div_fl );
6744
6745 /* position fracts and compute expo */
6746 if (fl->long_fract < div_fl->long_fract) {
6747 fl->expo = fl->expo - div_fl->expo + 64;
6748 } else {
6749 fl->expo = fl->expo - div_fl->expo + 65;
6750 div_fl->long_fract <<= 4;
6751 }
6752
6753 /* partial divide first hex digit */
6754 wk2 = fl->long_fract / div_fl->long_fract;
6755 wk = (fl->long_fract % div_fl->long_fract) << 4;
6756
6757 /* partial divide middle hex digits */
6758 i = 13;
6759 while (i--) {
6760 wk2 = (wk2 << 4)
6761 | (wk / div_fl->long_fract);
6762 wk = (wk % div_fl->long_fract) << 4;
6763 }
6764
6765 /* partial divide last hex digit */
6766 fl->long_fract = (wk2 << 4)
6767 | (wk / div_fl->long_fract);
6768
6769 /* determine sign */
6770 fl->sign = (fl->sign == div_fl->sign) ? 0 : 1;
6771
6772 /* handle overflow and underflow */
6773 return( over_under_flow_lf(fl) );
6774 } else {
6775 /* fraction of dividend 0, set true 0 */
6776
6777 fl->long_fract = 0;
6778 fl->expo = 0;
6779 fl->sign = 0;
6780 }
6781 } else {
6782 /* divisor 0 */
6783
6784 return(3);
6785 }
6786 return(0);
6787
6788 }
6789
6790