utils.g 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. # This file is part of asmc, a bootstrapping OS with minimal seed
  2. # Copyright (C) 2018 Giovanni Mascellani <gio@debian.org>
  3. # https://gitlab.com/giomasce/asmc
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. # You should have received a copy of the GNU General Public License
  13. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. fun resolve_symbol 3 {
  15. $loc
  16. $nameptr
  17. $offptr
  18. @loc 2 param = ;
  19. @nameptr 1 param = ;
  20. @offptr 0 param = ;
  21. $i
  22. @i 0 = ;
  23. offptr 0 = ;
  24. nameptr "<unknown>" = ;
  25. while i __symbol_num < {
  26. $this_loc
  27. @this_loc __symbol_locs i 4 * + ** = ;
  28. $this_name
  29. @this_name __symbol_names i __max_symbol_name_len * + = ;
  30. if this_loc loc <= this_loc offptr ** >= && {
  31. offptr this_loc = ;
  32. nameptr this_name = ;
  33. }
  34. @i i 1 + = ;
  35. }
  36. offptr loc offptr ** - = ;
  37. }
  38. fun dump_frame 1 {
  39. $frame_ptr
  40. @frame_ptr 0 param = ;
  41. if frame_ptr 0 == {
  42. ret ;
  43. }
  44. $prev_frame_ptr
  45. $ret_addr
  46. @prev_frame_ptr frame_ptr ** = ;
  47. @ret_addr frame_ptr 4 + ** = ;
  48. $name
  49. $off
  50. ret_addr @name @off resolve_symbol ;
  51. "Frame pointer: " 1 platform_log ;
  52. frame_ptr itoa 1 platform_log ;
  53. "; previous frame pointer: " 1 platform_log ;
  54. prev_frame_ptr itoa 1 platform_log ;
  55. "; return address: " 1 platform_log ;
  56. ret_addr itoa 1 platform_log ;
  57. " (" 1 platform_log ;
  58. name 1 platform_log ;
  59. "+" 1 platform_log ;
  60. off itoa 1 platform_log ;
  61. ")\n" 1 platform_log ;
  62. prev_frame_ptr dump_frame ;
  63. }
  64. fun dump_stacktrace 0 {
  65. $frame_ptr
  66. @frame_ptr __frame_ptr = ;
  67. frame_ptr dump_frame ;
  68. }
  69. fun read_ret_instr 0 {
  70. __ret_instr ret ;
  71. }
  72. $assert_pos
  73. fun set_assert_pos 1 {
  74. @assert_pos 0 param = ;
  75. }
  76. fun assert 1 {
  77. if 0 param ! {
  78. "\nASSERTION FAILED\n" 1 platform_log ;
  79. dump_stacktrace ;
  80. platform_panic ;
  81. }
  82. }
  83. fun assert_msg 2 {
  84. if 1 param ! {
  85. "\nASSERTION FAILED at line " 1 platform_log ;
  86. assert_pos itoa 1 platform_log ;
  87. "\n" 1 platform_log ;
  88. 0 param 1 platform_log ;
  89. "\n" 1 platform_log ;
  90. dump_stacktrace ;
  91. platform_panic ;
  92. }
  93. }
  94. fun assert_msg_str 3 {
  95. if 2 param ! {
  96. "\nASSERTION FAILED at line " 1 platform_log ;
  97. assert_pos itoa 1 platform_log ;
  98. "\n" 1 platform_log ;
  99. 1 param 1 platform_log ;
  100. "\n" 1 platform_log ;
  101. 0 param 1 platform_log ;
  102. "\n" 1 platform_log ;
  103. dump_stacktrace ;
  104. platform_panic ;
  105. }
  106. }
  107. fun assert_msg_int_int 4 {
  108. if 3 param ! {
  109. "\nASSERTION FAILED at line " 1 platform_log ;
  110. assert_pos itoa 1 platform_log ;
  111. "\n" 1 platform_log ;
  112. 2 param 1 platform_log ;
  113. "\n" 1 platform_log ;
  114. 1 param itoa 1 platform_log ;
  115. " " 1 platform_log ;
  116. 0 param itoa 1 platform_log ;
  117. "\n" 1 platform_log ;
  118. dump_stacktrace ;
  119. platform_panic ;
  120. }
  121. }
  122. fun min 2 {
  123. $x
  124. $y
  125. @x 0 param = ;
  126. @y 1 param = ;
  127. if x y < {
  128. x ret ;
  129. } else {
  130. y ret ;
  131. }
  132. }
  133. fun max 2 {
  134. $x
  135. $y
  136. @x 0 param = ;
  137. @y 1 param = ;
  138. if x y > {
  139. x ret ;
  140. } else {
  141. y ret ;
  142. }
  143. }
  144. fun take 2 {
  145. # The two parameters are actually perfectly interchangable...
  146. $ptr
  147. $off
  148. @ptr 1 param = ;
  149. @off 0 param = ;
  150. ptr off + ** ret ;
  151. }
  152. fun takec 2 {
  153. # The two parameters are actually perfectly interchangable...
  154. $ptr
  155. $off
  156. @ptr 1 param = ;
  157. @off 0 param = ;
  158. ptr off + **c ret ;
  159. }
  160. fun take_addr 2 {
  161. # The two parameters are actually perfectly interchangable...
  162. $ptr
  163. $off
  164. @ptr 1 param = ;
  165. @off 0 param = ;
  166. ptr off + ret ;
  167. }
  168. fun strcmp_case 2 {
  169. $s1
  170. $s2
  171. @s1 1 param = ;
  172. @s2 0 param = ;
  173. $diff
  174. @diff 'A' 'a' - = ;
  175. while 1 {
  176. $c1
  177. $c2
  178. @c1 s1 **c = ;
  179. @c2 s2 **c = ;
  180. if 'A' c1 <= c1 'Z' <= && {
  181. @c1 c1 diff - = ;
  182. }
  183. if 'A' c2 <= c2 'Z' <= && {
  184. @c2 c2 diff - = ;
  185. }
  186. if c1 c2 < {
  187. 0xffffffff ret ;
  188. }
  189. if c1 c2 > {
  190. 1 ret ;
  191. }
  192. if c1 0 == {
  193. 0 ret ;
  194. }
  195. @s1 s1 1 + = ;
  196. @s2 s2 1 + = ;
  197. }
  198. }
  199. fun isspace 1 {
  200. $c
  201. @c 0 param = ;
  202. if c '\n' == { 1 ret ; }
  203. if c '\r' == { 1 ret ; }
  204. if c '\f' == { 1 ret ; }
  205. if c '\v' == { 1 ret ; }
  206. if c '\t' == { 1 ret ; }
  207. if c ' ' == { 1 ret ; }
  208. 0 ret ;
  209. }
  210. fun strlen 1 {
  211. $ptr
  212. @ptr 0 param = ;
  213. $len
  214. @len 0 = ;
  215. while ptr **c 0 != {
  216. @len len 1 + = ;
  217. @ptr ptr 1 + = ;
  218. }
  219. len ret ;
  220. }
  221. fun strcmp 2 {
  222. $a
  223. $b
  224. @a 1 param = ;
  225. @b 0 param = ;
  226. while a **c b **c == {
  227. if a **c 0 == {
  228. 0 ret ;
  229. }
  230. @a a 1 + = ;
  231. @b b 1 + = ;
  232. }
  233. if a **c b **c < {
  234. 1 ret ;
  235. } else {
  236. 0 1 - ret ;
  237. }
  238. }
  239. fun strcpy 2 {
  240. $src
  241. $dest
  242. @src 1 param = ;
  243. @dest 0 param = ;
  244. while src **c 0 != {
  245. dest src **c =c ;
  246. @src src 1 + = ;
  247. @dest dest 1 + = ;
  248. }
  249. dest 0 =c ;
  250. }
  251. fun memcpy 3 {
  252. $n
  253. $src
  254. $dest
  255. @n 2 param = ;
  256. @src 1 param = ;
  257. @dest 0 param = ;
  258. while n 0 > {
  259. dest src **c =c ;
  260. @src src 1 + = ;
  261. @dest dest 1 + = ;
  262. @n n 1 - = ;
  263. }
  264. }
  265. fun strtol 3 {
  266. $ptr
  267. $endptr
  268. $base
  269. @ptr 2 param = ;
  270. @endptr 1 param = ;
  271. @base 0 param = ;
  272. $positive
  273. @positive 1 = ;
  274. $white
  275. @white 1 = ;
  276. $sign_found
  277. @sign_found 0 = ;
  278. $val
  279. @val 0 = ;
  280. while 1 {
  281. $c
  282. @c ptr **c = ;
  283. if c 0 == {
  284. if endptr 0 != {
  285. endptr ptr = ;
  286. }
  287. val positive * ret ;
  288. }
  289. base 0 >= base 1 != && base 36 <= && "strtol: wrong base" assert_msg ;
  290. if c isspace {
  291. white "strtol: wrong whitespace" assert_msg ;
  292. } else {
  293. @white 0 = ;
  294. if c '+' == {
  295. sign_found ! "strtol: more than one sign found" assert_msg ;
  296. @sign_found 1 = ;
  297. } else {
  298. if c '-' == {
  299. sign_found ! "strtol: more than one sign found" assert_msg ;
  300. @sign_found 1 = ;
  301. @positive 0 1 - = ;
  302. } else {
  303. @sign_found 1 = ;
  304. if base 0 == {
  305. if c '0' == {
  306. @base 8 = ;
  307. @ptr ptr 1 + = ;
  308. @c ptr **c = ;
  309. if c 'x' == c 'X' == || {
  310. @base 16 = ;
  311. @ptr ptr 1 + = ;
  312. @c ptr **c = ;
  313. }
  314. } else {
  315. @base 10 = ;
  316. }
  317. }
  318. if '0' c <= c '9' <= && {
  319. @c c '0' - = ;
  320. } else {
  321. if 'a' c <= c 'z' <= && {
  322. @c c 'a' - 10 + = ;
  323. } else {
  324. if 'A' c <= c 'Z' <= && {
  325. @c c 'A' - 10 + = ;
  326. } else {
  327. @c 0x100 = ;
  328. }
  329. }
  330. }
  331. if c base >= {
  332. if endptr 0 != {
  333. endptr ptr = ;
  334. }
  335. val positive * ret ;
  336. }
  337. @val val base * c + = ;
  338. }
  339. }
  340. }
  341. @ptr ptr 1 + = ;
  342. }
  343. }
  344. fun atoi 1 {
  345. $ptr
  346. @ptr 0 param = ;
  347. ptr 0 != "atoi: invalid null pointer" assert_msg ;
  348. ptr **c 0 != "atoi: invalid empty string" assert_msg ;
  349. $end
  350. $res
  351. @res ptr @end 0 strtol = ;
  352. # "atoi with input " 1 platform_log ;
  353. # ptr 1 platform_log ;
  354. # "\n" 1 platform_log ;
  355. end **c 0 == "atoi: invalid number" assert_msg ;
  356. res ret ;
  357. }
  358. fun atoi_c 1 {
  359. $ptr
  360. @ptr 0 param = ;
  361. ptr 0 != "atoi: invalid null pointer" assert_msg ;
  362. ptr **c 0 != "atoi: invalid empty string" assert_msg ;
  363. $end
  364. $res
  365. @res ptr @end 0 strtol = ;
  366. # "atoi with input " 1 platform_log ;
  367. # ptr 1 platform_log ;
  368. # "\n" 1 platform_log ;
  369. # Ignore L or LL suffixes
  370. if end **c 'L' == {
  371. @end end 1 + = ;
  372. }
  373. if end **c 'L' == {
  374. @end end 1 + = ;
  375. }
  376. end **c 0 == "atoi: invalid number" assert_msg ;
  377. res ret ;
  378. }
  379. fun memset 3 {
  380. $s
  381. $c
  382. $n
  383. @s 2 param = ;
  384. @c 1 param = ;
  385. @n 0 param = ;
  386. $i
  387. @i 0 = ;
  388. while i n < {
  389. s i + c =c ;
  390. @i i 1 + = ;
  391. }
  392. }
  393. fun memcheck 3 {
  394. $s
  395. $c
  396. $n
  397. @s 2 param = ;
  398. @c 1 param = ;
  399. @n 0 param = ;
  400. $i
  401. @i 0 = ;
  402. while i n < {
  403. if s i + **c c != {
  404. 0 ret ;
  405. }
  406. @i i 1 + = ;
  407. }
  408. 1 ret ;
  409. }
  410. fun dump_nibble 1 {
  411. $x
  412. @x 0 param = ;
  413. @x x 0xf & = ;
  414. if x 0 == { '0' 1 platform_write_char ; }
  415. if x 1 == { '1' 1 platform_write_char ; }
  416. if x 2 == { '2' 1 platform_write_char ; }
  417. if x 3 == { '3' 1 platform_write_char ; }
  418. if x 4 == { '4' 1 platform_write_char ; }
  419. if x 5 == { '5' 1 platform_write_char ; }
  420. if x 6 == { '6' 1 platform_write_char ; }
  421. if x 7 == { '7' 1 platform_write_char ; }
  422. if x 8 == { '8' 1 platform_write_char ; }
  423. if x 9 == { '9' 1 platform_write_char ; }
  424. if x 10 == { 'a' 1 platform_write_char ; }
  425. if x 11 == { 'b' 1 platform_write_char ; }
  426. if x 12 == { 'c' 1 platform_write_char ; }
  427. if x 13 == { 'd' 1 platform_write_char ; }
  428. if x 14 == { 'e' 1 platform_write_char ; }
  429. if x 15 == { 'f' 1 platform_write_char ; }
  430. }
  431. fun dump_byte 1 {
  432. $x
  433. @x 0 param = ;
  434. x 4 >> dump_nibble ;
  435. x dump_nibble ;
  436. ' ' 1 platform_write_char ;
  437. }
  438. fun dump_mem 2 {
  439. $ptr
  440. $size
  441. @ptr 1 param = ;
  442. @size 0 param = ;
  443. @size size ptr + = ;
  444. while ptr size < {
  445. ptr **c dump_byte ;
  446. @ptr ptr 1 + = ;
  447. }
  448. }
  449. fun get_char_type 1 {
  450. $x
  451. @x 0 param = ;
  452. if x '\n' == { 1 ret ; }
  453. if x '\t' == x ' ' == || x '\f' == || { 2 ret ; }
  454. if x '0' >= x '9' <= && x 'a' >= x 'z' <= && || x 'A' >= x 'Z' <= && || x '_' == || { 3 ret ; }
  455. 4 ret ;
  456. }