fvm-as.scm 5.1 KB

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