]>
Commit | Line | Data |
---|---|---|
b34c74ab JB |
1 | /* Miscellaneous routines making it easier to use GMP within GDB's framework. |
2 | ||
213516ef | 3 | Copyright (C) 2019-2023 Free Software Foundation, Inc. |
b34c74ab JB |
4 | |
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #ifndef GMP_UTILS_H | |
21 | #define GMP_UTILS_H | |
22 | ||
b34c74ab JB |
23 | /* Include <stdio.h> and <stdarg.h> ahead of <gmp.h>, so as to get |
24 | access to GMP's various formatting functions. */ | |
25 | #include <stdio.h> | |
26 | #include <stdarg.h> | |
27 | #include <gmp.h> | |
28 | #include "gdbsupport/traits.h" | |
29 | ||
987b6703 | 30 | /* Same as gmp_asprintf, but returning an std::string. */ |
b34c74ab | 31 | |
987b6703 | 32 | std::string gmp_string_printf (const char *fmt, ...); |
b34c74ab | 33 | |
7aeae94f TT |
34 | struct gdb_mpq; |
35 | struct gdb_mpf; | |
36 | ||
b34c74ab JB |
37 | /* A class to make it easier to use GMP's mpz_t values within GDB. */ |
38 | ||
39 | struct gdb_mpz | |
40 | { | |
b34c74ab | 41 | /* Constructors. */ |
7aeae94f | 42 | gdb_mpz () { mpz_init (m_val); } |
b34c74ab JB |
43 | |
44 | explicit gdb_mpz (const mpz_t &from_val) | |
45 | { | |
7aeae94f TT |
46 | mpz_init (m_val); |
47 | mpz_set (m_val, from_val); | |
b34c74ab JB |
48 | } |
49 | ||
50 | gdb_mpz (const gdb_mpz &from) | |
51 | { | |
7aeae94f TT |
52 | mpz_init (m_val); |
53 | mpz_set (m_val, from.m_val); | |
b34c74ab JB |
54 | } |
55 | ||
56 | /* Initialize using the given integral value. | |
57 | ||
58 | The main advantage of this method is that it handles both signed | |
59 | and unsigned types, with no size restriction. */ | |
60 | template<typename T, typename = gdb::Requires<std::is_integral<T>>> | |
61 | explicit gdb_mpz (T src) | |
62 | { | |
7aeae94f | 63 | mpz_init (m_val); |
b34c74ab JB |
64 | set (src); |
65 | } | |
66 | ||
67 | explicit gdb_mpz (gdb_mpz &&from) | |
68 | { | |
7aeae94f TT |
69 | mpz_init (m_val); |
70 | mpz_swap (m_val, from.m_val); | |
b34c74ab JB |
71 | } |
72 | ||
73 | ||
74 | gdb_mpz &operator= (const gdb_mpz &from) | |
75 | { | |
7aeae94f | 76 | mpz_set (m_val, from.m_val); |
b34c74ab JB |
77 | return *this; |
78 | } | |
79 | ||
80 | gdb_mpz &operator= (gdb_mpz &&other) | |
81 | { | |
7aeae94f | 82 | mpz_swap (m_val, other.m_val); |
b34c74ab JB |
83 | return *this; |
84 | } | |
85 | ||
86 | template<typename T, typename = gdb::Requires<std::is_integral<T>>> | |
87 | gdb_mpz &operator= (T src) | |
88 | { | |
89 | set (src); | |
90 | return *this; | |
91 | } | |
92 | ||
c225d6b8 TT |
93 | gdb_mpz &operator= (bool src) |
94 | { | |
95 | mpz_set_ui (m_val, (unsigned long) src); | |
96 | return *this; | |
97 | } | |
98 | ||
302273ca TT |
99 | /* Initialize this value from a string and a base. Returns true if |
100 | the string was parsed successfully, false otherwise. */ | |
101 | bool set (const char *str, int base) | |
102 | { | |
7aeae94f | 103 | return mpz_set_str (m_val, str, base) != -1; |
302273ca TT |
104 | } |
105 | ||
106 | /* Return a new value that is BASE**EXP. */ | |
107 | static gdb_mpz pow (unsigned long base, unsigned long exp) | |
108 | { | |
109 | gdb_mpz result; | |
7aeae94f | 110 | mpz_ui_pow_ui (result.m_val, base, exp); |
302273ca TT |
111 | return result; |
112 | } | |
113 | ||
c225d6b8 TT |
114 | /* Return a new value that is this value raised to EXP. */ |
115 | gdb_mpz pow (unsigned long exp) const | |
116 | { | |
117 | gdb_mpz result; | |
118 | mpz_pow_ui (result.m_val, m_val, exp); | |
119 | return result; | |
120 | } | |
121 | ||
767c4b92 | 122 | /* Convert this value to an integer of the given type. |
b34c74ab JB |
123 | |
124 | The return type can signed or unsigned, with no size restriction. */ | |
125 | template<typename T> T as_integer () const; | |
126 | ||
767c4b92 TT |
127 | /* Convert this value to an integer of the given type. If this |
128 | value is too large, it is truncated. | |
129 | ||
130 | The return type can signed or unsigned, with no size restriction. */ | |
131 | template<typename T> T as_integer_truncate () const; | |
132 | ||
c9f0b43f JB |
133 | /* Set VAL by importing the number stored in the byte array (BUF), |
134 | using the given BYTE_ORDER. The size of the data to read is | |
135 | the byte array's size. | |
b34c74ab JB |
136 | |
137 | UNSIGNED_P indicates whether the number has an unsigned type. */ | |
c9f0b43f | 138 | void read (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order, |
b34c74ab JB |
139 | bool unsigned_p); |
140 | ||
c9f0b43f JB |
141 | /* Write VAL into BUF as a number whose byte size is the size of BUF, |
142 | using the given BYTE_ORDER. | |
b34c74ab JB |
143 | |
144 | UNSIGNED_P indicates whether the number has an unsigned type. */ | |
c9f0b43f | 145 | void write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order, |
1c805ba0 TT |
146 | bool unsigned_p) const |
147 | { | |
148 | export_bits (buf, byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */, | |
149 | unsigned_p, true /* safe */); | |
150 | } | |
151 | ||
152 | /* Like write, but truncates the value to the desired number of | |
153 | bytes. */ | |
154 | void truncate (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order, | |
155 | bool unsigned_p) const | |
156 | { | |
157 | export_bits (buf, byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */, | |
158 | unsigned_p, false /* safe */); | |
159 | } | |
b34c74ab JB |
160 | |
161 | /* Return a string containing VAL. */ | |
7aeae94f | 162 | std::string str () const { return gmp_string_printf ("%Zd", m_val); } |
b34c74ab JB |
163 | |
164 | /* The destructor. */ | |
7aeae94f | 165 | ~gdb_mpz () { mpz_clear (m_val); } |
b34c74ab | 166 | |
302273ca TT |
167 | /* Negate this value in place. */ |
168 | void negate () | |
169 | { | |
7aeae94f | 170 | mpz_neg (m_val, m_val); |
302273ca TT |
171 | } |
172 | ||
c225d6b8 TT |
173 | /* Take the one's complement in place. */ |
174 | void complement () | |
175 | { mpz_com (m_val, m_val); } | |
176 | ||
177 | /* Mask this value to N bits, in place. */ | |
178 | void mask (unsigned n) | |
179 | { mpz_tdiv_r_2exp (m_val, m_val, n); } | |
180 | ||
181 | /* Return the sign of this value. This returns -1 for a negative | |
182 | value, 0 if the value is 0, and 1 for a positive value. */ | |
183 | int sgn () const | |
184 | { return mpz_sgn (m_val); } | |
185 | ||
186 | explicit operator bool () const | |
187 | { return sgn () != 0; } | |
188 | ||
302273ca TT |
189 | gdb_mpz &operator*= (long other) |
190 | { | |
7aeae94f | 191 | mpz_mul_si (m_val, m_val, other); |
302273ca TT |
192 | return *this; |
193 | } | |
194 | ||
c225d6b8 TT |
195 | gdb_mpz operator* (const gdb_mpz &other) const |
196 | { | |
197 | gdb_mpz result; | |
198 | mpz_mul (result.m_val, m_val, other.m_val); | |
199 | return result; | |
200 | } | |
201 | ||
202 | gdb_mpz operator/ (const gdb_mpz &other) const | |
203 | { | |
204 | gdb_mpz result; | |
205 | mpz_tdiv_q (result.m_val, m_val, other.m_val); | |
206 | return result; | |
207 | } | |
208 | ||
209 | gdb_mpz operator% (const gdb_mpz &other) const | |
210 | { | |
211 | gdb_mpz result; | |
212 | mpz_tdiv_r (result.m_val, m_val, other.m_val); | |
213 | return result; | |
214 | } | |
215 | ||
302273ca TT |
216 | gdb_mpz &operator+= (unsigned long other) |
217 | { | |
7aeae94f | 218 | mpz_add_ui (m_val, m_val, other); |
302273ca TT |
219 | return *this; |
220 | } | |
221 | ||
c225d6b8 TT |
222 | gdb_mpz &operator+= (const gdb_mpz &other) |
223 | { | |
224 | mpz_add (m_val, m_val, other.m_val); | |
225 | return *this; | |
226 | } | |
227 | ||
228 | gdb_mpz operator+ (const gdb_mpz &other) const | |
229 | { | |
230 | gdb_mpz result; | |
231 | mpz_add (result.m_val, m_val, other.m_val); | |
232 | return result; | |
233 | } | |
234 | ||
302273ca TT |
235 | gdb_mpz &operator-= (unsigned long other) |
236 | { | |
7aeae94f | 237 | mpz_sub_ui (m_val, m_val, other); |
302273ca TT |
238 | return *this; |
239 | } | |
240 | ||
c225d6b8 TT |
241 | gdb_mpz &operator-= (const gdb_mpz &other) |
242 | { | |
243 | mpz_sub (m_val, m_val, other.m_val); | |
244 | return *this; | |
245 | } | |
246 | ||
247 | gdb_mpz operator- (const gdb_mpz &other) const | |
248 | { | |
249 | gdb_mpz result; | |
250 | mpz_sub (result.m_val, m_val, other.m_val); | |
251 | return result; | |
252 | } | |
253 | ||
302273ca TT |
254 | gdb_mpz &operator<<= (unsigned long nbits) |
255 | { | |
7aeae94f | 256 | mpz_mul_2exp (m_val, m_val, nbits); |
302273ca TT |
257 | return *this; |
258 | } | |
259 | ||
c225d6b8 TT |
260 | gdb_mpz operator<< (unsigned long nbits) const |
261 | { | |
262 | gdb_mpz result; | |
263 | mpz_mul_2exp (result.m_val, m_val, nbits); | |
264 | return result; | |
265 | } | |
266 | ||
267 | gdb_mpz operator>> (unsigned long nbits) const | |
268 | { | |
269 | gdb_mpz result; | |
270 | mpz_tdiv_q_2exp (result.m_val, m_val, nbits); | |
271 | return result; | |
272 | } | |
273 | ||
274 | gdb_mpz &operator>>= (unsigned long nbits) | |
275 | { | |
276 | mpz_tdiv_q_2exp (m_val, m_val, nbits); | |
277 | return *this; | |
278 | } | |
279 | ||
280 | gdb_mpz operator& (const gdb_mpz &other) const | |
281 | { | |
282 | gdb_mpz result; | |
283 | mpz_and (result.m_val, m_val, other.m_val); | |
284 | return result; | |
285 | } | |
286 | ||
287 | gdb_mpz operator| (const gdb_mpz &other) const | |
288 | { | |
289 | gdb_mpz result; | |
290 | mpz_ior (result.m_val, m_val, other.m_val); | |
291 | return result; | |
292 | } | |
293 | ||
294 | gdb_mpz operator^ (const gdb_mpz &other) const | |
295 | { | |
296 | gdb_mpz result; | |
297 | mpz_xor (result.m_val, m_val, other.m_val); | |
298 | return result; | |
299 | } | |
300 | ||
302273ca TT |
301 | bool operator> (const gdb_mpz &other) const |
302 | { | |
7aeae94f | 303 | return mpz_cmp (m_val, other.m_val) > 0; |
302273ca TT |
304 | } |
305 | ||
c225d6b8 TT |
306 | bool operator>= (const gdb_mpz &other) const |
307 | { | |
308 | return mpz_cmp (m_val, other.m_val) >= 0; | |
309 | } | |
310 | ||
311 | bool operator< (const gdb_mpz &other) const | |
312 | { | |
313 | return mpz_cmp (m_val, other.m_val) < 0; | |
314 | } | |
315 | ||
316 | bool operator<= (const gdb_mpz &other) const | |
317 | { | |
318 | return mpz_cmp (m_val, other.m_val) <= 0; | |
319 | } | |
320 | ||
767c4b92 | 321 | bool operator< (long other) const |
302273ca | 322 | { |
7aeae94f | 323 | return mpz_cmp_si (m_val, other) < 0; |
302273ca TT |
324 | } |
325 | ||
326 | bool operator== (int other) const | |
327 | { | |
7aeae94f | 328 | return mpz_cmp_si (m_val, other) == 0; |
302273ca TT |
329 | } |
330 | ||
767c4b92 TT |
331 | bool operator== (long other) const |
332 | { | |
333 | return mpz_cmp_si (m_val, other) == 0; | |
334 | } | |
335 | ||
336 | bool operator== (unsigned long other) const | |
337 | { | |
338 | return mpz_cmp_ui (m_val, other) == 0; | |
339 | } | |
340 | ||
341 | template<typename T, | |
342 | typename = gdb::Requires< | |
343 | gdb::And<std::is_integral<T>, | |
344 | std::integral_constant<bool, | |
345 | (sizeof (T) > sizeof (long))>> | |
346 | > | |
347 | > | |
348 | bool operator== (T src) | |
349 | { | |
350 | return *this == gdb_mpz (src); | |
351 | } | |
352 | ||
302273ca TT |
353 | bool operator== (const gdb_mpz &other) const |
354 | { | |
7aeae94f | 355 | return mpz_cmp (m_val, other.m_val) == 0; |
302273ca TT |
356 | } |
357 | ||
c225d6b8 TT |
358 | bool operator!= (const gdb_mpz &other) const |
359 | { | |
360 | return mpz_cmp (m_val, other.m_val) != 0; | |
361 | } | |
362 | ||
b34c74ab JB |
363 | private: |
364 | ||
365 | /* Helper template for constructor and operator=. */ | |
366 | template<typename T> void set (T src); | |
63c457b9 JB |
367 | |
368 | /* Low-level function to export VAL into BUF as a number whose byte size | |
369 | is the size of BUF. | |
370 | ||
371 | If UNSIGNED_P is true, then export VAL into BUF as an unsigned value. | |
372 | Otherwise, export it as a signed value. | |
373 | ||
374 | The API is inspired from GMP's mpz_export, hence the naming and types | |
375 | of the following parameter: | |
376 | - ENDIAN should be: | |
287de656 | 377 | . 1 for most significant byte first; or |
63c457b9 JB |
378 | . -1 for least significant byte first; or |
379 | . 0 for native endianness. | |
380 | ||
1c805ba0 TT |
381 | If SAFE is true, an error is raised if BUF is not large enough to |
382 | contain the value being exported. If SAFE is false, the value is | |
383 | truncated to fit in BUF. */ | |
384 | void export_bits (gdb::array_view<gdb_byte> buf, int endian, bool unsigned_p, | |
385 | bool safe) const; | |
7aeae94f TT |
386 | |
387 | friend struct gdb_mpq; | |
388 | friend struct gdb_mpf; | |
389 | ||
390 | mpz_t m_val; | |
b34c74ab JB |
391 | }; |
392 | ||
393 | /* A class to make it easier to use GMP's mpq_t values within GDB. */ | |
394 | ||
395 | struct gdb_mpq | |
396 | { | |
b34c74ab | 397 | /* Constructors. */ |
81768386 | 398 | gdb_mpq () { mpq_init (m_val); } |
b34c74ab JB |
399 | |
400 | explicit gdb_mpq (const mpq_t &from_val) | |
401 | { | |
81768386 TT |
402 | mpq_init (m_val); |
403 | mpq_set (m_val, from_val); | |
b34c74ab JB |
404 | } |
405 | ||
406 | gdb_mpq (const gdb_mpq &from) | |
407 | { | |
81768386 TT |
408 | mpq_init (m_val); |
409 | mpq_set (m_val, from.m_val); | |
b34c74ab JB |
410 | } |
411 | ||
412 | explicit gdb_mpq (gdb_mpq &&from) | |
413 | { | |
81768386 TT |
414 | mpq_init (m_val); |
415 | mpq_swap (m_val, from.m_val); | |
b34c74ab JB |
416 | } |
417 | ||
302273ca TT |
418 | gdb_mpq (const gdb_mpz &num, const gdb_mpz &denom) |
419 | { | |
81768386 TT |
420 | mpq_init (m_val); |
421 | mpz_set (mpq_numref (m_val), num.m_val); | |
422 | mpz_set (mpq_denref (m_val), denom.m_val); | |
423 | mpq_canonicalize (m_val); | |
302273ca TT |
424 | } |
425 | ||
7607de94 TT |
426 | gdb_mpq (long num, long denom) |
427 | { | |
81768386 TT |
428 | mpq_init (m_val); |
429 | mpq_set_si (m_val, num, denom); | |
430 | mpq_canonicalize (m_val); | |
7607de94 TT |
431 | } |
432 | ||
b34c74ab JB |
433 | /* Copy assignment operator. */ |
434 | gdb_mpq &operator= (const gdb_mpq &from) | |
435 | { | |
81768386 | 436 | mpq_set (m_val, from.m_val); |
b34c74ab JB |
437 | return *this; |
438 | } | |
439 | ||
440 | gdb_mpq &operator= (gdb_mpq &&from) | |
441 | { | |
81768386 | 442 | mpq_swap (m_val, from.m_val); |
b34c74ab JB |
443 | return *this; |
444 | } | |
445 | ||
302273ca TT |
446 | gdb_mpq &operator= (const gdb_mpz &from) |
447 | { | |
81768386 | 448 | mpq_set_z (m_val, from.m_val); |
302273ca TT |
449 | return *this; |
450 | } | |
451 | ||
7607de94 TT |
452 | gdb_mpq &operator= (double d) |
453 | { | |
81768386 | 454 | mpq_set_d (m_val, d); |
7607de94 TT |
455 | return *this; |
456 | } | |
457 | ||
458 | /* Return the sign of this value. This returns -1 for a negative | |
459 | value, 0 if the value is 0, and 1 for a positive value. */ | |
460 | int sgn () const | |
81768386 | 461 | { return mpq_sgn (m_val); } |
7607de94 TT |
462 | |
463 | gdb_mpq operator+ (const gdb_mpq &other) const | |
464 | { | |
465 | gdb_mpq result; | |
81768386 | 466 | mpq_add (result.m_val, m_val, other.m_val); |
7607de94 TT |
467 | return result; |
468 | } | |
469 | ||
470 | gdb_mpq operator- (const gdb_mpq &other) const | |
471 | { | |
472 | gdb_mpq result; | |
81768386 | 473 | mpq_sub (result.m_val, m_val, other.m_val); |
7607de94 TT |
474 | return result; |
475 | } | |
476 | ||
477 | gdb_mpq operator* (const gdb_mpq &other) const | |
478 | { | |
479 | gdb_mpq result; | |
81768386 | 480 | mpq_mul (result.m_val, m_val, other.m_val); |
7607de94 TT |
481 | return result; |
482 | } | |
483 | ||
484 | gdb_mpq operator/ (const gdb_mpq &other) const | |
485 | { | |
486 | gdb_mpq result; | |
81768386 | 487 | mpq_div (result.m_val, m_val, other.m_val); |
7607de94 TT |
488 | return result; |
489 | } | |
490 | ||
491 | gdb_mpq &operator*= (const gdb_mpq &other) | |
492 | { | |
81768386 | 493 | mpq_mul (m_val, m_val, other.m_val); |
7607de94 TT |
494 | return *this; |
495 | } | |
496 | ||
497 | gdb_mpq &operator/= (const gdb_mpq &other) | |
498 | { | |
81768386 | 499 | mpq_div (m_val, m_val, other.m_val); |
7607de94 TT |
500 | return *this; |
501 | } | |
502 | ||
503 | bool operator== (const gdb_mpq &other) const | |
504 | { | |
81768386 | 505 | return mpq_cmp (m_val, other.m_val) == 0; |
7607de94 TT |
506 | } |
507 | ||
508 | bool operator< (const gdb_mpq &other) const | |
509 | { | |
81768386 | 510 | return mpq_cmp (m_val, other.m_val) < 0; |
7607de94 TT |
511 | } |
512 | ||
b34c74ab | 513 | /* Return a string representing VAL as "<numerator> / <denominator>". */ |
81768386 | 514 | std::string str () const { return gmp_string_printf ("%Qd", m_val); } |
b34c74ab JB |
515 | |
516 | /* Return VAL rounded to the nearest integer. */ | |
517 | gdb_mpz get_rounded () const; | |
518 | ||
302273ca TT |
519 | /* Return this value as an integer, rounded toward zero. */ |
520 | gdb_mpz as_integer () const | |
521 | { | |
522 | gdb_mpz result; | |
81768386 | 523 | mpz_tdiv_q (result.m_val, mpq_numref (m_val), mpq_denref (m_val)); |
302273ca TT |
524 | return result; |
525 | } | |
526 | ||
7607de94 TT |
527 | /* Return this value converted to a host double. */ |
528 | double as_double () const | |
81768386 | 529 | { return mpq_get_d (m_val); } |
7607de94 | 530 | |
c9f0b43f JB |
531 | /* Set VAL from the contents of the given byte array (BUF), which |
532 | contains the unscaled value of a fixed point type object. | |
533 | The byte size of the data is the size of BUF. | |
534 | ||
535 | BYTE_ORDER provides the byte_order to use when reading the data. | |
b34c74ab JB |
536 | |
537 | UNSIGNED_P indicates whether the number has an unsigned type. | |
538 | SCALING_FACTOR is the scaling factor to apply after having | |
539 | read the unscaled value from our buffer. */ | |
c9f0b43f | 540 | void read_fixed_point (gdb::array_view<const gdb_byte> buf, |
b34c74ab JB |
541 | enum bfd_endian byte_order, bool unsigned_p, |
542 | const gdb_mpq &scaling_factor); | |
543 | ||
c9f0b43f JB |
544 | /* Write VAL into BUF as fixed point value following the given BYTE_ORDER. |
545 | The size of BUF is used as the length to write the value into. | |
b34c74ab JB |
546 | |
547 | UNSIGNED_P indicates whether the number has an unsigned type. | |
548 | SCALING_FACTOR is the scaling factor to apply before writing | |
549 | the unscaled value to our buffer. */ | |
c9f0b43f | 550 | void write_fixed_point (gdb::array_view<gdb_byte> buf, |
b34c74ab JB |
551 | enum bfd_endian byte_order, bool unsigned_p, |
552 | const gdb_mpq &scaling_factor) const; | |
553 | ||
554 | /* The destructor. */ | |
81768386 TT |
555 | ~gdb_mpq () { mpq_clear (m_val); } |
556 | ||
557 | private: | |
558 | ||
559 | friend struct gdb_mpf; | |
560 | ||
561 | mpq_t m_val; | |
b34c74ab JB |
562 | }; |
563 | ||
564 | /* A class to make it easier to use GMP's mpf_t values within GDB. | |
565 | ||
566 | Should MPFR become a required dependency, we should probably | |
567 | drop this class in favor of using MPFR. */ | |
568 | ||
569 | struct gdb_mpf | |
570 | { | |
b34c74ab | 571 | /* Constructors. */ |
d0aa28e1 | 572 | gdb_mpf () { mpf_init (m_val); } |
b34c74ab JB |
573 | |
574 | DISABLE_COPY_AND_ASSIGN (gdb_mpf); | |
575 | ||
576 | /* Set VAL from the contents of the given buffer (BUF), which | |
577 | contains the unscaled value of a fixed point type object | |
578 | with the given size (LEN) and byte order (BYTE_ORDER). | |
579 | ||
580 | UNSIGNED_P indicates whether the number has an unsigned type. | |
581 | SCALING_FACTOR is the scaling factor to apply after having | |
582 | read the unscaled value from our buffer. */ | |
c9f0b43f | 583 | void read_fixed_point (gdb::array_view<const gdb_byte> buf, |
b34c74ab JB |
584 | enum bfd_endian byte_order, bool unsigned_p, |
585 | const gdb_mpq &scaling_factor) | |
586 | { | |
587 | gdb_mpq tmp_q; | |
588 | ||
c9f0b43f | 589 | tmp_q.read_fixed_point (buf, byte_order, unsigned_p, scaling_factor); |
d0aa28e1 | 590 | mpf_set_q (m_val, tmp_q.m_val); |
b34c74ab JB |
591 | } |
592 | ||
d0aa28e1 TT |
593 | /* Convert this value to a string. FMT is the format to use, and |
594 | should have a single '%' substitution. */ | |
595 | std::string str (const char *fmt) const | |
596 | { return gmp_string_printf (fmt, m_val); } | |
597 | ||
b34c74ab | 598 | /* The destructor. */ |
d0aa28e1 TT |
599 | ~gdb_mpf () { mpf_clear (m_val); } |
600 | ||
601 | private: | |
602 | ||
603 | mpf_t m_val; | |
b34c74ab JB |
604 | }; |
605 | ||
606 | /* See declaration above. */ | |
607 | ||
608 | template<typename T> | |
609 | void | |
610 | gdb_mpz::set (T src) | |
611 | { | |
7aeae94f | 612 | mpz_import (m_val, 1 /* count */, -1 /* order */, |
b34c74ab JB |
613 | sizeof (T) /* size */, 0 /* endian (0 = native) */, |
614 | 0 /* nails */, &src /* op */); | |
615 | if (std::is_signed<T>::value && src < 0) | |
616 | { | |
617 | /* mpz_import does not handle the sign, so our value was imported | |
618 | as an unsigned. Adjust that imported value so as to make it | |
619 | the correct negative value. */ | |
620 | gdb_mpz neg_offset; | |
621 | ||
7aeae94f TT |
622 | mpz_ui_pow_ui (neg_offset.m_val, 2, sizeof (T) * HOST_CHAR_BIT); |
623 | mpz_sub (m_val, m_val, neg_offset.m_val); | |
b34c74ab JB |
624 | } |
625 | } | |
626 | ||
627 | /* See declaration above. */ | |
628 | ||
629 | template<typename T> | |
630 | T | |
631 | gdb_mpz::as_integer () const | |
632 | { | |
63c457b9 | 633 | T result; |
b34c74ab | 634 | |
1c805ba0 | 635 | this->export_bits ({(gdb_byte *) &result, sizeof (result)}, |
63c457b9 | 636 | 0 /* endian (0 = native) */, |
1c805ba0 TT |
637 | !std::is_signed<T>::value /* unsigned_p */, |
638 | true /* safe */); | |
b34c74ab | 639 | |
b34c74ab JB |
640 | return result; |
641 | } | |
642 | ||
767c4b92 TT |
643 | /* See declaration above. */ |
644 | ||
645 | template<typename T> | |
646 | T | |
647 | gdb_mpz::as_integer_truncate () const | |
648 | { | |
649 | T result; | |
650 | ||
651 | this->export_bits ({(gdb_byte *) &result, sizeof (result)}, | |
652 | 0 /* endian (0 = native) */, | |
653 | !std::is_signed<T>::value /* unsigned_p */, | |
654 | false /* safe */); | |
655 | ||
656 | return result; | |
657 | } | |
658 | ||
b34c74ab | 659 | #endif |