assemblyx86bigintegerbigintadx

What is the difference between the ADC and ADCX instructions on x86?


I was looking through the Intel software developer manual when I encountered the ADCX instruction, which was previously unknown to me; its encoding is 66 0F 38 F6. It seems to be almost identical to the ADC instruction, so why would you use ADCX when:

Is there some other side effect, or special case, where ADCX proves advantageous over ADC? There must have been some good reason why this was added to the instruction repertoire.


Solution

  • To quote from the paper New Instructions Support Large Integer Arithmetic by Intel:

    The adcx and adox instructions are extensions of the adc instruction, designed to support two separate carry chains. They are defined as:

    adcx dest/src1, src2
    adox dest/src1, src2
    

    Both instructions compute the sum of src1 and src2 plus a carry-in and generate an output sum dest and a carry-out. The difference between these two instructions is that adcx uses the CF flag for the carry in and carry out (leaving the OF flag unchanged), whereas the adox instruction uses the OF flag for the carry in and carry out (leaving the CF flag unchanged).

    The primary advantage of these instructions over adc is that they support two independent carry chains.

    The paper shows examples of using it in combination with BMI2 mulx (no-flags widening multiply) for 512-bit BigInt multiply to handle the partial products being generated.

    Part of the benefit is not just parallel dependency chains for out-of-order exec, it's being able to use results closer to where they're generated so you don't run out of registers (or need extra mov instructions) to save them for adding later. Or without ADX instructions, sometimes their examples will terminate a chain of add/adc early with adc reg, 0, to pick it back up later after doing a different add.