[MLton-commit] r6690

Wesley Terpstra wesley at mlton.org
Thu Aug 7 10:09:22 PDT 2008


When the assembler gets an instruction
	movq $immediate, %rax
it needs to put the immediate into machine code. On amd64 32-bit immediates 
are sign extended to 64-bit by the processor. 64-bit immediates are possible
only with movq and cannot be used with addq/etc. MLton already knows that if
a 64 bit immediate cannot be represented as the sign extension of a 32 bit
value, it must first movq the value into a register, eg:
	movq $0x1234567890, %rax
	addq %rax, %rbx
because
	addq $0x1234567890, %rax
is invalid assembler.

The problem this patch addresses is the corner case of an immediate that is
32 bit with the high bit set. There is no 32 bit value which will be correct
after sign extension, so MLton will never generate an instruction using this
immediate without going first via a movq. However, when the assembler sees
movq with this immediate, it must decide between 64-bit and 32-bit encodings. 
The gas in debian will choose a 64-bit. The (newer) gas on win64 chooses a 
32-bit immediate. These have different results:

movq $0xFFFFFFFF, %rax --- when 32bit: %rax = 0xFFFFFFFFFFFFFFFF = ~1
movq $0xFFFFFFFF, %rax --- when 64bit: %rax = 0x00000000FFFFFFFF

Mlton always expects the assembler to produce the second case.

Fortunately, there is an easy fix which also produces smaller machine code:
	movl $3, %eax
32-bit operations on amd64 implicitly zero extend the result register. This
instruction is completely equivalent to
	movq $3, %rax
By exploiting this implicit zero extension, we can be unambiguous with movl:
	movl $0xFFFFFFFF, %eax --- always sets %rax = 0x00000000FFFFFFFF

Therefore, whenever the destination register is 64 bit, and the operand has
<= 32 bits, use a movl. This will always do what MLton expects. If the value
cannot be fit into a 32 bit immediate, output a movq with confidence that the 
assembler has no choice but the 64 bit encoding.


----------------------------------------------------------------------

U   mlton/trunk/mlton/codegen/amd64-codegen/amd64-allocate-registers.fun

----------------------------------------------------------------------

Modified: mlton/trunk/mlton/codegen/amd64-codegen/amd64-allocate-registers.fun
===================================================================
--- mlton/trunk/mlton/codegen/amd64-codegen/amd64-allocate-registers.fun	2008-08-06 00:21:53 UTC (rev 6689)
+++ mlton/trunk/mlton/codegen/amd64-codegen/amd64-allocate-registers.fun	2008-08-07 17:09:20 UTC (rev 6690)
@@ -4068,11 +4068,19 @@
             val _ = Int.dec depth
             val instruction
               = case Immediate.destruct immediate of
-                   Immediate.Word _ =>
-                      Assembly.instruction_mov 
-                      {dst = Operand.Register final_register,
-                       src = Operand.Immediate immediate,
-                       size = size}
+                   Immediate.Word x =>
+                      if size = Size.QUAD andalso
+                         WordX.equals (x, WordX.resize (WordX.resize (x, WordSize.word32), WordSize.word64))
+                      then (* use the implicit zero-extend of 32 bit ops *)
+                       Assembly.instruction_mov 
+                       {dst = Operand.Register (Register.lowPartOf (final_register, Size.LONG)),
+                        src = Operand.immediate_word (WordX.resize (x, WordSize.word32)),
+                        size = Size.LONG}
+                      else
+                       Assembly.instruction_mov 
+                       {dst = Operand.Register final_register,
+                        src = Operand.Immediate immediate,
+                        size = size}
                  | _ =>
                       Assembly.instruction_lea
                       {dst = Operand.Register final_register,




More information about the MLton-commit mailing list