14 imm(Con
*c
, int k
, int64_t *pn
)
30 if ((n
& 0x000fff) == n
)
32 if ((n
& 0xfff000) == n
)
34 if ((n
& 0xffffff) == n
)
40 arm64_logimm(uint64_t x
, int k
)
45 x
= (x
& 0xffffffff) | x
<< 32;
50 if (x
== 0xaaaaaaaaaaaaaaaa)
53 if (0x1111111111111111 * n
== x
)
56 if (0x0101010101010101 * n
== x
)
59 if (0x0001000100010001 * n
== x
)
62 if (0x0000000100000001 * n
== x
)
66 return (n
& (n
+ (n
& -n
))) == 0;
70 fixarg(Ref
*pr
, int k
, int phi
, Fn
*fn
)
83 && c
->sym
.type
== SThr
) {
84 r1
= newtmp("isel", Kl
, fn
);
87 r2
= newtmp("isel", Kl
, fn
);
88 cc
= (Con
){.type
= CBits
};
89 cc
.bits
.i
= c
->bits
.i
;
91 emit(Oadd
, Kl
, r1
, r2
, r3
);
94 emit(Ocopy
, Kl
, r1
, TMP(R0
), R
);
95 r1
= newtmp("isel", Kl
, fn
);
96 r2
= newtmp("isel", Kl
, fn
);
97 emit(Ocall
, 0, R
, r1
, CALL(33));
98 emit(Ocopy
, Kl
, TMP(R0
), r2
, R
);
99 emit(Oload
, Kl
, r1
, r2
, R
);
102 r3
= newcon(&cc
, fn
);
103 emit(Ocopy
, Kl
, r2
, r3
, R
);
106 if (KBASE(k
) == 0 && phi
)
108 r1
= newtmp("isel", k
, fn
);
110 emit(Ocopy
, k
, r1
, r0
, R
);
112 n
= stashbits(&c
->bits
, KWIDE(k
) ? 8 : 4);
113 vgrow(&fn
->con
, ++fn
->ncon
);
114 c
= &fn
->con
[fn
->ncon
-1];
115 sprintf(buf
, "%sfp%d", T
.asloc
, n
);
116 *c
= (Con
){.type
= CAddr
};
117 c
->sym
.id
= intern(buf
);
118 r2
= newtmp("isel", Kl
, fn
);
119 emit(Oload
, k
, r1
, r2
, R
);
120 emit(Ocopy
, Kl
, r2
, CON(c
-fn
->con
), R
);
125 s
= fn
->tmp
[r0
.val
].slot
;
128 r1
= newtmp("isel", Kl
, fn
);
129 emit(Oaddr
, Kl
, r1
, SLOT(s
), R
);
136 selcmp(Ref arg
[2], int k
, Fn
*fn
)
144 emit(Oafcmp
, k
, R
, arg
[0], arg
[1]);
146 fixarg(&iarg
[0], k
, 0, fn
);
147 fixarg(&iarg
[1], k
, 0, fn
);
150 swap
= rtype(arg
[0]) == RCon
;
159 if (rtype(r
) == RCon
) {
161 switch (imm(c
, k
, &n
)) {
176 emit(cmp
, k
, R
, arg
[0], r
);
178 fixarg(&iarg
[0], k
, 0, fn
);
180 fixarg(&iarg
[1], k
, 0, fn
);
185 callable(Ref r
, Fn
*fn
)
189 if (rtype(r
) == RTmp
)
191 if (rtype(r
) == RCon
) {
193 if (c
->type
== CAddr
)
207 if (INRANGE(i
.op
, Oalloc
, Oalloc1
)) {
209 salloc(i
.to
, i
.arg
[0], fn
);
210 fixarg(&i0
->arg
[0], Kl
, 0, fn
);
213 if (iscmp(i
.op
, &ck
, &cc
)) {
214 emit(Oflag
, i
.cls
, i
.to
, R
, R
);
216 if (selcmp(i
.arg
, ck
, fn
))
223 if (callable(i
.arg
[0], fn
)) {
229 iarg
= curi
->arg
; /* fixarg() can change curi */
230 fixarg(&iarg
[0], argcls(&i
, 0), 0, fn
);
231 fixarg(&iarg
[1], argcls(&i
, 1), 0, fn
);
236 seljmp(Blk
*b
, Fn
*fn
)
242 if (b
->jmp
.type
== Jret0
243 || b
->jmp
.type
== Jjmp
244 || b
->jmp
.type
== Jhlt
)
246 assert(b
->jmp
.type
== Jjnz
);
251 i
= &b
->ins
[b
->nins
];
253 if (req((--i
)->to
, r
)) {
254 use
= fn
->tmp
[r
.val
].nuse
;
259 && iscmp(ir
->op
, &ck
, &cc
)) {
260 if (selcmp(ir
->arg
, ck
, fn
))
262 b
->jmp
.type
= Jjf
+ cc
;
263 *ir
= (Ins
){.op
= Onop
};
266 selcmp((Ref
[]){r
, CON_Z
}, Kw
, fn
);
267 b
->jmp
.type
= Jjfine
;
280 /* assign slots to fast allocs */
282 /* specific to NAlign == 3 */ /* or change n=4 and sz /= 4 below */
283 for (al
=Oalloc
, n
=4; al
<=Oalloc1
; al
++, n
*=2)
284 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++)
286 if (rtype(i
->arg
[0]) != RCon
)
288 sz
= fn
->con
[i
->arg
[0].val
].bits
.i
;
289 if (sz
< 0 || sz
>= INT_MAX
-15)
290 err("invalid alloc size %"PRId64
, sz
);
291 sz
= (sz
+ n
-1) & -n
;
293 fn
->tmp
[i
->to
.val
].slot
= fn
->slot
;
295 *i
= (Ins
){.op
= Onop
};
298 for (b
=fn
->start
; b
; b
=b
->link
) {
300 for (sb
=(Blk
*[3]){b
->s1
, b
->s2
, 0}; *sb
; sb
++)
301 for (p
=(*sb
)->phi
; p
; p
=p
->link
) {
302 for (n
=0; p
->blk
[n
] != b
; n
++)
303 assert(n
+1 < p
->narg
);
304 fixarg(&p
->arg
[n
], p
->cls
, 1, fn
);
307 for (i
=&b
->ins
[b
->nins
]; i
!=b
->ins
;)
309 b
->nins
= &insb
[NIns
] - curi
;
310 idup(&b
->ins
, curi
, b
->nins
);
314 fprintf(stderr
, "\n> After instruction selection:\n");