Since the mid-range PICs don't have any built-in overflow detection circuitry, this must be done in software. I need to detect overflow in signed 8-bit addition, and I need to do it fairly efficiently. An overflow can be identified as a condition where the carry-in to bit 7 is not the same as the carry-out from bit 7. The signed range is -128 to +127. Does anyone have any really short way of detecting overflow in addition of such numbers in a PIC?
-Robert Scott Ypsilanti, Michigan (Reply through newsgroups, not by direct e-mail, as automatic reply address is fake.)
If you do multiple additions in a row, it could be better to use (semi) 16-bit arithmetic and check range of the final result.
------------
; res = resHigh:W
load_result: movf opp1,w ; move operand1 to resultLow
clrf resHigh ; sign extend result btfsc opp1,7 decf resHigh
return
add_to_result: addwf opp2,w ; add low bytes
btfsc status,c incf resHigh ; handle carry
btfsc opp2,7 decf resHigh ; add high bytes
return
check_result: ; this one destroys resHigh movwf resLow
btfsc resLow,7 ; sets resHigh to zero, if and only iff incf resHigh ; res[15..7] is all zeros or all ones movf resHigh,f btfsc STATUS,Z goto overflow ...
This makes 5 cycles per addition, if done with a macro insted of a subroutine.
In my application I am using signed overflow detection as a way of implementing a normal and expected limiting condition. Behaviour near the limiting condition does not have to be precise, so I have taken advantage of this fact. I need to add PhaseDelta (-8...+7) to PhaseAccum (-128...+127) so that PhaseAccum never overflows as a signed number. PhaseDelta is initially formed by subtracting two modulo-16 numbers, so it is only 4-bits and it needs to be sign extended to 8 bits. In the process of sign extending PhaseDelta, I already have the cases of (+) and (-) separated, so combine sign extension with overflow limiting as follows:
Even though PhaseAccum is a signed value, I use the unsigned comparison, because it is much faster (as compiled by the CCS PIC-C compiler). The limiting behaviour is a little more conservative than it needs to be because the code shown will limit at values other than
+127 or -128. But to make the limiting precise would have required more code, and this code is part of a tight DSP loop. Besides, the approximate limiting behaviour is adequate for the application. But I was just wondering if there was a slick way of doing signed overflow detection in general. By the way, the overflow detection in the code that you posted appears to be for unsigned arithmetic only. But thanks for responding anyway.
-Robert Scott Ypsilanti, Michigan (Reply through newsgroups, not by direct e-mail, as automatic reply address is fake.)
What a wonderful solution! (with the btfsc/btfss corrected). I had never realized the potential advantage of the offset representation of signed numbers, but it works perfectly for signed overflow detection. Thanks a lot.
I will be able maintain the offset representation so that I can avoid the repeated conversions at the beginning and the end, and just perform the offset conversion once when the grand total is used. Of course I will have to initialize the sum to 0x80 instead of 0 after each grand total is used.
In case you are interested, the application is a tuning device for pipe organs. Microphone values are quadrature demodulated into a phase angle (in 16ths of a cycle). Successive phase angles are subtracted to give the PhaseDelta (-8...+7). The PhaseDeltas are accumulated to get the overall phase change over a given time period, which determines pitch error. The limiting mentioned above represents the fact that if the pitch is off by a large amount, we really don't need to know how far off it is. Quantitative information becomes important only when the pipe is tuned somewhat closer to the correct pitch.
-Robert Scott Ypsilanti, Michigan (Reply through newsgroups, not by direct e-mail, as automatic reply address is fake.)
The real problem is that ANSI-C provides no method of handling carry or overflow. There are many ways to test for overflow. However, it depends on the architecture which one is fastest (usually, there are carry/overflow-flags available in hardware).
Your solution is very short in C and may do well enough on some architectures, but will result in bloated assembler code on PIC ;-(
I haven't realized the potential advantage myself, since I am used to have an overflow flag ;-)
This solution also works for the general case, if you leave out the sign extension and relace the "restore"-instruction with a goto/call to the error handling. This is faster than my first solution...
Your problem is that you may have a number such as 50, and if you add 100 to it, you'll get 150, which is beyond the range of your data type.
Whenever I have a problem like this, I change to the next larger data type. In this case, I would go to a signed 16-bit variable. Assuming that your initial value is always 8-bit signed (which is cast to 16-bit), then you can never have an overflow.
I realize it may run a little more slowly, and require a little more ROM, but in my projects that's typically not an issue.
The thing that scares me most is failure in the field. I will do whatever it takes to avoid having that happen.
As I said earlier, my problem is not one of handling an exceptional error condition. The overflow that I get is a normal, expected, and desireable opportunity to perform a limiting function, which just happens to make perfect sense for my particular application. Using a
16-number would avoid the overflows, but it would not afford the opportunity of such an easy limiting action.
-Robert Scott Ypsilanti, Michigan (Reply through newsgroups, not by direct e-mail, as automatic reply address is fake.)
The question was "detecting overflow in general", that's what I answered to. And since the principle of detecting signed overflow has nothing to do with neither carry nor overflow flag (if implemented, they will be set as a result of) I did not mention them.
For addition/subtraction of "a" and "b" resulting in "x" you only need to check two combinations of the MSBs of a, b and x, like:
a b x ------- 0 0 1 --> overflow 1 1 0 --> overflow
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.