#lang scheme/base
(require
(lib "match.ss")
"../tools.ss"
(for-template
scheme/base
(lib "match.ss")
"dictionary.ss"
"tools.ss"))
(provide
(all-defined-out))
(define (char->atom char)
((lambda (string)
(or (string->number string)
(string->symbol string)))
(string char)))
(define (valid-char? char)
(not (equal? char #\space)))
(define (bitstring->list str)
(map
char->atom
(filter valid-char?
(string->list str))))
(define (bin->number lst)
(foldl (lambda (digit rest)
(+ digit (* 2 rest))) 0 lst))
(define (combine-bits lst)
(match lst
(((k . n) (l . m) . rest)
(if (eq? k l)
(combine-bits `((,k . ,(+ m n)) ,@rest))
`((,k . ,n) ,@(combine-bits `((,l . ,m) . ,rest)))))
(other other)))
(define (split-opcode lst)
(let ((opcode (filter number? lst))
(arguments (map
(lambda (sym) (cons sym 1))
(filter symbol? lst))))
(cons
(cons (bin->number opcode) (length opcode))
(combine-bits arguments))))
(define (parse-opcode-proto str)
(split-opcode
(bitstring->list str)))
(define (binary->proto row)
(match row
((name proto . binary)
(append (list name proto)
(map parse-opcode-proto binary)))))
(check-set-mode! 'report-failed)
(check (binary->proto '(xorwf (f d a) "0001 10da ffff ffff"))
=> '(xorwf (f d a) ((6 . 6) (d . 1) (a . 1) (f . 8))))
(define (paramclass->asm name)
(case name
((R) 'pc-relative) (else 'ignore-overflow)))
(define (assembler-body opcode-body)
(foldl (match-lambda*
(((param . bits) rest)
`(,(paramclass->asm param)
,param ,bits ,rest)))
(caar opcode-body) (cdr opcode-body)))
(define (proto->assembler . proto)
(match proto
((name formals . operands)
#`(make-asm
(lambda #,formals
(list #,@(map assembler-body operands)))
'#,proto))))
(define (proto->disassembler name formals . binary-words)
(if (null? (cdar binary-words)) #`(lambda (opcode)
'(#,name))
#`(lambda (opcode)
(match
(cadr
(chain `(,opcode ())
#,@(map
(match-lambda
((param . bits)
#`(dasm-step '#,param #,bits))) (reverse (cdr (car binary-words))))))
(#,(map car
(cdr (car binary-words)))
(list '#,name #,@formals))))))
(define (instruction-set-tx asm! dasm! instructions)
(let ((protos
(map
binary->proto
(syntax->datum instructions))))
#`(begin
#,@(map
(lambda (proto)
(match proto
((name formals ((opc1 . bits) . args) . opcn)
#`(begin
(#,asm!
'#,name
#,(apply proto->assembler proto))
(#,dasm!
#,opc1 #,bits #,(apply proto->disassembler proto))
))))
protos))))