fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 338 lines 7.7 kB view raw
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}