blob: f70e342a961f64e6beb97124a48d5bb05986bbde [file] [log] [blame]
Russ Cox8c195bd2015-02-13 14:40:36 -05001// Copyright 2009 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
5package gc
6
Robert Griesemer5750b712015-03-26 18:07:19 -07007import (
Russ Cox17eba6e2015-05-21 13:28:10 -04008 "cmd/compile/internal/big"
Robert Griesemer5750b712015-03-26 18:07:19 -07009 "cmd/internal/obj"
10 "fmt"
11)
Robert Griesemer888767f2015-03-18 14:10:22 -070012
Robert Griesemer888767f2015-03-18 14:10:22 -070013/// implements fix arithmetic
Russ Cox8c195bd2015-02-13 14:40:36 -050014
Robert Griesemer888767f2015-03-18 14:10:22 -070015func mpsetovf(a *Mpint) {
Robert Griesemer99475df2015-04-21 10:39:21 -070016 a.Val.SetUint64(1) // avoid spurious div-zero errors
Robert Griesemer888767f2015-03-18 14:10:22 -070017 a.Ovf = true
18}
19
20func mptestovf(a *Mpint, extra int) bool {
21 // We don't need to be precise here, any reasonable upper limit would do.
22 // For now, use existing limit so we pass all the tests unchanged.
Robert Griesemer5750b712015-03-26 18:07:19 -070023 if a.Val.BitLen()+extra > Mpprec {
Robert Griesemer888767f2015-03-18 14:10:22 -070024 mpsetovf(a)
25 }
26 return a.Ovf
27}
28
Robert Griesemer5750b712015-03-26 18:07:19 -070029func mpmovefixfix(a, b *Mpint) {
30 a.Val.Set(&b.Val)
31}
32
33func mpmovefltfix(a *Mpint, b *Mpflt) int {
34 if _, acc := b.Val.Int(&a.Val); acc == big.Exact {
35 return 0
36 }
37
Robert Griesemera51d5f22015-04-02 16:34:48 -070038 const delta = 16 // a reasonably small number of bits > 0
Robert Griesemer5750b712015-03-26 18:07:19 -070039 var t big.Float
40 t.SetPrec(Mpprec - delta)
41
42 // try rounding down a little
43 t.SetMode(big.ToZero)
44 t.Set(&b.Val)
45 if _, acc := t.Int(&a.Val); acc == big.Exact {
46 return 0
47 }
48
49 // try rounding up a little
50 t.SetMode(big.AwayFromZero)
51 t.Set(&b.Val)
52 if _, acc := t.Int(&a.Val); acc == big.Exact {
53 return 0
54 }
55
56 return -1
57}
58
Robert Griesemer888767f2015-03-18 14:10:22 -070059func mpaddfixfix(a, b *Mpint, quiet int) {
60 if a.Ovf || b.Ovf {
61 if nsavederrors+nerrors == 0 {
Robert Griesemer5750b712015-03-26 18:07:19 -070062 Yyerror("ovf in mpaddfixfix")
Robert Griesemer888767f2015-03-18 14:10:22 -070063 }
64 mpsetovf(a)
65 return
66 }
67
68 a.Val.Add(&a.Val, &b.Val)
69
70 if mptestovf(a, 0) && quiet == 0 {
71 Yyerror("constant addition overflow")
72 }
73}
74
Robert Griesemer5750b712015-03-26 18:07:19 -070075func mpsubfixfix(a, b *Mpint) {
76 if a.Ovf || b.Ovf {
77 if nsavederrors+nerrors == 0 {
78 Yyerror("ovf in mpsubfixfix")
79 }
80 mpsetovf(a)
81 return
82 }
83
84 a.Val.Sub(&a.Val, &b.Val)
85
86 if mptestovf(a, 0) {
87 Yyerror("constant subtraction overflow")
88 }
89}
90
Robert Griesemer888767f2015-03-18 14:10:22 -070091func mpmulfixfix(a, b *Mpint) {
92 if a.Ovf || b.Ovf {
93 if nsavederrors+nerrors == 0 {
94 Yyerror("ovf in mpmulfixfix")
95 }
96 mpsetovf(a)
97 return
98 }
99
100 a.Val.Mul(&a.Val, &b.Val)
101
102 if mptestovf(a, 0) {
103 Yyerror("constant multiplication overflow")
104 }
105}
106
Robert Griesemer5750b712015-03-26 18:07:19 -0700107func mpdivfixfix(a, b *Mpint) {
108 if a.Ovf || b.Ovf {
109 if nsavederrors+nerrors == 0 {
110 Yyerror("ovf in mpdivfixfix")
111 }
112 mpsetovf(a)
113 return
114 }
115
116 a.Val.Quo(&a.Val, &b.Val)
117
118 if mptestovf(a, 0) {
119 // can only happen for div-0 which should be checked elsewhere
120 Yyerror("constant division overflow")
121 }
122}
123
124func mpmodfixfix(a, b *Mpint) {
125 if a.Ovf || b.Ovf {
126 if nsavederrors+nerrors == 0 {
127 Yyerror("ovf in mpmodfixfix")
128 }
129 mpsetovf(a)
130 return
131 }
132
133 a.Val.Rem(&a.Val, &b.Val)
134
135 if mptestovf(a, 0) {
136 // should never happen
137 Yyerror("constant modulo overflow")
138 }
139}
140
Robert Griesemer888767f2015-03-18 14:10:22 -0700141func mporfixfix(a, b *Mpint) {
142 if a.Ovf || b.Ovf {
143 if nsavederrors+nerrors == 0 {
144 Yyerror("ovf in mporfixfix")
145 }
146 mpsetovf(a)
147 return
148 }
149
150 a.Val.Or(&a.Val, &b.Val)
151}
152
Robert Griesemer888767f2015-03-18 14:10:22 -0700153func mpandfixfix(a, b *Mpint) {
154 if a.Ovf || b.Ovf {
155 if nsavederrors+nerrors == 0 {
156 Yyerror("ovf in mpandfixfix")
157 }
158 mpsetovf(a)
159 return
160 }
161
162 a.Val.And(&a.Val, &b.Val)
163}
164
Robert Griesemer888767f2015-03-18 14:10:22 -0700165func mpandnotfixfix(a, b *Mpint) {
166 if a.Ovf || b.Ovf {
167 if nsavederrors+nerrors == 0 {
168 Yyerror("ovf in mpandnotfixfix")
169 }
170 mpsetovf(a)
171 return
172 }
173
174 a.Val.AndNot(&a.Val, &b.Val)
175}
176
Robert Griesemer888767f2015-03-18 14:10:22 -0700177func mpxorfixfix(a, b *Mpint) {
178 if a.Ovf || b.Ovf {
179 if nsavederrors+nerrors == 0 {
180 Yyerror("ovf in mpxorfixfix")
181 }
182 mpsetovf(a)
183 return
184 }
185
186 a.Val.Xor(&a.Val, &b.Val)
187}
188
Robert Griesemer5750b712015-03-26 18:07:19 -0700189// shift left by s (or right by -s)
190func Mpshiftfix(a *Mpint, s int) {
191 switch {
192 case s > 0:
193 if mptestovf(a, s) {
194 Yyerror("constant shift overflow")
195 return
196 }
197 a.Val.Lsh(&a.Val, uint(s))
198 case s < 0:
199 a.Val.Rsh(&a.Val, uint(-s))
200 }
201}
202
Robert Griesemer888767f2015-03-18 14:10:22 -0700203func mplshfixfix(a, b *Mpint) {
204 if a.Ovf || b.Ovf {
Russ Cox8c195bd2015-02-13 14:40:36 -0500205 if nsavederrors+nerrors == 0 {
Robert Griesemer888767f2015-03-18 14:10:22 -0700206 Yyerror("ovf in mplshfixfix")
Russ Cox8c195bd2015-02-13 14:40:36 -0500207 }
Robert Griesemer888767f2015-03-18 14:10:22 -0700208 mpsetovf(a)
Russ Cox8c195bd2015-02-13 14:40:36 -0500209 return
210 }
211
Russ Cox382b44e2015-02-23 16:07:24 -0500212 s := Mpgetfix(b)
Robert Griesemer5750b712015-03-26 18:07:19 -0700213 if s < 0 || s >= Mpprec {
Russ Cox8c195bd2015-02-13 14:40:36 -0500214 Yyerror("stupid shift: %d", s)
215 Mpmovecfix(a, 0)
216 return
217 }
218
219 Mpshiftfix(a, int(s))
220}
221
Robert Griesemer888767f2015-03-18 14:10:22 -0700222func mprshfixfix(a, b *Mpint) {
223 if a.Ovf || b.Ovf {
224 if nsavederrors+nerrors == 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -0500225 Yyerror("ovf in mprshfixfix")
226 }
Robert Griesemer888767f2015-03-18 14:10:22 -0700227 mpsetovf(a)
Russ Cox8c195bd2015-02-13 14:40:36 -0500228 return
229 }
230
Russ Cox382b44e2015-02-23 16:07:24 -0500231 s := Mpgetfix(b)
Alberto Donizetti85de30e2015-08-20 17:53:41 +0200232 if s < 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -0500233 Yyerror("stupid shift: %d", s)
Robert Griesemer888767f2015-03-18 14:10:22 -0700234 if a.Val.Sign() < 0 {
Russ Cox8c195bd2015-02-13 14:40:36 -0500235 Mpmovecfix(a, -1)
236 } else {
237 Mpmovecfix(a, 0)
238 }
239 return
240 }
241
242 Mpshiftfix(a, int(-s))
243}
244
Robert Griesemer5750b712015-03-26 18:07:19 -0700245func Mpcmpfixfix(a, b *Mpint) int {
246 return a.Val.Cmp(&b.Val)
247}
248
249func mpcmpfixc(b *Mpint, c int64) int {
250 return b.Val.Cmp(big.NewInt(c))
251}
252
Russ Cox8c195bd2015-02-13 14:40:36 -0500253func mpnegfix(a *Mpint) {
Robert Griesemer888767f2015-03-18 14:10:22 -0700254 a.Val.Neg(&a.Val)
255}
256
Russ Cox8c195bd2015-02-13 14:40:36 -0500257func Mpgetfix(a *Mpint) int64 {
Robert Griesemer888767f2015-03-18 14:10:22 -0700258 if a.Ovf {
259 if nsavederrors+nerrors == 0 {
260 Yyerror("constant overflow")
261 }
262 return 0
263 }
264
265 return a.Val.Int64()
266}
267
Russ Cox8c195bd2015-02-13 14:40:36 -0500268func Mpmovecfix(a *Mpint, c int64) {
Robert Griesemer888767f2015-03-18 14:10:22 -0700269 a.Val.SetInt64(c)
270}
Robert Griesemer5750b712015-03-26 18:07:19 -0700271
272func mpatofix(a *Mpint, as string) {
273 _, ok := a.Val.SetString(as, 0)
274 if !ok {
275 // required syntax is [+-][0[x]]d*
276 // At the moment we lose precise error cause;
277 // the old code distinguished between:
278 // - malformed hex constant
279 // - malformed octal constant
280 // - malformed decimal constant
281 // TODO(gri) use different conversion function
282 Yyerror("malformed integer constant: %s", as)
283 a.Val.SetUint64(0)
284 return
285 }
286 if mptestovf(a, 0) {
287 Yyerror("constant too large: %s", as)
288 }
289}
290
Russ Cox96c91fa2015-04-17 11:56:29 -0400291func (x *Mpint) String() string {
292 return Bconv(x, 0)
293}
294
Robert Griesemer5750b712015-03-26 18:07:19 -0700295func Bconv(xval *Mpint, flag int) string {
296 if flag&obj.FmtSharp != 0 {
297 return fmt.Sprintf("%#x", &xval.Val)
298 }
299 return xval.Val.String()
300}