GE-115 Emulator
An Emulator of the General Electrics GE-115 computer
alu_logic.c
Go to the documentation of this file.
1
25#include "alu_logic.h"
26
27/* ------------------------------------------------------------------ */
28/* MVC – Move Characters */
29/* ------------------------------------------------------------------ */
30
31void alu_mvc(struct ge *ge, uint16_t dst, uint16_t src, uint16_t len)
32{
33 uint16_t i;
34 /*
35 * The manual says "movement is from left to right through each field
36 * a byte at a time" (§5.5.3.1). A plain left-to-right byte loop is
37 * correct even for overlapping fields when dst <= src (destructive
38 * overlap dst > src works identically to IBM MVC — the destination
39 * bytes already overwritten are used as source for later positions,
40 * which replicates the documented GE behaviour).
41 */
42 for (i = 0; i < len; i++)
43 ge_mem_store8(ge, (uint16_t)(dst + i), ge->mem[(uint16_t)(src + i)]);
44 /* CC not altered */
45}
46
47/* ------------------------------------------------------------------ */
48/* MVI – Move Immediate */
49/* ------------------------------------------------------------------ */
50
51void alu_mvi(struct ge *ge, uint16_t addr, uint8_t imm)
52{
53 ge_mem_store8(ge, addr, imm);
54 /* CC not altered */
55}
56
57/* ------------------------------------------------------------------ */
58/* NC – AND Characters */
59/* ------------------------------------------------------------------ */
60
61void alu_nc(struct ge *ge, uint16_t a, uint16_t b, uint8_t len)
62{
63 uint8_t i;
64 for (i = 0; i < len; i++)
65 ge->mem[(uint16_t)(a + i)] &= ge->mem[(uint16_t)(b + i)];
66 /* "Qualitative result: it is not interested." — CC not altered */
67}
68
69/* ------------------------------------------------------------------ */
70/* OC – OR Characters */
71/* ------------------------------------------------------------------ */
72
73void alu_oc(struct ge *ge, uint16_t a, uint16_t b, uint8_t len)
74{
75 uint8_t i;
76 for (i = 0; i < len; i++)
77 ge->mem[(uint16_t)(a + i)] |= ge->mem[(uint16_t)(b + i)];
78 /* "Qualitative result: it is not interested." — CC not altered */
79}
80
81/* ------------------------------------------------------------------ */
82/* XC – Exclusive-OR Characters */
83/* ------------------------------------------------------------------ */
84
85void alu_xc(struct ge *ge, uint16_t a, uint16_t b, uint8_t len)
86{
87 uint8_t i;
88 uint8_t all_zero = 1;
89
90 for (i = 0; i < len; i++) {
91 ge->mem[(uint16_t)(a + i)] ^= ge->mem[(uint16_t)(b + i)];
92 if (ge->mem[(uint16_t)(a + i)] != 0)
93 all_zero = 0;
94 }
95
96 /*
97 * §5.5.3.7 qualitative result table (FA04/FA05):
98 * FA04=1, FA05=0 -> cc=2: "Result equal to all zeroes"
99 * FA04=1, FA05=1 -> cc=3: "Result different from all zeroes"
100 */
101 alu_set_cc(ge, all_zero ? 2 : 3);
102}
103
104/* ------------------------------------------------------------------ */
105/* NI – AND Immediate */
106/* ------------------------------------------------------------------ */
107
108void alu_ni(struct ge *ge, uint16_t addr, uint8_t imm)
109{
110 ge_mem_store8(ge, addr, (uint8_t)(ge->mem[addr] & imm));
111 /* "Qualitative result: it is not interested." — CC not altered */
112}
113
114/* ------------------------------------------------------------------ */
115/* OI / CI – OR Immediate (opcode 0x96; "CI" in this deck's mnemonics) */
116/* ------------------------------------------------------------------ */
117
118void alu_oi(struct ge *ge, uint16_t addr, uint8_t imm)
119{
120 uint8_t result = (uint8_t)(ge->mem[addr] | imm);
121 ge_mem_store8(ge, addr, result);
122
123 /*
124 * Qualitative result (FA04/FA05), symmetric to XI:
125 * FA04=1, FA05=0 -> cc=2: result == 0
126 * FA04=1, FA05=1 -> cc=3: result != 0
127 * Validated against funktionalcpu step 0x32 (CI 0xAA on 0x55 -> 0xFF).
128 */
129 alu_set_cc(ge, (result == 0) ? 2 : 3);
130}
131
132/* ------------------------------------------------------------------ */
133/* XI – Exclusive-OR Immediate */
134/* ------------------------------------------------------------------ */
135
136void alu_xi(struct ge *ge, uint16_t addr, uint8_t imm)
137{
138 uint8_t result = (uint8_t)(ge->mem[addr] ^ imm);
139 ge_mem_store8(ge, addr, result);
140
141 /*
142 * §5.6.3.3 qualitative result table (FA04/FA05):
143 * FA04=1, FA05=0 -> cc=2: "Result equal to zero"
144 * FA04=1, FA05=1 -> cc=3: "Result different from zero"
145 */
146 alu_set_cc(ge, (result == 0) ? 2 : 3);
147}
148
149/* ------------------------------------------------------------------ */
150/* CMC – Compare Characters */
151/* ------------------------------------------------------------------ */
152
153void alu_cmc(struct ge *ge, uint16_t a, uint16_t b, uint8_t len)
154{
155 uint8_t i;
156 uint8_t ba, bb;
157
158 /*
159 * §5.5.3.2: "comparison is purely binary", proceeds left to right,
160 * stops as soon as an inequality is found.
161 *
162 * Qualitative result (FA04/FA05):
163 * FA04=0, FA05=1 -> cc=1: "First operand smaller than the second"
164 * FA04=1, FA05=0 -> cc=2: "First operand equal to the second"
165 * FA04=1, FA05=1 -> cc=3: "First operand greater than the second"
166 */
167 for (i = 0; i < len; i++) {
168 ba = ge->mem[(uint16_t)(a + i)];
169 bb = ge->mem[(uint16_t)(b + i)];
170 if (ba < bb) { alu_set_cc(ge, 1); return; }
171 if (ba > bb) { alu_set_cc(ge, 3); return; }
172 }
173 alu_set_cc(ge, 2); /* all bytes equal */
174}
175
176/* ------------------------------------------------------------------ */
177/* CI – Compare Immediate (CMI in manual, §5.5.5.1) */
178/* ------------------------------------------------------------------ */
179
180void alu_ci(struct ge *ge, uint16_t addr, uint8_t imm)
181{
182 uint8_t mem_byte = ge->mem[addr];
183
184 /*
185 * §5.5.5.1 qualitative result table (FA04/FA05):
186 * FA04=0, FA05=1 -> cc=1: "The storage character is smaller than K"
187 * FA04=1, FA05=0 -> cc=2: "The storage character is equal to K"
188 * FA04=1, FA05=1 -> cc=3: "The storage character is greater than K"
189 * Both operands treated as unsigned bytes.
190 */
191 if (mem_byte < imm)
192 alu_set_cc(ge, 1);
193 else if (mem_byte == imm)
194 alu_set_cc(ge, 2);
195 else
196 alu_set_cc(ge, 3);
197}
198
199/* ------------------------------------------------------------------ */
200/* TL – Translate (TR in manual, §5.5.3.3) */
201/* ------------------------------------------------------------------ */
202
203void alu_tl(struct ge *ge, uint16_t a, uint8_t len, uint16_t table)
204{
205 uint8_t i;
206
207 /*
208 * §5.5.3.3: "every byte of the first operand is substituted by the
209 * content of a location of the table adding the binary value of the
210 * byte of the first operand to the address of the second operand."
211 * The manual states the table base must be a multiple of 256.
212 * We honour that precondition but do not assert it here (the CPU
213 * instruction decoder is responsible for that check).
214 */
215 for (i = 0; i < len; i++) {
216 uint8_t b = ge->mem[(uint16_t)(a + i)];
217 ge_mem_store8(ge, (uint16_t)(a + i), ge->mem[(uint16_t)(table + b)]);
218 }
219 /* "Qualitative result: it is not interested." — CC not altered */
220}
221
222/* ------------------------------------------------------------------ */
223/* TM – Test under Mask */
224/* ------------------------------------------------------------------ */
225
226void alu_tm(struct ge *ge, uint16_t addr, uint8_t mask)
227{
228 uint8_t result = ge->mem[addr] & mask;
229
230 /*
231 * §5.6.3.4: "the result is not written in memory".
232 * Qualitative result table (FA04/FA05):
233 * FA04=1, FA05=0 -> cc=2: "Result equal to zero"
234 * FA04=1, FA05=1 -> cc=3: "Result different from zero"
235 * (Same encoding as XI.)
236 */
237 alu_set_cc(ge, (result == 0) ? 2 : 3);
238}
void alu_set_cc(struct ge *ge, uint8_t cc)
Definition alu_cc.c:4
void alu_tl(struct ge *ge, uint16_t a, uint8_t len, uint16_t table)
alu_tl – Translate (TL, §5.5.3.3, "TR" in manual)
Definition alu_logic.c:203
void alu_ni(struct ge *ge, uint16_t addr, uint8_t imm)
alu_ni – AND Immediate (NI, §5.6.3.2)
Definition alu_logic.c:108
void alu_nc(struct ge *ge, uint16_t a, uint16_t b, uint8_t len)
alu_nc – AND Characters (NC, §5.5.3.9)
Definition alu_logic.c:61
void alu_oc(struct ge *ge, uint16_t a, uint16_t b, uint8_t len)
alu_oc – OR Characters (OC, §5.5.3.8)
Definition alu_logic.c:73
void alu_cmc(struct ge *ge, uint16_t a, uint16_t b, uint8_t len)
alu_cmc – Compare Characters (CMC, §5.5.3.2)
Definition alu_logic.c:153
void alu_ci(struct ge *ge, uint16_t addr, uint8_t imm)
alu_ci – Compare Immediate (CMI, §5.5.5.1)
Definition alu_logic.c:180
void alu_xc(struct ge *ge, uint16_t a, uint16_t b, uint8_t len)
alu_xc – Exclusive-OR Characters (XC, §5.5.3.7)
Definition alu_logic.c:85
void alu_oi(struct ge *ge, uint16_t addr, uint8_t imm)
Definition alu_logic.c:118
void alu_mvc(struct ge *ge, uint16_t dst, uint16_t src, uint16_t len)
alu_mvc – Move Characters (MVC, §5.5.3.1)
Definition alu_logic.c:31
void alu_xi(struct ge *ge, uint16_t addr, uint8_t imm)
alu_xi – Exclusive-OR Immediate (XI, §5.6.3.3)
Definition alu_logic.c:136
void alu_mvi(struct ge *ge, uint16_t addr, uint8_t imm)
alu_mvi – Move Immediate (MVI, §5.5.5.2)
Definition alu_logic.c:51
void alu_tm(struct ge *ge, uint16_t addr, uint8_t mask)
alu_tm – Test under Mask (TM, §5.6.3.4)
Definition alu_logic.c:226
GE-120/130 ALU logical and string-move primitives.
void ge_mem_store8(struct ge *ge, uint16_t addr, uint8_t val)
Store a byte with generated odd parity + mark-written (for the hybrid ALU/SS write paths that write g...
Definition ge.c:119
The entire state of the emulated system, including registers, memory, peripherals and timings.
Definition ge.h:96
uint8_t mem[MEM_SIZE]
The memory of the emulated system.
Definition ge.h:566