fcomp.x 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. ! bcc 386 floating point routines (version 2) -- Fcomp, Fcompd, Fcompf
  2. ! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans
  3. #include "fplib.h"
  4. .extern Fpushf
  5. ! Pop 2 doubles from stack and compare them, return result in flags so
  6. ! normal signed branches work (unlike 80x87 which returns the result in
  7. ! the zero and carry flags).
  8. .globl Fcomp
  9. .align ALIGNMENT
  10. Fcomp:
  11. pop ecx ! get return address
  12. pop eax ! xl
  13. pop edx ! xu
  14. push ecx ! put back ret address - pop 2nd double later
  15. ! All this popping is bad on 486's since plain mov takes 1+ cycle and pop
  16. ! takes 4 cycles. But this code is designed for 386's where popping is
  17. ! nominally the same speed and saves code space and so maybe instruction
  18. ! fetch time as well as the instruction to adjust the stack (ret #n takes
  19. ! no longer than plain ret but inhibits gotos).
  20. mov ebx,PC_SIZE+D_LOW[esp] ! yl
  21. mov ecx,PC_SIZE+D_HIGH[esp] ! yu
  22. jmp compare
  23. ! Pop double from stack and compare with double at [ebx]
  24. .globl Fcompd
  25. .align ALIGNMENT
  26. Fcompd:
  27. mov eax,PC_SIZE+D_LOW[esp] ! xl
  28. mov edx,PC_SIZE+D_HIGH[esp] ! xu
  29. mov ecx,D_HIGH[ebx] ! yu
  30. mov ebx,D_LOW[ebx] ! yl
  31. compare:
  32. test edx,#D_SIGN_MASK ! is x >= 0?
  33. jz cmp0 ! yes; just compare x and y
  34. test ecx,#D_SIGN_MASK ! no; but is y >= 0?
  35. jz cmp0 ! yes; just compare x and y
  36. xchg edx,ecx ! x, y < 0, so ...
  37. xchg eax,ebx ! ... swap x and y ...
  38. xor edx,#D_SIGN_MASK ! ... and toggle signs
  39. xor ecx,#D_SIGN_MASK
  40. cmp0:
  41. cmp edx,ecx ! compare upper dwords
  42. jnz checkneg0 ! if upper dwords differ, job is almost done
  43. mov edx,eax ! upper dwords equal, so ...
  44. mov ecx,ebx ! ... must make unsigned comparison of lower dwords
  45. shr edx,#1 ! shift past sign
  46. shr ecx,#1
  47. cmp edx,ecx ! compare top 31 bits of lower dwords
  48. jnz return ! if these differ, job is done
  49. and eax,#1 ! compare lowest bits
  50. and ebx,#1
  51. cmp eax,ebx
  52. return:
  53. ret #D_SIZE ! return, popping 1 double from stack
  54. checkneg0:
  55. test edx,#D_EXP_MASK | D_FRAC_MASK ! check to catch unusual case ...
  56. jnz recheck
  57. test eax,eax
  58. jnz recheck
  59. test ecx,#D_EXP_MASK | D_FRAC_MASK
  60. jnz recheck
  61. test ebx,ebx
  62. jz return ! ... both are (+-) zero, return 'z'
  63. recheck:
  64. cmp edx,ecx ! the upper words were really different
  65. ret #D_SIZE
  66. .globl Fcompf
  67. .align ALIGNMENT
  68. Fcompf:
  69. call Fpushf
  70. pop ebx ! yl
  71. pop ecx ! yu
  72. mov eax,PC_SIZE+D_LOW[esp] ! xl
  73. mov edx,PC_SIZE+D_HIGH[esp] ! xu
  74. jmp compare