1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#include "lisc.h"
/* For x86_64, we have to:
*
* - check that constants are used only in
* places allowed by the machine
*
* - explicit machine register contraints
* on instructions like division.
*
* - lower calls (future, I have to think
* about their representation and the
* way I deal with structs/unions in the
* ABI)
*/
extern Ins insb[NIns], *curi; /* shared work buffer */
static void
emit(short op, Ref to, Ref arg0, Ref arg1)
{
if (curi == insb)
diag("isel: too many instructions");
*--curi = (Ins){op, to, {arg0, arg1}};
}
static void
sel(Ins *i, Fn *fn)
{
int t;
Ref r0, r1;
switch (i->op) {
case ODiv:
r0 = SYM(RAX);
r1 = SYM(RDX);
if (0) {
case ORem:
r0 = SYM(RDX);
r1 = SYM(RAX);
}
emit(OCopy, i->to, r0, R);
emit(OCopy, R, r1, R);
if (rtype(i->arg[1]) == RConst) {
/* immediates not allowed for
* divisions in x86
*/
t = fn->ntmp++;
r0 = SYM(t);
} else
r0 = i->arg[1];
emit(OIADiv, R, r0, R);
emit(OIACltd, SYM(RDX), R, R);
emit(OCopy, SYM(RAX), i->arg[0], R);
if (rtype(i->arg[1]) == RConst)
emit(OCopy, r0, i->arg[1], R);
break;
case OAdd:
case OSub:
case OCopy:
emit(i->op, i->to, i->arg[0], i->arg[1]);
break;
default:
diag("isel: non-exhaustive implementation");
}
}
/* instruction selection
*/
void
isel(Fn *fn)
{
Blk *b;
Ins *i;
int t0, t;
uint nins;
t0 = fn->ntmp;
for (b=fn->start; b; b=b->link) {
curi = &insb[NIns];
for (i=&b->ins[b->nins]; i!=b->ins;) {
sel(--i, fn);
}
nins = &insb[NIns] - curi;
free(b->ins);
b->ins = alloc(nins * sizeof b->ins[0]);
memcpy(b->ins, curi, nins * sizeof b->ins[0]);
b->nins = nins;
}
if (fn->ntmp == t0)
return;
fn->sym = realloc(fn->sym, fn->ntmp * sizeof(Sym));
if (!fn->sym)
diag("isel: out of memory");
for (t=t0; t<fn->ntmp; t++) {
fn->sym[t].type = STmp;
sprintf(fn->sym[t].name, "isel%d", t-t0);
}
}
|