Move further code to common, rename to assembler (last restructure I promise)
This commit is contained in:
80
scmvm/assembler.scm
Normal file
80
scmvm/assembler.scm
Normal file
@@ -0,0 +1,80 @@
|
||||
(define-module (scmvm assembler)
|
||||
#:use-module (scmvm vm)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:use-module (srfi srfi-9)
|
||||
#:use-module (rnrs bytevectors)
|
||||
#:use-module ((scheme base) #:select (write-bytevector))
|
||||
#:export ((make-assembler* . make-assembler)
|
||||
assembler?
|
||||
assembler-labels
|
||||
emit-label
|
||||
emit-instruction
|
||||
emit-literal
|
||||
emit-reference
|
||||
finalize-references
|
||||
assembler-dump-program))
|
||||
|
||||
(define (make-label) (cons #f '()))
|
||||
|
||||
(define-record-type <assembler>
|
||||
(make-assembler pos buf labels)
|
||||
assembler?
|
||||
(pos assembler-pos assembler-pos-set!)
|
||||
(buf assembler-buf assembler-buf-set!)
|
||||
(labels assembler-labels))
|
||||
|
||||
(define (make-assembler*)
|
||||
(make-assembler 0 (make-bytevector 1024) (make-hash-table)))
|
||||
|
||||
(define (assembler-buf-grow! asm)
|
||||
(let ([buf (make-bytevector (ash (bytevector-length (assembler-buf asm)) -1))])
|
||||
(bytevector-copy! (assembler-buf asm) 0 buf 0 (bytevector-length (assembler-buf asm)))
|
||||
(assembler-buf-set! asm buf)))
|
||||
|
||||
(define* (write-word word asm #:optional (pos (assembler-pos asm)))
|
||||
(when (> (+ pos 4) (bytevector-length (assembler-buf asm)))
|
||||
(assembler-buf-grow! asm))
|
||||
(bytevector-u32-native-set! (assembler-buf asm) pos word))
|
||||
|
||||
(define* (write-byte byte asm #:optional (pos (assembler-pos asm)))
|
||||
(when (> (+ pos 1) (bytevector-length (assembler-buf asm)))
|
||||
(assembler-buf-grow! asm))
|
||||
(bytevector-u8-set! (assembler-buf asm) pos byte))
|
||||
|
||||
(define (assembler-label-add-reference asm name addr)
|
||||
(when (not (hash-ref (assembler-labels asm) name))
|
||||
(hash-set! (assembler-labels asm) name (make-label)))
|
||||
(let ([label (hash-ref (assembler-labels asm) name)])
|
||||
(set-cdr! label (cons addr (cdr label)))))
|
||||
|
||||
(define (assembler-label-add-value asm name val)
|
||||
(when (not (hash-ref (assembler-labels asm) name))
|
||||
(hash-set! (assembler-labels asm) name (make-label)))
|
||||
;; 1+ to fudge for null pointers
|
||||
(set-car! (hash-ref (assembler-labels asm) name) (1+ val)))
|
||||
|
||||
(define (emit-label asm name)
|
||||
(assembler-label-add-value asm name (assembler-pos asm)))
|
||||
|
||||
(define (emit-instruction asm inst)
|
||||
(let ([inst-object (assq inst *instruction-set*)])
|
||||
(write-byte (instruction-code inst-object) asm)
|
||||
(assembler-pos-set! asm (+ (assembler-pos asm) 1))))
|
||||
|
||||
(define (emit-literal asm val)
|
||||
(write-word val asm)
|
||||
(assembler-pos-set! asm (+ (assembler-pos asm) 4)))
|
||||
|
||||
(define (emit-reference asm name)
|
||||
(assembler-label-add-reference asm name (assembler-pos asm))
|
||||
(assembler-pos-set! asm (+ (assembler-pos asm) 4)))
|
||||
|
||||
(define (finalize-references asm)
|
||||
(define (install-location _name label)
|
||||
(for-each
|
||||
(cute write-word (car label) asm <>)
|
||||
(cdr label)))
|
||||
(hash-for-each install-location (assembler-labels asm)))
|
||||
|
||||
(define (assembler-dump-program asm port)
|
||||
(write-bytevector (assembler-buf asm) port 0 (assembler-pos asm)))
|
||||
Reference in New Issue
Block a user