Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between the ADC and ADCX instructions on ia32/ia64?

Tags:

x86

assembly

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:

  • it is only supported in modern CPUs
  • instruction encoding takes more space (4 bytes versus 1 for ADC)

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.

like image 293
John Källén Avatar asked Apr 20 '15 12:04

John Källén


1 Answers

These instructions are used to speed up large integer arithmetic.

Before these instructions adding large numbers often resulted in a code-sequence that looked like this:

  add  
  adc  
  adc  
  adc  
  adc  

The important part here to note is, that if the result of an addition would not fit into a machine word, the carry flag gets set and is 'carried over' to the next higher machine word. All these instructions depend on each other because they take the previous addition carry flag into account and generate a new carry flag value after execution.

Since x86 processors are capable to execute several instructions at once this became a huge bottleneck. The dependency chain just made it impossible for the processor to execute any of the arithmetic in parallel. (to be correct in practice you'll find a loads and stores between the add/adc sequences, but the performance was still limited by the carry dependency).

To improve upon this Intel added a second carry chain by reinterpreting the overflow flag.

The adc instruction got two news variants: adcx and adox

adcx is the same as adc, except that it does not modify the OF (overflow) flag anymore.

adox is the same as adc, but it stores the carry information in the OF flag. It also does not modify the carry-flag anymore.

As you can see the two new adc variants don't influence each other with regards to the flag usage. This allows you to run two long integer additions in parallel by interleaving the instructions and use adcx for one sequence and adox for the other sequence.

like image 157
Nils Pipenbrinck Avatar answered Sep 28 '22 05:09

Nils Pipenbrinck