blob: 8eed67f6d2432befafd6654449a880bfa3134de0 [file] [log] [blame]
Colin Cross7bb052a2015-02-03 12:59:37 -08001// Copyright 2013 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5#include <u.h>
6#include <libc.h>
7#include "gg.h"
8#include "opt.h"
9
10// Matches real RtoB but can be used in global initializer.
11#define RtoB(r) (1<<((r)-D_AX))
12
13enum {
14 AX = RtoB(D_AX),
15 BX = RtoB(D_BX),
16 CX = RtoB(D_CX),
17 DX = RtoB(D_DX),
18 DI = RtoB(D_DI),
19 SI = RtoB(D_SI),
20
21 LeftRdwr = LeftRead | LeftWrite,
22 RightRdwr = RightRead | RightWrite,
23};
24
25#undef RtoB
26
27// This table gives the basic information about instruction
28// generated by the compiler and processed in the optimizer.
29// See opt.h for bit definitions.
30//
31// Instructions not generated need not be listed.
32// As an exception to that rule, we typically write down all the
33// size variants of an operation even if we just use a subset.
34//
35// The table is formatted for 8-space tabs.
36static ProgInfo progtable[ALAST] = {
37 [ATYPE]= {Pseudo | Skip},
38 [ATEXT]= {Pseudo},
39 [AFUNCDATA]= {Pseudo},
40 [APCDATA]= {Pseudo},
41 [AUNDEF]= {Break},
42 [AUSEFIELD]= {OK},
43 [ACHECKNIL]= {LeftRead},
44 [AVARDEF]= {Pseudo | RightWrite},
45 [AVARKILL]= {Pseudo | RightWrite},
46
47 // NOP is an internal no-op that also stands
48 // for USED and SET annotations, not the Intel opcode.
49 [ANOP]= {LeftRead | RightWrite},
50
51 [AADCL]= {SizeL | LeftRead | RightRdwr | SetCarry | UseCarry},
52 [AADCW]= {SizeW | LeftRead | RightRdwr | SetCarry | UseCarry},
53
54 [AADDB]= {SizeB | LeftRead | RightRdwr | SetCarry},
55 [AADDL]= {SizeL | LeftRead | RightRdwr | SetCarry},
56 [AADDW]= {SizeW | LeftRead | RightRdwr | SetCarry},
57
58 [AADDSD]= {SizeD | LeftRead | RightRdwr},
59 [AADDSS]= {SizeF | LeftRead | RightRdwr},
60
61 [AANDB]= {SizeB | LeftRead | RightRdwr | SetCarry},
62 [AANDL]= {SizeL | LeftRead | RightRdwr | SetCarry},
63 [AANDW]= {SizeW | LeftRead | RightRdwr | SetCarry},
64
65 [ACALL]= {RightAddr | Call | KillCarry},
66
67 [ACDQ]= {OK, AX, AX | DX},
68 [ACWD]= {OK, AX, AX | DX},
69
70 [ACLD]= {OK},
71 [ASTD]= {OK},
72
73 [ACMPB]= {SizeB | LeftRead | RightRead | SetCarry},
74 [ACMPL]= {SizeL | LeftRead | RightRead | SetCarry},
75 [ACMPW]= {SizeW | LeftRead | RightRead | SetCarry},
76
77 [ACOMISD]= {SizeD | LeftRead | RightRead | SetCarry},
78 [ACOMISS]= {SizeF | LeftRead | RightRead | SetCarry},
79
80 [ACVTSD2SL]= {SizeL | LeftRead | RightWrite | Conv},
81 [ACVTSD2SS]= {SizeF | LeftRead | RightWrite | Conv},
82 [ACVTSL2SD]= {SizeD | LeftRead | RightWrite | Conv},
83 [ACVTSL2SS]= {SizeF | LeftRead | RightWrite | Conv},
84 [ACVTSS2SD]= {SizeD | LeftRead | RightWrite | Conv},
85 [ACVTSS2SL]= {SizeL | LeftRead | RightWrite | Conv},
86 [ACVTTSD2SL]= {SizeL | LeftRead | RightWrite | Conv},
87 [ACVTTSS2SL]= {SizeL | LeftRead | RightWrite | Conv},
88
89 [ADECB]= {SizeB | RightRdwr},
90 [ADECL]= {SizeL | RightRdwr},
91 [ADECW]= {SizeW | RightRdwr},
92
93 [ADIVB]= {SizeB | LeftRead | SetCarry, AX, AX},
94 [ADIVL]= {SizeL | LeftRead | SetCarry, AX|DX, AX|DX},
95 [ADIVW]= {SizeW | LeftRead | SetCarry, AX|DX, AX|DX},
96
97 [ADIVSD]= {SizeD | LeftRead | RightRdwr},
98 [ADIVSS]= {SizeF | LeftRead | RightRdwr},
99
100 [AFLDCW]= {SizeW | LeftAddr},
101 [AFSTCW]= {SizeW | RightAddr},
102
103 [AFSTSW]= {SizeW | RightAddr | RightWrite},
104
105 [AFADDD]= {SizeD | LeftAddr | RightRdwr},
106 [AFADDDP]= {SizeD | LeftAddr | RightRdwr},
107 [AFADDF]= {SizeF | LeftAddr | RightRdwr},
108
109 [AFCOMD]= {SizeD | LeftAddr | RightRead},
110 [AFCOMDP]= {SizeD | LeftAddr | RightRead},
111 [AFCOMDPP]= {SizeD | LeftAddr | RightRead},
112 [AFCOMF]= {SizeF | LeftAddr | RightRead},
113 [AFCOMFP]= {SizeF | LeftAddr | RightRead},
114 [AFUCOMIP]= {SizeF | LeftAddr | RightRead},
115
116 [AFCHS]= {SizeD | RightRdwr}, // also SizeF
117
118 [AFDIVDP]= {SizeD | LeftAddr | RightRdwr},
119 [AFDIVF]= {SizeF | LeftAddr | RightRdwr},
120 [AFDIVD]= {SizeD | LeftAddr | RightRdwr},
121
122 [AFDIVRDP]= {SizeD | LeftAddr | RightRdwr},
123 [AFDIVRF]= {SizeF | LeftAddr | RightRdwr},
124 [AFDIVRD]= {SizeD | LeftAddr | RightRdwr},
125
126 [AFXCHD]= {SizeD | LeftRdwr | RightRdwr},
127
128 [AFSUBD]= {SizeD | LeftAddr | RightRdwr},
129 [AFSUBDP]= {SizeD | LeftAddr | RightRdwr},
130 [AFSUBF]= {SizeF | LeftAddr | RightRdwr},
131 [AFSUBRD]= {SizeD | LeftAddr | RightRdwr},
132 [AFSUBRDP]= {SizeD | LeftAddr | RightRdwr},
133 [AFSUBRF]= {SizeF | LeftAddr | RightRdwr},
134
135 [AFMOVD]= {SizeD | LeftAddr | RightWrite},
136 [AFMOVF]= {SizeF | LeftAddr | RightWrite},
137 [AFMOVL]= {SizeL | LeftAddr | RightWrite},
138 [AFMOVW]= {SizeW | LeftAddr | RightWrite},
139 [AFMOVV]= {SizeQ | LeftAddr | RightWrite},
140
141 // These instructions are marked as RightAddr
142 // so that the register optimizer does not try to replace the
143 // memory references with integer register references.
144 // But they do not use the previous value at the address, so
145 // we also mark them RightWrite.
146 [AFMOVDP]= {SizeD | LeftRead | RightWrite | RightAddr},
147 [AFMOVFP]= {SizeF | LeftRead | RightWrite | RightAddr},
148 [AFMOVLP]= {SizeL | LeftRead | RightWrite | RightAddr},
149 [AFMOVWP]= {SizeW | LeftRead | RightWrite | RightAddr},
150 [AFMOVVP]= {SizeQ | LeftRead | RightWrite | RightAddr},
151
152 [AFMULD]= {SizeD | LeftAddr | RightRdwr},
153 [AFMULDP]= {SizeD | LeftAddr | RightRdwr},
154 [AFMULF]= {SizeF | LeftAddr | RightRdwr},
155
156 [AIDIVB]= {SizeB | LeftRead | SetCarry, AX, AX},
157 [AIDIVL]= {SizeL | LeftRead | SetCarry, AX|DX, AX|DX},
158 [AIDIVW]= {SizeW | LeftRead | SetCarry, AX|DX, AX|DX},
159
160 [AIMULB]= {SizeB | LeftRead | SetCarry, AX, AX},
161 [AIMULL]= {SizeL | LeftRead | ImulAXDX | SetCarry},
162 [AIMULW]= {SizeW | LeftRead | ImulAXDX | SetCarry},
163
164 [AINCB]= {SizeB | RightRdwr},
165 [AINCL]= {SizeL | RightRdwr},
166 [AINCW]= {SizeW | RightRdwr},
167
168 [AJCC]= {Cjmp | UseCarry},
169 [AJCS]= {Cjmp | UseCarry},
170 [AJEQ]= {Cjmp | UseCarry},
171 [AJGE]= {Cjmp | UseCarry},
172 [AJGT]= {Cjmp | UseCarry},
173 [AJHI]= {Cjmp | UseCarry},
174 [AJLE]= {Cjmp | UseCarry},
175 [AJLS]= {Cjmp | UseCarry},
176 [AJLT]= {Cjmp | UseCarry},
177 [AJMI]= {Cjmp | UseCarry},
178 [AJNE]= {Cjmp | UseCarry},
179 [AJOC]= {Cjmp | UseCarry},
180 [AJOS]= {Cjmp | UseCarry},
181 [AJPC]= {Cjmp | UseCarry},
182 [AJPL]= {Cjmp | UseCarry},
183 [AJPS]= {Cjmp | UseCarry},
184
185 [AJMP]= {Jump | Break | KillCarry},
186
187 [ALEAL]= {LeftAddr | RightWrite},
188
189 [AMOVBLSX]= {SizeL | LeftRead | RightWrite | Conv},
190 [AMOVBLZX]= {SizeL | LeftRead | RightWrite | Conv},
191 [AMOVBWSX]= {SizeW | LeftRead | RightWrite | Conv},
192 [AMOVBWZX]= {SizeW | LeftRead | RightWrite | Conv},
193 [AMOVWLSX]= {SizeL | LeftRead | RightWrite | Conv},
194 [AMOVWLZX]= {SizeL | LeftRead | RightWrite | Conv},
195
196 [AMOVB]= {SizeB | LeftRead | RightWrite | Move},
197 [AMOVL]= {SizeL | LeftRead | RightWrite | Move},
198 [AMOVW]= {SizeW | LeftRead | RightWrite | Move},
199
200 [AMOVSB]= {OK, DI|SI, DI|SI},
201 [AMOVSL]= {OK, DI|SI, DI|SI},
202 [AMOVSW]= {OK, DI|SI, DI|SI},
203 [ADUFFCOPY]= {OK, DI|SI, DI|SI|CX},
204
205 [AMOVSD]= {SizeD | LeftRead | RightWrite | Move},
206 [AMOVSS]= {SizeF | LeftRead | RightWrite | Move},
207
208 // We use MOVAPD as a faster synonym for MOVSD.
209 [AMOVAPD]= {SizeD | LeftRead | RightWrite | Move},
210
211 [AMULB]= {SizeB | LeftRead | SetCarry, AX, AX},
212 [AMULL]= {SizeL | LeftRead | SetCarry, AX, AX|DX},
213 [AMULW]= {SizeW | LeftRead | SetCarry, AX, AX|DX},
214
215 [AMULSD]= {SizeD | LeftRead | RightRdwr},
216 [AMULSS]= {SizeF | LeftRead | RightRdwr},
217
218 [ANEGB]= {SizeB | RightRdwr | SetCarry},
219 [ANEGL]= {SizeL | RightRdwr | SetCarry},
220 [ANEGW]= {SizeW | RightRdwr | SetCarry},
221
222 [ANOTB]= {SizeB | RightRdwr},
223 [ANOTL]= {SizeL | RightRdwr},
224 [ANOTW]= {SizeW | RightRdwr},
225
226 [AORB]= {SizeB | LeftRead | RightRdwr | SetCarry},
227 [AORL]= {SizeL | LeftRead | RightRdwr | SetCarry},
228 [AORW]= {SizeW | LeftRead | RightRdwr | SetCarry},
229
230 [APOPL]= {SizeL | RightWrite},
231 [APUSHL]= {SizeL | LeftRead},
232
233 [ARCLB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
234 [ARCLL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
235 [ARCLW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
236
237 [ARCRB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
238 [ARCRL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
239 [ARCRW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
240
241 [AREP]= {OK, CX, CX},
242 [AREPN]= {OK, CX, CX},
243
244 [ARET]= {Break | KillCarry},
245
246 [AROLB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
247 [AROLL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
248 [AROLW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
249
250 [ARORB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
251 [ARORL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
252 [ARORW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
253
254 [ASAHF]= {OK, AX, AX},
255
256 [ASALB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
257 [ASALL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
258 [ASALW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
259
260 [ASARB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
261 [ASARL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
262 [ASARW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
263
264 [ASBBB]= {SizeB | LeftRead | RightRdwr | SetCarry | UseCarry},
265 [ASBBL]= {SizeL | LeftRead | RightRdwr | SetCarry | UseCarry},
266 [ASBBW]= {SizeW | LeftRead | RightRdwr | SetCarry | UseCarry},
267
268 [ASETCC]= {SizeB | RightRdwr | UseCarry},
269 [ASETCS]= {SizeB | RightRdwr | UseCarry},
270 [ASETEQ]= {SizeB | RightRdwr | UseCarry},
271 [ASETGE]= {SizeB | RightRdwr | UseCarry},
272 [ASETGT]= {SizeB | RightRdwr | UseCarry},
273 [ASETHI]= {SizeB | RightRdwr | UseCarry},
274 [ASETLE]= {SizeB | RightRdwr | UseCarry},
275 [ASETLS]= {SizeB | RightRdwr | UseCarry},
276 [ASETLT]= {SizeB | RightRdwr | UseCarry},
277 [ASETMI]= {SizeB | RightRdwr | UseCarry},
278 [ASETNE]= {SizeB | RightRdwr | UseCarry},
279 [ASETOC]= {SizeB | RightRdwr | UseCarry},
280 [ASETOS]= {SizeB | RightRdwr | UseCarry},
281 [ASETPC]= {SizeB | RightRdwr | UseCarry},
282 [ASETPL]= {SizeB | RightRdwr | UseCarry},
283 [ASETPS]= {SizeB | RightRdwr | UseCarry},
284
285 [ASHLB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
286 [ASHLL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
287 [ASHLW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
288
289 [ASHRB]= {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
290 [ASHRL]= {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
291 [ASHRW]= {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
292
293 [ASTOSB]= {OK, AX|DI, DI},
294 [ASTOSL]= {OK, AX|DI, DI},
295 [ASTOSW]= {OK, AX|DI, DI},
296 [ADUFFZERO]= {OK, AX|DI, DI},
297
298 [ASUBB]= {SizeB | LeftRead | RightRdwr | SetCarry},
299 [ASUBL]= {SizeL | LeftRead | RightRdwr | SetCarry},
300 [ASUBW]= {SizeW | LeftRead | RightRdwr | SetCarry},
301
302 [ASUBSD]= {SizeD | LeftRead | RightRdwr},
303 [ASUBSS]= {SizeF | LeftRead | RightRdwr},
304
305 [ATESTB]= {SizeB | LeftRead | RightRead | SetCarry},
306 [ATESTL]= {SizeL | LeftRead | RightRead | SetCarry},
307 [ATESTW]= {SizeW | LeftRead | RightRead | SetCarry},
308
309 [AUCOMISD]= {SizeD | LeftRead | RightRead},
310 [AUCOMISS]= {SizeF | LeftRead | RightRead},
311
312 [AXCHGB]= {SizeB | LeftRdwr | RightRdwr},
313 [AXCHGL]= {SizeL | LeftRdwr | RightRdwr},
314 [AXCHGW]= {SizeW | LeftRdwr | RightRdwr},
315
316 [AXORB]= {SizeB | LeftRead | RightRdwr | SetCarry},
317 [AXORL]= {SizeL | LeftRead | RightRdwr | SetCarry},
318 [AXORW]= {SizeW | LeftRead | RightRdwr | SetCarry},
319};
320
321void
322proginfo(ProgInfo *info, Prog *p)
323{
324 *info = progtable[p->as];
325 if(info->flags == 0)
326 fatal("unknown instruction %P", p);
327
328 if((info->flags & ShiftCX) && p->from.type != D_CONST)
329 info->reguse |= CX;
330
331 if(info->flags & ImulAXDX) {
332 if(p->to.type == D_NONE) {
333 info->reguse |= AX;
334 info->regset |= AX | DX;
335 } else {
336 info->flags |= RightRdwr;
337 }
338 }
339
340 // Addressing makes some registers used.
341 if(p->from.type >= D_INDIR)
342 info->regindex |= RtoB(p->from.type-D_INDIR);
343 if(p->from.index != D_NONE)
344 info->regindex |= RtoB(p->from.index);
345 if(p->to.type >= D_INDIR)
346 info->regindex |= RtoB(p->to.type-D_INDIR);
347 if(p->to.index != D_NONE)
348 info->regindex |= RtoB(p->to.index);
349}