0

I need a concise way to express the x86 Overflow Flag as a function of the two operands. I understand that the core sets OF when both operands have the same sign but the result has a different sign.

For example,

ADD SRC[31..0], DEST[31..0]

Can OF be reasonably expressed as a "one-liner" boolean function of the bits of SRC and DEST?

srking
  • 4,512
  • 1
  • 30
  • 46
  • Answered previously [here](http://stackoverflow.com/a/8037485/968261), you may also be interested in [this](http://stackoverflow.com/a/8061989/968261). – Alexey Frunze Jun 29 '12 at 00:08

2 Answers2

2

As the overflow flag is the xor of the carry out of the sign bit with the carry in to the sign bit, it could be expressed as:

((SRC[31..0] + DEST[31..0]) shr 32) xor ((SRC[30..0] + DEST[30..0]) shr 31)
Jens Björnhager
  • 5,632
  • 3
  • 27
  • 47
  • Perhaps I shouldn't have upvoted this answer since the text is correct, but the code is not. You can't determine carries from the sum (or logical AND) of just a pair of individual bits. You're loosing carry-ins that way. The correct implementation is [here](http://stackoverflow.com/a/8037485/968261). – Alexey Frunze Jun 29 '12 at 00:13
  • @Alexey Frunze Yes, I realize that my expression doesn't take the lower bits into account. I will revise my answer. – Jens Björnhager Jun 29 '12 at 06:23
  • I think a boolean representation of the same expression would be too long to be of any use. – Jens Björnhager Jun 29 '12 at 06:34
  • True, it will be too long if expressed in terms of the individual bits. Btw, your correction still doesn't fix the problem. – Alexey Frunze Jun 29 '12 at 07:51
  • @Alexey Frunze I got the shift amount wrong, but I don't see what the problem is now. Going to experiment a bit with this. I don't understand your formula completely, but it looks like it may be the same expression only distributed over xor instead of add. – Jens Björnhager Jun 29 '12 at 08:18
  • My formula is derived directly from the code between `#if` and `#else` in [this answer](http://stackoverflow.com/a/8037485/968261). I re-exressed `if` as `AND`. – Alexey Frunze Jun 29 '12 at 08:28
  • Now your formula is correct, but you should add that the addition `SRC[31..0] + DEST[31..0]` should be done as 33-bit, not as 32-bit, or you will lose the carry-out from it and may additionally fail to shift a 32-bit integer by 32 (won't work neither as a single x86 shift instruction nor as a single shift right in C(++)). – Alexey Frunze Jun 29 '12 at 08:35
  • @Alexey Frunze I'm thinking in the context of an ALU here, so the adds are 33 and 32 bits. I would rewrite the expression altogether - probably to look more loke yours - if I wanted it in a code context. – Jens Björnhager Jun 29 '12 at 09:02
  • You don't have to rewrite anything. The only thing I think you still should do is clearly state in the answer that the first addition ought to be 33-bit-long and the last ought to be 32-bit-long. Just a warning, so whoever uses your answer doesn't make a mistake because of either not understanding what's going on or not paying enough attention. – Alexey Frunze Jun 29 '12 at 09:11
  • @Alexey and @ Frunze +1 thanks for the effort on this tricky problem. – srking Jun 29 '12 at 18:56
1

This is how you can express the signed overflow flag value for addition of two signed (2's complement) 32-bit integers:

OV = (((SRC XOR DST) XOR 80000000H) AND ((SRC + DST) XOR SRC) AND 80000000H) ≠ 0

SRC and DST are the entire 32-bit integer values.

The expression essentially compares the signs of the sum and of the addends.

Expressing the overflow solely in terms of individual bits isn't very practical because you'd need to effectively replicate a full 32-bit adder. And that's not a good candidate for one-lining.

If you want a similar expression for subtraction, try to derive it or just express subtraction in terms of addition as is done in the Sbb() function in this answer. It shouldn't be hard.

Using a test to make sure your code works is a good idea, too. You can even write a small assembly routine for addition/subtraction that would return you the overflow flag and use that to test correctness of your one-liner.

Community
  • 1
  • 1
Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180