Source file src/pkg/cmd/compile/internal/x86/387.go
1
2
3
4
5 package x86
6
7 import (
8 "cmd/compile/internal/gc"
9 "cmd/compile/internal/ssa"
10 "cmd/compile/internal/types"
11 "cmd/internal/obj"
12 "cmd/internal/obj/x86"
13 "math"
14 )
15
16
17 func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) {
18
19
20
21
22
23 switch v.Op {
24 case ssa.Op386MOVSSconst, ssa.Op386MOVSDconst:
25 iv := uint64(v.AuxInt)
26 if iv == 0x0000000000000000 {
27 s.Prog(x86.AFLDZ)
28 } else if iv == 0x3ff0000000000000 {
29 s.Prog(x86.AFLD1)
30 } else if iv == 0x8000000000000000 {
31 s.Prog(x86.AFLDZ)
32 s.Prog(x86.AFCHS)
33 } else if iv == 0xbff0000000000000 {
34 s.Prog(x86.AFLD1)
35 s.Prog(x86.AFCHS)
36 } else if iv == 0x400921fb54442d18 {
37 s.Prog(x86.AFLDPI)
38 } else if iv == 0xc00921fb54442d18 {
39 s.Prog(x86.AFLDPI)
40 s.Prog(x86.AFCHS)
41 } else {
42 p := s.Prog(loadPush(v.Type))
43 p.From.Type = obj.TYPE_FCONST
44 p.From.Val = math.Float64frombits(iv)
45 p.To.Type = obj.TYPE_REG
46 p.To.Reg = x86.REG_F0
47 }
48 popAndSave(s, v)
49
50 case ssa.Op386MOVSSconst2, ssa.Op386MOVSDconst2:
51 p := s.Prog(loadPush(v.Type))
52 p.From.Type = obj.TYPE_MEM
53 p.From.Reg = v.Args[0].Reg()
54 p.To.Type = obj.TYPE_REG
55 p.To.Reg = x86.REG_F0
56 popAndSave(s, v)
57
58 case ssa.Op386MOVSSload, ssa.Op386MOVSDload, ssa.Op386MOVSSloadidx1, ssa.Op386MOVSDloadidx1, ssa.Op386MOVSSloadidx4, ssa.Op386MOVSDloadidx8:
59 p := s.Prog(loadPush(v.Type))
60 p.From.Type = obj.TYPE_MEM
61 p.From.Reg = v.Args[0].Reg()
62 gc.AddAux(&p.From, v)
63 switch v.Op {
64 case ssa.Op386MOVSSloadidx1, ssa.Op386MOVSDloadidx1:
65 p.From.Scale = 1
66 p.From.Index = v.Args[1].Reg()
67 if p.From.Index == x86.REG_SP {
68 p.From.Reg, p.From.Index = p.From.Index, p.From.Reg
69 }
70 case ssa.Op386MOVSSloadidx4:
71 p.From.Scale = 4
72 p.From.Index = v.Args[1].Reg()
73 case ssa.Op386MOVSDloadidx8:
74 p.From.Scale = 8
75 p.From.Index = v.Args[1].Reg()
76 }
77 p.To.Type = obj.TYPE_REG
78 p.To.Reg = x86.REG_F0
79 popAndSave(s, v)
80
81 case ssa.Op386MOVSSstore, ssa.Op386MOVSDstore:
82
83 push(s, v.Args[1])
84
85
86 var op obj.As
87 switch v.Op {
88 case ssa.Op386MOVSSstore:
89 op = x86.AFMOVFP
90 case ssa.Op386MOVSDstore:
91 op = x86.AFMOVDP
92 }
93 p := s.Prog(op)
94 p.From.Type = obj.TYPE_REG
95 p.From.Reg = x86.REG_F0
96 p.To.Type = obj.TYPE_MEM
97 p.To.Reg = v.Args[0].Reg()
98 gc.AddAux(&p.To, v)
99
100 case ssa.Op386MOVSSstoreidx1, ssa.Op386MOVSDstoreidx1, ssa.Op386MOVSSstoreidx4, ssa.Op386MOVSDstoreidx8:
101 push(s, v.Args[2])
102 var op obj.As
103 switch v.Op {
104 case ssa.Op386MOVSSstoreidx1, ssa.Op386MOVSSstoreidx4:
105 op = x86.AFMOVFP
106 case ssa.Op386MOVSDstoreidx1, ssa.Op386MOVSDstoreidx8:
107 op = x86.AFMOVDP
108 }
109 p := s.Prog(op)
110 p.From.Type = obj.TYPE_REG
111 p.From.Reg = x86.REG_F0
112 p.To.Type = obj.TYPE_MEM
113 p.To.Reg = v.Args[0].Reg()
114 gc.AddAux(&p.To, v)
115 switch v.Op {
116 case ssa.Op386MOVSSstoreidx1, ssa.Op386MOVSDstoreidx1:
117 p.To.Scale = 1
118 p.To.Index = v.Args[1].Reg()
119 if p.To.Index == x86.REG_SP {
120 p.To.Reg, p.To.Index = p.To.Index, p.To.Reg
121 }
122 case ssa.Op386MOVSSstoreidx4:
123 p.To.Scale = 4
124 p.To.Index = v.Args[1].Reg()
125 case ssa.Op386MOVSDstoreidx8:
126 p.To.Scale = 8
127 p.To.Index = v.Args[1].Reg()
128 }
129
130 case ssa.Op386ADDSS, ssa.Op386ADDSD, ssa.Op386SUBSS, ssa.Op386SUBSD,
131 ssa.Op386MULSS, ssa.Op386MULSD, ssa.Op386DIVSS, ssa.Op386DIVSD:
132 if v.Reg() != v.Args[0].Reg() {
133 v.Fatalf("input[0] and output not in same register %s", v.LongString())
134 }
135
136
137 push(s, v.Args[1])
138
139
140 switch v.Op {
141 case ssa.Op386ADDSS, ssa.Op386SUBSS, ssa.Op386MULSS, ssa.Op386DIVSS:
142 p := s.Prog(x86.AFSTCW)
143 s.AddrScratch(&p.To)
144 p = s.Prog(x86.AFLDCW)
145 p.From.Type = obj.TYPE_MEM
146 p.From.Name = obj.NAME_EXTERN
147 p.From.Sym = gc.ControlWord32
148 }
149
150 var op obj.As
151 switch v.Op {
152 case ssa.Op386ADDSS, ssa.Op386ADDSD:
153 op = x86.AFADDDP
154 case ssa.Op386SUBSS, ssa.Op386SUBSD:
155 op = x86.AFSUBDP
156 case ssa.Op386MULSS, ssa.Op386MULSD:
157 op = x86.AFMULDP
158 case ssa.Op386DIVSS, ssa.Op386DIVSD:
159 op = x86.AFDIVDP
160 }
161 p := s.Prog(op)
162 p.From.Type = obj.TYPE_REG
163 p.From.Reg = x86.REG_F0
164 p.To.Type = obj.TYPE_REG
165 p.To.Reg = s.SSEto387[v.Reg()] + 1
166
167
168 switch v.Op {
169 case ssa.Op386ADDSS, ssa.Op386SUBSS, ssa.Op386MULSS, ssa.Op386DIVSS:
170 p := s.Prog(x86.AFLDCW)
171 s.AddrScratch(&p.From)
172 }
173
174 case ssa.Op386UCOMISS, ssa.Op386UCOMISD:
175 push(s, v.Args[0])
176
177
178 p := s.Prog(x86.AFUCOMP)
179 p.From.Type = obj.TYPE_REG
180 p.From.Reg = x86.REG_F0
181 p.To.Type = obj.TYPE_REG
182 p.To.Reg = s.SSEto387[v.Args[1].Reg()] + 1
183
184
185 p = s.Prog(x86.AMOVL)
186 p.From.Type = obj.TYPE_REG
187 p.From.Reg = x86.REG_AX
188 s.AddrScratch(&p.To)
189
190
191 p = s.Prog(x86.AFSTSW)
192 p.To.Type = obj.TYPE_REG
193 p.To.Reg = x86.REG_AX
194
195
196 s.Prog(x86.ASAHF)
197
198
199 p = s.Prog(x86.AMOVL)
200 s.AddrScratch(&p.From)
201 p.To.Type = obj.TYPE_REG
202 p.To.Reg = x86.REG_AX
203
204 case ssa.Op386SQRTSD:
205 push(s, v.Args[0])
206 s.Prog(x86.AFSQRT)
207 popAndSave(s, v)
208
209 case ssa.Op386FCHS:
210 push(s, v.Args[0])
211 s.Prog(x86.AFCHS)
212 popAndSave(s, v)
213
214 case ssa.Op386CVTSL2SS, ssa.Op386CVTSL2SD:
215 p := s.Prog(x86.AMOVL)
216 p.From.Type = obj.TYPE_REG
217 p.From.Reg = v.Args[0].Reg()
218 s.AddrScratch(&p.To)
219 p = s.Prog(x86.AFMOVL)
220 s.AddrScratch(&p.From)
221 p.To.Type = obj.TYPE_REG
222 p.To.Reg = x86.REG_F0
223 popAndSave(s, v)
224
225 case ssa.Op386CVTTSD2SL, ssa.Op386CVTTSS2SL:
226 push(s, v.Args[0])
227
228
229 p := s.Prog(x86.AFSTCW)
230 s.AddrScratch(&p.To)
231 p.To.Offset += 4
232
233
234 p = s.Prog(x86.AFLDCW)
235 p.From.Type = obj.TYPE_MEM
236 p.From.Name = obj.NAME_EXTERN
237 p.From.Sym = gc.ControlWord64trunc
238
239
240 p = s.Prog(x86.AFMOVLP)
241 p.From.Type = obj.TYPE_REG
242 p.From.Reg = x86.REG_F0
243 s.AddrScratch(&p.To)
244 p = s.Prog(x86.AMOVL)
245 s.AddrScratch(&p.From)
246 p.To.Type = obj.TYPE_REG
247 p.To.Reg = v.Reg()
248
249
250 p = s.Prog(x86.AFLDCW)
251 s.AddrScratch(&p.From)
252 p.From.Offset += 4
253
254 case ssa.Op386CVTSS2SD:
255
256 push(s, v.Args[0])
257 popAndSave(s, v)
258
259 case ssa.Op386CVTSD2SS:
260
261 push(s, v.Args[0])
262 p := s.Prog(x86.AFMOVFP)
263 p.From.Type = obj.TYPE_REG
264 p.From.Reg = x86.REG_F0
265 s.AddrScratch(&p.To)
266 p = s.Prog(x86.AFMOVF)
267 s.AddrScratch(&p.From)
268 p.To.Type = obj.TYPE_REG
269 p.To.Reg = x86.REG_F0
270 popAndSave(s, v)
271
272 case ssa.OpLoadReg:
273 if !v.Type.IsFloat() {
274 ssaGenValue(s, v)
275 return
276 }
277
278 p := s.Prog(loadPush(v.Type))
279 gc.AddrAuto(&p.From, v.Args[0])
280 p.To.Type = obj.TYPE_REG
281 p.To.Reg = x86.REG_F0
282
283 popAndSave(s, v)
284
285 case ssa.OpStoreReg:
286 if !v.Type.IsFloat() {
287 ssaGenValue(s, v)
288 return
289 }
290 push(s, v.Args[0])
291 var op obj.As
292 switch v.Type.Size() {
293 case 4:
294 op = x86.AFMOVFP
295 case 8:
296 op = x86.AFMOVDP
297 }
298 p := s.Prog(op)
299 p.From.Type = obj.TYPE_REG
300 p.From.Reg = x86.REG_F0
301 gc.AddrAuto(&p.To, v)
302
303 case ssa.OpCopy:
304 if !v.Type.IsFloat() {
305 ssaGenValue(s, v)
306 return
307 }
308 push(s, v.Args[0])
309 popAndSave(s, v)
310
311 case ssa.Op386CALLstatic, ssa.Op386CALLclosure, ssa.Op386CALLinter:
312 flush387(s)
313 fallthrough
314 default:
315 ssaGenValue(s, v)
316 }
317 }
318
319
320 func push(s *gc.SSAGenState, v *ssa.Value) {
321 p := s.Prog(x86.AFMOVD)
322 p.From.Type = obj.TYPE_REG
323 p.From.Reg = s.SSEto387[v.Reg()]
324 p.To.Type = obj.TYPE_REG
325 p.To.Reg = x86.REG_F0
326 }
327
328
329
330 func popAndSave(s *gc.SSAGenState, v *ssa.Value) {
331 r := v.Reg()
332 if _, ok := s.SSEto387[r]; ok {
333
334 p := s.Prog(x86.AFMOVDP)
335 p.From.Type = obj.TYPE_REG
336 p.From.Reg = x86.REG_F0
337 p.To.Type = obj.TYPE_REG
338 p.To.Reg = s.SSEto387[v.Reg()] + 1
339 } else {
340
341
342
343 for rSSE, r387 := range s.SSEto387 {
344 s.SSEto387[rSSE] = r387 + 1
345 }
346 s.SSEto387[r] = x86.REG_F0
347 }
348 }
349
350
351 func loadPush(t *types.Type) obj.As {
352 if t.Size() == 4 {
353 return x86.AFMOVF
354 }
355 return x86.AFMOVD
356 }
357
358
359 func flush387(s *gc.SSAGenState) {
360 for k := range s.SSEto387 {
361 p := s.Prog(x86.AFMOVDP)
362 p.From.Type = obj.TYPE_REG
363 p.From.Reg = x86.REG_F0
364 p.To.Type = obj.TYPE_REG
365 p.To.Reg = x86.REG_F0
366 delete(s.SSEto387, k)
367 }
368 }
369
370 func ssaGenBlock387(s *gc.SSAGenState, b, next *ssa.Block) {
371
372 flush387(s)
373
374 ssaGenBlock(s, b, next)
375 }
376
View as plain text