InstEmitIntegerArithmetic.cs
1 using Ryujinx.Graphics.Shader.Decoders; 2 using Ryujinx.Graphics.Shader.IntermediateRepresentation; 3 using Ryujinx.Graphics.Shader.Translation; 4 5 using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; 6 using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; 7 using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; 8 9 namespace Ryujinx.Graphics.Shader.Instructions 10 { 11 static partial class InstEmit 12 { 13 public static void IaddR(EmitterContext context) 14 { 15 InstIaddR op = context.GetOp<InstIaddR>(); 16 17 var srcA = GetSrcReg(context, op.SrcA); 18 var srcB = GetSrcReg(context, op.SrcB); 19 20 EmitIadd(context, srcA, srcB, op.Dest, op.AvgMode, op.X, op.WriteCC); 21 } 22 23 public static void IaddI(EmitterContext context) 24 { 25 InstIaddI op = context.GetOp<InstIaddI>(); 26 27 var srcA = GetSrcReg(context, op.SrcA); 28 var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); 29 30 EmitIadd(context, srcA, srcB, op.Dest, op.AvgMode, op.X, op.WriteCC); 31 } 32 33 public static void IaddC(EmitterContext context) 34 { 35 InstIaddC op = context.GetOp<InstIaddC>(); 36 37 var srcA = GetSrcReg(context, op.SrcA); 38 var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); 39 40 EmitIadd(context, srcA, srcB, op.Dest, op.AvgMode, op.X, op.WriteCC); 41 } 42 43 public static void Iadd32i(EmitterContext context) 44 { 45 InstIadd32i op = context.GetOp<InstIadd32i>(); 46 47 var srcA = GetSrcReg(context, op.SrcA); 48 var srcB = GetSrcImm(context, op.Imm32); 49 50 EmitIadd(context, srcA, srcB, op.Dest, op.AvgMode, op.X, op.WriteCC); 51 } 52 53 public static void Iadd3R(EmitterContext context) 54 { 55 InstIadd3R op = context.GetOp<InstIadd3R>(); 56 57 var srcA = GetSrcReg(context, op.SrcA); 58 var srcB = GetSrcReg(context, op.SrcB); 59 var srcC = GetSrcReg(context, op.SrcC); 60 61 EmitIadd3(context, op.Lrs, srcA, srcB, srcC, op.Apart, op.Bpart, op.Cpart, op.Dest, op.NegA, op.NegB, op.NegC); 62 } 63 64 public static void Iadd3I(EmitterContext context) 65 { 66 InstIadd3I op = context.GetOp<InstIadd3I>(); 67 68 var srcA = GetSrcReg(context, op.SrcA); 69 var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); 70 var srcC = GetSrcReg(context, op.SrcC); 71 72 EmitIadd3(context, Lrs.None, srcA, srcB, srcC, HalfSelect.B32, HalfSelect.B32, HalfSelect.B32, op.Dest, op.NegA, op.NegB, op.NegC); 73 } 74 75 public static void Iadd3C(EmitterContext context) 76 { 77 InstIadd3C op = context.GetOp<InstIadd3C>(); 78 79 var srcA = GetSrcReg(context, op.SrcA); 80 var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); 81 var srcC = GetSrcReg(context, op.SrcC); 82 83 EmitIadd3(context, Lrs.None, srcA, srcB, srcC, HalfSelect.B32, HalfSelect.B32, HalfSelect.B32, op.Dest, op.NegA, op.NegB, op.NegC); 84 } 85 86 public static void ImadR(EmitterContext context) 87 { 88 InstImadR op = context.GetOp<InstImadR>(); 89 90 var srcA = GetSrcReg(context, op.SrcA); 91 var srcB = GetSrcReg(context, op.SrcB); 92 var srcC = GetSrcReg(context, op.SrcC); 93 94 EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); 95 } 96 97 public static void ImadI(EmitterContext context) 98 { 99 InstImadI op = context.GetOp<InstImadI>(); 100 101 var srcA = GetSrcReg(context, op.SrcA); 102 var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); 103 var srcC = GetSrcReg(context, op.SrcC); 104 105 EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); 106 } 107 108 public static void ImadC(EmitterContext context) 109 { 110 InstImadC op = context.GetOp<InstImadC>(); 111 112 var srcA = GetSrcReg(context, op.SrcA); 113 var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); 114 var srcC = GetSrcReg(context, op.SrcC); 115 116 EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); 117 } 118 119 public static void ImadRc(EmitterContext context) 120 { 121 InstImadRc op = context.GetOp<InstImadRc>(); 122 123 var srcA = GetSrcReg(context, op.SrcA); 124 var srcB = GetSrcReg(context, op.SrcC); 125 var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); 126 127 EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); 128 } 129 130 public static void Imad32i(EmitterContext context) 131 { 132 InstImad32i op = context.GetOp<InstImad32i>(); 133 134 var srcA = GetSrcReg(context, op.SrcA); 135 var srcB = GetSrcImm(context, op.Imm32); 136 var srcC = GetSrcReg(context, op.Dest); 137 138 EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); 139 } 140 141 public static void ImulR(EmitterContext context) 142 { 143 InstImulR op = context.GetOp<InstImulR>(); 144 145 var srcA = GetSrcReg(context, op.SrcA); 146 var srcB = GetSrcReg(context, op.SrcB); 147 148 EmitImad(context, srcA, srcB, Const(0), op.Dest, AvgMode.NoNeg, op.ASigned, op.BSigned, op.Hilo); 149 } 150 151 public static void ImulI(EmitterContext context) 152 { 153 InstImulI op = context.GetOp<InstImulI>(); 154 155 var srcA = GetSrcReg(context, op.SrcA); 156 var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); 157 158 EmitImad(context, srcA, srcB, Const(0), op.Dest, AvgMode.NoNeg, op.ASigned, op.BSigned, op.Hilo); 159 } 160 161 public static void ImulC(EmitterContext context) 162 { 163 InstImulC op = context.GetOp<InstImulC>(); 164 165 var srcA = GetSrcReg(context, op.SrcA); 166 var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); 167 168 EmitImad(context, srcA, srcB, Const(0), op.Dest, AvgMode.NoNeg, op.ASigned, op.BSigned, op.Hilo); 169 } 170 171 public static void Imul32i(EmitterContext context) 172 { 173 InstImul32i op = context.GetOp<InstImul32i>(); 174 175 var srcA = GetSrcReg(context, op.SrcA); 176 var srcB = GetSrcImm(context, op.Imm32); 177 178 EmitImad(context, srcA, srcB, Const(0), op.Dest, AvgMode.NoNeg, op.ASigned, op.BSigned, op.Hilo); 179 } 180 181 public static void IscaddR(EmitterContext context) 182 { 183 InstIscaddR op = context.GetOp<InstIscaddR>(); 184 185 var srcA = GetSrcReg(context, op.SrcA); 186 var srcB = GetSrcReg(context, op.SrcB); 187 188 EmitIscadd(context, srcA, srcB, op.Dest, op.Imm5, op.AvgMode, op.WriteCC); 189 } 190 191 public static void IscaddI(EmitterContext context) 192 { 193 InstIscaddI op = context.GetOp<InstIscaddI>(); 194 195 var srcA = GetSrcReg(context, op.SrcA); 196 var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); 197 198 EmitIscadd(context, srcA, srcB, op.Dest, op.Imm5, op.AvgMode, op.WriteCC); 199 } 200 201 public static void IscaddC(EmitterContext context) 202 { 203 InstIscaddC op = context.GetOp<InstIscaddC>(); 204 205 var srcA = GetSrcReg(context, op.SrcA); 206 var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); 207 208 EmitIscadd(context, srcA, srcB, op.Dest, op.Imm5, op.AvgMode, op.WriteCC); 209 } 210 211 public static void Iscadd32i(EmitterContext context) 212 { 213 InstIscadd32i op = context.GetOp<InstIscadd32i>(); 214 215 var srcA = GetSrcReg(context, op.SrcA); 216 var srcB = GetSrcImm(context, op.Imm32); 217 218 EmitIscadd(context, srcA, srcB, op.Dest, op.Imm5, AvgMode.NoNeg, op.WriteCC); 219 } 220 221 public static void LeaR(EmitterContext context) 222 { 223 InstLeaR op = context.GetOp<InstLeaR>(); 224 225 var srcA = GetSrcReg(context, op.SrcA); 226 var srcB = GetSrcReg(context, op.SrcB); 227 228 EmitLea(context, srcA, srcB, op.Dest, op.NegA, op.ImmU5); 229 } 230 231 public static void LeaI(EmitterContext context) 232 { 233 InstLeaI op = context.GetOp<InstLeaI>(); 234 235 var srcA = GetSrcReg(context, op.SrcA); 236 var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); 237 238 EmitLea(context, srcA, srcB, op.Dest, op.NegA, op.ImmU5); 239 } 240 241 public static void LeaC(EmitterContext context) 242 { 243 InstLeaC op = context.GetOp<InstLeaC>(); 244 245 var srcA = GetSrcReg(context, op.SrcA); 246 var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); 247 248 EmitLea(context, srcA, srcB, op.Dest, op.NegA, op.ImmU5); 249 } 250 251 public static void LeaHiR(EmitterContext context) 252 { 253 InstLeaHiR op = context.GetOp<InstLeaHiR>(); 254 255 var srcA = GetSrcReg(context, op.SrcA); 256 var srcB = GetSrcReg(context, op.SrcB); 257 var srcC = GetSrcReg(context, op.SrcC); 258 259 EmitLeaHi(context, srcA, srcB, srcC, op.Dest, op.NegA, op.ImmU5); 260 } 261 262 public static void LeaHiC(EmitterContext context) 263 { 264 InstLeaHiC op = context.GetOp<InstLeaHiC>(); 265 266 var srcA = GetSrcReg(context, op.SrcA); 267 var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); 268 var srcC = GetSrcReg(context, op.SrcC); 269 270 EmitLeaHi(context, srcA, srcB, srcC, op.Dest, op.NegA, op.ImmU5); 271 } 272 273 public static void XmadR(EmitterContext context) 274 { 275 InstXmadR op = context.GetOp<InstXmadR>(); 276 277 var srcA = GetSrcReg(context, op.SrcA); 278 var srcB = GetSrcReg(context, op.SrcB); 279 var srcC = GetSrcReg(context, op.SrcC); 280 281 EmitXmad(context, op.XmadCop, srcA, srcB, srcC, op.Dest, op.ASigned, op.BSigned, op.HiloA, op.HiloB, op.Psl, op.Mrg, op.X, op.WriteCC); 282 } 283 284 public static void XmadI(EmitterContext context) 285 { 286 InstXmadI op = context.GetOp<InstXmadI>(); 287 288 var srcA = GetSrcReg(context, op.SrcA); 289 var srcB = GetSrcImm(context, op.Imm16); 290 var srcC = GetSrcReg(context, op.SrcC); 291 292 EmitXmad(context, op.XmadCop, srcA, srcB, srcC, op.Dest, op.ASigned, op.BSigned, op.HiloA, false, op.Psl, op.Mrg, op.X, op.WriteCC); 293 } 294 295 public static void XmadC(EmitterContext context) 296 { 297 InstXmadC op = context.GetOp<InstXmadC>(); 298 299 var srcA = GetSrcReg(context, op.SrcA); 300 var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); 301 var srcC = GetSrcReg(context, op.SrcC); 302 303 EmitXmad(context, op.XmadCop, srcA, srcB, srcC, op.Dest, op.ASigned, op.BSigned, op.HiloA, op.HiloB, op.Psl, op.Mrg, op.X, op.WriteCC); 304 } 305 306 public static void XmadRc(EmitterContext context) 307 { 308 InstXmadRc op = context.GetOp<InstXmadRc>(); 309 310 var srcA = GetSrcReg(context, op.SrcA); 311 var srcB = GetSrcReg(context, op.SrcC); 312 var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); 313 314 EmitXmad(context, op.XmadCop, srcA, srcB, srcC, op.Dest, op.ASigned, op.BSigned, op.HiloA, op.HiloB, false, false, op.X, op.WriteCC); 315 } 316 317 private static void EmitIadd( 318 EmitterContext context, 319 Operand srcA, 320 Operand srcB, 321 int rd, 322 AvgMode avgMode, 323 bool extended, 324 bool writeCC) 325 { 326 srcA = context.INegate(srcA, avgMode == AvgMode.NegA); 327 srcB = context.INegate(srcB, avgMode == AvgMode.NegB); 328 329 Operand res = context.IAdd(srcA, srcB); 330 331 if (extended) 332 { 333 res = context.IAdd(res, context.BitwiseAnd(GetCF(), Const(1))); 334 } 335 336 SetIaddFlags(context, res, srcA, srcB, writeCC, extended); 337 338 // TODO: SAT. 339 340 context.Copy(GetDest(rd), res); 341 } 342 343 private static void EmitIadd3( 344 EmitterContext context, 345 Lrs mode, 346 Operand srcA, 347 Operand srcB, 348 Operand srcC, 349 HalfSelect partA, 350 HalfSelect partB, 351 HalfSelect partC, 352 int rd, 353 bool negateA, 354 bool negateB, 355 bool negateC) 356 { 357 Operand Extend(Operand src, HalfSelect part) 358 { 359 if (part == HalfSelect.B32) 360 { 361 return src; 362 } 363 364 if (part == HalfSelect.H0) 365 { 366 return context.BitwiseAnd(src, Const(0xffff)); 367 } 368 else if (part == HalfSelect.H1) 369 { 370 return context.ShiftRightU32(src, Const(16)); 371 } 372 else 373 { 374 context.TranslatorContext.GpuAccessor.Log($"Iadd3 has invalid component selection {part}."); 375 } 376 377 return src; 378 } 379 380 srcA = context.INegate(Extend(srcA, partA), negateA); 381 srcB = context.INegate(Extend(srcB, partB), negateB); 382 srcC = context.INegate(Extend(srcC, partC), negateC); 383 384 Operand res = context.IAdd(srcA, srcB); 385 386 if (mode != Lrs.None) 387 { 388 if (mode == Lrs.LeftShift) 389 { 390 res = context.ShiftLeft(res, Const(16)); 391 } 392 else if (mode == Lrs.RightShift) 393 { 394 res = context.ShiftRightU32(res, Const(16)); 395 } 396 else 397 { 398 // TODO: Warning. 399 } 400 } 401 402 res = context.IAdd(res, srcC); 403 404 context.Copy(GetDest(rd), res); 405 406 // TODO: CC, X, corner cases. 407 } 408 409 private static void EmitImad( 410 EmitterContext context, 411 Operand srcA, 412 Operand srcB, 413 Operand srcC, 414 int rd, 415 AvgMode avgMode, 416 bool signedA, 417 bool signedB, 418 bool high) 419 { 420 srcB = context.INegate(srcB, avgMode == AvgMode.NegA); 421 srcC = context.INegate(srcC, avgMode == AvgMode.NegB); 422 423 Operand res; 424 425 if (high) 426 { 427 if (signedA && signedB) 428 { 429 res = context.MultiplyHighS32(srcA, srcB); 430 } 431 else 432 { 433 res = context.MultiplyHighU32(srcA, srcB); 434 435 if (signedA) 436 { 437 res = context.IAdd(res, context.IMultiply(srcB, context.ShiftRightS32(srcA, Const(31)))); 438 } 439 else if (signedB) 440 { 441 res = context.IAdd(res, context.IMultiply(srcA, context.ShiftRightS32(srcB, Const(31)))); 442 } 443 } 444 } 445 else 446 { 447 res = context.IMultiply(srcA, srcB); 448 } 449 450 if (srcC.Type != OperandType.Constant || srcC.Value != 0) 451 { 452 res = context.IAdd(res, srcC); 453 } 454 455 // TODO: CC, X, SAT, and more? 456 457 context.Copy(GetDest(rd), res); 458 } 459 460 private static void EmitIscadd( 461 EmitterContext context, 462 Operand srcA, 463 Operand srcB, 464 int rd, 465 int shift, 466 AvgMode avgMode, 467 bool writeCC) 468 { 469 srcA = context.ShiftLeft(srcA, Const(shift)); 470 471 srcA = context.INegate(srcA, avgMode == AvgMode.NegA); 472 srcB = context.INegate(srcB, avgMode == AvgMode.NegB); 473 474 Operand res = context.IAdd(srcA, srcB); 475 476 SetIaddFlags(context, res, srcA, srcB, writeCC, false); 477 478 context.Copy(GetDest(rd), res); 479 } 480 481 public static void EmitLea(EmitterContext context, Operand srcA, Operand srcB, int rd, bool negateA, int shift) 482 { 483 srcA = context.ShiftLeft(srcA, Const(shift)); 484 srcA = context.INegate(srcA, negateA); 485 486 Operand res = context.IAdd(srcA, srcB); 487 488 context.Copy(GetDest(rd), res); 489 490 // TODO: CC, X. 491 } 492 493 private static void EmitLeaHi( 494 EmitterContext context, 495 Operand srcA, 496 Operand srcB, 497 Operand srcC, 498 int rd, 499 bool negateA, 500 int shift) 501 { 502 Operand aLow = context.ShiftLeft(srcA, Const(shift)); 503 Operand aHigh = shift == 0 ? Const(0) : context.ShiftRightU32(srcA, Const(32 - shift)); 504 aHigh = context.BitwiseOr(aHigh, context.ShiftLeft(srcC, Const(shift))); 505 506 if (negateA) 507 { 508 // Perform 64-bit negation by doing bitwise not of the value, 509 // then adding 1 and carrying over from low to high. 510 aLow = context.BitwiseNot(aLow); 511 aHigh = context.BitwiseNot(aHigh); 512 513 #pragma warning disable IDE0059 // Remove unnecessary value assignment 514 aLow = AddWithCarry(context, aLow, Const(1), out Operand aLowCOut); 515 #pragma warning restore IDE0059 516 aHigh = context.IAdd(aHigh, aLowCOut); 517 } 518 519 Operand res = context.IAdd(aHigh, srcB); 520 521 context.Copy(GetDest(rd), res); 522 523 // TODO: CC, X. 524 } 525 526 public static void EmitXmad( 527 EmitterContext context, 528 XmadCop2 mode, 529 Operand srcA, 530 Operand srcB, 531 Operand srcC, 532 int rd, 533 bool signedA, 534 bool signedB, 535 bool highA, 536 bool highB, 537 bool productShiftLeft, 538 bool merge, 539 bool extended, 540 bool writeCC) 541 { 542 XmadCop modeConv; 543 switch (mode) 544 { 545 case XmadCop2.Cfull: 546 modeConv = XmadCop.Cfull; 547 break; 548 case XmadCop2.Clo: 549 modeConv = XmadCop.Clo; 550 break; 551 case XmadCop2.Chi: 552 modeConv = XmadCop.Chi; 553 break; 554 case XmadCop2.Csfu: 555 modeConv = XmadCop.Csfu; 556 break; 557 default: 558 context.TranslatorContext.GpuAccessor.Log($"Invalid XMAD mode \"{mode}\"."); 559 return; 560 } 561 562 EmitXmad(context, modeConv, srcA, srcB, srcC, rd, signedA, signedB, highA, highB, productShiftLeft, merge, extended, writeCC); 563 } 564 565 public static void EmitXmad( 566 EmitterContext context, 567 XmadCop mode, 568 Operand srcA, 569 Operand srcB, 570 Operand srcC, 571 int rd, 572 bool signedA, 573 bool signedB, 574 bool highA, 575 bool highB, 576 bool productShiftLeft, 577 bool merge, 578 bool extended, 579 bool writeCC) 580 { 581 var srcBUnmodified = srcB; 582 583 Operand Extend16To32(Operand src, bool high, bool signed) 584 { 585 if (signed && high) 586 { 587 return context.ShiftRightS32(src, Const(16)); 588 } 589 else if (signed) 590 { 591 return context.BitfieldExtractS32(src, Const(0), Const(16)); 592 } 593 else if (high) 594 { 595 return context.ShiftRightU32(src, Const(16)); 596 } 597 else 598 { 599 return context.BitwiseAnd(src, Const(0xffff)); 600 } 601 } 602 603 srcA = Extend16To32(srcA, highA, signedA); 604 srcB = Extend16To32(srcB, highB, signedB); 605 606 Operand res = context.IMultiply(srcA, srcB); 607 608 if (productShiftLeft) 609 { 610 res = context.ShiftLeft(res, Const(16)); 611 } 612 613 switch (mode) 614 { 615 case XmadCop.Cfull: 616 break; 617 618 case XmadCop.Clo: 619 srcC = Extend16To32(srcC, high: false, signed: false); 620 break; 621 case XmadCop.Chi: 622 srcC = Extend16To32(srcC, high: true, signed: false); 623 break; 624 625 case XmadCop.Cbcc: 626 srcC = context.IAdd(srcC, context.ShiftLeft(srcBUnmodified, Const(16))); 627 break; 628 629 case XmadCop.Csfu: 630 Operand signAdjustA = context.ShiftLeft(context.ShiftRightU32(srcA, Const(31)), Const(16)); 631 Operand signAdjustB = context.ShiftLeft(context.ShiftRightU32(srcB, Const(31)), Const(16)); 632 633 srcC = context.ISubtract(srcC, context.IAdd(signAdjustA, signAdjustB)); 634 break; 635 636 default: 637 context.TranslatorContext.GpuAccessor.Log($"Invalid XMAD mode \"{mode}\"."); 638 return; 639 } 640 641 Operand product = res; 642 643 if (extended) 644 { 645 // Add with carry. 646 res = context.IAdd(res, context.BitwiseAnd(GetCF(), Const(1))); 647 } 648 else 649 { 650 // Add (no carry in). 651 res = context.IAdd(res, srcC); 652 } 653 654 SetIaddFlags(context, res, product, srcC, writeCC, extended); 655 656 if (merge) 657 { 658 res = context.BitwiseAnd(res, Const(0xffff)); 659 res = context.BitwiseOr(res, context.ShiftLeft(srcBUnmodified, Const(16))); 660 } 661 662 context.Copy(GetDest(rd), res); 663 } 664 665 private static void SetIaddFlags(EmitterContext context, Operand res, Operand srcA, Operand srcB, bool setCC, bool extended) 666 { 667 if (!setCC) 668 { 669 return; 670 } 671 672 if (extended) 673 { 674 // C = (d == a && CIn) || d < a 675 Operand tempC0 = context.ICompareEqual(res, srcA); 676 Operand tempC1 = context.ICompareLessUnsigned(res, srcA); 677 678 tempC0 = context.BitwiseAnd(tempC0, GetCF()); 679 680 context.Copy(GetCF(), context.BitwiseOr(tempC0, tempC1)); 681 } 682 else 683 { 684 // C = d < a 685 context.Copy(GetCF(), context.ICompareLessUnsigned(res, srcA)); 686 } 687 688 // V = (d ^ a) & ~(a ^ b) < 0 689 Operand tempV0 = context.BitwiseExclusiveOr(res, srcA); 690 Operand tempV1 = context.BitwiseExclusiveOr(srcA, srcB); 691 692 tempV1 = context.BitwiseNot(tempV1); 693 694 Operand tempV = context.BitwiseAnd(tempV0, tempV1); 695 696 context.Copy(GetVF(), context.ICompareLess(tempV, Const(0))); 697 698 SetZnFlags(context, res, setCC: true, extended: extended); 699 } 700 } 701 }