fvm-as.scm 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. (import srfi-69)
  2. (import matchable)
  3. (import (chicken io))
  4. (import (chicken condition))
  5. (import (chicken keyword))
  6. (import (chicken process-context))
  7. (import (chicken port))
  8. (import (chicken blob))
  9. (import srfi-4)
  10. (define (make-opcode-table)
  11. (define opcodes
  12. '(sp ssp bp sbp pc rv srv
  13. imm
  14. ld8 ld16 ld32 ld
  15. st8 st16 st32 st
  16. dup pop swap over rot
  17. add sub div mul mod
  18. shr shl sar
  19. and or not
  20. bitand bitor xor invert
  21. gt lt ge le eq neq
  22. jmp jz jnz
  23. ret call syscall
  24. fadd fsub fmul fdiv
  25. fge fgt fle flt feq fneq
  26. fti itf
  27. exit))
  28. (define (assign-index opcodes idx ret)
  29. (if (null? opcodes)
  30. (reverse ret)
  31. (assign-index (cdr opcodes)
  32. (+ 1 idx)
  33. (cons (cons (car opcodes) idx) ret))))
  34. (alist->hash-table (assign-index opcodes 0 '())))
  35. (define opcode-table (make-opcode-table))
  36. (define pseudo-op-table
  37. (alist->hash-table
  38. '((rel . (pc add))
  39. (ldarg . ((imm 2) add (imm 8) mul bp add ld))
  40. (ldvar . ((imm -1) swap sub (imm 8) mul bp add ld))
  41. (starg . ((imm 2) add (imm 8) mul bp add st))
  42. (stvar . ((imm -1) swap sub (imm 8) mul bp add st)))))
  43. (define (is-pseudo-op? sym)
  44. (hash-table-ref/default pseudo-op-table sym #f))
  45. (define (is-op? sym)
  46. (hash-table-ref/default opcode-table sym #f))
  47. (define (is-tag? sym tag-table)
  48. (not (or (is-op? sym)
  49. (is-pseudo-op? sym)
  50. (not (hash-table-ref/default tag-table sym #f)))))
  51. (define (preprocess prog)
  52. (let loop ((lst prog) (ret '()))
  53. (match lst
  54. (() (reverse ret))
  55. (('imm num . r) (loop r (cons (list 'imm num) ret)))
  56. (((? number? x) . r) (loop r (cons (list 'imm x) ret)))
  57. ((x . r) (if (keyword? x)
  58. (loop r
  59. (cons (list 'tag
  60. (string->symbol (keyword->string x)))
  61. ret))
  62. (loop r (cons x ret)))))))
  63. (define (pseudo-op-pass prog)
  64. (define (add-to-prog oplist ret)
  65. (if (null? oplist)
  66. ret
  67. (add-to-prog (cdr oplist) (cons (car oplist) ret))))
  68. (define (impl prog ret)
  69. (if (null? prog)
  70. ret
  71. (let ((next-op (car prog)))
  72. (if (is-pseudo-op? next-op)
  73. (impl (cdr prog) (add-to-prog
  74. (hash-table-ref pseudo-op-table next-op)
  75. ret))
  76. (impl (cdr prog) (cons (car prog) ret))))))
  77. (reverse (impl prog '())))
  78. (define (is-tag-op? op)
  79. (and (list? op) (eq? 'tag (car op))))
  80. (define (is-imm-op? op)
  81. (and (list? op) (eq? 'imm (car op))))
  82. (define (tag-preprocess-pass prog)
  83. (define (is-local-tag? sym)
  84. (eq? #\. (string-ref (symbol->string sym) 0)))
  85. (define (compose-tag seg sym)
  86. (if (null? seg)
  87. sym
  88. (if (is-local-tag? sym)
  89. (string->symbol (string-append (symbol->string seg) (symbol->string sym)))
  90. sym)))
  91. (define (not-op? sym) (not (or (is-op? sym) (is-pseudo-op? sym))))
  92. (define (impl prog ret curseg)
  93. (if (null? prog)
  94. (reverse ret)
  95. (let ((cur (car prog)))
  96. (cond ((symbol? cur) (if (not-op? cur)
  97. (impl (cdr prog)
  98. (cons (compose-tag curseg cur) ret)
  99. curseg)
  100. (impl (cdr prog) (cons cur ret) curseg)))
  101. ((is-tag-op? cur) (if (is-local-tag? (cadr cur))
  102. (impl (cdr prog)
  103. (cons (list 'tag (compose-tag curseg (cadr cur))) ret)
  104. curseg)
  105. (impl (cdr prog) (cons cur ret) (cadr cur))))
  106. (else (impl (cdr prog) (cons cur ret) curseg))))))
  107. (impl prog '() '()))
  108. (define (calculate-tag-pos prog)
  109. (define tag-table (make-hash-table))
  110. (define (impl prog cur-pos)
  111. (if (null? prog)
  112. '()
  113. (let ((cur-op (car prog)))
  114. (cond ((is-tag-op? cur-op) (let ()
  115. (hash-table-set! tag-table (cadr cur-op) cur-pos)
  116. (impl (cdr prog) cur-pos)))
  117. ((is-op? cur-op) (impl (cdr prog) (+ 1 cur-pos)))
  118. (else (impl (cdr prog) (+ 9 cur-pos)))))))
  119. (impl prog 0)
  120. tag-table)
  121. (define (tag-pass prog)
  122. (define tag-table (calculate-tag-pos prog))
  123. (define (impl prog ret cur-pos)
  124. (if (null? prog)
  125. (reverse ret)
  126. (let ((cur-op (car prog)))
  127. (define do-nothing
  128. (lambda (op-size)
  129. (impl (cdr prog) (cons cur-op ret) (+ op-size cur-pos))))
  130. (cond ((and (symbol? cur-op) (not (is-op? cur-op)))
  131. (let ((sym-pos (hash-table-ref/default tag-table cur-op #f)))
  132. (if sym-pos
  133. (impl (cdr prog)
  134. (cons (list 'imm (+ -9 (- sym-pos cur-pos))) ret)
  135. (+ 9 cur-pos))
  136. `(error "symbol not found:" ,cur-op)))) ;; error
  137. ((is-tag-op? cur-op) (impl (cdr prog) ret cur-pos))
  138. ((is-op? cur-op) (do-nothing 1))
  139. (else (do-nothing 9))))))
  140. (impl prog '() 0))
  141. (define (output-prog prog output-file)
  142. (define (write-number x port)
  143. (cond ((exact-integer? x) (write-string (blob->string
  144. (u64vector->blob (u64vector x)))
  145. #f
  146. port))
  147. ((real? x) (write-string
  148. (blob->string (f64vector->blob (f64vector x)))
  149. #f
  150. port))
  151. (else (abort "Expect a number"))))
  152. (call-with-output-file output-file
  153. (lambda (port)
  154. (let loop ((prog prog))
  155. (if (null? prog)
  156. '()
  157. (let ((cur (car prog)))
  158. (match cur
  159. (('imm x)
  160. (let ()
  161. (write-byte (hash-table-ref opcode-table 'imm) port)
  162. (write-number x port)
  163. (loop (cdr prog))))
  164. (x
  165. (let ()
  166. (write-byte (hash-table-ref opcode-table x) port)
  167. (loop (cdr prog)))))))))))
  168. (define (main input-file output-file)
  169. (define prog '())
  170. ;; read s-exp from file
  171. (define input-str
  172. (with-input-from-file input-file
  173. read-string))
  174. (call-with-input-string (string-append "(" input-str ")")
  175. (lambda (port) (set! prog (read port))))
  176. (set! prog (preprocess prog))
  177. (set! prog (pseudo-op-pass prog))
  178. (set! prog (tag-preprocess-pass prog))
  179. (let ((new-prog (tag-pass prog)))
  180. (if (or (null? new-prog)
  181. (eq? 'error (car prog)))
  182. (display new-prog) ;; error
  183. (output-prog new-prog output-file))))
  184. (define args (argv))
  185. (if (not (= (length args) 3))
  186. (let ()
  187. (display "Usage: fvm-as <input-file> <output-file>")
  188. (newline)
  189. (exit))
  190. '())
  191. (main (cadr args) (caddr args))