RTL.ob07 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2021, 2023, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE RTL;
  7. IMPORT SYSTEM, API;
  8. CONST
  9. minint = ROR(1, 1);
  10. WORD = API.BIT_DEPTH DIV 8;
  11. VAR
  12. name, types, tcount: INTEGER;
  13. PROCEDURE [stdcall] _move* (bytes, dest, source: INTEGER);
  14. BEGIN
  15. SYSTEM.CODE(
  16. 08BH, 045H, 008H, (* mov eax, dword [ebp + 8] *)
  17. 085H, 0C0H, (* test eax, eax *)
  18. 07EH, 019H, (* jle L *)
  19. 0FCH, (* cld *)
  20. 057H, (* push edi *)
  21. 056H, (* push esi *)
  22. 08BH, 075H, 010H, (* mov esi, dword [ebp + 16] *)
  23. 08BH, 07DH, 00CH, (* mov edi, dword [ebp + 12] *)
  24. 089H, 0C1H, (* mov ecx, eax *)
  25. 0C1H, 0E9H, 002H, (* shr ecx, 2 *)
  26. 0F3H, 0A5H, (* rep movsd *)
  27. 089H, 0C1H, (* mov ecx, eax *)
  28. 083H, 0E1H, 003H, (* and ecx, 3 *)
  29. 0F3H, 0A4H, (* rep movsb *)
  30. 05EH, (* pop esi *)
  31. 05FH (* pop edi *)
  32. (* L: *)
  33. )
  34. END _move;
  35. PROCEDURE [stdcall] _arrcpy* (base_size, len_dst, dst, len_src, src: INTEGER): BOOLEAN;
  36. VAR
  37. res: BOOLEAN;
  38. BEGIN
  39. IF len_src > len_dst THEN
  40. res := FALSE
  41. ELSE
  42. _move(len_src * base_size, dst, src);
  43. res := TRUE
  44. END
  45. RETURN res
  46. END _arrcpy;
  47. PROCEDURE [stdcall] _strcpy* (chr_size, len_src, src, len_dst, dst: INTEGER);
  48. BEGIN
  49. _move(MIN(len_dst, len_src) * chr_size, dst, src)
  50. END _strcpy;
  51. PROCEDURE [stdcall] _rot* (Len, Ptr: INTEGER);
  52. BEGIN
  53. SYSTEM.CODE(
  54. 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- Len *)
  55. 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- Ptr *)
  56. 049H, (* dec ecx *)
  57. 053H, (* push ebx *)
  58. 08BH, 018H, (* mov ebx, dword [eax] *)
  59. (* L: *)
  60. 08BH, 050H, 004H, (* mov edx, dword [eax + 4] *)
  61. 089H, 010H, (* mov dword [eax], edx *)
  62. 083H, 0C0H, 004H, (* add eax, 4 *)
  63. 049H, (* dec ecx *)
  64. 075H, 0F5H, (* jnz L *)
  65. 089H, 018H, (* mov dword [eax], ebx *)
  66. 05BH, (* pop ebx *)
  67. 05DH, (* pop ebp *)
  68. 0C2H, 008H, 000H (* ret 8 *)
  69. )
  70. END _rot;
  71. PROCEDURE [stdcall] _set* (b, a: INTEGER); (* {a..b} -> eax *)
  72. BEGIN
  73. SYSTEM.CODE(
  74. 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- b *)
  75. 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- a *)
  76. 039H, 0C8H, (* cmp eax, ecx *)
  77. 07FH, 033H, (* jg L1 *)
  78. 083H, 0F8H, 01FH, (* cmp eax, 31 *)
  79. 07FH, 02EH, (* jg L1 *)
  80. 085H, 0C9H, (* test ecx, ecx *)
  81. 07CH, 02AH, (* jl L1 *)
  82. 083H, 0F9H, 01FH, (* cmp ecx, 31 *)
  83. 07EH, 005H, (* jle L3 *)
  84. 0B9H, 01FH, 000H, 000H, 000H, (* mov ecx, 31 *)
  85. (* L3: *)
  86. 085H, 0C0H, (* test eax, eax *)
  87. 07DH, 002H, (* jge L2 *)
  88. 031H, 0C0H, (* xor eax, eax *)
  89. (* L2: *)
  90. 089H, 0CAH, (* mov edx, ecx *)
  91. 029H, 0C2H, (* sub edx, eax *)
  92. 0B8H, 000H, 000H, 000H, 080H, (* mov eax, 0x80000000 *)
  93. 087H, 0CAH, (* xchg edx, ecx *)
  94. 0D3H, 0F8H, (* sar eax, cl *)
  95. 087H, 0CAH, (* xchg edx, ecx *)
  96. 083H, 0E9H, 01FH, (* sub ecx, 31 *)
  97. 0F7H, 0D9H, (* neg ecx *)
  98. 0D3H, 0E8H, (* shr eax, cl *)
  99. 05DH, (* pop ebp *)
  100. 0C2H, 008H, 000H, (* ret 8 *)
  101. (* L1: *)
  102. 031H, 0C0H, (* xor eax, eax *)
  103. 05DH, (* pop ebp *)
  104. 0C2H, 008H, 000H (* ret 8 *)
  105. )
  106. END _set;
  107. PROCEDURE [stdcall] _set1* (a: INTEGER); (* {a} -> eax *)
  108. BEGIN
  109. SYSTEM.CODE(
  110. 031H, 0C0H, (* xor eax, eax *)
  111. 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- a *)
  112. 083H, 0F9H, 01FH, (* cmp ecx, 31 *)
  113. 077H, 003H, (* ja L *)
  114. 00FH, 0ABH, 0C8H (* bts eax, ecx *)
  115. (* L: *)
  116. )
  117. END _set1;
  118. PROCEDURE [stdcall] _divmod* (y, x: INTEGER); (* (x div y) -> eax; (x mod y) -> edx *)
  119. BEGIN
  120. SYSTEM.CODE(
  121. 053H, (* push ebx *)
  122. 08BH, 045H, 00CH, (* mov eax, dword [ebp + 12] *) (* eax <- x *)
  123. 031H, 0D2H, (* xor edx, edx *)
  124. 085H, 0C0H, (* test eax, eax *)
  125. 074H, 018H, (* je L2 *)
  126. 07FH, 002H, (* jg L1 *)
  127. 0F7H, 0D2H, (* not edx *)
  128. (* L1: *)
  129. 089H, 0C3H, (* mov ebx, eax *)
  130. 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *) (* ecx <- y *)
  131. 0F7H, 0F9H, (* idiv ecx *)
  132. 085H, 0D2H, (* test edx, edx *)
  133. 074H, 009H, (* je L2 *)
  134. 031H, 0CBH, (* xor ebx, ecx *)
  135. 085H, 0DBH, (* test ebx, ebx *)
  136. 07DH, 003H, (* jge L2 *)
  137. 048H, (* dec eax *)
  138. 001H, 0CAH, (* add edx, ecx *)
  139. (* L2: *)
  140. 05BH (* pop ebx *)
  141. )
  142. END _divmod;
  143. PROCEDURE [stdcall] _new* (t, size: INTEGER; VAR ptr: INTEGER);
  144. BEGIN
  145. ptr := API._NEW(size);
  146. IF ptr # 0 THEN
  147. SYSTEM.PUT(ptr, t);
  148. INC(ptr, WORD)
  149. END
  150. END _new;
  151. PROCEDURE [stdcall] _dispose* (VAR ptr: INTEGER);
  152. BEGIN
  153. IF ptr # 0 THEN
  154. ptr := API._DISPOSE(ptr - WORD)
  155. END
  156. END _dispose;
  157. PROCEDURE [stdcall] _length* (len, str: INTEGER);
  158. BEGIN
  159. SYSTEM.CODE(
  160. 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *)
  161. 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *)
  162. 048H, (* dec eax *)
  163. (* L1: *)
  164. 040H, (* inc eax *)
  165. 080H, 038H, 000H, (* cmp byte [eax], 0 *)
  166. 074H, 003H, (* jz L2 *)
  167. 0E2H, 0F8H, (* loop L1 *)
  168. 040H, (* inc eax *)
  169. (* L2: *)
  170. 02BH, 045H, 00CH (* sub eax, dword [ebp + 0Ch] *)
  171. )
  172. END _length;
  173. PROCEDURE [stdcall] _lengthw* (len, str: INTEGER);
  174. BEGIN
  175. SYSTEM.CODE(
  176. 08BH, 045H, 00CH, (* mov eax, dword [ebp + 0Ch] *)
  177. 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 08h] *)
  178. 048H, (* dec eax *)
  179. 048H, (* dec eax *)
  180. (* L1: *)
  181. 040H, (* inc eax *)
  182. 040H, (* inc eax *)
  183. 066H, 083H, 038H, 000H, (* cmp word [eax], 0 *)
  184. 074H, 004H, (* jz L2 *)
  185. 0E2H, 0F6H, (* loop L1 *)
  186. 040H, (* inc eax *)
  187. 040H, (* inc eax *)
  188. (* L2: *)
  189. 02BH, 045H, 00CH, (* sub eax, dword [ebp + 0Ch] *)
  190. 0D1H, 0E8H (* shr eax, 1 *)
  191. )
  192. END _lengthw;
  193. PROCEDURE [stdcall] strncmp (a, b, n: INTEGER): INTEGER;
  194. BEGIN
  195. SYSTEM.CODE(
  196. 056H, (* push esi *)
  197. 057H, (* push edi *)
  198. 053H, (* push ebx *)
  199. 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *)
  200. 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *)
  201. 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *)
  202. 031H, 0C9H, (* xor ecx, ecx *)
  203. 031H, 0D2H, (* xor edx, edx *)
  204. 0B8H,
  205. 000H, 000H, 000H, 080H, (* mov eax, minint *)
  206. (* L1: *)
  207. 085H, 0DBH, (* test ebx, ebx *)
  208. 07EH, 017H, (* jle L3 *)
  209. 08AH, 00EH, (* mov cl, byte[esi] *)
  210. 08AH, 017H, (* mov dl, byte[edi] *)
  211. 046H, (* inc esi *)
  212. 047H, (* inc edi *)
  213. 04BH, (* dec ebx *)
  214. 039H, 0D1H, (* cmp ecx, edx *)
  215. 074H, 006H, (* je L2 *)
  216. 089H, 0C8H, (* mov eax, ecx *)
  217. 029H, 0D0H, (* sub eax, edx *)
  218. 0EBH, 006H, (* jmp L3 *)
  219. (* L2: *)
  220. 085H, 0C9H, (* test ecx, ecx *)
  221. 075H, 0E7H, (* jne L1 *)
  222. 031H, 0C0H, (* xor eax, eax *)
  223. (* L3: *)
  224. 05BH, (* pop ebx *)
  225. 05FH, (* pop edi *)
  226. 05EH, (* pop esi *)
  227. 05DH, (* pop ebp *)
  228. 0C2H, 00CH, 000H (* ret 12 *)
  229. )
  230. RETURN 0
  231. END strncmp;
  232. PROCEDURE [stdcall] strncmpw (a, b, n: INTEGER): INTEGER;
  233. BEGIN
  234. SYSTEM.CODE(
  235. 056H, (* push esi *)
  236. 057H, (* push edi *)
  237. 053H, (* push ebx *)
  238. 08BH, 075H, 008H, (* mov esi, dword[ebp + 8]; esi <- a *)
  239. 08BH, 07DH, 00CH, (* mov edi, dword[ebp + 12]; edi <- b *)
  240. 08BH, 05DH, 010H, (* mov ebx, dword[ebp + 16]; ebx <- n *)
  241. 031H, 0C9H, (* xor ecx, ecx *)
  242. 031H, 0D2H, (* xor edx, edx *)
  243. 0B8H,
  244. 000H, 000H, 000H, 080H, (* mov eax, minint *)
  245. (* L1: *)
  246. 085H, 0DBH, (* test ebx, ebx *)
  247. 07EH, 01BH, (* jle L3 *)
  248. 066H, 08BH, 00EH, (* mov cx, word[esi] *)
  249. 066H, 08BH, 017H, (* mov dx, word[edi] *)
  250. 046H, (* inc esi *)
  251. 046H, (* inc esi *)
  252. 047H, (* inc edi *)
  253. 047H, (* inc edi *)
  254. 04BH, (* dec ebx *)
  255. 039H, 0D1H, (* cmp ecx, edx *)
  256. 074H, 006H, (* je L2 *)
  257. 089H, 0C8H, (* mov eax, ecx *)
  258. 029H, 0D0H, (* sub eax, edx *)
  259. 0EBH, 006H, (* jmp L3 *)
  260. (* L2: *)
  261. 085H, 0C9H, (* test ecx, ecx *)
  262. 075H, 0E3H, (* jne L1 *)
  263. 031H, 0C0H, (* xor eax, eax *)
  264. (* L3: *)
  265. 05BH, (* pop ebx *)
  266. 05FH, (* pop edi *)
  267. 05EH, (* pop esi *)
  268. 05DH, (* pop ebp *)
  269. 0C2H, 00CH, 000H (* ret 12 *)
  270. )
  271. RETURN 0
  272. END strncmpw;
  273. PROCEDURE [stdcall] _strcmp* (op, len2, str2, len1, str1: INTEGER): BOOLEAN;
  274. VAR
  275. res: INTEGER;
  276. bRes: BOOLEAN;
  277. c: CHAR;
  278. BEGIN
  279. res := strncmp(str1, str2, MIN(len1, len2));
  280. IF res = minint THEN
  281. IF len1 > len2 THEN
  282. SYSTEM.GET(str1 + len2, c);
  283. res := ORD(c)
  284. ELSIF len1 < len2 THEN
  285. SYSTEM.GET(str2 + len1, c);
  286. res := -ORD(c)
  287. ELSE
  288. res := 0
  289. END
  290. END;
  291. CASE op OF
  292. |0: bRes := res = 0
  293. |1: bRes := res # 0
  294. |2: bRes := res < 0
  295. |3: bRes := res <= 0
  296. |4: bRes := res > 0
  297. |5: bRes := res >= 0
  298. END
  299. RETURN bRes
  300. END _strcmp;
  301. PROCEDURE [stdcall] _strcmpw* (op, len2, str2, len1, str1: INTEGER): BOOLEAN;
  302. VAR
  303. res: INTEGER;
  304. bRes: BOOLEAN;
  305. c: WCHAR;
  306. BEGIN
  307. res := strncmpw(str1, str2, MIN(len1, len2));
  308. IF res = minint THEN
  309. IF len1 > len2 THEN
  310. SYSTEM.GET(str1 + len2 * 2, c);
  311. res := ORD(c)
  312. ELSIF len1 < len2 THEN
  313. SYSTEM.GET(str2 + len1 * 2, c);
  314. res := -ORD(c)
  315. ELSE
  316. res := 0
  317. END
  318. END;
  319. CASE op OF
  320. |0: bRes := res = 0
  321. |1: bRes := res # 0
  322. |2: bRes := res < 0
  323. |3: bRes := res <= 0
  324. |4: bRes := res > 0
  325. |5: bRes := res >= 0
  326. END
  327. RETURN bRes
  328. END _strcmpw;
  329. PROCEDURE PCharToStr (pchar: INTEGER; VAR s: ARRAY OF CHAR);
  330. VAR
  331. c: CHAR;
  332. i: INTEGER;
  333. BEGIN
  334. i := 0;
  335. REPEAT
  336. SYSTEM.GET(pchar, c);
  337. s[i] := c;
  338. INC(pchar);
  339. INC(i)
  340. UNTIL c = 0X
  341. END PCharToStr;
  342. PROCEDURE IntToStr (x: INTEGER; VAR str: ARRAY OF CHAR);
  343. VAR
  344. i, a: INTEGER;
  345. BEGIN
  346. i := 0;
  347. a := x;
  348. REPEAT
  349. INC(i);
  350. a := a DIV 10
  351. UNTIL a = 0;
  352. str[i] := 0X;
  353. REPEAT
  354. DEC(i);
  355. str[i] := CHR(x MOD 10 + ORD("0"));
  356. x := x DIV 10
  357. UNTIL x = 0
  358. END IntToStr;
  359. PROCEDURE append (VAR s1: ARRAY OF CHAR; s2: ARRAY OF CHAR);
  360. VAR
  361. n1, n2: INTEGER;
  362. BEGIN
  363. n1 := LENGTH(s1);
  364. n2 := LENGTH(s2);
  365. ASSERT(n1 + n2 < LEN(s1));
  366. SYSTEM.MOVE(SYSTEM.ADR(s2[0]), SYSTEM.ADR(s1[n1]), n2);
  367. s1[n1 + n2] := 0X
  368. END append;
  369. PROCEDURE [stdcall] _error* (modnum, _module, err, line: INTEGER);
  370. VAR
  371. s, temp: ARRAY 1024 OF CHAR;
  372. BEGIN
  373. CASE err OF
  374. | 1: s := "assertion failure"
  375. | 2: s := "NIL dereference"
  376. | 3: s := "bad divisor"
  377. | 4: s := "NIL procedure call"
  378. | 5: s := "type guard error"
  379. | 6: s := "index out of range"
  380. | 7: s := "invalid CASE"
  381. | 8: s := "array assignment error"
  382. | 9: s := "CHR out of range"
  383. |10: s := "WCHR out of range"
  384. |11: s := "BYTE out of range"
  385. END;
  386. append(s, API.eol + "module: "); PCharToStr(_module, temp); append(s, temp);
  387. append(s, API.eol + "line: "); IntToStr(line, temp); append(s, temp);
  388. API.DebugMsg(SYSTEM.ADR(s[0]), name);
  389. API.exit_thread(0)
  390. END _error;
  391. PROCEDURE [stdcall] _isrec* (t0, t1, r: INTEGER): BOOLEAN;
  392. BEGIN
  393. (* r IS t0 *)
  394. WHILE (t1 # 0) & (t1 # t0) DO
  395. SYSTEM.GET(types + t1 * WORD, t1)
  396. END
  397. RETURN t1 = t0
  398. END _isrec;
  399. PROCEDURE [stdcall] _is* (t0, p: INTEGER): BOOLEAN;
  400. VAR
  401. t1: INTEGER;
  402. BEGIN
  403. (* p IS t0 *)
  404. IF p # 0 THEN
  405. SYSTEM.GET(p - WORD, t1);
  406. WHILE (t1 # 0) & (t1 # t0) DO
  407. SYSTEM.GET(types + t1 * WORD, t1)
  408. END
  409. ELSE
  410. t1 := -1
  411. END
  412. RETURN t1 = t0
  413. END _is;
  414. PROCEDURE [stdcall] _guardrec* (t0, t1: INTEGER): BOOLEAN;
  415. BEGIN
  416. (* r:t1 IS t0 *)
  417. WHILE (t1 # 0) & (t1 # t0) DO
  418. SYSTEM.GET(types + t1 * WORD, t1)
  419. END
  420. RETURN t1 = t0
  421. END _guardrec;
  422. PROCEDURE [stdcall] _guard* (t0, p: INTEGER): BOOLEAN;
  423. VAR
  424. t1: INTEGER;
  425. BEGIN
  426. (* p IS t0 *)
  427. SYSTEM.GET(p, p);
  428. IF p # 0 THEN
  429. SYSTEM.GET(p - WORD, t1);
  430. WHILE (t1 # t0) & (t1 # 0) DO
  431. SYSTEM.GET(types + t1 * WORD, t1)
  432. END
  433. ELSE
  434. t1 := t0
  435. END
  436. RETURN t1 = t0
  437. END _guard;
  438. PROCEDURE [stdcall] _dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER;
  439. RETURN API.dllentry(hinstDLL, fdwReason, lpvReserved)
  440. END _dllentry;
  441. PROCEDURE [stdcall] _sofinit*;
  442. BEGIN
  443. API.sofinit
  444. END _sofinit;
  445. PROCEDURE [stdcall] _exit* (code: INTEGER);
  446. BEGIN
  447. API.exit(code)
  448. END _exit;
  449. PROCEDURE [stdcall] _init* (modname: INTEGER; _tcount, _types: INTEGER; code, param: INTEGER);
  450. BEGIN
  451. SYSTEM.CODE(09BH, 0DBH, 0E3H); (* finit *)
  452. API.init(param, code);
  453. tcount := _tcount;
  454. types := _types;
  455. name := modname
  456. END _init;
  457. END RTL.