fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/cpu/e8080/flags.c *
7 * Created: 2012-11-28 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2012-2023 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include "e8080.h"
24#include "internal.h"
25
26#include <stdlib.h>
27#include <stdio.h>
28
29
30static char parity[256] = {
31 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
32 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
33 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
34 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
35 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
36 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
37 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
38 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
39 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
40 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
41 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
42 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
43 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
44 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
45 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
46 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0
47};
48
49
50static inline
51void set_psw_sz (e8080_t *c, unsigned char val)
52{
53 val &= 0xff;
54
55 if (val == 0) {
56 c->psw |= E8080_FLG_Z;
57 }
58 else if (val & 0x80) {
59 c->psw |= E8080_FLG_S;
60 }
61}
62
63static inline
64void set_psw_szp (e8080_t *c, unsigned char val)
65{
66 val &= 0xff;
67
68 if (val == 0) {
69 c->psw |= E8080_FLG_Z;
70 }
71 else if (val & 0x80) {
72 c->psw |= E8080_FLG_S;
73 }
74
75 if (parity[val] == 0) {
76 c->psw |= E8080_FLG_P;
77 }
78}
79
80void e8080_set_psw_szp (e8080_t *c, unsigned char val, unsigned set, unsigned reset)
81{
82 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_P | reset);
83 set_psw_szp (c, val);
84 c->psw |= set;
85}
86
87void e8080_set_psw_log (e8080_t *c, unsigned char val)
88{
89 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P | E8080_FLG_C);
90
91 set_psw_szp (c, val);
92}
93
94void e8080_set_psw_inc (e8080_t *c, unsigned char val)
95{
96 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P);
97
98 set_psw_szp (c, val + 1);
99
100 if ((val ^ (val + 1)) & 0x10) {
101 c->psw |= E8080_FLG_A;
102 }
103}
104
105void e8080_set_psw_dec (e8080_t *c, unsigned char val)
106{
107 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P);
108
109 set_psw_szp (c, val - 1);
110
111 if ((val ^ (val - 1)) & 0x10) {
112 c->psw |= E8080_FLG_A;
113 }
114}
115
116void e8080_set_psw_add (e8080_t *c, unsigned char s1, unsigned char s2)
117{
118 unsigned d;
119
120 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P | E8080_FLG_C);
121
122 d = (unsigned) s1 + (unsigned) s2;
123
124 set_psw_szp (c, d);
125
126 if (d > 255) {
127 c->psw |= E8080_FLG_C;
128 }
129
130 if ((s1 ^ s2 ^ d) & 0x10) {
131 c->psw |= E8080_FLG_A;
132 }
133}
134
135void e8080_set_psw_sub (e8080_t *c, unsigned char s1, unsigned char s2)
136{
137 unsigned d;
138
139 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P | E8080_FLG_C);
140
141 d = (unsigned) s1 - (unsigned) s2;
142
143 set_psw_szp (c, d);
144
145 if (d > 255) {
146 c->psw |= E8080_FLG_C;
147 }
148
149 if ((s1 ^ s2 ^ d) & 0x10) {
150 c->psw |= E8080_FLG_A;
151 }
152}
153
154void e8080_set_psw_adc (e8080_t *c, unsigned char s1, unsigned char s2, unsigned char s3)
155{
156 unsigned d;
157
158 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P | E8080_FLG_C);
159
160 d = (unsigned) s1 + (unsigned) s2 + (unsigned) s3;
161
162 set_psw_szp (c, d);
163
164 if (d > 255) {
165 c->psw |= E8080_FLG_C;
166 }
167
168 if ((s1 ^ s2 ^ d) & 0x10) {
169 c->psw |= E8080_FLG_A;
170 }
171}
172
173void e8080_set_psw_sbb (e8080_t *c, unsigned char s1, unsigned char s2, unsigned char s3)
174{
175 unsigned d;
176
177 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P | E8080_FLG_C);
178
179 d = (unsigned) s1 - (unsigned) s2 - (unsigned) s3;
180
181 set_psw_szp (c, d);
182
183 if (d > 255) {
184 c->psw |= E8080_FLG_C;
185 }
186
187 if ((s1 ^ s2 ^ d) & 0x10) {
188 c->psw |= E8080_FLG_A;
189 }
190}
191
192void z80_set_psw_rot (e8080_t *c, unsigned char val, int cf)
193{
194 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P | E8080_FLG_N | E8080_FLG_C);
195
196 set_psw_szp (c, val);
197
198 if (cf) {
199 c->psw |= E8080_FLG_C;
200 }
201}
202
203void z80_set_psw_inc (e8080_t *c, unsigned char val)
204{
205 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P | E8080_FLG_N);
206
207 set_psw_sz (c, val + 1);
208
209 if ((val ^ (val + 1)) & 0x10) {
210 c->psw |= E8080_FLG_A;
211 }
212
213 if (val == 0x7f) {
214 c->psw |= E8080_FLG_P;
215 }
216}
217
218void z80_set_psw_dec (e8080_t *c, unsigned char val)
219{
220 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P);
221
222 set_psw_sz (c, val - 1);
223
224 if ((val ^ (val - 1)) & 0x10) {
225 c->psw |= E8080_FLG_A;
226 }
227
228 if (val == 0x80) {
229 c->psw |= E8080_FLG_P;
230 }
231
232 c->psw |= E8080_FLG_N;
233}
234
235void z80_set_psw_add (e8080_t *c, unsigned d, unsigned char s1, unsigned char s2)
236{
237 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P | E8080_FLG_N | E8080_FLG_C);
238
239 set_psw_sz (c, d);
240
241 if (d > 255) {
242 c->psw |= E8080_FLG_C;
243 }
244
245 if ((d ^ s1) & (d ^ s2) & 0x80) {
246 c->psw |= E8080_FLG_P;
247 }
248
249 if ((s1 ^ s2 ^ d) & 0x10) {
250 c->psw |= E8080_FLG_A;
251 }
252}
253
254void z80_set_psw_add16 (e8080_t *c, unsigned long d, unsigned s1, unsigned s2)
255{
256 c->psw &= ~(E8080_FLG_A | E8080_FLG_N | E8080_FLG_C);
257
258 if (d > 65535) {
259 c->psw |= E8080_FLG_C;
260 }
261
262 if ((s1 ^ s2 ^ d) & 0x1000) {
263 c->psw |= E8080_FLG_A;
264 }
265}
266
267void z80_set_psw_add16_2 (e8080_t *c, unsigned long d, unsigned s1, unsigned s2)
268{
269 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P | E8080_FLG_N | E8080_FLG_C);
270
271 if (d & 0x8000) {
272 c->psw |= E8080_FLG_S;
273 }
274
275 if ((d & 0xffff) == 0) {
276 c->psw |= E8080_FLG_Z;
277 }
278
279 if (d > 65535) {
280 c->psw |= E8080_FLG_C;
281 }
282
283 if ((s1 ^ d) & (s1 ^ s2) & 0x8000) {
284 c->psw |= E8080_FLG_P;
285 }
286
287 if ((s1 ^ s2 ^ d) & 0x1000) {
288 c->psw |= E8080_FLG_A;
289 }
290}
291
292void z80_set_psw_sub (e8080_t *c, unsigned d, unsigned char s1, unsigned char s2)
293{
294 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P | E8080_FLG_C);
295
296 set_psw_sz (c, d);
297
298 if (d > 255) {
299 c->psw |= E8080_FLG_C;
300 }
301
302 if ((s1 ^ d) & (s1 ^ s2) & 0x80) {
303 c->psw |= E8080_FLG_P;
304 }
305
306 if ((s1 ^ s2 ^ d) & 0x10) {
307 c->psw |= E8080_FLG_A;
308 }
309
310 c->psw |= E8080_FLG_N;
311}
312
313void z80_set_psw_sub16_2 (e8080_t *c, unsigned long d, unsigned s1, unsigned s2)
314{
315 c->psw &= ~(E8080_FLG_S | E8080_FLG_Z | E8080_FLG_A | E8080_FLG_P | E8080_FLG_C);
316
317 if (d & 0x8000) {
318 c->psw |= E8080_FLG_S;
319 }
320
321 if ((d & 0xffff) == 0) {
322 c->psw |= E8080_FLG_Z;
323 }
324
325 if (d > 65535) {
326 c->psw |= E8080_FLG_C;
327 }
328
329 if ((s1 ^ d) & (s1 ^ s2) & 0x8000) {
330 c->psw |= E8080_FLG_P;
331 }
332
333 if ((s1 ^ s2 ^ d) & 0x1000) {
334 c->psw |= E8080_FLG_A;
335 }
336
337 c->psw |= E8080_FLG_N;
338}