tw8282.pp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. { %opt=-O2 -Sew }
  2. {$inline on}
  3. type
  4. Int96 = packed record
  5. case Integer of
  6. 0:
  7. (
  8. {$IFDEF ENDIAN_LITTLE}
  9. Lo32 : DWord;
  10. case Integer of
  11. 0:
  12. (
  13. Mid32 : DWord;
  14. Hi32 : LongInt;
  15. );
  16. 1:
  17. ( Hi64: Int64; );
  18. {$ELSE ENDIAN_LITTLE}
  19. Hi32 : LongInt;
  20. case Integer of
  21. 0:
  22. (
  23. Mid32 : DWord;
  24. Lo32 : DWord;
  25. );
  26. 1:
  27. ( Lo64: QWord; );
  28. {$ENDIF ENDIAN_LITTLE}
  29. );
  30. 1:
  31. (
  32. {$IFDEF ENDIAN_LITTLE}
  33. Lo64 : QWord;
  34. {$ELSE ENDIAN_LITTLE}
  35. Hi64 : Int64;
  36. {$ENDIF ENDIAN_LITTLE}
  37. );
  38. end;
  39. operator shl (const Left: Int96; const Right: LongInt) Result : Int96; forward;
  40. operator shr (const Left: Int96; const Right: LongInt) Result : Int96; inline;
  41. begin
  42. if Right >= 0 then
  43. if Right = 32 then begin
  44. Result.Lo32 := Left.Mid32;
  45. Result.Mid32 := Left.Hi32;
  46. Result.Hi32 := 0;
  47. end else if Right = 0 then begin
  48. Result.Lo32 := Left.Lo32;
  49. Result.Mid32 := Left.Mid32;
  50. Result.Hi32 := Left.Hi32;
  51. end else if Right = 64 then begin
  52. Result.Lo32 := Left.Hi32;
  53. Result.Mid32 := 0;
  54. Result.Hi32 := 0;
  55. end else if Right < 32 then begin
  56. Result.Hi32 := Left.Hi32 shr Right;
  57. Result.Mid32 := (Left.Mid32 shr Right) or (Left.Hi32 shl (32 - Right));
  58. Result.Lo32 := (Left.Lo32 shr Right) or (Left.Mid32 shl (32 - Right));
  59. end else if Right < 64 then begin
  60. Result.Hi32 := 0;
  61. Result.Mid32 := Left.Hi32 shr (Right-32);
  62. Result.Lo32 := (Left.Mid32 shr (Right-32)) or (Left.Hi32 shl (64 - Right));
  63. end else if Right < 96 then begin
  64. Result.Hi32 := 0;
  65. Result.Mid32 := 0;
  66. Result.Lo32 := Left.Hi32 shr (Right-64);
  67. end else begin
  68. Result.Lo32 := 0;
  69. Result.Mid32 := 0;
  70. Result.Hi32 := 0;
  71. end
  72. else
  73. Result := Left shl (-Right);
  74. end;
  75. operator shl (const Left: Int96; const Right: LongInt) Result : Int96; inline;
  76. begin
  77. { ToDo: optimized code for 64bit cpu's }
  78. if Right >= 0 then
  79. if Right = 32 then begin
  80. Result.Lo32 := 0;
  81. Result.Mid32 := Left.Lo32;
  82. Result.Hi32 := Left.Mid32;
  83. end else if Right = 0 then begin
  84. Result.Lo32 := Left.Lo32;
  85. Result.Mid32 := Left.Mid32;
  86. Result.Hi32 := Left.Hi32;
  87. end else if Right = 64 then begin
  88. Result.Lo32 := 0;
  89. Result.Mid32 := 0;
  90. Result.Hi32 := Left.Lo32;
  91. end else if Right < 32 then begin
  92. Result.Lo32 := Left.Lo32 shl Right;
  93. Result.Mid32 := (Left.Mid32 shl Right) or (Left.Lo32 shr (32 - Right));
  94. Result.Hi32 := (Left.Hi32 shl Right) or (Left.Mid32 shr (32 - Right));
  95. end else if Right < 64 then begin
  96. Result.Lo32 := 0;
  97. Result.Mid32 := Left.Lo32 shl (Right-32);
  98. Result.Hi32 := (Left.Mid32 shl (Right-32)) or (Left.Lo32 shr (64 - Right));
  99. end else if Right < 96 then begin
  100. Result.Lo32 := 0;
  101. Result.Mid32 := 0;
  102. Result.Hi32 := Left.Lo32 shl (Right-64);
  103. end else begin
  104. Result.Lo32 := 0;
  105. Result.Mid32 := 0;
  106. Result.Hi32 := 0;
  107. end
  108. else
  109. Result := Left shr (-Right);
  110. end;
  111. operator := (const Right: QWord) Result : Int96; inline;
  112. begin
  113. Result.Lo64 := Right;
  114. Result.Hi32 := 0;
  115. end;
  116. procedure t;
  117. var
  118. a: int96;
  119. begin
  120. a := 500000000000000;
  121. a := a shr 1;
  122. if (a.lo64 <> (500000000000000 shr 1)) or
  123. (a.hi32 <> 0) then
  124. halt(1);
  125. end;
  126. begin
  127. t;
  128. end.