アセンブラをリファクタリング中

子守の合間にアセンブラリファクタリングしていた。ようやくまとまってきた。リファクタリングの過程で x86-64 のアドレッシングに関して更に理解が深まった。
mov とか lea はおおよそ以下の pack-op 手続きでアセンブルできる。

(define (pack-op bits64? opcode mod r64 r/m64 scale index base disp0/8/32 imm8/32)
  (receive (rex-prefix modrr/m sib)
      (if scale (compose-reg+sib mod r64 scale index base) (compose-reg mod r64 r/m64))
    (values `(,@(if bits64? (list rex-prefix) '()) ,opcode ,modrr/m ,@sib ,@disp0/8/32 ,@imm8/32) #f)))

(define (compose-reg mod r64 r/m64)
  (values
   (rex-prefix #t (ext-reg? r64) #f (ext-reg? r/m64))
   (mod-r-r/m mod r64 r/m64)
   (cond
    ;; r/m = #b*100 (rsp, r12) requires sib except mod=#x11
    ;;   see http://www.mztn.org/lxasm64/amd05.html
    [(and (not (= mod mod.register)) (memq r/m64 '(#b0100 #b1100)))
     (let ([r64-index #b100])   ;; #b100 means "none", no index.
       (list (sib sib.scale1 r64-index r/m64)))]
    [else '()])))

(define (compose-reg+sib mod r64 scale index base)
  (values
   (rex-prefix #t (ext-reg? r64) (ext-reg? index) #f)
   (mod-r-r/m mod r64 #b100) ;; r/m64 = #b100 is SIB flag.
   (list (sib scale index base))))