blob: c855cc556b48a3284ef2a91ae653bc4209b35db0 [file] [log] [blame] [raw]
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001/* eclipse_cpu.c: Eclipse CPU simulator
2
3 Modified from the original NOVA simulator by Robert Supnik.
4
Mark Pizzolatodb9bf322012-04-23 11:50:43 -07005 Copyright (c) 1998-2012, Charles E Owen
Bob Supnikdf647512002-07-14 15:20:00 -07006 Portions Copyright (c) 1993-2002, Robert M Supnik
Bob Supnik4d6dfa42001-11-06 20:50:00 -08007
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
Bob Supnikb7c1eae2005-09-09 18:09:00 -070025 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
Bob Supnik4d6dfa42001-11-06 20:50:00 -080027 in this Software without prior written authorization from Robert M Supnik.
28
Bob Supnikb7c1eae2005-09-09 18:09:00 -070029 cpu Eclipse central processor
Bob Supnik4d6dfa42001-11-06 20:50:00 -080030
Mark Pizzolatodb9bf322012-04-23 11:50:43 -070031 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)
Bob Supnikb7c1eae2005-09-09 18:09:00 -070034 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
Bob Supnik4d6dfa42001-11-06 20:50:00 -080042
43 The register state for the Eclipse CPU is basically the same as
44 the NOVA's:
45
Bob Supnikb7c1eae2005-09-09 18:09:00 -070046 AC[0:3]<0:15> general registers
47 C carry flag
48 PC<0:14> program counter
Bob Supnik1da2d942003-12-31 11:49:00 -080049
50 Eclipses with Folating Point Units added these registers:
51
Bob Supnikb7c1eae2005-09-09 18:09:00 -070052 FPAC[0:3]<0:63> Floating Point Accumulators
53 FPSR Floating Point Status Register
Bob Supnik1da2d942003-12-31 11:49:00 -080054
Bob Supnik4d6dfa42001-11-06 20:50:00 -080055 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)
Bob Supnikb7c1eae2005-09-09 18:09:00 -070065 7: VECTOR stack fault address (VCT again)
Bob Supnik4d6dfa42001-11-06 20:50:00 -080066 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)
Bob Supnikb7c1eae2005-09-09 18:09:00 -070070 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.
Bob Supnik4d6dfa42001-11-06 20:50:00 -080078
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
Bob Supnik1da2d942003-12-31 11:49:00 -080089 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
Bob Supnik4d6dfa42001-11-06 20:50:00 -080096 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
Bob Supnik1da2d942003-12-31 11:49:00 -0800102 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.
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800105
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",
Bob Supnik1da2d942003-12-31 11:49:00 -0800128 an 8086, at device code 6. Also, some new CPU device
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800129 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
Bob Supnik1da2d942003-12-31 11:49:00 -0800144 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.
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800148
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 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700157 | 0| op | AC |in| mode| displacement | memory reference
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800158 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
159
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700160 <0:4> mnemonic action
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800161
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700162 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
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800168
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700169 <5:7> mode action
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800170
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700171 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>)]
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800179
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.
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700187
188 The I/O transfer format is:
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800189
190 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
191 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700192 | 0 1 1| AC | opcode |pulse| device | I/O transfer
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800193 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
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 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700203 | 1|srcAC|dstAC| opcode |shift|carry|nl| skip | operate
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800204 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
205 \______/ \___/ \___/ | | | |
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700206 | | | | | | +--- 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)
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800226
227 The operate instruction can be microprogrammed to perform operations
228 on the source and destination AC's and the Carry flag.
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700229
230 This routine is the instruction decode routine for the NOVA.
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800231 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
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700239 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
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800244
245 2. Interrupts. Interrupts are maintained by four parallel variables:
246
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700247 dev_done device done flags
248 dev_disable device interrupt disable flags
249 dev_busy device busy flags
250 int_req interrupt requests
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800251
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
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700264 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
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800267*/
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**
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700290** Note: when detailed logging is off, the last 4096 or so
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800291** instructions executed are saved in a memory buffer, and
Bob Supnik1da2d942003-12-31 11:49:00 -0800292** when the sim stops, the "show" command can write this
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800293** history information to the file "history.log". This only
294** works if the DEBUG register is non-zero however, because
Bob Supnik1da2d942003-12-31 11:49:00 -0800295** of the performance hit even this recording makes. To
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700296** dump history, enter the command "show cpu history", with
297** the file "history" spelled correctly and lower case.
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800298**
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
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700312** an invalid instruction. When DEBUG is zero, any such
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800313** 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**
Bob Supnik1da2d942003-12-31 11:49:00 -0800330** 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**
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800334** Of course, the standard BREAK register is available for breakpoints
335** as in all the sims based on this standard.
336--------------------------------------------------------------------------*/
Bob Supnik1da2d942003-12-31 11:49:00 -0800337
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800338#include "nova_defs.h"
339
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700340#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)
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800348
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700349uint16 M[MAXMEMSIZE] = { 0 }; /* memory */
350int32 AC[4] = { 0 }; /* accumulators */
351int32 C = 0; /* carry flag */
352int32 saved_PC = 0; /* program counter */
353int32 SR = 0; /* switch register */
354int32 dev_done = 0; /* device done flags */
355int32 dev_busy = 0; /* device busy flags */
356int32 dev_disable = 0; /* int disable flags */
357int32 iot_enb = -1; /* IOT enables */
358int32 int_req = 0; /* interrupt requests */
359int32 pimask = 0; /* priority int mask */
360int32 pwr_low = 0; /* power fail flag */
361int32 ind_max = 15; /* iadr nest limit */
362int32 stop_dev = 0; /* stop on ill dev */
363int32 old_PC = 0; /* previous PC */
364int32 model = 140; /* Model of Eclipse */
365int32 speed = 0; /* Delay for each instruction */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800366
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700367int32 XCT_mode = 0; /* 1 if XCT mode */
368int32 XCT_inst = 0; /* XCT instruction */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800369int32 PPC = -1;
Bob Supnik59aa4a72008-06-24 14:21:00 -0700370int32 AMASK = 077777;
Bob Supnik2c2dd5e2002-11-17 15:54:00 -0800371
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700372struct ndev dev_table[64]; /* dispatch table */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800373
374/* Instruction history buffer */
375
376#define HISTMAX 4096
377
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700378int32 hnext = 0; /* # of current entry */
379int32 hwrap = 0; /* 1 if wrapped */
380int32 hmax = HISTMAX; /* Maximum entries b4 wrap */
Bob Supnikb6393b32004-11-23 15:49:00 -0800381uint16 hpc[HISTMAX];
382uint16 hinst[HISTMAX];
383uint16 hinst2[HISTMAX];
384uint16 hac0[HISTMAX];
385uint16 hac1[HISTMAX];
386uint16 hac2[HISTMAX];
387uint16 hac3[HISTMAX];
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800388unsigned short hflags[HISTMAX];
389
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700390/* 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
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800402*/
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700403
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800404
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
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700423#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 */
426int32 MapStat = 0; /* Map status register */
427int32 Inhibit = 0; /* !0=inhibit interrupts : */
428 /* 1 = single cycle inhibit */
429 /* 2 = inhibit until indirection */
430 /* 3 = inhibit next instruction only */
431int32 Enable = 0; /* User map to activate 1=A 2=B */
432int32 Usermap = 0; /* Active Map? 0=supvr mode, 1=user A, 2 = user B */
433int32 Map[8][32]; /* The actual MAPs 0=dch A, 1=A, 2=B, 3-5=dchB-D 6-7 User C-D */
434int32 Map31 = 037; /* Map for block 31 in supervisor mode */
435int32 SingleCycle = 0; /* Map one LDA/STA */
436int32 Check = 0; /* Page Check Register */
437int32 Fault = 0; /* Fault register */
438int32 MapInit = 0; /* 1 when map initialized */
439int32 MapIntMode = 0; /* Save of map user mode when int occurs */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800440
Bob Supnik1da2d942003-12-31 11:49:00 -0800441/* The Eclipse Floating Point Unit: This unit is optional on all Eclipse
442 models.
443*/
444
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700445int32 FPSR = 0; /* 32-bit FPU Status Register */
446t_int64 FPAC[4] = { 0,0,0,0 }; /* 4 64-bit Accumulators */
447int32 FPFault = 0; /* Save Fault State */
Bob Supnik1da2d942003-12-31 11:49:00 -0800448
449/* Definitions for internal floating point arithmetic */
450
451typedef struct _SHORT_FLOAT {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700452 int32 short_fract; /* Fraction */
453 short expo; /* Exponent + 64 */
454 uint8 sign; /* Sign */
Bob Supnik1da2d942003-12-31 11:49:00 -0800455} SHORT_FLOAT;
456
457typedef struct _LONG_FLOAT {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700458 t_int64 long_fract; /* Fraction */
459 short expo; /* Exponent + 64 */
460 uint8 sign; /* Sign */
Bob Supnik1da2d942003-12-31 11:49:00 -0800461} LONG_FLOAT;
462
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700463LONG_FLOAT dfl,dfl2; /* Double Precision Work Fields */
464SHORT_FLOAT sfl,sfl2; /* Single Precision Work Fields */
465t_int64 tempfp, holdfp; /* Working area for FPAC */
466int shift,m3;
Bob Supnik1da2d942003-12-31 11:49:00 -0800467t_int64 lsfract;
468
469void get_sf(SHORT_FLOAT *fl, t_int64 *fpr);
470void store_sf(SHORT_FLOAT *fl, t_int64 *fpr);
471void get_lf(LONG_FLOAT *fl, t_int64 *fpr);
472void store_lf(LONG_FLOAT *fl, t_int64 *fpr);
473int normal_sf (SHORT_FLOAT *fl);
474int normal_lf (LONG_FLOAT *fl);
475int overflow_sf(SHORT_FLOAT *fl);
476int overflow_lf(LONG_FLOAT *fl);
477int underflow_sf(SHORT_FLOAT *fl);
478int underflow_lf(LONG_FLOAT *fl);
479int significance_sf(SHORT_FLOAT *fl);
480int significance_lf(LONG_FLOAT *fl);
481int add_sf(SHORT_FLOAT *fl, SHORT_FLOAT *add_f1, int normal);
482int add_lf(LONG_FLOAT *fl, LONG_FLOAT *add_fl, int normal);
483int mul_sf(SHORT_FLOAT *fl, SHORT_FLOAT *mul_fl);
484int mul_lf(LONG_FLOAT *fl, LONG_FLOAT *mul_fl);
485int div_sf(SHORT_FLOAT *fl, SHORT_FLOAT *div_fl);
486int div_lf(LONG_FLOAT *fl, LONG_FLOAT *div_fl);
487
488/* Special Debugging Info */
489
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700490int32 Debug_Flags = 0; /* Debug register - selects debug features */
491int32 Debug_Char = 0; /* Debug Character Register */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800492
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700493int32 Tron = 0; /* For trace files */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800494FILE *Trace;
Bob Supnik1da2d942003-12-31 11:49:00 -0800495
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800496
497t_stat reason;
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800498extern int32 sim_int_char;
Bob Supnik1e704bf2005-10-15 15:38:00 -0700499extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
Bob Supnik2c2dd5e2002-11-17 15:54:00 -0800500extern DEVICE *sim_devices[];
Bob Supnik701f0fe2001-12-26 09:38:00 -0800501
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800502t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
503t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
504t_stat cpu_reset (DEVICE *dptr);
Bob Supnik2c2dd5e2002-11-17 15:54:00 -0800505t_stat cpu_boot (int32 unitno, DEVICE *dptr);
Bob Supnik701f0fe2001-12-26 09:38:00 -0800506t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
507t_stat Debug_Dump (UNIT *uptr, int32 val, char *cptr, void *desc);
Bob Supnik1da2d942003-12-31 11:49:00 -0800508t_stat Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc);
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800509t_stat map_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
510t_stat map_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
511t_stat map_reset (DEVICE *dptr);
512t_stat map_svc (UNIT *uptr);
Bob Supnik1da2d942003-12-31 11:49:00 -0800513t_stat fpu_svc (UNIT *uptr);
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800514int32 GetMap(int32 addr);
515int32 PutMap(int32 addr, int32 data);
516int32 Debug_Entry(int32 PC, int32 inst, int32 inst2, int32 AC0, int32 AC1, int32 AC2, int32 AC3, int32 flags);
Bob Supnik2c2dd5e2002-11-17 15:54:00 -0800517t_stat build_devtab (void);
Bob Supnikdf647512002-07-14 15:20:00 -0700518
Bob Supnikdf647512002-07-14 15:20:00 -0700519extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700520 UNIT *uptr, int32 sw);
521
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800522/* CPU data structures
523
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700524 cpu_dev CPU device descriptor
525 cpu_unit CPU unit descriptor
526 cpu_reg CPU register list
527 cpu_mod CPU modifiers list
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800528*/
529
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700530UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) };
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800531
532REG cpu_reg[] = {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700533 { 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};
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800557
558MTAB cpu_mod[] = {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700559 { 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};
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800579
580DEVICE cpu_dev = {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700581 "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};
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800586
587/* MAP data structures
588
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700589 map_dev MAP device descriptor
590 map_unit MAP unit descriptor
591 map_reg MAP register list
592 map_mod MAP modifiers list
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800593*/
594
595UNIT map_unit = { UDATA (&map_svc, UNIT_17B, MAXMEMSIZE) };
596
597REG map_reg[] = {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700598 { 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};
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800608
609MTAB map_mod[] = {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700610 { UNIT_17B, UNIT_17B, "17bit", "17B", NULL },
611 { UNIT_17B, 0, "19bit", "19B", NULL },
612 { 0 }
613};
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800614
615DEVICE map_dev = {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700616 "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};
Bob Supnik1da2d942003-12-31 11:49:00 -0800621
622/* FPU data structures
623
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700624 fpu_dev MAP device descriptor
625 fpu_unit MAP unit descriptor
626 fpu_reg MAP register list
627 fpu_mod MAP modifiers list
Bob Supnik1da2d942003-12-31 11:49:00 -0800628*/
629
630UNIT fpu_unit = { UDATA (&fpu_svc, UNIT_UP, MAXMEMSIZE) };
631
632REG fpu_reg[] = {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700633 { 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};
Bob Supnik1da2d942003-12-31 11:49:00 -0800641
642MTAB fpu_mod[] = {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700643 { UNIT_UP, UNIT_UP, "Enabled (UP)", "UP", NULL },
644 { UNIT_UP, 0, "Disabled (DOWN)", "DOWN", NULL },
645 { 0 }
646};
Bob Supnik1da2d942003-12-31 11:49:00 -0800647
648DEVICE fpu_dev = {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700649 "FPU", &fpu_unit, fpu_reg, fpu_mod,
650 1, 16, 17, 1, 16, 16,
651 NULL, NULL, NULL,
652 NULL, NULL, NULL
653};
Bob Supnik1da2d942003-12-31 11:49:00 -0800654
655
656/* ---- Programmable Interval Timer Device ----------- */
657
658int32 pit_time = 100;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700659int32 pit_tps = 10000; /* ticks per sec */
660int32 pit_adj = 20; /* tmxr adjust */
661int32 pit_poll = 16000; /* tmxr poll */
662int32 pit_initial = 0; /* initial counter reg */
663int32 pit_counter = 0; /* Counter */
664int32 pit_flag = 0; /* Initial setting flag */
Bob Supnik1da2d942003-12-31 11:49:00 -0800665
666int32 pit (int32 pulse, int32 code, int32 AC);
667t_stat pit_svc (UNIT *uptr);
668t_stat pit_reset (DEVICE *dptr);
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700669
Bob Supnik1da2d942003-12-31 11:49:00 -0800670/* PIT data structures
671
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700672 pit_dev device descriptor
673 pit_unit unit descriptor
674 pit_reg register list
Bob Supnik1da2d942003-12-31 11:49:00 -0800675*/
676
677DIB pit_dib = { DEV_PIT, INT_PIT, PI_PIT, &pit };
678
679UNIT pit_unit = { UDATA (&pit_svc, 0, 0) };
680
681REG pit_reg[] = {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700682 { 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};
Bob Supnik1da2d942003-12-31 11:49:00 -0800691
692DEVICE pit_dev = {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700693 "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
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800700t_stat sim_instr (void)
701{
702extern int32 sim_interval;
Bob Supnik1da2d942003-12-31 11:49:00 -0800703register int32 PC, IR, i, t, MA, j, k, tac;
Bob Supnikb6393b32004-11-23 15:49:00 -0800704register uint32 mddata, uAC0, uAC1, uAC2, uAC3;
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800705int16 sAC0, sAC1, sAC2;
Bob Supnik1da2d942003-12-31 11:49:00 -0800706int32 sddata, mi1, mi2, fpnum32;
707t_int64 fpnum, expon;
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800708t_value simeval[20];
709void mask_out (int32 mask);
710/* char debstr[128]; */
711/* char debadd[64]; */
712char debmap[4], debion[4];
713int debcar, iodev, iodata, debflags;
714int32 DisMap, debpc;
715/* int32 sp, sl; */
716int cmdptr, cmsptr, cmopt, cmptr;
717int16 cmslen, cmdlen;
718int tabaddr, tabptr;
719int32 effective(int32 PC, int32 index, int32 disp);
720int32 indirect(int32 d);
721int32 LEFmode(int32 PC, int32 index, int32 disp, int32 indirect);
722int32 LoadMap(int32 w);
723int32 Bytepointer(int32 PC, int32 index);
724int32 unimp(int32 PC);
725int32 pushrtn(int32 pc);
726
727/* Restore register state */
728
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700729if (build_devtab () != SCPE_OK) return SCPE_IERR; /* build dispatch */
730PC = saved_PC & AMASK; /* load local PC */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800731C = C & 0200000;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700732mask_out (pimask); /* reset int system */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800733reason = 0;
734if (MapInit == 0) {
735 MapInit = 1;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700736 for (mi1 = 0; mi1 < 6; mi1++) { /* Initialize MAPs */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800737 for (mi2 = 0; mi2 < 32; mi2++) {
738 Map[mi1][mi2] = mi2;
739 }
740 }
741}
742
743/* Main instruction fetch/decode loop */
744
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700745while (reason == 0) { /* loop until halted */
746if (sim_interval <= 0) { /* check clock queue */
Mark Pizzolato0f8e6cf2012-04-29 11:59:44 -0700747 if ((reason = sim_process_event ()))
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700748 break;
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800749}
750
Bob Supnik1da2d942003-12-31 11:49:00 -0800751//if (speed > 0) for (i = 0; i < speed; i++) { j = 0; }
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800752
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700753if (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;
Bob Supnik1da2d942003-12-31 11:49:00 -0800775}
776
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700777if (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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800787}
788
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700789if (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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800840
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700841if (Inhibit != 0) { /* Handle 1-instruction inhibit sequence */
842 if (Inhibit == 3) /* Used by SYC instruction */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800843 Inhibit = 4;
844 if (Inhibit == 4)
845 Inhibit = 0;
846}
847
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700848if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
849 reason = STOP_IBKPT; /* stop simulation */
850 break;
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800851}
852
853if ((PC < 1 || PC > 077777) && Debug_Flags) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700854 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800859}
860
861PPC = PC;
862
863if (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) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700878 debpc = PC;
879 simeval[0] = GetMap(PC);
880 simeval[1] = GetMap(PC+1);
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800881 } else {
882 debpc = 0177777;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700883 simeval[0] = XCT_inst;
884 simeval[1] = 0;
885 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800886 if (Debug_Flags & 0100000) {
887 fprintf(Trace, "%s%s%06o acs: %06o %06o %06o %06o %01o ",
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700888 debion, debmap, debpc, AC[0], AC[1], AC[2], AC[3], debcar);
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800889 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;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700899 Debug_Entry(debpc, (int32)simeval[0], (int32)simeval[1], AC[0], AC[1], AC[2], AC[3], debflags);
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800900 }
901}
902
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700903if (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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800907} else {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700908 IR = XCT_inst; /* Yes: Get inst to XCT */
909 XCT_mode = 0; /* Go back to normal mode */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800910}
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700911int_req = int_req | INT_NO_ION_PENDING; /* clear ION delay */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800912sim_interval = sim_interval - 1;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700913t = IR >> 11; /* prepare to decode */
914
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800915/* ---------------- 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
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700928if ((IR & 0100017) == 0100010) { /* This pattern for all */
929 /* Eclipse instructions */
930
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800931/****************************************************************/
932/* This is the standard Eclipse instruction set */
933/****************************************************************/
934
935 /* Byte operations */
936
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700937 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) {
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800942 AC[j] = GetMap(MA) & 0377;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700943 } else {
944 AC[j] = (GetMap(MA) >> 8) & 0377;
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800945 }
946 continue;
947 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700948 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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800955 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
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700967 if ((IR & 0162377) == 0122070) { /* ELDA: Extended LDA */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800968 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700981 if ((IR & 0162377) == 0142070) { /* ESTA: Extended STA */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800982 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700995 if ((IR & 0103777) == 0100010) { /* ADI: Add Immediate */
Bob Supnik4d6dfa42001-11-06 20:50:00 -0800996 t = (IR >> 11) & 3;
997 AC[t] = (AC[t] + ((IR >> 13) & 3) + 1) & 0xffff;
998 continue;
999 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001000 if ((IR & 0103777) == 0100110) { /* SBI: Subtract Immediate */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001001 t = (IR >> 11) & 3;
1002 AC[t] = (AC[t] - (((IR >> 13) & 3) + 1)) & 0xffff;
1003 continue;
1004 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001005 if ((IR & 0163777) == 0163770) { /* ADDI: Extended Add Immed. */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001006 t = (IR >> 11) & 3;
1007 i = GetMap(PC);
1008 PC = (PC + 1) & AMASK;
1009 AC[t] = (AC[t] + i) & 0xffff;
1010 continue;
1011 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001012 if ((IR & 0103777) == 0100710) { /* XCH: Exchange Accumulators */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001013 t = AC[(IR >> 11) & 3];
1014 AC[(IR >> 11) & 3] = AC[(IR >> 13) & 3];
1015 AC[(IR >> 13) & 3] = t;
1016 continue;
1017 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001018 if ((IR & 0162377) == 0162070) { /* ELEF: Load Effective Addr */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001019 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
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001027 if ((IR & 0163777) == 0143770) { /* ANDI: And Immediate */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001028 AC[(IR >> 11) & 3] &= GetMap(PC);
1029 PC = (PC + 1) & AMASK;
1030 continue;
1031 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001032 if ((IR & 0163777) == 0103770) { /* IORI: Inclusive Or Immed */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001033 AC[(IR >> 11) & 3] |= GetMap(PC);
1034 PC = (PC + 1) & AMASK;
1035 continue;
1036 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001037 if ((IR & 0163777) == 0123770) { /* XORI: Exclusive Or Immed */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001038 AC[(IR >> 11) & 3] ^= GetMap(PC);
1039 PC = (PC + 1) & AMASK;
1040 continue;
1041 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001042 if ((IR & 0103777) == 0100410) { /* IOR: Inclusive Or */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001043 AC[(IR >> 11) & 3] |= AC[(IR >> 13) & 3];
1044 continue;
1045 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001046 if ((IR & 0103777) == 0100510) { /* XOR: Exclusive Or */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001047 AC[(IR >> 11) & 3] ^= AC[(IR >> 13) & 3];
1048 continue;
1049 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001050 if ((IR & 0103777) == 0100610) { /* ANC: And with complemented src */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001051 AC[(IR >> 11) & 3] &= ~(AC[(IR >> 13) & 3]);
1052 continue;
1053 }
1054
1055 /* Shift operations */
1056
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001057 if ((IR & 0103777) == 0101210) { /* LSH: Logical Shift */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001058 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001071 if ((IR & 0103777) == 0101310) { /* DLSH: Double logical shift */
1072 register int16 sh;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001073 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001092 if ((IR & 0103777) == 0101410) { /* HXL: Hex shift left */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001093 t = ((IR >> 13) & 3) + 1;
1094 i = (IR >> 11) & 3;
1095 AC[i] = AC[i] << (t * 4);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001096 AC[i] &= 0xffff;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001097 continue;
1098 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001099 if ((IR & 0103777) == 0101510) { /* HXR: Hex shift right */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001100 t = ((IR >> 13) & 3) + 1;
1101 i = (IR >> 11) & 3;
1102 AC[i] = AC[i] >> (t * 4);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001103 AC[i] &= 0xffff;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001104 continue;
1105 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001106 if ((IR & 0103777) == 0101610) { /* DHXL: Double Hex shift left */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001107 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001118 if ((IR & 0103777) == 0101710) { /* DHXR: Double Hex shift right */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001119 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001130
1131 /* Bit operations */
1132
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001133 if ((IR & 0103777) == 0102010) { /* BTO: Set bit to one */
1134 i = (IR >> 11) & 3;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001135 j = (IR >> 13) & 3;
1136 if (i != j) {
1137 k = (AC[i] >> 4) & AMASK;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001138 if ((AC[j] + k) & 0100000)
1139 t = 1;
Bob Supnik1da2d942003-12-31 11:49:00 -08001140//AOS MA = indirect(AC[j] + k);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001141 MA = (AC[j] + k) & AMASK;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001142 } 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001150 if ((IR & 0103777) == 0102110) { /* BTZ: Set bit to zero */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001151 i = (IR >> 11) & 3;
1152 j = (IR >> 13) & 3;
1153 if (i != j) {
1154 k = (AC[i] >> 4) & AMASK;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001155 if ((AC[j] + k) & 0100000)
1156 t = 1;
Bob Supnik1da2d942003-12-31 11:49:00 -08001157//AOS MA = indirect(AC[j] + k);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001158 MA = (AC[j] + k) & AMASK;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001159 } 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001167 if ((IR & 0103777) == 0102210) { /* SZB: Skip on zero bit */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001168 i = (IR >> 11) & 3;
1169 j = (IR >> 13) & 3;
1170 if (i != j) {
1171 k = (AC[i] >> 4) & AMASK;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001172 if ((AC[j] + k) & 0100000)
1173 t = 1;
1174 MA = indirect(AC[j] + k);
1175// MA = (AC[j] + k) & AMASK;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001176 } 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001183 if ((IR & 0103777) == 0102770) { /* SNB: Skip on non-zero bit */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001184 i = (IR >> 11) & 3;
1185 j = (IR >> 13) & 3;
1186 if (i != j) {
1187 k = (AC[i] >> 4) & AMASK;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001188 if ((AC[j] + k) & 0100000)
1189 t = 1;
1190 MA = indirect(AC[j] + k);
1191// MA = (AC[j] + k) & AMASK;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001192 } 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001199 if ((IR & 0103777) == 0102310) { /* SZBO: skip on zero bit & set to 1 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001200 register int32 save;
1201 i = (IR >> 11) & 3;
1202 j = (IR >> 13) & 3;
1203 if (i != j) {
1204 k = (AC[i] >> 4) & AMASK;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001205 MA = indirect(AC[j] + k);
1206// MA = (AC[j] + k) & AMASK;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001207 } 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001219 if ((IR & 0103777) == 0102410) { /* LOB: Locate lead bit */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001220 register int32 a, r;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001221 register int16 b;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001222 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001232 if ((IR & 0103777) == 0102510) { /* LRB: Locate & reset lead bit */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001233 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001248 if ((IR & 0103777) == 0102610) { /* COB: Count bits */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001249 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
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001262 /* Jump & similar operations */
1263
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001264 if ((IR & 0176377) == 0102070) { /* EJMP: Extended JMP */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001265 PC = effective(PC, (IR >> 8) & 3, GetMap(PC));
1266 continue;
1267 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001268 if ((IR & 0176377) == 0106070) { /* EJSR: Extended JMP to subr */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001269 t = effective(PC, (IR >> 8) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001270 AC[3] = (PC + 1) & AMASK;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001271 PC = t & AMASK;
1272 continue;
1273 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001274 if ((IR & 0176377) == 0112070) { /* EISZ: Ext Inc & skip if 0 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001275 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001281 if ((IR & 0176377) == 0116070) { /* EDSZ: Ext Dec & skip if 0 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001282 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001288 if ((IR & 0103777) == 0101010) { /* SGT: Skip if ACS > ACD */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001289 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001296 if ((IR & 0103777) == 0101110) { /* SGE: Skip if ACS >= ACD */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001297 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001304 if ((IR & 0103777) == 0102370) { /* CLM: Compare to limits */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001305 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001323 if ((IR & 0163777) == 0123370) { /* XCT: Execute */
1324 XCT_mode = 1; /* Set up to execute on next loop */
1325 XCT_inst = AC[(IR >> 11) & 3];
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001326 continue;
1327 }
1328
1329 /* Memory block operations */
1330
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001331 if (IR == 0113710) { /* BAM: Block add & move */
1332 register int32 w;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001333 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001353 if (IR == 0133710) { /* BLM: Block move */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001354 t = AC[1];
1355 if (t < 1 || t > 0100000)
1356 continue;
1357 i = indirect(AC[2]);
1358 j = indirect(AC[3]);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001359 if (Fault) continue;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001360 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001374
1375 /* Stack operations */
1376
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001377 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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001410 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001411 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));
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001419 t = GetMap(040);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001420 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));
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001438 t = GetMap(040);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001439 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001446 continue;
1447 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001448 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001458 continue;
1459 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001460 if (IR == 0163710) { /* SAVE */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001461 register int32 savep;
1462 savep = ((GetMap(PC) + GetMap(040)) + 5) & AMASK;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001463 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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001471 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001489 if ((IR & 0163777) == 0103370) { /* MSP: Modify stack pointer */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001490 t = (GetMap(040) + AC[(IR >> 11) & 3]) & 0177777;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001491 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);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001499 continue;
1500 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001501 if ((IR & 0176377) == 0102270) { /* PSHJ: Push JMP */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001502 PutMap(040, (GetMap(040) + 1));
1503 PutMap((GetMap(040) & AMASK), ((PC + 1) & AMASK));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001504 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001511 PC = effective(PC, (IR >> 8) & 3, GetMap(PC));
1512 continue;
1513 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001514 if (IR == 0117710) { /* POPJ: Pop PC and Jump */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001515 PC = GetMap(GetMap(040)) & AMASK;
1516 PutMap(040, (GetMap(040) - 1));
1517 if (MapStat & 1) {
1518 Usermap = Enable;
1519 Inhibit = 0;
1520 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001521 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001529 continue;
1530 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001531 if (IR == 0107710) { /* POPB: Pop block */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001532 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);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001547 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001553 if (MapStat & 1) {
1554 Usermap = Enable;
1555 Inhibit = 0;
1556 }
1557 continue;
1558 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001559 if (IR == 0127710) { /* RTN: Return */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001560 PutMap(040, GetMap(041));
1561 PC = GetMap(GetMap(040)) & AMASK;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001562 t = GetMap(040);
1563 t = GetMap(t);
Bob Supnik1da2d942003-12-31 11:49:00 -08001564 if (t & 0100000)
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001565 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);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001579 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001585 if (MapStat & 1) {
1586 Usermap = Enable;
1587 Inhibit = 0;
1588 }
1589 continue;
1590 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001591 if (IR == 0167710) { /* RSTR: Restore */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001592 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);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001621 if (t < 0100000 && t < 0400) {
1622 pushrtn(PC);
1623 PC = indirect(GetMap(043));
1624 }*/
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001625 if (MapStat & 1) {
1626 Usermap = Enable;
1627 Inhibit = 0;
1628 }
1629 continue;
1630 }
1631
1632 /* Multiply / Divide */
1633
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001634 if (IR == 0143710) { /* MUL: Unsigned Multiply */
1635 uAC0 = (uint32) AC[0];
1636 uAC1 = (uint32) AC[1];
1637 uAC2 = (uint32) AC[2];
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001638
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001639 mddata = (uAC1 * uAC2) + uAC0;
1640 AC[0] = (mddata >> 16) & 0177777;
1641 AC[1] = mddata & 0177777;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001642 continue;
1643 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001644 if (IR == 0147710) { /* MULS: Signed Multiply */
1645 sAC0 = AC[0];
1646 sAC1 = AC[1];
1647 sAC2 = AC[2];
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001648
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001649 sddata = (sAC1 * sAC2) + sAC0;
1650 AC[0] = (sddata >> 16) & 0177777;
1651 AC[1] = sddata & 0177777;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001652 continue;
1653 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001654 if (IR == 0153710) { /* DIV: Unsigned Divide */
1655 uAC0 = (uint32) AC[0];
1656 uAC1 = (uint32) AC[1];
1657 uAC2 = (uint32) AC[2];
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001658
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001659 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001666 continue;
1667 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001668 if (IR == 0157710) { /* DIVS: Signed Divide */
1669 if ((AC[0] == 0) ||
Bob Supnik15919a22006-07-20 13:36:00 -07001670 ((AC[0] == 0100000) && (AC[1] == 0) && (AC[2] == 0177777)))
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001671 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001685 continue;
1686 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001687 if (IR == 0137710) { /* DIVX: Sign extend and Divide */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001688 int32 q;
1689 if (AC[1] & 0100000) {
1690 AC[0] = 0177777;
1691 } else {
1692 AC[0] = 0;
1693 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001694 sAC0 = AC[0];
1695 sAC1 = AC[1];
1696 sAC2 = AC[2];
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001697
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001698 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001707 continue;
1708 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001709 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001718 continue;
1719 }
1720
1721 /* Decimal arithmetic */
1722
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001723 if ((IR & 0103777) == 0100210) { /* DAD: Decimal add */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001724 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001738 if ((IR & 0103777) == 0100310) { /* DSB: Decimal subtract */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001739 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
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001756 if ((IR & 0162377) == 0142170) { /* DSPA: Dispatch */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001757 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001772 PC = indirect(d) & AMASK;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001773 continue;
1774 }
1775
1776 if (((IR & 0100077) == 0100030) ||
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001777 ((IR & 0102077) == 0100070)) { /* XOP: Extended Operation */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001778 register int32 op, d, sa, da;
1779 op = (IR >> 6) & 037;
1780 if ((IR & 077) == 070) op += 32;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001781 t = GetMap(040) & AMASK;
1782 for (i = 0; i <= 3; i++) {
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001783 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);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001795 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001802 continue;
1803 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001804 if ((IR & 0103777) == 0103510) { /* SYC: System call */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001805 register int32 j;
1806 DisMap = Usermap;
1807 Usermap = 0;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001808 MapStat &= ~1; /* Disable MAP */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001809 i = (IR >> 13) & 3;
1810 j = (IR >> 11) & 3;
1811 if (i != 0 || j != 0) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001812 t = (GetMap(040) + 1) & AMASK;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001813 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)
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001828 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001835 continue;
1836 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001837 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);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001841 t = AC[1];
1842 i = AC[2];
1843 while (t) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001844 if (int_req > INT_PENDING && !Inhibit) { /* interrupt? */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001845 PC = PC - 1;
1846 break;
1847 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001848 if (!Usermap || !(MapStat & 0140)) { /* Only load if in sup mode */
1849 w = (GetMap(i) + AC[0]) & 0xffff; /* Or not IO & LEF mode for user */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001850 m = (w >> 10) & 037;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001851 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);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001854 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;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001863 MapStat &= ~02000;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001864 continue;
1865 }
1866
1867/****************************************************************/
1868/* Character Instruction Set */
1869/****************************************************************/
1870
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001871 if ((IR & 0162377) == 0102170) { /* ELDB */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001872 t = Bytepointer(PC, (IR >> 8) & 3);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001873 i = (IR >> 11) & 03;
1874 MA = (t >> 1) & AMASK;
1875 if (t & 01) {
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001876 AC[i] = GetMap(MA) & 0377;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001877 } else {
1878 AC[i] = (GetMap(MA) >> 8) & 0377;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001879 }
1880 PC = (PC + 1) & AMASK;
1881 continue;
1882 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001883 if ((IR & 0162377) == 0122170) { /* ESTB */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001884 t = Bytepointer(PC, (IR >> 8) & 3);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001885 i = (IR >> 11) & 03;
1886 MA = (t >> 1) & AMASK;
1887 j = GetMap(MA);
1888 if (t & 01) {
1889 j &= 0177400;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001890 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
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001901 if ((IR & 077) == 050) { /* All CIS end with 050 except ELDB/ESTB */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001902
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001903 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001913 if (cmslen == 0) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001914 uAC2 = ' ' & 0377; /* Handle short source */
Bob Supnik1da2d942003-12-31 11:49:00 -08001915 } else {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001916 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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001926 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) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001934 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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001951 continue;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001952 }
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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001967 }
1968 } else {
1969 uAC2 = ' ' & 0377;
1970 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001971 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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08001977 }
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) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001990 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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002012 continue;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002013 }
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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002032 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002033 cmptr = tabptr + j; /* Translate */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002034 MA = (cmptr >> 1) & AMASK;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002035 if (cmptr & 01) {
2036 uAC2 = GetMap(MA) & 0377;
2037 } else {
2038 uAC2 = (GetMap(MA) >> 8) & 0377;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002039 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002040 if (cmopt) { /* MOVE... */
2041 MA = (cmdptr >> 1) & AMASK; /* do an STB */
2042 j = GetMap(MA);
2043 if (cmdptr & 01) {
2044 j &= 0177400;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002045 j |= (uAC2 & 0377);
2046 PutMap(MA, j);
2047 } else {
2048 j &= 0377;
2049 j |= (uAC2 & 0377) << 8;
2050 PutMap(MA, j);
2051 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002052 } 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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002058 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002059 cmptr = tabptr + j; /* Translate */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002060 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002075 cmsptr++;
2076 cmdptr++;
2077 cmslen--;
2078 if (cmslen == 0)
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002079 break;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002080 }
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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002108 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) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002116 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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002132 continue;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002133 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002134
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
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002141 if ((IR & 0163777) == 0103650) { /* LDI Load Integer */
2142 unimp(PC);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002143 continue;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002144 }
2145 if ((IR & 0163777) == 0123650) { /* STI Store Integer */
2146 unimp(PC);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002147 continue;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002148 }
2149 if (IR == 0143650) { /* LDIX Load Int Extended */
2150 unimp(PC);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002151 continue;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002152 }
2153 if (IR == 0143750) { /* STIX Store Int Extended */
2154 unimp(PC);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002155 continue;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002156 }
2157 if ((IR & 0163777) == 0143150) { /* FINT Integerize */
2158 unimp(PC);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002159 continue;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002160 }
2161 if (IR == 0177650) { /* LSN Load Sign */
2162 unimp(PC);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002163 continue;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002164 }
2165 if (IR == 0173650) { /* EDIT */
2166 unimp(PC);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002167 continue;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002168 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002169 }
2170
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002171 /* FPU Instructions */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002172
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002173 if ((IR & 0163777) == 0123350) { /* FLST Load Status */
2174 if (!(fpu_unit.flags & UNIT_UP))
2175 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002176 if (Debug_Flags == 1) {
2177 printf("\n<<FPU instruction: FLST>>\n");
2178 reason = STOP_IBKPT;
2179 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002180 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08002198 MA = effective(PC, (IR >> 11) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002199 FPSR = (GetMap(MA) << 16);
2200 FPSR |= (GetMap(MA + 1));
2201 FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */
2202 FPSR |= ((PC - 1) & AMASK);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002203 PC = (PC + 1) & AMASK;
2204 continue;
2205 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002206 if ((IR & 0163777) == 0103350) { /* FSST Store Status */
2207 if (!(fpu_unit.flags & UNIT_UP))
2208 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002209 if (Debug_Flags == 1) {
2210 printf("\n<<FPU instruction: FSST>>\n");
2211 reason = STOP_IBKPT;
2212 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002213 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 }
Bob Supnik1da2d942003-12-31 11:49:00 -08002230 MA = effective(PC, (IR >> 11) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002231 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);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002257 PC = (PC + 1) & AMASK;
2258 continue;
2259 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002260 if ((IR & 0103777) == 0102050) { /* FLDS Load FP single */
2261 if (!(fpu_unit.flags & UNIT_UP))
2262 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002263 if (Debug_Flags == 1) {
2264 printf("\n<<FPU instruction: FLDS>>\n");
2265 reason = STOP_IBKPT;
2266 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002267 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08002286 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002287 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08002300 PC = (PC + 1) & AMASK;
2301 continue;
2302 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002303 if ((IR & 0103777) == 0102150) { /* FLDD Load FP double */
2304 if (!(fpu_unit.flags & UNIT_UP))
2305 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002306 if (Debug_Flags == 1) {
2307 printf("\n<<FPU instruction: FLDD>>\n");
2308 reason = STOP_IBKPT;
2309 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002310 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08002329 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002330 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08002347 PC = (PC + 1) & AMASK;
2348 continue;
2349 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002350 if ((IR & 0103777) == 0102250) { /* FSTS Store FP single */
2351 if (!(fpu_unit.flags & UNIT_UP))
2352 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002353 if (Debug_Flags == 1) {
2354 printf("\n<<FPU instruction: FSTS>>\n");
2355 reason = STOP_IBKPT;
2356 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002357 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08002375 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002376 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08002380 PC = (PC + 1) & AMASK;
2381 continue;
2382 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002383 if ((IR & 0103777) == 0102350) { /* FSTD Store FP double */
2384 if (!(fpu_unit.flags & UNIT_UP))
2385 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002386 if (Debug_Flags == 1) {
2387 printf("\n<<FPU instruction: FSTD>>\n");
2388 reason = STOP_IBKPT;
2389 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002390 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08002408 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002409 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08002415 PC = (PC + 1) & AMASK;
2416 continue;
2417 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002418 if ((IR & 0103777) == 0103550) { /* FMOV Move FP */
2419 if (!(fpu_unit.flags & UNIT_UP))
2420 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002421 if (Debug_Flags == 1) {
2422 printf("\n<<FPU instruction: FMOV>>\n");
2423 reason = STOP_IBKPT;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002424 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002425 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002426 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 }
Bob Supnik1da2d942003-12-31 11:49:00 -08002443 i = (IR >> 13) & 3;
2444 j = (IR >> 11) & 3;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002445 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08002455 continue;
2456 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002457 if (IR == 0143350) { /* FTE Trap Enable */
2458 if (!(fpu_unit.flags & UNIT_UP))
2459 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002460 if (Debug_Flags == 2) {
2461 printf("\n<<FPU instruction: FTE>>\n");
2462 reason = STOP_IBKPT;
2463 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002464 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);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002484 continue;
2485 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002486 if (IR == 0147350) { /* FTD Trap Disable */
2487 if (!(fpu_unit.flags & UNIT_UP))
2488 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002489 if (Debug_Flags == 1) {
2490 printf("\n<<FPU instruction: FTD>>\n");
2491 reason = STOP_IBKPT;
2492 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002493 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08002513 continue;
2514 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002515 if ((IR & 0103777) == 0102450) { /* FLAS Float from AC */
2516 if (!(fpu_unit.flags & UNIT_UP))
2517 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002518 if (Debug_Flags == 1) {
2519 printf("\n<<FPU instruction: FLAS>>\n");
2520 reason = STOP_IBKPT;
2521 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002522 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);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002572 continue;
2573 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002574 if ((IR & 0103777) == 0102550) { /* FLMD Float from memory */
2575 if (!(fpu_unit.flags & UNIT_UP))
2576 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002577 if (Debug_Flags == 1) {
2578 printf("\n<<FPU instruction: FLMD>>\n");
2579 reason = STOP_IBKPT;
2580 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002581 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08002600 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
2601 PC = (PC + 1) & AMASK;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002602 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);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08002636 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002637 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002638 if ((IR & 0103777) == 0102650) { /* FFAS Fix to AC */
2639 if (!(fpu_unit.flags & UNIT_UP))
2640 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002641 if (Debug_Flags == 1) {
2642 printf("\n<<FPU instruction: FFAS>>\n");
2643 reason = STOP_IBKPT;
2644 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002645 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];
Bob Supnik1da2d942003-12-31 11:49:00 -08002665
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002666 t = 0;
Bob Supnik1da2d942003-12-31 11:49:00 -08002667
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002668 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
Bob Supnik1da2d942003-12-31 11:49:00 -08002669
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002670 /* Get register content */
2671 get_lf(&dfl, &FPAC[j]);
Bob Supnik1da2d942003-12-31 11:49:00 -08002672
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002673 if (dfl.long_fract) {
2674 /* not zero */
2675 normal_lf(&dfl);
Bob Supnik1da2d942003-12-31 11:49:00 -08002676
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002677 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08002739 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002740 if ((IR & 0103777) == 0102750) { /* FFMD Fix to Memory */
2741 if (!(fpu_unit.flags & UNIT_UP))
2742 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002743 if (Debug_Flags == 1) {
2744 printf("\n<<FPU instruction: FFMD>>\n");
2745 reason = STOP_IBKPT;
2746 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002747 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08002767
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002768 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08002775
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002776 FPSR &= 0xFCFFFFFF; /* Z+N bits off */
Bob Supnik1da2d942003-12-31 11:49:00 -08002777
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002778 /* Get register content */
2779 get_lf(&dfl, &FPAC[j]);
Bob Supnik1da2d942003-12-31 11:49:00 -08002780
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002781 if (dfl.long_fract) {
2782 /* not zero */
2783 normal_lf(&dfl);
Bob Supnik1da2d942003-12-31 11:49:00 -08002784
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002785 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 }
Bob Supnik1da2d942003-12-31 11:49:00 -08002839
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002840 if (dfl.sign && i != 0)
2841 i |= 0x80000000;
Bob Supnik1da2d942003-12-31 11:49:00 -08002842
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002843 if (t == 1)
2844 i = 0x4a430000;
2845 if (t == 2)
2846 i = 0x27e00000;
2847 if (t == 3)
2848 i = 0xF925FD00;
Bob Supnik1da2d942003-12-31 11:49:00 -08002849
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002850 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08002859 if (Debug_Flags == 1) {
2860 printf("\n<<FPU instruction: FAS>>\n");
2861 reason = STOP_IBKPT;
2862 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002863 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08002906 continue;
2907 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002908 if ((IR & 0103777) == 0101050) { /* FAMS Add single (memory) */
2909 if (!(fpu_unit.flags & UNIT_UP))
2910 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002911 if (Debug_Flags == 1) {
2912 printf("\n<<FPU instruction: FAMS>>\n");
2913 reason = STOP_IBKPT;
2914 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002915 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08002933 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002934 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08002962 PC = (PC + 1) & AMASK;
2963 continue;
2964 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002965 if ((IR & 0103777) == 0100150) { /* FAD Add double */
2966 if (!(fpu_unit.flags & UNIT_UP))
2967 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08002968 if (Debug_Flags == 1) {
2969 printf("\n<<FPU instruction: FAD>>\n");
2970 reason = STOP_IBKPT;
2971 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002972 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003015 continue;
3016 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003017 if ((IR & 0103777) == 0101150) { /* FAMD Add double (memory) */
3018 if (!(fpu_unit.flags & UNIT_UP))
3019 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003020 if (Debug_Flags == 1) {
3021 printf("\n<<FPU instruction: FAMD>>\n");
3022 reason = STOP_IBKPT;
3023 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003024 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08003042 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003043 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003073 PC = (PC + 1) & AMASK;
3074 continue;
3075 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003076 if ((IR & 0103777) == 0100250) { /* FSS Sub single to AC */
3077 if (!(fpu_unit.flags & UNIT_UP))
3078 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003079 if (Debug_Flags == 1) {
3080 printf("\n<<FPU instruction: FSS>>\n");
3081 reason = STOP_IBKPT;
3082 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003083 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003127 continue;
3128 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003129 if ((IR & 0103777) == 0101250) { /* FSMS Sub single (memory) */
3130 if (!(fpu_unit.flags & UNIT_UP))
3131 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003132 if (Debug_Flags == 1) {
3133 printf("\n<<FPU instruction: FSMS>>\n");
3134 reason = STOP_IBKPT;
3135 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003136 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08003154 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003155 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003184 PC = (PC + 1) & AMASK;
3185 continue;
3186 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003187 if ((IR & 0103777) == 0100350) { /* FSD Sub double from AC */
3188 if (!(fpu_unit.flags & UNIT_UP))
3189 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003190 if (Debug_Flags == 1) {
3191 printf("\n<<FPU instruction: FSD>>\n");
3192 reason = STOP_IBKPT;
3193 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003194 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003238 continue;
3239 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003240 if ((IR & 0103777) == 0101350) { /* FSMD Sub double from memory */
3241 if (!(fpu_unit.flags & UNIT_UP))
3242 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003243 if (Debug_Flags == 1) {
3244 printf("\n<<FPU instruction: FSMD>>\n");
3245 reason = STOP_IBKPT;
3246 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003247 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08003265 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003266 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003297 PC = (PC + 1) & AMASK;
3298 continue;
3299 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003300 if ((IR & 0103777) == 0100450) { /* FMS Mult single by AC */
3301 if (!(fpu_unit.flags & UNIT_UP))
3302 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003303 if (Debug_Flags == 1) {
3304 printf("\n<<FPU instruction: FMS>>\n");
3305 reason = STOP_IBKPT;
3306 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003307 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003350 continue;
3351 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003352 if ((IR & 0103777) == 0101450) { /* FMMS Mult single by memory */
3353 if (!(fpu_unit.flags & UNIT_UP))
3354 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003355 if (Debug_Flags == 1) {
3356 printf("\n<<FPU instruction: FMMS>>\n");
3357 reason = STOP_IBKPT;
3358 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003359 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08003377 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003378 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003406 PC = (PC + 1) & AMASK;
3407 continue;
3408 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003409 if ((IR & 0103777) == 0100550) { /* FMD Mult double by AC */
3410 if (!(fpu_unit.flags & UNIT_UP))
3411 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003412 if (Debug_Flags == 1) {
3413 printf("\n<<FPU instruction: FMD>>\n");
3414 reason = STOP_IBKPT;
3415 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003416 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003459 continue;
3460 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003461 if ((IR & 0103777) == 0101550) { /* FMMD Mult double by memory */
3462 if (!(fpu_unit.flags & UNIT_UP))
3463 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003464 if (Debug_Flags == 1) {
3465 printf("\n<<FPU instruction: FMMD>>\n");
3466 reason = STOP_IBKPT;
3467 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003468 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08003486 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003487 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003517 PC = (PC + 1) & AMASK;
3518 continue;
3519 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003520 if ((IR & 0103777) == 0100650) { /* FDS Div single by AC */
3521 if (!(fpu_unit.flags & UNIT_UP))
3522 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003523 if (Debug_Flags == 1) {
3524 printf("\n<<FPU instruction: FDS>>\n");
3525 reason = STOP_IBKPT;
3526 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003527 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003573 continue;
3574 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003575 if ((IR & 0103777) == 0101650) { /* FDMS Div single by memory */
3576 if (!(fpu_unit.flags & UNIT_UP))
3577 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003578 if (Debug_Flags == 1) {
3579 printf("\n<<FPU instruction: FDMS>>\n");
3580 reason = STOP_IBKPT;
3581 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003582 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08003600 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003601 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003632 PC = (PC + 1) & AMASK;
3633 continue;
3634 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003635 if ((IR & 0103777) == 0100650) { /* FDD Div double by AC */
3636 if (!(fpu_unit.flags & UNIT_UP))
3637 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003638 if (Debug_Flags == 1) {
3639 printf("\n<<FPU instruction: FDD>>\n");
3640 reason = STOP_IBKPT;
3641 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003642 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003688 continue;
3689 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003690 if ((IR & 0103777) == 0101650) { /* FDMD Div double by memory */
3691 if (!(fpu_unit.flags & UNIT_UP))
3692 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003693 if (Debug_Flags == 1) {
3694 printf("\n<<FPU instruction: FDMD>>\n");
3695 reason = STOP_IBKPT;
3696 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003697 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;
Bob Supnik1da2d942003-12-31 11:49:00 -08003715 MA = effective(PC, (IR >> 13) & 3, GetMap(PC));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003716 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003749 PC = (PC + 1) & AMASK;
3750 continue;
3751 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003752 if ((IR & 0163777) == 0163050) { /* FNEG Negate */
3753 if (!(fpu_unit.flags & UNIT_UP))
3754 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003755 if (Debug_Flags == 1) {
3756 printf("\n<<FPU instruction: FNEG>>\n");
3757 reason = STOP_IBKPT;
3758 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003759 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003790 continue;
3791 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003792 if ((IR & 0163777) == 0143050) { /* FAB Absolute Value*/
3793 if (!(fpu_unit.flags & UNIT_UP))
3794 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003795 if (Debug_Flags == 1) {
3796 printf("\n<<FPU instruction: FAB>>\n");
3797 reason = STOP_IBKPT;
3798 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003799 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003830 continue;
3831 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003832 if ((IR & 0163777) == 0103050) { /* FNOM Normalize*/
3833 if (!(fpu_unit.flags & UNIT_UP))
3834 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003835 if (Debug_Flags == 1) {
3836 printf("\n<<FPU instruction: FNOM>>\n");
3837 reason = STOP_IBKPT;
3838 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003839 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003872 continue;
3873 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003874 if ((IR & 0163777) == 0123050) { /* FRH Read High Word */
3875 if (!(fpu_unit.flags & UNIT_UP))
3876 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003877 if (Debug_Flags == 1) {
3878 printf("\n<<FPU instruction: FRH>>\n");
3879 reason = STOP_IBKPT;
3880 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003881 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003902 continue;
3903 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003904 if ((IR & 0163777) == 0123150) { /* FEXP Load Exponent */
3905 if (!(fpu_unit.flags & UNIT_UP))
3906 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003907 if (Debug_Flags == 1) {
3908 printf("\n<<FPU instruction: FEXP>>\n");
3909 reason = STOP_IBKPT;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003910 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003911 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003912 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003941 continue;
3942 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003943 if ((IR & 0103777) == 0103450) { /* FCMP FP Compare */
3944 if (!(fpu_unit.flags & UNIT_UP)) /* (Subtract double AC without storing result) */
3945 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003946 if (Debug_Flags == 1) {
3947 printf("\n<<FPU instruction: FCMP>>\n");
3948 reason = STOP_IBKPT;
3949 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003950 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08003993 continue;
3994 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003995 if (IR == 0163350) { /* FPSH Push State */
3996 if (!(fpu_unit.flags & UNIT_UP))
3997 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08003998 if (Debug_Flags == 2) {
3999 printf("\n<<FPU instruction: FPSH>>\n");
4000 reason = STOP_IBKPT;
4001 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004002 /* 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004040 continue;
4041 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004042 if (IR == 0167350) { /* FPOP Pop State */
4043 if (!(fpu_unit.flags & UNIT_UP))
4044 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004045 if (Debug_Flags == 2) {
4046 printf("\n<<FPU instruction: FPOP>>\n");
4047 reason = STOP_IBKPT;
4048 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004049 /* 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004088 continue;
4089 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004090 if ((IR & 0163777) == 0163150) { /* FHLV Halve */
4091 if (!(fpu_unit.flags & UNIT_UP))
4092 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004093 if (Debug_Flags == 1) {
4094 printf("\n<<FPU instruction: FHLV>>\n");
4095 reason = STOP_IBKPT;
4096 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004097 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08004129 continue;
4130 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004131 if ((IR & 0163777) == 0103150) { /* FSCAL Scale */
4132 if (!(fpu_unit.flags & UNIT_UP))
4133 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004134 if (Debug_Flags == 1) {
4135 printf("\n<<FPU instruction: FSCAL>>\n");
4136 reason = STOP_IBKPT;
4137 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004138 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08004186 continue;
4187 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004188 if (IR == 0153350) { /* FCLE Clear Errors */
4189 if (!(fpu_unit.flags & UNIT_UP))
4190 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004191 if (Debug_Flags == 1) {
4192 printf("\n<<FPU instruction: FCLE>>\n");
4193 reason = STOP_IBKPT;
4194 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004195 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08004215 continue;
4216 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004217 if (IR == 0103250) { /* FNS No Skip */
4218 if (!(fpu_unit.flags & UNIT_UP))
4219 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004220 if (Debug_Flags == 1) {
4221 printf("\n<<FPU instruction: FNS>>\n");
4222 reason = STOP_IBKPT;
4223 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004224 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);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004243 continue;
4244 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004245 if (IR == 0107250) { /* FSA Always Skip */
4246 if (!(fpu_unit.flags & UNIT_UP))
4247 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004248 if (Debug_Flags == 2) {
4249 printf("\n<<FPU instruction: FSA>>\n");
4250 reason = STOP_IBKPT;
4251 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004252 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08004271 PC = (PC + 1) & AMASK;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004272 continue;
4273 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004274 if (IR == 0137250) { /* FSGT */
4275 if (!(fpu_unit.flags & UNIT_UP))
4276 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004277 if (Debug_Flags == 1) {
4278 printf("\n<<FPU instruction: FSGT>>\n");
4279 reason = STOP_IBKPT;
4280 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004281 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004302 continue;
4303 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004304 if (IR == 0123250) { /* FSLT */
4305 if (!(fpu_unit.flags & UNIT_UP))
4306 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004307 if (Debug_Flags == 1) {
4308 printf("\n<<FPU instruction: FSLT>>\n");
4309 reason = STOP_IBKPT;
4310 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004311 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004332 continue;
4333 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004334 if (IR == 0113250) { /* FSEQ */
4335 if (!(fpu_unit.flags & UNIT_UP))
4336 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004337 if (Debug_Flags == 1) {
4338 printf("\n<<FPU instruction: FSEQ>>\n");
4339 reason = STOP_IBKPT;
4340 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004341 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004362 continue;
4363 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004364 if (IR == 0133250) { /* FSLE */
4365 if (!(fpu_unit.flags & UNIT_UP))
4366 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004367 if (Debug_Flags == 1) {
4368 printf("\n<<FPU instruction: FSLE>>\n");
4369 reason = STOP_IBKPT;
4370 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004371 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004392 continue;
4393 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004394 if (IR == 0127250) { /* FSGE */
4395 if (!(fpu_unit.flags & UNIT_UP))
4396 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004397 if (Debug_Flags == 1) {
4398 printf("\n<<FPU instruction: FSGE>>\n");
4399 reason = STOP_IBKPT;
4400 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004401 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004422 continue;
4423 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004424 if (IR == 0117250) { /* FSNE */
4425 if (!(fpu_unit.flags & UNIT_UP))
4426 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004427 if (Debug_Flags == 1) {
4428 printf("\n<<FPU instruction: FSNE>>\n");
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004429 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004430 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004431 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004452 continue;
4453 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004454 if (IR == 0143250) { /* FSNM */
4455 if (!(fpu_unit.flags & UNIT_UP))
4456 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004457 if (Debug_Flags == 1) {
4458 printf("\n<<FPU instruction: FSNM>>\n");
4459 reason = STOP_IBKPT;
4460 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004461 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004482 continue;
4483 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004484 if (IR == 0153250) { /* FSNU */
4485 if (!(fpu_unit.flags & UNIT_UP))
4486 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004487 if (Debug_Flags == 1) {
4488 printf("\n<<FPU instruction: FSNU>>\n");
4489 reason = STOP_IBKPT;
4490 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004491 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004512 continue;
4513 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004514 if (IR == 0163250) { /* FSNO */
4515 if (!(fpu_unit.flags & UNIT_UP))
4516 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004517 if (Debug_Flags == 1) {
4518 printf("\n<<FPU instruction: FSNO>>\n");
4519 reason = STOP_IBKPT;
4520 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004521 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004542 continue;
4543 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004544 if (IR == 0147250) { /* FSND */
4545 if (!(fpu_unit.flags & UNIT_UP))
4546 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004547 if (Debug_Flags == 1) {
4548 printf("\n<<FPU instruction: FSND>>\n");
4549 reason = STOP_IBKPT;
4550 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004551 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004572 continue;
4573 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004574 if (IR == 0157250) { /* FSNUD */
4575 if (!(fpu_unit.flags & UNIT_UP))
4576 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004577 if (Debug_Flags == 1) {
4578 printf("\n<<FPU instruction: FSNUD>>\n");
4579 reason = STOP_IBKPT;
4580 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004581 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004602 continue;
4603 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004604 if (IR == 0167250) { /* FSNOD */
4605 if (!(fpu_unit.flags & UNIT_UP))
4606 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004607 if (Debug_Flags == 1) {
4608 printf("\n<<FPU instruction: FSNOD>>\n");
4609 reason = STOP_IBKPT;
4610 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004611 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004632 continue;
4633 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004634 if (IR == 0173250) { /* FSNUO */
4635 if (!(fpu_unit.flags & UNIT_UP))
4636 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004637 if (Debug_Flags == 1) {
4638 printf("\n<<FPU instruction: FSNUO>>\n");
4639 reason = STOP_IBKPT;
4640 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004641 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004662 continue;
4663 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004664 if (IR == 0177250) { /* FSNER */
4665 if (!(fpu_unit.flags & UNIT_UP))
4666 continue;
Bob Supnik1da2d942003-12-31 11:49:00 -08004667 if (Debug_Flags == 1) {
4668 printf("\n<<FPU instruction: FSNER>>\n");
4669 reason = STOP_IBKPT;
4670 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004671 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004692 continue;
4693 }
4694
4695 if (Debug_Flags) {
Bob Supnik1da2d942003-12-31 11:49:00 -08004696 printf("\n<<Unexecuted inst = %o at PC=%o>>\n\r", IR, PC-1);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004697 if (Debug_Flags & 040000) reason = STOP_IBKPT;
4698 }
4699}
4700
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004701if (IR == 061777) { /* VCT: Vector on Interrupt */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004702 int32 stkchg, vtable;
4703 int32 ventry, dctadr;
4704 int32 old40, old41, old42, old43;
4705
4706 /* Ok, folks, this is one helluva instruction */
4707
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004708 stkchg = GetMap(PC) & 0100000; /* Save stack change bit */
4709 vtable = GetMap(PC) & AMASK; /* Address of vector table */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004710
4711 iodev = 0;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004712 int_req = (int_req & ~INT_DEV) | /* Do an INTA w/o an accum */
4713 (dev_done & ~dev_disable);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004714 iodata = int_req & (-int_req);
4715 for (i = DEV_LOW; i <= DEV_HIGH; i++) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004716 if (iodata & dev_table[i].mask) {
4717 iodev = i;
4718 break;
4719 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004720 }
4721
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004722 ventry = GetMap(vtable + iodev); /* Get Vector Entry */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004723
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004724 if (!(ventry & 0100000)) { /* Direct bit = 0? */
4725 PC = ventry & AMASK; /* YES - Mode A, so JMP */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004726 continue;
4727 }
4728
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004729 dctadr = ventry & AMASK; /* Get address of DCT entry */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004730
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004731 if (stkchg) { /* Stack change bit = 1? */
4732 old40 = GetMap(040); /* Save stack info */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004733 old41 = GetMap(041);
4734 old42 = GetMap(042);
4735 old43 = GetMap(043);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004736 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004740 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
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004749 t = GetMap(dctadr & AMASK); /* Get word 0 of DCT */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004750
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004751 if (t & 0100000) { /* Push bit set ? */
4752 PutMap(040, (GetMap(040) + 1)); /* Push "Standard rtn block" */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004753 PutMap(GetMap(040) & AMASK, AC[0]);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004754 PutMap(040, (GetMap(040) + 1));
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004755 PutMap(GetMap(040) & AMASK, AC[1]);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004756 PutMap(040, (GetMap(040) + 1));
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004757 PutMap(GetMap(040) & AMASK, AC[2]);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004758 PutMap(040, (GetMap(040) + 1));
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004759 PutMap(GetMap(040) & AMASK, AC[3]);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004760 PutMap(040, (GetMap(040) + 1));
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004761 PutMap(GetMap(040) & AMASK, GetMap(0));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004762 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));
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004767 }
4768
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004769 AC[2] = dctadr & AMASK; /* DCT Addr into AC2 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004770
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004771 PutMap(040, (GetMap(040) + 1)); /* Push pri int mask onto stack */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004772 PutMap(GetMap(040) & AMASK, pimask);
4773
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004774 AC[0] = GetMap(dctadr + 1) | pimask; /* Build new mask from word 1 of dct */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004775 PutMap(005, AC[0]);
4776
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004777 mask_out(pimask = AC[0]); /* Do a mask out inst */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004778
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004779 PC = GetMap(dctadr) & AMASK; /* Finally, JMP to int routine */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004780
4781 continue;
4782}
4783
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004784/*************************************************************************
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
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004789/* Memory reference instructions */
4790
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004791if (t < 014) { /* mem ref? */
4792 register int32 src, MA;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004793
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004794 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
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004941/* Operate instruction */
4942
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004943else if (t & 020) { /* operate? */
4944 register int32 src, srcAC, dstAC;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08004945
Bob Supnikb7c1eae2005-09-09 18:09:00 -07004946 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
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005035/* IOT instruction */
5036
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005037else { /* 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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005047 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005048 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005099
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005100 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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005148
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005149 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
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005328/* Simulation halted */
5329
5330saved_PC = PC;
5331return reason;
5332}
5333
5334/* Computes and returns a 16-bit effective address, given a
5335 program counter, index, and a displacement.
5336*/
5337
5338int32 effective(int32 PC, int32 index, int32 disp)
5339{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005340 register int32 i, MA;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005341
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005342 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);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005376}
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
5384int32 LEFmode(int32 PC, int32 index, int32 disp, int32 indirect)
5385{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005386 register int32 i, MA;
5387 int16 sMA;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005388
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005389 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);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005433}
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
5438int32 Bytepointer(int32 PC, int32 index)
5439{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005440 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);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005459}
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
5465int32 indirect(int32 d)
5466{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005467 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);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005491}
5492
5493/* Push a standard return block onto the stack */
5494
5495int32 pushrtn(int32 pc)
5496{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005497 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;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005512}
5513
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005514/* Eclipse memory get/put - uses MAP if enabled */
5515
5516int32 GetMap(int32 addr)
5517{
5518 int32 page;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005519 t_addr paddr;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005520
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)
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005535 Fault = 0100000/*!!!*/; /* Validity */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005536 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)
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005545 Fault = 0100000/*!!!*/; /* Validity */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005546 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)
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005555 Fault = 0100000/*!!!*/; /* Validity */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005556 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)
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005565 Fault = 0100000/*!!!*/; /* Validity */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005566 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
5578int32 PutMap(int32 addr, int32 data)
5579{
5580 int32 page;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005581 t_addr paddr;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005582
5583 switch (Usermap) {
5584 case 0:
5585 if (addr < 076000) {
5586 M[addr] = data;
5587 return (data);
Bob Supnik1da2d942003-12-31 11:49:00 -08005588 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005589 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08005595 if (((Map[1][page] & 0100000) && (MapStat & 020)) || Map[1][page] == INVALID)
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005596 Fault = 010000; /* Write Protect Fault */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005597 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08005602 if (((Map[2][page] & 0100000) && (MapStat & 020)) || Map[2][page] == INVALID)
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005603 Fault = 010000; /* Write Protect Fault */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005604 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08005609 if (((Map[6][page] & 0100000) && (MapStat & 020)) || Map[6][page] == INVALID)
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005610 Fault = 010000; /* Write Protect Fault */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005611 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);
Bob Supnik1da2d942003-12-31 11:49:00 -08005616 if (((Map[7][page] & 0100000) && (MapStat & 020)) || Map[7][page] == INVALID)
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005617 Fault = 010000; /* Write Protect Fault */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005618 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
5628int16 GetDCHMap(int32 map, int32 addr)
5629{
Bob Supnik1da2d942003-12-31 11:49:00 -08005630 t_addr paddr;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005631 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
5638int16 PutDCHMap(int32 map, int32 addr, int16 data)
5639{
Bob Supnik1da2d942003-12-31 11:49:00 -08005640 t_addr paddr;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005641 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)
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005647 M[paddr] = data;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005648 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
5657int32 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
5668int32 LoadMap(int32 w)
5669{
5670 int32 m;
5671
5672 m = (w >> 10) & 037;
5673 switch ((MapStat >> 7) & 07) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005674 case 0: /* Load user A Map */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005675 Map[1][m] = w & MAPMASK;
5676 break;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005677 case 1: /* Load user C Map */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005678 Map[6][m] = w & MAPMASK;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005679 break;
5680 case 2: /* Load user B Map */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005681 Map[2][m] = w & MAPMASK;
5682 break;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005683 case 3: /* Load user D Map */
5684 Map[7][m] = w & MAPMASK;
5685 break;
5686 case 4: /* Load DCH A Map */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005687 Map[0][m] = w & MAPMASK;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005688 break;
5689 case 5: /* Load DCH C Map */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005690 Map[4][m] = w;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005691 break;
5692 case 6: /* Load DCH B Map */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005693 Map[3][m] = w;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005694 break;
5695 case 7: /* Load DCH D Map */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005696 Map[5][m] = w;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005697 break;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005698 default:
5699 break;
5700 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005701 return 0;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005702}
5703
5704/* Displays an error on a unimplemented (in this sim) instr. */
5705
5706int32 unimp(int32 PC)
5707{
5708 if (Debug_Flags)
5709 printf("\n\r\007<<<Unimplemented instruction: [%o] %o>>>\n\r", PC - 1, GetMap(PC - 1));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005710 return 0;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005711}
5712
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005713/* New priority mask out */
5714
5715void mask_out (int32 newmask)
5716{
5717int32 i;
5718
5719dev_disable = 0;
5720for (i = DEV_LOW; i <= DEV_HIGH; i++) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005721 if (newmask & dev_table[i].pi)
5722 dev_disable = dev_disable | dev_table[i].mask;
5723}
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005724int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
5725return;
5726}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005727
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005728/* Reset routine */
5729
5730t_stat cpu_reset (DEVICE *dptr)
5731{
5732int_req = int_req & ~INT_ION;
5733pimask = 0;
5734dev_disable = 0;
5735pwr_low = 0;
Bob Supnik701f0fe2001-12-26 09:38:00 -08005736sim_brk_types = sim_brk_dflt = SWMASK ('E');
5737return SCPE_OK;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005738}
5739
5740/* Memory examine */
5741
5742t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
5743{
Bob Supnik1da2d942003-12-31 11:49:00 -08005744if (sw & SWMASK ('V')) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005745 if (addr > 077777) return SCPE_NXM;
5746 if (vptr != NULL) *vptr = GetMap (addr);
5747}
5748else {
5749 if (addr >= MEMSIZE) return SCPE_NXM;
5750 if (vptr != NULL) *vptr = M[addr] & 0177777;
5751}
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005752return SCPE_OK;
5753}
5754
5755/* Memory deposit */
5756
5757t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
5758{
Bob Supnik1da2d942003-12-31 11:49:00 -08005759if (sw & SWMASK ('V')) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005760 if (addr > 077777) return SCPE_NXM;
5761 PutMap (addr, (int32) val);
5762}
5763else {
5764 if (addr >= MEMSIZE) return SCPE_NXM;
5765 M[addr] = (int32) val & 0177777;
5766}
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005767return SCPE_OK;
5768}
Bob Supnik2c2dd5e2002-11-17 15:54:00 -08005769
5770/* Alter memory size */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005771
Bob Supnik701f0fe2001-12-26 09:38:00 -08005772t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005773{
5774int32 mc = 0;
Bob Supnik1da2d942003-12-31 11:49:00 -08005775t_addr i;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005776
Bob Supnik701f0fe2001-12-26 09:38:00 -08005777if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005778 return SCPE_ARG;
Bob Supnik701f0fe2001-12-26 09:38:00 -08005779for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005780if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005781 return SCPE_OK;
Bob Supnik701f0fe2001-12-26 09:38:00 -08005782MEMSIZE = val;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005783for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
5784return SCPE_OK;
5785}
5786
5787/* MAP device services */
5788
5789t_stat map_svc (UNIT *uptr)
5790{
5791return SCPE_OK;
5792}
5793
5794/* Map examine */
5795
5796t_stat map_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
5797{
5798if ((addr & 077) >= 037 || addr > 737) return SCPE_NXM;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005799uptr->u4 = -2; /* signal to print_sys in eclipse_sys.c: do not map */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005800if (vptr != NULL) *vptr = Map[(addr >> 6) & 3][addr & 037] & 0177777;
5801return SCPE_OK;
5802}
5803
5804/* Memory deposit */
5805
5806t_stat map_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
5807{
5808if ((addr & 077) >= 037 || addr > 0737) return SCPE_NXM;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005809uptr->u4 = -2; /* signal to print_sys in eclipse_sys.c: do not map */
Bob Supnik1da2d942003-12-31 11:49:00 -08005810Map[(addr >> 6) & 3][addr & 037] = (int32)val & 0177777;
5811return SCPE_OK;
5812}
5813
5814/* FPU device services */
5815
5816t_stat fpu_svc (UNIT *uptr)
5817{
5818return SCPE_OK;
5819}
5820
5821/* PIT Device Services */
5822
5823/* IOT routine */
5824
5825int32 pit (int32 pulse, int32 code, int32 AC)
5826{
5827int32 iodata = 0;
5828
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005829if (code == ioDIA) { /* DIA */
5830 if (pit_flag == 0) {
5831 pit_flag = 1;
5832 }
5833 iodata = pit_counter;
Bob Supnik1da2d942003-12-31 11:49:00 -08005834}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005835if (code == ioDOA) { /* DOA */
5836 pit_initial = AC; /* Load Counter */
5837 sim_rtcn_init (pit_time, 1); /* init calibr */
Bob Supnik1da2d942003-12-31 11:49:00 -08005838}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005839switch (pulse) { /* decode IR<8:9> */
5840case 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;
5849case 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 */
5855return iodata;
Bob Supnik1da2d942003-12-31 11:49:00 -08005856}
5857
5858/* Unit service */
5859
5860t_stat pit_svc (UNIT *uptr)
5861{
5862int32 t;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005863t = sim_rtcn_calb (pit_tps, 1); /* calibrate delay */
5864sim_activate (&pit_unit, t); /* reactivate unit */
5865pit_poll = t / (-pit_adj); /* adjust poll */
5866pit_counter++; /* Increment counter */
5867if (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;
Bob Supnik1da2d942003-12-31 11:49:00 -08005872}
5873return SCPE_OK;
5874}
5875
5876/* Reset routine */
5877
5878t_stat pit_reset (DEVICE *dptr)
5879{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005880pit_counter = 0; /* clear counter */
5881dev_busy = dev_busy & ~INT_PIT; /* clear busy */
5882dev_done = dev_done & ~INT_PIT; /* clear done, int */
Bob Supnik1da2d942003-12-31 11:49:00 -08005883int_req = int_req & ~INT_PIT;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005884sim_cancel (&pit_unit); /* deactivate unit */
5885pit_poll = pit_time; /* poll is default */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005886return 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
5894static const int32 boot_rom[] = {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005895
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 */
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005931};
5932
Bob Supnik2c2dd5e2002-11-17 15:54:00 -08005933t_stat cpu_boot (int32 unitno, DEVICE *dptr)
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005934{
5935int32 i;
5936extern int32 saved_PC;
5937
5938for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
5939saved_PC = BOOT_START;
5940return SCPE_OK;
5941}
5942
5943int32 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005958 return 0;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005959}
5960
Mark Pizzolatoa6964f82011-04-15 09:04:39 -07005961t_stat Debug_Dump(UNIT *uptr, int32 val, char *cptr, void *desc)
Bob Supnik1da2d942003-12-31 11:49:00 -08005962{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005963 return SCPE_OK;
Bob Supnik1da2d942003-12-31 11:49:00 -08005964}
5965
Mark Pizzolatoa6964f82011-04-15 09:04:39 -07005966t_stat Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc)
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005967{
5968 char debmap[4], debion[4];
5969 t_value simeval[20];
5970 int debcar;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005971 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 }
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005979 if (!hwrap) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005980 start = 0;
5981 end = hnext;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005982 } else {
5983 start = hnext;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005984 end = hnext - 1;
5985 if (end < 0) end = hmax;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005986 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005987 ctr = start;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005988 while (1) {
5989 if (ctr == end)
5990 break;
5991 count++;
5992 strcpy(debion, " ");
5993 strcpy(debmap, " ");
5994 debcar = 0;
5995 if (hflags[ctr] & 0x80) {
Bob Supnikb6393b32004-11-23 15:49:00 -08005996 fprintf(st, "--------- Interrupt %o (%o) to %6o ---------\n",
Bob Supnikb7c1eae2005-09-09 18:09:00 -07005997 hinst[ctr], hac0[ctr], hac1[ctr]);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08005998 } 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");
Bob Supnikb6393b32004-11-23 15:49:00 -08006005 fprintf(st, "%s%s%06o acs: %06o %06o %06o %06o %01o ",
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006006 debion, debmap, hpc[ctr], hac0[ctr], hac1[ctr], hac2[ctr],
6007 hac3[ctr], debcar);
Bob Supnik4d6dfa42001-11-06 20:50:00 -08006008 simeval[0] = hinst[ctr];
6009 simeval[1] = hinst2[ctr];
Bob Supnikb6393b32004-11-23 15:49:00 -08006010 fprint_sym (st, hpc[ctr], simeval, NULL, SWMASK('M'));
6011 fprintf(st, "\n");
Bob Supnik4d6dfa42001-11-06 20:50:00 -08006012 }
6013 ctr++;
6014 if (ctr > hmax)
6015 ctr = 0;
6016 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006017 return SCPE_OK;
Bob Supnik4d6dfa42001-11-06 20:50:00 -08006018}
Bob Supnikdf647512002-07-14 15:20:00 -07006019
Bob Supnik2c2dd5e2002-11-17 15:54:00 -08006020/* Build dispatch table */
Bob Supnikdf647512002-07-14 15:20:00 -07006021
Bob Supnik2c2dd5e2002-11-17 15:54:00 -08006022t_stat build_devtab (void)
Bob Supnikdf647512002-07-14 15:20:00 -07006023{
6024DEVICE *dptr;
Bob Supnik2c2dd5e2002-11-17 15:54:00 -08006025DIB *dibp;
6026int32 i, dn;
Bob Supnikdf647512002-07-14 15:20:00 -07006027
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006028for (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}
6033for (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}
Bob Supnikdf647512002-07-14 15:20:00 -07006042return SCPE_OK;
6043}
Bob Supnik1da2d942003-12-31 11:49:00 -08006044
6045/* ------------------------------------------------------------------- */
6046/* Floating Point Arithmetic */
6047/* ------------------------------------------------------------------- */
6048
6049
6050/* Get short float from FPAC */
6051
6052void 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
6061void 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
6071void 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
6081void 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
6092int 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
6104int 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)
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006124 return (2);
Bob Supnik1da2d942003-12-31 11:49:00 -08006125 return(0);
6126}
6127
6128/* Normalize long float */
6129
6130int 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)
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006154 return (2);
Bob Supnik1da2d942003-12-31 11:49:00 -08006155 return(0);
6156}
6157
6158/* Check Long for Overflow */
6159
6160int 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
6170int underflow_sf(SHORT_FLOAT *fl)
6171{
6172 if (fl->expo < 0) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006173 fl->short_fract = 0;
6174 fl->expo = 0;
6175 fl->sign = 0;
Bob Supnik1da2d942003-12-31 11:49:00 -08006176 }
6177 return(0);
6178
6179}
6180
6181
6182int underflow_lf(LONG_FLOAT *fl)
6183{
6184 if (fl->expo < 0) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006185 fl->long_fract = 0;
6186 fl->expo = 0;
6187 fl->sign = 0;
Bob Supnik1da2d942003-12-31 11:49:00 -08006188 }
6189 return(0);
6190}
6191
6192/* Check Short for Over/Under flow */
6193
6194int 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) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006201 /* set true 0 */
6202 fl->short_fract = 0;
6203 fl->expo = 0;
6204 fl->sign = 0;
Bob Supnik1da2d942003-12-31 11:49:00 -08006205 }
6206 }
6207 return(0);
6208
6209}
6210
6211/* Check Long for Over/Under flow */
6212
6213int 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) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006220 /* set true 0 */
6221 fl->long_fract = 0;
6222 fl->expo = 0;
6223 fl->sign = 0;
Bob Supnik1da2d942003-12-31 11:49:00 -08006224 }
6225 }
6226 return(0);
6227
6228}
6229
6230int significance_sf (SHORT_FLOAT *fl)
6231{
6232 fl->sign = 0;
6233 fl->expo = 0;
6234 return(0);
6235
6236}
6237
6238int 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/*-------------------------------------------------------------------*/
6257int add_sf (SHORT_FLOAT *fl, SHORT_FLOAT *add_fl, int normal)
6258{
6259int pgm_check;
6260int shift;
6261
6262 pgm_check = 0;
6263 if (add_fl->short_fract
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006264 || add_fl->expo) { /* add_fl not 0 */
Bob Supnik1da2d942003-12-31 11:49:00 -08006265 if (fl->short_fract
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006266 || fl->expo) { /* fl not 0 */
Bob Supnik1da2d942003-12-31 11:49:00 -08006267 /* 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) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006360 /* not normalize, just guard digit */
Bob Supnik1da2d942003-12-31 11:49:00 -08006361 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);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006381 } else { /* fl 0, add_fl not 0 */
Bob Supnik1da2d942003-12-31 11:49:00 -08006382 /* 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006391 } else { /* add_fl 0 */
6392 if (fl->short_fract == 0) { /* fl 0 */
Bob Supnik1da2d942003-12-31 11:49:00 -08006393 /* 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/*-------------------------------------------------------------------*/
6417int add_lf (LONG_FLOAT *fl, LONG_FLOAT *add_fl, int normal)
6418{
6419int pgm_check;
6420int shift;
6421
6422 pgm_check = 0;
6423 if (add_fl->long_fract
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006424 || add_fl->expo) { /* add_fl not 0 */
Bob Supnik1da2d942003-12-31 11:49:00 -08006425 if (fl->long_fract
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006426 || fl->expo) { /* fl not 0 */
Bob Supnik1da2d942003-12-31 11:49:00 -08006427 /* 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);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006541 } else { /* fl 0, add_fl not 0 */
Bob Supnik1da2d942003-12-31 11:49:00 -08006542 /* 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 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006551 } else { /* add_fl 0 */
6552 if (fl->long_fract == 0) { /* fl 0 */
Bob Supnik1da2d942003-12-31 11:49:00 -08006553 /* 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
6576int mul_sf(SHORT_FLOAT *fl, SHORT_FLOAT *mul_fl)
6577{
6578t_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/*-------------------------------------------------------------------*/
6624int mul_lf(LONG_FLOAT *fl, LONG_FLOAT *mul_fl)
6625{
6626t_int64 wk;
6627int32 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/*-------------------------------------------------------------------*/
6681int div_sf(SHORT_FLOAT *fl, SHORT_FLOAT *div_fl)
6682{
6683t_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 {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006715 /* divisor 0 */
Bob Supnik1da2d942003-12-31 11:49:00 -08006716
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/*-------------------------------------------------------------------*/
6733int div_lf(LONG_FLOAT *fl, LONG_FLOAT *div_fl)
6734{
6735t_int64 wk;
6736t_int64 wk2;
6737int 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 {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07006782 /* divisor 0 */
Bob Supnik1da2d942003-12-31 11:49:00 -08006783
6784 return(3);
6785 }
6786 return(0);
6787
6788}
6789