summary refs log tree commit diff
path: root/amd64.e
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2026-05-28 20:48:37 -0700
committerIrene Knapp <ireneista@irenes.space>2026-05-28 20:48:37 -0700
commit5e7b34b259ae56513294087426a237e778605f64 (patch)
tree4dccc8e328ee6d8efb95a1b3a2ba69d6d16d5cc1 /amd64.e
parent3b00a5376036bb3f50a1a1f97d136305a2d03a57 (diff)
better documentation of parameter order for arithmetic instructions
Force-Push: yes
Change-Id: I02af0267657cf21fcf4e4d79457645da42f6798d
Diffstat (limited to 'amd64.e')
-rw-r--r--amd64.e32
1 files changed, 20 insertions, 12 deletions
diff --git a/amd64.e b/amd64.e
index 2060a3d..f755112 100644
--- a/amd64.e
+++ b/amd64.e
@@ -746,6 +746,16 @@ s" :cc-greater" keyword
 
 ~ Arithmetic instructions
 ~ ~~~~~~~~~~~~~~~~~~~~~~~
+~
+~   Operations between two registers always have the target register as the
+~ last parameter. Operations between a register and an immediate ALSO have the
+~ target register as the last parameter, which is obvious for add-reg64-imm8
+~ but can be confusing for sub-reg64-imm8 or cmp-reg64-imm8. Also note what
+~ this means for sub-reg64-reg64 and cmp-reg64-reg64.
+~
+~   Every possible convention here leads to counterintuitive behavior in some
+~ cases. This one has proven to be more memorable than the other obvious
+~ choices, and that'll have to be enough.
 
 ~ (output point, source register, target register -- output point)
 : add-reg64-reg64
@@ -762,13 +772,13 @@ s" :cc-greater" keyword
   3roll rex-w 0x03 pack8 3unroll
   reg64 swap addressing-indirect-reg64 ;
 
-~ TODO needs description of argument order considerations
-~
 ~ (output point, immediate value, target register -- output point)
 : add-reg64-imm8
   3roll rex-w 0x83 pack8 swap 0 swap addressing-reg64
   swap pack8 ;
 
+~ See above re: parameter order.
+~
 ~ (output point, source register, target register -- output point)
 : sub-reg64-reg64
   3roll rex-w 0x2B pack8 3unroll
@@ -779,14 +789,15 @@ s" :cc-greater" keyword
   3roll rex-w 0x2B pack8 3unroll
   swap reg64 swap addressing-indirect-reg64 ;
 
-~ TODO this convention is unlike other arithmetic operations. See the note
-~ on cmp-reg64-imm8, pick one to go with, and document it.
+~ See above re: parameter order.
 ~
 ~ (output point, immediate value, target register -- output point)
 : sub-reg64-imm8
   3roll rex-w 0x83 pack8 swap 5 swap addressing-reg64
   swap pack8 ;
 
+~ See above re: parameter order.
+~
 ~ (output point, source register, target register -- output point)
 : sbb-reg64-imm8
   3roll rex-w 0x83 pack8 swap 3 swap addressing-reg64
@@ -885,6 +896,10 @@ s" :cc-greater" keyword
 
 ~ Control flow instructions
 ~ ~~~~~~~~~~~~~~~~~~~~~~~~~
+~
+~   The comparator instructions cmp and test follow the same argument-order
+~ conventions as the arithmetic instructions: The target register always comes
+~ last. See the arithmetic section for more discussion.
 
 ~   Pretend to subtract right from left, and set the flags the same way as if
 ~ we actually had.
@@ -894,14 +909,7 @@ s" :cc-greater" keyword
   3roll rex-w 0x3B pack8 3unroll
   reg64 swap addressing-reg64 ;
 
-~   The parameter order here is weird, so take note. In a comparison between
-~ a register and an immediate value, it makes sense to think of the register
-~ as the target... but instead we opt to be consistent with the other cmp
-~ instructions, which in turn are consistent with the sub instructions, in
-~ which we put the left operand first because subtraction is not commutative.
-~ TODO wrong, backwards, other choice
-~
-~ TODO the immediate arithmetic instructions are all documented wrong
+~ See above re: parameter order.
 ~
 ~ (output point, immediate value, target register -- output point)
 : cmp-reg64-imm8