t35_not.pas 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. program t35;
  2. { t35 -- `not', on both of the operand types it is defined for.
  3. TPSRC9 neglevel picks the instruction from the operand's type before it
  4. emits anything:
  5. CMP.B CL,#$0A ; integer ?
  6. JZ negnot ; -> CALL loadatom ; NOT AX (F7 D0)
  7. CMP.B CL,#$0B ; boolean ?
  8. CALL errnz ; -> error 47 for anything else
  9. CALL loadatom
  10. ; -> XOR AL,#01 (34 01)
  11. This compiler used to emit NOT AX for both of them, so every boolean
  12. came out wrong one way: `not (a = a)' computed 0FFFEh and the runtime's
  13. wrbool tests [BP+4] <> 0, which reads 0FFFEh as TRUE. Pascal says
  14. FALSE. Exec86 and qemu agreed with each other and both disagreed with
  15. Pascal, which is what pins the fault on the compiler and not on the
  16. interpreter.
  17. The integer half is here because it is the other arm of the same branch:
  18. `not a' has to stay NOT AX, and must not be dragged along to XOR AL,#01
  19. by a fix aimed at booleans.
  20. A BOOLEAN variable is one byte and LoadAtom clears AH after a byte load,
  21. so XOR AL,#01 cannot leave a dirty high byte for wrbool to trip over.
  22. Every expectation below is derived from Pascal's definition - `not' on an
  23. integer is the 16-bit one's complement, `not' on a boolean is logical
  24. negation - and from nowhere else. }
  25. var
  26. a : integer;
  27. b : boolean;
  28. begin
  29. a := 17;
  30. writeln (not a);
  31. writeln (not (a = 17));
  32. writeln (not (a = 18));
  33. writeln (not (a > 100));
  34. b := a = 17;
  35. writeln (not b);
  36. b := a = 18;
  37. writeln (not b);
  38. writeln (not 5)
  39. end.