1 module Alpha.CodeGen ()
7 getRegister :: CmmExpr -> NatM Register
9 #if !x86_64_TARGET_ARCH
10 -- on x86_64, we have %rip for PicBaseReg, but it's not a full-featured
11 -- register, it can only be used for rip-relative addressing.
12 getRegister (CmmReg (CmmGlobal PicBaseReg))
14 reg <- getPicBaseNat wordSize
15 return (Fixed wordSize reg nilOL)
18 getRegister (CmmReg reg)
19 = return (Fixed (cmmTypeSize (cmmRegType reg))
20 (getRegisterReg reg) nilOL)
22 getRegister tree@(CmmRegOff _ _)
23 = getRegister (mangleIndexTree tree)
26 #if WORD_SIZE_IN_BITS==32
27 -- for 32-bit architectuers, support some 64 -> 32 bit conversions:
28 -- TO_W_(x), TO_W_(x >> 32)
30 getRegister (CmmMachOp (MO_UU_Conv W64 W32)
31 [CmmMachOp (MO_U_Shr W64) [x,CmmLit (CmmInt 32 _)]]) = do
32 ChildCode64 code rlo <- iselExpr64 x
33 return $ Fixed II32 (getHiVRegFromLo rlo) code
35 getRegister (CmmMachOp (MO_SS_Conv W64 W32)
36 [CmmMachOp (MO_U_Shr W64) [x,CmmLit (CmmInt 32 _)]]) = do
37 ChildCode64 code rlo <- iselExpr64 x
38 return $ Fixed II32 (getHiVRegFromLo rlo) code
40 getRegister (CmmMachOp (MO_UU_Conv W64 W32) [x]) = do
41 ChildCode64 code rlo <- iselExpr64 x
42 return $ Fixed II32 rlo code
44 getRegister (CmmMachOp (MO_SS_Conv W64 W32) [x]) = do
45 ChildCode64 code rlo <- iselExpr64 x
46 return $ Fixed II32 rlo code
50 -- end of machine-"independent" bit; here we go on the rest...
53 getRegister (StDouble d)
54 = getBlockIdNat `thenNat` \ lbl ->
55 getNewRegNat PtrRep `thenNat` \ tmp ->
56 let code dst = mkSeqInstrs [
57 LDATA RoDataSegment lbl [
58 DATA TF [ImmLab (rational d)]
60 LDA tmp (AddrImm (ImmCLbl lbl)),
61 LD TF dst (AddrReg tmp)]
63 return (Any FF64 code)
65 getRegister (StPrim primop [x]) -- unary PrimOps
67 IntNegOp -> trivialUCode (NEG Q False) x
69 NotOp -> trivialUCode NOT x
71 FloatNegOp -> trivialUFCode FloatRep (FNEG TF) x
72 DoubleNegOp -> trivialUFCode FF64 (FNEG TF) x
74 OrdOp -> coerceIntCode IntRep x
77 Float2IntOp -> coerceFP2Int x
78 Int2FloatOp -> coerceInt2FP pr x
79 Double2IntOp -> coerceFP2Int x
80 Int2DoubleOp -> coerceInt2FP pr x
82 Double2FloatOp -> coerceFltCode x
83 Float2DoubleOp -> coerceFltCode x
85 other_op -> getRegister (StCall fn CCallConv FF64 [x])
88 FloatExpOp -> fsLit "exp"
89 FloatLogOp -> fsLit "log"
90 FloatSqrtOp -> fsLit "sqrt"
91 FloatSinOp -> fsLit "sin"
92 FloatCosOp -> fsLit "cos"
93 FloatTanOp -> fsLit "tan"
94 FloatAsinOp -> fsLit "asin"
95 FloatAcosOp -> fsLit "acos"
96 FloatAtanOp -> fsLit "atan"
97 FloatSinhOp -> fsLit "sinh"
98 FloatCoshOp -> fsLit "cosh"
99 FloatTanhOp -> fsLit "tanh"
100 DoubleExpOp -> fsLit "exp"
101 DoubleLogOp -> fsLit "log"
102 DoubleSqrtOp -> fsLit "sqrt"
103 DoubleSinOp -> fsLit "sin"
104 DoubleCosOp -> fsLit "cos"
105 DoubleTanOp -> fsLit "tan"
106 DoubleAsinOp -> fsLit "asin"
107 DoubleAcosOp -> fsLit "acos"
108 DoubleAtanOp -> fsLit "atan"
109 DoubleSinhOp -> fsLit "sinh"
110 DoubleCoshOp -> fsLit "cosh"
111 DoubleTanhOp -> fsLit "tanh"
113 pr = panic "MachCode.getRegister: no primrep needed for Alpha"
115 getRegister (StPrim primop [x, y]) -- dyadic PrimOps
117 CharGtOp -> trivialCode (CMP LTT) y x
118 CharGeOp -> trivialCode (CMP LE) y x
119 CharEqOp -> trivialCode (CMP EQQ) x y
120 CharNeOp -> int_NE_code x y
121 CharLtOp -> trivialCode (CMP LTT) x y
122 CharLeOp -> trivialCode (CMP LE) x y
124 IntGtOp -> trivialCode (CMP LTT) y x
125 IntGeOp -> trivialCode (CMP LE) y x
126 IntEqOp -> trivialCode (CMP EQQ) x y
127 IntNeOp -> int_NE_code x y
128 IntLtOp -> trivialCode (CMP LTT) x y
129 IntLeOp -> trivialCode (CMP LE) x y
131 WordGtOp -> trivialCode (CMP ULT) y x
132 WordGeOp -> trivialCode (CMP ULE) x y
133 WordEqOp -> trivialCode (CMP EQQ) x y
134 WordNeOp -> int_NE_code x y
135 WordLtOp -> trivialCode (CMP ULT) x y
136 WordLeOp -> trivialCode (CMP ULE) x y
138 AddrGtOp -> trivialCode (CMP ULT) y x
139 AddrGeOp -> trivialCode (CMP ULE) y x
140 AddrEqOp -> trivialCode (CMP EQQ) x y
141 AddrNeOp -> int_NE_code x y
142 AddrLtOp -> trivialCode (CMP ULT) x y
143 AddrLeOp -> trivialCode (CMP ULE) x y
145 FloatGtOp -> cmpF_code (FCMP TF LE) EQQ x y
146 FloatGeOp -> cmpF_code (FCMP TF LTT) EQQ x y
147 FloatEqOp -> cmpF_code (FCMP TF EQQ) NE x y
148 FloatNeOp -> cmpF_code (FCMP TF EQQ) EQQ x y
149 FloatLtOp -> cmpF_code (FCMP TF LTT) NE x y
150 FloatLeOp -> cmpF_code (FCMP TF LE) NE x y
152 DoubleGtOp -> cmpF_code (FCMP TF LE) EQQ x y
153 DoubleGeOp -> cmpF_code (FCMP TF LTT) EQQ x y
154 DoubleEqOp -> cmpF_code (FCMP TF EQQ) NE x y
155 DoubleNeOp -> cmpF_code (FCMP TF EQQ) EQQ x y
156 DoubleLtOp -> cmpF_code (FCMP TF LTT) NE x y
157 DoubleLeOp -> cmpF_code (FCMP TF LE) NE x y
159 IntAddOp -> trivialCode (ADD Q False) x y
160 IntSubOp -> trivialCode (SUB Q False) x y
161 IntMulOp -> trivialCode (MUL Q False) x y
162 IntQuotOp -> trivialCode (DIV Q False) x y
163 IntRemOp -> trivialCode (REM Q False) x y
165 WordAddOp -> trivialCode (ADD Q False) x y
166 WordSubOp -> trivialCode (SUB Q False) x y
167 WordMulOp -> trivialCode (MUL Q False) x y
168 WordQuotOp -> trivialCode (DIV Q True) x y
169 WordRemOp -> trivialCode (REM Q True) x y
171 FloatAddOp -> trivialFCode W32 (FADD TF) x y
172 FloatSubOp -> trivialFCode W32 (FSUB TF) x y
173 FloatMulOp -> trivialFCode W32 (FMUL TF) x y
174 FloatDivOp -> trivialFCode W32 (FDIV TF) x y
176 DoubleAddOp -> trivialFCode W64 (FADD TF) x y
177 DoubleSubOp -> trivialFCode W64 (FSUB TF) x y
178 DoubleMulOp -> trivialFCode W64 (FMUL TF) x y
179 DoubleDivOp -> trivialFCode W64 (FDIV TF) x y
181 AddrAddOp -> trivialCode (ADD Q False) x y
182 AddrSubOp -> trivialCode (SUB Q False) x y
183 AddrRemOp -> trivialCode (REM Q True) x y
185 AndOp -> trivialCode AND x y
186 OrOp -> trivialCode OR x y
187 XorOp -> trivialCode XOR x y
188 SllOp -> trivialCode SLL x y
189 SrlOp -> trivialCode SRL x y
191 ISllOp -> trivialCode SLL x y -- was: panic "AlphaGen:isll"
192 ISraOp -> trivialCode SRA x y -- was: panic "AlphaGen:isra"
193 ISrlOp -> trivialCode SRL x y -- was: panic "AlphaGen:isrl"
195 FloatPowerOp -> getRegister (StCall (fsLit "pow") CCallConv FF64 [x,y])
196 DoublePowerOp -> getRegister (StCall (fsLit "pow") CCallConv FF64 [x,y])
198 {- ------------------------------------------------------------
199 Some bizarre special code for getting condition codes into
200 registers. Integer non-equality is a test for equality
201 followed by an XOR with 1. (Integer comparisons always set
202 the result register to 0 or 1.) Floating point comparisons of
203 any kind leave the result in a floating point register, so we
204 need to wrangle an integer register out of things.
206 int_NE_code :: StixTree -> StixTree -> NatM Register
209 = trivialCode (CMP EQQ) x y `thenNat` \ register ->
210 getNewRegNat IntRep `thenNat` \ tmp ->
212 code = registerCode register tmp
213 src = registerName register tmp
214 code__2 dst = code . mkSeqInstr (XOR src (RIImm (ImmInt 1)) dst)
216 return (Any IntRep code__2)
218 {- ------------------------------------------------------------
219 Comments for int_NE_code also apply to cmpF_code
222 :: (Reg -> Reg -> Reg -> Instr)
224 -> StixTree -> StixTree
227 cmpF_code instr cond x y
228 = trivialFCode pr instr x y `thenNat` \ register ->
229 getNewRegNat FF64 `thenNat` \ tmp ->
230 getBlockIdNat `thenNat` \ lbl ->
232 code = registerCode register tmp
233 result = registerName register tmp
235 code__2 dst = code . mkSeqInstrs [
236 OR zeroh (RIImm (ImmInt 1)) dst,
237 BF cond result (ImmCLbl lbl),
238 OR zeroh (RIReg zeroh) dst,
241 return (Any IntRep code__2)
243 pr = panic "trivialU?FCode: does not use PrimRep on Alpha"
244 ------------------------------------------------------------
246 getRegister (CmmLoad pk mem)
247 = getAmode mem `thenNat` \ amode ->
249 code = amodeCode amode
250 src = amodeAddr amode
251 size = primRepToSize pk
252 code__2 dst = code . mkSeqInstr (LD size dst src)
254 return (Any pk code__2)
256 getRegister (StInt i)
259 code dst = mkSeqInstr (OR zeroh (RIImm src) dst)
261 return (Any IntRep code)
264 code dst = mkSeqInstr (LDI Q dst src)
266 return (Any IntRep code)
268 src = ImmInt (fromInteger i)
273 code dst = mkSeqInstr (LDA dst (AddrImm imm__2))
275 return (Any PtrRep code)
278 imm__2 = case imm of Just x -> x
281 getAmode :: CmmExpr -> NatM Amode
282 getAmode tree@(CmmRegOff _ _) = getAmode (mangleIndexTree tree)
284 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
286 #if alpha_TARGET_ARCH
288 getAmode (StPrim IntSubOp [x, StInt i])
289 = getNewRegNat PtrRep `thenNat` \ tmp ->
290 getRegister x `thenNat` \ register ->
292 code = registerCode register tmp
293 reg = registerName register tmp
294 off = ImmInt (-(fromInteger i))
296 return (Amode (AddrRegImm reg off) code)
298 getAmode (StPrim IntAddOp [x, StInt i])
299 = getNewRegNat PtrRep `thenNat` \ tmp ->
300 getRegister x `thenNat` \ register ->
302 code = registerCode register tmp
303 reg = registerName register tmp
304 off = ImmInt (fromInteger i)
306 return (Amode (AddrRegImm reg off) code)
310 = return (Amode (AddrImm imm__2) id)
313 imm__2 = case imm of Just x -> x
316 = getNewRegNat PtrRep `thenNat` \ tmp ->
317 getRegister other `thenNat` \ register ->
319 code = registerCode register tmp
320 reg = registerName register tmp
322 return (Amode (AddrReg reg) code)
324 #endif /* alpha_TARGET_ARCH */
327 -- -----------------------------------------------------------------------------
328 -- Generating assignments
330 -- Assignments are really at the heart of the whole code generation
331 -- business. Almost all top-level nodes of any real importance are
332 -- assignments, which correspond to loads, stores, or register
333 -- transfers. If we're really lucky, some of the register transfers
334 -- will go away, because we can use the destination register to
335 -- complete the code generation for the right hand side. This only
336 -- fails when the right hand side is forced into a fixed register
337 -- (e.g. the result of a call).
339 assignMem_IntCode :: Size -> CmmExpr -> CmmExpr -> NatM InstrBlock
340 assignReg_IntCode :: Size -> CmmReg -> CmmExpr -> NatM InstrBlock
342 assignMem_FltCode :: Size -> CmmExpr -> CmmExpr -> NatM InstrBlock
343 assignReg_FltCode :: Size -> CmmReg -> CmmExpr -> NatM InstrBlock
346 assignIntCode pk (CmmLoad dst _) src
347 = getNewRegNat IntRep `thenNat` \ tmp ->
348 getAmode dst `thenNat` \ amode ->
349 getRegister src `thenNat` \ register ->
351 code1 = amodeCode amode []
352 dst__2 = amodeAddr amode
353 code2 = registerCode register tmp []
354 src__2 = registerName register tmp
355 sz = primRepToSize pk
356 code__2 = asmSeqThen [code1, code2] . mkSeqInstr (ST sz src__2 dst__2)
360 assignIntCode pk dst src
361 = getRegister dst `thenNat` \ register1 ->
362 getRegister src `thenNat` \ register2 ->
364 dst__2 = registerName register1 zeroh
365 code = registerCode register2 dst__2
366 src__2 = registerName register2 dst__2
367 code__2 = if isFixed register2
368 then code . mkSeqInstr (OR src__2 (RIReg src__2) dst__2)
373 assignFltCode pk (CmmLoad dst _) src
374 = getNewRegNat pk `thenNat` \ tmp ->
375 getAmode dst `thenNat` \ amode ->
376 getRegister src `thenNat` \ register ->
378 code1 = amodeCode amode []
379 dst__2 = amodeAddr amode
380 code2 = registerCode register tmp []
381 src__2 = registerName register tmp
382 sz = primRepToSize pk
383 code__2 = asmSeqThen [code1, code2] . mkSeqInstr (ST sz src__2 dst__2)
387 assignFltCode pk dst src
388 = getRegister dst `thenNat` \ register1 ->
389 getRegister src `thenNat` \ register2 ->
391 dst__2 = registerName register1 zeroh
392 code = registerCode register2 dst__2
393 src__2 = registerName register2 dst__2
394 code__2 = if isFixed register2
395 then code . mkSeqInstr (FMOV src__2 dst__2)
401 -- -----------------------------------------------------------------------------
402 -- Generating an non-local jump
404 -- (If applicable) Do not fill the delay slots here; you will confuse the
405 -- register allocator.
407 genJump :: CmmExpr{-the branch target-} -> NatM InstrBlock
409 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
412 genJump (CmmLabel lbl)
413 | isAsmTemp lbl = returnInstr (BR target)
414 | otherwise = returnInstrs [LDA pv (AddrImm target), JMP zeroh (AddrReg pv) 0]
419 = getRegister tree `thenNat` \ register ->
420 getNewRegNat PtrRep `thenNat` \ tmp ->
422 dst = registerName register pv
423 code = registerCode register pv
424 target = registerName register pv
426 if isFixed register then
427 returnSeq code [OR dst (RIReg dst) pv, JMP zeroh (AddrReg pv) 0]
429 return (code . mkSeqInstr (JMP zeroh (AddrReg pv) 0))
432 -- -----------------------------------------------------------------------------
433 -- Unconditional branches
435 genBranch :: BlockId -> NatM InstrBlock
437 genBranch = return . toOL . mkBranchInstr
440 -- -----------------------------------------------------------------------------
444 Conditional jumps are always to local labels, so we can use branch
445 instructions. We peek at the arguments to decide what kind of
448 ALPHA: For comparisons with 0, we're laughing, because we can just do
449 the desired conditional branch.
455 :: BlockId -- the branch target
456 -> CmmExpr -- the condition on which to branch
459 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
461 genCondJump id (StPrim op [x, StInt 0])
462 = getRegister x `thenNat` \ register ->
463 getNewRegNat (registerRep register)
466 code = registerCode register tmp
467 value = registerName register tmp
468 pk = registerRep register
471 returnSeq code [BI (cmpOp op) value target]
486 cmpOp WordGeOp = ALWAYS
489 cmpOp WordLtOp = NEVER
492 cmpOp AddrGeOp = ALWAYS
495 cmpOp AddrLtOp = NEVER
498 genCondJump lbl (StPrim op [x, StDouble 0.0])
499 = getRegister x `thenNat` \ register ->
500 getNewRegNat (registerRep register)
503 code = registerCode register tmp
504 value = registerName register tmp
505 pk = registerRep register
508 return (code . mkSeqInstr (BF (cmpOp op) value target))
510 cmpOp FloatGtOp = GTT
512 cmpOp FloatEqOp = EQQ
514 cmpOp FloatLtOp = LTT
516 cmpOp DoubleGtOp = GTT
517 cmpOp DoubleGeOp = GE
518 cmpOp DoubleEqOp = EQQ
519 cmpOp DoubleNeOp = NE
520 cmpOp DoubleLtOp = LTT
521 cmpOp DoubleLeOp = LE
523 genCondJump lbl (StPrim op [x, y])
525 = trivialFCode pr instr x y `thenNat` \ register ->
526 getNewRegNat FF64 `thenNat` \ tmp ->
528 code = registerCode register tmp
529 result = registerName register tmp
532 return (code . mkSeqInstr (BF cond result target))
534 pr = panic "trivialU?FCode: does not use PrimRep on Alpha"
536 fltCmpOp op = case op of
550 (instr, cond) = case op of
551 FloatGtOp -> (FCMP TF LE, EQQ)
552 FloatGeOp -> (FCMP TF LTT, EQQ)
553 FloatEqOp -> (FCMP TF EQQ, NE)
554 FloatNeOp -> (FCMP TF EQQ, EQQ)
555 FloatLtOp -> (FCMP TF LTT, NE)
556 FloatLeOp -> (FCMP TF LE, NE)
557 DoubleGtOp -> (FCMP TF LE, EQQ)
558 DoubleGeOp -> (FCMP TF LTT, EQQ)
559 DoubleEqOp -> (FCMP TF EQQ, NE)
560 DoubleNeOp -> (FCMP TF EQQ, EQQ)
561 DoubleLtOp -> (FCMP TF LTT, NE)
562 DoubleLeOp -> (FCMP TF LE, NE)
564 genCondJump lbl (StPrim op [x, y])
565 = trivialCode instr x y `thenNat` \ register ->
566 getNewRegNat IntRep `thenNat` \ tmp ->
568 code = registerCode register tmp
569 result = registerName register tmp
572 return (code . mkSeqInstr (BI cond result target))
574 (instr, cond) = case op of
575 CharGtOp -> (CMP LE, EQQ)
576 CharGeOp -> (CMP LTT, EQQ)
577 CharEqOp -> (CMP EQQ, NE)
578 CharNeOp -> (CMP EQQ, EQQ)
579 CharLtOp -> (CMP LTT, NE)
580 CharLeOp -> (CMP LE, NE)
581 IntGtOp -> (CMP LE, EQQ)
582 IntGeOp -> (CMP LTT, EQQ)
583 IntEqOp -> (CMP EQQ, NE)
584 IntNeOp -> (CMP EQQ, EQQ)
585 IntLtOp -> (CMP LTT, NE)
586 IntLeOp -> (CMP LE, NE)
587 WordGtOp -> (CMP ULE, EQQ)
588 WordGeOp -> (CMP ULT, EQQ)
589 WordEqOp -> (CMP EQQ, NE)
590 WordNeOp -> (CMP EQQ, EQQ)
591 WordLtOp -> (CMP ULT, NE)
592 WordLeOp -> (CMP ULE, NE)
593 AddrGtOp -> (CMP ULE, EQQ)
594 AddrGeOp -> (CMP ULT, EQQ)
595 AddrEqOp -> (CMP EQQ, NE)
596 AddrNeOp -> (CMP EQQ, EQQ)
597 AddrLtOp -> (CMP ULT, NE)
598 AddrLeOp -> (CMP ULE, NE)
600 -- -----------------------------------------------------------------------------
601 -- Generating C calls
603 -- Now the biggest nightmare---calls. Most of the nastiness is buried in
604 -- @get_arg@, which moves the arguments to the correct registers/stack
605 -- locations. Apart from that, the code is easy.
607 -- (If applicable) Do not fill the delay slots here; you will confuse the
608 -- register allocator.
611 :: CmmCallTarget -- function to call
612 -> HintedCmmFormals -- where to put the result
613 -> HintedCmmActuals -- arguments (of mixed type)
616 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
620 genCCall fn cconv result_regs args
621 = mapAccumLNat get_arg (allArgRegs, eXTRA_STK_ARGS_HERE) args
622 `thenNat` \ ((unused,_), argCode) ->
624 nRegs = length allArgRegs - length unused
625 code = asmSeqThen (map ($ []) argCode)
628 LDA pv (AddrImm (ImmLab (ptext fn))),
629 JSR ra (AddrReg pv) nRegs,
630 LDGP gp (AddrReg ra)]
632 ------------------------
633 {- Try to get a value into a specific register (or registers) for
634 a call. The first 6 arguments go into the appropriate
635 argument register (separate registers for integer and floating
636 point arguments, but used in lock-step), and the remaining
637 arguments are dumped to the stack, beginning at 0(sp). Our
638 first argument is a pair of the list of remaining argument
639 registers to be assigned for this call and the next stack
640 offset to use for overflowing arguments. This way,
641 @get_Arg@ can be applied to all of a call's arguments using
645 :: ([(Reg,Reg)], Int) -- Argument registers and stack offset (accumulator)
646 -> StixTree -- Current argument
647 -> NatM (([(Reg,Reg)],Int), InstrBlock) -- Updated accumulator and code
649 -- We have to use up all of our argument registers first...
651 get_arg ((iDst,fDst):dsts, offset) arg
652 = getRegister arg `thenNat` \ register ->
654 reg = if isFloatType pk then fDst else iDst
655 code = registerCode register reg
656 src = registerName register reg
657 pk = registerRep register
660 if isFloatType pk then
661 ((dsts, offset), if isFixed register then
662 code . mkSeqInstr (FMOV src fDst)
665 ((dsts, offset), if isFixed register then
666 code . mkSeqInstr (OR src (RIReg src) iDst)
669 -- Once we have run out of argument registers, we move to the
672 get_arg ([], offset) arg
673 = getRegister arg `thenNat` \ register ->
674 getNewRegNat (registerRep register)
677 code = registerCode register tmp
678 src = registerName register tmp
679 pk = registerRep register
680 sz = primRepToSize pk
682 return (([], offset + 1), code . mkSeqInstr (ST sz src (spRel offset)))
684 trivialCode instr x (StInt y)
686 = getRegister x `thenNat` \ register ->
687 getNewRegNat IntRep `thenNat` \ tmp ->
689 code = registerCode register tmp
690 src1 = registerName register tmp
691 src2 = ImmInt (fromInteger y)
692 code__2 dst = code . mkSeqInstr (instr src1 (RIImm src2) dst)
694 return (Any IntRep code__2)
696 trivialCode instr x y
697 = getRegister x `thenNat` \ register1 ->
698 getRegister y `thenNat` \ register2 ->
699 getNewRegNat IntRep `thenNat` \ tmp1 ->
700 getNewRegNat IntRep `thenNat` \ tmp2 ->
702 code1 = registerCode register1 tmp1 []
703 src1 = registerName register1 tmp1
704 code2 = registerCode register2 tmp2 []
705 src2 = registerName register2 tmp2
706 code__2 dst = asmSeqThen [code1, code2] .
707 mkSeqInstr (instr src1 (RIReg src2) dst)
709 return (Any IntRep code__2)
713 = getRegister x `thenNat` \ register ->
714 getNewRegNat IntRep `thenNat` \ tmp ->
716 code = registerCode register tmp
717 src = registerName register tmp
718 code__2 dst = code . mkSeqInstr (instr (RIReg src) dst)
720 return (Any IntRep code__2)
723 trivialFCode _ instr x y
724 = getRegister x `thenNat` \ register1 ->
725 getRegister y `thenNat` \ register2 ->
726 getNewRegNat FF64 `thenNat` \ tmp1 ->
727 getNewRegNat FF64 `thenNat` \ tmp2 ->
729 code1 = registerCode register1 tmp1
730 src1 = registerName register1 tmp1
732 code2 = registerCode register2 tmp2
733 src2 = registerName register2 tmp2
735 code__2 dst = asmSeqThen [code1 [], code2 []] .
736 mkSeqInstr (instr src1 src2 dst)
738 return (Any FF64 code__2)
740 trivialUFCode _ instr x
741 = getRegister x `thenNat` \ register ->
742 getNewRegNat FF64 `thenNat` \ tmp ->
744 code = registerCode register tmp
745 src = registerName register tmp
746 code__2 dst = code . mkSeqInstr (instr src dst)
748 return (Any FF64 code__2)
750 #if alpha_TARGET_ARCH
753 = getRegister x `thenNat` \ register ->
754 getNewRegNat IntRep `thenNat` \ reg ->
756 code = registerCode register reg
757 src = registerName register reg
759 code__2 dst = code . mkSeqInstrs [
764 return (Any FF64 code__2)
768 = getRegister x `thenNat` \ register ->
769 getNewRegNat FF64 `thenNat` \ tmp ->
771 code = registerCode register tmp
772 src = registerName register tmp
774 code__2 dst = code . mkSeqInstrs [
779 return (Any IntRep code__2)
781 #endif /* alpha_TARGET_ARCH */