ARM.ARMRuntime.Mod 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. MODULE ARMRuntime;
  2. IMPORT SYSTEM, FPE64;
  3. CONST
  4. B = 127;
  5. C = 800000H;
  6. E = 100H;
  7. S = LONGINT(80000000H); (* used by VFP unit emulation *)
  8. MAXREAL = LONGINT(7F7FFFFFH);
  9. TYPE
  10. ULONGINT = LONGINT; (* alias to make distinction between signed and unsigned more clear *)
  11. UHUGEINT = HUGEINT;
  12. FLOAT32 = LONGINT; (* alias to make clear that the integer actually contains a IEEE 32 bit float *)
  13. FLOAT64= HUGEINT;
  14. PROCEDURE DivS8*(left, right: SHORTINT): SHORTINT;
  15. VAR result, dummy: LONGINT;
  16. BEGIN DivModS32(left, right, result, dummy); RETURN SHORTINT(result)
  17. END DivS8;
  18. PROCEDURE DivS16*(left, right: INTEGER): INTEGER;
  19. VAR result, dummy: LONGINT;
  20. BEGIN DivModS32(left, right, result, dummy); RETURN INTEGER(result)
  21. END DivS16;
  22. PROCEDURE DivS32*(left, right: LONGINT): LONGINT;
  23. VAR result, dummy: LONGINT;
  24. BEGIN DivModS32(left, right, result, dummy); RETURN result
  25. END DivS32;
  26. PROCEDURE DivU32*(left, right: ULONGINT): ULONGINT;
  27. VAR result, dummy: LONGINT;
  28. BEGIN DivModU32(left, right, result, dummy); RETURN result
  29. END DivU32;
  30. PROCEDURE DivS64*(left, right: HUGEINT): HUGEINT;
  31. VAR result, dummy: HUGEINT;
  32. BEGIN
  33. DivModS64(left, right, result, dummy); RETURN result
  34. END DivS64;
  35. PROCEDURE ModS8*(left, right: SHORTINT): SHORTINT;
  36. VAR result, dummy: LONGINT;
  37. BEGIN DivModS32(left, right, dummy, result); RETURN SHORTINT(result)
  38. END ModS8;
  39. PROCEDURE ModS16*(left, right: INTEGER): INTEGER;
  40. VAR result, dummy: LONGINT;
  41. BEGIN DivModS32(left, right, dummy, result); RETURN INTEGER(result)
  42. END ModS16;
  43. PROCEDURE ModS32*(left, right: LONGINT): LONGINT;
  44. VAR result, dummy: LONGINT;
  45. BEGIN DivModS32(left, right, dummy, result); RETURN result
  46. END ModS32;
  47. PROCEDURE ModU32*(left, right: ULONGINT): ULONGINT;
  48. VAR result, dummy: LONGINT;
  49. BEGIN DivModU32(left, right, dummy, result); RETURN result
  50. END ModU32;
  51. PROCEDURE ModS64*(left, right: HUGEINT): HUGEINT;
  52. VAR result, dummy: HUGEINT;
  53. BEGIN
  54. DivModS64(left, right, dummy, result); RETURN result
  55. END ModS64;
  56. PROCEDURE RolS64*(source: HUGEINT; amount: ULONGINT): HUGEINT;
  57. CODE
  58. LDR R2, [FP, #+8] ; R2 := amount
  59. LDR R3, [FP, #+12] ; R3 := source[Low]
  60. LDR R4, [FP, #+16] ; R4 := source[High]
  61. ; source = R4:R3
  62. AND R2, R2, #3FH ; R2 := R2 MOD 64
  63. CMP R2, #32
  64. ; IF R2 < 32:
  65. MOVLT R0, R3, LSL R2
  66. MOVLT R1, R4, LSL R2
  67. RSBLT R2, R2, #32 ; R2 := 32 - R2
  68. ORRLT R0, R0, R4, LSR R2
  69. ORRLT R1, R1, R3, LSR R2
  70. ; IF R2 >= 32:
  71. SUBGE R2, R2, #32 ; R2 := R2 - 32
  72. MOVGE R0, R4, LSL R2
  73. MOVGE R1, R3, LSL R2
  74. RSBGE R2, R2, #32 ; R2 := 32 - R2
  75. ORRGE R0, R0, R3, LSR R2
  76. ORRGE R1, R1, R4, LSR R2
  77. ; result = R1:R0
  78. END RolS64;
  79. PROCEDURE RolU64*(source: HUGEINT; amount: ULONGINT): HUGEINT;
  80. BEGIN RETURN RolS64(source, amount)
  81. END RolU64;
  82. PROCEDURE RorS64*(source: HUGEINT; amount: ULONGINT): HUGEINT;
  83. BEGIN RETURN RolS64(source, 64 - (amount MOD 64))
  84. END RorS64;
  85. PROCEDURE RorU64*(source: HUGEINT; amount: ULONGINT): HUGEINT;
  86. BEGIN RETURN RolS64(source, 64 - (amount MOD 64))
  87. END RorU64;
  88. (* signed division and modulus
  89. - note: this implements the mathematical definition of DIV and MOD in contrast to the symmetric one
  90. *)
  91. PROCEDURE DivModS32(dividend, divisor: LONGINT; VAR quotient, remainder: LONGINT);
  92. BEGIN
  93. ASSERT(divisor > 0);
  94. IF dividend >= 0 THEN
  95. DivModU32(dividend, divisor, quotient, remainder)
  96. ELSE
  97. dividend := -dividend;
  98. DivModU32(dividend, divisor, quotient, remainder);
  99. quotient := -quotient;
  100. IF remainder # 0 THEN
  101. DEC(quotient);
  102. remainder := divisor - remainder
  103. END
  104. END
  105. END DivModS32;
  106. (*
  107. Fast 32-bit unsigned integer division/modulo (author Alexey Morozov)
  108. *)
  109. PROCEDURE DivModU32*(dividend, divisor: ULONGINT; VAR quotient, remainder: ULONGINT);
  110. CODE
  111. MOV R2, #0 ; quotient will be stored in R2
  112. LDR R0, [FP,#dividend] ; R0 := dividend
  113. LDR R1, [FP,#divisor] ; R1 := divisor
  114. ; check for the case dividend < divisor
  115. CMP R0, R1
  116. BEQ Equal
  117. BLS Exit ; nothing to do than setting quotient to 0 and remainder to dividend (R0)
  118. CLZ R3, R0 ; R3 := clz(dividend)
  119. CLZ R4, R1 ; R4 := clz(divisor)
  120. SUB R3, R4, R3 ; R2 := clz(divisor) - clz(dividend) , R2 >= 0
  121. LSL R1, R1, R3 ; scale divisor: divisor := LSH(divisor,clz(divisor)-clz(dividend))
  122. Loop:
  123. CMP R0, R1
  124. ADC R2, R2, R2
  125. SUBCS R0, R0, R1
  126. LSR R1, R1, #1
  127. SUBS R3, R3, #1
  128. BPL Loop
  129. ; R0 holds the remainder
  130. B Exit
  131. Equal:
  132. MOV R2, #1
  133. MOV R0, #0
  134. Exit:
  135. LDR R1, [FP,#quotient] ; R1 := address of quotient
  136. LDR R3, [FP,#remainder] ; R3 := address of remainder
  137. STR R2, [R1,#0] ; quotient := R2
  138. STR R0, [R3,#0] ; remainder := R0
  139. END DivModU32;
  140. (**
  141. Signed 64-bit multiplication. Adapted version based on the original code
  142. from "Runtime ABI for the ARM Cortex-M0" (https://github.com/bobbl/libaeabi-cortexm0/blob/master/lmul.S)
  143. /* Runtime ABI for the ARM Cortex-M0
  144. * lmul.S: 64 bit multiplication
  145. *
  146. * Copyright (c) 2013 Jörg Mische <bobbl@gmx.de>
  147. *
  148. * Permission to use, copy, modify, and/or distribute this software for any
  149. * purpose with or without fee is hereby granted, provided that the above
  150. * copyright notice and this permission notice appear in all copies.
  151. *
  152. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  153. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  154. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  155. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  156. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  157. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  158. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  159. */
  160. Multiply r1:r0 and r3:r2 and return the product in r1:r0
  161. Can also be used for unsigned long product
  162. *)
  163. PROCEDURE MulS64*(x, y: HUGEINT): HUGEINT;
  164. CODE
  165. ldr r0, [FP,#x]
  166. ldr r1, [FP,#x+4]
  167. ldr r2, [FP,#y]
  168. ldr r3, [FP,#y+4]
  169. muls r1, r1, r2
  170. muls r3, r3, r0
  171. adds r1, r1, r3
  172. lsrs r3, r0, #16
  173. lsrs r4, r2, #16
  174. muls r3, r3, r4
  175. adds r1, r1, r3
  176. lsrs r3, r0, #16
  177. uxth r0, r0
  178. uxth r2, r2
  179. muls r3, r3, r2
  180. muls r4, r4, r0
  181. muls r0, r0, r2
  182. movs r2, #0
  183. adds r3, r3, r4
  184. adcs r2, r2, r2
  185. lsls r2, r2, #16
  186. adds r1, r1, r2
  187. lsls r2, r3, #16
  188. lsrs r3, r3, #16
  189. adds r0, r0, r2
  190. adcs r1, r1, r3
  191. END MulS64;
  192. (* signed division and modulus
  193. - note: this implements the mathematical definition of DIV and MOD in contrast to the symmetric one
  194. *)
  195. PROCEDURE DivModS64*(dividend, divisor: HUGEINT; VAR quotient, remainder: HUGEINT);
  196. BEGIN
  197. ASSERT(divisor > 0);
  198. IF dividend >= 0 THEN
  199. DivModU64(dividend, divisor, quotient, remainder)
  200. ELSE
  201. dividend := -dividend;
  202. DivModU64(dividend, divisor, quotient, remainder);
  203. quotient := -quotient;
  204. IF remainder # 0 THEN
  205. DEC(quotient);
  206. remainder := divisor - remainder
  207. END
  208. END
  209. END DivModS64;
  210. (* Count leading zeros in a binary representation of a given 64-bit integer number *)
  211. PROCEDURE Clz64*(x: UHUGEINT): LONGINT;
  212. CODE
  213. ; high-half
  214. LDR R1, [FP,#x+4]
  215. CMP R1, #0 ; if high-half is zero count leading zeros of the low-half
  216. BEQ LowHalf
  217. CLZ R0, R1
  218. B Exit
  219. ; low-half
  220. LowHalf:
  221. LDR R1, [FP,#x]
  222. CLZ R0, R1
  223. ADD R0, R0, #32 ; add 32 zeros from the high-half
  224. Exit:
  225. END Clz64;
  226. (*
  227. Fast 64-bit unsigned integer division/modulo (Alexey Morozov)
  228. *)
  229. PROCEDURE DivModU64*(dividend, divisor: UHUGEINT; VAR quotient, remainder: UHUGEINT);
  230. VAR m: LONGINT;
  231. BEGIN
  232. quotient := 0;
  233. IF dividend = 0 THEN remainder := 0; RETURN; END;
  234. IF dividend < divisor THEN remainder := dividend; RETURN; END;
  235. m := Clz64(divisor) - Clz64(dividend);
  236. ASSERT(m >= 0);
  237. divisor := LSH(divisor,m);
  238. WHILE m >= 0 DO
  239. quotient := LSH(quotient,1);
  240. IF dividend >= divisor THEN
  241. INC(quotient);
  242. DEC(dividend,divisor);
  243. END;
  244. divisor := LSH(divisor,-1);
  245. DEC(m);
  246. END;
  247. remainder := dividend;
  248. (*
  249. CODE
  250. ldr r0, [FP,#dividend]
  251. ldr r1, [FP,#dividend+4]
  252. ldr r2, [FP,#divisor]
  253. ldr r3, [FP,#divisor+4]
  254. ldr r5, [FP,#quotient]
  255. ldr r6, [FP,#remainder]
  256. str r0, [r5,#0]
  257. str r1, [r5,#4]
  258. str r2, [r6,#0]
  259. str r3, [r6,#4]
  260. *)
  261. END DivModU64;
  262. PROCEDURE NegF32*(float: FLOAT32): FLOAT32;
  263. CODE
  264. LDR R0, [FP, #+float] ; R0 := float
  265. EOR R0, R0, #S ; invert only the sign bit
  266. END NegF32;
  267. PROCEDURE AbsF32*(float: FLOAT32): FLOAT32;
  268. CODE
  269. LDR R0, [FP, #+float] ; R0 := float
  270. BIC R0, R0, #S ; clear the sign bit
  271. END AbsF32;
  272. PROCEDURE AddF32*(x, y: FLOAT32): FLOAT32;
  273. VAR xe, ye, s: LONGINT;
  274. BEGIN
  275. IF SYSTEM.NULL(x) = TRUE THEN x := y
  276. ELSIF SYSTEM.NULL(y) = FALSE THEN
  277. xe := x DIV C MOD E; (* exponent with bias *)
  278. IF x >= 0 THEN x := (x MOD C + C)*2 ELSE x := -(x MOD C + C)*2 END ;
  279. ye := y DIV C MOD E; (* exponent with bias *)
  280. IF y >= 0 THEN y := (y MOD C + C)*2 ELSE y := -(y MOD C + C)*2 END ;
  281. IF xe < ye THEN
  282. ye := ye - xe; xe := xe + ye; (*denorm x*)
  283. IF ye <= 25 THEN x := ASH(x, -ye) ELSE x := 0 END
  284. ELSIF ye < xe THEN
  285. ye := xe - ye; (*denorm y*)
  286. IF ye <= 25 THEN y := ASH(y, -ye) ELSE y := 0 END
  287. END ;
  288. s := x + y; x := ABS(s);
  289. s := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, s)*{31});
  290. IF x # 0 THEN
  291. IF x >= 4*C THEN x := (x+2) DIV 4; INC(xe)
  292. ELSIF x >= 2*C THEN x := (x+1) DIV 2
  293. ELSE DEC(xe);
  294. WHILE x < C DO x := 2*x; DEC(xe) END
  295. END ;
  296. IF xe < 0 THEN x := 0 (*underflow*)
  297. ELSIF xe > 0FEH THEN x := MAXREAL + s; (* overflow *)
  298. ELSE x := xe*C + (x - C) + s;
  299. END;
  300. END
  301. END ;
  302. RETURN x
  303. END AddF32;
  304. PROCEDURE AddF64*(x,y: FLOAT64): FLOAT64;
  305. VAR z: FLOAT64;
  306. BEGIN FPE64.Add(SYSTEM.VAL(FPE64.Float64,x),SYSTEM.VAL(FPE64.Float64,y),SYSTEM.VAL(FPE64.Float64,z)); RETURN z
  307. END AddF64;
  308. PROCEDURE MulF64*(x,y: FLOAT64): FLOAT64;
  309. VAR z: FLOAT64;
  310. BEGIN FPE64.Mul(SYSTEM.VAL(FPE64.Float64,x),SYSTEM.VAL(FPE64.Float64,y),SYSTEM.VAL(FPE64.Float64,z)); RETURN z
  311. END MulF64;
  312. PROCEDURE DivF64*(x,y: FLOAT64): FLOAT64;
  313. VAR z: FLOAT64;
  314. BEGIN FPE64.Div(SYSTEM.VAL(FPE64.Float64,x),SYSTEM.VAL(FPE64.Float64,y),SYSTEM.VAL(FPE64.Float64,z)); RETURN z
  315. END DivF64;
  316. PROCEDURE SubF64*(x,y: FLOAT64): FLOAT64;
  317. VAR z: FLOAT64;
  318. BEGIN FPE64.Sub(SYSTEM.VAL(FPE64.Float64,x),SYSTEM.VAL(FPE64.Float64,y),SYSTEM.VAL(FPE64.Float64,z)); RETURN z
  319. END SubF64;
  320. PROCEDURE AbsF64*(x: FLOAT64): FLOAT64;
  321. VAR z: FLOAT64;
  322. BEGIN FPE64.Abs(SYSTEM.VAL(FPE64.Float64,x),SYSTEM.VAL(FPE64.Float64,z)); RETURN z
  323. END AbsF64;
  324. PROCEDURE NegF64*(x: FLOAT64): FLOAT64;
  325. VAR z: FLOAT64;
  326. BEGIN FPE64.Neg(SYSTEM.VAL(FPE64.Float64,x),SYSTEM.VAL(FPE64.Float64,z)); RETURN z
  327. END NegF64;
  328. PROCEDURE ConvS32F64*(x: FLOAT64): LONGINT;
  329. BEGIN RETURN FPE64.Fix(SYSTEM.VAL(FPE64.Float64,x))
  330. END ConvS32F64;
  331. PROCEDURE ConvS64F64*(x: FLOAT64): HUGEINT;
  332. BEGIN RETURN FPE64.FixInt64(SYSTEM.VAL(FPE64.Float64,x))
  333. END ConvS64F64;
  334. PROCEDURE ConvF32F64*(x: FLOAT64): FLOAT32;
  335. BEGIN RETURN SYSTEM.VAL(FLOAT32, FPE64.Single(SYSTEM.VAL(FPE64.Float64,x)))
  336. END ConvF32F64;
  337. PROCEDURE ConvF64F32*(x: REAL): FLOAT64;
  338. VAR z: FLOAT64;
  339. BEGIN FPE64.Double(x,SYSTEM.VAL(FPE64.Float64,z)); RETURN z
  340. END ConvF64F32;
  341. PROCEDURE ConvF64S64*(x: HUGEINT): FLOAT64;
  342. VAR flt: FLOAT64;
  343. BEGIN
  344. FPE64.FloatInt64(x, SYSTEM.VAL(FPE64.Float64, flt)); RETURN flt
  345. END ConvF64S64;
  346. PROCEDURE ConvF64S32*(x: LONGINT): FLOAT64;
  347. VAR flt: FLOAT64;
  348. BEGIN FPE64.Float(x, SYSTEM.VAL(FPE64.Float64,flt)); RETURN flt
  349. END ConvF64S32;
  350. PROCEDURE ConvF64S16*(x: INTEGER): FLOAT64;
  351. VAR flt: FLOAT64;
  352. BEGIN FPE64.Float(x, SYSTEM.VAL(FPE64.Float64,flt)); RETURN flt
  353. END ConvF64S16;
  354. PROCEDURE ConvF32S16*(x: INTEGER): REAL;
  355. BEGIN
  356. RETURN ConvF32S32(LONGINT(x))
  357. END ConvF32S16;
  358. PROCEDURE ConvF32S8*(x: SHORTINT): REAL;
  359. BEGIN
  360. RETURN ConvF32S16(INTEGER(x))
  361. END ConvF32S8;
  362. PROCEDURE ConvF64S8*(x: SHORTINT): FLOAT64;
  363. BEGIN
  364. RETURN ConvF64S16(INTEGER(x))
  365. END ConvF64S8;
  366. PROCEDURE SubF32*(left, right: FLOAT32): FLOAT32;
  367. BEGIN RETURN AddF32(left, NegF32(right))
  368. END SubF32;
  369. PROCEDURE MulF32*(x, y: FLOAT32): FLOAT32;
  370. VAR xe, zh, ye, s: LONGINT; (*zh, ye in this order; ye used as zh in MULD*)
  371. BEGIN
  372. IF SYSTEM.NULL(y) = TRUE THEN x := 0
  373. ELSIF SYSTEM.NULL(y) = FALSE THEN
  374. s := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, SYSTEM.XOR(x, y))*{31});
  375. xe := x DIV C MOD E; (* exponent with bias *)
  376. ye := y DIV C MOD E; (* exponent with bias *)
  377. x := (x MOD C + C) * 20H;
  378. y := (y MOD C + C) * 20H;
  379. xe := xe + ye - B; (* exponent with bias *)
  380. SYSTEM.MULD(ye, x, y); (* note that this implicitly changes zh *)
  381. IF zh >= 4*C THEN
  382. x := (zh+2) DIV 4;
  383. INC(xe);
  384. ELSE
  385. x := (zh+1) DIV 2;
  386. END;
  387. IF xe < 0 THEN (* underflow *)
  388. x := 0;
  389. ELSIF xe > 0FEH THEN (* overflow *)
  390. x := MAXREAL + s;
  391. ELSE
  392. x := xe*C + (x-C) + s;
  393. END;
  394. END ;
  395. RETURN x
  396. END MulF32;
  397. PROCEDURE DivF32*(x, y: FLOAT32): FLOAT32;
  398. VAR xe, ye, q, s: LONGINT;
  399. BEGIN
  400. s := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, SYSTEM.XOR(x, y))*{31});
  401. IF SYSTEM.NULL(y) = TRUE THEN
  402. x := MAXREAL + s;
  403. ELSIF SYSTEM.NULL(x) = FALSE THEN
  404. xe := x DIV C MOD E; (* exponent with bias *)
  405. ye := y DIV C MOD E; (* exponent with bias *)
  406. x := x MOD C + C;
  407. y := y MOD C + C;
  408. xe := xe - ye + B; (* exponent with bias *)
  409. IF x < y THEN
  410. x := x*2; DEC(xe);
  411. END ;
  412. IF xe < 0 THEN (* underflow *)
  413. x := 0;
  414. ELSIF xe > 0FEH THEN (* overflow *)
  415. x := MAXREAL + s;
  416. ELSE (* divide *)
  417. q := 0;
  418. WHILE q < LONGINT(1000000H) DO (* 2*C *)
  419. q := 2*q;
  420. IF x >= y THEN
  421. x := x - y;
  422. INC(q);
  423. END;
  424. x := 2*x;
  425. END;
  426. q := (q+1) DIV 2; (*round*)
  427. x := xe*C + (q-C) + s;
  428. END;
  429. END;
  430. RETURN x
  431. END DivF32;
  432. (** converts a float into an integer, ignores the fractional part
  433. - corresponds to ENTIER(x) **)
  434. PROCEDURE ConvS32F32*(x: FLOAT32): LONGINT;
  435. VAR xe, s: LONGINT;
  436. BEGIN
  437. IF SYSTEM.NULL(x) = TRUE THEN
  438. x := 0
  439. ELSE
  440. s := x; xe := x DIV C MOD E - B; x := x MOD C + C;
  441. IF s < 0 THEN x := -x END ;
  442. IF xe < 24 THEN x := ASH(x, xe - 23)
  443. ELSIF xe < 31 THEN x := LSH(x, xe - 23)
  444. ELSIF s < 0 THEN x := LONGINT(80000000H);
  445. ELSE x := LONGINT(7FFFFFFFH);
  446. END;
  447. END ;
  448. RETURN x
  449. END ConvS32F32;
  450. (** converts an integer into a float, ignores the non-integer part
  451. - corresponds to REAL(int)
  452. - note that no rounding occurs
  453. **)
  454. PROCEDURE ConvF32S32*(x: LONGINT): FLOAT32;
  455. VAR xe, s: LONGINT;
  456. BEGIN
  457. IF x = LONGINT(80000000H) THEN (* ABS cannot handle the most negative LONGINT number! *)
  458. x := LONGINT(0CF000000H);
  459. ELSIF x # 0 THEN
  460. s := x;
  461. x := ABS(x); xe := 23;
  462. WHILE x >= 2*C DO
  463. x := x DIV 2; INC(xe);
  464. END;
  465. WHILE x < C DO
  466. x := 2*x; DEC(xe);
  467. END;
  468. x := (xe + B)*C - C + x;
  469. IF s < 0 THEN x := x+S END
  470. END ;
  471. RETURN x
  472. END ConvF32S32;
  473. PROCEDURE ConvF32S64*(x: HUGEINT): FLOAT32;
  474. BEGIN
  475. RETURN ConvF32F64(ConvF64S64(x))
  476. END ConvF32S64;
  477. (* ---- STRING OPERATIONS ---- *)
  478. (** compare two strings
  479. - returns 0 if both strings are lexicographically equal
  480. - returns +1 if 'left' is lexicographically greater than 'right'
  481. - returns -1 if 'left' is lexicographically less than 'right'
  482. **)
  483. PROCEDURE CompareString*(CONST left, right: ARRAY OF CHAR): SHORTINT;
  484. VAR
  485. result: SHORTINT;
  486. i: LONGINT;
  487. leftChar, rightChar: CHAR;
  488. BEGIN
  489. result := 0;
  490. i := 0;
  491. REPEAT
  492. leftChar := left[i]; rightChar := right[i];
  493. IF leftChar < rightChar THEN result := -1
  494. ELSIF leftChar > rightChar THEN result := +1
  495. END;
  496. INC(i)
  497. UNTIL (result # 0) OR (leftChar = 0X) OR (rightChar = 0X);
  498. RETURN result
  499. END CompareString;
  500. (** copy a string from 'source' to 'destination'
  501. - note that PACO semantics are used **)
  502. PROCEDURE CopyString*(VAR destination: ARRAY OF CHAR; CONST source: ARRAY OF CHAR);
  503. VAR
  504. sourceLength, destinationLength: LONGINT;
  505. BEGIN
  506. destinationLength := LEN(destination);
  507. sourceLength := LEN(source);
  508. IF destinationLength < sourceLength THEN sourceLength := destinationLength END;
  509. SYSTEM.MOVE(ADDRESSOF(source[0]), ADDRESSOF(destination[0]), sourceLength)
  510. END CopyString;
  511. END ARMRuntime.