Split instruction and formatting helpers

ober

d66718e73631b119b44aeff9d068636163b1f904

diff --git a/jasm b/jasm
index 1e1f922..2d0ced7 100755
Binary files a/jasm and b/jasm differ
diff --git a/lib/jasm/disasm.ss b/lib/jasm/disasm.ss
index d5e2386..816baed 100644
--- a/lib/jasm/disasm.ss
+++ b/lib/jasm/disasm.ss
@@ -16,7 +16,9 @@
     instruction-text
     instruction-bytes)
 
-  (import (chezscheme))
+  (import (chezscheme)
+          (jasm instruction)
+          (jasm format))
 
   (define supported-architectures '(x86-64 aarch64 mips mipsel mips64 mips64el))
 
@@ -52,27 +54,6 @@
       [(mipsel mips64el) 'little]
       [else 'little]))
 
-  (define (instruction? x)
-    (and (pair? x) (eq? (car x) 'instruction)))
-
-  (define (make-instruction arch address size text bytes)
-    (list 'instruction
-          (cons 'arch arch)
-          (cons 'address address)
-          (cons 'size size)
-          (cons 'text text)
-          (cons 'bytes bytes)))
-
-  (define (instruction-ref insn key)
-    (let ([cell (assq key (cdr insn))])
-      (if cell (cdr cell) #f)))
-
-  (define (instruction-arch insn) (instruction-ref insn 'arch))
-  (define (instruction-address insn) (instruction-ref insn 'address))
-  (define (instruction-size insn) (instruction-ref insn 'size))
-  (define (instruction-text insn) (instruction-ref insn 'text))
-  (define (instruction-bytes insn) (instruction-ref insn 'bytes))
-
   (define (option-ref options key default)
     (let ([cell (assq key options)])
       (if cell (cdr cell) default)))
@@ -599,15 +580,6 @@
                     (+ address (instruction-size insn))
                     (cons insn out)))))))
 
-  (define (format-instruction insn)
-    (string-append
-      (hex-number (instruction-address insn))
-      ":\t"
-      (instruction-text insn)
-      "\n"))
-
   (define (disassemble->string arch bv . maybe-options)
     (let ([options (if (null? maybe-options) '() (car maybe-options))])
-      (apply string-append
-        (map format-instruction
-             (disassemble-bytevector arch bv options))))))
+      (format-instructions (disassemble-bytevector arch bv options)))))
diff --git a/lib/jasm/format.ss b/lib/jasm/format.ss
new file mode 100644
index 0000000..4d8d69d
--- /dev/null
+++ b/lib/jasm/format.ss
@@ -0,0 +1,38 @@
+#!chezscheme
+
+(library (jasm format)
+  (export
+    format-instruction
+    format-instructions)
+
+  (import (chezscheme))
+
+  (define (instruction-ref insn key)
+    (let ([cell (assq key (cdr insn))])
+      (if cell (cdr cell) #f)))
+
+  (define (instruction-address insn) (instruction-ref insn 'address))
+  (define (instruction-text insn) (instruction-ref insn 'text))
+
+  (define (ascii-downcase c)
+    (if (and (char>=? c #\A) (char<=? c #\Z))
+        (integer->char (+ (char->integer #\a)
+                          (- (char->integer c) (char->integer #\A))))
+        c))
+
+  (define (number->hex n)
+    (list->string (map ascii-downcase
+                       (string->list (number->string n 16)))))
+
+  (define (hex-number n)
+    (string-append "0x" (number->hex n)))
+
+  (define (format-instruction insn)
+    (string-append
+      (hex-number (instruction-address insn))
+      ":\t"
+      (instruction-text insn)
+      "\n"))
+
+  (define (format-instructions insns)
+    (apply string-append (map format-instruction insns))))
diff --git a/lib/jasm/instruction.ss b/lib/jasm/instruction.ss
new file mode 100644
index 0000000..8de402f
--- /dev/null
+++ b/lib/jasm/instruction.ss
@@ -0,0 +1,34 @@
+#!chezscheme
+
+(library (jasm instruction)
+  (export
+    make-instruction
+    instruction?
+    instruction-arch
+    instruction-address
+    instruction-size
+    instruction-text
+    instruction-bytes)
+
+  (import (chezscheme))
+
+  (define (instruction? x)
+    (and (pair? x) (eq? (car x) 'instruction)))
+
+  (define (make-instruction arch address size text bytes)
+    (list 'instruction
+          (cons 'arch arch)
+          (cons 'address address)
+          (cons 'size size)
+          (cons 'text text)
+          (cons 'bytes bytes)))
+
+  (define (instruction-ref insn key)
+    (let ([cell (assq key (cdr insn))])
+      (if cell (cdr cell) #f)))
+
+  (define (instruction-arch insn) (instruction-ref insn 'arch))
+  (define (instruction-address insn) (instruction-ref insn 'address))
+  (define (instruction-size insn) (instruction-ref insn 'size))
+  (define (instruction-text insn) (instruction-ref insn 'text))
+  (define (instruction-bytes insn) (instruction-ref insn 'bytes)))
diff --git a/tests/test-jasm.ss b/tests/test-jasm.ss
index e13121d..089d0e6 100644
--- a/tests/test-jasm.ss
+++ b/tests/test-jasm.ss
@@ -1,6 +1,6 @@
 #!chezscheme
 
-(import (chezscheme) (jasm disasm))
+(import (chezscheme) (jasm disasm) (jasm format))
 
 (define pass 0)
 (define fail 0)
@@ -119,5 +119,12 @@
     '((syntax . intel) (address . #x10)))
   "0x10:\tpush\trbp\n0x11:\tret\n")
 
+(test "format module"
+  (format-instructions
+    (disassemble-bytevector 'mips
+      (hex-string->bytevector "27 bd ff e0")
+      '((address . #x20))))
+  "0x20:\taddiu\t$sp, $sp, -32\n")
+
 (printf "~%pass: ~a fail: ~a~%" pass fail)
 (when (> fail 0) (exit 1))