+* You cannot assume anything about the destination register dst;
+ it may be anything, includind a fixed reg.
+
+* You may compute a value into a fixed reg, but you may not
+ subsequently change the contents of that fixed reg. If you
+ want to do so, first copy the value either to a temporary
+ or into dst. You are free to modify dst even if it happens
+ to be a fixed reg -- that's not your problem.
+
+* You cannot assume that a fixed reg will stay live over an
+ arbitrary computation. The same applies to the dst reg.
+
+* Temporary regs obtained from getNewRegNCG are distinct from
+ all other regs, and stay live over arbitrary computations.
+
+\begin{code}
+
+infixr 3 `bind`
+x `bind` f = f x
+
+trivialCode instr maybe_revinstr a b
+
+ | is_imm_b
+ = getRegister a `thenUs` \ rega ->
+ let mkcode dst
+ = if isFloat rega
+ then registerCode rega dst `bind` \ code_a ->
+ code_a .
+ mkSeqInstr (instr (OpImm imm_b) (OpReg dst))
+ else registerCodeF rega `bind` \ code_a ->
+ registerNameF rega `bind` \ r_a ->
+ code_a .
+ mkSeqInstr (MOV L (OpReg r_a) (OpReg dst)) .
+ mkSeqInstr (instr (OpImm imm_b) (OpReg dst))
+ in
+ returnUs (Any IntRep mkcode)
+
+ | is_imm_a
+ = getRegister b `thenUs` \ regb ->
+ getNewRegNCG IntRep `thenUs` \ tmp ->
+ let revinstr_avail = maybeToBool maybe_revinstr
+ revinstr = case maybe_revinstr of Just ri -> ri
+ mkcode dst
+ | revinstr_avail
+ = if isFloat regb
+ then registerCode regb dst `bind` \ code_b ->
+ code_b .
+ mkSeqInstr (revinstr (OpImm imm_a) (OpReg dst))
+ else registerCodeF regb `bind` \ code_b ->
+ registerNameF regb `bind` \ r_b ->
+ code_b .
+ mkSeqInstr (MOV L (OpReg r_b) (OpReg dst)) .
+ mkSeqInstr (revinstr (OpImm imm_a) (OpReg dst))
+
+ | otherwise
+ = if isFloat regb
+ then registerCode regb tmp `bind` \ code_b ->
+ code_b .
+ mkSeqInstr (MOV L (OpImm imm_a) (OpReg dst)) .
+ mkSeqInstr (instr (OpReg tmp) (OpReg dst))
+ else registerCodeF regb `bind` \ code_b ->
+ registerNameF regb `bind` \ r_b ->
+ code_b .
+ mkSeqInstr (MOV L (OpReg r_b) (OpReg tmp)) .
+ mkSeqInstr (MOV L (OpImm imm_a) (OpReg dst)) .
+ mkSeqInstr (instr (OpReg tmp) (OpReg dst))
+ in
+ returnUs (Any IntRep mkcode)
+
+ | otherwise
+ = getRegister a `thenUs` \ rega ->
+ getRegister b `thenUs` \ regb ->
+ getNewRegNCG IntRep `thenUs` \ tmp ->
+ let mkcode dst
+ = case (isFloat rega, isFloat regb) of
+ (True, True)
+ -> registerCode regb tmp `bind` \ code_b ->
+ registerCode rega dst `bind` \ code_a ->
+ code_b .
+ code_a .
+ mkSeqInstr (instr (OpReg tmp) (OpReg dst))
+ (True, False)
+ -> registerCode rega tmp `bind` \ code_a ->
+ registerCodeF regb `bind` \ code_b ->
+ registerNameF regb `bind` \ r_b ->
+ code_a .
+ code_b .
+ mkSeqInstr (instr (OpReg r_b) (OpReg tmp)) .
+ mkSeqInstr (MOV L (OpReg tmp) (OpReg dst))
+ (False, True)
+ -> registerCode regb tmp `bind` \ code_b ->
+ registerCodeF rega `bind` \ code_a ->
+ registerNameF rega `bind` \ r_a ->
+ code_b .
+ code_a .
+ mkSeqInstr (MOV L (OpReg r_a) (OpReg dst)) .
+ mkSeqInstr (instr (OpReg tmp) (OpReg dst))
+ (False, False)
+ -> registerCodeF rega `bind` \ code_a ->
+ registerNameF rega `bind` \ r_a ->
+ registerCodeF regb `bind` \ code_b ->
+ registerNameF regb `bind` \ r_b ->
+ code_a .
+ mkSeqInstr (MOV L (OpReg r_a) (OpReg tmp)) .
+ code_b .
+ mkSeqInstr (instr (OpReg r_b) (OpReg tmp)) .
+ mkSeqInstr (MOV L (OpReg tmp) (OpReg dst))
+ in
+ returnUs (Any IntRep mkcode)
+
+ where
+ maybe_imm_a = maybeImm a
+ is_imm_a = maybeToBool maybe_imm_a
+ imm_a = case maybe_imm_a of Just imm -> imm
+
+ maybe_imm_b = maybeImm b
+ is_imm_b = maybeToBool maybe_imm_b
+ imm_b = case maybe_imm_b of Just imm -> imm