Here are my notes for x86 code generation for some of the IR primitives. Note that the code generation logic contains optimizations (for example testing equality with 0, moving a register to itself, etc) and also some required tests (in sub_ovf the case where the destination register is the same as the second operand, to avoid clobbering the second operand).
Marc
-------------------------------------------------------------------------------
rptr $t_1 = get_ctx;
no-op. register allocator should assign context register to $t_1
-------------------------------------------------------------------------------
box $t_1 = load_box $t_2, K;
movq K( %REG($t_2) ), %REG($t_1)
-------------------------------------------------------------------------------
i64 $t_1 = and_box_i64 $t_2, K;
if K = 0 then
xorq %REG($t_1), %REG($t_1)
else
if %REG($t_1) != %REG($t_2) then
movq %REG($t_2), %REG($t_1)
endif
andq $K, %REG($t_1)
endif
-------------------------------------------------------------------------------
i64 $t_1 = and_box_i64 $t_2, $t_3;
if %REG($t_2) = %REG($t_3) then
if %REG($t_1) != %REG($t_2) then
movq %REG($t_2), %REG($t_1)
endif
elsif %REG($t_1) = %REG($t_2) then
andq %REG($t_3), %REG($t_1)
elseif %REG($t_1) = %REG($t_3) then
andq %REG($t_2), %REG($t_1)
else
movq %REG($t_2), %REG($t_1)
andq %REG($t_3), %REG($t_1)
endif
-------------------------------------------------------------------------------
i8 $t_1 = eq_i64 $t_2, K;
if K = 0 then
testq %REG($t_2), %REG($t_2)
else
cmpq $K, %REG($t_2)
endif
movb $0, %REG($t_1)
cmoveb $1, %REG($t_1)
-------------------------------------------------------------------------------
i8 $t_1 = eq_i64 $t_2, $t_3;
cmpq %REG($t_2), %REG($t_3)
movb $0, %REG($t_1)
cmoveb $1, %REG($t_1)
-------------------------------------------------------------------------------
if_i8 $t_1 then lbl1 else lbl2;
testb %REG($t_1), %REG($t_1)
if the if_i8 instruction is immediately followed by lbl1 then
je lbl2
elsif the if_i8 instruction is immediately followed by lbl2 then
jne lbl1
else
jne lbl1
jmp lbl2
endif
-------------------------------------------------------------------------------
box $t_1 = add_ovf $t_2, K normal lbl1 overflow lbl2;
if %REG($t_1) != %REG($t_2) then
movq %REG($t_2), %REG($t_1)
endif
if K = 1 then
incq %REG($t_1)
else
addq $K, %REG($t_1)
endif
if the add_ovf instruction is immediately followed by lbl1 then
jo lbl2
elsif the add_ovf instruction is immediately followed by lbl2 then
jno lbl1
else
jno lbl1
jmp lbl2
endif
-------------------------------------------------------------------------------
box $t_1 = add_ovf $t_2, $t_3 normal lbl1 overflow lbl2;
if %REG($t_1) != %REG($t_2) then
movq %REG($t_2), %REG($t_1)
endif
addq %REG($t_3), %REG($t_1)
if the add_ovf instruction is immediately followed by lbl1 then
jo lbl2
elsif the add_ovf instruction is immediately followed by lbl2 then
jno lbl1
else
jno lbl1
jmp lbl2
endif
-------------------------------------------------------------------------------
box $t_1 = sub_ovf $t_2, K normal lbl1 overflow lbl2;
if %REG($t_1) != %REG($t_2) then
movq %REG($t_2), %REG($t_1)
endif
if K = 1 then
decq %REG($t_1)
else
subq $K, %REG($t_1)
endif
if the sub_ovf instruction is immediately followed by lbl1 then
jo lbl2
elsif the sub_ovf instruction is immediately followed by lbl2 then
jno lbl1
else
jno lbl1
jmp lbl2
endif
-------------------------------------------------------------------------------
box $t_1 = sub_ovf $t_2, $t_3 normal lbl1 overflow lbl2;
if %REG($t_2) = %REG($t_3) then
xorq %REG($t_1), %REG($t_1)
else
if %REG($t_1) = %REG($t_3) then
movq %REG($t_3), %TEMP
movq %REG($t_2), %REG($t_1)
subq %TEMP, %REG($t_1)
// note: %TEMP can be a free register, stack or context slot
else
if %REG($t_1) != %REG($t_2) then
movq %REG($t_2), %REG($t_1)
endif
subq %REG($t_3), %REG($t_1)
endif
if the sub_ovf instruction is immediately followed by lbl1 then
jo lbl2
elsif the sub_ovf instruction is immediately followed by lbl2 then
jno lbl1
else
jno lbl1
jmp lbl2
endif
endif
-------------------------------------------------------------------------------