summary refs log tree commit diff
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2026-09-07 22:44:03 -0700
committerIrene Knapp <ireneista@irenes.space>2026-09-07 22:44:03 -0700
commit92b8da05981328c2d4b106d9de008625b6895620 (patch)
treeb5c834b61f47b5a8403997a1c6d583d910fb8eb4
parent08d58db689cac50ef582340e93047273f7759a37 (diff)
add magic hex-transform comments in all the amd64 instruction words
also add logic to output newlines at the start of these comments

Force-Push: yes
Change-Id: I4c3ce99c264e7d02150cdf2b40d486e925b5fb72
-rw-r--r--amd64.e234
-rw-r--r--transform.e28
2 files changed, 204 insertions, 58 deletions
diff --git a/amd64.e b/amd64.e
index 95cdb2a..04c4aa7 100644
--- a/amd64.e
+++ b/amd64.e
@@ -466,35 +466,47 @@ s" :cc-greater" keyword
 ~ grouping. These are the ones that were easy to deal with.
 
 ~ (output point -- output point)
-: cld 0xFC pack8 ;
-: std 0xFD pack8 ;
-: syscall 0x0F pack8 0x05 pack8 ;
-: hlt 0xF4 pack8 ;
+: cld ~ : cld
+  0xFC pack8 ;
+: std ~ : std
+  0xFD pack8 ;
+: syscall ~ : syscall
+  0x0F pack8 0x05 pack8 ;
+: hlt ~ : hlt
+  0xF4 pack8 ;
 
 ~ (output point, source register -- output point)
-: push-reg64 reg64 0x50 opcodereg ;
-: push-extrareg64 swap rex-b swap extrareg64 0x50 opcodereg ;
+: push-reg64 ~ : push-reg64
+  reg64 0x50 opcodereg ;
+: push-extrareg64 ~ : push-extrareg64
+  swap rex-b swap extrareg64 0x50 opcodereg ;
   ~   Note the use of the B rex bit here; this instruction puts the register
   ~ number in the opcode field, so it uses Table 3-1.
 
 ~ (output point, target register -- output point)
-: pop-reg64 reg64 0x58 opcodereg ;
-: pop-extrareg64 swap rex-b swap extrareg64 0x58 opcodereg ;
+: pop-reg64 ~ : pop-reg64
+  reg64 0x58 opcodereg ;
+: pop-extrareg64 ~ : pop-extrareg64
+  swap rex-b swap extrareg64 0x58 opcodereg ;
   ~   Note the use of the B rex bit here; this instruction puts the register
   ~ number in the opcode field, so it uses Table 3-1.
 
 ~ (output point, immediate value -- output point)
-: push-imm32-extended64 swap 0x68 pack8 swap pack32 ;
+: push-imm32-extended64
+  ~ : push-imm32-extended64
+  swap 0x68 pack8 swap pack32 ;
 
 ~ (output point, source register, source displacement value, target register
 ~  -- output point)
 : lea-reg64-disp8-reg64
+  ~ : lea-reg64-disp8-reg64
   4 roll rex-w 0x8D pack8 4 unroll
   reg64 3unroll addressing-disp8-reg64 ;
 
 ~ (output point, source register, source displacement value, target register
 ~  -- output point)
 : lea-reg64-disp32-reg64
+  ~ : lea-reg64-disp32-reg64
   4 roll rex-w 0x8D pack8 4 unroll
   reg64 3unroll addressing-disp32-reg64 ;
 
@@ -502,6 +514,7 @@ s" :cc-greater" keyword
 ~  source base register, source index register, source index scale factor,
 ~  target register -- output point)
 : lea-reg64-indexed-reg64
+  ~ : lea-reg64-indexed-reg64
   5 roll rex-w 0x8D pack8 5 unroll
   reg64 4 unroll 3unroll swap addressing-indexed-reg64 ;
 
@@ -510,6 +523,7 @@ s" :cc-greater" keyword
 ~  source displacement value,
 ~  target register -- output point)
 : lea-reg64-disp8-indexed-reg64
+  ~ : lea-reg64-disp8-indexed-reg64
   6 roll rex-w 0x8D pack8 6 unroll
   reg64 5 unroll 3 roll 4 roll 3 roll addressing-disp8-indexed-reg64 ;
 
@@ -529,41 +543,50 @@ s" :cc-greater" keyword
 
 ~ (output point, immediate value, register -- output point)
 : mov-reg64-imm32
+  ~ : mov-reg64-imm32
   3roll rex-w 0xC7 pack8 swap
   0 swap addressing-reg64
   swap pack32 ;
 : mov-reg64-imm64
+  ~ : mov-reg64-imm64
   3roll rex-w swap reg64 0xB8 opcodereg swap pack64 ;
 : mov-extrareg64-imm64
+  ~ : mov-extrareg64-imm64
   ~   Note the use of the B rex bit here; this instruction puts the register
   ~ number in the opcode field, so it uses Table 3-1.
   3roll rex-wb swap extrareg64 0xB8 opcodereg swap pack64 ;
 
 ~ (output point, source register, target register -- output point)
 : mov-reg64-reg64
+  ~ : mov-reg64-reg64
   3roll rex-w 0x89 pack8 3unroll
   swap reg64 swap addressing-reg64 ;
 : mov-indirect-reg64-reg64
+  ~ : mov-indirect-reg64-reg64
   3roll rex-w 0x89 pack8 3unroll
   swap reg64 swap addressing-indirect-reg64 ;
 
 ~ (output point, source register, target register, target displacement value
 ~  -- output point)
 : mov-disp8-reg64-reg64
+  ~ : mov-disp8-reg64-reg64
   4 roll rex-w 0x89 pack8 4 unroll
   3roll reg64 3unroll addressing-disp8-reg64 ;
 
 ~ (output point, source register, target register -- output point)
 : mov-reg64-indirect-reg64
+  ~ : mov-reg64-indirect-reg64
   3roll rex-w 0x8B pack8 3unroll
   reg64 swap addressing-indirect-reg64 ;
 
 ~ (output point, source register, source displacement value, target register
 ~  -- output point)
 : mov-reg64-disp8-reg64
+  ~ : mov-reg64-disp8-reg64
   4 roll rex-w 0x8B pack8 4 unroll
   reg64 3unroll addressing-disp8-reg64 ;
 : mov-reg64-disp32-reg64
+  ~ : mov-reg64-disp32-reg64
   4 roll rex-w 0x89 pack8 4 unroll
   3roll reg64 swap 3roll addressing-disp32-reg64 ;
 
@@ -571,6 +594,7 @@ s" :cc-greater" keyword
 ~  source base register, source index register, source index scale factor,
 ~  target register -- output point)
 : mov-reg64-indexed-reg64
+  ~ : mov-reg64-indexed-reg64
   5 roll rex-w 0x8B pack8 5 unroll
   reg64 4 unroll 3unroll swap addressing-indexed-reg64 ;
 
@@ -578,78 +602,92 @@ s" :cc-greater" keyword
 ~  target base register, target index register, target index scale factor
 ~  -- output point)
 : mov-indexed-reg64-reg64
+  ~ : mov-indexed-reg64-reg64
   5 roll rex-w 0x89 pack8 5 unroll
   4 roll reg64 4 unroll
   3unroll swap addressing-indexed-reg64 ;
 
 ~ (output point, source register, target register -- output point)
 : mov-indirect-reg64-reg32
+  ~ : mov-indirect-reg64-reg32
   3roll 0x89 pack8 3unroll
   swap reg32 swap addressing-indirect-reg64 ;
 
 ~ (output point, source regisgter, target register, target displacement value
 ~  -- output point)
 : mov-disp8-reg64-reg32
+  ~ : mov-disp8-reg64-reg32
   4 roll 0x89 pack8 4 unroll
   3roll reg32 3unroll addressing-disp8-reg64 ;
 
 ~ (output point, source register, target register -- output point)
 : mov-reg32-indirect-reg64
+  ~ : mov-reg32-indirect-reg64
   3roll 0x8B pack8 3unroll
   reg32 swap addressing-indirect-reg64 ;
 
 ~ (output point, source register, source displacement value, target register
 ~ -- output point)
 : mov-reg32-disp8-reg64
+  ~ : mov-reg32-disp8-reg64
   4 roll 0x8B pack8 4 unroll
   reg32 3unroll addressing-disp8-reg64 ;
 
 ~ (output point, source register, target register -- output point)
 : mov-indirect-reg64-reg16
+  ~ : mov-indirect-reg64-reg16
   3roll 0x66 pack8 0x89 pack8 3unroll
   swap reg16 swap addressing-indirect-reg64 ;
 
 ~ (output point, source register, target register, target displacement value
 ~  -- output point)
 : mov-disp8-reg64-reg16
+  ~ : mov-disp8-reg64-reg16
   4 roll 0x66 pack8 0x89 pack8 4 unroll
   3roll reg16 3unroll addressing-disp8-reg64 ;
 
 ~ (output point, source register, target register -- output point)
 : mov-reg16-indirect-reg64
+  ~ : mov-reg16-indirect-reg64
   3roll 0x66 pack8 0x8B pack8 3unroll
   reg16 swap addressing-indirect-reg64 ;
 
 ~ (output point, source register, target displacement value, target register
 ~  -- output point)
 : mov-reg16-disp8-reg64
+  ~ : mov-reg16-disp8-reg64
   4 roll 0x66 pack8 0x8B pack8 4 unroll
   reg16 3unroll addressing-disp8-reg64 ;
 
 ~ (output point, source register, target register -- output point)
 : mov-indirect-reg64-reg8
+  ~ : mov-indirect-reg64-reg8
   3roll 0x88 pack8 3unroll
   swap reg8 swap addressing-indirect-reg64 ;
 
 ~ (output point, source register, target register, target displacement value
 ~  -- output point)
 : mov-disp8-reg64-reg8
+  ~ : mov-disp8-reg64-reg8
   4 roll 0x88 pack8 4 unroll
   3roll reg8 3unroll addressing-disp8-reg64 ;
 
 ~ (output point, source register, target register -- output point)
 : mov-reg8-indirect-reg64
+  ~ : mov-reg8-indirect-reg64
   3roll 0x8A pack8 3unroll
   reg8 swap addressing-indirect-reg64 ;
 
 ~ (output point, source register, source displacement value, target register
 ~  -- output point)
 : mov-reg8-disp8-reg64
+  ~ : mov-reg8-disp8-reg64
   4 roll pack8 0x8A pack8 4 unroll
   reg8 3unroll addressing-disp8-reg64 ;
 
 ~ (output point, source register, target register -- output point)
 : mov-reg8-reg8
+  ~ : mov-reg8-reg8
   3roll 0x88 pack8 3unroll
   swap reg8 swap addressing-reg8 ;
 
@@ -684,62 +722,110 @@ s" :cc-greater" keyword
 ~ here...
 
 ~ (output point -- output point)
-: movs8 0xA4 pack8 ;
-: movs16 0x66 pack8 0xA5 pack8 ;
-: movs32 0xA5 pack8 ;
-: movs64 rex-w 0xA5 pack8 ;
-: rep-movs8 0xF3 pack8 0xA4 pack8 ;
-: rep-movs16 0xF3 pack8 0x66 pack8 0xA5 pack8 ;
-: rep-movs32 0xF3 pack8 0xA5 pack8 ;
-: rep-movs64 0xF3 pack8 rex-w 0xA5 pack8 ;
+: movs8 ~ : movs8
+  0xA4 pack8 ;
+: movs16 ~ : movs16
+  0x66 pack8 0xA5 pack8 ;
+: movs32 ~ : movs32
+  0xA5 pack8 ;
+: movs64 ~ : movs64
+  rex-w 0xA5 pack8 ;
+: rep-movs8 ~ : rep-movs8
+  0xF3 pack8 0xA4 pack8 ;
+: rep-movs16 ~ : rep-movs16
+  0xF3 pack8 0x66 pack8 0xA5 pack8 ;
+: rep-movs32 ~ : rep-movs32
+  0xF3 pack8 0xA5 pack8 ;
+: rep-movs64 ~ : rep-movs64
+  0xF3 pack8 rex-w 0xA5 pack8 ;
 
 ~ (output point -- output point)
-: lods8 0xAC pack8 ;
-: lods16 0x66 pack8 0xAd pack8 ;
-: lods32 0xAD pack8 ;
-: lods64 rex-w 0xAD pack8 ;
-: rep-lods8 0xF3 pack8 0xAC pack8 ;
-: rep-lods16 0xF3 pack8 0x66 pack8 0xAD pack8 ;
-: rep-lods32 0xF3 pack8 0xAD pack8 ;
-: rep-lods64 0xF3 pack8 rex-w 0xAD pack8 ;
+: lods8 ~ : lods8
+  0xAC pack8 ;
+: lods16 ~ : lods16
+  0x66 pack8 0xAd pack8 ;
+: lods32 ~ : lods32
+  0xAD pack8 ;
+: lods64 ~ : lods64
+  rex-w 0xAD pack8 ;
+: rep-lods8 ~ : rep-lods8
+  0xF3 pack8 0xAC pack8 ;
+: rep-lods16 ~ : rep-lods16
+  0xF3 pack8 0x66 pack8 0xAD pack8 ;
+: rep-lods32 ~ : rep-lods32
+  0xF3 pack8 0xAD pack8 ;
+: rep-lods64 ~ : rep-lods64
+  0xF3 pack8 rex-w 0xAD pack8 ;
 
 ~ (output point -- output point)
-: stos8 0xAA pack8 ;
-: stos16 0x66 pack8 0xAB pack8 ;
-: stos32 0xAB pack8 ;
-: stos64 rex-w 0xAB pack8 ;
-: rep-stos8 0xF3 pack8 0xAA pack8 ;
-: rep-stos16 0xF3 pack8 0x66 pack8 0xAB pack8 ;
-: rep-stos32 0xF3 pack8 0xAB pack8 ;
-: rep-stos64 0xF3 pack8 rex-w 0xAB pack8 ;
+: stos8 ~ : stos8
+  0xAA pack8 ;
+: stos16 ~ : stos16
+  0x66 pack8 0xAB pack8 ;
+: stos32 ~ : stos32
+  0xAB pack8 ;
+: stos64 ~ : stos64
+  rex-w 0xAB pack8 ;
+: rep-stos8 ~ : rep-stos8
+  0xF3 pack8 0xAA pack8 ;
+: rep-stos16 ~ : rep-stos16
+  0xF3 pack8 0x66 pack8 0xAB pack8 ;
+: rep-stos32 ~ : rep-stos32
+  0xF3 pack8 0xAB pack8 ;
+: rep-stos64 ~ : rep-stos64
+  0xF3 pack8 rex-w 0xAB pack8 ;
 
 ~ (output point -- output point)
-: cmps8 0xA6 pack8 ;
-: cmps16 0x66 pack8 0xA7 pack8 ;
-: cmps32 0xA7 pack8 ;
-: cmps64 rex-w 0xA7 pack8 ;
-: repz-cmps8 0xF3 pack8 0xA6 pack8 ;
-: repz-cmps16 0xF3 pack8 0x66 pack8 0xA7 pack8 ;
-: repz-cmps32 0xF3 pack8 0xA7 pack8 ;
-: repz-cmps64 0xF3 pack8 rex-w 0xA7 pack8 ;
-: repnz-cmps8 0xF2 pack8 0xA6 pack8 ;
-: repnz-cmps16 0xF2 pack8 0x66 pack8 0xA7 pack8 ;
-: repnz-cmps32 0xF2 pack8 0xA7 pack8 ;
-: repnz-cmps64 0xF2 pack8 rex-w 0xA7 pack8 ;
+: cmps8 ~ : cmps8
+  0xA6 pack8 ;
+: cmps16 ~ : cmps16
+  0x66 pack8 0xA7 pack8 ;
+: cmps32 ~ : cmps32
+  0xA7 pack8 ;
+: cmps64 ~ : cmps64
+  rex-w 0xA7 pack8 ;
+: repz-cmps8 ~ : repz-cmps8
+  0xF3 pack8 0xA6 pack8 ;
+: repz-cmps16 ~ : repz-cmps16
+  0xF3 pack8 0x66 pack8 0xA7 pack8 ;
+: repz-cmps32 ~ : repz-cmps32
+  0xF3 pack8 0xA7 pack8 ;
+: repz-cmps64 ~ : repz-cmps64
+  0xF3 pack8 rex-w 0xA7 pack8 ;
+: repnz-cmps8 ~ : repnz-cmps8
+  0xF2 pack8 0xA6 pack8 ;
+: repnz-cmps16 ~ : repnz-cmps16
+  0xF2 pack8 0x66 pack8 0xA7 pack8 ;
+: repnz-cmps32 ~ : repnz-cmps32
+  0xF2 pack8 0xA7 pack8 ;
+: repnz-cmps64 ~ : repnz-cmps64
+  0xF2 pack8 rex-w 0xA7 pack8 ;
 
 ~ (output point -- output point)
-: scas8 0xA8 pack8 ;
-: scas16 0x66 pack8 0xAF pack8 ;
-: scas32 0xAF pack8 ;
-: scas64 rex-w 0xAF pack8 ;
-: repz-scas8 0xF3 pack8 0xAE pack8 ;
-: repz-scas16 0xF3 pack8 0x66 pack8 0xAF pack8 ;
-: repz-scas32 0xF3 pack8 0xAF pack8 ;
-: repz-scas64 0xF3 pack8 rex-w 0xAF pack8 ;
-: repnz-scas8 0xF2 pack8 0xAE pack8 ;
-: repnz-scas16 0xF2 pack8 0x66 pack8 0xAF pack8 ;
-: repnz-scas32 0xF2 pack8 0xAF pack8 ;
-: repnz-scas64 0xF2 pack8 rex-w 0xAF pack8 ;
+: scas8 ~ : scas8
+  0xA8 pack8 ;
+: scas16 ~ : scas16
+  0x66 pack8 0xAF pack8 ;
+: scas32 ~ : scas32
+  0xAF pack8 ;
+: scas64 ~ : scas64
+  rex-w 0xAF pack8 ;
+: repz-scas8 ~ : repz-scas8
+  0xF3 pack8 0xAE pack8 ;
+: repz-scas16 ~ : repz-scas16
+  0xF3 pack8 0x66 pack8 0xAF pack8 ;
+: repz-scas32 ~ : repz-scas32
+  0xF3 pack8 0xAF pack8 ;
+: repz-scas64 ~ : repz-scas64
+  0xF3 pack8 rex-w 0xAF pack8 ;
+: repnz-scas8 ~ : repnz-scas8
+  0xF2 pack8 0xAE pack8 ;
+: repnz-scas16 ~ : repnz-scas16
+  0xF2 pack8 0x66 pack8 0xAF pack8 ;
+: repnz-scas32 ~ : repnz-scas32
+  0xF2 pack8 0xAF pack8 ;
+: repnz-scas64 ~ : repnz-scas64
+  0xF2 pack8 rex-w 0xAF pack8 ;
 
 
 ~ Arithmetic instructions
@@ -757,21 +843,25 @@ s" :cc-greater" keyword
 
 ~ (output point, source register, target register -- output point)
 : add-reg64-reg64
+  ~ : add-reg64-reg64
   3roll rex-w 0x01 pack8 3unroll
   swap reg64 swap addressing-reg64 ;
 
 ~ (output point, source register, target register -- output point)
 : add-indirect-reg64-reg64
+  ~ : add-indirect-reg64-reg64
   3roll rex-w 0x01 pack8 3unroll
   swap reg64 swap addressing-indirect-reg64 ;
 
 ~ (output point, source register, target register -- output point)
 : add-reg64-indirect-reg64
+  ~ : add-reg64-indirect-reg64
   3roll rex-w 0x03 pack8 3unroll
   reg64 swap addressing-indirect-reg64 ;
 
 ~ (output point, immediate value, target register -- output point)
 : add-reg64-imm8
+  ~ : add-reg64-imm8
   3roll rex-w 0x83 pack8 swap 0 swap addressing-reg64
   swap pack8 ;
 
@@ -779,11 +869,13 @@ s" :cc-greater" keyword
 ~
 ~ (output point, source register, target register -- output point)
 : sub-reg64-reg64
+  ~ : sub-reg64-reg64
   3roll rex-w 0x2B pack8 3unroll
   reg64 swap addressing-reg64 ;
 
 ~ (output point, source register, target register -- output point)
 : sub-indirect-reg64-reg64
+  ~ : sub-indirect-reg64-reg64
   3roll rex-w 0x2B pack8 3unroll
   swap reg64 swap addressing-indirect-reg64 ;
 
@@ -791,6 +883,7 @@ s" :cc-greater" keyword
 ~
 ~ (output point, immediate value, target register -- output point)
 : sub-reg64-imm8
+  ~ : sub-reg64-imm8
   3roll rex-w 0x83 pack8 swap 5 swap addressing-reg64
   swap pack8 ;
 
@@ -798,6 +891,7 @@ s" :cc-greater" keyword
 ~
 ~ (output point, source register, target register -- output point)
 : sbb-reg64-imm8
+  ~ : sbb-reg64-imm8
   3roll rex-w 0x83 pack8 swap 3 swap addressing-reg64
   swap pack8 ;
 
@@ -805,6 +899,7 @@ s" :cc-greater" keyword
 ~
 ~ (output point, source register -- output point)
 : mul-reg64
+  ~ : mul-reg64
   swap rex-w 0xF7 pack8 swap
   4 swap addressing-reg64 ;
 
@@ -817,6 +912,7 @@ s" :cc-greater" keyword
 ~
 ~ (output point, divisor register -- output point)
 : divmod-reg64
+  ~ : divmod-reg64
   swap rex-w 0xF7 pack8 swap
   6 swap addressing-reg64 ;
 
@@ -824,69 +920,82 @@ s" :cc-greater" keyword
 ~
 ~ (output point, divisor register -- output point)
 : idivmod-reg64
+  ~ : idivmod-reg64
   swap rex-w 0xF7 pack8 swap
   7 swap addressing-reg64 ;
 
 ~ (output point, target register -- output point)
 : inc-reg64
+  ~ : inc-reg64
   swap rex-w 0xFF pack8 swap 0 swap addressing-reg64 ;
 
 ~ (output point, target register -- output point)
 : dec-reg64
+  ~ : dec-reg64
   swap rex-w 0xFF pack8 swap 1 swap addressing-reg64 ;
 
 ~ (output point, source register, target register -- output point)
 : and-reg64-reg64
+  ~ : and-reg64-reg64
   3roll rex-w 0x23 pack8 3unroll
   reg64 swap addressing-reg64 ;
 
 ~ (output point, source value, target register -- output point)
 : and-reg64-imm8
+  ~ : and-reg64-imm8
   3roll rex-w 0x83 pack8 swap
   4 swap addressing-reg64
   swap pack8 ;
 
 ~ (output point, source register, target register -- output point)
 : or-reg64-reg64
+  ~ : or-reg64-reg64
   3roll rex-w 0x0B pack8 3unroll
   reg64 swap addressing-reg64 ;
 
 ~ (output point, source value, target register -- output point)
 : or-reg64-imm8
+  ~ : or-reg64-imm8
   3roll rex-w 0x83 pack8 swap
   1 swap addressing-reg64
   swap pack8 ;
 
 ~ (output point, source register, target register -- output point)
 : xor-reg64-reg64
+  ~ : xor-reg64-reg64
   3roll rex-w 0x33 pack8 3unroll
   reg64 swap addressing-reg64 ;
 
 ~ (output point, target register -- output point)
 : not-reg64
+  ~ : not-reg64
   swap rex-w 0xF7 pack8
   swap 2 swap addressing-reg64 ;
 
 ~ (output point, bit count, target register -- output point)
 : rol-reg64-imm8
+  ~ : rol-reg64-imm8
   3roll rex-w 0xC1 pack8 swap
   0 swap addressing-reg64
   swap pack8 ;
 
 ~ (output point, bit count, target register -- output point)
 : rol-reg8-imm8
+  ~ : rol-reg8-imm8
   3roll 0xC0 pack8 swap
   0 swap addressing-reg8
   swap pack8 ;
 
 ~ (output point, bit count, target register -- output point)
 : ror-reg64-imm8
+  ~ : ror-reg64-imm8
   3roll rex-w 0xC1 swap
   1 swap addressing-reg64
   swap pack8 ;
 
 ~ (output point, bit count, target register -- output point)
 : ror-reg8-imm8
+  ~ : ror-reg8-imm8
   3roll 0xC0 pack8 swap
   1 swap addressing-reg64
   swap pack8 ;
@@ -904,6 +1013,7 @@ s" :cc-greater" keyword
 ~
 ~ (output point, left register, right register -- output point)
 : cmp-reg64-reg64
+  ~ : cmp-reg64-reg64
   3roll rex-w 0x3B pack8 3unroll
   reg64 swap addressing-reg64 ;
 
@@ -911,6 +1021,7 @@ s" :cc-greater" keyword
 ~
 ~ (output point, immediate value, target register -- output point)
 : cmp-reg64-imm8
+  ~ : cmp-reg64-imm8
   3roll rex-w 0x83 pack8
   ~ (immediate value, register, output point)
   swap 7 swap addressing-reg64
@@ -926,38 +1037,45 @@ s" :cc-greater" keyword
 ~
 ~ (output point, left register, right register -- output point)
 : test-reg64-reg64
+  ~ : test-reg64-reg64
   3roll rex-w 0x85 pack8 3unroll
   swap reg64 swap addressing-reg64 ;
 
 ~ (output point, condition code, target register -- output point)
 : set-reg8-cc
+  ~ : set-reg8-cc
   3roll 0x0F pack8
   3roll condition-code 0x90 opcodecc
   swap reg8 3 0 3roll modrm ;
 
 ~ (output point, address offset value, condition code -- output point)
 : jmp-cc-rel-imm8
+  ~ : jmp-cc-rel-imm8
   3roll swap condition-code 0x70 opcodecc
   swap pack8 ;
 
 ~ (output point, address offset value, condition code -- output point)
 : jmp-cc-rel-imm32
+  ~ : jmp-cc-rel-imm32
   3unroll 0x0F pack8
   swap condition-code 0x70 opcodecc
   swap pack32 ;
 
 ~ (output point, register -- output point)
 : jmp-abs-indirect-reg64
+  ~ : jmp-abs-indirect-reg64
   swap 0xFF pack8 swap
   4 swap addressing-indirect-reg64 ;
 
 ~ (output point, address offset value -- output point)
 : jmp-rel-imm8
+  ~ : jmp-rel-imm8
   swap 0xEB pack8
   swap pack8 ;
 
 ~ (output point, address offset value -- output point)
 : jmp-rel-imm32
+  ~ : jmp-rel-imm32
   swap 0xE9 pack8
   swap pack32 ;
 
@@ -965,6 +1083,7 @@ s" :cc-greater" keyword
 ~
 ~ (output point, address offset value -- output point)
 : call-rel-imm32
+  ~ : call-rel-imm32
   swap 0xE8 pack8
   swap pack32 ;
 
@@ -972,5 +1091,6 @@ s" :cc-greater" keyword
 ~
 ~ (output point)
 : ret
+  ~ : ret
   0xC3 pack8 ;
 
diff --git a/transform.e b/transform.e
index eb8e8bf..3086968 100644
--- a/transform.e
+++ b/transform.e
@@ -2720,7 +2720,8 @@ allocate-transformation-state s" transformation-state" variable
 : hex-output-metadata-label-loop-buffer-start ;
 : hex-output-metadata-label-loop-buffer-length 8 + ;
 : hex-output-metadata-latest-output-point 2 8 * + ;
-: hex-output-metadata-first-entry 3 8 * + ;
+: hex-output-metadata-is-fresh-line 3 8 * + ;
+: hex-output-metadata-first-entry 4 8 * + ;
 : hex-output-metadata-entry-data-start ;
 : hex-output-metadata-entry-data-length 8 + ;
 : hex-output-metadata-entry-type 2 8 * + ;
@@ -2742,6 +2743,7 @@ allocate-transformation-state s" transformation-state" variable
   dup hex-output-metadata-label-loop-buffer-start 0 swap !
   dup hex-output-metadata-label-loop-buffer-length 0 swap !
   dup hex-output-metadata-latest-output-point 0 swap !
+  dup hex-output-metadata-is-fresh-line 1 swap !
   dup hex-output-metadata-first-entry 0 swap ! ;
 
 ~ (pointer -- boolean)
@@ -2937,11 +2939,28 @@ allocate-transformation-state s" transformation-state" variable
 
   s" swap" find entry-to-execution-token , ;
 
+: is-fresh-line@
+  transformation-state transformation-state-output-metadata @
+  hex-output-metadata-is-fresh-line @ ;
+
+: is-fresh-line!
+  transformation-state transformation-state-output-metadata @
+  hex-output-metadata-is-fresh-line ! ;
+
+: fresh-line is-fresh-line@ not { newline } if ;
+
 ~   This "replacement" is a little different from an alternate: When the code
 ~ under transformation attempts to compile its own version of sys-write, it
 ~ gets a stub that calls this word instead. It's swapped out by
 ~ hex-colon-alternate, whereas the regular alternates are swapped out by
 ~ hex-transform-one.
+~
+~   In the programs we're actually running the transform on, there's only ever
+~ a single call to sys-write which is the whole binary in one go, but we don't
+~ want to require that, so we keep all the formatting state in the output
+~ metadata. In particular, hex-output-metadata-entry-is-fresh-line is kept
+~ there.
+~
 ~ (length to write, base address --)
 : hex-sys-write-replacement
   { over } {
@@ -2956,12 +2975,15 @@ allocate-transformation-state s" transformation-state" variable
 
         dup hex-output-metadata-entry-type @
         hex-output-metadata-entry-type-line-comment = {
+          fresh-line
           dup hex-output-metadata-entry-string @ ." ~ " emitstring newline
+          1 is-fresh-line!
         } if
 
         dup hex-output-metadata-entry-type @
         hex-output-metadata-entry-type-line-break = {
           newline
+          1 is-fresh-line!
         } if
 
         dup hex-output-metadata-entry-type @
@@ -2972,6 +2994,7 @@ allocate-transformation-state s" transformation-state" variable
           dup hex-output-metadata-entry-string @ emitstring
           0x22 value@ emitstring drop
           newline
+          1 is-fresh-line!
         } if
 
         dup hex-output-metadata-entry-type @
@@ -2980,6 +3003,7 @@ allocate-transformation-state s" transformation-state" variable
           ." ~ Alignment padding to width "
           dup hex-output-metadata-entry-string @ .
           newline
+          1 is-fresh-line!
         } if
 
       } if
@@ -2988,6 +3012,8 @@ allocate-transformation-state s" transformation-state" variable
     drop
 
     dup 8@ .hex8 space
+    0 is-fresh-line!
+
     1+ swap 1- swap
   } while ;