1 /*
2  *      Small C+ Compiler
3  *      Split into parts 3/3/99 djm
4  *
5  *      This part deals with the evaluation of a constant
6  */
7 
8 #include "ccdefs.h"
9 
10 #include <math.h>
11 #include "utlist.h"
12 
13 static Type *get_member(Type *tag);
14 
15 
16 typedef struct elem_s {
17     struct elem_s *next;
18     Kind           kind;
19     int            written;
20     int            litlab;
21     zdouble        value;
22     unsigned char  fa[MAX_MANTISSA_SIZE+1];      /* The parsed representation */
23     char           str[60];    /* A raw string version */
24 } elem_t;
25 
26 struct fp_decomposed {
27     uint8_t   exponent;
28     uint8_t   sign;
29     uint8_t   mantissa[MAX_MANTISSA_SIZE + 1];
30 };
31 
32 static elem_t    *bigconst_queue = NULL;
33 
34 
35 static int  hex(char c);
36 static int  pstr(LVALUE *lval);
37 static int  tstr(int32_t *val);
38 static int  fnumber(LVALUE *val);
39 static int  number(LVALUE *lval);
40 
41 static void dofloat_ieee(double raw, unsigned char fa[]);
42 static void dofloat_ieee16(double raw, unsigned char fa[]);
43 static void dofloat_z80(double raw, unsigned char fa[]);
44 static void dofloat_mbfs(double raw, unsigned char fa[]);
45 static void dofloat_mbf40(double raw, unsigned char fa[]);
46 static void dofloat_mbf64(double raw, unsigned char fa[]);
47 static void dofloat_am9511(double raw, unsigned char fa[]);
48 static void decompose_float(double raw, struct fp_decomposed *fs);
49 
50 
51 /* Modified slightly to sort have two pools - one for strings and one
52  * for doubles..
53  */
54 
constant(LVALUE * lval)55 int constant(LVALUE* lval)
56 {
57     int32_t val;
58     lval->val_type = KIND_INT;
59     lval->ltype = type_int;
60     lval->is_const = 1; /* assume constant will be found */
61     if (fnumber(lval)) {
62         load_constant(lval);
63         lval->flags = FLAGS_NONE;
64         return (1);
65     } else if (number(lval) || pstr(lval)) {
66         if (lval->val_type == KIND_LONG)
67             vlongconst(lval->const_val);
68         else
69             vconst(lval->const_val);
70         return (1);
71     } else if (tstr(&val)) {
72         lval->const_val = val;
73         lval->is_const = 0; /* string address not constant */
74         lval->ltype = make_pointer(type_char);
75         lval->ptr_type = KIND_CHAR;
76         lval->val_type = KIND_INT;
77         lval->flags = FLAGS_NONE;
78         immedlit(litlab,lval->const_val);
79         nl();
80         return (1);
81     }
82     lval->is_const = 0;
83     return (0);
84 }
85 
fnumber(LVALUE * lval)86 int fnumber(LVALUE *lval)
87 {
88     int i,k; /* flag and mask */
89     char minus; /* is if negative! */
90     char* start; /* copy of pointer to starting point */
91     char* s; /* points into source code */
92     char* end;
93     double dval;
94     start = s = line + lptr; /* save starting point */
95     k = 1;
96     minus = 1;
97     while (k) {
98         k = 0;
99         if (*s == '+') {
100             ++s;
101             k = 1;
102         }
103         if (*s == '-') {
104             ++s;
105             k = 1;
106             minus = (-minus);
107         }
108     }
109 
110     while (*s == ' ') /* Ignore white space after sign */
111         s++;
112 
113     while (numeric(*s))
114         ++s;
115 
116     if (*s != '.' && (*s != 'e' && *s != 'f')) { /* Check that it is floating point */
117         s++;
118         return 0;
119     }
120     s++;
121     if ( *s == '+' || *s == '-')
122         ++s;
123     while (numeric(*s))
124         ++s;
125 
126     lptr = (s--) - line; /* save ending point */
127     dval = strtod(start, &end);
128     if (end == start)
129         return 0;
130 
131 
132     lptr = end - line;
133 
134     lval->val_type = KIND_DOUBLE;
135     lval->ltype = type_double;
136 
137     if ( line[lptr] == 'f' ) {
138         lptr++;
139         if ( line[lptr] == '1' && line[lptr+1] == '6') {
140             lptr+=2;
141             lval->val_type = KIND_FLOAT16;
142             lval->ltype = type_float16;
143         }
144     }
145     for ( i = 0; i < buffer_fps_num; i++ )
146         fprintf(buffer_fps[i], "%.*s", (int)(line+lptr-start), start);
147 
148     lval->const_val = dval;
149 
150     return (1); /* report success */
151 }
152 
153 
number(LVALUE * lval)154 int number(LVALUE *lval)
155 {
156     char c;
157     int minus;
158     int64_t k;
159     int isunsigned = 0;
160 
161     k = minus = 1;
162     while (k) {
163         k = 0;
164         if (cmatch('+'))
165             k = 1;
166         if (cmatch('-')) {
167             minus = (-minus);
168             k = 1;
169         }
170     }
171     if (ch() == '0' && toupper(nch()) == 'X') {
172         gch();
173         gch();
174         if (hex(ch()) == 0)
175             return (0);
176         while (hex(ch())) {
177             c = inbyte();
178             if (c <= '9')
179                 k = (k << 4) + (c - '0');
180             else
181                 k = (k << 4) + ((c & 95) - '7');
182         }
183         lval->const_val = k;
184         goto typecheck;
185     }
186     if (ch() == '0' && toupper(nch()) == 'B') {
187         int c;
188         gch();
189         gch();
190         if (ch() != '0' && ch() != '1')
191             return (0);
192         while (ch() == '0' || ch() == '1') {
193             c = inbyte();
194             k = (k << 1) + (c - '0');
195         }
196         lval->const_val = k;
197         goto typecheck;
198     }
199     if (ch() == '0') {
200         gch();
201         while (numeric(ch())) {
202             c = inbyte();
203             if (c < '8')
204                 k = k * 8 + (c - '0');
205         }
206         lval->const_val = k;
207         goto typecheck;
208     }
209     if (numeric(ch()) == 0)
210         return (0);
211     while (numeric(ch())) {
212         c = inbyte();
213         k = k * 10 + (c - '0');
214     }
215     if (minus < 0)
216         k = (-k);
217     lval->const_val = k;
218 typecheck:
219     lval->val_type = KIND_CHAR;
220     if ( lval->const_val >= 256 || lval->const_val < -127 ) {
221         lval->val_type = KIND_INT;
222     }
223     if ( lval->const_val >= 65536 || lval->const_val < -32767 ) {
224         lval->val_type = KIND_LONG;
225     }
226     if ( lval->const_val >= UINT32_MAX || lval->const_val < INT32_MIN ) {
227         lval->val_type = KIND_LONGLONG;
228         if ( sizeof(long double) == sizeof(double)) {
229             warningfmt("limited-range", "On this host, 64 bit constants may not be correct\n");
230         }
231     }
232     lval->is_const = 1;
233 
234     while (checkws() == 0 && (rcmatch('L') || rcmatch('U') || rcmatch('S') || rcmatch('f'))) {
235         if (cmatch('L')) {
236             lval->val_type = KIND_LONG;
237             if (cmatch('L'))
238                 lval->val_type = KIND_LONGLONG;
239         }
240         if (cmatch('U')) {
241             isunsigned = 1;
242             lval->const_val = (uint64_t)k;
243         }
244         if (cmatch('S'))
245             isunsigned = 0;
246         if (amatch("f16")) {
247             lval->val_type = KIND_FLOAT16;
248             lval->ltype = type_float16;
249         }
250         if (cmatch('f')) {
251             lval->val_type = KIND_DOUBLE;
252             lval->ltype = type_double;
253         }
254     }
255     if ( lval->val_type == KIND_LONGLONG ) {
256         if ( isunsigned )
257             lval->ltype = type_ulonglong;
258         else
259             lval->ltype = type_longlong;
260     } else if ( lval->val_type == KIND_LONG ) {
261         if ( isunsigned )
262             lval->ltype = type_ulong;
263         else
264             lval->ltype = type_long;
265     } else {
266         if ( isunsigned )
267             lval->ltype = type_uint;
268         else
269             lval->ltype = type_int;
270     }
271     return (1);
272 }
273 
hex(char c)274 int hex(char c)
275 {
276     char c1;
277 
278     c1 = toupper(c);
279     return ((c1 >= '0' && c1 <= '9') || (c1 >= 'A' && c1 <= 'F'));
280 }
281 
282 /* djm, seems to load up literal address? */
283 
address(SYMBOL * ptr)284 void address(SYMBOL* ptr)
285 {
286     immed();
287     outname(ptr->name, dopref(ptr));
288     nl();
289     if ( ptr->ctype->kind == KIND_CPTR ) {
290         const2(0);
291     }
292 }
293 
pstr(LVALUE * lval)294 int pstr(LVALUE *lval)
295 {
296     int k;
297 
298     lval->val_type = KIND_INT;
299     if ( c_default_unsigned ) {
300         lval->ltype = type_uint;
301     } else {
302         lval->ltype = type_int;
303     }
304     if (cmatch('\'')) {
305         k = 0;
306         while (ch() && ch() != '\'')
307             k = (k & 255) * 256 + litchar();
308         gch();
309         lval->const_val = k;
310         return (1);
311     }
312     return (0);
313 }
314 
315 /* Scan in literals within function into temporary buffer and then
316  * check to see if present elsewhere, if so do the merge as for doubles
317  */
318 
tstr(int32_t * val)319 int tstr(int32_t* val)
320 {
321     int k = 0;
322 
323     if (cmatch('"') == 0)
324         return (0);
325     do {
326         while (ch() != '"') {
327             if (ch() == 0)
328                 break;
329             tempq[k] = litchar();
330             k++; /* counter */
331         }
332         gch();
333     } while (cmatch('"'));
334     tempq[k] = 0;
335     k++;
336     return (storeq(k, tempq, val));
337 }
338 
339 /*
340  * Messed around with 5/5/99 djm to allow queues to start from 1
341  * internally, but to the asm file show it to start from 0
342  */
343 
storeq(int length,unsigned char * queue,int32_t * val)344 int storeq(int length, unsigned char* queue, int32_t* val)
345 {
346     int j, k, len;
347     /* Have stashed it in our temporary queue, we know the length, so lets
348     * get checking to see if one exactly the same has already been placed
349     * in there...
350     */
351     k = length;
352     len = litptr - k; /* Amount of leeway to search through.. */
353     j = 1; /* Literal queue starts from 1 not 0 now
354                          * this allows scan for miniprintf to work
355                          * correctly
356                          */
357     while (len >= j) {
358         if (strncmp((char*)queue, (char*)litq + j, k) == 0) {
359             *val = j - 1;
360             return (1);
361         } /*success!*/
362         j++;
363     }
364     /* If we get here, then dump it in the queue as per normal... */
365     *val = (int32_t)litptr - 1;
366     for (j = 0; j < k; j++) {
367         /* Have to dump it in our special queue here for function literals */
368         if ((litptr + 1) >= FNMAX) {
369             errorfmt("Literal Queue Overflow", 1);
370         }
371         *(litq + litptr) = *(queue + j);
372         litptr++;
373     }
374     return (k);
375 }
376 
qstr(double * val)377 int qstr(double *val)
378 {
379     int cnt = 0;
380 
381     if (cmatch('"') == 0)
382         return (-1);
383 
384     *val = gltptr;
385     do {
386         while (ch() != '"') {
387             if (ch() == 0)
388                 break;
389             cnt++;
390             stowlit(litchar(), 1);
391         }
392         gch();
393     } while (cmatch('"') || (cmatch('\\') && cmatch('"')));
394 
395     glbq[gltptr++] = 0;
396     return (cnt);
397 }
398 
399 /* store integer i of size size bytes in global var literal queue */
stowlit(int value,int size)400 void stowlit(int value, int size)
401 {
402     if ((gltptr + size) >= LITMAX) {
403         errorfmt("Literal Queue Overflow", 1);
404     }
405     putint(value, glbq + gltptr, size);
406     gltptr += size;
407 }
408 
409 /* Return current literal char & bump lptr */
litchar()410 unsigned char litchar()
411 {
412     int i, oct;
413 
414     if (ch() != '\\')
415         return (gch());
416     if (nch() == 0)
417         return (gch());
418     gch();
419     switch (ch()) {
420     case 'a': /* Bell */
421         gch();
422         return 7;
423     case 'b': /* BS */
424         gch();
425         return 8;
426     case 't': /* HT */
427         gch();
428         return 9;
429     case 'r': /* LF */
430         gch();
431         return c_standard_escapecodes ? 13 : 10;
432     case 'v': /* VT */
433         gch();
434         return 11;
435     case 'f': /* FF */
436         gch();
437         return 12;
438     case 'n': /* CR */
439         gch();
440         return c_standard_escapecodes ? 10 : 13;
441     case '\"': /* " */
442         gch();
443         return 34;
444     case '\'': /* ' */
445         gch();
446         return 39;
447     case '\\': /* / */
448         gch();
449         return '\\';
450     case '\?': /* ? */
451         gch();
452         return '\?';
453     case 'l': /* LF (non standard)*/
454         gch();
455         return 10;
456     case 'e':
457         gch();
458         return 27;
459     }
460 
461     if (ch() != 'x' && (ch() < '0' || ch() > '7')) {
462         warningfmt("parser","Unknown escape sequence \\%c", ch());
463         return (gch());
464     }
465     if (ch() == 'x') {
466         gch();
467         oct = 0;
468         i = 2;
469         while (i-- > 0 && hex(ch())) {
470             if (ch() <= '9')
471                 oct = (oct << 4) + (gch() - '0');
472             else
473                 oct = (oct << 4) + ((gch() & 95) - '7');
474         }
475         if (isxdigit(ch())) {
476             warningfmt("parser","Hex escape sequence out of range");
477         }
478         return ((char)oct);
479     }
480 
481     i = 3;
482     oct = 0;
483     while (i-- > 0 && ch() >= '0' && ch() <= '7')
484         oct = (oct << 3) + gch() - '0';
485     if (i == 2)
486         return (gch());
487     else {
488         return ((char)oct);
489     }
490 }
491 
492 /* Perform an offsetof(structure, member) */
offset_of(LVALUE * lval)493 void offset_of(LVALUE *lval)
494 {
495     char   struct_name[NAMESIZE];
496     char   memb_name[NAMESIZE];
497     char   foundit = 0;
498 
499     memb_name[0] = struct_name[0] = 0;
500     needchar('(');
501     if ( symname(struct_name) ) {
502         needchar(',');
503         if ( symname(memb_name) ) {
504             Type* tag = find_tag(struct_name);
505 
506             /* Consider typedefs */
507             if ( tag == NULL ) {
508                 SYMBOL *ptr;
509 
510                 if (((ptr = findloc(struct_name)) != NULL) || ((ptr = findstc(struct_name)) != NULL) || ((ptr = findglb(struct_name)) != NULL)) {
511                     if ( ispointer(ptr->ctype) && ptr->ctype->ptr->kind == KIND_STRUCT ) {
512                         tag = ptr->ctype->ptr->tag;
513                     } else if ( ptr->ctype->kind == KIND_STRUCT ) {
514                         tag = ptr->ctype->tag;
515                     } else {
516                         printf("%d\n",ptr->type);
517                     }
518                 }
519             }
520             if ( tag != NULL ) {
521                 Type *member = find_tag_field(tag, memb_name);
522 
523                 if ( member != NULL ) {
524                     foundit = 1;
525                     lval->const_val = member->offset;
526                 }
527             }
528         }
529     }
530     needchar(')');
531     if ( foundit ) {
532         lval->is_const = 1;
533         lval->ltype = type_int;
534         lval->val_type = KIND_INT;
535         vconst(lval->const_val);
536     } else {
537         errorfmt("Cannot evaluate __builtin_offsetof(%s,%s)", 1, strlen(struct_name) ? struct_name : "<unknown>", strlen(memb_name) ? memb_name : "<unknown>");
538     }
539 
540 
541 }
542 
543 /* Perform a sizeof (works on variables as well */
size_of(LVALUE * lval)544 void size_of(LVALUE* lval)
545 {
546     char sname[NAMESIZE];
547     int length;
548     Type *type;
549     SYMBOL *ptr;
550     int          deref = 0;
551     int     brackets = 0;
552 
553     if ( rcmatch('(')) {
554         brackets = 1;
555         needchar('(');
556     }
557     while ( cmatch('*') ) {
558         deref++;
559     }
560     lval->ltype = type_int;
561 
562     if ( (type = parse_expr_type()) != NULL ) {
563         if ( deref && type->kind != KIND_PTR ) {
564             UT_string *str;
565             utstring_new(str);
566             type_describe(type, str);
567             errorfmt("sizeof expects a pointer but got %s", 1, utstring_body(str) );
568             utstring_free(str);
569             lval->const_val = 2;
570             lval->is_const = 1;
571             return;
572         }
573         while ( deref && type ) {
574             Type *next = type->ptr;
575             type = next;
576             deref--;
577         }
578         if ( type == NULL ) {
579             lval->const_val = 2;
580             lval->is_const = 1;
581             errorfmt("Cannot dereference far enough, assuming size of 2",1);
582         } else {
583             lval->const_val = type->size;
584         }
585     } else if (cmatch('"')) { /* Check size of string */
586         length = 1; /* Always at least one */
587         do
588         {
589             while (!cmatch('"')) {
590                 length++;
591                 litchar();
592             };
593             /* Keep going for "concatenated" "strings" */
594             if (!cmatch('"')) {
595                 break;
596             }
597             /* But correct the opening quotes */
598             length--;
599         } while (1);
600         lval->const_val = length;
601         if ( deref )
602             lval->const_val = 1;
603     } else if (symname(sname)) { /* Size of an object */
604         Type *type;
605         if (((ptr = findloc(sname)) != NULL) || ((ptr = findstc(sname)) != NULL) || ((ptr = findglb(sname)) != NULL)) {
606             type = ptr->ctype;
607             lval->const_val = type->size;
608 
609             if (type->kind != KIND_FUNC && ptr->ident != ID_MACRO) {
610                 if ( type->kind == KIND_PTR && type->ptr->kind == KIND_STRUCT ) {
611                     type = type->ptr;
612                 }
613                 if (type->kind != KIND_STRUCT ) {
614                 } else {
615                     Type *mptr;
616 
617                     /* We're a member of a structure */
618                     do {
619                         if ( (mptr = get_member(type->kind == KIND_STRUCT ? type->tag : type->ptr->tag) ) != NULL ) {
620                             type = mptr;
621                             if ( (mptr->kind == KIND_PTR || mptr->kind == KIND_CPTR) && deref ) {
622                                 // Do nothing
623                             } else {
624                                 // tag_sym->size = numner of elements
625                                 lval->const_val = mptr->size;
626                             }
627                         } else {
628                             lval->const_val = type->size;
629                         }
630                     } while ( mptr && ( (mptr->kind == KIND_STRUCT && rcmatch('.')) ||
631                                       ( ispointer(mptr) && mptr->ptr->kind == KIND_STRUCT && rmatch2("->"))) );
632                 }
633                 /* Check for index operator on array */
634                 if (type->kind == KIND_ARRAY ) {
635                     if (rcmatch('[')) {
636                         double val;
637                         Kind valtype;
638                         needchar('[');
639                         constexpr(&val, &valtype,  1);
640                         needchar(']');
641                         deref++;
642                         lval->const_val = type->size / type->len;
643                     }
644                 }
645                 while ( deref && type ) {
646                     lval->const_val = type->size;
647                     type = type->ptr;
648                     if ( type ) {
649                         lval->const_val = type->size;
650                     }
651                     deref--;
652                 }
653             } else {
654                 lval->const_val = 2;
655             }
656         } else {
657             errorfmt("Unknown symbol: %s", 1, sname);
658         }
659     }
660     if ( brackets )
661         needchar(')');
662     lval->is_const = 1;
663     lval->val_type = KIND_INT;
664     vconst(lval->const_val);
665 }
666 
get_member(Type * tag)667 static Type *get_member(Type *tag)
668 {
669     char sname[NAMESIZE];
670     Type *member;;
671 
672     if (cmatch('.') == NO && match("->") == NO)
673         return NULL;
674 
675     if (symname(sname) && (member = find_tag_field(tag, sname))) {
676         return member;
677     }
678     errorfmt("Unknown member: %s", 1, sname);
679     return NULL;
680 }
681 
682 
683 
684 
dofloat(enum maths_mode mode,double raw,unsigned char fa[])685 void dofloat(enum maths_mode mode,double raw, unsigned char fa[])
686 {
687     switch ( mode ) {
688         case MATHS_IEEE:
689             dofloat_ieee(raw, fa);
690             break;
691         case MATHS_MBFS:
692             dofloat_mbfs(raw, fa);
693             break;
694         case MATHS_MBF40:
695             dofloat_mbf40(raw, fa);
696             break;
697         case MATHS_MBF64:
698             dofloat_mbf64(raw, fa);
699             break;
700         case MATHS_IEEE16:
701             dofloat_ieee16(raw, fa);
702             break;
703         case MATHS_AM9511:
704             dofloat_am9511(raw, fa);
705             break;
706         default:
707             dofloat_z80(raw, fa);
708             break;
709     }
710 }
711 
pack32bit_float(uint32_t val,unsigned char fa[])712 static void pack32bit_float(uint32_t val, unsigned char fa[])
713 {
714     fa[0] = val & 0xff;
715     fa[1] = (val >> 8) & 0xff;
716     fa[2] = (val >> 16) & 0xff;
717     fa[3] = (val >> 24) & 0xff;
718 }
719 
dofloat_ieee(double raw,unsigned char fa[])720 static void dofloat_ieee(double raw, unsigned char fa[])
721 {
722     if ( isnan(raw)) {
723         // quiet nan: 7FC00000
724         // signalling nan: 7F800001
725         pack32bit_float(0x7fc00000, fa);
726         fa[0] = 0x00;
727         fa[1] = 0x00;
728         fa[2] = 0xc0;
729         fa[3] = 0x7f;
730     } else if ( isinf(raw) && raw > 0 ) {
731         // positive infinity: 7F800000
732         pack32bit_float(0x7f800000, fa);
733         fa[0] = 0x00;
734         fa[1] = 0x00;
735         fa[2] = 0x80;
736         fa[3] = 0x7f;
737     } else if ( isinf(raw) && raw < 0 ) {
738         // negative infinity: FF800000
739         pack32bit_float(0xff800000, fa);
740     } else {
741         struct fp_decomposed fs = {0};
742         uint32_t fp_value = 0;
743 
744         decompose_float(raw, &fs);
745 
746         // Bundle up mantissa
747         fp_value = ( ( (uint32_t)fs.mantissa[4]) | ( ((uint32_t)fs.mantissa[5]) << 8) | (((uint32_t)fs.mantissa[6]) << 16))  & 0x007fffff;
748 
749         // And now the exponent
750         fp_value |= (((uint32_t)fs.exponent) << 23);
751 
752         // And the sign bit
753         fp_value |= fs.sign ? 0x80000000 : 0x00000000;
754         pack32bit_float(fp_value, fa);
755     }
756 }
757 
dofloat_ieee16(double raw,unsigned char fa[])758 static void dofloat_ieee16(double raw, unsigned char fa[])
759 {
760     if ( isnan(raw)) {
761         fa[0] = 0xff;
762         fa[1] = 0xff;
763     } else if ( isinf(raw) && raw > 0 ) {
764         // positive infinity: 7c00
765         fa[0] = 0x00;
766         fa[1] = 0x7c;
767     } else if ( isinf(raw) && raw < 0 ) {
768         // positive infinity: 7c00
769         fa[0] = 0x00;
770         fa[1] = 0xfc;
771     } else {
772         struct fp_decomposed fs = {0};
773         uint32_t fp_value = 0;
774         int saved_exp = c_fp_exponent_bias;
775         int saved_mant = c_fp_mantissa_bytes;
776 
777         c_fp_exponent_bias = 14;
778         c_fp_mantissa_bytes = 2;
779         decompose_float(raw, &fs);
780 
781         c_fp_exponent_bias = saved_exp;
782         c_fp_mantissa_bytes = saved_mant;
783 
784 
785 
786         // Bundle up mantissa - it's only 10 bits
787         fp_value = ((((uint32_t)fs.mantissa[6]) << 3) |  ((((uint32_t)fs.mantissa[5]) >> 5 ) & 0x07) ) & 0x3ff  ;
788 
789         // And now the exponent
790         fp_value |= (((uint32_t)fs.exponent) << 10) & 0x7fc0;
791 
792         // And the sign bit
793         fp_value |= fs.sign ? 0x8000 : 0x0000;
794         fa[0] = fp_value & 0xff;
795         fa[1] = (fp_value & 0xff00) >> 8;
796     }
797 }
798 
dofloat_mbfs(double raw,unsigned char fa[])799 static void dofloat_mbfs(double raw, unsigned char fa[])
800 {
801     struct fp_decomposed fs = {0};
802     uint32_t fp_value = 0;
803 
804     decompose_float(raw, &fs);
805 
806     // Bundle up mantissa
807     fp_value = ( ( (uint32_t)fs.mantissa[4]) | ( ((uint32_t)fs.mantissa[5]) << 8) | (((uint32_t)fs.mantissa[6]) << 16))  & 0x007fffff;
808 
809     // And now the exponent
810     fp_value |= (((uint32_t)fs.exponent) << 24);
811 
812     // And the sign bit
813     fp_value |= fs.sign ? 0x00800000 : 0x00000000;
814     pack32bit_float(fp_value, fa);
815 }
816 
dofloat_am9511(double raw,unsigned char fa[])817 static void dofloat_am9511(double raw, unsigned char fa[])
818 {
819     struct fp_decomposed fs = {0};
820     uint32_t fp_value = 0;
821 
822     if ( raw != 0.0 ) {
823         decompose_float(raw, &fs);
824 
825         // Bundle up mantissa
826         fp_value = (((uint32_t)fs.mantissa[4]) | ( ((uint32_t)fs.mantissa[5]) << 8) | (((uint32_t)fs.mantissa[6]) << 16)) | 0x00800000;
827 
828         // And now the exponent
829         fp_value |= ((((uint32_t)fs.exponent) << 24) & 0x7f000000);
830 
831         // And the sign bit
832         fp_value |= fs.sign ? 0x80000000 : 0x00000000;
833     }
834     pack32bit_float(fp_value, fa);
835 }
836 
837 
dofloat_mbf64(double raw,unsigned char fa[])838 static void dofloat_mbf64(double raw, unsigned char fa[])
839 {
840     struct fp_decomposed fs = {0};
841 
842     decompose_float(raw, &fs);
843 
844     memcpy(fa, fs.mantissa, 7);
845     fa[6] |= fs.sign ? 0x80 : 00;
846     fa[7] = fs.exponent;
847 }
848 
849 
dofloat_mbf40(double raw,unsigned char fa[])850 static void dofloat_mbf40(double raw, unsigned char fa[])
851 {
852     struct fp_decomposed fs = {0};
853 
854     decompose_float(raw, &fs);
855 
856     memcpy(fa, fs.mantissa + 3, 4);
857     fa[3] |= fs.sign ? 0x80 : 00;
858     fa[4] = fs.exponent;
859 }
860 
dofloat_z80(double raw,unsigned char fa[])861 static void dofloat_z80(double raw, unsigned char fa[])
862 {
863     struct fp_decomposed fs = {0};
864     int      offs = MAX_MANTISSA_SIZE - c_fp_mantissa_bytes;
865     int      i;
866 
867     decompose_float(raw, &fs);
868 
869 
870     for ( i = offs; i < MAX_MANTISSA_SIZE ; i++ ) {
871         fa[i - offs + c_fp_fudge_offset] = fs.mantissa[i];
872     }
873     fa[i - offs -1 + c_fp_fudge_offset] |= fs.sign ? 0x80 : 0;
874     fa[i - offs + c_fp_fudge_offset] = fs.exponent;
875 }
876 
877 
decompose_float(double raw,struct fp_decomposed * fs)878 static void decompose_float(double raw, struct fp_decomposed *fs)
879 {
880     double norm;
881     double x = fabs(raw);
882     double exp = log(x) / log(2);
883     int i;
884     int mant_bytes = c_fp_mantissa_bytes;
885     int exp_bias = c_fp_exponent_bias;
886 
887     fs->sign = 0;
888     fs->exponent = 0;
889 
890     for ( i = 0; i < MAX_MANTISSA_SIZE; i++ ) {
891        fs->mantissa[i] = 0;
892     }
893 
894     if (mant_bytes > MAX_MANTISSA_SIZE ) {
895         mant_bytes = MAX_MANTISSA_SIZE;
896     }
897 
898     if (x == 0.0) {
899         memset(fs->mantissa, 0, MAX_MANTISSA_SIZE + 1);
900         return;
901     }
902 
903     if (floor(exp) == ceil(exp)) {
904         exp = ceil(exp) + 1;
905     } else {
906         exp = ceil(exp);
907     }
908 
909     norm = x / pow(2, exp);
910 
911     fs->exponent = (int)exp + exp_bias;
912     for (i = 0; i < (mant_bytes * 2) + 1; i++) {
913         double mult = norm * 16.;
914         double res = floor(mult);
915         unsigned char bit = res;
916 
917         if (i == 0 && raw > 0)
918             bit -= 8;
919         if (i == mant_bytes * 2) {
920             if (bit > 7) {
921                 int carry = 1;
922                 for (i = MAX_MANTISSA_SIZE - mant_bytes; i < MAX_MANTISSA_SIZE; i++) {
923                     int res = fs->mantissa[i] + carry;
924 
925                     fs->mantissa[i] = res % 256;
926                     carry = res / 256;
927                 }
928             }
929             break;
930         }
931         if (i % 2 == 0) {
932             fs->mantissa[(MAX_MANTISSA_SIZE-1) - i / 2] = (bit << 4);
933         } else {
934             fs->mantissa[(MAX_MANTISSA_SIZE-1) - i / 2] |= (bit & 0x0f);
935         }
936         norm = mult - res;
937     }
938     if ( raw < 0 ) {
939         fs->sign = 1;
940     }
941 }
942 
943 
get_elem_for_fa(unsigned char fa[],double value)944 elem_t *get_elem_for_fa(unsigned char fa[], double value)
945 {
946     elem_t  *elem;
947 
948     LL_FOREACH(bigconst_queue, elem ) {
949         if ( elem->kind == KIND_DOUBLE && memcmp(elem->fa, fa, MAX_MANTISSA_SIZE) == 0 ) {
950             return elem;
951         }
952     }
953     elem = MALLOC(sizeof(*elem));
954     elem->kind = KIND_DOUBLE;
955     elem->litlab = getlabel();
956     elem->value = value;
957     elem->written = 0;
958     memcpy(elem->fa, fa, MAX_MANTISSA_SIZE+1);
959     LL_APPEND(bigconst_queue, elem);
960     return elem;
961 }
962 
indicate_constant_written(int litlab)963 void indicate_constant_written(int litlab)
964 {
965     elem_t  *elem;
966 
967     LL_FOREACH(bigconst_queue, elem ) {
968         if ( elem->litlab == litlab ) {
969             elem->written = 1;
970         }
971     }
972 }
973 
get_elem_for_buf(char * str,double value)974 elem_t *get_elem_for_buf(char *str, double value)
975 {
976     elem_t  *elem;
977 
978     LL_FOREACH(bigconst_queue, elem ) {
979         if ( elem->kind == KIND_DOUBLE && strcmp(elem->str, str) == 0 ) {
980             return elem;
981         }
982     }
983     elem = MALLOC(sizeof(*elem));
984     elem->kind = KIND_DOUBLE;
985     elem->litlab = getlabel();
986     elem->value = value;
987     elem->written = 0;
988     strcpy(elem->str,str);
989     LL_APPEND(bigconst_queue, elem);
990     return elem;
991 }
992 
993 
get_elem_for_llong(char buf[8])994 elem_t *get_elem_for_llong(char buf[8])
995 {
996     elem_t  *elem;
997 
998     LL_FOREACH(bigconst_queue, elem ) {
999         if ( elem->kind == KIND_LONGLONG && memcmp(elem->fa, buf, 8) == 0 ) {
1000             return elem;
1001         }
1002     }
1003     elem = MALLOC(sizeof(*elem));
1004     elem->kind = KIND_LONGLONG;
1005     elem->litlab = getlabel();
1006     elem->written = 0;
1007     memcpy(elem->fa, buf, 8);
1008     LL_APPEND(bigconst_queue, elem);
1009     return elem;
1010 }
1011 
1012 
1013 
write_constant_queue(void)1014 void write_constant_queue(void)
1015 {
1016     elem_t  *elem;
1017 
1018     LL_FOREACH(bigconst_queue, elem ) {
1019         if ( elem->written ) {
1020             gen_switch_section(c_rodata_section);
1021             prefix();
1022             queuelabel(elem->litlab);
1023             col();
1024             nl();
1025             if ( elem->kind == KIND_DOUBLE) {
1026                 if ( c_double_strings ) {
1027                     defmesg(); outstr(elem->str); outstr("\"\n");
1028                     defbyte(); outdec(0); nl();
1029                 } else {
1030                     char   buf[128];
1031                     int    i, offs;
1032 
1033                     for ( i = 0, offs = 0; i < c_fp_size; i++) {
1034                         offs += snprintf(buf + offs, sizeof(buf) - offs,"%s0x%02x", i != 0 ? "," : "", elem->fa[i]);
1035                     }
1036                     //outfmt("\t;%lf ref: %d written: %d\n",elem->value,elem->refcount, elem->written);
1037                     outfmt("\t;%Lf\n",elem->value);
1038                     outfmt("\tdefb\t%s\n", buf);
1039                 }
1040             } else {
1041                 char   buf[128];
1042                 int    i, offs;
1043                 for ( i = 0, offs = 0; i < 8; i++) {
1044                     offs += snprintf(buf + offs, sizeof(buf) - offs,"%s0x%02x", i != 0 ? "," : "", elem->fa[i]);
1045                 }
1046                 outfmt("\tdefb\t%s\n", buf);
1047             }
1048         }
1049     }
1050     nl();
1051 }
1052 
load_llong_into_acc(zdouble val)1053 void load_llong_into_acc(zdouble val)
1054 {
1055     uint64_t v,l;
1056     char    buf[8];
1057     elem_t *elem;
1058 
1059     v = val;
1060 
1061 
1062     l = v & 0xffffffff;
1063     buf[0] = (l % 65536) % 256;
1064     buf[1] = (l % 65536) / 256;
1065     buf[2] = (l / 65536) % 256;
1066     buf[3] =  (l / 65536) / 256;
1067     l = (v >> 32) & 0xffffffff;
1068     buf[4] = (l % 65536) % 256;
1069     buf[5] = (l % 65536) / 256;
1070     buf[6] = (l / 65536) % 256;
1071     buf[7] =  (l / 65536) / 256;
1072 
1073     elem = get_elem_for_llong(buf);
1074     immedlit(elem->litlab,0);
1075     nl();
1076     callrts("l_i64_load");
1077 }
1078 
1079 
load_double_into_fa(LVALUE * lval)1080 void load_double_into_fa(LVALUE *lval)
1081 {
1082     unsigned char    fa[MAX_MANTISSA_SIZE+1] = {0};
1083     elem_t          *elem;
1084     memset(fa, 0, sizeof(fa));
1085 
1086     if ( c_double_strings ) {
1087         char  buf[40];
1088         snprintf(buf, sizeof(buf), "%Lf", lval->const_val);
1089         elem = get_elem_for_buf(buf, lval->const_val);
1090         immedlit(elem->litlab,0);
1091         nl();
1092         callrts("__atof2");
1093         WriteDefined("math_atof", 1);
1094     } else {
1095         dofloat(c_maths_mode,lval->const_val, fa);
1096         if ( lval->val_type == KIND_FLOAT16 ) {
1097             dofloat_ieee16(lval->const_val, fa);
1098             vconst(fa[1] << 8 | fa[0]);
1099         } else if ( c_fp_size == 4 ) {
1100             vconst(fa[1] << 8 | fa[0]);
1101             const2(fa[3] << 8 | fa[2]);
1102         } else {
1103             elem = get_elem_for_fa(fa,lval->const_val);
1104             immedlit(elem->litlab,0);
1105             nl();
1106             callrts("dload");
1107         }
1108     }
1109 }
1110