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_store8(ge, (uint16_t)(a + i),
66 ge->mem[(uint16_t)(a + i)] & ge->mem[(uint16_t)(b + i)]);
67 /* "Qualitative result: it is not interested." — CC not altered */
68}
69
70/* ------------------------------------------------------------------ */
71/* OC – OR Characters */
72/* ------------------------------------------------------------------ */
73
74void alu_oc(struct ge *ge, uint16_t a, uint16_t b, uint8_t len)
75{
76 uint8_t i;
77 for (i = 0; i < len; i++)
78 ge_mem_store8(ge, (uint16_t)(a + i),
79 ge->mem[(uint16_t)(a + i)] | ge->mem[(uint16_t)(b + i)]);
80 /* "Qualitative result: it is not interested." — CC not altered */
81}
82
83/* ------------------------------------------------------------------ */
84/* XC – Exclusive-OR Characters */
85/* ------------------------------------------------------------------ */
86
87void alu_xc(struct ge *ge, uint16_t a, uint16_t b, uint8_t len)
88{
89 uint8_t i;
90 uint8_t all_zero = 1;
91
92 for (i = 0; i < len; i++) {
93 ge_mem_store8(ge, (uint16_t)(a + i),
94 ge->mem[(uint16_t)(a + i)] ^ ge->mem[(uint16_t)(b + i)]);
95 if (ge->mem[(uint16_t)(a + i)] != 0)
96 all_zero = 0;
97 }
98
99 /*
100 * §5.5.3.7 qualitative result table (FA04/FA05):
101 * FA04=1, FA05=0 -> cc=2: "Result equal to all zeroes"
102 * FA04=1, FA05=1 -> cc=3: "Result different from all zeroes"
103 */
104 alu_set_cc(ge, all_zero ? 2 : 3);
105}
106
107/* ------------------------------------------------------------------ */
108/* NI – AND Immediate */
109/* ------------------------------------------------------------------ */
110
111void alu_ni(struct ge *ge, uint16_t addr, uint8_t imm)
112{
113 ge_mem_store8(ge, addr, (uint8_t)(ge->mem[addr] & imm));
114 /* "Qualitative result: it is not interested." — CC not altered */
115}
116
117/* ------------------------------------------------------------------ */
118/* OI – Or Immediate (opcode 0x96, cp04 p21/p65) */
119/* ------------------------------------------------------------------ */
120
121void alu_oi(struct ge *ge, uint16_t addr, uint8_t imm)
122{
123 uint8_t result = (uint8_t)(ge->mem[addr] | imm);
124 ge_mem_store8(ge, addr, result);
125
126 /*
127 * Qualitative result (FA04/FA05), symmetric to XI:
128 * FA04=1, FA05=0 -> cc=2: result == 0
129 * FA04=1, FA05=1 -> cc=3: result != 0
130 * Validated against funktionalcpu step 0x32 (OI 0xAA on 0x55 -> 0xFF).
131 */
132 alu_set_cc(ge, (result == 0) ? 2 : 3);
133}
134
135/* ------------------------------------------------------------------ */
136/* XI – Exclusive-OR Immediate */
137/* ------------------------------------------------------------------ */
138
139void alu_xi(struct ge *ge, uint16_t addr, uint8_t imm)
140{
141 uint8_t result = (uint8_t)(ge->mem[addr] ^ imm);
142 ge_mem_store8(ge, addr, result);
143
144 /*
145 * §5.6.3.3 qualitative result table (FA04/FA05):
146 * FA04=1, FA05=0 -> cc=2: "Result equal to zero"
147 * FA04=1, FA05=1 -> cc=3: "Result different from zero"
148 */
149 alu_set_cc(ge, (result == 0) ? 2 : 3);
150}
151
152/* ------------------------------------------------------------------ */
153/* CMC – Compare Characters */
154/* ------------------------------------------------------------------ */
155
156void alu_cmc(struct ge *ge, uint16_t a, uint16_t b, uint8_t len)
157{
158 uint8_t i;
159 uint8_t ba, bb;
160
161 /*
162 * §5.5.3.2: "comparison is purely binary", proceeds left to right,
163 * stops as soon as an inequality is found.
164 *
165 * Qualitative result (FA04/FA05):
166 * FA04=0, FA05=1 -> cc=1: "First operand smaller than the second"
167 * FA04=1, FA05=0 -> cc=2: "First operand equal to the second"
168 * FA04=1, FA05=1 -> cc=3: "First operand greater than the second"
169 */
170 for (i = 0; i < len; i++) {
171 ba = ge->mem[(uint16_t)(a + i)];
172 bb = ge->mem[(uint16_t)(b + i)];
173 if (ba < bb) { alu_set_cc(ge, 1); return; }
174 if (ba > bb) { alu_set_cc(ge, 3); return; }
175 }
176 alu_set_cc(ge, 2); /* all bytes equal */
177}
178
179/* ------------------------------------------------------------------ */
180/* CMI – Compare Immediate (opcode 0x95, §5.5.5.1) */
181/* ------------------------------------------------------------------ */
182
183void alu_cmi(struct ge *ge, uint16_t addr, uint8_t imm)
184{
185 uint8_t mem_byte = ge->mem[addr];
186
187 /*
188 * §5.5.5.1 qualitative result table (FA04/FA05):
189 * FA04=0, FA05=1 -> cc=1: "The storage character is smaller than K"
190 * FA04=1, FA05=0 -> cc=2: "The storage character is equal to K"
191 * FA04=1, FA05=1 -> cc=3: "The storage character is greater than K"
192 * Both operands treated as unsigned bytes.
193 */
194 if (mem_byte < imm)
195 alu_set_cc(ge, 1);
196 else if (mem_byte == imm)
197 alu_set_cc(ge, 2);
198 else
199 alu_set_cc(ge, 3);
200}
201
202/* ------------------------------------------------------------------ */
203/* TR – Translate (opcode 0xDC, cp04 p22/p46, §5.5.3.3) */
204/* ------------------------------------------------------------------ */
205
206void alu_tr(struct ge *ge, uint16_t a, uint8_t len, uint16_t table)
207{
208 uint8_t i;
209
210 /*
211 * §5.5.3.3: "every byte of the first operand is substituted by the
212 * content of a location of the table adding the binary value of the
213 * byte of the first operand to the address of the second operand."
214 * The manual states the table base must be a multiple of 256.
215 * We honour that precondition but do not assert it here (the CPU
216 * instruction decoder is responsible for that check).
217 */
218 for (i = 0; i < len; i++) {
219 uint8_t b = ge->mem[(uint16_t)(a + i)];
220 ge_mem_store8(ge, (uint16_t)(a + i), ge->mem[(uint16_t)(table + b)]);
221 }
222 /* "Qualitative result: it is not interested." — CC not altered */
223}
224
225/* ------------------------------------------------------------------ */
226/* TM – Test under Mask */
227/* ------------------------------------------------------------------ */
228
229void alu_tm(struct ge *ge, uint16_t addr, uint8_t mask)
230{
231 uint8_t result = ge->mem[addr] & mask;
232
233 /*
234 * §5.6.3.4: "the result is not written in memory".
235 * Qualitative result table (FA04/FA05):
236 * FA04=1, FA05=0 -> cc=2: "Result equal to zero"
237 * FA04=1, FA05=1 -> cc=3: "Result different from zero"
238 * (Same encoding as XI.)
239 */
240 alu_set_cc(ge, (result == 0) ? 2 : 3);
241}
void alu_set_cc(struct ge *ge, uint8_t cc)
Definition alu_cc.c:4
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:111
void alu_tr(struct ge *ge, uint16_t a, uint8_t len, uint16_t table)
alu_tr – Translate (TR, opcode 0xDC, §5.5.3.3)
Definition alu_logic.c:206
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:74
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:156
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:87
void alu_oi(struct ge *ge, uint16_t addr, uint8_t imm)
Definition alu_logic.c:121
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:139
void alu_cmi(struct ge *ge, uint16_t addr, uint8_t imm)
alu_cmi – Compare Immediate (CMI, opcode 0x95, §5.5.5.1)
Definition alu_logic.c:183
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:229
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:317
The entire state of the emulated system, including registers, memory, peripherals and timings.
Definition ge.h:172
uint8_t mem[MEM_SIZE]
The memory of the emulated system.
Definition ge.h:695