|
| 1 | +#lang racket |
| 2 | +(provide (all-defined-out)) |
| 3 | + |
| 4 | +;; Asm -> String |
| 5 | +(define (asm->string a) |
| 6 | + (foldr (λ (i s) (string-append (instr->string i) s)) "" a)) |
| 7 | + |
| 8 | +;; Instruction -> String |
| 9 | +(define (instr->string i) |
| 10 | + (match i |
| 11 | + [`(,(? opcode2? o) ,a1 ,a2) |
| 12 | + (string-append "\t" |
| 13 | + (symbol->string o) " " |
| 14 | + (arg->string a1) ", " |
| 15 | + (arg->string a2) "\n")] |
| 16 | + [`(jmp ,l) |
| 17 | + (string-append "\tjmp " (arg->string l) "\n")] |
| 18 | + [`(je ,l) |
| 19 | + (string-append "\tje " (label->string l) "\n")] |
| 20 | + [`(jle ,l) |
| 21 | + (string-append "\tjle " (label->string l) "\n")] |
| 22 | + [`(jl ,l) |
| 23 | + (string-append "\tjl " (label->string l) "\n")] |
| 24 | + [`(jg ,l) |
| 25 | + (string-append "\tjg " (label->string l) "\n")] |
| 26 | + [`(jge ,l) |
| 27 | + (string-append "\tjge " (label->string l) "\n")] |
| 28 | + [`(jne ,l) |
| 29 | + (string-append "\tjne " (label->string l) "\n")] |
| 30 | + [`ret "\tret\n"] |
| 31 | + [`(neg ,a1) |
| 32 | + (string-append "\tneg " (arg->string a1) "\n")] |
| 33 | + [`(call ,l) |
| 34 | + (string-append "\tcall " (arg->string l) "\n")] |
| 35 | + [`(push ,r) |
| 36 | + (string-append "\tpush " (reg->string r) "\n")] |
| 37 | + [l (string-append (label->string l) ":\n")])) |
| 38 | + |
| 39 | +(define (opcode2? x) |
| 40 | + (memq x '(mov add sub cmp and cmovl xor or sal sar lea))) |
| 41 | + |
| 42 | +;; Arg -> String |
| 43 | +(define (arg->string a) |
| 44 | + (match a |
| 45 | + [(? reg?) (reg->string a)] |
| 46 | + [`(offset ,r) |
| 47 | + (string-append "[" (arg->string r) "]")] |
| 48 | + [`(offset ,r ,i) |
| 49 | + (string-append "[" (arg->string r) " + " (number->string (* i 8)) "]")] |
| 50 | + [(? integer?) (number->string a)] |
| 51 | + [(? symbol?) (label->string a)])) |
| 52 | + |
| 53 | +;; Any -> Boolean |
| 54 | +(define (reg? x) |
| 55 | + (and (symbol? x) |
| 56 | + (memq x '(rax rbx rcx rdx rsp rdi rip rbp rsi r8 r9 r10 r11 r12 r13 r14 r15)))) |
| 57 | + |
| 58 | +;; Reg -> String |
| 59 | +(define (reg->string r) |
| 60 | + (symbol->string r)) |
| 61 | + |
| 62 | +;; Label -> String |
| 63 | +;; prefix with _ for Mac |
| 64 | +(define label->string |
| 65 | + (match (system-type 'os) |
| 66 | + ['macosx |
| 67 | + (λ (s) (string-append "_" (symbol->string s)))] |
| 68 | + [_ symbol->string])) |
| 69 | + |
| 70 | +;; Asm -> Void |
| 71 | +(define (asm-display a) |
| 72 | + ;; entry point will be first label |
| 73 | + (let ((g (findf symbol? a))) |
| 74 | + (display |
| 75 | + (string-append "\tglobal " (label->string g) "\n" |
| 76 | + "\tdefault rel\n" |
| 77 | + "\textern " (label->string 'error) "\n" |
| 78 | + "\tsection .text\n" |
| 79 | + (asm->string a))))) |
0 commit comments