RTL.ob07 19 KB

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