utils.inc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. ; vim:ft=fasm:
  2. ;include 'align.inc'
  3. include 'inline.inc'
  4. if ~ defined utils
  5. restore utils
  6. define utils yes
  7. struc static_string str&
  8. . db str
  9. .len = $ - .
  10. end struc
  11. namespace mov_args
  12. ;;; 8 ;;;
  13. reg8_1 = rdi
  14. reg8_2 = rsi
  15. reg8_3 = rdx
  16. reg8_4 = r10
  17. reg8_5 = r9
  18. reg8_6 = r8
  19. ;;; 4 ;;;
  20. reg4_1 = edi
  21. reg4_2 = esi
  22. reg4_3 = edx
  23. reg4_4 = r10d
  24. reg4_5 = r9d
  25. reg4_6 = r8d
  26. ;;; 2 ;;;
  27. reg2_1 = di
  28. reg2_2 = si
  29. reg2_3 = dx
  30. reg2_4 = r10w
  31. reg2_5 = r9w
  32. reg2_6 = r8w
  33. ;;; 1 ;;;
  34. reg1_1 = dil
  35. reg1_2 = sil
  36. reg1_3 = dl
  37. reg1_4 = r10b
  38. reg1_5 = r9b
  39. reg1_6 = r8b
  40. max_args = 6
  41. end namespace
  42. macro mov_args args&
  43. match any, args
  44. iterate arg, args
  45. if % > mov_args.max_args
  46. err 'too many args: maximum is ', '0' + mov_args.max_args
  47. end if
  48. local skip, size
  49. skip = 0
  50. x86.parse_operand@src arg
  51. if @src.size = 0
  52. size = 8
  53. else
  54. size = @src.size
  55. end if
  56. local current_arg
  57. repeat 1, _i:(%)
  58. repeat 1, _size:(size)
  59. current_arg = mov_args.reg#_size#_#_i
  60. end repeat
  61. end repeat
  62. if @src.type = 'reg'
  63. if arg eq current_arg
  64. skip = 1
  65. end if
  66. end if
  67. if skip = 0
  68. mov current_arg, arg
  69. end if
  70. end iterate
  71. end match
  72. end macro
  73. macro do_syscall sys*,args&
  74. mov_args args
  75. mov rax, sys
  76. syscall
  77. end macro
  78. macro call_args fn*, args&
  79. mov_args args
  80. call fn
  81. end macro
  82. ; TODO: automatically define macro for proc (`proc func ...` should define `func` macro and `func_impl` function)
  83. macro proc name*
  84. macro end?.proc!
  85. .end:
  86. ret
  87. end if
  88. purge end?.proc
  89. end macro
  90. name:
  91. if used name
  92. end macro
  93. macro using_regs regs&
  94. macro end?.using_regs!
  95. calminstruction reverse_pop reg&
  96. local tmp, stack, cmd
  97. collect:
  98. match tmp=,reg, reg
  99. take stack, tmp
  100. jyes collect
  101. execute:
  102. arrange cmd, =pop reg
  103. assemble cmd
  104. take reg, stack
  105. jyes execute
  106. end calminstruction
  107. match any, regs
  108. reverse_pop regs
  109. end match
  110. purge reverse_pop
  111. purge end?.using_regs
  112. end macro
  113. match any, regs
  114. iterate reg, regs
  115. x86.parse_operand@src reg
  116. if ~ @src.type = 'reg'
  117. err '"', `reg, '" is not register'
  118. end if
  119. push reg
  120. end iterate
  121. end match
  122. end macro
  123. inlinemacro sum_irpv arr
  124. local res
  125. res = 0
  126. irpv i, arr
  127. res = res + i
  128. end irpv
  129. return = res
  130. end inlinemacro
  131. macro stack_frame size*
  132. local aligned_size
  133. local _stack_frame
  134. virtual at 0
  135. _stack_frame rb size
  136. align 16
  137. aligned_size = $
  138. end virtual
  139. local used_stack_arr, used_stack, stack_start
  140. stack_start = rbp
  141. define used_stack stack_start
  142. inlinemacro stack_frame.use use_size*
  143. local sz, _stack_frame
  144. virtual at 0
  145. _stack_frame rb use_size
  146. align 8
  147. sz = $
  148. end virtual
  149. used_stack_arr equ (sz)
  150. local sum
  151. sum = sum_irpv(used_stack_arr)
  152. if sum > (aligned_size)
  153. repeat 1, _sum:(sum)
  154. repeat 1, _size:(aligned_size)
  155. err 'used more than frame size (wanted: ', `_sum, ', frame size: ', `_size, ')'
  156. end repeat
  157. end repeat
  158. end if
  159. define used_stack used_stack - (sz)
  160. return = (used_stack)
  161. end inlinemacro
  162. macro end?.stack_frame!
  163. lea rsp, [rsp + aligned_size]
  164. pop rbp
  165. purge end?.stack_frame
  166. ; FIXME: `stack_frame.use` still defined after `end stack_frame`
  167. purge stack_frame.use
  168. end macro
  169. push rbp
  170. mov rbp, rsp
  171. lea rsp, [rsp - aligned_size]
  172. end macro
  173. ; macro struct? name
  174. ; macro end?.struct?!
  175. ; end namespace
  176. ; esc end struc
  177. ; virtual at 0
  178. ; name name
  179. ; align16 sizeof.name, $
  180. ; end virtual
  181. ; purge end?.struct?
  182. ; end macro
  183. ; esc struc name
  184. ; label . : sizeof.name
  185. ; namespace .
  186. ; end macro
  187. inlinemacro align_comptime n*, to*
  188. return = ((n + to - 1) and (not (to - 1)))
  189. end inlinemacro
  190. macro mov2mem dst*, src*, tmp_reg:rax
  191. mov tmp_reg, src
  192. mov dst, tmp_reg
  193. end macro
  194. macro enum name
  195. local counter
  196. counter = 0
  197. namespace name
  198. macro ? line&
  199. match =end =enum, line
  200. end namespace
  201. purge ?
  202. else match name==n, line
  203. name := n
  204. counter = n + 1
  205. else match name, line
  206. name := counter
  207. counter = counter + 1
  208. else match any, line
  209. err "syntax error"
  210. end match
  211. end macro
  212. end macro
  213. ;end namespace
  214. end if