{{ message }}
Repository navigation
Expand file tree
/
Copy pathfixed_pt.c
More file actions
1473 lines (1338 loc) · 55.6 KB
/
Copy pathfixed_pt.c
File metadata and controls
1473 lines (1338 loc) · 55.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
Part of the EDG Compiler Project, under the Apache License v2.0 with LLVM
Exceptions.
See https://edgcpp.org/LICENSE.txt for license information.
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
/*
fixed_pt.c -- Routines that manipulate internal fixed-point quantities.
The versions in this file are for prototyping only, and should be replaced
for a production version.
*/
/* Header files common to all files. */
#include "fe_common.h"
#ifdef PCH_PRAGMA_GUARD
/* Mark the end of the sequence of headers subject to precompiled header
processing. */
#pragma hdrstop
#endif /* ifdef PCH_PRAGMA_GUARD */
#if FIXED_POINT_ALLOWED
#include "folding.h"
/* Conditionally open the "edg" namespace. */
BEGIN_EDG_NAMESPACE
a_boolean fxp_value_is_zero(a_fixed_point_value *value)
/*
Return TRUE if and only if the given fixed-point value is zero.
*/
{
an_integer_value zero;
set_integer_value(&zero, (a_host_large_integer)0);
/* Use the integer comparison routine. Note that signedness doesn't
matter for the zero case. */
return (cmp_integer_values(value, /*op_1_signed=*/FALSE,
&zero, /*op_2_signed=*/FALSE) == 0);
} /* fxp_value_is_zero */
#if !STANDALONE_UTILITY_PROGRAM
void fxp_init_value(a_fixed_point_value *value)
/*
Initialize the given fixed-point value to zero.
*/
{
set_integer_value(value, (a_host_large_integer)0);
} /* fxp_init_value */
static a_targ_size_t value_bits_for_fixed_point(
a_fixed_point_type_descr *fxp_descr)
/*
Return the number of data bits in a fixed-point value (i.e., the number of
bits excluding the sign bit).
*/
{
a_targ_size_t bits =
targ_sizeof_fixed_point[fxp_descr->is_unsigned]
[(int)fxp_descr->precision]
[fxp_descr->is_fract_type] * CHAR_BIT;
if (!fxp_descr->is_unsigned) {
check_assertion(bits > 0);
bits--;
} /* if */
return bits;
} /* value_bits_for_fixed_point */
static a_targ_size_t sizeof_fixed_point(a_fixed_point_type_descr *fxp_descr)
/*
Return the number of bytes in a fixed-point value.
*/
{
return targ_sizeof_fixed_point[fxp_descr->is_unsigned]
[(int)fxp_descr->precision]
[fxp_descr->is_fract_type];
} /* sizeof_fixed_point */
a_targ_size_t non_fractional_bits_for_fixed_point(
a_fixed_point_type_descr *fxp_descr)
/*
Return the number of bits in the non-fractional part of a fixed-point value.
The sign bit (if any) is included in the non-fractional bits.
*/
{
a_targ_alignment fract_bits;
a_targ_size_t total_bits;
fract_bits = targ_fractional_bits_for_fixed_point[fxp_descr->is_unsigned]
[(int)fxp_descr->precision]
[fxp_descr->is_fract_type];
total_bits = targ_sizeof_fixed_point[fxp_descr->is_unsigned]
[(int)fxp_descr->precision]
[fxp_descr->is_fract_type] *
CHAR_BIT;
return total_bits - fract_bits;
} /* non_fractional_bits_for_fixed_point */
a_fixed_point_type_descr *fxp_descr_for_constant(a_constant_ptr cp)
/*
Return the fixed-point descriptor pointer for the specified constant.
*/
{
a_type_ptr type = skip_typerefs(cp->type);
check_assertion(type->kind == (a_type_kind)tk_fixed_point);
return &type->variant.fixed_point;
} /* fxp_descr_for_constant */
static void set_fixed_point_to_saturated_value(
a_fixed_point_value *value,
a_targ_size_t value_bits,
a_boolean is_negative,
a_fixed_point_type_descr *fxp_descr)
/*
Set value to the representation used for a saturated fixed-point
value. is_negative is TRUE if the value should be the saturated negative
value. The positive value is all 1 bits, except for the sign bit. The
negative value has just the sign bit set. value_bits is the number of bits
used to represent an fxp_descr value. Note that it does not include the
sign bit.
*/
{
int shift_count;
/* Set all of the bits. */
set_integer_value(value, (a_host_large_integer)-1);
if (!fxp_descr->is_unsigned) {
/* Clear the sign bit. */
shift_right_integer_value(value, 1,
/*is_signed=*/FALSE, /*sign_extend=*/FALSE);
/* For a negative value, only the sign bit should be set. */
if (is_negative) complement_integer_value(value);
/* Update value_bits to reflect the bit used for the sign. */
value_bits++;
} /* if */
/* Shift the saturated value to just fill the portion of the integer
value actually used to the representation. */
shift_count = (int)BITS_IN_AN_INTEGER_VALUE - (int)value_bits;
if (shift_count > 0) {
shift_right_integer_value(value, shift_count,
/*is_signed=*/!fxp_descr->is_unsigned,
/*sign_extend=*/TRUE);
} /* if */
} /* set_fixed_point_to_saturated_value */
static void negate_fixed_point_value(a_fixed_point_value *op_1,
a_boolean *err)
/*
Negate a fixed-point value. The result is returned in the first operand
(op_1 = -op_1). err is TRUE if an overflow occurred.
This routine requires that a_fixed_point_value be an_integer_value. Note
that this routine only checks for error cases that cannot be represented
by an_integer_value. Range checking for specific fixed-point types must
be done by the caller. fxp_negate is a more general version of this
routine.
*/
{
negate_integer_value(op_1, err);
} /* negate_fixed_point_value */
/*
Return TRUE if the fixed-point value is negative. The caller is responsible
for checking that the fixed-point type is signed.
This macro requires that a_fixed_point_value be an_integer_value.
*/
#define fxp_sign_of(value) (sign_of(value))
#if INTEGER_VALUE_REPR_IS_A_HOST_INTEGER
/*
Return the byte offset of a given logical byte of an integer value. This is
a no-op when an integer value is a host integer.
This is only used on little-endian systems.
*/
#define byte_offset_in_integer_value(i) (i)
#else /* INTEGER_VALUE_REPR_IS_A_HOST_INTEGER */
static int byte_offset_in_integer_value(unsigned int byte)
/*
Return the byte offset of a given logical byte of an integer value.
This is only used on little-endian systems.
*/
{
long unsigned int_value_part = INT_VALUE_PARTS_PER_INTEGER_VALUE -
(byte / SIZEOF_INT_VALUE_PART) - 1;
long unsigned offset = (int_value_part * SIZEOF_INT_VALUE_PART) +
(byte % SIZEOF_INT_VALUE_PART);
return (int)offset;
} /* byte_offset_in_integer_value */
#endif /* INTEGER_VALUE_REPR_IS_A_HOST_INTEGER */
static void store_hex_fxp_value(
a_mantissa_ptr mp,
a_fixed_point_type_descr *fxp_descr,
a_fixed_point_value *value)
/*
Store the value represented by mp in the fixed-point value "value".
fxp_descr describes the format of the value being stored.
*/
{
a_targ_size_t parts_to_copy;
a_targ_size_t source_size;
a_targ_size_t part_offset;
/* Zero the memory so that all of the space occupied by "value"
is cleared, even if we are not storing all of the bytes of the value. */
memzero((char *)value, sizeof(a_fixed_point_value));
source_size = sizeof_fixed_point(fxp_descr);
parts_to_copy = (source_size + sizeof(an_fp_value_part) - 1) /
sizeof(an_fp_value_part);
/* In most cases, an entire fp_value_part is copied. If the target is just
a 1 or 2 byte value, however, only the high-order bytes of the source
fp_value_part are copied. */
part_offset = source_size < sizeof(an_fp_value_part)
? source_size : sizeof(an_fp_value_part);
part_offset = sizeof(an_fp_value_part) - part_offset;
/* The source value is in the upper source_size bytes of the mantissa.
This needs to be copied to the low order bytes of the fixed-point
value. */
if (host_little_endian) {
/* For a typical system where an_fp_value_part is 4 bytes and an
integer value is 8 bytes, a short value is copied:
from 2 to 0
from 3 to 1
A 64 bit value is copied:
from 4 to 0
from 5 to 1
from 6 to 2
from 7 to 3
from 0 to 4
from 1 to 5
from 2 to 6
from 3 to 7
*/
unsigned int i;
for (i = 0; i < source_size; ++i) {
char *source;
char *dest;
int source_part;
int source_byte;
dest = &((char*)value)[byte_offset_in_integer_value(i)];
source_part = (int)((parts_to_copy - 1) - (i/sizeof(an_fp_value_part)));
source_byte = (int)((i % sizeof(an_fp_value_part)) + part_offset);
source = (char*)&(mp->parts[source_part]) + source_byte;
*dest = *source;
#if DEBUG
if (db_flag_is_set("fxp_store")) {
long source_offset, dest_offset;
source_offset = (long)(source - (char *)(&mp->parts[0]));
dest_offset = (long)(dest - (char*)&value[0]);
fprintf(f_debug, "fxp copy from %ld to %ld, value=%x\n",
source_offset, dest_offset,
(unsigned int)(unsigned char)*dest);
} /* if */
#endif /* DEBUG */
} /* for */
} else {
/* Copy the value from the mantissa to the low order bytes of the
fixed-point value. */
memcpy((char*)value + sizeof(a_fixed_point_value) - source_size,
(char*)&mp->parts[0], size_t_arg(source_size));
} /* if */
} /* store_hex_fxp_value */
static void load_hex_fxp_value(a_fixed_point_value *value,
a_fixed_point_type_descr *fxp_descr,
a_mantissa_ptr mp,
long *exponent,
a_boolean *is_negative)
/*
Create mantissa (mp), exponent, and is_negative from a_fixed_point_value
(value). fxp_descr describes the format of the fixed-point value.
*/
{
a_targ_size_t parts_to_copy;
a_targ_size_t dest_size;
a_targ_size_t part_offset;
a_fixed_point_value local_value;
init_mantissa(mp);
*is_negative = !fxp_descr->is_unsigned && fxp_sign_of(*value);
if (*is_negative) {
a_boolean local_err;
local_value = *value;
negate_fixed_point_value(&local_value, &local_err);
/* An error should only occur on negating the smallest integer. In
that case, just use the original value. */
if (!local_err) value = &local_value;
} /* if */
dest_size = sizeof_fixed_point(fxp_descr);
parts_to_copy = (dest_size + sizeof(an_fp_value_part) - 1) /
sizeof(an_fp_value_part);
/* In most cases, an entire fp_value_part is copied. If the target is just
a 1 or 2 byte value, however, only the high-order bytes of the dest
fp_value_part are copied. */
part_offset = dest_size < sizeof(an_fp_value_part)
? dest_size : sizeof(an_fp_value_part);
part_offset = sizeof(an_fp_value_part) - part_offset;
/* The destination value is in the upper dest_size bytes of the mantissa.
This needs to be copied from the low order bytes of the fixed-point
value. See the comments in store_hex_fxp_value for more information. */
if (host_little_endian) {
unsigned int i;
for (i = 0; i < dest_size; ++i) {
char *dest;
char *source;
int dest_part;
int dest_byte;
source = &((char*)value)[byte_offset_in_integer_value(i)];
dest_part = (int)((parts_to_copy - 1) - (i / sizeof(an_fp_value_part)));
dest_byte = (int)((i % sizeof(an_fp_value_part)) + part_offset);
dest = (char*)&(mp->parts[dest_part]) + dest_byte;
*dest = *source;
} /* for */
} else {
/* Copy the value from the low order bytes for the fixed-point value
to the mantissa. */
memcpy((char*)&mp->parts[0],
(char*)value + sizeof(a_fixed_point_value) - dest_size,
size_t_arg(dest_size));
} /* if */
/* The exponent is the number of non-fractional bits of the value. */
*exponent = (long)non_fractional_bits_for_fixed_point(fxp_descr);
} /* load_hex_fxp_value */
static void normalize_mantissa(a_mantissa_ptr mp,
long *exponent)
/*
Normalize the mantissa value so that it occupies the high-order bits
of "mp". Adjust the exponent accordingly.
*/
{
if (!mantissa_is_zero(mp)) {
/* Adjust the mantissa so that it is normalized in the high-order bits
of the mantissa. */
while ((mp->parts[0] & 0x80000000) == 0) {
shift_left_mantissa(mp, 1);
(*exponent)--;
} /* while */
} else {
/* Clear the exponent if the mantissa is zero. */
*exponent = 0;
} /* if */
} /* normalize_mantissa */
static void make_mantissa_from_integer_value(an_integer_value *value,
a_boolean is_negative,
a_mantissa_ptr mp,
long *exponent)
/*
Create a mantissa (mp) and exponent from an_integer_value (value). If
value is negative, is_negative will be TRUE.
*/
{
a_targ_size_t parts_to_copy;
an_integer_value local_value;
#if CHECKING
{ /* Make sure an_integer_value can be copied into a_mantissa. */
a_boolean okay = sizeof(an_integer_value) <= sizeof(mp->parts);
check_assertion(okay);
}
#endif /* CHECKING */
/* Clear the mantissa. */
init_mantissa(mp);
*exponent = 0;
if (is_negative) {
/* If the source value is negative, get the positive version for the
conversion. */
a_boolean err;
local_value = *value;
negate_integer_value(&local_value, &err);
/* An error should only occur on negating the smallest integer. In
that case, just use the original value. */
if (!err) value = &local_value;
} /* if */
parts_to_copy = (sizeof(an_integer_value) + sizeof(an_fp_value_part) - 1) /
sizeof(an_fp_value_part);
/* The source value is in the low order bytes of the integer value.
This needs to be copied to the high order bytes of the mantissa. */
if (host_little_endian) {
unsigned int i;
for (i = 0; i < sizeof(an_integer_value); ++i) {
char *source;
char *dest;
source = &((char*)value)[byte_offset_in_integer_value(i)];
dest = (char*)&(mp->parts[(parts_to_copy - 1) -
(i / sizeof(an_fp_value_part))]) +
(i % sizeof(an_fp_value_part));
*dest = *source;
} /* for */
} else {
/* Copy the value from the high-order bytes of the mantissa. */
memcpy((char*)&mp->parts[0], (char*)value, sizeof(an_integer_value));
} /* if */
*exponent = BITS_IN_AN_INTEGER_VALUE;
/* Adjust the mantissa so that it is normalized in the high-order bits
of the mantissa. */
normalize_mantissa(mp, exponent);
} /* make_mantissa_from_integer_value */
static void make_integer_value_from_mantissa(an_integer_value *value,
a_boolean is_negative,
a_mantissa_ptr mp,
long exponent,
a_boolean *err)
/*
Create an_integer_value from a mantissa (mp) and exponent. If the value is
negative, is_negative will be TRUE.
*/
{
int parts_to_copy;
int shift_count;
*err = FALSE;
/* Compute the number of bits to shift the mantissa so that any fractional
bits will be discarded. */
shift_count = (int)((long)BITS_IN_AN_INTEGER_VALUE - exponent);
if (shift_count >= 0) {
if (shift_count > 0) shift_right_mantissa(mp, shift_count);
} else {
/* The value will not fit in an integer value. */
*err = TRUE;
goto done;
} /* if */
parts_to_copy = (sizeof(an_integer_value) + sizeof(an_fp_value_part) - 1) /
sizeof(an_fp_value_part);
/* The destination value is in the low order bytes of the integer value.
This needs to be copied from the high order bytes of the mantissa. */
if (host_little_endian) {
unsigned int i;
for (i = 0; i < sizeof(an_integer_value); ++i) {
char *dest;
char *source;
dest = &((char*)value)[byte_offset_in_integer_value(i)];
source = (char*)&(mp->parts[(size_t)(parts_to_copy - 1) -
(i / sizeof(an_fp_value_part))]) +
(i % sizeof(an_fp_value_part));
*dest = *source;
} /* for */
} else {
/* Copy the value to the high order bits of the mantissa. */
memcpy((char*)value, (char*)&mp->parts[0], sizeof(an_integer_value));
} /* if */
if (is_negative) {
/* If the value should be negative, negate the resulting value. */
a_boolean local_err;
an_integer_value saved_value;
saved_value = *value;
negate_integer_value(value, &local_err);
/* An error should only occur on negating the smallest integer. In
that case, just use the original value. */
if (local_err) *value = saved_value;
} /* if */
done:
return;
} /* make_integer_value_from_mantissa */
static void clear_unused_mantissa_bits(a_mantissa_ptr mp,
a_targ_size_t bits_used)
/*
Zero any bits in the mantissa that are beyond the first N bits specified by
bits_used.
*/
{
for (size_t part = 0; part < MANTISSA_PARTS; part++) {
if (bits_used >= 32) {
/* The whole part is used. Skip to the next part. */
bits_used -= 32;
continue;
} else if (bits_used == 0) {
/* None of this part is used. Clear it. */
mp->parts[part] = 0;
} else {
/* A portion of the part is used. Clear the unused part. */
unsigned bits_to_clear = (unsigned)(32 - bits_used);
an_fp_value_part mask;
mask = 0xffffffff << bits_to_clear;
mp->parts[part] &= mask;
bits_used = 0;
} /* if */
} /* for */
} /* clear_unused_mantissa_bits */
static void conv_mantissa_to_fixed_point(a_mantissa_ptr mp,
long exponent,
a_boolean is_negative,
a_fixed_point_type_descr *fxp_descr,
a_boolean overflow,
a_fixed_point_value *value,
a_boolean *err,
a_boolean *inexact)
/*
Given a mantissa (mp) and exponent that represent a fixed-point value, check
that the value is representable in the destination type specified by
fxp_descr and shift the value as needed so that it contains the correct
number of value bits for the destination type. is_negative is TRUE if the
value to be stored must be created as a negative value. overflow is TRUE if
the value is already known to be too large. Set *err on overflow. Set
*inexact if any bits are lost because of scaling or rounding.
*/
{
long nonfract_bits = 0;
long shift_count = 0;
a_targ_size_t value_bits = 0;
unsigned mantissa_bits = 0;
unsigned sign_bits = 0;
*err = FALSE;
*inexact = FALSE;
if (!overflow) {
if (is_negative && fxp_descr->is_unsigned) {
/* A negative value being stored in an unsigned value. Set it to
zero. */
init_mantissa(mp);
exponent = 0;
} /* if */
/* Adjust the mantissa so that it is normalized in the high-order bits
of the mantissa. */
normalize_mantissa(mp, &exponent);
/* Compute the number of bits to shift the mantissa so that it contains
the right number of fractional and non-fractional bits. */
nonfract_bits = (long)non_fractional_bits_for_fixed_point(fxp_descr);
value_bits = value_bits_for_fixed_point(fxp_descr);
shift_count = nonfract_bits - exponent;
mantissa_bits = number_of_bits_in_mantissa(mp, /*normalize=*/FALSE);
sign_bits = fxp_descr->is_unsigned ? 0 : 1;
if (shift_count > 0) shift_right_mantissa(mp, (int)shift_count);
/* See if the result value has more bits of precision than fit into
the destination type. */
if (mantissa_bits > value_bits) *inexact = TRUE;
/* Round the value to the nearest representable value. */
round_hex_fp_value(mp, &exponent, value_bits + sign_bits,
/*is_fixed_point=*/TRUE, !fxp_descr->is_unsigned,
inexact);
/* Zero any bits in the mantissa that are not actually used in the
value. */
clear_unused_mantissa_bits(mp, value_bits + sign_bits);
/* Recompute the shift count and mantissa bits after rounding. */
shift_count = nonfract_bits - exponent;
mantissa_bits = number_of_bits_in_mantissa(mp, /*normalize=*/TRUE);
/* A shift count of zero represents an overflow for a signed value because
the sign bit would be needed for the representation. */
if (shift_count < (long)sign_bits) {
/* We would be shifting bits out of the high end of this mantissa. */
overflow = TRUE;
} /* if */
} /* if */
#if DEBUG
if (db_flag_is_set("fxp_conv")) {
fprintf(f_debug, "fxp hex value: ");
db_mantissa(mp);
fprintf(f_debug, "exponent=%ld, nonfract=%ld, shift=%ld\n",
exponent, nonfract_bits, shift_count);
} /* if */
#endif /* DEBUG */
if (overflow) {
/* On overflow, return an error flag and set the result value to a
saturated value. */
if (fxp_descr->is_fract_type && mantissa_bits == 1 && exponent == 1) {
/* The input value is 1 or -1. Return the saturated value, but don't
set the error flag. */
} else if (!fxp_descr->is_fract_type &&
mantissa_bits == 1 && exponent == nonfract_bits) {
/* The input is the smallest value of an _Accum type, or the positive
version of the same value. Also return the saturated value without
setting the error flag. */
} else if (fxp_descr->saturating) {
/* If this is a saturating type, silently saturate. */
} else {
/* Except for the case above, set the error flag on overflow. */
*err = TRUE;
} /* if */
set_fixed_point_to_saturated_value(value, value_bits,
is_negative, fxp_descr);
} else {
/* No overflow. Store the result in the appropriate form. */
store_hex_fxp_value(mp, fxp_descr, value);
/* Negate the value, if necessary. If the source is negative and the
destination is unsigned, a diagnostic will be issued by the caller
and the value set to zero above. On overflow, the saturated value
will have already been created with the appropriate sign above. */
if (is_negative && !fxp_descr->is_unsigned) {
a_boolean negate_err;
negate_fixed_point_value(value, &negate_err);
if (negate_err) *err = TRUE;
} /* if */
} /* if */
/* If an underflow occurred, set the flag that indicates that the resulting
value is not an exact representation of the specified value. */
if (mp->underflow) *inexact = TRUE;
} /* conv_mantissa_to_fixed_point */
void conv_integer_to_fixed_point(a_constant_ptr old_constant,
a_constant_ptr new_constant,
an_error_code *err_code,
an_error_severity *err_severity)
/*
Convert the integer constant "old_constant" to a fixed-point constant
in "new_constant. If, as a result of the conversion, a diagnostic should
be issued, set err_code and err_severity to the values for the message
to be issued; otherwise set err_code to ec_no_error.
*/
{
a_mantissa mantissa;
long exponent;
a_boolean is_negative;
a_boolean err;
a_boolean inexact;
an_integer_kind ikind;
a_boolean is_signed;
size_t bit_size;
a_fixed_point_type_descr
*fxp_descr;
check_assertion(old_constant->kind == (a_constant_repr_kind)ck_integer);
set_constant_kind(new_constant, (a_constant_repr_kind)ck_fixed_point);
*err_code = ec_no_error;
/* Determine attributes (size, signedness) of the integer kind. */
get_integer_attributes(old_constant, &ikind, &is_signed, &bit_size);
/* Determine if the value is negative. */
is_negative = is_signed && sign_of_integer_constant(old_constant) < 0;
/* Convert the integer into the internal mantissa representation. */
make_mantissa_from_integer_value(&old_constant->variant.integer_value,
is_negative, &mantissa, &exponent);
fxp_descr = fxp_descr_for_constant(new_constant);
/* Convert and store the mantissa as a fixed-point value. */
conv_mantissa_to_fixed_point(&mantissa, exponent, is_negative,
fxp_descr,
/*overflow=*/FALSE,
&new_constant->variant.fixed_point_value,
&err, &inexact);
if (err) {
/* The conversion to fixed-point does not fit in the result type. */
*err_code = ec_integer_to_fixed_conversion;
*err_severity = es_error;
} else if (is_negative && fxp_descr->is_unsigned) {
/* The conversion results in a negative value being converted to
unsigned. */
*err_code = ec_fixed_sign_change;
*err_severity = es_error;
} else if (inexact) {
/* The conversion loses precision. This doesn't seem like it should be
possible for an integer to fixed conversion, but is provided for
in case there is some fixed format where this would be possible. */
*err_code = ec_inexact_fixed_conversion;
*err_severity = es_warning;
} /* if */
} /* conv_integer_to_fixed_point */
void conv_fixed_point_to_integer(a_constant_ptr old_constant,
a_constant_ptr new_constant,
an_error_code *err_code,
an_error_severity *err_severity)
/*
Convert the fixed-point constant "old_constant" to an integer constant
in "new_constant. If, as a result of the conversion, a diagnostic should
be issued, set err_code and err_severity to the values for the message
to be issued; otherwise set err_code to ec_no_error.
*/
{
a_mantissa mantissa;
long exponent;
a_boolean is_negative;
a_boolean err;
a_fixed_point_type_descr
*fxp_descr;
an_integer_value int_value;
an_integer_kind ikind;
a_boolean is_signed;
size_t bit_size;
check_assertion(old_constant->kind == (a_constant_repr_kind)ck_fixed_point);
set_constant_kind(new_constant, (a_constant_repr_kind)ck_integer);
*err_code = ec_no_error;
fxp_descr = fxp_descr_for_constant(old_constant);
/* Convert the fixed-point value into the internal mantissa
representation. */
load_hex_fxp_value(&old_constant->variant.fixed_point_value,
fxp_descr, &mantissa, &exponent, &is_negative);
/* Convert and store the mantissa as an integer value. */
make_integer_value_from_mantissa(&int_value, is_negative,
&mantissa, exponent, &err);
/* Determine attributes (size, signedness) of the integer kind. */
get_integer_attributes(new_constant, &ikind, &is_signed, &bit_size);
/* If the value is negative and the destination is unsigned, issue as
diagnostic. */
if (is_negative && !is_signed) err = TRUE;
if (err) {
/* The conversion to integer does not fit in the result type. This case
occurs only if the fixed-point type does not fit in even the largest
integer type, which is unlikely. */
*err_code = ec_fixed_to_integer_conversion;
*err_severity = es_error;
} else {
/* Truncate the value to the size of the destination integer type. */
trunc_and_set_integer(&int_value, new_constant, /*check_overflow=*/TRUE,
/*saturate_on_overflow=*/FALSE,
err_code, err_severity);
if (*err_code != ec_no_error) {
/* If an error occurred while storing the value, remap the error code
into a more appropriate one for this particular case. */
*err_code = ec_fixed_to_integer_conversion;
*err_severity = es_error;
} /* if */
} /* if */
} /* conv_fixed_point_to_integer */
void conv_float_to_fixed_point(a_constant_ptr old_constant,
a_constant_ptr new_constant,
an_error_code *err_code,
an_error_severity *err_severity)
/*
Convert the floating-point constant "old_constant" to a fixed-point constant
in "new_constant. If, as a result of the conversion, a diagnostic should
be issued, set err_code and err_severity to the values for the message
to be issued; otherwise set err_code to ec_no_error.
*/
{
a_mantissa mantissa;
long exponent;
a_boolean is_negative;
a_boolean err;
a_boolean inexact;
a_fixed_point_type_descr
*fxp_descr;
a_boolean overflow = FALSE;
a_type_ptr float_tp = skip_typerefs(old_constant->type);
a_float_kind float_kind = float_tp->variant.float_kind;
an_internal_float_value
*float_value;
#if C99_IL_EXTENSIONS_SUPPORTED
an_internal_float_value zero;
if (float_tp->kind == (a_type_kind)tk_complex) {
/* Converting from complex to fixed-point. The real part of the
constant is converted to fixed-point, and the imaginary part is
discarded. */
float_value = &old_constant->variant.complex_value->real;
} else if (float_tp->kind == (a_type_kind)tk_imaginary) {
/* Converting from imaginary to fixed-point. The result is zero. */
fp_host_large_integer_to_float(float_kind, (a_host_large_integer)0,
&zero, &err);
float_value = &zero;
} else
#endif /* C99_IL_EXTENSIONS_SUPPORTED */
/* Do not insert code here. */
{
check_assertion(old_constant->kind == (a_constant_repr_kind)ck_float);
float_value = &old_constant->variant.float_value;
} /* if */
set_constant_kind(new_constant, (a_constant_repr_kind)ck_fixed_point);
*err_code = ec_no_error;
fxp_descr = fxp_descr_for_constant(new_constant);
/* Convert the floating-point value into the internal mantissa
representation. This is done even in the NaN and infinity case
to set is_negative flag, etc. */
load_hex_fp_value(float_value, float_kind,
&mantissa, &exponent, &is_negative,
/*restore_implicit_bit=*/TRUE);
#if TARG_HAS_IEEE_FLOATING_POINT
if (fp_is_nan_or_infinity(float_value, float_kind)) {
/* Not-a-number or infinity. Treat this as an overflow. */
overflow = TRUE;
} /* if */
#endif /* TARG_HAS_IEEE_FLOATING_POINT */
/* The fixed-point representation has no negative zero, so clear the
is_negative flag if the mantissa is zero. */
if (is_negative && mantissa_is_zero(&mantissa)) is_negative = FALSE;
/* Convert and store the mantissa as a fixed-point value. */
conv_mantissa_to_fixed_point(&mantissa, exponent, is_negative,
fxp_descr, overflow,
&new_constant->variant.fixed_point_value,
&err, &inexact);
if (err) {
/* The conversion to fixed-point does not fit in the result type. */
*err_code = ec_float_to_fixed_conversion;
*err_severity = es_error;
} else if (is_negative && fxp_descr->is_unsigned) {
/* The conversion results in a negative value being converted to
unsigned. */
*err_code = ec_fixed_sign_change;
*err_severity = es_error;
} else if (inexact) {
/* The conversion loses precision. */
*err_code = ec_inexact_fixed_conversion;
*err_severity = es_warning;
} /* if */
} /* conv_float_to_fixed_point */
void conv_fixed_point_to_float(a_constant_ptr old_constant,
a_constant_ptr new_constant,
an_error_code *err_code,
an_error_severity *err_severity)
/*
Convert the fixed-point constant "old_constant" to a floating-point constant
in "new_constant. If, as a result of the conversion, a diagnostic should
be issued, set err_code and err_severity to the values for the message
to be issued; otherwise set err_code to ec_no_error.
*/
{
a_mantissa mantissa;
long exponent;
a_boolean is_negative;
a_boolean err;
a_boolean inexact;
a_fixed_point_type_descr
*fxp_descr;
a_type_ptr float_tp = skip_typerefs(new_constant->type);
#if C99_IL_EXTENSIONS_SUPPORTED
a_float_kind float_kind = float_tp->variant.float_kind;
#endif /* C99_IL_EXTENSIONS_SUPPORTED */
an_internal_float_value
*float_value = NULL;
a_boolean skip_conversion = FALSE;
a_constant_repr_kind constant_kind = (a_constant_repr_kind)ck_float;
check_assertion(old_constant->kind == (a_constant_repr_kind)ck_fixed_point);
#if C99_IL_EXTENSIONS_SUPPORTED
/* We may be converting to a nonreal floating type. */
if (float_tp->kind == (a_type_kind)tk_complex) {
constant_kind = (a_constant_repr_kind)ck_complex;
} else if (float_tp->kind == (a_type_kind)tk_imaginary) {
constant_kind = (a_constant_repr_kind)ck_imaginary;
} /* if */
#endif /* C99_IL_EXTENSIONS_SUPPORTED */
set_constant_kind(new_constant, constant_kind);
*err_code = ec_no_error;
fxp_descr = fxp_descr_for_constant(old_constant);
#if C99_IL_EXTENSIONS_SUPPORTED
if (float_tp->kind == (a_type_kind)tk_complex) {
/* Converting to complex. The value is converted into the real
part, and the imaginary part is set to zero. */
float_value = &new_constant->variant.complex_value->real;
fp_host_large_integer_to_float(float_kind, (a_host_large_integer)0,
&new_constant->variant.complex_value->imag,
&err);
check_assertion(!err);
} else if (float_tp->kind == (a_type_kind)tk_imaginary) {
/* Converting to imaginary. The result is zero. */
fp_host_large_integer_to_float(float_kind, (a_host_large_integer)0,
&new_constant->variant.float_value, &err);
check_assertion(!err);
skip_conversion = TRUE;
} else
#endif /* C99_IL_EXTENSIONS_SUPPORTED */
/* Do not insert code here. */
{
float_value = &new_constant->variant.float_value;
} /* if */
if (!skip_conversion) {
/* Convert the fixed-point value into the internal mantissa
representation. */
load_hex_fxp_value(&old_constant->variant.fixed_point_value,
fxp_descr, &mantissa, &exponent, &is_negative);
/* Convert and store the mantissa as a floating-point value. */
conv_mantissa_to_floating_point(&mantissa, &exponent, is_negative,
float_tp->variant.float_kind,
float_value,
/*overflow=*/FALSE, &err, &inexact);
/* No diagnostic is given for an inexact result. */
if (err) {
/* The conversion to floating-point does not fit in the result type.
This should not occur unless there are fixed-point or floating-point
types with unusual sizes. */
*err_code = ec_fixed_to_float_conversion;
*err_severity = es_error;
} /* if */
} /* if */
} /* conv_fixed_point_to_float */
void conv_fixed_point_to_fixed_point(
a_constant_ptr old_constant,
a_constant_ptr new_constant,
an_error_code *err_code,
an_error_severity *err_severity)
/*
Convert the fixed-point constant "old_constant" to a fixed-point constant
in "new_constant. If, as a result of the conversion, a diagnostic should
be issued, set err_code and err_severity to the values for the message
to be issued; otherwise set err_code to ec_no_error.
*/
{
a_mantissa mantissa;
long exponent;
a_boolean is_negative;
a_boolean err;
a_boolean inexact;
a_fixed_point_type_descr
*old_fxp_descr;
a_fixed_point_type_descr
*new_fxp_descr;
check_assertion(old_constant->kind == (a_constant_repr_kind)ck_fixed_point);
set_constant_kind(new_constant, (a_constant_repr_kind)ck_fixed_point);
*err_code = ec_no_error;
old_fxp_descr = fxp_descr_for_constant(old_constant);
new_fxp_descr = fxp_descr_for_constant(new_constant);
/* Convert the fixed-point value into the internal mantissa
representation. */
load_hex_fxp_value(&old_constant->variant.fixed_point_value,
old_fxp_descr, &mantissa, &exponent, &is_negative);
/* Convert and store the mantissa as a fixed-point value. */
conv_mantissa_to_fixed_point(&mantissa, exponent, is_negative,
new_fxp_descr, /*overflow=*/FALSE,
&new_constant->variant.fixed_point_value,
&err, &inexact);
if (err) {
/* The conversion to fixed-point does not fit in the result type. */
*err_code = ec_fixed_to_fixed_conversion;
*err_severity = es_error;
} else if (is_negative && new_fxp_descr->is_unsigned) {
/* The conversion results in a negative value being converted to
unsigned. */
*err_code = ec_fixed_sign_change;
*err_severity = es_error;
} /* if */
} /* conv_fixed_point_to_fixed_point */
void fxp_hex_string_to_fixed_point(a_fixed_point_type_descr *fxp_descr,
a_const_char *str,
a_fixed_point_value *value,
a_boolean *err,
a_boolean *inexact)
/*
Convert the hexadecimal fixed-point number in the null-terminated string str
to internal form in *value. The number is known to be syntactically correct,
but may not be representable (it may be too large or too small); if there's
an error, return *err = TRUE. The specific fixed-point kind is indicated by
*fxp_descr (an will typically affect the representation in *value).
*inexact is set to TRUE if *value does not exactly represent the value
indicated by the given string. Otherwise, it is set to FALSE.
*/
{
a_boolean overflow = FALSE;
long exponent = 0;
a_mantissa mantissa;
conv_hex_string_to_mantissa_and_exponent(str, &mantissa, &exponent,
&overflow);
conv_mantissa_to_fixed_point(&mantissa, exponent, /*is_negative=*/FALSE,
fxp_descr, overflow, value, err, inexact);
} /* fxp_hex_string_to_fixed_point */
void fxp_string_to_fixed_point(a_fixed_point_type_descr *fxp_descr,
a_const_char *str,
a_fixed_point_value *value,
a_boolean *err)
/*
Convert the decimal fixed-point number in the null-terminated string str to
internal form in *value. The number is known to be syntactically correct,
but may not be representable (it may be too large or too small); if there's
an error, return *err = TRUE. The specific fixed-point kind is indicated by
*fxp_descr (and will typically affect the representation in *value).
The string need not have a decimal point or exponent (it can look like an
integer).
This implementation is for demonstration purposes only: It is known to be
imprecise. Specifically, this implementation scans the string as a floating-
point value. It relies on a_fixed_point_value being identical to
an_integer_value.
*/
You can’t perform that action at this time.
