Mirror of CollapseOS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
6.0KB

  1. ( depends: cmp, parse
  2. Relink a dictionary by applying offsets to all word
  3. references in words of the "compiled" type.
  4. A typical usage of this unit would be to, right after a
  5. bootstrap-from-icore-from-source operation, identify the
  6. root word of the source part, probably "H@", and run
  7. " ' thatword RLDICT ". Then, take the resulting relinked
  8. binary, concatenate it to the boot binary, and write to
  9. boot media.
  10. LIMITATIONS
  11. This unit can't automatically detect all offsets needing
  12. relinking. This is a list of situations that aren't handled:
  13. Cells: It's not possible to know for sure whether a cellWord
  14. contains an address or a number. They are therefore not
  15. automatically relinked. You have to manually relink each of
  16. them with RLCELL. In the case of a DOES> word, PFA+2, which
  17. is always an offset, is automatically relinked, but not
  18. PFA+0.
  19. )
  20. ( Skip atom, considering special atom types. )
  21. ( a -- a+n )
  22. : ASKIP
  23. DUP @ ( a n )
  24. ( ?br or br or NUMBER )
  25. DUP <>{ 0x70 &= 0x58 |= 0x20 |= 0x24 |= <>}
  26. IF DROP 4 + EXIT THEN
  27. ( regular word )
  28. 0x22 = NOT IF 2 + EXIT THEN
  29. ( it's a lit, skip to null char )
  30. ( a )
  31. 1 + ( we skip by 2, but the loop below is pre-inc... )
  32. BEGIN 1 + DUP C@ NOT UNTIL
  33. ( skip null char )
  34. 1 +
  35. ;
  36. ( Get word addr, starting at name's address )
  37. : '< ' DUP WHLEN - ;
  38. ( Relink atom at a, applying offset o with limit ol.
  39. Returns a, appropriately skipped.
  40. )
  41. ( a o ol -- a+n )
  42. : RLATOM
  43. ROT ( o ol a )
  44. DUP @ ( o ol a n )
  45. DUP 0x24 = IF
  46. ( 0x24 is an addrWord, which should be offsetted in
  47. the same way that a regular word would. To achieve
  48. this, we skip ASKIP and instead of skipping 4 bytes
  49. like a numberWord, we skip only 2, which means that
  50. our number will be treated like a regular wordref.
  51. )
  52. DROP
  53. 2 + ( o ol a+2 )
  54. ROT ROT 2DROP ( a )
  55. EXIT
  56. THEN
  57. ROT ( o a n ol )
  58. < IF ( under limit, do nothing )
  59. SWAP DROP ( a )
  60. ELSE
  61. ( o a )
  62. SWAP OVER @ ( a o n )
  63. -^ ( a n-o )
  64. OVER ! ( a )
  65. THEN
  66. ASKIP
  67. ;
  68. ( Relink a word with specified offset. If it's not of the type
  69. "compiled word", ignore. If it is, advance in word until a2
  70. is met, and for each word that is above ol, reduce that
  71. reference by o.
  72. Arguments: a1: wordref a2: word end addr o: offset to apply
  73. ol: offset limit. don't apply on refs under it.
  74. )
  75. ( ol o a1 a2 -- )
  76. : RLWORD
  77. SWAP DUP @ ( ol o a2 a1 n )
  78. ( 0e == compiledWord, 2b == doesWord )
  79. DUP <>{ 0x0e &= 0x2b |= <>} NOT IF
  80. ( unwind all args )
  81. 2DROP 2DROP
  82. EXIT
  83. THEN
  84. ( we have a compiled word or doesWord, proceed )
  85. ( doesWord is processed exactly like a compiledWord, but
  86. starts 2 bytes further. )
  87. ( ol o a2 a1 n )
  88. 0x2b = IF 2 + THEN
  89. ( ol o a2 a1 )
  90. 2 + ( ol o a2 a1+2 )
  91. BEGIN ( ol o a2 a1 )
  92. 2OVER ( ol o a2 a1 ol o )
  93. SWAP ( ol o a2 a1 o ol )
  94. RLATOM ( ol o a2 a+n )
  95. 2DUP < IF ABORT THEN ( Something is very wrong )
  96. 2DUP = ( ol o a2 a+n f )
  97. IF
  98. ( unwind )
  99. 2DROP 2DROP
  100. EXIT
  101. THEN
  102. AGAIN
  103. ;
  104. ( TODO implement RLCELL )
  105. ( Copy dict from target wordref, including header, up to HERE.
  106. We're going to compact the space between that word and its
  107. prev word. To do this, we're copying this whole memory area
  108. in HERE and then iterate through that copied area and call
  109. RLWORD on each word. That results in a dict that can be
  110. concatenated to target's prev entry in a more compact way.
  111. This copy of data doesn't allocate anything, so H@ doesn't
  112. move. Moreover, we reserve 4 bytes at H@ to write our target
  113. and offset because otherwise, things get too complicated
  114. with the PSP.
  115. The output of this word is 3 numbers: top copied address,
  116. top copied CURRENT, and then the beginning of the copied dict
  117. at the end to indicate that we're finished processing.
  118. )
  119. ( target -- )
  120. : RLDICT
  121. ( First of all, let's get our offset. It's easy, it's
  122. target's prev field, which is already an offset, minus
  123. its name length. We expect, in RLDICT that a target's
  124. prev word is a "hook word", that is, an empty word. )
  125. ( H@ == target )
  126. DUP H@ !
  127. DUP 1 - C@ 0x7f AND ( t namelen )
  128. SWAP 3 - @ ( namelen po )
  129. -^ ( o )
  130. ( H@+2 == offset )
  131. H@ 2 + ! ( )
  132. ( We have our offset, now let's copy our memory chunk )
  133. H@ @ DUP WHLEN - ( src )
  134. DUP H@ -^ ( src u )
  135. DUP ROT SWAP ( u src u )
  136. H@ 4 + ( u src u dst )
  137. SWAP ( u src dst u )
  138. MOVE ( u )
  139. ( Now, let's iterate that dict down )
  140. ( wr == wordref we == word end )
  141. ( To get our wr and we, we use H@ and CURRENT, which we
  142. offset by u+4. +4 before, remember, we're using 4 bytes
  143. as variable space. )
  144. 4 + ( u+4 )
  145. DUP H@ + ( u we )
  146. DUP .X LF
  147. SWAP CURRENT @ + ( we wr )
  148. DUP .X LF
  149. BEGIN ( we wr )
  150. DUP ROT ( wr wr we )
  151. ( call RLWORD. we need a sig: ol o wr we )
  152. H@ @ ( wr wr we ol )
  153. H@ 2 + @ ( wr wr we ol o )
  154. 2SWAP ( wr ol o wr we )
  155. RLWORD ( wr )
  156. ( wr becomes wr's prev and we is wr-header )
  157. DUP ( wr wr )
  158. PREV ( oldwr newwr )
  159. SWAP ( wr oldwr )
  160. DUP WHLEN - ( wr we )
  161. SWAP ( we wr )
  162. ( Are we finished? We're finished if wr-4 <= H@ )
  163. DUP 4 - H@ <=
  164. UNTIL
  165. H@ 4 + .X LF
  166. ;
  167. ( Relink a regular Forth full interpreter. )
  168. : RLCORE
  169. LIT< H@ (find) DROP RLDICT
  170. ;