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 */