Skip to content

Commit 856ce4c

Browse files
committed
Allow movsd/movss patching in asm template
1 parent 1e62cd7 commit 856ce4c

2 files changed

Lines changed: 103 additions & 3 deletions

File tree

lib/lang/asm/x86_64.scm

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,18 @@
123123
[patches (asm-template-patches tmpl)])
124124
;; Apply each patch whose keyword appears in PARAMS.
125125
(for-each (match-lambda
126+
;; Integer patch: write value as little-endian bytes.
126127
[(kw offset width)
127128
(and-let1 val (assq kw params)
128-
(patch-bytes! bytes offset width (cdr val)))])
129+
(patch-bytes! bytes offset width (cdr val)))]
130+
;; movs_ patch: translate symbol movsd->#xf2, movss->#xf3.
131+
[(kw offset 1 'movs_)
132+
(let* ([v (assq-ref params kw 'movsd)]
133+
[pfx (case v
134+
[(movsd) #xf2]
135+
[(movss) #xf3]
136+
[else (error "movs_ value must be movsd or movss:" v)])])
137+
(u8vector-set! bytes offset pfx))])
129138
patches)
130139
(values bytes labels)))
131140

@@ -300,6 +309,15 @@
300309
[`(movsd (mem . ,x) (sse ,dst)) (! (opc'(#xf2 #x0f #x10)) (reg dst) (mem x))]
301310
[`(movsd (sse ,src) (mem . ,x)) (! (opc'(#xf2 #x0f #x11)) (reg src) (mem x))]
302311

312+
;; movs_ -- switchable movsd/movss: prefix byte (#xf2/#xf3) is patchable.
313+
;; Default encoding uses movsd (#xf2); asm-instantiate flips to #xf3 for movss.
314+
[`((movs_ ,kw) (sse ,src) (sse ,dst))
315+
(op-movs_ kw (! (opc '(#xf2 #x0f #x10)) (reg dst) (r/m-reg dst)))]
316+
[`((movs_ ,kw) (mem . ,x) (sse ,dst))
317+
(op-movs_ kw (! (opc '(#xf2 #x0f #x10)) (reg dst) (mem x)))]
318+
[`((movs_ ,kw) (sse ,src) (mem . ,x))
319+
(op-movs_ kw (! (opc '(#xf2 #x0f #x11)) (reg src) (mem x)))]
320+
303321
;; calculations
304322
[('addq _ _) (op-add pinsn 0)]
305323
[('orq _ _) (op-add pinsn 1)]
@@ -364,6 +382,20 @@
364382
((! w (rex.b dst) (opc+rq #xb8 dst) (imm64 laddr)) 0 0))
365383
((! w (rex.b dst) (opc+rq #xb8 dst) (imm64 0)) 0 0)))) ;; dummy
366384

385+
;; op-movs_ :: keyword, closure -> closure
386+
;; Wraps an inner expand-spec closure for a movsd instruction. In pass 2,
387+
;; records a patch of kind 'movs_ at the prefix byte (offset 0 within the
388+
;; instruction, i.e. addr - length(bytes)).
389+
;; asm-instantiate translates movsd->#xf2, movss->#xf3 when applying it.
390+
(define (op-movs_ kw inner)
391+
(^[a t]
392+
(let1 bytes (inner a t)
393+
(when (and t (patch-collector))
394+
(let1 acc (patch-collector)
395+
(set-car! acc (cons (list kw (- a (length bytes)) 1 'movs_)
396+
(car acc)))))
397+
bytes)))
398+
367399
;; addq family
368400
;; opcode variations are derived from a single number, regc.
369401
(define (op-add pinsn regc)

tests/lang.scm

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@
331331
#f
332332
(eq? b1 b2)))))
333333

334-
;; --- Stage 2: immediate-value placeholders ---
334+
;; --- immediate-value placeholders ---
335335

336336
;; imm64 placeholder: movq (imm64 :val), %rax
337337
;; Encoding: REX.W(48) B8 <8 bytes immediate> -- 10 bytes total
@@ -421,7 +421,7 @@
421421
'((start . 0))
422422
labels)))
423423

424-
;; --- Stage 3: data-directive placeholders ---
424+
;; --- data-directive placeholders ---
425425

426426
;; .dataq placeholder: 8-byte hole
427427
(let ()
@@ -479,6 +479,74 @@
479479
'(#x08 #x07 #x06 #x05 #x04 #x03 #x02 #x01)
480480
(u8vector->list b))))
481481

482+
;; --- movs_ instruction-variant placeholder ---
483+
484+
;; ((movs_ :op) %xmm0 %xmm1) -- sse->sse form
485+
;; Default encoding: F2 0F 10 ModRM
486+
;; ModRM: mod=3(reg-reg), reg=1(xmm1/dst), r/m=1(xmm1/dst) -> 0b11_001_001 = #xc9
487+
(let ()
488+
(define tmpl (asm-template '(((movs_ :op) %xmm0 %xmm1))))
489+
;; Default is movsd
490+
(receive (b _) (asm-instantiate tmpl '())
491+
(test* "movs_ sse->sse default (movsd)"
492+
'(#xf2 #x0f #x10 #xc9)
493+
(u8vector->list b)))
494+
;; Explicit movsd
495+
(receive (b _) (asm-instantiate tmpl '((:op . movsd)))
496+
(test* "movs_ sse->sse explicit movsd"
497+
'(#xf2 #x0f #x10 #xc9)
498+
(u8vector->list b)))
499+
;; Switch to movss
500+
(receive (b _) (asm-instantiate tmpl '((:op . movss)))
501+
(test* "movs_ sse->sse switched to movss"
502+
'(#xf3 #x0f #x10 #xc9)
503+
(u8vector->list b)))
504+
;; Re-instantiate as movsd again (template not mutated)
505+
(receive (b _) (asm-instantiate tmpl '((:op . movsd)))
506+
(test* "movs_ sse->sse back to movsd"
507+
'(#xf2 #x0f #x10 #xc9)
508+
(u8vector->list b))))
509+
510+
;; ((movs_ :op) (%rax) %xmm1) -- mem->sse form
511+
;; Default encoding: F2 0F 10 ModRM
512+
;; ModRM: mod=0, reg=1(xmm1/dst), r/m=0(%rax) -> 0b00_001_000 = #x08
513+
(let ()
514+
(define tmpl (asm-template '(((movs_ :op) (%rax) %xmm1))))
515+
(receive (b _) (asm-instantiate tmpl '())
516+
(test* "movs_ mem->sse default (movsd)"
517+
'(#xf2 #x0f #x10 #x08)
518+
(u8vector->list b)))
519+
(receive (b _) (asm-instantiate tmpl '((:op . movss)))
520+
(test* "movs_ mem->sse switched to movss"
521+
'(#xf3 #x0f #x10 #x08)
522+
(u8vector->list b))))
523+
524+
;; ((movs_ :op) %xmm0 (%rax)) -- sse->mem form
525+
;; Default encoding: F2 0F 11 ModRM
526+
;; ModRM: mod=0, reg=0(xmm0/src), r/m=0(%rax) -> #x00
527+
(let ()
528+
(define tmpl (asm-template '(((movs_ :op) %xmm0 (%rax)))))
529+
(receive (b _) (asm-instantiate tmpl '())
530+
(test* "movs_ sse->mem default (movsd)"
531+
'(#xf2 #x0f #x11 #x00)
532+
(u8vector->list b)))
533+
(receive (b _) (asm-instantiate tmpl '((:op . movss)))
534+
(test* "movs_ sse->mem switched to movss"
535+
'(#xf3 #x0f #x11 #x00)
536+
(u8vector->list b))))
537+
538+
;; movs_ combined with other placeholders in a sequence
539+
(let ()
540+
(define tmpl (asm-template '((.dataq :fn-ptr)
541+
((movs_ :variant) (%rax) %xmm0)
542+
(ret))))
543+
(receive (b _) (asm-instantiate tmpl `((:fn-ptr . #xdeadbeef) (:variant . movss)))
544+
(test* "movs_ combined with .dataq placeholder"
545+
(append '(#xef #xbe #xad #xde 0 0 0 0) ; .dataq :fn-ptr
546+
'(#xf3 #x0f #x10 #x00) ; movss (%rax),%xmm0
547+
'(#xc3)) ; ret
548+
(u8vector->list b))))
549+
482550
;;----------------------------------------------------------------------
483551
(test-section "lang.c")
484552

0 commit comments

Comments
 (0)