1 /* 2 * Copyright (C) 2002-2021 The DOSBox Team 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License along 15 * with this program; if not, write to the Free Software Foundation, Inc., 16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19 #include "lazyflags.h" 20 21 /* Jumps */ 22 23 /* All Byte general instructions */ 24 #define ADDB(op1,op2,load,save) \ 25 lf_var1b=load(op1);lf_var2b=op2; \ 26 lf_resb=lf_var1b+lf_var2b; \ 27 save(op1,lf_resb); \ 28 lflags.type=t_ADDb; 29 30 #define ADCB(op1,op2,load,save) \ 31 lflags.oldcf=get_CF()!=0; \ 32 lf_var1b=load(op1);lf_var2b=op2; \ 33 lf_resb=lf_var1b+lf_var2b+lflags.oldcf; \ 34 save(op1,lf_resb); \ 35 lflags.type=t_ADCb; 36 37 #define SBBB(op1,op2,load,save) \ 38 lflags.oldcf=get_CF()!=0; \ 39 lf_var1b=load(op1);lf_var2b=op2; \ 40 lf_resb=lf_var1b-(lf_var2b+lflags.oldcf); \ 41 save(op1,lf_resb); \ 42 lflags.type=t_SBBb; 43 44 #define SUBB(op1,op2,load,save) \ 45 lf_var1b=load(op1);lf_var2b=op2; \ 46 lf_resb=lf_var1b-lf_var2b; \ 47 save(op1,lf_resb); \ 48 lflags.type=t_SUBb; 49 50 #define ORB(op1,op2,load,save) \ 51 lf_var1b=load(op1);lf_var2b=op2; \ 52 lf_resb=lf_var1b | lf_var2b; \ 53 save(op1,lf_resb); \ 54 lflags.type=t_ORb; 55 56 #define XORB(op1,op2,load,save) \ 57 lf_var1b=load(op1);lf_var2b=op2; \ 58 lf_resb=lf_var1b ^ lf_var2b; \ 59 save(op1,lf_resb); \ 60 lflags.type=t_XORb; 61 62 #define ANDB(op1,op2,load,save) \ 63 lf_var1b=load(op1);lf_var2b=op2; \ 64 lf_resb=lf_var1b & lf_var2b; \ 65 save(op1,lf_resb); \ 66 lflags.type=t_ANDb; 67 68 #define CMPB(op1,op2,load,save) \ 69 lf_var1b=load(op1);lf_var2b=op2; \ 70 lf_resb=lf_var1b-lf_var2b; \ 71 lflags.type=t_CMPb; 72 73 #define TESTB(op1,op2,load,save) \ 74 lf_var1b=load(op1);lf_var2b=op2; \ 75 lf_resb=lf_var1b & lf_var2b; \ 76 lflags.type=t_TESTb; 77 78 /* All Word General instructions */ 79 80 #define ADDW(op1,op2,load,save) \ 81 lf_var1w=load(op1);lf_var2w=op2; \ 82 lf_resw=lf_var1w+lf_var2w; \ 83 save(op1,lf_resw); \ 84 lflags.type=t_ADDw; 85 86 #define ADCW(op1,op2,load,save) \ 87 lflags.oldcf=get_CF()!=0; \ 88 lf_var1w=load(op1);lf_var2w=op2; \ 89 lf_resw=lf_var1w+lf_var2w+lflags.oldcf; \ 90 save(op1,lf_resw); \ 91 lflags.type=t_ADCw; 92 93 #define SBBW(op1,op2,load,save) \ 94 lflags.oldcf=get_CF()!=0; \ 95 lf_var1w=load(op1);lf_var2w=op2; \ 96 lf_resw=lf_var1w-(lf_var2w+lflags.oldcf); \ 97 save(op1,lf_resw); \ 98 lflags.type=t_SBBw; 99 100 #define SUBW(op1,op2,load,save) \ 101 lf_var1w=load(op1);lf_var2w=op2; \ 102 lf_resw=lf_var1w-lf_var2w; \ 103 save(op1,lf_resw); \ 104 lflags.type=t_SUBw; 105 106 #define ORW(op1,op2,load,save) \ 107 lf_var1w=load(op1);lf_var2w=op2; \ 108 lf_resw=lf_var1w | lf_var2w; \ 109 save(op1,lf_resw); \ 110 lflags.type=t_ORw; 111 112 #define XORW(op1,op2,load,save) \ 113 lf_var1w=load(op1);lf_var2w=op2; \ 114 lf_resw=lf_var1w ^ lf_var2w; \ 115 save(op1,lf_resw); \ 116 lflags.type=t_XORw; 117 118 #define ANDW(op1,op2,load,save) \ 119 lf_var1w=load(op1);lf_var2w=op2; \ 120 lf_resw=lf_var1w & lf_var2w; \ 121 save(op1,lf_resw); \ 122 lflags.type=t_ANDw; 123 124 #define CMPW(op1,op2,load,save) \ 125 lf_var1w=load(op1);lf_var2w=op2; \ 126 lf_resw=lf_var1w-lf_var2w; \ 127 lflags.type=t_CMPw; 128 129 #define TESTW(op1,op2,load,save) \ 130 lf_var1w=load(op1);lf_var2w=op2; \ 131 lf_resw=lf_var1w & lf_var2w; \ 132 lflags.type=t_TESTw; 133 134 /* All DWORD General Instructions */ 135 136 #define ADDD(op1,op2,load,save) \ 137 lf_var1d=load(op1);lf_var2d=op2; \ 138 lf_resd=lf_var1d+lf_var2d; \ 139 save(op1,lf_resd); \ 140 lflags.type=t_ADDd; 141 142 #define ADCD(op1,op2,load,save) \ 143 lflags.oldcf=get_CF()!=0; \ 144 lf_var1d=load(op1);lf_var2d=op2; \ 145 lf_resd=lf_var1d+lf_var2d+lflags.oldcf; \ 146 save(op1,lf_resd); \ 147 lflags.type=t_ADCd; 148 149 #define SBBD(op1,op2,load,save) \ 150 lflags.oldcf=get_CF()!=0; \ 151 lf_var1d=load(op1);lf_var2d=op2; \ 152 lf_resd=lf_var1d-(lf_var2d+lflags.oldcf); \ 153 save(op1,lf_resd); \ 154 lflags.type=t_SBBd; 155 156 #define SUBD(op1,op2,load,save) \ 157 lf_var1d=load(op1);lf_var2d=op2; \ 158 lf_resd=lf_var1d-lf_var2d; \ 159 save(op1,lf_resd); \ 160 lflags.type=t_SUBd; 161 162 #define ORD(op1,op2,load,save) \ 163 lf_var1d=load(op1);lf_var2d=op2; \ 164 lf_resd=lf_var1d | lf_var2d; \ 165 save(op1,lf_resd); \ 166 lflags.type=t_ORd; 167 168 #define XORD(op1,op2,load,save) \ 169 lf_var1d=load(op1);lf_var2d=op2; \ 170 lf_resd=lf_var1d ^ lf_var2d; \ 171 save(op1,lf_resd); \ 172 lflags.type=t_XORd; 173 174 #define ANDD(op1,op2,load,save) \ 175 lf_var1d=load(op1);lf_var2d=op2; \ 176 lf_resd=lf_var1d & lf_var2d; \ 177 save(op1,lf_resd); \ 178 lflags.type=t_ANDd; 179 180 #define CMPD(op1,op2,load,save) \ 181 lf_var1d=load(op1);lf_var2d=op2; \ 182 lf_resd=lf_var1d-lf_var2d; \ 183 lflags.type=t_CMPd; 184 185 186 #define TESTD(op1,op2,load,save) \ 187 lf_var1d=load(op1);lf_var2d=op2; \ 188 lf_resd=lf_var1d & lf_var2d; \ 189 lflags.type=t_TESTd; 190 191 192 193 194 #define INCB(op1,load,save) \ 195 LoadCF;lf_var1b=load(op1); \ 196 lf_resb=lf_var1b+1; \ 197 save(op1,lf_resb); \ 198 lflags.type=t_INCb; \ 199 200 #define INCW(op1,load,save) \ 201 LoadCF;lf_var1w=load(op1); \ 202 lf_resw=lf_var1w+1; \ 203 save(op1,lf_resw); \ 204 lflags.type=t_INCw; 205 206 #define INCD(op1,load,save) \ 207 LoadCF;lf_var1d=load(op1); \ 208 lf_resd=lf_var1d+1; \ 209 save(op1,lf_resd); \ 210 lflags.type=t_INCd; 211 212 #define DECB(op1,load,save) \ 213 LoadCF;lf_var1b=load(op1); \ 214 lf_resb=lf_var1b-1; \ 215 save(op1,lf_resb); \ 216 lflags.type=t_DECb; 217 218 #define DECW(op1,load,save) \ 219 LoadCF;lf_var1w=load(op1); \ 220 lf_resw=lf_var1w-1; \ 221 save(op1,lf_resw); \ 222 lflags.type=t_DECw; 223 224 #define DECD(op1,load,save) \ 225 LoadCF;lf_var1d=load(op1); \ 226 lf_resd=lf_var1d-1; \ 227 save(op1,lf_resd); \ 228 lflags.type=t_DECd; 229 230 231 232 #define ROLB(op1,op2,load,save) \ 233 FillFlagsNoCFOF(); \ 234 lf_var1b=load(op1); \ 235 lf_var2b=op2&0x07; \ 236 lf_resb=(lf_var1b << lf_var2b) | \ 237 (lf_var1b >> (8-lf_var2b)); \ 238 save(op1,lf_resb); \ 239 SETFLAGBIT(CF,lf_resb & 1); \ 240 SETFLAGBIT(OF,(lf_resb & 1) ^ (lf_resb >> 7)); 241 242 #define ROLW(op1,op2,load,save) \ 243 FillFlagsNoCFOF(); \ 244 lf_var1w=load(op1); \ 245 lf_var2b=op2&0xf; \ 246 lf_resw=(lf_var1w << lf_var2b) | \ 247 (lf_var1w >> (16-lf_var2b)); \ 248 save(op1,lf_resw); \ 249 SETFLAGBIT(CF,lf_resw & 1); \ 250 SETFLAGBIT(OF,(lf_resw & 1) ^ (lf_resw >> 15)); 251 252 #define ROLD(op1,op2,load,save) \ 253 FillFlagsNoCFOF(); \ 254 lf_var1d=load(op1); \ 255 lf_var2b=op2; \ 256 lf_resd=(lf_var1d << lf_var2b) | \ 257 (lf_var1d >> (32-lf_var2b)); \ 258 save(op1,lf_resd); \ 259 SETFLAGBIT(CF,lf_resd & 1); \ 260 SETFLAGBIT(OF,(lf_resd & 1) ^ (lf_resd >> 31)); 261 262 263 #define RORB(op1,op2,load,save) \ 264 FillFlagsNoCFOF(); \ 265 lf_var1b=load(op1); \ 266 lf_var2b=op2&0x07; \ 267 lf_resb=(lf_var1b >> lf_var2b) | \ 268 (lf_var1b << (8-lf_var2b)); \ 269 save(op1,lf_resb); \ 270 SETFLAGBIT(CF,lf_resb & 0x80); \ 271 SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); 272 273 #define RORW(op1,op2,load,save) \ 274 FillFlagsNoCFOF(); \ 275 lf_var1w=load(op1); \ 276 lf_var2b=op2&0xf; \ 277 lf_resw=(lf_var1w >> lf_var2b) | \ 278 (lf_var1w << (16-lf_var2b)); \ 279 save(op1,lf_resw); \ 280 SETFLAGBIT(CF,lf_resw & 0x8000); \ 281 SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); 282 283 #define RORD(op1,op2,load,save) \ 284 FillFlagsNoCFOF(); \ 285 lf_var1d=load(op1); \ 286 lf_var2b=op2; \ 287 lf_resd=(lf_var1d >> lf_var2b) | \ 288 (lf_var1d << (32-lf_var2b)); \ 289 save(op1,lf_resd); \ 290 SETFLAGBIT(CF,lf_resd & 0x80000000); \ 291 SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); 292 293 294 #define RCLB(op1,op2,load,save) \ 295 if (!(op2%9)) break; \ 296 { Bit8u cf=(Bit8u)FillFlags()&0x1; \ 297 lf_var1b=load(op1); \ 298 lf_var2b=op2%9; \ 299 lf_resb=(lf_var1b << lf_var2b) | \ 300 (cf << (lf_var2b-1)) | \ 301 (lf_var1b >> (9-lf_var2b)); \ 302 save(op1,lf_resb); \ 303 SETFLAGBIT(CF,((lf_var1b >> (8-lf_var2b)) & 1)); \ 304 SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resb >> 7)); \ 305 } 306 307 #define RCLW(op1,op2,load,save) \ 308 if (!(op2%17)) break; \ 309 { Bit16u cf=(Bit16u)FillFlags()&0x1; \ 310 lf_var1w=load(op1); \ 311 lf_var2b=op2%17; \ 312 lf_resw=(lf_var1w << lf_var2b) | \ 313 (cf << (lf_var2b-1)) | \ 314 (lf_var1w >> (17-lf_var2b)); \ 315 save(op1,lf_resw); \ 316 SETFLAGBIT(CF,((lf_var1w >> (16-lf_var2b)) & 1)); \ 317 SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resw >> 15)); \ 318 } 319 320 #define RCLD(op1, op2, load, save) \ 321 if (!op2) \ 322 break; \ 323 { \ 324 const uint32_t cf = FillFlags() & 0x1; \ 325 lf_var1d = load(op1); \ 326 lf_var2b = op2; \ 327 if (lf_var2b == 1) { \ 328 lf_resd = (lf_var1d << 1) | cf; \ 329 } else { \ 330 lf_resd = (lf_var1d << lf_var2b) | \ 331 (cf << lf_var2b_minus_one()) | \ 332 (lf_var1d >> (33 - lf_var2b)); \ 333 } \ 334 save(op1, lf_resd); \ 335 SETFLAGBIT(CF, ((lf_var1d >> (32 - lf_var2b)) & 1)); \ 336 SETFLAGBIT(OF, (reg_flags & 1) ^ (lf_resd >> 31)); \ 337 } 338 339 #define RCRB(op1, op2, load, save) \ 340 if (op2 % 9) { \ 341 Bit8u cf = (Bit8u)FillFlags() & 0x1; \ 342 lf_var1b = load(op1); \ 343 lf_var2b = op2 % 9; \ 344 lf_resb = (lf_var1b >> lf_var2b) | (cf << (8 - lf_var2b)) | \ 345 (lf_var1b << (9 - lf_var2b)); \ 346 save(op1, lf_resb); \ 347 SETFLAGBIT(CF, (lf_var1b >> lf_var2b_minus_one()) & 1); \ 348 SETFLAGBIT(OF, (lf_resb ^ (lf_resb << 1)) & 0x80); \ 349 } 350 351 #define RCRW(op1, op2, load, save) \ 352 if (op2 % 17) { \ 353 Bit16u cf = (Bit16u)FillFlags() & 0x1; \ 354 lf_var1w = load(op1); \ 355 lf_var2b = op2 % 17; \ 356 lf_resw = (lf_var1w >> lf_var2b) | (cf << (16 - lf_var2b)) | \ 357 (lf_var1w << (17 - lf_var2b)); \ 358 save(op1, lf_resw); \ 359 SETFLAGBIT(CF, (lf_var1w >> lf_var2b_minus_one()) & 1); \ 360 SETFLAGBIT(OF, (lf_resw ^ (lf_resw << 1)) & 0x8000); \ 361 } 362 363 #define RCRD(op1, op2, load, save) \ 364 if (op2) { \ 365 const uint32_t cf = FillFlags() & 0x1; \ 366 lf_var1d = load(op1); \ 367 lf_var2b = op2; \ 368 if (lf_var2b == 1) { \ 369 lf_resd = lf_var1d >> 1 | cf << 31; \ 370 } else { \ 371 lf_resd = (lf_var1d >> lf_var2b) | \ 372 (cf << (32 - lf_var2b)) | \ 373 (lf_var1d << (33 - lf_var2b)); \ 374 } \ 375 save(op1, lf_resd); \ 376 SETFLAGBIT(CF, (lf_var1d >> lf_var2b_minus_one()) & 1); \ 377 SETFLAGBIT(OF, (lf_resd ^ (lf_resd << 1)) & 0x80000000); \ 378 } 379 380 #define SHLB(op1,op2,load,save) \ 381 lf_var1b=load(op1);lf_var2b=op2; \ 382 lf_resb=lf_var1b << lf_var2b; \ 383 save(op1,lf_resb); \ 384 lflags.type=t_SHLb; 385 386 #define SHLW(op1,op2,load,save) \ 387 lf_var1w=load(op1);lf_var2b=op2 ; \ 388 lf_resw=lf_var1w << lf_var2b; \ 389 save(op1,lf_resw); \ 390 lflags.type=t_SHLw; 391 392 #define SHLD(op1,op2,load,save) \ 393 lf_var1d=load(op1);lf_var2b=op2; \ 394 lf_resd=lf_var1d << lf_var2b; \ 395 save(op1,lf_resd); \ 396 lflags.type=t_SHLd; 397 398 399 #define SHRB(op1,op2,load,save) \ 400 lf_var1b=load(op1);lf_var2b=op2; \ 401 lf_resb=lf_var1b >> lf_var2b; \ 402 save(op1,lf_resb); \ 403 lflags.type=t_SHRb; 404 405 #define SHRW(op1,op2,load,save) \ 406 lf_var1w=load(op1);lf_var2b=op2; \ 407 lf_resw=lf_var1w >> lf_var2b; \ 408 save(op1,lf_resw); \ 409 lflags.type=t_SHRw; 410 411 #define SHRD(op1,op2,load,save) \ 412 lf_var1d=load(op1);lf_var2b=op2; \ 413 lf_resd=lf_var1d >> lf_var2b; \ 414 save(op1,lf_resd); \ 415 lflags.type=t_SHRd; 416 417 418 #define SARB(op1,op2,load,save) \ 419 lf_var1b=load(op1);lf_var2b=op2; \ 420 if (lf_var2b>8) lf_var2b=8; \ 421 if (lf_var1b & 0x80) { \ 422 lf_resb=(lf_var1b >> lf_var2b)| \ 423 (0xff << (8 - lf_var2b)); \ 424 } else { \ 425 lf_resb=lf_var1b >> lf_var2b; \ 426 } \ 427 save(op1,lf_resb); \ 428 lflags.type=t_SARb; 429 430 #define SARW(op1,op2,load,save) \ 431 lf_var1w=load(op1);lf_var2b=op2; \ 432 if (lf_var2b>16) lf_var2b=16; \ 433 if (lf_var1w & 0x8000) { \ 434 lf_resw=(lf_var1w >> lf_var2b)| \ 435 (0xffff << (16 - lf_var2b)); \ 436 } else { \ 437 lf_resw=lf_var1w >> lf_var2b; \ 438 } \ 439 save(op1,lf_resw); \ 440 lflags.type=t_SARw; 441 442 #define SARD(op1,op2,load,save) \ 443 lf_var2b=op2;lf_var1d=load(op1); \ 444 if (lf_var1d & 0x80000000) { \ 445 lf_resd=(lf_var1d >> lf_var2b)| \ 446 (0xffffffff << (32 - lf_var2b)); \ 447 } else { \ 448 lf_resd=lf_var1d >> lf_var2b; \ 449 } \ 450 save(op1,lf_resd); \ 451 lflags.type=t_SARd; 452 453 454 455 #define DAA() \ 456 if (((reg_al & 0x0F)>0x09) || get_AF()) { \ 457 if ((reg_al > 0x99) || get_CF()) { \ 458 reg_al+=0x60; \ 459 SETFLAGBIT(CF,true); \ 460 } else { \ 461 SETFLAGBIT(CF,false); \ 462 } \ 463 reg_al+=0x06; \ 464 SETFLAGBIT(AF,true); \ 465 } else { \ 466 if ((reg_al > 0x99) || get_CF()) { \ 467 reg_al+=0x60; \ 468 SETFLAGBIT(CF,true); \ 469 } else { \ 470 SETFLAGBIT(CF,false); \ 471 } \ 472 SETFLAGBIT(AF,false); \ 473 } \ 474 SETFLAGBIT(SF,(reg_al&0x80)); \ 475 SETFLAGBIT(ZF,(reg_al==0)); \ 476 SETFLAGBIT(PF,parity_lookup[reg_al]); \ 477 lflags.type=t_UNKNOWN; 478 479 480 #define DAS() \ 481 { \ 482 Bit8u osigned=reg_al & 0x80; \ 483 if (((reg_al & 0x0f) > 9) || get_AF()) { \ 484 if ((reg_al>0x99) || get_CF()) { \ 485 reg_al-=0x60; \ 486 SETFLAGBIT(CF,true); \ 487 } else { \ 488 SETFLAGBIT(CF,(reg_al<=0x05)); \ 489 } \ 490 reg_al-=6; \ 491 SETFLAGBIT(AF,true); \ 492 } else { \ 493 if ((reg_al>0x99) || get_CF()) { \ 494 reg_al-=0x60; \ 495 SETFLAGBIT(CF,true); \ 496 } else { \ 497 SETFLAGBIT(CF,false); \ 498 } \ 499 SETFLAGBIT(AF,false); \ 500 } \ 501 SETFLAGBIT(OF,osigned && ((reg_al&0x80)==0)); \ 502 SETFLAGBIT(SF,(reg_al&0x80)); \ 503 SETFLAGBIT(ZF,(reg_al==0)); \ 504 SETFLAGBIT(PF,parity_lookup[reg_al]); \ 505 lflags.type=t_UNKNOWN; \ 506 } 507 508 509 #define AAA() \ 510 SETFLAGBIT(SF,((reg_al>=0x7a) && (reg_al<=0xf9))); \ 511 if ((reg_al & 0xf) > 9) { \ 512 SETFLAGBIT(OF,(reg_al&0xf0)==0x70); \ 513 reg_ax += 0x106; \ 514 SETFLAGBIT(CF,true); \ 515 SETFLAGBIT(ZF,(reg_al == 0)); \ 516 SETFLAGBIT(AF,true); \ 517 } else if (get_AF()) { \ 518 reg_ax += 0x106; \ 519 SETFLAGBIT(OF,false); \ 520 SETFLAGBIT(CF,true); \ 521 SETFLAGBIT(ZF,false); \ 522 SETFLAGBIT(AF,true); \ 523 } else { \ 524 SETFLAGBIT(OF,false); \ 525 SETFLAGBIT(CF,false); \ 526 SETFLAGBIT(ZF,(reg_al == 0)); \ 527 SETFLAGBIT(AF,false); \ 528 } \ 529 SETFLAGBIT(PF,parity_lookup[reg_al]); \ 530 reg_al &= 0x0F; \ 531 lflags.type=t_UNKNOWN; 532 533 #define AAS() \ 534 if ((reg_al & 0x0f)>9) { \ 535 SETFLAGBIT(SF,(reg_al>0x85)); \ 536 reg_ax -= 0x106; \ 537 SETFLAGBIT(OF,false); \ 538 SETFLAGBIT(CF,true); \ 539 SETFLAGBIT(AF,true); \ 540 } else if (get_AF()) { \ 541 SETFLAGBIT(OF,((reg_al>=0x80) && (reg_al<=0x85))); \ 542 SETFLAGBIT(SF,(reg_al<0x06) || (reg_al>0x85)); \ 543 reg_ax -= 0x106; \ 544 SETFLAGBIT(CF,true); \ 545 SETFLAGBIT(AF,true); \ 546 } else { \ 547 SETFLAGBIT(SF,(reg_al>=0x80)); \ 548 SETFLAGBIT(OF,false); \ 549 SETFLAGBIT(CF,false); \ 550 SETFLAGBIT(AF,false); \ 551 } \ 552 SETFLAGBIT(ZF,(reg_al == 0)); \ 553 SETFLAGBIT(PF,parity_lookup[reg_al]); \ 554 reg_al &= 0x0F; \ 555 lflags.type=t_UNKNOWN; 556 557 #define AAM(op1) \ 558 { \ 559 Bit8u dv=op1; \ 560 if (dv!=0) { \ 561 reg_ah=reg_al / dv; \ 562 reg_al=reg_al % dv; \ 563 SETFLAGBIT(SF,(reg_al & 0x80)); \ 564 SETFLAGBIT(ZF,(reg_al == 0)); \ 565 SETFLAGBIT(PF,parity_lookup[reg_al]); \ 566 SETFLAGBIT(CF,false); \ 567 SETFLAGBIT(OF,false); \ 568 SETFLAGBIT(AF,false); \ 569 lflags.type=t_UNKNOWN; \ 570 } else EXCEPTION(0); \ 571 } 572 573 574 //Took this from bochs, i seriously hate these weird bcd opcodes 575 #define AAD(op1) \ 576 { \ 577 Bit16u ax1 = reg_ah * op1; \ 578 Bit16u ax2 = ax1 + reg_al; \ 579 reg_al = (Bit8u) ax2; \ 580 reg_ah = 0; \ 581 SETFLAGBIT(CF,false); \ 582 SETFLAGBIT(OF,false); \ 583 SETFLAGBIT(AF,false); \ 584 SETFLAGBIT(SF,reg_al >= 0x80); \ 585 SETFLAGBIT(ZF,reg_al == 0); \ 586 SETFLAGBIT(PF,parity_lookup[reg_al]); \ 587 lflags.type=t_UNKNOWN; \ 588 } 589 590 #define MULB(op1,load,save) \ 591 reg_ax=reg_al*load(op1); \ 592 FillFlagsNoCFOF(); \ 593 SETFLAGBIT(ZF,reg_al == 0); \ 594 if (reg_ax & 0xff00) { \ 595 SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ 596 } else { \ 597 SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ 598 } 599 600 #define MULW(op1, load, save) \ 601 { \ 602 const uint32_t res = static_cast<uint32_t>(reg_ax) * \ 603 static_cast<uint32_t>(load(op1)); \ 604 reg_ax = static_cast<uint16_t>(res); \ 605 reg_dx = static_cast<uint16_t>(res >> 16); \ 606 FillFlagsNoCFOF(); \ 607 SETFLAGBIT(ZF, reg_ax == 0); \ 608 if (reg_dx) { \ 609 SETFLAGBIT(CF, true); \ 610 SETFLAGBIT(OF, true); \ 611 } else { \ 612 SETFLAGBIT(CF, false); \ 613 SETFLAGBIT(OF, false); \ 614 } \ 615 } 616 617 #define MULD(op1, load, save) \ 618 { \ 619 const uint64_t res = static_cast<uint64_t>(reg_eax) * \ 620 static_cast<uint64_t>(load(op1)); \ 621 reg_eax = static_cast<uint32_t>(res); \ 622 reg_edx = static_cast<uint32_t>(res >> 32); \ 623 FillFlagsNoCFOF(); \ 624 SETFLAGBIT(ZF, reg_eax == 0); \ 625 if (reg_edx) { \ 626 SETFLAGBIT(CF, true); \ 627 SETFLAGBIT(OF, true); \ 628 } else { \ 629 SETFLAGBIT(CF, false); \ 630 SETFLAGBIT(OF, false); \ 631 } \ 632 } 633 634 #define DIVB(op1,load,save) \ 635 { \ 636 Bitu val=load(op1); \ 637 if (val==0) EXCEPTION(0); \ 638 Bitu quo=reg_ax / val; \ 639 Bit8u rem=(Bit8u)(reg_ax % val); \ 640 Bit8u quo8=(Bit8u)(quo&0xff); \ 641 if (quo>0xff) EXCEPTION(0); \ 642 reg_ah=rem; \ 643 reg_al=quo8; \ 644 SETFLAGBIT(OF,false); \ 645 } 646 647 648 #define DIVW(op1,load,save) \ 649 { \ 650 Bitu val=load(op1); \ 651 if (val==0) EXCEPTION(0); \ 652 Bitu num=((Bit32u)reg_dx<<16)|reg_ax; \ 653 Bitu quo=num/val; \ 654 Bit16u rem=(Bit16u)(num % val); \ 655 Bit16u quo16=(Bit16u)(quo&0xffff); \ 656 if (quo!=(Bit32u)quo16) EXCEPTION(0); \ 657 reg_dx=rem; \ 658 reg_ax=quo16; \ 659 SETFLAGBIT(OF,false); \ 660 } 661 662 #define DIVD(op1,load,save) \ 663 { \ 664 Bitu val=load(op1); \ 665 if (val==0) EXCEPTION(0); \ 666 Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax; \ 667 Bit64u quo=num/val; \ 668 Bit32u rem=(Bit32u)(num % val); \ 669 Bit32u quo32=(Bit32u)(quo&0xffffffff); \ 670 if (quo!=(Bit64u)quo32) EXCEPTION(0); \ 671 reg_edx=rem; \ 672 reg_eax=quo32; \ 673 SETFLAGBIT(OF,false); \ 674 } 675 676 677 #define IDIVB(op1,load,save) \ 678 { \ 679 Bits val=(Bit8s)(load(op1)); \ 680 if (val==0) EXCEPTION(0); \ 681 Bits quo=((Bit16s)reg_ax) / val; \ 682 Bit8s rem=(Bit8s)((Bit16s)reg_ax % val); \ 683 Bit8s quo8s=(Bit8s)(quo&0xff); \ 684 if (quo!=(Bit16s)quo8s) EXCEPTION(0); \ 685 reg_ah=rem; \ 686 reg_al=quo8s; \ 687 SETFLAGBIT(OF,false); \ 688 } 689 690 #define IDIVW(op1, load, save) \ 691 { \ 692 const auto val = static_cast<int16_t>(load(op1)); \ 693 if (val == 0) \ 694 EXCEPTION(0); \ 695 const auto num = (reg_dx << 16) | reg_ax; \ 696 const auto quo = num / val; \ 697 const auto rem = num % val; \ 698 const auto quo16s = static_cast<int16_t>(quo); \ 699 if (quo != quo16s) \ 700 EXCEPTION(0); \ 701 reg_ax = quo16s; \ 702 reg_dx = static_cast<int16_t>(rem); \ 703 SETFLAGBIT(OF, false); \ 704 } 705 706 #define IDIVD(op1,load,save) \ 707 { \ 708 Bits val=(Bit32s)(load(op1)); \ 709 if (val==0) EXCEPTION(0); \ 710 Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax; \ 711 Bit64s quo=num/val; \ 712 Bit32s rem=(Bit32s)(num % val); \ 713 Bit32s quo32s=(Bit32s)(quo&0xffffffff); \ 714 if (quo!=(Bit64s)quo32s) EXCEPTION(0); \ 715 reg_edx=rem; \ 716 reg_eax=quo32s; \ 717 SETFLAGBIT(OF,false); \ 718 } 719 720 #define IMULB(op1,load,save) \ 721 { \ 722 reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1))); \ 723 FillFlagsNoCFOF(); \ 724 SETFLAGBIT(ZF,reg_al == 0); \ 725 SETFLAGBIT(SF,reg_al & 0x80); \ 726 if ((reg_ax & 0xff80)==0xff80 || \ 727 (reg_ax & 0xff80)==0x0000) { \ 728 SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ 729 } else { \ 730 SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ 731 } \ 732 } 733 734 #define IMULW(op1, load, save) \ 735 { \ 736 const auto res = static_cast<int16_t>(reg_ax) * \ 737 static_cast<int16_t>(load(op1)); \ 738 reg_ax = static_cast<int16_t>(res); \ 739 reg_dx = static_cast<int16_t>(res >> 16); \ 740 FillFlagsNoCFOF(); \ 741 SETFLAGBIT(ZF, reg_ax == 0); \ 742 SETFLAGBIT(SF, reg_ax & 0x8000); \ 743 if (((res & 0xffff8000) == 0xffff8000 || \ 744 (res & 0xffff8000) == 0x0000)) { \ 745 SETFLAGBIT(CF, false); \ 746 SETFLAGBIT(OF, false); \ 747 } else { \ 748 SETFLAGBIT(CF, true); \ 749 SETFLAGBIT(OF, true); \ 750 } \ 751 } 752 753 #define IMULD(op1, load, save) \ 754 { \ 755 Bit64s temps = ((Bit64s)((Bit32s)reg_eax)) * \ 756 ((Bit64s)((Bit32s)(load(op1)))); \ 757 reg_eax = (Bit32s)(temps); \ 758 reg_edx = (Bit32s)(temps >> 32); \ 759 FillFlagsNoCFOF(); \ 760 SETFLAGBIT(ZF, reg_eax == 0); \ 761 SETFLAGBIT(SF, reg_eax & 0x80000000); \ 762 if ((reg_edx == 0xffffffff) && (reg_eax & 0x80000000)) { \ 763 SETFLAGBIT(CF, false); \ 764 SETFLAGBIT(OF, false); \ 765 } else if ((reg_edx == 0x00000000) && (reg_eax < 0x80000000)) { \ 766 SETFLAGBIT(CF, false); \ 767 SETFLAGBIT(OF, false); \ 768 } else { \ 769 SETFLAGBIT(CF, true); \ 770 SETFLAGBIT(OF, true); \ 771 } \ 772 } 773 774 #define DIMULW(op1, op2, op3, load, save) \ 775 { \ 776 const auto res = op2 * op3; \ 777 save(op1, res & 0xffff); \ 778 FillFlagsNoCFOF(); \ 779 if ((res >= -32768) && (res <= 32767)) { \ 780 SETFLAGBIT(CF, false); \ 781 SETFLAGBIT(OF, false); \ 782 } else { \ 783 SETFLAGBIT(CF, true); \ 784 SETFLAGBIT(OF, true); \ 785 } \ 786 } 787 788 #define DIMULD(op1, op2, op3, load, save) \ 789 { \ 790 const auto res = static_cast<int64_t>(op2) * \ 791 static_cast<int64_t>(op3); \ 792 save(op1, (Bit32s)res); \ 793 FillFlagsNoCFOF(); \ 794 if ((res >= -((Bit64s)(2147483647) + 1)) && \ 795 (res <= (Bit64s)2147483647)) { \ 796 SETFLAGBIT(CF, false); \ 797 SETFLAGBIT(OF, false); \ 798 } else { \ 799 SETFLAGBIT(CF, true); \ 800 SETFLAGBIT(OF, true); \ 801 } \ 802 } 803 804 #define GRP2B(blah) \ 805 { \ 806 GetRM;Bitu which=(rm>>3)&7; \ 807 if (rm >= 0xc0) { \ 808 GetEArb; \ 809 Bit8u val=blah & 0x1f; \ 810 if (!val) break; \ 811 switch (which) { \ 812 case 0x00:ROLB(*earb,val,LoadRb,SaveRb);break; \ 813 case 0x01:RORB(*earb,val,LoadRb,SaveRb);break; \ 814 case 0x02:RCLB(*earb,val,LoadRb,SaveRb);break; \ 815 case 0x03:RCRB(*earb,val,LoadRb,SaveRb);break; \ 816 case 0x04:/* SHL and SAL are the same */ \ 817 case 0x06:SHLB(*earb,val,LoadRb,SaveRb);break; \ 818 case 0x05:SHRB(*earb,val,LoadRb,SaveRb);break; \ 819 case 0x07:SARB(*earb,val,LoadRb,SaveRb);break; \ 820 } \ 821 } else { \ 822 GetEAa; \ 823 Bit8u val=blah & 0x1f; \ 824 if (!val) break; \ 825 switch (which) { \ 826 case 0x00:ROLB(eaa,val,LoadMb,SaveMb);break; \ 827 case 0x01:RORB(eaa,val,LoadMb,SaveMb);break; \ 828 case 0x02:RCLB(eaa,val,LoadMb,SaveMb);break; \ 829 case 0x03:RCRB(eaa,val,LoadMb,SaveMb);break; \ 830 case 0x04:/* SHL and SAL are the same */ \ 831 case 0x06:SHLB(eaa,val,LoadMb,SaveMb);break; \ 832 case 0x05:SHRB(eaa,val,LoadMb,SaveMb);break; \ 833 case 0x07:SARB(eaa,val,LoadMb,SaveMb);break; \ 834 } \ 835 } \ 836 } 837 838 839 840 #define GRP2W(blah) \ 841 { \ 842 GetRM;Bitu which=(rm>>3)&7; \ 843 if (rm >= 0xc0) { \ 844 GetEArw; \ 845 Bit8u val=blah & 0x1f; \ 846 if (!val) break; \ 847 switch (which) { \ 848 case 0x00:ROLW(*earw,val,LoadRw,SaveRw);break; \ 849 case 0x01:RORW(*earw,val,LoadRw,SaveRw);break; \ 850 case 0x02:RCLW(*earw,val,LoadRw,SaveRw);break; \ 851 case 0x03:RCRW(*earw,val,LoadRw,SaveRw);break; \ 852 case 0x04:/* SHL and SAL are the same */ \ 853 case 0x06:SHLW(*earw,val,LoadRw,SaveRw);break; \ 854 case 0x05:SHRW(*earw,val,LoadRw,SaveRw);break; \ 855 case 0x07:SARW(*earw,val,LoadRw,SaveRw);break; \ 856 } \ 857 } else { \ 858 GetEAa; \ 859 Bit8u val=blah & 0x1f; \ 860 if (!val) break; \ 861 switch (which) { \ 862 case 0x00:ROLW(eaa,val,LoadMw,SaveMw);break; \ 863 case 0x01:RORW(eaa,val,LoadMw,SaveMw);break; \ 864 case 0x02:RCLW(eaa,val,LoadMw,SaveMw);break; \ 865 case 0x03:RCRW(eaa,val,LoadMw,SaveMw);break; \ 866 case 0x04:/* SHL and SAL are the same */ \ 867 case 0x06:SHLW(eaa,val,LoadMw,SaveMw);break; \ 868 case 0x05:SHRW(eaa,val,LoadMw,SaveMw);break; \ 869 case 0x07:SARW(eaa,val,LoadMw,SaveMw);break; \ 870 } \ 871 } \ 872 } 873 874 875 #define GRP2D(blah) \ 876 { \ 877 GetRM;Bitu which=(rm>>3)&7; \ 878 if (rm >= 0xc0) { \ 879 GetEArd; \ 880 Bit8u val=blah & 0x1f; \ 881 if (!val) break; \ 882 switch (which) { \ 883 case 0x00:ROLD(*eard,val,LoadRd,SaveRd);break; \ 884 case 0x01:RORD(*eard,val,LoadRd,SaveRd);break; \ 885 case 0x02:RCLD(*eard,val,LoadRd,SaveRd);break; \ 886 case 0x03:RCRD(*eard,val,LoadRd,SaveRd);break; \ 887 case 0x04:/* SHL and SAL are the same */ \ 888 case 0x06:SHLD(*eard,val,LoadRd,SaveRd);break; \ 889 case 0x05:SHRD(*eard,val,LoadRd,SaveRd);break; \ 890 case 0x07:SARD(*eard,val,LoadRd,SaveRd);break; \ 891 } \ 892 } else { \ 893 GetEAa; \ 894 Bit8u val=blah & 0x1f; \ 895 if (!val) break; \ 896 switch (which) { \ 897 case 0x00:ROLD(eaa,val,LoadMd,SaveMd);break; \ 898 case 0x01:RORD(eaa,val,LoadMd,SaveMd);break; \ 899 case 0x02:RCLD(eaa,val,LoadMd,SaveMd);break; \ 900 case 0x03:RCRD(eaa,val,LoadMd,SaveMd);break; \ 901 case 0x04:/* SHL and SAL are the same */ \ 902 case 0x06:SHLD(eaa,val,LoadMd,SaveMd);break; \ 903 case 0x05:SHRD(eaa,val,LoadMd,SaveMd);break; \ 904 case 0x07:SARD(eaa,val,LoadMd,SaveMd);break; \ 905 } \ 906 } \ 907 } 908 909 /* let's hope bochs has it correct with the higher than 16 shifts */ 910 /* double-precision shift left has low bits in second argument */ 911 #define DSHLW(op1,op2,op3,load,save) \ 912 Bit8u val=op3 & 0x1F; \ 913 if (!val) break; \ 914 lf_var2b=val;lf_var1d=(load(op1)<<16)|op2; \ 915 Bit32u tempd=lf_var1d << lf_var2b; \ 916 if (lf_var2b>16) tempd |= (op2 << (lf_var2b - 16)); \ 917 lf_resw=(Bit16u)(tempd >> 16); \ 918 save(op1,lf_resw); \ 919 lflags.type=t_DSHLw; 920 921 #define DSHLD(op1,op2,op3,load,save) \ 922 Bit8u val=op3 & 0x1F; \ 923 if (!val) break; \ 924 lf_var2b=val;lf_var1d=load(op1); \ 925 lf_resd=(lf_var1d << lf_var2b) | (op2 >> (32-lf_var2b)); \ 926 save(op1,lf_resd); \ 927 lflags.type=t_DSHLd; 928 929 /* double-precision shift right has high bits in second argument */ 930 #define DSHRW(op1,op2,op3,load,save) \ 931 Bit8u val=op3 & 0x1F; \ 932 if (!val) break; \ 933 lf_var2b=val;lf_var1d=(op2<<16)|load(op1); \ 934 Bit32u tempd=lf_var1d >> lf_var2b; \ 935 if (lf_var2b>16) tempd |= (op2 << (32-lf_var2b )); \ 936 lf_resw=(Bit16u)(tempd); \ 937 save(op1,lf_resw); \ 938 lflags.type=t_DSHRw; 939 940 #define DSHRD(op1,op2,op3,load,save) \ 941 Bit8u val=op3 & 0x1F; \ 942 if (!val) break; \ 943 lf_var2b=val;lf_var1d=load(op1); \ 944 lf_resd=(lf_var1d >> lf_var2b) | (op2 << (32-lf_var2b)); \ 945 save(op1,lf_resd); \ 946 lflags.type=t_DSHRd; 947 948 #define BSWAPW(op1) \ 949 op1 = 0; 950 951 #define BSWAPD(op1) \ 952 op1 = (op1>>24)|((op1>>8)&0xFF00)|((op1<<8)&0xFF0000)|((op1<<24)&0xFF000000); 953