blob: f57bbcb62a87d1f314820a7e5e4698f019f80721 [file] [log] [blame]
Russ Cox8c195bd2015-02-13 14:40:36 -05001// Derived from Inferno utils/8c/txt.c
2// http://code.google.com/p/inferno-os/source/browse/utils/8c/txt.c
3//
4// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
5// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
6// Portions Copyright © 1997-1999 Vita Nuova Limited
7// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
8// Portions Copyright © 2004,2006 Bruce Ellis
9// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
10// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
11// Portions Copyright © 2009 The Go Authors. All rights reserved.
12//
13// Permission is hereby granted, free of charge, to any person obtaining a copy
14// of this software and associated documentation files (the "Software"), to deal
15// in the Software without restriction, including without limitation the rights
16// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17// copies of the Software, and to permit persons to whom the Software is
18// furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included in
21// all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29// THE SOFTWARE.
30
Russ Cox17eba6e2015-05-21 13:28:10 -040031package x86
Russ Cox8c195bd2015-02-13 14:40:36 -050032
33import (
Russ Cox17eba6e2015-05-21 13:28:10 -040034 "cmd/compile/internal/big"
35 "cmd/compile/internal/gc"
Russ Cox8c195bd2015-02-13 14:40:36 -050036 "cmd/internal/obj"
Russ Cox8afb3962015-03-04 22:58:27 -050037 "cmd/internal/obj/x86"
Russ Cox8c195bd2015-02-13 14:40:36 -050038 "fmt"
39)
Russ Cox8c195bd2015-02-13 14:40:36 -050040
41// TODO(rsc): Can make this bigger if we move
42// the text segment up higher in 8l for all GOOS.
43// At the same time, can raise StackBig in ../../runtime/stack.h.
44var unmappedzero uint32 = 4096
45
Brad Fitzpatrick05efc182015-04-13 18:26:08 -050046// foptoas flags
47const (
48 Frev = 1 << 0
49 Fpop = 1 << 1
50 Fpop2 = 1 << 2
51)
52
Russ Cox8c195bd2015-02-13 14:40:36 -050053/*
54 * return Axxx for Oxxx on type t.
55 */
56func optoas(op int, t *gc.Type) int {
Russ Cox8c195bd2015-02-13 14:40:36 -050057 if t == nil {
Håvard Haugen3c9fa382015-08-30 23:10:03 +020058 gc.Fatalf("optoas: t is nil")
Russ Cox8c195bd2015-02-13 14:40:36 -050059 }
60
Russ Cox382b44e2015-02-23 16:07:24 -050061 a := obj.AXXX
Russ Cox8c195bd2015-02-13 14:40:36 -050062 switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
63 default:
Håvard Haugen3c9fa382015-08-30 23:10:03 +020064 gc.Fatalf("optoas: no entry %v-%v", gc.Oconv(int(op), 0), t)
Russ Cox8c195bd2015-02-13 14:40:36 -050065
66 case gc.OADDR<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -050067 a = x86.ALEAL
Russ Cox8c195bd2015-02-13 14:40:36 -050068
69 case gc.OEQ<<16 | gc.TBOOL,
70 gc.OEQ<<16 | gc.TINT8,
71 gc.OEQ<<16 | gc.TUINT8,
72 gc.OEQ<<16 | gc.TINT16,
73 gc.OEQ<<16 | gc.TUINT16,
74 gc.OEQ<<16 | gc.TINT32,
75 gc.OEQ<<16 | gc.TUINT32,
76 gc.OEQ<<16 | gc.TINT64,
77 gc.OEQ<<16 | gc.TUINT64,
78 gc.OEQ<<16 | gc.TPTR32,
79 gc.OEQ<<16 | gc.TPTR64,
80 gc.OEQ<<16 | gc.TFLOAT32,
81 gc.OEQ<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -050082 a = x86.AJEQ
Russ Cox8c195bd2015-02-13 14:40:36 -050083
84 case gc.ONE<<16 | gc.TBOOL,
85 gc.ONE<<16 | gc.TINT8,
86 gc.ONE<<16 | gc.TUINT8,
87 gc.ONE<<16 | gc.TINT16,
88 gc.ONE<<16 | gc.TUINT16,
89 gc.ONE<<16 | gc.TINT32,
90 gc.ONE<<16 | gc.TUINT32,
91 gc.ONE<<16 | gc.TINT64,
92 gc.ONE<<16 | gc.TUINT64,
93 gc.ONE<<16 | gc.TPTR32,
94 gc.ONE<<16 | gc.TPTR64,
95 gc.ONE<<16 | gc.TFLOAT32,
96 gc.ONE<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -050097 a = x86.AJNE
Russ Cox8c195bd2015-02-13 14:40:36 -050098
99 case gc.OLT<<16 | gc.TINT8,
100 gc.OLT<<16 | gc.TINT16,
101 gc.OLT<<16 | gc.TINT32,
102 gc.OLT<<16 | gc.TINT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500103 a = x86.AJLT
Russ Cox8c195bd2015-02-13 14:40:36 -0500104
105 case gc.OLT<<16 | gc.TUINT8,
106 gc.OLT<<16 | gc.TUINT16,
107 gc.OLT<<16 | gc.TUINT32,
108 gc.OLT<<16 | gc.TUINT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500109 a = x86.AJCS
Russ Cox8c195bd2015-02-13 14:40:36 -0500110
111 case gc.OLE<<16 | gc.TINT8,
112 gc.OLE<<16 | gc.TINT16,
113 gc.OLE<<16 | gc.TINT32,
114 gc.OLE<<16 | gc.TINT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500115 a = x86.AJLE
Russ Cox8c195bd2015-02-13 14:40:36 -0500116
117 case gc.OLE<<16 | gc.TUINT8,
118 gc.OLE<<16 | gc.TUINT16,
119 gc.OLE<<16 | gc.TUINT32,
120 gc.OLE<<16 | gc.TUINT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500121 a = x86.AJLS
Russ Cox8c195bd2015-02-13 14:40:36 -0500122
123 case gc.OGT<<16 | gc.TINT8,
124 gc.OGT<<16 | gc.TINT16,
125 gc.OGT<<16 | gc.TINT32,
126 gc.OGT<<16 | gc.TINT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500127 a = x86.AJGT
Russ Cox8c195bd2015-02-13 14:40:36 -0500128
129 case gc.OGT<<16 | gc.TUINT8,
130 gc.OGT<<16 | gc.TUINT16,
131 gc.OGT<<16 | gc.TUINT32,
132 gc.OGT<<16 | gc.TUINT64,
133 gc.OLT<<16 | gc.TFLOAT32,
134 gc.OLT<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500135 a = x86.AJHI
Russ Cox8c195bd2015-02-13 14:40:36 -0500136
137 case gc.OGE<<16 | gc.TINT8,
138 gc.OGE<<16 | gc.TINT16,
139 gc.OGE<<16 | gc.TINT32,
140 gc.OGE<<16 | gc.TINT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500141 a = x86.AJGE
Russ Cox8c195bd2015-02-13 14:40:36 -0500142
143 case gc.OGE<<16 | gc.TUINT8,
144 gc.OGE<<16 | gc.TUINT16,
145 gc.OGE<<16 | gc.TUINT32,
146 gc.OGE<<16 | gc.TUINT64,
147 gc.OLE<<16 | gc.TFLOAT32,
148 gc.OLE<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500149 a = x86.AJCC
Russ Cox8c195bd2015-02-13 14:40:36 -0500150
151 case gc.OCMP<<16 | gc.TBOOL,
152 gc.OCMP<<16 | gc.TINT8,
153 gc.OCMP<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500154 a = x86.ACMPB
Russ Cox8c195bd2015-02-13 14:40:36 -0500155
156 case gc.OCMP<<16 | gc.TINT16,
157 gc.OCMP<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500158 a = x86.ACMPW
Russ Cox8c195bd2015-02-13 14:40:36 -0500159
160 case gc.OCMP<<16 | gc.TINT32,
161 gc.OCMP<<16 | gc.TUINT32,
162 gc.OCMP<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500163 a = x86.ACMPL
Russ Cox8c195bd2015-02-13 14:40:36 -0500164
165 case gc.OAS<<16 | gc.TBOOL,
166 gc.OAS<<16 | gc.TINT8,
167 gc.OAS<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500168 a = x86.AMOVB
Russ Cox8c195bd2015-02-13 14:40:36 -0500169
170 case gc.OAS<<16 | gc.TINT16,
171 gc.OAS<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500172 a = x86.AMOVW
Russ Cox8c195bd2015-02-13 14:40:36 -0500173
174 case gc.OAS<<16 | gc.TINT32,
175 gc.OAS<<16 | gc.TUINT32,
176 gc.OAS<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500177 a = x86.AMOVL
Russ Cox8c195bd2015-02-13 14:40:36 -0500178
179 case gc.OAS<<16 | gc.TFLOAT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500180 a = x86.AMOVSS
Russ Cox8c195bd2015-02-13 14:40:36 -0500181
182 case gc.OAS<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500183 a = x86.AMOVSD
Russ Cox8c195bd2015-02-13 14:40:36 -0500184
185 case gc.OADD<<16 | gc.TINT8,
186 gc.OADD<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500187 a = x86.AADDB
Russ Cox8c195bd2015-02-13 14:40:36 -0500188
189 case gc.OADD<<16 | gc.TINT16,
190 gc.OADD<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500191 a = x86.AADDW
Russ Cox8c195bd2015-02-13 14:40:36 -0500192
193 case gc.OADD<<16 | gc.TINT32,
194 gc.OADD<<16 | gc.TUINT32,
195 gc.OADD<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500196 a = x86.AADDL
Russ Cox8c195bd2015-02-13 14:40:36 -0500197
198 case gc.OSUB<<16 | gc.TINT8,
199 gc.OSUB<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500200 a = x86.ASUBB
Russ Cox8c195bd2015-02-13 14:40:36 -0500201
202 case gc.OSUB<<16 | gc.TINT16,
203 gc.OSUB<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500204 a = x86.ASUBW
Russ Cox8c195bd2015-02-13 14:40:36 -0500205
206 case gc.OSUB<<16 | gc.TINT32,
207 gc.OSUB<<16 | gc.TUINT32,
208 gc.OSUB<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500209 a = x86.ASUBL
Russ Cox8c195bd2015-02-13 14:40:36 -0500210
211 case gc.OINC<<16 | gc.TINT8,
212 gc.OINC<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500213 a = x86.AINCB
Russ Cox8c195bd2015-02-13 14:40:36 -0500214
215 case gc.OINC<<16 | gc.TINT16,
216 gc.OINC<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500217 a = x86.AINCW
Russ Cox8c195bd2015-02-13 14:40:36 -0500218
219 case gc.OINC<<16 | gc.TINT32,
220 gc.OINC<<16 | gc.TUINT32,
221 gc.OINC<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500222 a = x86.AINCL
Russ Cox8c195bd2015-02-13 14:40:36 -0500223
224 case gc.ODEC<<16 | gc.TINT8,
225 gc.ODEC<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500226 a = x86.ADECB
Russ Cox8c195bd2015-02-13 14:40:36 -0500227
228 case gc.ODEC<<16 | gc.TINT16,
229 gc.ODEC<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500230 a = x86.ADECW
Russ Cox8c195bd2015-02-13 14:40:36 -0500231
232 case gc.ODEC<<16 | gc.TINT32,
233 gc.ODEC<<16 | gc.TUINT32,
234 gc.ODEC<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500235 a = x86.ADECL
Russ Cox8c195bd2015-02-13 14:40:36 -0500236
237 case gc.OCOM<<16 | gc.TINT8,
238 gc.OCOM<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500239 a = x86.ANOTB
Russ Cox8c195bd2015-02-13 14:40:36 -0500240
241 case gc.OCOM<<16 | gc.TINT16,
242 gc.OCOM<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500243 a = x86.ANOTW
Russ Cox8c195bd2015-02-13 14:40:36 -0500244
245 case gc.OCOM<<16 | gc.TINT32,
246 gc.OCOM<<16 | gc.TUINT32,
247 gc.OCOM<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500248 a = x86.ANOTL
Russ Cox8c195bd2015-02-13 14:40:36 -0500249
250 case gc.OMINUS<<16 | gc.TINT8,
251 gc.OMINUS<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500252 a = x86.ANEGB
Russ Cox8c195bd2015-02-13 14:40:36 -0500253
254 case gc.OMINUS<<16 | gc.TINT16,
255 gc.OMINUS<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500256 a = x86.ANEGW
Russ Cox8c195bd2015-02-13 14:40:36 -0500257
258 case gc.OMINUS<<16 | gc.TINT32,
259 gc.OMINUS<<16 | gc.TUINT32,
260 gc.OMINUS<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500261 a = x86.ANEGL
Russ Cox8c195bd2015-02-13 14:40:36 -0500262
263 case gc.OAND<<16 | gc.TINT8,
264 gc.OAND<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500265 a = x86.AANDB
Russ Cox8c195bd2015-02-13 14:40:36 -0500266
267 case gc.OAND<<16 | gc.TINT16,
268 gc.OAND<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500269 a = x86.AANDW
Russ Cox8c195bd2015-02-13 14:40:36 -0500270
271 case gc.OAND<<16 | gc.TINT32,
272 gc.OAND<<16 | gc.TUINT32,
273 gc.OAND<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500274 a = x86.AANDL
Russ Cox8c195bd2015-02-13 14:40:36 -0500275
276 case gc.OOR<<16 | gc.TINT8,
277 gc.OOR<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500278 a = x86.AORB
Russ Cox8c195bd2015-02-13 14:40:36 -0500279
280 case gc.OOR<<16 | gc.TINT16,
281 gc.OOR<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500282 a = x86.AORW
Russ Cox8c195bd2015-02-13 14:40:36 -0500283
284 case gc.OOR<<16 | gc.TINT32,
285 gc.OOR<<16 | gc.TUINT32,
286 gc.OOR<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500287 a = x86.AORL
Russ Cox8c195bd2015-02-13 14:40:36 -0500288
289 case gc.OXOR<<16 | gc.TINT8,
290 gc.OXOR<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500291 a = x86.AXORB
Russ Cox8c195bd2015-02-13 14:40:36 -0500292
293 case gc.OXOR<<16 | gc.TINT16,
294 gc.OXOR<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500295 a = x86.AXORW
Russ Cox8c195bd2015-02-13 14:40:36 -0500296
297 case gc.OXOR<<16 | gc.TINT32,
298 gc.OXOR<<16 | gc.TUINT32,
299 gc.OXOR<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500300 a = x86.AXORL
Russ Cox8c195bd2015-02-13 14:40:36 -0500301
302 case gc.OLROT<<16 | gc.TINT8,
303 gc.OLROT<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500304 a = x86.AROLB
Russ Cox8c195bd2015-02-13 14:40:36 -0500305
306 case gc.OLROT<<16 | gc.TINT16,
307 gc.OLROT<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500308 a = x86.AROLW
Russ Cox8c195bd2015-02-13 14:40:36 -0500309
310 case gc.OLROT<<16 | gc.TINT32,
311 gc.OLROT<<16 | gc.TUINT32,
312 gc.OLROT<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500313 a = x86.AROLL
Russ Cox8c195bd2015-02-13 14:40:36 -0500314
315 case gc.OLSH<<16 | gc.TINT8,
316 gc.OLSH<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500317 a = x86.ASHLB
Russ Cox8c195bd2015-02-13 14:40:36 -0500318
319 case gc.OLSH<<16 | gc.TINT16,
320 gc.OLSH<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500321 a = x86.ASHLW
Russ Cox8c195bd2015-02-13 14:40:36 -0500322
323 case gc.OLSH<<16 | gc.TINT32,
324 gc.OLSH<<16 | gc.TUINT32,
325 gc.OLSH<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500326 a = x86.ASHLL
Russ Cox8c195bd2015-02-13 14:40:36 -0500327
328 case gc.ORSH<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500329 a = x86.ASHRB
Russ Cox8c195bd2015-02-13 14:40:36 -0500330
331 case gc.ORSH<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500332 a = x86.ASHRW
Russ Cox8c195bd2015-02-13 14:40:36 -0500333
334 case gc.ORSH<<16 | gc.TUINT32,
335 gc.ORSH<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500336 a = x86.ASHRL
Russ Cox8c195bd2015-02-13 14:40:36 -0500337
338 case gc.ORSH<<16 | gc.TINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500339 a = x86.ASARB
Russ Cox8c195bd2015-02-13 14:40:36 -0500340
341 case gc.ORSH<<16 | gc.TINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500342 a = x86.ASARW
Russ Cox8c195bd2015-02-13 14:40:36 -0500343
344 case gc.ORSH<<16 | gc.TINT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500345 a = x86.ASARL
Russ Cox8c195bd2015-02-13 14:40:36 -0500346
347 case gc.OHMUL<<16 | gc.TINT8,
348 gc.OMUL<<16 | gc.TINT8,
349 gc.OMUL<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500350 a = x86.AIMULB
Russ Cox8c195bd2015-02-13 14:40:36 -0500351
352 case gc.OHMUL<<16 | gc.TINT16,
353 gc.OMUL<<16 | gc.TINT16,
354 gc.OMUL<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500355 a = x86.AIMULW
Russ Cox8c195bd2015-02-13 14:40:36 -0500356
357 case gc.OHMUL<<16 | gc.TINT32,
358 gc.OMUL<<16 | gc.TINT32,
359 gc.OMUL<<16 | gc.TUINT32,
360 gc.OMUL<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500361 a = x86.AIMULL
Russ Cox8c195bd2015-02-13 14:40:36 -0500362
363 case gc.OHMUL<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500364 a = x86.AMULB
Russ Cox8c195bd2015-02-13 14:40:36 -0500365
366 case gc.OHMUL<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500367 a = x86.AMULW
Russ Cox8c195bd2015-02-13 14:40:36 -0500368
369 case gc.OHMUL<<16 | gc.TUINT32,
370 gc.OHMUL<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500371 a = x86.AMULL
Russ Cox8c195bd2015-02-13 14:40:36 -0500372
373 case gc.ODIV<<16 | gc.TINT8,
374 gc.OMOD<<16 | gc.TINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500375 a = x86.AIDIVB
Russ Cox8c195bd2015-02-13 14:40:36 -0500376
377 case gc.ODIV<<16 | gc.TUINT8,
378 gc.OMOD<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500379 a = x86.ADIVB
Russ Cox8c195bd2015-02-13 14:40:36 -0500380
381 case gc.ODIV<<16 | gc.TINT16,
382 gc.OMOD<<16 | gc.TINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500383 a = x86.AIDIVW
Russ Cox8c195bd2015-02-13 14:40:36 -0500384
385 case gc.ODIV<<16 | gc.TUINT16,
386 gc.OMOD<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500387 a = x86.ADIVW
Russ Cox8c195bd2015-02-13 14:40:36 -0500388
389 case gc.ODIV<<16 | gc.TINT32,
390 gc.OMOD<<16 | gc.TINT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500391 a = x86.AIDIVL
Russ Cox8c195bd2015-02-13 14:40:36 -0500392
393 case gc.ODIV<<16 | gc.TUINT32,
394 gc.ODIV<<16 | gc.TPTR32,
395 gc.OMOD<<16 | gc.TUINT32,
396 gc.OMOD<<16 | gc.TPTR32:
Russ Cox8afb3962015-03-04 22:58:27 -0500397 a = x86.ADIVL
Russ Cox8c195bd2015-02-13 14:40:36 -0500398
399 case gc.OEXTEND<<16 | gc.TINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500400 a = x86.ACWD
Russ Cox8c195bd2015-02-13 14:40:36 -0500401
402 case gc.OEXTEND<<16 | gc.TINT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500403 a = x86.ACDQ
Russ Cox8c195bd2015-02-13 14:40:36 -0500404 }
405
406 return a
407}
408
409func foptoas(op int, t *gc.Type, flg int) int {
Russ Cox382b44e2015-02-23 16:07:24 -0500410 a := obj.AXXX
411 et := int(gc.Simtype[t.Etype])
Russ Cox8c195bd2015-02-13 14:40:36 -0500412
Dave Cheney01d005c2015-03-25 09:17:09 +1100413 if !gc.Thearch.Use387 {
Russ Cox79f727a2015-03-02 12:35:15 -0500414 switch uint32(op)<<16 | uint32(et) {
415 default:
Håvard Haugen3c9fa382015-08-30 23:10:03 +0200416 gc.Fatalf("foptoas-sse: no entry %v-%v", gc.Oconv(int(op), 0), t)
Russ Cox79f727a2015-03-02 12:35:15 -0500417
418 case gc.OCMP<<16 | gc.TFLOAT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500419 a = x86.AUCOMISS
Russ Cox79f727a2015-03-02 12:35:15 -0500420
421 case gc.OCMP<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500422 a = x86.AUCOMISD
Russ Cox79f727a2015-03-02 12:35:15 -0500423
424 case gc.OAS<<16 | gc.TFLOAT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500425 a = x86.AMOVSS
Russ Cox79f727a2015-03-02 12:35:15 -0500426
427 case gc.OAS<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500428 a = x86.AMOVSD
Russ Cox79f727a2015-03-02 12:35:15 -0500429
430 case gc.OADD<<16 | gc.TFLOAT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500431 a = x86.AADDSS
Russ Cox79f727a2015-03-02 12:35:15 -0500432
433 case gc.OADD<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500434 a = x86.AADDSD
Russ Cox79f727a2015-03-02 12:35:15 -0500435
436 case gc.OSUB<<16 | gc.TFLOAT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500437 a = x86.ASUBSS
Russ Cox79f727a2015-03-02 12:35:15 -0500438
439 case gc.OSUB<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500440 a = x86.ASUBSD
Russ Cox79f727a2015-03-02 12:35:15 -0500441
442 case gc.OMUL<<16 | gc.TFLOAT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500443 a = x86.AMULSS
Russ Cox79f727a2015-03-02 12:35:15 -0500444
445 case gc.OMUL<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500446 a = x86.AMULSD
Russ Cox79f727a2015-03-02 12:35:15 -0500447
448 case gc.ODIV<<16 | gc.TFLOAT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500449 a = x86.ADIVSS
Russ Cox79f727a2015-03-02 12:35:15 -0500450
451 case gc.ODIV<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -0500452 a = x86.ADIVSD
Russ Cox79f727a2015-03-02 12:35:15 -0500453 }
454
455 return a
Russ Cox8c195bd2015-02-13 14:40:36 -0500456 }
457
458 // If we need Fpop, it means we're working on
459 // two different floating-point registers, not memory.
460 // There the instruction only has a float64 form.
461 if flg&Fpop != 0 {
462 et = gc.TFLOAT64
463 }
464
465 // clear Frev if unneeded
466 switch op {
467 case gc.OADD,
468 gc.OMUL:
469 flg &^= Frev
470 }
471
472 switch uint32(op)<<16 | (uint32(et)<<8 | uint32(flg)) {
473 case gc.OADD<<16 | (gc.TFLOAT32<<8 | 0):
Russ Cox8afb3962015-03-04 22:58:27 -0500474 return x86.AFADDF
Russ Cox8c195bd2015-02-13 14:40:36 -0500475
476 case gc.OADD<<16 | (gc.TFLOAT64<<8 | 0):
Russ Cox8afb3962015-03-04 22:58:27 -0500477 return x86.AFADDD
Russ Cox8c195bd2015-02-13 14:40:36 -0500478
479 case gc.OADD<<16 | (gc.TFLOAT64<<8 | Fpop):
Russ Cox8afb3962015-03-04 22:58:27 -0500480 return x86.AFADDDP
Russ Cox8c195bd2015-02-13 14:40:36 -0500481
482 case gc.OSUB<<16 | (gc.TFLOAT32<<8 | 0):
Russ Cox8afb3962015-03-04 22:58:27 -0500483 return x86.AFSUBF
Russ Cox8c195bd2015-02-13 14:40:36 -0500484
485 case gc.OSUB<<16 | (gc.TFLOAT32<<8 | Frev):
Russ Cox8afb3962015-03-04 22:58:27 -0500486 return x86.AFSUBRF
Russ Cox8c195bd2015-02-13 14:40:36 -0500487
488 case gc.OSUB<<16 | (gc.TFLOAT64<<8 | 0):
Russ Cox8afb3962015-03-04 22:58:27 -0500489 return x86.AFSUBD
Russ Cox8c195bd2015-02-13 14:40:36 -0500490
491 case gc.OSUB<<16 | (gc.TFLOAT64<<8 | Frev):
Russ Cox8afb3962015-03-04 22:58:27 -0500492 return x86.AFSUBRD
Russ Cox8c195bd2015-02-13 14:40:36 -0500493
494 case gc.OSUB<<16 | (gc.TFLOAT64<<8 | Fpop):
Russ Cox8afb3962015-03-04 22:58:27 -0500495 return x86.AFSUBDP
Russ Cox8c195bd2015-02-13 14:40:36 -0500496
497 case gc.OSUB<<16 | (gc.TFLOAT64<<8 | (Fpop | Frev)):
Russ Cox8afb3962015-03-04 22:58:27 -0500498 return x86.AFSUBRDP
Russ Cox8c195bd2015-02-13 14:40:36 -0500499
500 case gc.OMUL<<16 | (gc.TFLOAT32<<8 | 0):
Russ Cox8afb3962015-03-04 22:58:27 -0500501 return x86.AFMULF
Russ Cox8c195bd2015-02-13 14:40:36 -0500502
503 case gc.OMUL<<16 | (gc.TFLOAT64<<8 | 0):
Russ Cox8afb3962015-03-04 22:58:27 -0500504 return x86.AFMULD
Russ Cox8c195bd2015-02-13 14:40:36 -0500505
506 case gc.OMUL<<16 | (gc.TFLOAT64<<8 | Fpop):
Russ Cox8afb3962015-03-04 22:58:27 -0500507 return x86.AFMULDP
Russ Cox8c195bd2015-02-13 14:40:36 -0500508
509 case gc.ODIV<<16 | (gc.TFLOAT32<<8 | 0):
Russ Cox8afb3962015-03-04 22:58:27 -0500510 return x86.AFDIVF
Russ Cox8c195bd2015-02-13 14:40:36 -0500511
512 case gc.ODIV<<16 | (gc.TFLOAT32<<8 | Frev):
Russ Cox8afb3962015-03-04 22:58:27 -0500513 return x86.AFDIVRF
Russ Cox8c195bd2015-02-13 14:40:36 -0500514
515 case gc.ODIV<<16 | (gc.TFLOAT64<<8 | 0):
Russ Cox8afb3962015-03-04 22:58:27 -0500516 return x86.AFDIVD
Russ Cox8c195bd2015-02-13 14:40:36 -0500517
518 case gc.ODIV<<16 | (gc.TFLOAT64<<8 | Frev):
Russ Cox8afb3962015-03-04 22:58:27 -0500519 return x86.AFDIVRD
Russ Cox8c195bd2015-02-13 14:40:36 -0500520
521 case gc.ODIV<<16 | (gc.TFLOAT64<<8 | Fpop):
Russ Cox8afb3962015-03-04 22:58:27 -0500522 return x86.AFDIVDP
Russ Cox8c195bd2015-02-13 14:40:36 -0500523
524 case gc.ODIV<<16 | (gc.TFLOAT64<<8 | (Fpop | Frev)):
Russ Cox8afb3962015-03-04 22:58:27 -0500525 return x86.AFDIVRDP
Russ Cox8c195bd2015-02-13 14:40:36 -0500526
527 case gc.OCMP<<16 | (gc.TFLOAT32<<8 | 0):
Russ Cox8afb3962015-03-04 22:58:27 -0500528 return x86.AFCOMF
Russ Cox8c195bd2015-02-13 14:40:36 -0500529
530 case gc.OCMP<<16 | (gc.TFLOAT32<<8 | Fpop):
Russ Cox8afb3962015-03-04 22:58:27 -0500531 return x86.AFCOMFP
Russ Cox8c195bd2015-02-13 14:40:36 -0500532
533 case gc.OCMP<<16 | (gc.TFLOAT64<<8 | 0):
Russ Cox8afb3962015-03-04 22:58:27 -0500534 return x86.AFCOMD
Russ Cox8c195bd2015-02-13 14:40:36 -0500535
536 case gc.OCMP<<16 | (gc.TFLOAT64<<8 | Fpop):
Russ Cox8afb3962015-03-04 22:58:27 -0500537 return x86.AFCOMDP
Russ Cox8c195bd2015-02-13 14:40:36 -0500538
539 case gc.OCMP<<16 | (gc.TFLOAT64<<8 | Fpop2):
Russ Cox8afb3962015-03-04 22:58:27 -0500540 return x86.AFCOMDPP
Russ Cox8c195bd2015-02-13 14:40:36 -0500541
542 case gc.OMINUS<<16 | (gc.TFLOAT32<<8 | 0):
Russ Cox8afb3962015-03-04 22:58:27 -0500543 return x86.AFCHS
Russ Cox8c195bd2015-02-13 14:40:36 -0500544
545 case gc.OMINUS<<16 | (gc.TFLOAT64<<8 | 0):
Russ Cox8afb3962015-03-04 22:58:27 -0500546 return x86.AFCHS
Russ Cox8c195bd2015-02-13 14:40:36 -0500547 }
548
Håvard Haugen3c9fa382015-08-30 23:10:03 +0200549 gc.Fatalf("foptoas %v %v %#x", gc.Oconv(int(op), 0), t, flg)
Russ Cox8c195bd2015-02-13 14:40:36 -0500550 return 0
Russ Cox8c195bd2015-02-13 14:40:36 -0500551}
552
553var resvd = []int{
554 // REG_DI, // for movstring
555 // REG_SI, // for movstring
556
Russ Cox8afb3962015-03-04 22:58:27 -0500557 x86.REG_AX, // for divide
558 x86.REG_CX, // for shift
Russ Cox27edd722015-06-29 13:56:27 -0400559 x86.REG_DX, // for divide, context
Russ Cox8afb3962015-03-04 22:58:27 -0500560 x86.REG_SP, // for stack
Russ Cox8c195bd2015-02-13 14:40:36 -0500561}
562
563/*
564 * generate
565 * as $c, reg
566 */
567func gconreg(as int, c int64, reg int) {
568 var n1 gc.Node
569 var n2 gc.Node
570
571 gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
572 gc.Nodreg(&n2, gc.Types[gc.TINT64], reg)
573 gins(as, &n1, &n2)
574}
575
576/*
Russ Coxb115c352015-03-18 17:26:36 -0400577 * generate
578 * as $c, n
579 */
580func ginscon(as int, c int64, n2 *gc.Node) {
581 var n1 gc.Node
582 gc.Nodconst(&n1, gc.Types[gc.TINT32], c)
583 gins(as, &n1, n2)
584}
585
Russ Coxf8d14fc2015-05-06 12:28:19 -0400586func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
587 if gc.Isint[t.Etype] || int(t.Etype) == gc.Tptr {
588 if (n1.Op == gc.OLITERAL || n1.Op == gc.OADDR && n1.Left.Op == gc.ONAME) && n2.Op != gc.OLITERAL {
589 // Reverse comparison to place constant (including address constant) last.
590 op = gc.Brrev(op)
591 n1, n2 = n2, n1
592 }
593 }
594
595 // General case.
596 var r1, r2, g1, g2 gc.Node
597 if n1.Op == gc.ONAME && n1.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
598 r1 = *n1
599 } else {
600 gc.Regalloc(&r1, t, n1)
601 gc.Regalloc(&g1, n1.Type, &r1)
602 gc.Cgen(n1, &g1)
603 gmove(&g1, &r1)
604 }
605 if n2.Op == gc.OLITERAL && gc.Isint[t.Etype] || n2.Op == gc.OADDR && n2.Left.Op == gc.ONAME && n2.Left.Class == gc.PEXTERN {
606 r2 = *n2
607 } else {
608 gc.Regalloc(&r2, t, n2)
609 gc.Regalloc(&g2, n1.Type, &r2)
610 gc.Cgen(n2, &g2)
611 gmove(&g2, &r2)
612 }
613 gins(optoas(gc.OCMP, t), &r1, &r2)
614 if r1.Op == gc.OREGISTER {
615 gc.Regfree(&g1)
616 gc.Regfree(&r1)
617 }
618 if r2.Op == gc.OREGISTER {
619 gc.Regfree(&g2)
620 gc.Regfree(&r2)
621 }
622 return gc.Gbranch(optoas(op, t), nil, likely)
623}
624
Russ Coxb115c352015-03-18 17:26:36 -0400625/*
Russ Cox8c195bd2015-02-13 14:40:36 -0500626 * swap node contents
627 */
628func nswap(a *gc.Node, b *gc.Node) {
Russ Cox382b44e2015-02-23 16:07:24 -0500629 t := *a
Russ Cox8c195bd2015-02-13 14:40:36 -0500630 *a = *b
631 *b = t
632}
633
634/*
635 * return constant i node.
636 * overwritten by next call, but useful in calls to gins.
637 */
638
639var ncon_n gc.Node
640
641func ncon(i uint32) *gc.Node {
642 if ncon_n.Type == nil {
643 gc.Nodconst(&ncon_n, gc.Types[gc.TUINT32], 0)
644 }
Josh Bleecher Snyder0112f6f2015-04-22 20:08:03 -0700645 ncon_n.SetInt(int64(i))
Russ Cox8c195bd2015-02-13 14:40:36 -0500646 return &ncon_n
647}
648
649var sclean [10]gc.Node
650
651var nsclean int
652
653/*
654 * n is a 64-bit value. fill in lo and hi to refer to its 32-bit halves.
655 */
656func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) {
Russ Coxdc7b54b2015-02-17 22:13:49 -0500657 if !gc.Is64(n.Type) {
Håvard Haugen3c9fa382015-08-30 23:10:03 +0200658 gc.Fatalf("split64 %v", n.Type)
Russ Cox8c195bd2015-02-13 14:40:36 -0500659 }
660
661 if nsclean >= len(sclean) {
Håvard Haugen3c9fa382015-08-30 23:10:03 +0200662 gc.Fatalf("split64 clean")
Russ Cox8c195bd2015-02-13 14:40:36 -0500663 }
664 sclean[nsclean].Op = gc.OEMPTY
665 nsclean++
666 switch n.Op {
667 default:
668 switch n.Op {
669 default:
Russ Cox382b44e2015-02-23 16:07:24 -0500670 var n1 gc.Node
Russ Coxdc7b54b2015-02-17 22:13:49 -0500671 if !dotaddable(n, &n1) {
Russ Coxb115c352015-03-18 17:26:36 -0400672 gc.Igen(n, &n1, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -0500673 sclean[nsclean-1] = n1
674 }
675
676 n = &n1
677
678 case gc.ONAME:
679 if n.Class == gc.PPARAMREF {
Russ Cox382b44e2015-02-23 16:07:24 -0500680 var n1 gc.Node
Josh Bleecher Snyder8fa14ea2015-05-15 10:02:19 -0700681 gc.Cgen(n.Name.Heapaddr, &n1)
Russ Cox8c195bd2015-02-13 14:40:36 -0500682 sclean[nsclean-1] = n1
683 n = &n1
684 }
685
686 // nothing
687 case gc.OINDREG:
688 break
689 }
690
691 *lo = *n
692 *hi = *n
693 lo.Type = gc.Types[gc.TUINT32]
694 if n.Type.Etype == gc.TINT64 {
695 hi.Type = gc.Types[gc.TINT32]
696 } else {
697 hi.Type = gc.Types[gc.TUINT32]
698 }
699 hi.Xoffset += 4
700
701 case gc.OLITERAL:
Russ Cox382b44e2015-02-23 16:07:24 -0500702 var n1 gc.Node
Josh Bleecher Snyderba577812015-05-07 18:43:03 -0700703 n.Convconst(&n1, n.Type)
Josh Bleecher Snyder0112f6f2015-04-22 20:08:03 -0700704 i := n1.Int()
Russ Cox8c195bd2015-02-13 14:40:36 -0500705 gc.Nodconst(lo, gc.Types[gc.TUINT32], int64(uint32(i)))
706 i >>= 32
707 if n.Type.Etype == gc.TINT64 {
708 gc.Nodconst(hi, gc.Types[gc.TINT32], int64(int32(i)))
709 } else {
710 gc.Nodconst(hi, gc.Types[gc.TUINT32], int64(uint32(i)))
711 }
712 }
713}
714
715func splitclean() {
716 if nsclean <= 0 {
Håvard Haugen3c9fa382015-08-30 23:10:03 +0200717 gc.Fatalf("splitclean")
Russ Cox8c195bd2015-02-13 14:40:36 -0500718 }
719 nsclean--
720 if sclean[nsclean].Op != gc.OEMPTY {
Russ Coxb115c352015-03-18 17:26:36 -0400721 gc.Regfree(&sclean[nsclean])
Russ Cox8c195bd2015-02-13 14:40:36 -0500722 }
723}
724
Josh Bleecher Snyder0112f6f2015-04-22 20:08:03 -0700725// set up nodes representing fp constants
726var (
727 zerof gc.Node
728 two63f gc.Node
729 two64f gc.Node
730 bignodes_did bool
731)
Russ Cox8c195bd2015-02-13 14:40:36 -0500732
733func bignodes() {
Josh Bleecher Snyder0112f6f2015-04-22 20:08:03 -0700734 if bignodes_did {
Russ Cox8c195bd2015-02-13 14:40:36 -0500735 return
736 }
Josh Bleecher Snyder0112f6f2015-04-22 20:08:03 -0700737 bignodes_did = true
Russ Cox8c195bd2015-02-13 14:40:36 -0500738
Josh Bleecher Snyder0112f6f2015-04-22 20:08:03 -0700739 gc.Nodconst(&zerof, gc.Types[gc.TINT64], 0)
Josh Bleecher Snyderba577812015-05-07 18:43:03 -0700740 zerof.Convconst(&zerof, gc.Types[gc.TFLOAT64])
Russ Cox8c195bd2015-02-13 14:40:36 -0500741
Josh Bleecher Snyder0112f6f2015-04-22 20:08:03 -0700742 var i big.Int
743 i.SetInt64(1)
744 i.Lsh(&i, 63)
745 var bigi gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -0500746
Josh Bleecher Snyder0112f6f2015-04-22 20:08:03 -0700747 gc.Nodconst(&bigi, gc.Types[gc.TUINT64], 0)
748 bigi.SetBigInt(&i)
Josh Bleecher Snyderba577812015-05-07 18:43:03 -0700749 bigi.Convconst(&two63f, gc.Types[gc.TFLOAT64])
Josh Bleecher Snyder0112f6f2015-04-22 20:08:03 -0700750
751 gc.Nodconst(&bigi, gc.Types[gc.TUINT64], 0)
752 i.Lsh(&i, 1)
753 bigi.SetBigInt(&i)
Josh Bleecher Snyderba577812015-05-07 18:43:03 -0700754 bigi.Convconst(&two64f, gc.Types[gc.TFLOAT64])
Russ Cox8c195bd2015-02-13 14:40:36 -0500755}
756
757func memname(n *gc.Node, t *gc.Type) {
758 gc.Tempname(n, t)
759 n.Sym = gc.Lookup("." + n.Sym.Name[1:]) // keep optimizer from registerizing
760 n.Orig.Sym = n.Sym
761}
762
763func gmove(f *gc.Node, t *gc.Node) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500764 if gc.Debug['M'] != 0 {
Russ Cox17228f42015-04-17 12:03:22 -0400765 fmt.Printf("gmove %v -> %v\n", f, t)
Russ Cox8c195bd2015-02-13 14:40:36 -0500766 }
767
Russ Cox382b44e2015-02-23 16:07:24 -0500768 ft := gc.Simsimtype(f.Type)
769 tt := gc.Simsimtype(t.Type)
770 cvt := t.Type
Russ Cox8c195bd2015-02-13 14:40:36 -0500771
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +0000772 if gc.Iscomplex[ft] || gc.Iscomplex[tt] {
Russ Cox8c195bd2015-02-13 14:40:36 -0500773 gc.Complexmove(f, t)
774 return
775 }
776
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +0000777 if gc.Isfloat[ft] || gc.Isfloat[tt] {
Russ Cox8c195bd2015-02-13 14:40:36 -0500778 floatmove(f, t)
779 return
780 }
781
782 // cannot have two integer memory operands;
783 // except 64-bit, which always copies via registers anyway.
Russ Cox382b44e2015-02-23 16:07:24 -0500784 var r1 gc.Node
785 var a int
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +0000786 if gc.Isint[ft] && gc.Isint[tt] && !gc.Is64(f.Type) && !gc.Is64(t.Type) && gc.Ismem(f) && gc.Ismem(t) {
Russ Cox8c195bd2015-02-13 14:40:36 -0500787 goto hard
788 }
789
790 // convert constant to desired type
791 if f.Op == gc.OLITERAL {
Russ Cox382b44e2015-02-23 16:07:24 -0500792 var con gc.Node
Josh Bleecher Snyderba577812015-05-07 18:43:03 -0700793 f.Convconst(&con, t.Type)
Russ Cox8c195bd2015-02-13 14:40:36 -0500794 f = &con
795 ft = gc.Simsimtype(con.Type)
796 }
797
798 // value -> value copy, only one memory operand.
799 // figure out the instruction to use.
800 // break out of switch for one-instruction gins.
801 // goto rdst for "destination must be register".
802 // goto hard for "convert to cvt type first".
803 // otherwise handle and return.
804
805 switch uint32(ft)<<16 | uint32(tt) {
806 default:
Russ Cox79f727a2015-03-02 12:35:15 -0500807 // should not happen
Håvard Haugen3c9fa382015-08-30 23:10:03 +0200808 gc.Fatalf("gmove %v -> %v", f, t)
Russ Cox79f727a2015-03-02 12:35:15 -0500809 return
Russ Cox8c195bd2015-02-13 14:40:36 -0500810
811 /*
812 * integer copy and truncate
813 */
814 case gc.TINT8<<16 | gc.TINT8, // same size
815 gc.TINT8<<16 | gc.TUINT8,
816 gc.TUINT8<<16 | gc.TINT8,
817 gc.TUINT8<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500818 a = x86.AMOVB
Russ Cox8c195bd2015-02-13 14:40:36 -0500819
820 case gc.TINT16<<16 | gc.TINT8, // truncate
821 gc.TUINT16<<16 | gc.TINT8,
822 gc.TINT32<<16 | gc.TINT8,
823 gc.TUINT32<<16 | gc.TINT8,
824 gc.TINT16<<16 | gc.TUINT8,
825 gc.TUINT16<<16 | gc.TUINT8,
826 gc.TINT32<<16 | gc.TUINT8,
827 gc.TUINT32<<16 | gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -0500828 a = x86.AMOVB
Russ Cox8c195bd2015-02-13 14:40:36 -0500829
830 goto rsrc
831
832 case gc.TINT64<<16 | gc.TINT8, // truncate low word
833 gc.TUINT64<<16 | gc.TINT8,
834 gc.TINT64<<16 | gc.TUINT8,
835 gc.TUINT64<<16 | gc.TUINT8:
Russ Cox382b44e2015-02-23 16:07:24 -0500836 var flo gc.Node
837 var fhi gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -0500838 split64(f, &flo, &fhi)
839
Russ Cox382b44e2015-02-23 16:07:24 -0500840 var r1 gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -0500841 gc.Nodreg(&r1, t.Type, x86.REG_AX)
Russ Cox8c195bd2015-02-13 14:40:36 -0500842 gmove(&flo, &r1)
Russ Cox8afb3962015-03-04 22:58:27 -0500843 gins(x86.AMOVB, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -0500844 splitclean()
845 return
846
847 case gc.TINT16<<16 | gc.TINT16, // same size
848 gc.TINT16<<16 | gc.TUINT16,
849 gc.TUINT16<<16 | gc.TINT16,
850 gc.TUINT16<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500851 a = x86.AMOVW
Russ Cox8c195bd2015-02-13 14:40:36 -0500852
853 case gc.TINT32<<16 | gc.TINT16, // truncate
854 gc.TUINT32<<16 | gc.TINT16,
855 gc.TINT32<<16 | gc.TUINT16,
856 gc.TUINT32<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500857 a = x86.AMOVW
Russ Cox8c195bd2015-02-13 14:40:36 -0500858
859 goto rsrc
860
861 case gc.TINT64<<16 | gc.TINT16, // truncate low word
862 gc.TUINT64<<16 | gc.TINT16,
863 gc.TINT64<<16 | gc.TUINT16,
864 gc.TUINT64<<16 | gc.TUINT16:
Russ Cox382b44e2015-02-23 16:07:24 -0500865 var flo gc.Node
866 var fhi gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -0500867 split64(f, &flo, &fhi)
868
Russ Cox382b44e2015-02-23 16:07:24 -0500869 var r1 gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -0500870 gc.Nodreg(&r1, t.Type, x86.REG_AX)
Russ Cox8c195bd2015-02-13 14:40:36 -0500871 gmove(&flo, &r1)
Russ Cox8afb3962015-03-04 22:58:27 -0500872 gins(x86.AMOVW, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -0500873 splitclean()
874 return
875
876 case gc.TINT32<<16 | gc.TINT32, // same size
877 gc.TINT32<<16 | gc.TUINT32,
878 gc.TUINT32<<16 | gc.TINT32,
879 gc.TUINT32<<16 | gc.TUINT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500880 a = x86.AMOVL
Russ Cox8c195bd2015-02-13 14:40:36 -0500881
882 case gc.TINT64<<16 | gc.TINT32, // truncate
883 gc.TUINT64<<16 | gc.TINT32,
884 gc.TINT64<<16 | gc.TUINT32,
885 gc.TUINT64<<16 | gc.TUINT32:
Russ Cox382b44e2015-02-23 16:07:24 -0500886 var fhi gc.Node
887 var flo gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -0500888 split64(f, &flo, &fhi)
889
Russ Cox382b44e2015-02-23 16:07:24 -0500890 var r1 gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -0500891 gc.Nodreg(&r1, t.Type, x86.REG_AX)
Russ Cox8c195bd2015-02-13 14:40:36 -0500892 gmove(&flo, &r1)
Russ Cox8afb3962015-03-04 22:58:27 -0500893 gins(x86.AMOVL, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -0500894 splitclean()
895 return
896
897 case gc.TINT64<<16 | gc.TINT64, // same size
898 gc.TINT64<<16 | gc.TUINT64,
899 gc.TUINT64<<16 | gc.TINT64,
900 gc.TUINT64<<16 | gc.TUINT64:
Russ Cox382b44e2015-02-23 16:07:24 -0500901 var fhi gc.Node
902 var flo gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -0500903 split64(f, &flo, &fhi)
904
Russ Cox382b44e2015-02-23 16:07:24 -0500905 var tlo gc.Node
906 var thi gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -0500907 split64(t, &tlo, &thi)
908 if f.Op == gc.OLITERAL {
Russ Cox8afb3962015-03-04 22:58:27 -0500909 gins(x86.AMOVL, &flo, &tlo)
910 gins(x86.AMOVL, &fhi, &thi)
Russ Cox8c195bd2015-02-13 14:40:36 -0500911 } else {
Russ Cox27edd722015-06-29 13:56:27 -0400912 // Implementation of conversion-free x = y for int64 or uint64 x.
913 // This is generated by the code that copies small values out of closures,
914 // and that code has DX live, so avoid DX and use CX instead.
Russ Cox382b44e2015-02-23 16:07:24 -0500915 var r1 gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -0500916 gc.Nodreg(&r1, gc.Types[gc.TUINT32], x86.REG_AX)
Russ Cox382b44e2015-02-23 16:07:24 -0500917 var r2 gc.Node
Russ Cox27edd722015-06-29 13:56:27 -0400918 gc.Nodreg(&r2, gc.Types[gc.TUINT32], x86.REG_CX)
Russ Cox8afb3962015-03-04 22:58:27 -0500919 gins(x86.AMOVL, &flo, &r1)
920 gins(x86.AMOVL, &fhi, &r2)
921 gins(x86.AMOVL, &r1, &tlo)
922 gins(x86.AMOVL, &r2, &thi)
Russ Cox8c195bd2015-02-13 14:40:36 -0500923 }
924
925 splitclean()
926 splitclean()
927 return
928
929 /*
930 * integer up-conversions
931 */
932 case gc.TINT8<<16 | gc.TINT16, // sign extend int8
933 gc.TINT8<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500934 a = x86.AMOVBWSX
Russ Cox8c195bd2015-02-13 14:40:36 -0500935
936 goto rdst
937
938 case gc.TINT8<<16 | gc.TINT32,
939 gc.TINT8<<16 | gc.TUINT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500940 a = x86.AMOVBLSX
Russ Cox8c195bd2015-02-13 14:40:36 -0500941 goto rdst
942
943 case gc.TINT8<<16 | gc.TINT64, // convert via int32
944 gc.TINT8<<16 | gc.TUINT64:
945 cvt = gc.Types[gc.TINT32]
946
947 goto hard
948
949 case gc.TUINT8<<16 | gc.TINT16, // zero extend uint8
950 gc.TUINT8<<16 | gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -0500951 a = x86.AMOVBWZX
Russ Cox8c195bd2015-02-13 14:40:36 -0500952
953 goto rdst
954
955 case gc.TUINT8<<16 | gc.TINT32,
956 gc.TUINT8<<16 | gc.TUINT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500957 a = x86.AMOVBLZX
Russ Cox8c195bd2015-02-13 14:40:36 -0500958 goto rdst
959
960 case gc.TUINT8<<16 | gc.TINT64, // convert via uint32
961 gc.TUINT8<<16 | gc.TUINT64:
962 cvt = gc.Types[gc.TUINT32]
963
964 goto hard
965
966 case gc.TINT16<<16 | gc.TINT32, // sign extend int16
967 gc.TINT16<<16 | gc.TUINT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500968 a = x86.AMOVWLSX
Russ Cox8c195bd2015-02-13 14:40:36 -0500969
970 goto rdst
971
972 case gc.TINT16<<16 | gc.TINT64, // convert via int32
973 gc.TINT16<<16 | gc.TUINT64:
974 cvt = gc.Types[gc.TINT32]
975
976 goto hard
977
978 case gc.TUINT16<<16 | gc.TINT32, // zero extend uint16
979 gc.TUINT16<<16 | gc.TUINT32:
Russ Cox8afb3962015-03-04 22:58:27 -0500980 a = x86.AMOVWLZX
Russ Cox8c195bd2015-02-13 14:40:36 -0500981
982 goto rdst
983
984 case gc.TUINT16<<16 | gc.TINT64, // convert via uint32
985 gc.TUINT16<<16 | gc.TUINT64:
986 cvt = gc.Types[gc.TUINT32]
987
988 goto hard
989
990 case gc.TINT32<<16 | gc.TINT64, // sign extend int32
991 gc.TINT32<<16 | gc.TUINT64:
Russ Cox382b44e2015-02-23 16:07:24 -0500992 var thi gc.Node
993 var tlo gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -0500994 split64(t, &tlo, &thi)
995
Russ Cox382b44e2015-02-23 16:07:24 -0500996 var flo gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -0500997 gc.Nodreg(&flo, tlo.Type, x86.REG_AX)
Russ Cox382b44e2015-02-23 16:07:24 -0500998 var fhi gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -0500999 gc.Nodreg(&fhi, thi.Type, x86.REG_DX)
Russ Cox8c195bd2015-02-13 14:40:36 -05001000 gmove(f, &flo)
Russ Cox8afb3962015-03-04 22:58:27 -05001001 gins(x86.ACDQ, nil, nil)
1002 gins(x86.AMOVL, &flo, &tlo)
1003 gins(x86.AMOVL, &fhi, &thi)
Russ Cox8c195bd2015-02-13 14:40:36 -05001004 splitclean()
1005 return
1006
1007 case gc.TUINT32<<16 | gc.TINT64, // zero extend uint32
1008 gc.TUINT32<<16 | gc.TUINT64:
Russ Cox382b44e2015-02-23 16:07:24 -05001009 var tlo gc.Node
1010 var thi gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001011 split64(t, &tlo, &thi)
1012
1013 gmove(f, &tlo)
Russ Cox8afb3962015-03-04 22:58:27 -05001014 gins(x86.AMOVL, ncon(0), &thi)
Russ Cox8c195bd2015-02-13 14:40:36 -05001015 splitclean()
1016 return
1017 }
1018
1019 gins(a, f, t)
1020 return
1021
1022 // requires register source
1023rsrc:
Russ Coxb115c352015-03-18 17:26:36 -04001024 gc.Regalloc(&r1, f.Type, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001025
1026 gmove(f, &r1)
1027 gins(a, &r1, t)
Russ Coxb115c352015-03-18 17:26:36 -04001028 gc.Regfree(&r1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001029 return
1030
1031 // requires register destination
1032rdst:
Russ Cox44928112015-03-02 20:34:22 -05001033 {
Russ Coxb115c352015-03-18 17:26:36 -04001034 gc.Regalloc(&r1, t.Type, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001035
Russ Cox44928112015-03-02 20:34:22 -05001036 gins(a, f, &r1)
1037 gmove(&r1, t)
Russ Coxb115c352015-03-18 17:26:36 -04001038 gc.Regfree(&r1)
Russ Cox44928112015-03-02 20:34:22 -05001039 return
1040 }
Russ Cox8c195bd2015-02-13 14:40:36 -05001041
1042 // requires register intermediate
1043hard:
Russ Coxb115c352015-03-18 17:26:36 -04001044 gc.Regalloc(&r1, cvt, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001045
1046 gmove(f, &r1)
1047 gmove(&r1, t)
Russ Coxb115c352015-03-18 17:26:36 -04001048 gc.Regfree(&r1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001049 return
Russ Cox8c195bd2015-02-13 14:40:36 -05001050}
1051
1052func floatmove(f *gc.Node, t *gc.Node) {
1053 var r1 gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001054
Russ Cox382b44e2015-02-23 16:07:24 -05001055 ft := gc.Simsimtype(f.Type)
1056 tt := gc.Simsimtype(t.Type)
1057 cvt := t.Type
Russ Cox8c195bd2015-02-13 14:40:36 -05001058
1059 // cannot have two floating point memory operands.
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00001060 if gc.Isfloat[ft] && gc.Isfloat[tt] && gc.Ismem(f) && gc.Ismem(t) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001061 goto hard
1062 }
1063
1064 // convert constant to desired type
1065 if f.Op == gc.OLITERAL {
Russ Cox382b44e2015-02-23 16:07:24 -05001066 var con gc.Node
Josh Bleecher Snyderba577812015-05-07 18:43:03 -07001067 f.Convconst(&con, t.Type)
Russ Cox8c195bd2015-02-13 14:40:36 -05001068 f = &con
1069 ft = gc.Simsimtype(con.Type)
1070
1071 // some constants can't move directly to memory.
Russ Coxdc7b54b2015-02-17 22:13:49 -05001072 if gc.Ismem(t) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001073 // float constants come from memory.
Josh Bleecher Snyder25da5942015-03-01 07:54:01 +00001074 if gc.Isfloat[tt] {
Russ Cox8c195bd2015-02-13 14:40:36 -05001075 goto hard
1076 }
1077 }
1078 }
1079
1080 // value -> value copy, only one memory operand.
1081 // figure out the instruction to use.
1082 // break out of switch for one-instruction gins.
1083 // goto rdst for "destination must be register".
1084 // goto hard for "convert to cvt type first".
1085 // otherwise handle and return.
1086
1087 switch uint32(ft)<<16 | uint32(tt) {
1088 default:
Dave Cheney01d005c2015-03-25 09:17:09 +11001089 if gc.Thearch.Use387 {
Russ Cox8c195bd2015-02-13 14:40:36 -05001090 floatmove_387(f, t)
Dave Cheney01d005c2015-03-25 09:17:09 +11001091 } else {
1092 floatmove_sse(f, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001093 }
1094 return
1095
1096 // float to very long integer.
1097 case gc.TFLOAT32<<16 | gc.TINT64,
1098 gc.TFLOAT64<<16 | gc.TINT64:
1099 if f.Op == gc.OREGISTER {
1100 cvt = f.Type
1101 goto hardmem
1102 }
1103
Russ Cox382b44e2015-02-23 16:07:24 -05001104 var r1 gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -05001105 gc.Nodreg(&r1, gc.Types[ft], x86.REG_F0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001106 if ft == gc.TFLOAT32 {
Russ Cox8afb3962015-03-04 22:58:27 -05001107 gins(x86.AFMOVF, f, &r1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001108 } else {
Russ Cox8afb3962015-03-04 22:58:27 -05001109 gins(x86.AFMOVD, f, &r1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001110 }
1111
1112 // set round to zero mode during conversion
Russ Cox382b44e2015-02-23 16:07:24 -05001113 var t1 gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001114 memname(&t1, gc.Types[gc.TUINT16])
1115
Russ Cox382b44e2015-02-23 16:07:24 -05001116 var t2 gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001117 memname(&t2, gc.Types[gc.TUINT16])
Russ Cox8afb3962015-03-04 22:58:27 -05001118 gins(x86.AFSTCW, nil, &t1)
1119 gins(x86.AMOVW, ncon(0xf7f), &t2)
1120 gins(x86.AFLDCW, &t2, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05001121 if tt == gc.TINT16 {
Russ Cox8afb3962015-03-04 22:58:27 -05001122 gins(x86.AFMOVWP, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001123 } else if tt == gc.TINT32 {
Russ Cox8afb3962015-03-04 22:58:27 -05001124 gins(x86.AFMOVLP, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001125 } else {
Russ Cox8afb3962015-03-04 22:58:27 -05001126 gins(x86.AFMOVVP, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001127 }
Russ Cox8afb3962015-03-04 22:58:27 -05001128 gins(x86.AFLDCW, &t1, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05001129 return
1130
1131 case gc.TFLOAT32<<16 | gc.TUINT64,
1132 gc.TFLOAT64<<16 | gc.TUINT64:
Russ Coxdc7b54b2015-02-17 22:13:49 -05001133 if !gc.Ismem(f) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001134 cvt = f.Type
1135 goto hardmem
1136 }
1137
1138 bignodes()
Russ Cox382b44e2015-02-23 16:07:24 -05001139 var f0 gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -05001140 gc.Nodreg(&f0, gc.Types[ft], x86.REG_F0)
Russ Cox382b44e2015-02-23 16:07:24 -05001141 var f1 gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -05001142 gc.Nodreg(&f1, gc.Types[ft], x86.REG_F0+1)
Russ Cox382b44e2015-02-23 16:07:24 -05001143 var ax gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -05001144 gc.Nodreg(&ax, gc.Types[gc.TUINT16], x86.REG_AX)
Russ Cox8c195bd2015-02-13 14:40:36 -05001145
1146 if ft == gc.TFLOAT32 {
Russ Cox8afb3962015-03-04 22:58:27 -05001147 gins(x86.AFMOVF, f, &f0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001148 } else {
Russ Cox8afb3962015-03-04 22:58:27 -05001149 gins(x86.AFMOVD, f, &f0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001150 }
1151
1152 // if 0 > v { answer = 0 }
Russ Cox8afb3962015-03-04 22:58:27 -05001153 gins(x86.AFMOVD, &zerof, &f0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001154
Russ Cox8afb3962015-03-04 22:58:27 -05001155 gins(x86.AFUCOMIP, &f0, &f1)
Russ Cox382b44e2015-02-23 16:07:24 -05001156 p1 := gc.Gbranch(optoas(gc.OGT, gc.Types[tt]), nil, 0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001157
1158 // if 1<<64 <= v { answer = 0 too }
Russ Cox8afb3962015-03-04 22:58:27 -05001159 gins(x86.AFMOVD, &two64f, &f0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001160
Russ Cox8afb3962015-03-04 22:58:27 -05001161 gins(x86.AFUCOMIP, &f0, &f1)
Russ Cox382b44e2015-02-23 16:07:24 -05001162 p2 := gc.Gbranch(optoas(gc.OGT, gc.Types[tt]), nil, 0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001163 gc.Patch(p1, gc.Pc)
Russ Cox8afb3962015-03-04 22:58:27 -05001164 gins(x86.AFMOVVP, &f0, t) // don't care about t, but will pop the stack
Russ Cox382b44e2015-02-23 16:07:24 -05001165 var thi gc.Node
1166 var tlo gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001167 split64(t, &tlo, &thi)
Russ Cox8afb3962015-03-04 22:58:27 -05001168 gins(x86.AMOVL, ncon(0), &tlo)
1169 gins(x86.AMOVL, ncon(0), &thi)
Russ Cox8c195bd2015-02-13 14:40:36 -05001170 splitclean()
1171 p1 = gc.Gbranch(obj.AJMP, nil, 0)
1172 gc.Patch(p2, gc.Pc)
1173
1174 // in range; algorithm is:
1175 // if small enough, use native float64 -> int64 conversion.
1176 // otherwise, subtract 2^63, convert, and add it back.
1177
1178 // set round to zero mode during conversion
Russ Cox382b44e2015-02-23 16:07:24 -05001179 var t1 gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001180 memname(&t1, gc.Types[gc.TUINT16])
1181
Russ Cox382b44e2015-02-23 16:07:24 -05001182 var t2 gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001183 memname(&t2, gc.Types[gc.TUINT16])
Russ Cox8afb3962015-03-04 22:58:27 -05001184 gins(x86.AFSTCW, nil, &t1)
1185 gins(x86.AMOVW, ncon(0xf7f), &t2)
1186 gins(x86.AFLDCW, &t2, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05001187
1188 // actual work
Russ Cox8afb3962015-03-04 22:58:27 -05001189 gins(x86.AFMOVD, &two63f, &f0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001190
Russ Cox8afb3962015-03-04 22:58:27 -05001191 gins(x86.AFUCOMIP, &f0, &f1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001192 p2 = gc.Gbranch(optoas(gc.OLE, gc.Types[tt]), nil, 0)
Russ Cox8afb3962015-03-04 22:58:27 -05001193 gins(x86.AFMOVVP, &f0, t)
Russ Cox382b44e2015-02-23 16:07:24 -05001194 p3 := gc.Gbranch(obj.AJMP, nil, 0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001195 gc.Patch(p2, gc.Pc)
Russ Cox8afb3962015-03-04 22:58:27 -05001196 gins(x86.AFMOVD, &two63f, &f0)
1197 gins(x86.AFSUBDP, &f0, &f1)
1198 gins(x86.AFMOVVP, &f0, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001199 split64(t, &tlo, &thi)
Russ Cox8afb3962015-03-04 22:58:27 -05001200 gins(x86.AXORL, ncon(0x80000000), &thi) // + 2^63
Russ Cox8c195bd2015-02-13 14:40:36 -05001201 gc.Patch(p3, gc.Pc)
1202 splitclean()
1203
1204 // restore rounding mode
Russ Cox8afb3962015-03-04 22:58:27 -05001205 gins(x86.AFLDCW, &t1, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05001206
1207 gc.Patch(p1, gc.Pc)
1208 return
1209
1210 /*
1211 * integer to float
1212 */
1213 case gc.TINT64<<16 | gc.TFLOAT32,
1214 gc.TINT64<<16 | gc.TFLOAT64:
1215 if t.Op == gc.OREGISTER {
1216 goto hardmem
1217 }
Russ Cox382b44e2015-02-23 16:07:24 -05001218 var f0 gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -05001219 gc.Nodreg(&f0, t.Type, x86.REG_F0)
1220 gins(x86.AFMOVV, f, &f0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001221 if tt == gc.TFLOAT32 {
Russ Cox8afb3962015-03-04 22:58:27 -05001222 gins(x86.AFMOVFP, &f0, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001223 } else {
Russ Cox8afb3962015-03-04 22:58:27 -05001224 gins(x86.AFMOVDP, &f0, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001225 }
1226 return
1227
1228 // algorithm is:
1229 // if small enough, use native int64 -> float64 conversion.
1230 // otherwise, halve (rounding to odd?), convert, and double.
1231 case gc.TUINT64<<16 | gc.TFLOAT32,
1232 gc.TUINT64<<16 | gc.TFLOAT64:
Russ Cox382b44e2015-02-23 16:07:24 -05001233 var ax gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -05001234 gc.Nodreg(&ax, gc.Types[gc.TUINT32], x86.REG_AX)
Russ Cox8c195bd2015-02-13 14:40:36 -05001235
Russ Cox382b44e2015-02-23 16:07:24 -05001236 var dx gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -05001237 gc.Nodreg(&dx, gc.Types[gc.TUINT32], x86.REG_DX)
Russ Cox382b44e2015-02-23 16:07:24 -05001238 var cx gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -05001239 gc.Nodreg(&cx, gc.Types[gc.TUINT32], x86.REG_CX)
Russ Cox382b44e2015-02-23 16:07:24 -05001240 var t1 gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001241 gc.Tempname(&t1, f.Type)
Russ Cox382b44e2015-02-23 16:07:24 -05001242 var tlo gc.Node
1243 var thi gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001244 split64(&t1, &tlo, &thi)
1245 gmove(f, &t1)
Russ Cox8afb3962015-03-04 22:58:27 -05001246 gins(x86.ACMPL, &thi, ncon(0))
1247 p1 := gc.Gbranch(x86.AJLT, nil, 0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001248
1249 // native
Russ Cox382b44e2015-02-23 16:07:24 -05001250 var r1 gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -05001251 gc.Nodreg(&r1, gc.Types[tt], x86.REG_F0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001252
Russ Cox8afb3962015-03-04 22:58:27 -05001253 gins(x86.AFMOVV, &t1, &r1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001254 if tt == gc.TFLOAT32 {
Russ Cox8afb3962015-03-04 22:58:27 -05001255 gins(x86.AFMOVFP, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001256 } else {
Russ Cox8afb3962015-03-04 22:58:27 -05001257 gins(x86.AFMOVDP, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001258 }
Russ Cox382b44e2015-02-23 16:07:24 -05001259 p2 := gc.Gbranch(obj.AJMP, nil, 0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001260
1261 // simulated
1262 gc.Patch(p1, gc.Pc)
1263
1264 gmove(&tlo, &ax)
1265 gmove(&thi, &dx)
Russ Cox8afb3962015-03-04 22:58:27 -05001266 p1 = gins(x86.ASHRL, ncon(1), &ax)
1267 p1.From.Index = x86.REG_DX // double-width shift DX -> AX
Russ Cox8c195bd2015-02-13 14:40:36 -05001268 p1.From.Scale = 0
Russ Cox8afb3962015-03-04 22:58:27 -05001269 gins(x86.AMOVL, ncon(0), &cx)
1270 gins(x86.ASETCC, nil, &cx)
1271 gins(x86.AORL, &cx, &ax)
1272 gins(x86.ASHRL, ncon(1), &dx)
Russ Cox8c195bd2015-02-13 14:40:36 -05001273 gmove(&dx, &thi)
1274 gmove(&ax, &tlo)
Russ Cox8afb3962015-03-04 22:58:27 -05001275 gc.Nodreg(&r1, gc.Types[tt], x86.REG_F0)
Russ Cox382b44e2015-02-23 16:07:24 -05001276 var r2 gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -05001277 gc.Nodreg(&r2, gc.Types[tt], x86.REG_F0+1)
1278 gins(x86.AFMOVV, &t1, &r1)
1279 gins(x86.AFMOVD, &r1, &r1)
1280 gins(x86.AFADDDP, &r1, &r2)
Russ Cox8c195bd2015-02-13 14:40:36 -05001281 if tt == gc.TFLOAT32 {
Russ Cox8afb3962015-03-04 22:58:27 -05001282 gins(x86.AFMOVFP, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001283 } else {
Russ Cox8afb3962015-03-04 22:58:27 -05001284 gins(x86.AFMOVDP, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001285 }
1286 gc.Patch(p2, gc.Pc)
1287 splitclean()
1288 return
1289 }
1290
1291 // requires register intermediate
1292hard:
Russ Coxb115c352015-03-18 17:26:36 -04001293 gc.Regalloc(&r1, cvt, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001294
1295 gmove(f, &r1)
1296 gmove(&r1, t)
Russ Coxb115c352015-03-18 17:26:36 -04001297 gc.Regfree(&r1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001298 return
1299
1300 // requires memory intermediate
1301hardmem:
1302 gc.Tempname(&r1, cvt)
1303
1304 gmove(f, &r1)
1305 gmove(&r1, t)
1306 return
1307}
1308
1309func floatmove_387(f *gc.Node, t *gc.Node) {
1310 var r1 gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001311 var a int
Russ Cox8c195bd2015-02-13 14:40:36 -05001312
Russ Cox382b44e2015-02-23 16:07:24 -05001313 ft := gc.Simsimtype(f.Type)
1314 tt := gc.Simsimtype(t.Type)
1315 cvt := t.Type
Russ Cox8c195bd2015-02-13 14:40:36 -05001316
1317 switch uint32(ft)<<16 | uint32(tt) {
1318 default:
1319 goto fatal
1320
1321 /*
1322 * float to integer
1323 */
1324 case gc.TFLOAT32<<16 | gc.TINT16,
1325 gc.TFLOAT32<<16 | gc.TINT32,
1326 gc.TFLOAT32<<16 | gc.TINT64,
1327 gc.TFLOAT64<<16 | gc.TINT16,
1328 gc.TFLOAT64<<16 | gc.TINT32,
1329 gc.TFLOAT64<<16 | gc.TINT64:
1330 if t.Op == gc.OREGISTER {
1331 goto hardmem
1332 }
Russ Cox382b44e2015-02-23 16:07:24 -05001333 var r1 gc.Node
Russ Cox8afb3962015-03-04 22:58:27 -05001334 gc.Nodreg(&r1, gc.Types[ft], x86.REG_F0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001335 if f.Op != gc.OREGISTER {
1336 if ft == gc.TFLOAT32 {
Russ Cox8afb3962015-03-04 22:58:27 -05001337 gins(x86.AFMOVF, f, &r1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001338 } else {
Russ Cox8afb3962015-03-04 22:58:27 -05001339 gins(x86.AFMOVD, f, &r1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001340 }
1341 }
1342
1343 // set round to zero mode during conversion
Russ Cox382b44e2015-02-23 16:07:24 -05001344 var t1 gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001345 memname(&t1, gc.Types[gc.TUINT16])
1346
Russ Cox382b44e2015-02-23 16:07:24 -05001347 var t2 gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001348 memname(&t2, gc.Types[gc.TUINT16])
Russ Cox8afb3962015-03-04 22:58:27 -05001349 gins(x86.AFSTCW, nil, &t1)
1350 gins(x86.AMOVW, ncon(0xf7f), &t2)
1351 gins(x86.AFLDCW, &t2, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05001352 if tt == gc.TINT16 {
Russ Cox8afb3962015-03-04 22:58:27 -05001353 gins(x86.AFMOVWP, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001354 } else if tt == gc.TINT32 {
Russ Cox8afb3962015-03-04 22:58:27 -05001355 gins(x86.AFMOVLP, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001356 } else {
Russ Cox8afb3962015-03-04 22:58:27 -05001357 gins(x86.AFMOVVP, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001358 }
Russ Cox8afb3962015-03-04 22:58:27 -05001359 gins(x86.AFLDCW, &t1, nil)
Russ Cox8c195bd2015-02-13 14:40:36 -05001360 return
1361
1362 // convert via int32.
1363 case gc.TFLOAT32<<16 | gc.TINT8,
1364 gc.TFLOAT32<<16 | gc.TUINT16,
1365 gc.TFLOAT32<<16 | gc.TUINT8,
1366 gc.TFLOAT64<<16 | gc.TINT8,
1367 gc.TFLOAT64<<16 | gc.TUINT16,
1368 gc.TFLOAT64<<16 | gc.TUINT8:
Russ Cox382b44e2015-02-23 16:07:24 -05001369 var t1 gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001370 gc.Tempname(&t1, gc.Types[gc.TINT32])
1371
1372 gmove(f, &t1)
1373 switch tt {
1374 default:
Håvard Haugen3c9fa382015-08-30 23:10:03 +02001375 gc.Fatalf("gmove %v", t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001376
1377 case gc.TINT8:
Russ Cox8afb3962015-03-04 22:58:27 -05001378 gins(x86.ACMPL, &t1, ncon(-0x80&(1<<32-1)))
Russ Cox382b44e2015-02-23 16:07:24 -05001379 p1 := gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TINT32]), nil, -1)
Russ Cox8afb3962015-03-04 22:58:27 -05001380 gins(x86.ACMPL, &t1, ncon(0x7f))
Russ Cox382b44e2015-02-23 16:07:24 -05001381 p2 := gc.Gbranch(optoas(gc.OGT, gc.Types[gc.TINT32]), nil, -1)
1382 p3 := gc.Gbranch(obj.AJMP, nil, 0)
Russ Cox8c195bd2015-02-13 14:40:36 -05001383 gc.Patch(p1, gc.Pc)
1384 gc.Patch(p2, gc.Pc)
1385 gmove(ncon(-0x80&(1<<32-1)), &t1)
1386 gc.Patch(p3, gc.Pc)
1387 gmove(&t1, t)
1388
1389 case gc.TUINT8:
Russ Cox8afb3962015-03-04 22:58:27 -05001390 gins(x86.ATESTL, ncon(0xffffff00), &t1)
1391 p1 := gc.Gbranch(x86.AJEQ, nil, +1)
1392 gins(x86.AMOVL, ncon(0), &t1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001393 gc.Patch(p1, gc.Pc)
1394 gmove(&t1, t)
1395
1396 case gc.TUINT16:
Russ Cox8afb3962015-03-04 22:58:27 -05001397 gins(x86.ATESTL, ncon(0xffff0000), &t1)
1398 p1 := gc.Gbranch(x86.AJEQ, nil, +1)
1399 gins(x86.AMOVL, ncon(0), &t1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001400 gc.Patch(p1, gc.Pc)
1401 gmove(&t1, t)
1402 }
1403
1404 return
1405
1406 // convert via int64.
1407 case gc.TFLOAT32<<16 | gc.TUINT32,
1408 gc.TFLOAT64<<16 | gc.TUINT32:
1409 cvt = gc.Types[gc.TINT64]
1410
1411 goto hardmem
1412
1413 /*
1414 * integer to float
1415 */
1416 case gc.TINT16<<16 | gc.TFLOAT32,
1417 gc.TINT16<<16 | gc.TFLOAT64,
1418 gc.TINT32<<16 | gc.TFLOAT32,
1419 gc.TINT32<<16 | gc.TFLOAT64,
1420 gc.TINT64<<16 | gc.TFLOAT32,
1421 gc.TINT64<<16 | gc.TFLOAT64:
1422 if t.Op != gc.OREGISTER {
1423 goto hard
1424 }
1425 if f.Op == gc.OREGISTER {
1426 cvt = f.Type
1427 goto hardmem
1428 }
1429
1430 switch ft {
1431 case gc.TINT16:
Russ Cox8afb3962015-03-04 22:58:27 -05001432 a = x86.AFMOVW
Russ Cox8c195bd2015-02-13 14:40:36 -05001433
1434 case gc.TINT32:
Russ Cox8afb3962015-03-04 22:58:27 -05001435 a = x86.AFMOVL
Russ Cox8c195bd2015-02-13 14:40:36 -05001436
1437 default:
Russ Cox8afb3962015-03-04 22:58:27 -05001438 a = x86.AFMOVV
Russ Cox8c195bd2015-02-13 14:40:36 -05001439 }
1440
1441 // convert via int32 memory
1442 case gc.TINT8<<16 | gc.TFLOAT32,
1443 gc.TINT8<<16 | gc.TFLOAT64,
1444 gc.TUINT16<<16 | gc.TFLOAT32,
1445 gc.TUINT16<<16 | gc.TFLOAT64,
1446 gc.TUINT8<<16 | gc.TFLOAT32,
1447 gc.TUINT8<<16 | gc.TFLOAT64:
1448 cvt = gc.Types[gc.TINT32]
1449
1450 goto hardmem
1451
1452 // convert via int64 memory
1453 case gc.TUINT32<<16 | gc.TFLOAT32,
1454 gc.TUINT32<<16 | gc.TFLOAT64:
1455 cvt = gc.Types[gc.TINT64]
1456
1457 goto hardmem
1458
1459 // The way the code generator uses floating-point
1460 // registers, a move from F0 to F0 is intended as a no-op.
1461 // On the x86, it's not: it pushes a second copy of F0
1462 // on the floating point stack. So toss it away here.
1463 // Also, F0 is the *only* register we ever evaluate
1464 // into, so we should only see register/register as F0/F0.
1465 /*
1466 * float to float
1467 */
1468 case gc.TFLOAT32<<16 | gc.TFLOAT32,
1469 gc.TFLOAT64<<16 | gc.TFLOAT64:
Russ Coxdc7b54b2015-02-17 22:13:49 -05001470 if gc.Ismem(f) && gc.Ismem(t) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001471 goto hard
1472 }
1473 if f.Op == gc.OREGISTER && t.Op == gc.OREGISTER {
Josh Bleecher Snyder5ed90cb2015-04-13 10:28:57 -07001474 if f.Reg != x86.REG_F0 || t.Reg != x86.REG_F0 {
Russ Cox8c195bd2015-02-13 14:40:36 -05001475 goto fatal
1476 }
1477 return
1478 }
1479
Russ Cox8afb3962015-03-04 22:58:27 -05001480 a = x86.AFMOVF
Russ Cox8c195bd2015-02-13 14:40:36 -05001481 if ft == gc.TFLOAT64 {
Russ Cox8afb3962015-03-04 22:58:27 -05001482 a = x86.AFMOVD
Russ Cox8c195bd2015-02-13 14:40:36 -05001483 }
Russ Coxdc7b54b2015-02-17 22:13:49 -05001484 if gc.Ismem(t) {
Josh Bleecher Snyder5ed90cb2015-04-13 10:28:57 -07001485 if f.Op != gc.OREGISTER || f.Reg != x86.REG_F0 {
Håvard Haugen3c9fa382015-08-30 23:10:03 +02001486 gc.Fatalf("gmove %v", f)
Russ Cox8c195bd2015-02-13 14:40:36 -05001487 }
Russ Cox8afb3962015-03-04 22:58:27 -05001488 a = x86.AFMOVFP
Russ Cox8c195bd2015-02-13 14:40:36 -05001489 if ft == gc.TFLOAT64 {
Russ Cox8afb3962015-03-04 22:58:27 -05001490 a = x86.AFMOVDP
Russ Cox8c195bd2015-02-13 14:40:36 -05001491 }
1492 }
1493
1494 case gc.TFLOAT32<<16 | gc.TFLOAT64:
Russ Coxdc7b54b2015-02-17 22:13:49 -05001495 if gc.Ismem(f) && gc.Ismem(t) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001496 goto hard
1497 }
1498 if f.Op == gc.OREGISTER && t.Op == gc.OREGISTER {
Josh Bleecher Snyder5ed90cb2015-04-13 10:28:57 -07001499 if f.Reg != x86.REG_F0 || t.Reg != x86.REG_F0 {
Russ Cox8c195bd2015-02-13 14:40:36 -05001500 goto fatal
1501 }
1502 return
1503 }
1504
1505 if f.Op == gc.OREGISTER {
Russ Cox8afb3962015-03-04 22:58:27 -05001506 gins(x86.AFMOVDP, f, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001507 } else {
Russ Cox8afb3962015-03-04 22:58:27 -05001508 gins(x86.AFMOVF, f, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001509 }
1510 return
1511
1512 case gc.TFLOAT64<<16 | gc.TFLOAT32:
Russ Coxdc7b54b2015-02-17 22:13:49 -05001513 if gc.Ismem(f) && gc.Ismem(t) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001514 goto hard
1515 }
1516 if f.Op == gc.OREGISTER && t.Op == gc.OREGISTER {
Russ Cox382b44e2015-02-23 16:07:24 -05001517 var r1 gc.Node
Russ Cox8c195bd2015-02-13 14:40:36 -05001518 gc.Tempname(&r1, gc.Types[gc.TFLOAT32])
Russ Cox8afb3962015-03-04 22:58:27 -05001519 gins(x86.AFMOVFP, f, &r1)
1520 gins(x86.AFMOVF, &r1, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001521 return
1522 }
1523
1524 if f.Op == gc.OREGISTER {
Russ Cox8afb3962015-03-04 22:58:27 -05001525 gins(x86.AFMOVFP, f, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001526 } else {
Russ Cox8afb3962015-03-04 22:58:27 -05001527 gins(x86.AFMOVD, f, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001528 }
1529 return
1530 }
1531
1532 gins(a, f, t)
1533 return
1534
1535 // requires register intermediate
1536hard:
Russ Coxb115c352015-03-18 17:26:36 -04001537 gc.Regalloc(&r1, cvt, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001538
1539 gmove(f, &r1)
1540 gmove(&r1, t)
Russ Coxb115c352015-03-18 17:26:36 -04001541 gc.Regfree(&r1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001542 return
1543
1544 // requires memory intermediate
1545hardmem:
1546 gc.Tempname(&r1, cvt)
1547
1548 gmove(f, &r1)
1549 gmove(&r1, t)
1550 return
1551
1552 // should not happen
1553fatal:
Håvard Haugen3c9fa382015-08-30 23:10:03 +02001554 gc.Fatalf("gmove %v -> %v", gc.Nconv(f, obj.FmtLong), gc.Nconv(t, obj.FmtLong))
Russ Cox8c195bd2015-02-13 14:40:36 -05001555
1556 return
1557}
1558
1559func floatmove_sse(f *gc.Node, t *gc.Node) {
1560 var r1 gc.Node
1561 var cvt *gc.Type
1562 var a int
Russ Cox8c195bd2015-02-13 14:40:36 -05001563
Russ Cox382b44e2015-02-23 16:07:24 -05001564 ft := gc.Simsimtype(f.Type)
1565 tt := gc.Simsimtype(t.Type)
Russ Cox8c195bd2015-02-13 14:40:36 -05001566
1567 switch uint32(ft)<<16 | uint32(tt) {
1568 // should not happen
1569 default:
Håvard Haugen3c9fa382015-08-30 23:10:03 +02001570 gc.Fatalf("gmove %v -> %v", f, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001571
1572 return
1573
1574 // convert via int32.
1575 /*
1576 * float to integer
1577 */
1578 case gc.TFLOAT32<<16 | gc.TINT16,
1579 gc.TFLOAT32<<16 | gc.TINT8,
1580 gc.TFLOAT32<<16 | gc.TUINT16,
1581 gc.TFLOAT32<<16 | gc.TUINT8,
1582 gc.TFLOAT64<<16 | gc.TINT16,
1583 gc.TFLOAT64<<16 | gc.TINT8,
1584 gc.TFLOAT64<<16 | gc.TUINT16,
1585 gc.TFLOAT64<<16 | gc.TUINT8:
1586 cvt = gc.Types[gc.TINT32]
1587
1588 goto hard
1589
1590 // convert via int64.
1591 case gc.TFLOAT32<<16 | gc.TUINT32,
1592 gc.TFLOAT64<<16 | gc.TUINT32:
1593 cvt = gc.Types[gc.TINT64]
1594
1595 goto hardmem
1596
1597 case gc.TFLOAT32<<16 | gc.TINT32:
Russ Cox8afb3962015-03-04 22:58:27 -05001598 a = x86.ACVTTSS2SL
Russ Cox8c195bd2015-02-13 14:40:36 -05001599 goto rdst
1600
1601 case gc.TFLOAT64<<16 | gc.TINT32:
Russ Cox8afb3962015-03-04 22:58:27 -05001602 a = x86.ACVTTSD2SL
Russ Cox8c195bd2015-02-13 14:40:36 -05001603 goto rdst
1604
1605 // convert via int32 memory
1606 /*
1607 * integer to float
1608 */
1609 case gc.TINT8<<16 | gc.TFLOAT32,
1610 gc.TINT8<<16 | gc.TFLOAT64,
1611 gc.TINT16<<16 | gc.TFLOAT32,
1612 gc.TINT16<<16 | gc.TFLOAT64,
1613 gc.TUINT16<<16 | gc.TFLOAT32,
1614 gc.TUINT16<<16 | gc.TFLOAT64,
1615 gc.TUINT8<<16 | gc.TFLOAT32,
1616 gc.TUINT8<<16 | gc.TFLOAT64:
1617 cvt = gc.Types[gc.TINT32]
1618
1619 goto hard
1620
1621 // convert via int64 memory
1622 case gc.TUINT32<<16 | gc.TFLOAT32,
1623 gc.TUINT32<<16 | gc.TFLOAT64:
1624 cvt = gc.Types[gc.TINT64]
1625
1626 goto hardmem
1627
1628 case gc.TINT32<<16 | gc.TFLOAT32:
Russ Cox8afb3962015-03-04 22:58:27 -05001629 a = x86.ACVTSL2SS
Russ Cox8c195bd2015-02-13 14:40:36 -05001630 goto rdst
1631
1632 case gc.TINT32<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -05001633 a = x86.ACVTSL2SD
Russ Cox8c195bd2015-02-13 14:40:36 -05001634 goto rdst
1635
1636 /*
1637 * float to float
1638 */
1639 case gc.TFLOAT32<<16 | gc.TFLOAT32:
Russ Cox8afb3962015-03-04 22:58:27 -05001640 a = x86.AMOVSS
Russ Cox8c195bd2015-02-13 14:40:36 -05001641
1642 case gc.TFLOAT64<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -05001643 a = x86.AMOVSD
Russ Cox8c195bd2015-02-13 14:40:36 -05001644
1645 case gc.TFLOAT32<<16 | gc.TFLOAT64:
Russ Cox8afb3962015-03-04 22:58:27 -05001646 a = x86.ACVTSS2SD
Russ Cox8c195bd2015-02-13 14:40:36 -05001647 goto rdst
1648
1649 case gc.TFLOAT64<<16 | gc.TFLOAT32:
Russ Cox8afb3962015-03-04 22:58:27 -05001650 a = x86.ACVTSD2SS
Russ Cox8c195bd2015-02-13 14:40:36 -05001651 goto rdst
1652 }
1653
1654 gins(a, f, t)
1655 return
1656
1657 // requires register intermediate
1658hard:
Russ Coxb115c352015-03-18 17:26:36 -04001659 gc.Regalloc(&r1, cvt, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001660
1661 gmove(f, &r1)
1662 gmove(&r1, t)
Russ Coxb115c352015-03-18 17:26:36 -04001663 gc.Regfree(&r1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001664 return
1665
1666 // requires memory intermediate
1667hardmem:
1668 gc.Tempname(&r1, cvt)
1669
1670 gmove(f, &r1)
1671 gmove(&r1, t)
1672 return
1673
1674 // requires register destination
1675rdst:
Russ Coxb115c352015-03-18 17:26:36 -04001676 gc.Regalloc(&r1, t.Type, t)
Russ Cox8c195bd2015-02-13 14:40:36 -05001677
1678 gins(a, f, &r1)
1679 gmove(&r1, t)
Russ Coxb115c352015-03-18 17:26:36 -04001680 gc.Regfree(&r1)
Russ Cox8c195bd2015-02-13 14:40:36 -05001681 return
1682}
1683
Russ Coxdc7b54b2015-02-17 22:13:49 -05001684func samaddr(f *gc.Node, t *gc.Node) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -05001685 if f.Op != t.Op {
Russ Coxdc7b54b2015-02-17 22:13:49 -05001686 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001687 }
1688
1689 switch f.Op {
1690 case gc.OREGISTER:
Josh Bleecher Snyder5ed90cb2015-04-13 10:28:57 -07001691 if f.Reg != t.Reg {
Russ Cox8c195bd2015-02-13 14:40:36 -05001692 break
1693 }
Russ Coxdc7b54b2015-02-17 22:13:49 -05001694 return true
Russ Cox8c195bd2015-02-13 14:40:36 -05001695 }
1696
Russ Coxdc7b54b2015-02-17 22:13:49 -05001697 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001698}
1699
1700/*
1701 * generate one instruction:
1702 * as f, t
1703 */
1704func gins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
Russ Cox8afb3962015-03-04 22:58:27 -05001705 if as == x86.AFMOVF && f != nil && f.Op == gc.OREGISTER && t != nil && t.Op == gc.OREGISTER {
Håvard Haugen3c9fa382015-08-30 23:10:03 +02001706 gc.Fatalf("gins MOVF reg, reg")
Russ Cox8c195bd2015-02-13 14:40:36 -05001707 }
Russ Cox8afb3962015-03-04 22:58:27 -05001708 if as == x86.ACVTSD2SS && f != nil && f.Op == gc.OLITERAL {
Håvard Haugen3c9fa382015-08-30 23:10:03 +02001709 gc.Fatalf("gins CVTSD2SS const")
Russ Cox8c195bd2015-02-13 14:40:36 -05001710 }
Josh Bleecher Snyder5ed90cb2015-04-13 10:28:57 -07001711 if as == x86.AMOVSD && t != nil && t.Op == gc.OREGISTER && t.Reg == x86.REG_F0 {
Håvard Haugen3c9fa382015-08-30 23:10:03 +02001712 gc.Fatalf("gins MOVSD into F0")
Russ Cox8c195bd2015-02-13 14:40:36 -05001713 }
1714
Russ Coxb115c352015-03-18 17:26:36 -04001715 if as == x86.AMOVL && f != nil && f.Op == gc.OADDR && f.Left.Op == gc.ONAME && f.Left.Class != gc.PEXTERN && f.Left.Class != gc.PFUNC {
1716 // Turn MOVL $xxx(FP/SP) into LEAL xxx.
1717 // These should be equivalent but most of the backend
1718 // only expects to see LEAL, because that's what we had
1719 // historically generated. Various hidden assumptions are baked in by now.
1720 as = x86.ALEAL
1721 f = f.Left
1722 }
1723
Russ Cox8c195bd2015-02-13 14:40:36 -05001724 switch as {
Russ Cox8afb3962015-03-04 22:58:27 -05001725 case x86.AMOVB,
1726 x86.AMOVW,
1727 x86.AMOVL:
Russ Coxdc7b54b2015-02-17 22:13:49 -05001728 if f != nil && t != nil && samaddr(f, t) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001729 return nil
1730 }
1731
Russ Cox8afb3962015-03-04 22:58:27 -05001732 case x86.ALEAL:
Russ Coxdc7b54b2015-02-17 22:13:49 -05001733 if f != nil && gc.Isconst(f, gc.CTNIL) {
Håvard Haugen3c9fa382015-08-30 23:10:03 +02001734 gc.Fatalf("gins LEAL nil %v", f.Type)
Russ Cox8c195bd2015-02-13 14:40:36 -05001735 }
1736 }
1737
Russ Cox382b44e2015-02-23 16:07:24 -05001738 p := gc.Prog(as)
Russ Cox8b9a3d42015-03-16 15:27:19 -04001739 gc.Naddr(&p.From, f)
1740 gc.Naddr(&p.To, t)
1741
Russ Cox8c195bd2015-02-13 14:40:36 -05001742 if gc.Debug['g'] != 0 {
1743 fmt.Printf("%v\n", p)
1744 }
1745
Russ Cox382b44e2015-02-23 16:07:24 -05001746 w := 0
Russ Cox8c195bd2015-02-13 14:40:36 -05001747 switch as {
Russ Cox8afb3962015-03-04 22:58:27 -05001748 case x86.AMOVB:
Russ Cox8c195bd2015-02-13 14:40:36 -05001749 w = 1
1750
Russ Cox8afb3962015-03-04 22:58:27 -05001751 case x86.AMOVW:
Russ Cox8c195bd2015-02-13 14:40:36 -05001752 w = 2
1753
Russ Cox8afb3962015-03-04 22:58:27 -05001754 case x86.AMOVL:
Russ Cox8c195bd2015-02-13 14:40:36 -05001755 w = 4
1756 }
1757
Russ Cox8b9a3d42015-03-16 15:27:19 -04001758 if true && w != 0 && f != nil && (p.From.Width > int64(w) || p.To.Width > int64(w)) {
Russ Cox8c195bd2015-02-13 14:40:36 -05001759 gc.Dump("bad width from:", f)
1760 gc.Dump("bad width to:", t)
Håvard Haugen3c9fa382015-08-30 23:10:03 +02001761 gc.Fatalf("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
Russ Cox8c195bd2015-02-13 14:40:36 -05001762 }
1763
1764 if p.To.Type == obj.TYPE_ADDR && w > 0 {
Håvard Haugen3c9fa382015-08-30 23:10:03 +02001765 gc.Fatalf("bad use of addr: %v", p)
Russ Cox8c195bd2015-02-13 14:40:36 -05001766 }
1767
1768 return p
1769}
1770
Russ Coxb115c352015-03-18 17:26:36 -04001771func ginsnop() {
1772 var reg gc.Node
1773 gc.Nodreg(&reg, gc.Types[gc.TINT], x86.REG_AX)
1774 gins(x86.AXCHGL, &reg, &reg)
1775}
1776
Russ Coxdc7b54b2015-02-17 22:13:49 -05001777func dotaddable(n *gc.Node, n1 *gc.Node) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -05001778 if n.Op != gc.ODOT {
Russ Coxdc7b54b2015-02-17 22:13:49 -05001779 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001780 }
1781
Russ Cox382b44e2015-02-23 16:07:24 -05001782 var oary [10]int64
1783 var nn *gc.Node
1784 o := gc.Dotoffset(n, oary[:], &nn)
Josh Bleecher Snyder75883ba2015-04-02 19:58:37 -07001785 if nn != nil && nn.Addable && o == 1 && oary[0] >= 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -05001786 *n1 = *nn
1787 n1.Type = n.Type
1788 n1.Xoffset += oary[0]
Russ Coxdc7b54b2015-02-17 22:13:49 -05001789 return true
Russ Cox8c195bd2015-02-13 14:40:36 -05001790 }
1791
Russ Coxdc7b54b2015-02-17 22:13:49 -05001792 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001793}
1794
1795func sudoclean() {
1796}
1797
Russ Coxdc7b54b2015-02-17 22:13:49 -05001798func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool {
Russ Cox8c195bd2015-02-13 14:40:36 -05001799 *a = obj.Addr{}
Russ Coxdc7b54b2015-02-17 22:13:49 -05001800 return false
Russ Cox8c195bd2015-02-13 14:40:36 -05001801}