hugh@hcrvx1.UUCP (Hugh Redelmeier) (07/05/85)
All 8086 manuals I have read say that shift instructions set
the flags to reflect the value of the result. All the chips
that I have tested (8086, 8088, 80186) do not set the flags
if the shift count is zero. I discovered this when the following
C code gave the wrong answer (under XENIX 2.1 -- not their
fault though) (this code is from memory, so it may be slightly
inaccurate):
main() {
register int i, j;
i = 0;
j = 1; j += 1; /* clear Z flag */
if (i << i) /* shift of 0 by 0 should set Z flag, but doesn't */
printf("WRONG!\n");
}
[Even if the predicate is written more cleanly as (i<<i != 0), the
compiler is smart enough to generate the same code. The use of i
instead of the literal 0 is to prevent compile-time evaluation.]
At the machine language level what is going on? The key
instruction is a shift with its count in a register. This
count is 0. The shift does not change the flags from their
previous value.
Cure(idealistic): INTEL et al should fix the chips (and give users new ones!)
Cure(imaginable): INTEL et al should revise the manuals; every compiler that
is affected should be updated (and users given new ones); every
program compiled using the previous compiler should be re-compiled;
every assembler program should be combed for this problem.
unCure(sad but true): users should be aware of this problem
dww@stl.UUCP (David Wright) (07/10/85)
In article <1190@hcrvx1.UUCP> hugh@hcrvx1.UUCP (Hugh Redelmeier) writes: >All 8086 manuals I have read say that shift instructions set >the flags to reflect the value of the result. All the chips >that I have tested (8086, 8088, 80186) do not set the flags >if the shift count is zero. 1 - If I remember rightly, the 8086 (et al) Users Guides say that for count of 0 "the result is undefined" - in practice you seem to have discovered that the result is <do nothing> (not even set flags). I think it is very bad to have undefined results unnecessarily, but at least it's a "feature" not a bug (a "feature" is a bug that you documented .... ). I guess the C manual you're using didn't get round to documenting it - not Intel's fault if their "feature" wasn't recognised! 2 - I guess one reason Intel haven't bothered to fix this "feature" is that their PL/M-86 compiler isn't (usually) upset by such things, because it can almost always optimise out shift 0 anyway, and the C example you gave is pretty unlikely to appear in PL/M.
hugh@hcrvx1.UUCP (Hugh Redelmeier) (07/15/85)
In article <190@stl.UUCP> dww@stl.UUCP (David Wright) writes: >1 - If I remember rightly, the 8086 (et al) Users Guides say that for count of >0 "the result is undefined" - in practice you seem to have discovered that the >result is <do nothing> (not even set flags). I think it is very bad to have >undefined results unnecessarily, but at least it's a "feature" not a bug >(a "feature" is a bug that you documented .... ). As I said in my original posting "All 8086 manuals I have read say...". I guess I should have been more explicit. Here goes. I found the various manuals were not easy to follow on this point. The discussion is divided among several places. Here goes chapter and verse; these are all the manuals I have acccess to (and the only ones the XENIX 2.1 C-compiler porters had access to too, I bet). INTEL: MCS-86 User's Manual; 1978 January [marked preliminary] 4-16 under heading "SHIFTS": "... and PF, SF, and ZF are set to reflect the result value." under subheading "Mnemonic: SHL and SAL": "Flags affected: CF, OF, PF, SF, ZF. AF undefined" INTEL: 8086 Family User's Manual; 1979 October 2-35 (discussing arithmetic instructions and flags) "- ZF (zero flag): If the result of an arithmetic or logical operation is zero then ZF is set; otherwise ZF is cleared" 2-39 "Shift instructions affect the flags as follows: ... PF, SF and ZF are updated normally, as in logical instructions." 2-65 says SAL/SAR do NOT affect ZF etc! But I know they do affect ZF sometimes -- clearly this does not describe what the chips do. Nor does this agree with the other quotes from this same manual. INTEL: iAPX 86, 88 User's Manual; 1981 July same as previous manual EXCEPT: 2-65 SAR does set ZF. A documentation fix? also in this manual: 2-8 "6) if ZF(the zero flag) is set, the result of the operation is zero". This sentence seems to imply backwards causality! Other flags are described in a similar way nearby. INTEL: iAPX 88 Book; 1981 July 2-13 (discussing shifts) "... PF, SF, and ZF are set to reflect the result value" 2-139 SAL affects ZF. This section does not say in what way the flag is set (but then neither does the description of the ADD instruction). Clearly 2-13 is the operative section. <end of chapter-and-verse> If newer manuals say something different, please tell me. I am also curious about what the 286 actually does, since I understand that it has fancy shifting hardware. (I just tried to find out, but after half an hour, Xenix 3.0 has defeated me. I did learn that the 3.0 compiler generates an explicit compare, so I had to try assembler. Unfortunately, I couldn't get cc to accept as input a .s that it created.) > I guess the C manual you're >using didn't get round to documenting it - not Intel's fault if their "feature" >wasn't recognised! What is it that you feel the C manual should have said? Hugh Redelmeier (416) 922-1937 {utzoo, ihnp4, decvax}!hcr!hugh