1 /* 2 * E-UAE - The portable Amiga Emulator 3 * 4 * MC68000 emulation - machine-dependent optimized operations 5 * 6 * (c) 2004-2007 Richard Drummond 7 */ 8 9 #ifndef EUAE_MACHDEP_M68KOPS_H 10 #define EUAE_MACHDEP_M68KOPS_H 11 12 #ifndef ANDROID 13 14 #if defined(__CELLOS_LV2__) || defined(_WIN32) || defined(__x86_64__) || defined(ARM) || defined(WIIU) || defined(__powerpc__) 15 16 #ifdef WIIU 17 #define FLAGBIT_N 31 18 #define FLAGBIT_Z 29 19 #define FLAGBIT_V 22 20 #define FLAGBIT_C 21 21 #define FLAGBIT_X 21 22 #else 23 #define FLAGBIT_N 15 24 #define FLAGBIT_Z 14 25 #define FLAGBIT_C 8 26 #define FLAGBIT_V 0 27 #define FLAGBIT_X 8 28 #endif 29 30 #define FLAGVAL_N (1 << FLAGBIT_N) 31 #define FLAGVAL_Z (1 << FLAGBIT_Z) 32 #define FLAGVAL_C (1 << FLAGBIT_C) 33 #define FLAGVAL_V (1 << FLAGBIT_V) 34 #define FLAGVAL_X (1 << FLAGBIT_X) 35 36 #define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~FLAGVAL_Z) | (((y) ? 1 : 0) << FLAGBIT_Z)) 37 #define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~FLAGVAL_C) | (((y) ? 1 : 0) << FLAGBIT_C)) 38 #define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~FLAGVAL_V) | (((y) ? 1 : 0) << FLAGBIT_V)) 39 #define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~FLAGVAL_N) | (((y) ? 1 : 0) << FLAGBIT_N)) 40 #define SET_XFLG(y) (regflags.x = ((y) ? 1 : 0) << FLAGBIT_X) 41 42 #define GET_ZFLG() ((regflags.cznv >> FLAGBIT_Z) & 1) 43 #define GET_CFLG() ((regflags.cznv >> FLAGBIT_C) & 1) 44 #define GET_VFLG() ((regflags.cznv >> FLAGBIT_V) & 1) 45 #define GET_NFLG() ((regflags.cznv >> FLAGBIT_N) & 1) 46 #define GET_XFLG() ((regflags.x >> FLAGBIT_X) & 1) 47 48 #define CLEAR_CZNV() (regflags.cznv = 0) 49 #define GET_CZNV (regflags.cznv) 50 #define IOR_CZNV(X) (regflags.cznv |= (X)) 51 #define SET_CZNV(X) (regflags.cznv = (X)) 52 53 #define COPY_CARRY() (regflags.x = regflags.cznv) 54 55 /* 56 * Test operations 57 * 58 * Evaluate operand and set Z and N flags. Always clear C and V. 59 */ 60 61 62 #define optflag_testl(v) \ 63 do { \ 64 CLEAR_CZNV ();\ 65 SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0);\ 66 SET_NFLG ( (((uae_s32)(v)) < 0) ? 1 : 0); \ 67 } while (0) 68 69 #define optflag_testw(v) \ 70 do { \ 71 CLEAR_CZNV ();\ 72 SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0);\ 73 SET_NFLG ( (((uae_s16)(v)) < 0) ? 1 : 0); \ 74 } while (0) 75 76 #define optflag_testb(v) \ 77 do { \ 78 CLEAR_CZNV ();\ 79 SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0);\ 80 SET_NFLG ( (((uae_s8)(v)) < 0) ? 1 : 0); \ 81 } while (0) 82 83 84 85 /* 86 * Add operations 87 * 88 * Perform v = s + d and set ZNCV accordingly 89 */ 90 91 #define optflag_addl(v, s, d) \ 92 do {\ 93 v = ((uae_s32)(d)) + ((uae_s32)(s)); \ 94 int flgs = (((uae_s32)(s)) < 0) ? 1 : 0; \ 95 int flgo = (((uae_s32)(d)) < 0) ? 1 : 0; \ 96 int flgn = (((uae_s32)(v)) < 0) ? 1 : 0; \ 97 SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0); \ 98 SET_VFLG ( (flgs ^ flgn) & (flgo ^ flgn)); \ 99 SET_CFLG ( (((uae_u32)(~d)) < ((uae_u32)(s))) ? 1 : 0); \ 100 COPY_CARRY (); \ 101 SET_NFLG ( flgn); \ 102 } while (0) 103 104 #define optflag_addw(v, s, d) \ 105 do {\ 106 v = ((uae_s16)(d)) + ((uae_s16)(s)); \ 107 int flgs = (((uae_s16)(s)) < 0) ? 1 : 0; \ 108 int flgo = (((uae_s16)(d)) < 0) ? 1 : 0; \ 109 int flgn = (((uae_s16)(v)) < 0) ? 1 : 0; \ 110 SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0); \ 111 SET_VFLG ( (flgs ^ flgn) & (flgo ^ flgn)); \ 112 SET_CFLG ( (((uae_u16)(~d)) < ((uae_u16)(s))) ? 1 : 0); \ 113 COPY_CARRY (); \ 114 SET_NFLG ( flgn); \ 115 } while (0) 116 117 #define optflag_addb(v, s, d) \ 118 do {\ 119 v = ((uae_s8)(d)) + ((uae_s8)(s)); \ 120 int flgs = (((uae_s8)(s)) < 0) ? 1 : 0; \ 121 int flgo = (((uae_s8)(d)) < 0) ? 1 : 0; \ 122 int flgn = (((uae_s8)(v)) < 0) ? 1 : 0; \ 123 SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0); \ 124 SET_VFLG ( (flgs ^ flgn) & (flgo ^ flgn)); \ 125 SET_CFLG ( (((uae_u8)(~d)) < ((uae_u8)(s))) ? 1 : 0); \ 126 COPY_CARRY (); \ 127 SET_NFLG ( flgn); \ 128 } while (0) 129 130 /* 131 * Subtraction operations 132 * 133 * Perform v = d - s and set ZNCV accordingly 134 */ 135 136 #define optflag_subb(v, s, d) \ 137 do {\ 138 v = ((uae_s8)(d)) - ((uae_s8)(s)); \ 139 int flgs = (((uae_s8)(s)) < 0) ? 1 : 0; \ 140 int flgo = (((uae_s8)(d)) < 0) ? 1 : 0; \ 141 int flgn = (((uae_s8)(v)) < 0) ? 1 : 0; \ 142 SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0); \ 143 SET_VFLG ( (flgs ^ flgo) & (flgn ^ flgo)); \ 144 SET_CFLG ( (((uae_u8)(s)) > ((uae_u8)(d))) ? 1 : 0); \ 145 COPY_CARRY (); \ 146 SET_NFLG ( flgn); \ 147 } while (0) 148 149 #define optflag_subw(v, s, d) \ 150 do {\ 151 v = ((uae_s16)(d)) - ((uae_s16)(s)); \ 152 int flgs = (((uae_s16)(s)) < 0) ? 1 : 0; \ 153 int flgo = (((uae_s16)(d)) < 0) ? 1 : 0; \ 154 int flgn = (((uae_s16)(v)) < 0) ? 1 : 0; \ 155 SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0); \ 156 SET_VFLG ( (flgs ^ flgo) & (flgn ^ flgo)); \ 157 SET_CFLG ( (((uae_u16)(s)) > ((uae_u16)(d))) ? 1 : 0); \ 158 COPY_CARRY (); \ 159 SET_NFLG ( flgn); \ 160 } while (0) 161 162 #define optflag_subl(v, s, d) \ 163 do {\ 164 v = ((uae_s32)(d)) - ((uae_s32)(s)); \ 165 int flgs = (((uae_s32)(s)) < 0) ? 1 : 0; \ 166 int flgo = (((uae_s32)(d)) < 0) ? 1 : 0; \ 167 int flgn = (((uae_s32)(v)) < 0) ? 1 : 0; \ 168 SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0); \ 169 SET_VFLG ( (flgs ^ flgo) & (flgn ^ flgo)); \ 170 SET_CFLG ( (((uae_u32)(s)) > ((uae_u32)(d))) ? 1 : 0); \ 171 COPY_CARRY (); \ 172 SET_NFLG ( flgn); \ 173 } while (0) 174 175 176 /* 177 * Compare operations 178 */ 179 180 #define optflag_cmpb(s, d) \ 181 do {\ 182 uae_u32 v = ((uae_s8)(d)) - ((uae_s8)(s)); \ 183 int flgs = (((uae_s8)(s)) < 0) ? 1 : 0; \ 184 int flgo = (((uae_s8)(d)) < 0) ? 1 : 0; \ 185 int flgn = (((uae_s8)(v)) < 0) ? 1 : 0; \ 186 SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0); \ 187 SET_VFLG ( (flgs != flgo) && (flgn != flgo));\ 188 SET_CFLG ( (((uae_u8)(s)) > ((uae_u8)(d))) ? 1 : 0); \ 189 SET_NFLG ( flgn); \ 190 }while (0) 191 192 193 #define optflag_cmpw(s, d) \ 194 do {\ 195 uae_u32 v = ((uae_s16)(d)) - ((uae_s16)(s)); \ 196 int flgs = (((uae_s16)(s)) < 0) ? 1 : 0; \ 197 int flgo = (((uae_s16)(d)) < 0) ? 1 : 0; \ 198 int flgn = (((uae_s16)(v)) < 0) ? 1 : 0; \ 199 SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0); \ 200 SET_VFLG ( (flgs != flgo) && (flgn != flgo));\ 201 SET_CFLG ( (((uae_u16)(s)) > ((uae_u16)(d))) ? 1 : 0); \ 202 SET_NFLG ( flgn); \ 203 }while (0) 204 205 #define optflag_cmpl(s, d) \ 206 do {\ 207 uae_u32 v = ((uae_s32)(d)) - ((uae_s32)(s)); \ 208 int flgs = (((uae_s32)(s)) < 0) ? 1 : 0; \ 209 int flgo = (((uae_s32)(d)) < 0) ? 1 : 0; \ 210 int flgn = (((uae_s32)(v)) < 0) ? 1 : 0; \ 211 SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0); \ 212 SET_VFLG ( (flgs != flgo) && (flgn != flgo));\ 213 SET_CFLG ( (((uae_u32)(s)) > ((uae_u32)(d))) ? 1 : 0); \ 214 SET_NFLG ( flgn); \ 215 }while (0) 216 217 #else 218 219 #warning "OPT TESTFLAG" 220 /* 221 * Optimized code which uses the host CPU's condition flags to evaluate 222 * 68K CCR flags for certain operations. 223 * 224 * These are used by various opcode handlers when 225 * gencpu has been built with OPTIMIZED_FLAGS defined 226 */ 227 228 /* 229 * Test operations 230 * 231 * Evaluate operand and set Z and N flags. Always clear C and V. 232 */ 233 /* Is there any way to do this without declaring *all* memory clobbered? 234 I.e. any way to tell gcc that some byte-sized value is in %al? */ 235 #ifdef __APPLE__ 236 #define optflag_testl(v) \ 237 __asm__ __volatile__ ("andl %0,%0\n\t" \ 238 "lahf\n\t" \ 239 "seto %%al\n\t" \ 240 "movb %%al,_regflags\n\t" \ 241 "movb %%ah,_regflags+1\n\t" \ 242 :: "r" (v) : "%eax","cc","memory") 243 #define optflag_testw(v) \ 244 __asm__ __volatile__ ("andw %w0,%w0\n\t" \ 245 "lahf\n\t" \ 246 "seto %%al\n\t" \ 247 "movb %%al,_regflags\n\t" \ 248 "movb %%ah,_regflags+1\n\t" \ 249 :: "r" (v) : "%eax","cc","memory") 250 251 #define optflag_testb(v) \ 252 __asm__ __volatile__ ("andb %b0,%b0\n\t" \ 253 "lahf\n\t" \ 254 "seto %%al\n\t" \ 255 "movb %%al,_regflags\n\t" \ 256 "movb %%ah,_regflags+1\n\t" \ 257 :: "q" (v) : "%eax","cc","memory") 258 259 #define optflag_addl(v, s, d) do { \ 260 __asm__ __volatile__ ("addl %k1,%k0\n\t" \ 261 "lahf\n\t" \ 262 "seto %%al\n\t" \ 263 "movb %%al,_regflags\n\t" \ 264 "movb %%ah,_regflags+1\n\t" \ 265 :"=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ 266 regflags.x = regflags.cznv; \ 267 } while (0) 268 #define optflag_addw(v, s, d) do { \ 269 __asm__ __volatile__ ("addw %w1,%w0\n\t" \ 270 "lahf\n\t" \ 271 "seto %%al\n\t" \ 272 "movb %%al,_regflags\n\t" \ 273 "movb %%ah,_regflags+1\n\t" \ 274 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ 275 regflags.x = regflags.cznv; \ 276 } while (0) 277 278 #define optflag_addb(v, s, d) do { \ 279 __asm__ __volatile__ ("addb %b1,%b0\n\t" \ 280 "lahf\n\t" \ 281 "seto %%al\n\t" \ 282 "movb %%al,_regflags\n\t" \ 283 "movb %%ah,_regflags+1\n\t" \ 284 :"=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \ 285 regflags.x = regflags.cznv; \ 286 } while (0) 287 288 #define optflag_subl(v, s, d) do { \ 289 __asm__ __volatile__ ("subl %k1,%k0\n\t" \ 290 "lahf\n\t" \ 291 "seto %%al\n\t" \ 292 "movb %%al,_regflags\n\t" \ 293 "movb %%ah,_regflags+1\n\t" \ 294 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ 295 regflags.x = regflags.cznv; \ 296 } while (0) 297 298 #define optflag_subw(v, s, d) do { \ 299 __asm__ __volatile__ ("subw %w1,%w0\n\t" \ 300 "lahf\n\t" \ 301 "seto %%al\n\t" \ 302 "movb %%al,_regflags\n\t" \ 303 "movb %%ah,_regflags+1\n\t" \ 304 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ 305 regflags.x = regflags.cznv; \ 306 } while (0) 307 308 #define optflag_subb(v, s, d) do { \ 309 __asm__ __volatile__ ("subb %b1,%b0\n\t" \ 310 "lahf\n\t" \ 311 "seto %%al\n\t" \ 312 "movb %%al,_regflags\n\t" \ 313 "movb %%ah,_regflags+1\n\t" \ 314 : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \ 315 regflags.x = regflags.cznv; \ 316 } while (0) 317 318 #define optflag_cmpl(s, d) \ 319 __asm__ __volatile__ ("cmpl %k0,%k1\n\t" \ 320 "lahf\n\t" \ 321 "seto %%al\n\t" \ 322 "movb %%al,_regflags\n\t" \ 323 "movb %%ah,_regflags+1\n\t" \ 324 :: "rmi" (s), "r" (d) : "%eax","cc","memory") 325 326 #define optflag_cmpw(s, d) \ 327 __asm__ __volatile__ ("cmpw %w0,%w1\n\t" \ 328 "lahf\n\t" \ 329 "seto %%al\n\t" \ 330 "movb %%al,_regflags\n\t" \ 331 "movb %%ah,_regflags+1\n\t" \ 332 :: "rmi" (s), "r" (d) : "%eax","cc","memory"); 333 334 #define optflag_cmpb(s, d) \ 335 __asm__ __volatile__ ("cmpb %b0,%b1\n\t" \ 336 "lahf\n\t" \ 337 "seto %%al\n\t" \ 338 "movb %%al,_regflags\n\t" \ 339 "movb %%ah,_regflags+1\n\t" \ 340 :: "qmi" (s), "q" (d) : "%eax","cc","memory") 341 #else /*ifdef apple*/ 342 #define optflag_testl(v) \ 343 __asm__ __volatile__ ("andl %0,%0\n\t" \ 344 "lahf\n\t" \ 345 "seto %%al\n\t" \ 346 "movb %%al,regflags\n\t" \ 347 "movb %%ah,regflags+1\n\t" \ 348 :: "r" (v) : "%eax","cc","memory") 349 #define optflag_testw(v) \ 350 __asm__ __volatile__ ("andw %w0,%w0\n\t" \ 351 "lahf\n\t" \ 352 "seto %%al\n\t" \ 353 "movb %%al,regflags\n\t" \ 354 "movb %%ah,regflags+1\n\t" \ 355 :: "r" (v) : "%eax","cc","memory") 356 357 #define optflag_testb(v) \ 358 __asm__ __volatile__ ("andb %b0,%b0\n\t" \ 359 "lahf\n\t" \ 360 "seto %%al\n\t" \ 361 "movb %%al,regflags\n\t" \ 362 "movb %%ah,regflags+1\n\t" \ 363 :: "q" (v) : "%eax","cc","memory") 364 365 #define optflag_addl(v, s, d) do { \ 366 __asm__ __volatile__ ("addl %k1,%k0\n\t" \ 367 "lahf\n\t" \ 368 "seto %%al\n\t" \ 369 "movb %%al,regflags\n\t" \ 370 "movb %%ah,regflags+1\n\t" \ 371 :"=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ 372 regflags.x = regflags.cznv; \ 373 } while (0) 374 #define optflag_addw(v, s, d) do { \ 375 __asm__ __volatile__ ("addw %w1,%w0\n\t" \ 376 "lahf\n\t" \ 377 "seto %%al\n\t" \ 378 "movb %%al,regflags\n\t" \ 379 "movb %%ah,regflags+1\n\t" \ 380 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ 381 regflags.x = regflags.cznv; \ 382 } while (0) 383 384 #define optflag_addb(v, s, d) do { \ 385 __asm__ __volatile__ ("addb %b1,%b0\n\t" \ 386 "lahf\n\t" \ 387 "seto %%al\n\t" \ 388 "movb %%al,regflags\n\t" \ 389 "movb %%ah,regflags+1\n\t" \ 390 :"=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \ 391 regflags.x = regflags.cznv; \ 392 } while (0) 393 394 #define optflag_subl(v, s, d) do { \ 395 __asm__ __volatile__ ("subl %k1,%k0\n\t" \ 396 "lahf\n\t" \ 397 "seto %%al\n\t" \ 398 "movb %%al,regflags\n\t" \ 399 "movb %%ah,regflags+1\n\t" \ 400 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ 401 regflags.x = regflags.cznv; \ 402 } while (0) 403 404 #define optflag_subw(v, s, d) do { \ 405 __asm__ __volatile__ ("subw %w1,%w0\n\t" \ 406 "lahf\n\t" \ 407 "seto %%al\n\t" \ 408 "movb %%al,regflags\n\t" \ 409 "movb %%ah,regflags+1\n\t" \ 410 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ 411 regflags.x = regflags.cznv; \ 412 } while (0) 413 414 #define optflag_subb(v, s, d) do { \ 415 __asm__ __volatile__ ("subb %b1,%b0\n\t" \ 416 "lahf\n\t" \ 417 "seto %%al\n\t" \ 418 "movb %%al,regflags\n\t" \ 419 "movb %%ah,regflags+1\n\t" \ 420 : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \ 421 regflags.x = regflags.cznv; \ 422 } while (0) 423 424 #define optflag_cmpl(s, d) \ 425 __asm__ __volatile__ ("cmpl %k0,%k1\n\t" \ 426 "lahf\n\t" \ 427 "seto %%al\n\t" \ 428 "movb %%al,regflags\n\t" \ 429 "movb %%ah,regflags+1\n\t" \ 430 :: "rmi" (s), "r" (d) : "%eax","cc","memory") 431 432 #define optflag_cmpw(s, d) \ 433 __asm__ __volatile__ ("cmpw %w0,%w1\n\t" \ 434 "lahf\n\t" \ 435 "seto %%al\n\t" \ 436 "movb %%al,regflags\n\t" \ 437 "movb %%ah,regflags+1\n\t" \ 438 :: "rmi" (s), "r" (d) : "%eax","cc","memory"); 439 440 #define optflag_cmpb(s, d) \ 441 __asm__ __volatile__ ("cmpb %b0,%b1\n\t" \ 442 "lahf\n\t" \ 443 "seto %%al\n\t" \ 444 "movb %%al,regflags\n\t" \ 445 "movb %%ah,regflags+1\n\t" \ 446 :: "qmi" (s), "q" (d) : "%eax","cc","memory") 447 #endif /*ifdef apple*/ 448 449 #endif 450 451 #else 452 /* 453 #define FLAGBIT_N 31 454 #define FLAGBIT_Z 30 455 #define FLAGBIT_C 29 456 #define FLAGBIT_V 28 457 #define FLAGBIT_X 29 458 */ 459 /* ARM COND 460 31 30 29 28 461 N Z C V 462 */ 463 #if ARM_OPT_TEST 464 465 #define optflag_testl(v) \ 466 __asm__ __volatile__ ( \ 467 "adds %1,%1,#0 \n"\ 468 "mrs %0, cpsr \n"\ 469 : "=r" (regflags.cznv) \ 470 : "r" (v)\ 471 : "cc"\ 472 ); 473 474 #define optflag_testw(v) optflag_testl((uae_s32)(v)) 475 #define optflag_testb(v) optflag_testl((uae_s32)(v)) 476 477 #define optflag_addlong(v, s, d) \ 478 __asm__ __volatile__ ( \ 479 "adds %1,%2,%3 \n"\ 480 "mrs %0, cpsr \n"\ 481 : "=r" (regflags.cznv), "=r" (v) \ 482 : "r" (s), "r" (d) \ 483 : "cc"\ 484 ); 485 486 #define optflag_addl(v, s, d) do { optflag_addlong(v, s, d); regflags.x = regflags.cznv; } while (0) 487 #define optflag_addw(v, s, d) do { optflag_addlong(v, (s) << 16, (d) << 16); v = v >> 16; regflags.x = regflags.cznv; } while (0) 488 #define optflag_addb(v, s, d) do { optflag_addlong(v, (s) << 24, (d) << 24); v = v >> 24; regflags.x = regflags.cznv; } while (0) 489 490 #define optflag_sublong(v, s, d) \ 491 __asm__ __volatile__ (\ 492 "rsbs %1, %2, %3\n\t" \ 493 "mrs %0, cpsr \n"\ 494 "eor %0,%0,#0x20000000 \n"\ 495 : "=r" (regflags.cznv), "=r" (v) \ 496 : "r" (s), "r" (d) \ 497 : "cc"\ 498 ); 499 500 #define optflag_subl(v, s, d) do { optflag_sublong(v, s, d); regflags.x = regflags.cznv; } while (0) 501 #define optflag_subw(v, s, d) do { optflag_sublong(v, (s) << 16, (d) << 16); v = v >> 16; regflags.x = regflags.cznv; } while (0) 502 #define optflag_subb(v, s, d) do { optflag_sublong(v, (s) << 24, (d) << 24); v = v >> 24; regflags.x = regflags.cznv; } while (0) 503 504 #define optflag_cmplong(s,d) \ 505 register int tmp;\ 506 __asm__ __volatile__ ( \ 507 "rsbs %1, %2,%3 \n"\ 508 "mrs %0, cpsr \n"\ 509 "eor %0,%0,#0x20000000 \n"\ 510 :"=r"(regflags.cznv) ,"=r"(tmp) \ 511 :"r" (s), "r" (d)\ 512 :"cc" \ 513 ); 514 515 #define optflag_cmpl(s, d) optflag_cmplong(s, d) 516 #define optflag_cmpw(s, d) optflag_cmplong((s) << 16, (d) << 16) 517 #define optflag_cmpb(s, d) optflag_cmplong((s) << 24, (d) << 24) 518 519 520 #else 521 522 #define FLAGBIT_N 15 523 #define FLAGBIT_Z 14 524 #define FLAGBIT_C 8 525 #define FLAGBIT_V 0 526 #define FLAGBIT_X 8 527 528 #define FLAGVAL_N (1 << FLAGBIT_N) 529 #define FLAGVAL_Z (1 << FLAGBIT_Z) 530 #define FLAGVAL_C (1 << FLAGBIT_C) 531 #define FLAGVAL_V (1 << FLAGBIT_V) 532 #define FLAGVAL_X (1 << FLAGBIT_X) 533 534 #define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~FLAGVAL_Z) | (((y) ? 1 : 0) << FLAGBIT_Z)) 535 #define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~FLAGVAL_C) | (((y) ? 1 : 0) << FLAGBIT_C)) 536 #define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~FLAGVAL_V) | (((y) ? 1 : 0) << FLAGBIT_V)) 537 #define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~FLAGVAL_N) | (((y) ? 1 : 0) << FLAGBIT_N)) 538 #define SET_XFLG(y) (regflags.x = ((y) ? 1 : 0) << FLAGBIT_X) 539 540 #define GET_ZFLG() ((regflags.cznv >> FLAGBIT_Z) & 1) 541 #define GET_CFLG() ((regflags.cznv >> FLAGBIT_C) & 1) 542 #define GET_VFLG() ((regflags.cznv >> FLAGBIT_V) & 1) 543 #define GET_NFLG() ((regflags.cznv >> FLAGBIT_N) & 1) 544 #define GET_XFLG() ((regflags.x >> FLAGBIT_X) & 1) 545 546 #define CLEAR_CZNV() (regflags.cznv = 0) 547 #define GET_CZNV (regflags.cznv) 548 #define IOR_CZNV(X) (regflags.cznv |= (X)) 549 #define SET_CZNV(X) (regflags.cznv = (X)) 550 551 #define COPY_CARRY() (regflags.x = regflags.cznv) 552 553 /* 554 * Test operations 555 * 556 * Evaluate operand and set Z and N flags. Always clear C and V. 557 */ 558 559 560 #define optflag_testl(v) \ 561 do { \ 562 CLEAR_CZNV ();\ 563 SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0);\ 564 SET_NFLG ( (((uae_s32)(v)) < 0) ? 1 : 0); \ 565 } while (0) 566 567 #define optflag_testw(v) \ 568 do { \ 569 CLEAR_CZNV ();\ 570 SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0);\ 571 SET_NFLG ( (((uae_s16)(v)) < 0) ? 1 : 0); \ 572 } while (0) 573 574 #define optflag_testb(v) \ 575 do { \ 576 CLEAR_CZNV ();\ 577 SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0);\ 578 SET_NFLG ( (((uae_s8)(v)) < 0) ? 1 : 0); \ 579 } while (0) 580 581 582 583 /* 584 * Add operations 585 * 586 * Perform v = s + d and set ZNCV accordingly 587 */ 588 589 #define optflag_addl(v, s, d) \ 590 do {\ 591 v = ((uae_s32)(d)) + ((uae_s32)(s)); \ 592 int flgs = (((uae_s32)(s)) < 0) ? 1 : 0; \ 593 int flgo = (((uae_s32)(d)) < 0) ? 1 : 0; \ 594 int flgn = (((uae_s32)(v)) < 0) ? 1 : 0; \ 595 SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0); \ 596 SET_VFLG ( (flgs ^ flgn) & (flgo ^ flgn)); \ 597 SET_CFLG ( (((uae_u32)(~d)) < ((uae_u32)(s))) ? 1 : 0); \ 598 COPY_CARRY (); \ 599 SET_NFLG ( flgn); \ 600 } while (0) 601 602 #define optflag_addw(v, s, d) \ 603 do {\ 604 v = ((uae_s16)(d)) + ((uae_s16)(s)); \ 605 int flgs = (((uae_s16)(s)) < 0) ? 1 : 0; \ 606 int flgo = (((uae_s16)(d)) < 0) ? 1 : 0; \ 607 int flgn = (((uae_s16)(v)) < 0) ? 1 : 0; \ 608 SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0); \ 609 SET_VFLG ( (flgs ^ flgn) & (flgo ^ flgn)); \ 610 SET_CFLG ( (((uae_u16)(~d)) < ((uae_u16)(s))) ? 1 : 0); \ 611 COPY_CARRY (); \ 612 SET_NFLG ( flgn); \ 613 } while (0) 614 615 #define optflag_addb(v, s, d) \ 616 do {\ 617 v = ((uae_s8)(d)) + ((uae_s8)(s)); \ 618 int flgs = (((uae_s8)(s)) < 0) ? 1 : 0; \ 619 int flgo = (((uae_s8)(d)) < 0) ? 1 : 0; \ 620 int flgn = (((uae_s8)(v)) < 0) ? 1 : 0; \ 621 SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0); \ 622 SET_VFLG ( (flgs ^ flgn) & (flgo ^ flgn)); \ 623 SET_CFLG ( (((uae_u8)(~d)) < ((uae_u8)(s))) ? 1 : 0); \ 624 COPY_CARRY (); \ 625 SET_NFLG ( flgn); \ 626 } while (0) 627 628 /* 629 * Subtraction operations 630 * 631 * Perform v = d - s and set ZNCV accordingly 632 */ 633 634 #define optflag_subb(v, s, d) \ 635 do {\ 636 v = ((uae_s8)(d)) - ((uae_s8)(s)); \ 637 int flgs = (((uae_s8)(s)) < 0) ? 1 : 0; \ 638 int flgo = (((uae_s8)(d)) < 0) ? 1 : 0; \ 639 int flgn = (((uae_s8)(v)) < 0) ? 1 : 0; \ 640 SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0); \ 641 SET_VFLG ( (flgs ^ flgo) & (flgn ^ flgo)); \ 642 SET_CFLG ( (((uae_u8)(s)) > ((uae_u8)(d))) ? 1 : 0); \ 643 COPY_CARRY (); \ 644 SET_NFLG ( flgn); \ 645 } while (0) 646 647 #define optflag_subw(v, s, d) \ 648 do {\ 649 v = ((uae_s16)(d)) - ((uae_s16)(s)); \ 650 int flgs = (((uae_s16)(s)) < 0) ? 1 : 0; \ 651 int flgo = (((uae_s16)(d)) < 0) ? 1 : 0; \ 652 int flgn = (((uae_s16)(v)) < 0) ? 1 : 0; \ 653 SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0); \ 654 SET_VFLG ( (flgs ^ flgo) & (flgn ^ flgo)); \ 655 SET_CFLG ( (((uae_u16)(s)) > ((uae_u16)(d))) ? 1 : 0); \ 656 COPY_CARRY (); \ 657 SET_NFLG ( flgn); \ 658 } while (0) 659 660 #define optflag_subl(v, s, d) \ 661 do {\ 662 v = ((uae_s32)(d)) - ((uae_s32)(s)); \ 663 int flgs = (((uae_s32)(s)) < 0) ? 1 : 0; \ 664 int flgo = (((uae_s32)(d)) < 0) ? 1 : 0; \ 665 int flgn = (((uae_s32)(v)) < 0) ? 1 : 0; \ 666 SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0); \ 667 SET_VFLG ( (flgs ^ flgo) & (flgn ^ flgo)); \ 668 SET_CFLG ( (((uae_u32)(s)) > ((uae_u32)(d))) ? 1 : 0); \ 669 COPY_CARRY (); \ 670 SET_NFLG ( flgn); \ 671 } while (0) 672 673 674 /* 675 * Compare operations 676 */ 677 678 #define optflag_cmpb(s, d) \ 679 do {\ 680 uae_u32 v = ((uae_s8)(d)) - ((uae_s8)(s)); \ 681 int flgs = (((uae_s8)(s)) < 0) ? 1 : 0; \ 682 int flgo = (((uae_s8)(d)) < 0) ? 1 : 0; \ 683 int flgn = (((uae_s8)(v)) < 0) ? 1 : 0; \ 684 SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0); \ 685 SET_VFLG ( (flgs != flgo) && (flgn != flgo));\ 686 SET_CFLG ( (((uae_u8)(s)) > ((uae_u8)(d))) ? 1 : 0); \ 687 SET_NFLG ( flgn); \ 688 }while (0) 689 690 691 #define optflag_cmpw(s, d) \ 692 do {\ 693 uae_u32 v = ((uae_s16)(d)) - ((uae_s16)(s)); \ 694 int flgs = (((uae_s16)(s)) < 0) ? 1 : 0; \ 695 int flgo = (((uae_s16)(d)) < 0) ? 1 : 0; \ 696 int flgn = (((uae_s16)(v)) < 0) ? 1 : 0; \ 697 SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0); \ 698 SET_VFLG ( (flgs != flgo) && (flgn != flgo));\ 699 SET_CFLG ( (((uae_u16)(s)) > ((uae_u16)(d))) ? 1 : 0); \ 700 SET_NFLG ( flgn); \ 701 }while (0) 702 703 #define optflag_cmpl(s, d) \ 704 do {\ 705 uae_u32 v = ((uae_s32)(d)) - ((uae_s32)(s)); \ 706 int flgs = (((uae_s32)(s)) < 0) ? 1 : 0; \ 707 int flgo = (((uae_s32)(d)) < 0) ? 1 : 0; \ 708 int flgn = (((uae_s32)(v)) < 0) ? 1 : 0; \ 709 SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0); \ 710 SET_VFLG ( (flgs != flgo) && (flgn != flgo));\ 711 SET_CFLG ( (((uae_u32)(s)) > ((uae_u32)(d))) ? 1 : 0); \ 712 SET_NFLG ( flgn); \ 713 }while (0) 714 715 #endif 716 717 #endif 718 719 #endif /* EUAE_MACHDEP_M68KOPS_H */ 720