FIx initialization of pointers in code space for DS390
[fw/sdcc] / src / SDCCglue.c
1 /*-------------------------------------------------------------------------
2
3   SDCCglue.c - glues everything we have done together into one file.                 
4                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5                 
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19    
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!  
23 -------------------------------------------------------------------------*/
24
25 #include "common.h"
26 #include "asm.h"
27 #include <time.h>
28
29 symbol *interrupts[256];
30 /*extern char *aopLiteral (value *, int);*//* drdani Jan 30 2000 */
31 void printIval (symbol *, link *, initList *, FILE *);
32 extern int noAlloc;
33 set *publics = NULL;            /* public variables */
34 set *externs = NULL;            /* Varibles that are declared as extern */
35
36 /* TODO: this should be configurable (DS803C90 uses more than 6) */
37 int maxInterrupts = 6;
38 int allocInfo = 1;
39 extern int maxRegBank ;
40 symbol *mainf;
41 extern char *VersionString;
42 extern FILE *codeOutFile;
43 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
44 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
45
46 /*-----------------------------------------------------------------*/
47 /* closeTmpFiles - closes all tmp files created by the compiler    */
48 /*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
49 /*-----------------------------------------------------------------*/
50 DEFSETFUNC(closeTmpFiles)
51 {
52     FILE *tfile = item;
53
54     if (tfile)
55         fclose(tfile);
56     
57     return 0;
58 }
59
60 /*-----------------------------------------------------------------*/
61 /* rmTmpFiles - closes all tmp files created by the compiler    */
62 /*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
63 /*-----------------------------------------------------------------*/
64 DEFSETFUNC(rmTmpFiles)
65 {
66     char *name = item;
67
68     if (name) {
69         unlink(name);
70         free(name);
71     }
72     return 0;
73 }
74
75 /*-----------------------------------------------------------------*/
76 /* copyFile - copies source file to destination file               */
77 /*-----------------------------------------------------------------*/
78 void copyFile (FILE * dest, FILE * src)
79 {
80     int ch;
81     
82     rewind (src);
83     while (!feof (src))
84         if ((ch = fgetc (src)) != EOF)
85             fputc (ch, dest);
86 }
87
88 char *aopLiteralLong(value *val, int offset, int size)
89 {
90     char *rs;
91     union {
92         float f;
93         unsigned char c[4];
94     } fl;
95
96     /* if it is a float then it gets tricky */
97     /* otherwise it is fairly simple */
98     if (!IS_FLOAT(val->type)) {
99         unsigned long v = floatFromVal(val);
100
101         v >>= (offset * 8);
102         switch (size) {
103         case 1:
104             tsprintf(buffer, "!immedbyte", (unsigned int)v & 0xff);
105             break;
106         case 2:
107             tsprintf(buffer, "!immedword", (unsigned int)v & 0xffff);
108             break;
109         default:
110             /* Hmm.  Too big for now. */
111             assert(0);
112         }
113         ALLOC_ATOMIC(rs,strlen(buffer)+1);
114         return strcpy (rs,buffer);
115     }
116
117     /* PENDING: For now size must be 1 */
118     assert(size == 1);
119
120     /* it is type float */
121     fl.f = (float) floatFromVal(val);
122 #ifdef _BIG_ENDIAN
123     tsprintf(buffer, "!immedbyte", fl.c[3-offset]);
124 #else
125     tsprintf(buffer, "!immedbyte", fl.c[offset]);
126 #endif
127     ALLOC_ATOMIC(rs,strlen(buffer)+1);
128     return strcpy (rs,buffer);
129 }
130
131 /*-----------------------------------------------------------------*/
132 /* aopLiteral - string from a literal value                        */
133 /*-----------------------------------------------------------------*/
134 char *aopLiteral (value *val, int offset)
135 {
136     return aopLiteralLong(val, offset, 1);
137 }
138
139 /*-----------------------------------------------------------------*/
140 /* emitRegularMap - emit code for maps with no special cases       */
141 /*-----------------------------------------------------------------*/
142 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
143 {
144     symbol *sym;
145     
146     if (addPublics) {
147         /* PENDING: special case here - should remove */
148         if (!strcmp(map->sname, CODE_NAME))
149             tfprintf(map->oFile, "\t!areacode\n", map->sname);
150         else if (!strcmp(map->sname, DATA_NAME)) 
151             tfprintf(map->oFile, "\t!areadata\n", map->sname);
152         else if (!strcmp(map->sname, HOME_NAME)) 
153             tfprintf(map->oFile, "\t!areahome\n", map->sname);
154         else
155             tfprintf(map->oFile, "\t!area\n", map->sname);
156     }
157     
158     /* print the area name */
159     for (sym = setFirstItem (map->syms); sym;
160          sym = setNextItem (map->syms))  {
161         
162         /* if extern then add it into the extern list */
163         if (IS_EXTERN (sym->etype)) {
164             addSetHead (&externs, sym);
165             continue;
166         }
167         
168         /* if allocation required check is needed
169            then check if the symbol really requires
170            allocation only for local variables */
171         if (arFlag && !IS_AGGREGATE(sym->type) &&
172             !(sym->_isparm && !IS_REGPARM(sym->etype)) && 
173               !sym->allocreq && sym->level)
174             continue ;
175         
176         /* if global variable & not static or extern 
177            and addPublics allowed then add it to the public set */
178         if ((sym->level == 0 || 
179              (sym->_isparm && !IS_REGPARM(sym->etype))) &&
180             addPublics &&
181             !IS_STATIC (sym->etype) &&
182             (sym->used || sym->fbody)) {
183             addSetHead (&publics, sym);
184         }
185         
186         /* if extern then do nothing or is a function 
187            then do nothing */
188         if (IS_FUNC (sym->type))
189             continue;
190         
191         /* print extra debug info if required */
192         if ((options.debug || sym->level == 0) && !options.nodebug) {
193
194             cdbSymbol(sym,cdbFile,FALSE,FALSE);
195
196             if (!sym->level) /* global */
197                 if (IS_STATIC(sym->etype))
198                     fprintf(map->oFile,"F%s$",moduleName); /* scope is file */
199                 else
200                     fprintf(map->oFile,"G$"); /* scope is global */
201             else
202                 /* symbol is local */
203                 fprintf(map->oFile,"L%s$",(sym->localof ? sym->localof->name : "-null-"));
204             fprintf(map->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
205         }
206
207         /* if is has an absolute address then generate
208            an equate for this no need to allocate space */
209         if (SPEC_ABSA (sym->etype)) {
210             if ((options.debug || sym->level == 0) && !options.nodebug)
211                 fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));         
212
213             fprintf (map->oFile, "%s\t=\t0x%04x\n",
214                      sym->rname,
215                      SPEC_ADDR (sym->etype));
216         }
217         else {
218             /* allocate space */
219             if ((options.debug || sym->level == 0) && !options.nodebug)
220                 fprintf(map->oFile,"==.\n");
221             if (IS_STATIC(sym->etype))
222                 tfprintf(map->oFile, "!slabeldef\n", sym->rname);
223             else
224                 tfprintf(map->oFile, "!labeldef\n", sym->rname);
225             tfprintf(map->oFile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
226         }
227         
228         /* if it has a initial value then do it only if
229            it is a global variable */
230         if (sym->ival && sym->level == 0) {
231             ast *ival = NULL;
232             
233             if (IS_AGGREGATE (sym->type))
234                 ival = initAggregates (sym, sym->ival, NULL);
235             else
236                 ival = newNode ('=', newAst (EX_VALUE, symbolVal (sym)),
237                                 decorateType (resolveSymbols (list2expr (sym->ival))));
238             codeOutFile = statsg->oFile;
239             allocInfo = 0;
240             eBBlockFromiCode (iCodeFromAst (ival));
241             allocInfo = 1;
242             sym->ival = NULL;
243         }
244     }
245 }
246
247 /*-----------------------------------------------------------------*/
248 /* initPointer - pointer initialization code massaging             */
249 /*-----------------------------------------------------------------*/
250 value *initPointer (initList *ilist)
251 {
252     value *val;
253     ast *expr = list2expr(ilist);
254
255     if (!expr) 
256         goto wrong;             
257         
258     /* try it the oldway first */
259     if ((val = constExprValue(expr,FALSE)))
260         return val;
261
262     /* no then we have to do these cludgy checks */
263     /* pointers can be initialized with address of
264        a variable or address of an array element */
265     if (IS_AST_OP(expr) && expr->opval.op == '&') {
266         /* address of symbol */
267         if (IS_AST_SYM_VALUE(expr->left)) {
268             val = copyValue(AST_VALUE(expr->left));
269             val->type = newLink();
270             if (SPEC_SCLS(expr->left->etype) == S_CODE) {
271                 DCL_TYPE(val->type) = CPOINTER ;
272                 DCL_PTR_CONST(val->type) = port->mem.code_ro;
273             }
274             else
275                 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
276                     DCL_TYPE(val->type) = FPOINTER;
277                 else
278                     if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
279                         DCL_TYPE(val->type) = PPOINTER ;
280                     else
281                         if (SPEC_SCLS(expr->left->etype) == S_IDATA)
282                             DCL_TYPE(val->type) = IPOINTER ;
283                         else
284                             if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
285                                 DCL_TYPE(val->type) = EEPPOINTER ;
286                             else
287                                 DCL_TYPE(val->type) = POINTER ;
288             val->type->next = expr->left->ftype;
289             val->etype = getSpec(val->type);
290             return val;
291         }
292
293         /* if address of indexed array */
294         if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
295             return valForArray(expr->left);     
296
297         /* if address of structure element then 
298            case 1. a.b ; */
299         if (IS_AST_OP(expr->left) && 
300             expr->left->opval.op == '.' ) {
301                 return valForStructElem(expr->left->left,
302                                         expr->left->right);
303         }
304
305         /* case 2. (&a)->b ; 
306            (&some_struct)->element */
307         if (IS_AST_OP(expr->left) &&
308             expr->left->opval.op == PTR_OP &&
309             IS_ADDRESS_OF_OP(expr->left->left))
310                 return valForStructElem(expr->left->left->left,
311                                         expr->left->right);
312
313     }
314     /* case 3. (((char *) &a) +/- constant) */
315     if (IS_AST_OP(expr) && 
316         (expr->opval.op == '+' || expr->opval.op == '-') &&
317         IS_AST_OP(expr->left) && expr->left->opval.op == CAST &&
318         IS_AST_OP(expr->left->right) && 
319         expr->left->right->opval.op == '&' &&
320         IS_AST_LIT_VALUE(expr->right)) {
321         
322         return valForCastAggr(expr->left->right->left,
323                               expr->left->left->opval.lnk,
324                               expr->right,expr->opval.op);
325         
326     }
327
328  wrong:    
329     werror(E_INIT_WRONG);
330     return NULL;
331     
332 }
333
334 /*-----------------------------------------------------------------*/
335 /* printChar - formats and prints a characater string with DB      */
336 /*-----------------------------------------------------------------*/
337 void printChar (FILE * ofile, char *s, int plen)
338 {
339     int i;
340     int len = strlen (s);
341     int pplen = 0;
342     char buf[100];
343     char *p = buf;
344
345     while (len && pplen < plen) {
346         i = 60;
347         while (i && *s && pplen < plen) {
348             if (*s < ' ' || *s == '\"') {
349                 *p = '\0';
350                 if (p != buf) 
351                     tfprintf(ofile, "\t!ascii\n", buf);
352                 tfprintf(ofile, "\t!db !constbyte\n", *s);
353                 p = buf;
354             }
355             else {
356                 *p = *s;
357                 p++;
358             }
359             s++;
360             pplen++;
361             i--;
362         }
363         if (p != buf) {
364             *p = '\0';
365             tfprintf(ofile, "\t!ascii\n", buf);
366             p = buf;
367         }
368         
369         if (len > 60)
370             len -= 60;
371         else
372             len = 0;
373     }
374     tfprintf(ofile, "\t!db !constbyte\n", 0);
375 }
376
377 /*-----------------------------------------------------------------*/
378 /* return the generic pointer high byte for a given pointer type.  */
379 /*-----------------------------------------------------------------*/
380 int pointerTypeToGPByte(const int p_type)
381 {
382     switch (p_type) 
383     {
384             case IPOINTER:
385             case POINTER:
386                 return 0;
387             case GPOINTER:
388                 /* hack - if we get a generic pointer, we just assume
389                  * it's an FPOINTER (i.e. in XDATA space).
390                  */
391             case FPOINTER:
392                 return 1;
393             case CPOINTER:
394                 return 2;
395             case PPOINTER:
396                 return 3;
397             default:
398                 fprintf(stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
399                         p_type);
400                 break;
401     }
402     return -1;
403 }
404     
405     
406 /*-----------------------------------------------------------------*/
407 /* printPointerType - generates ival for pointer type              */
408 /*-----------------------------------------------------------------*/
409 void _printPointerType(FILE *oFile, const char *name)
410 {
411     if (IS_DS390_PORT)
412     {
413         fprintf(oFile, "\t.byte %s,(%s >> 8),(%s >> 16)",name,name,name);
414     }
415     else
416     {
417         fprintf(oFile, "\t.byte %s,(%s >> 8)",name,name);
418     }
419 }
420
421 /*-----------------------------------------------------------------*/
422 /* printPointerType - generates ival for pointer type              */
423 /*-----------------------------------------------------------------*/
424 void printPointerType(FILE *oFile, const char *name)
425 {
426     _printPointerType(oFile, name);
427     fprintf(oFile, "\n");
428 }
429
430 /*-----------------------------------------------------------------*/
431 /* printGPointerType - generates ival for generic pointer type     */
432 /*-----------------------------------------------------------------*/
433 void printGPointerType(FILE *oFile, const char *name, 
434                       const unsigned int type)
435 {
436     _printPointerType(oFile,name);
437     fprintf(oFile, ",#0x%02x\n", pointerTypeToGPByte(type)); 
438 }
439
440 /*-----------------------------------------------------------------*/
441 /* printIvalType - generates ival for int/char                     */
442 /*-----------------------------------------------------------------*/
443 void printIvalType (link * type, initList * ilist, FILE * oFile)
444 {
445     value *val;
446     
447     /* if initList is deep */
448     if (ilist->type == INIT_DEEP)
449         ilist = ilist->init.deep;
450     
451     val = list2val (ilist);
452     switch (getSize (type)) {
453     case 1:
454         if (!val)
455             tfprintf(oFile, "\t!db !constbyte\n", 0);
456         else
457             tfprintf(oFile, "\t!dbs\n",
458                      aopLiteral (val, 0));
459         break;
460
461     case 2:
462         if (port->use_dw_for_init)
463             tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
464         else
465             fprintf(oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
466         break;
467     case 4:
468         if (!val) {
469             tfprintf (oFile, "\t!dw !constword\n", 0);
470             tfprintf (oFile, "\t!dw !constword\n", 0);
471         }
472         else {
473             fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
474                      aopLiteral (val, 0), aopLiteral (val, 1),
475                      aopLiteral (val, 2), aopLiteral (val, 3));
476         }
477         break;
478     }
479 }
480
481 /*-----------------------------------------------------------------*/
482 /* printIvalStruct - generates initial value for structures        */
483 /*-----------------------------------------------------------------*/
484 void printIvalStruct (symbol * sym,link * type,
485                       initList * ilist, FILE * oFile)
486 {
487     symbol *sflds;
488     initList *iloop;
489     
490     sflds = SPEC_STRUCT (type)->fields;
491     if (ilist->type != INIT_DEEP) {
492         werror (E_INIT_STRUCT, sym->name);
493         return;
494     }
495     
496     iloop = ilist->init.deep;
497     
498     for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
499         printIval (sflds, sflds->type, iloop, oFile);
500     
501     return;
502 }
503
504 /*-----------------------------------------------------------------*/
505 /* printIvalChar - generates initital value for character array    */
506 /*-----------------------------------------------------------------*/
507 int printIvalChar (link * type, initList * ilist, FILE * oFile, char *s)
508 {
509     value *val;
510     int remain;
511     
512     if (!s) {
513         
514         val = list2val (ilist);
515         /* if the value is a character string  */
516         if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
517             if (!DCL_ELEM (type))
518                 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
519             
520             /* if size mismatch  */
521 /*          if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
522 /*              werror (E_ARRAY_BOUND); */
523             
524             printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
525             
526             if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
527                 while (remain--)
528                     tfprintf (oFile, "\t!db !constbyte\n", 0);
529             
530             return 1;
531         }
532         else
533             return 0;
534     }
535     else
536         printChar (oFile, s,strlen(s)+1);
537     return 1;
538 }
539
540 /*-----------------------------------------------------------------*/
541 /* printIvalArray - generates code for array initialization        */
542 /*-----------------------------------------------------------------*/
543 void printIvalArray (symbol * sym, link * type, initList * ilist,
544                      FILE * oFile)
545 {
546     initList *iloop;
547     int lcnt = 0, size = 0;
548     
549     /* take care of the special   case  */
550     /* array of characters can be init  */
551     /* by a string                      */
552     if (IS_CHAR (type->next))
553         if (printIvalChar (type,
554                            (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
555                            oFile, SPEC_CVAL (sym->etype).v_char))
556             return;
557     
558     /* not the special case             */
559     if (ilist->type != INIT_DEEP) {
560         werror (E_INIT_STRUCT, sym->name);
561         return;
562     }
563     
564     iloop = ilist->init.deep;
565     lcnt = DCL_ELEM (type);
566     
567     for (;;) {
568         size++;
569         printIval (sym, type->next, iloop, oFile);
570         iloop = (iloop ? iloop->next : NULL);
571         
572         
573         /* if not array limits given & we */
574         /* are out of initialisers then   */
575         if (!DCL_ELEM (type) && !iloop)
576             break;
577         
578         /* no of elements given and we    */
579         /* have generated for all of them */
580         if (!--lcnt)
581             break;
582     }
583     
584     /* if we have not been given a size  */
585     if (!DCL_ELEM (type))
586         DCL_ELEM (type) = size;
587     
588     return;
589 }
590
591 /*-----------------------------------------------------------------*/
592 /* printIvalFuncPtr - generate initial value for function pointers */
593 /*-----------------------------------------------------------------*/
594 void printIvalFuncPtr (link * type, initList * ilist, FILE * oFile)
595 {
596     value *val;
597     int dLvl = 0;
598     
599     val = list2val (ilist);
600     /* check the types   */
601     if ((dLvl = checkType (val->type, type->next)) <= 0) {
602         tfprintf(oFile, "\t!dw !constword\n", 0);
603         return;
604     }
605     
606     /* now generate the name */
607     if (!val->sym) {
608         if (port->use_dw_for_init)
609         {
610             tfprintf(oFile, "\t!dws\n", val->name);
611         }
612         else  
613         {
614             printPointerType(oFile, val->name);
615         }
616     }
617     else
618         if (port->use_dw_for_init)
619         {
620             tfprintf(oFile, "\t!dws\n", val->sym->rname);
621         }
622         else
623         {
624             printPointerType(oFile, val->sym->rname);
625         }
626     
627     return;
628 }
629
630 /*-----------------------------------------------------------------*/
631 /* printIvalCharPtr - generates initial values for character pointers */
632 /*-----------------------------------------------------------------*/
633 int printIvalCharPtr (symbol * sym, link * type, value * val, FILE * oFile)
634 {
635     int size = 0;
636     
637     /* PENDING: this is _very_ mcs51 specific, including a magic
638        number... 
639        It's also endin specific.
640     */
641     size = getSize (type);
642
643     if (val->name && strlen(val->name)) {
644         if (size == 1) /* This appears to be Z80 specific?? */
645         {
646             tfprintf(oFile,
647                     "\t!dbs\n", val->name);
648         }
649         else if (size == FPTRSIZE)
650         {
651             if (port->use_dw_for_init)
652             {
653                 tfprintf(oFile, "\t!dws\n", val->name);
654             }
655             else
656             {
657                 printPointerType(oFile, val->name);
658             }
659         }
660         else  if (size == GPTRSIZE)
661         {
662             /* PENDING: 0x02 or 0x%02x, CDATA? */
663             printGPointerType(oFile, val->name, 
664                               (IS_PTR(val->type) ? DCL_TYPE(val->type) :
665                               PTR_TYPE(SPEC_OCLS(val->etype))));
666         }
667         else
668         {
669             fprintf(stderr, "*** internal error: unknown size in "
670                             "printIvalCharPtr.\n");
671         }
672     }
673     else {
674         /* What is this case? Are these pointers? */
675         switch (size) {
676         case 1:
677             tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
678             break;
679         case 2:
680             if (port->use_dw_for_init)
681                 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, size));
682             else 
683                 tfprintf(oFile, "\t.byte %s,%s\n", 
684                          aopLiteral(val, 0),aopLiteral(val, 1));
685             break;
686         case 3:
687             /* PENDING: 0x02 or 0x%02x, CDATA? */
688             fprintf(oFile, "\t.byte %s,%s,#0x02\n",
689                     aopLiteral (val, 0), aopLiteral (val, 1));
690             break;
691         default:
692             assert(0);
693         }
694     }
695
696
697     if (val->sym && val->sym->isstrlit)
698         addSet (&statsg->syms, val->sym);
699     
700     return 1;
701 }
702
703 /*-----------------------------------------------------------------*/
704 /* printIvalPtr - generates initial value for pointers             */
705 /*-----------------------------------------------------------------*/
706 void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
707 {
708     value *val;
709     int size;
710     
711     /* if deep then   */
712     if (ilist->type == INIT_DEEP)
713         ilist = ilist->init.deep;
714     
715     /* function pointer     */
716     if (IS_FUNC (type->next)) {
717         printIvalFuncPtr (type, ilist, oFile);
718         return;
719     }
720     
721     if (!(val = initPointer (ilist)))
722         return ;
723
724     /* if character pointer */
725     if (IS_CHAR (type->next))
726         if (printIvalCharPtr (sym, type, val, oFile))
727             return;
728     
729     /* check the type      */
730     if (checkType (type, val->type) != 1)
731         werror (E_INIT_WRONG);
732     
733     /* if val is literal */
734     if (IS_LITERAL (val->etype)) {
735         switch (getSize (type)) {
736         case 1:
737             tfprintf(oFile, "\t!db !constbyte\n", (unsigned int)floatFromVal(val) & 0xff);
738             break;
739         case 2:
740             if (port->use_dw_for_init)
741                 tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
742             else
743                 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
744             break;
745         case 3:
746             fprintf (oFile, "\t.byte %s,%s,#0x02\n",
747                      aopLiteral (val, 0), aopLiteral (val, 1));
748         }
749         return;
750     }
751     
752     
753     size = getSize (type);
754     
755     if (size == 1)  /* Z80 specific?? */
756     {
757         tfprintf (oFile, "\t!dbs\n", val->name);
758     }
759     else if (size == FPTRSIZE)
760     {
761         tfprintf (oFile, "\t!dws\n", val->name);
762     }
763     else if (size == GPTRSIZE)
764     {
765         printGPointerType(oFile, val->name, 
766                       (IS_PTR(val->type) ? DCL_TYPE(val->type) :
767                       PTR_TYPE(SPEC_OCLS(val->etype))));
768     }
769     return;
770 }
771
772 /*-----------------------------------------------------------------*/
773 /* printIval - generates code for initial value                    */
774 /*-----------------------------------------------------------------*/
775 void printIval (symbol * sym, link * type, initList * ilist, FILE * oFile)
776 {
777     if (!ilist)
778         return;    
779     
780     /* if structure then    */
781     if (IS_STRUCT (type)) {
782         printIvalStruct (sym, type, ilist, oFile);
783         return;
784     }
785     
786     /* if this is a pointer */
787     if (IS_PTR (type)) {
788         printIvalPtr (sym, type, ilist, oFile);
789         return;
790     }
791     
792     /* if this is an array   */
793     if (IS_ARRAY (type)) {
794         printIvalArray (sym, type, ilist, oFile);
795         return;
796     }
797     
798     /* if type is SPECIFIER */
799     if (IS_SPEC (type)) {
800         printIvalType (type, ilist, oFile);
801         return;
802     }
803 }
804
805 /*-----------------------------------------------------------------*/
806 /* emitStaticSeg - emitcode for the static segment                 */
807 /*-----------------------------------------------------------------*/
808 void emitStaticSeg(memmap * map, FILE *out)
809 {
810     symbol *sym;
811     
812     /*     fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
813     if (!out)
814         out = code->oFile;
815
816     /* for all variables in this segment do */
817     for (sym = setFirstItem (map->syms); sym;
818          sym = setNextItem (map->syms)) {
819         
820         /* if it is "extern" then do nothing */
821         if (IS_EXTERN (sym->etype))
822             continue;
823         
824         /* if it is not static add it to the public
825            table */
826         if (!IS_STATIC (sym->etype))
827             addSetHead (&publics, sym);
828
829         /* print extra debug info if required */
830         if ((options.debug || sym->level == 0) && !options.nodebug) {
831
832             cdbSymbol(sym,cdbFile,FALSE,FALSE);
833
834             if (!sym->level) { /* global */
835                 if (IS_STATIC(sym->etype))
836                     fprintf(out,"F%s$",moduleName); /* scope is file */
837                 else
838                     fprintf(out,"G$"); /* scope is global */
839             }
840             else
841                 /* symbol is local */
842                 fprintf(out,"L%s$",
843                         (sym->localof ? sym->localof->name : "-null-"));
844             fprintf(out,"%s$%d$%d",sym->name,sym->level,sym->block);
845         }
846         
847         /* if it has an absolute address */
848         if (SPEC_ABSA (sym->etype)) {
849             if ((options.debug || sym->level == 0) && !options.nodebug)
850                 fprintf(out," == 0x%04x\n", SPEC_ADDR (sym->etype));
851
852             fprintf (out, "%s\t=\t0x%04x\n",
853                      sym->rname,
854                      SPEC_ADDR (sym->etype));
855         }
856         else {
857             if ((options.debug || sym->level == 0) && !options.nodebug)
858                 fprintf(out," == .\n"); 
859
860             /* if it has an initial value */
861             if (sym->ival) {
862                 fprintf (out, "%s:\n", sym->rname);
863                 noAlloc++;
864                 resolveIvalSym (sym->ival);
865                 printIval (sym, sym->type, sym->ival, out);
866                 noAlloc--;
867             }
868             else {
869                 /* allocate space */
870                 fprintf (out, "%s:\n", sym->rname);
871                 /* special case for character strings */
872                 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
873                     SPEC_CVAL (sym->etype).v_char)
874                     printChar (out,
875                                SPEC_CVAL (sym->etype).v_char,
876                                strlen(SPEC_CVAL (sym->etype).v_char)+1);
877                 else 
878                     tfprintf(out, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
879             }
880         }
881     }
882 }
883
884 /*-----------------------------------------------------------------*/
885 /* emitMaps - emits the code for the data portion the code         */
886 /*-----------------------------------------------------------------*/
887 void emitMaps ()
888 {
889     /* no special considerations for the following
890        data, idata & bit & xdata */
891     emitRegularMap (data, TRUE, TRUE);
892     emitRegularMap (idata, TRUE,TRUE);
893     emitRegularMap (bit, TRUE,FALSE);
894     emitRegularMap (xdata, TRUE,TRUE);
895     emitRegularMap (sfr, FALSE,FALSE);
896     emitRegularMap (sfrbit, FALSE,FALSE);
897     emitRegularMap (home, TRUE,FALSE);
898     emitRegularMap (code, TRUE,FALSE);
899
900     emitStaticSeg (statsg, code->oFile);
901 }
902
903 /*-----------------------------------------------------------------*/
904 /* flushStatics - flush all currently defined statics out to file  */
905 /*  and delete.  Temporary function                                */
906 /*-----------------------------------------------------------------*/
907 void flushStatics(void)
908 {
909     emitStaticSeg(statsg, codeOutFile);
910     statsg->syms = NULL;
911 }
912
913 /*-----------------------------------------------------------------*/
914 /* createInterruptVect - creates the interrupt vector              */
915 /*-----------------------------------------------------------------*/
916 void createInterruptVect (FILE * vFile)
917 {
918     int i = 0;
919     mainf = newSymbol ("main", 0);
920     mainf->block = 0;
921     
922     /* only if the main function exists */
923     if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
924         if (!options.cc_only)
925             werror(E_NO_MAIN);
926         return;
927     }
928     
929     /* if the main is only a prototype ie. no body then do nothing */
930     if (!mainf->fbody) {
931         /* if ! compile only then main function should be present */
932         if (!options.cc_only)
933             werror(E_NO_MAIN);
934         return;
935     }
936     
937     tfprintf(vFile, "\t!areacode\n", CODE_NAME);
938     fprintf (vFile, "__interrupt_vect:\n");
939
940     
941     if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
942     {
943         /* "generic" interrupt table header (if port doesn't specify one).
944          *
945          * Look suspiciously like 8051 code to me...
946          */
947     
948         fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
949     
950     
951         /* now for the other interrupts */
952         for (; i < maxInterrupts; i++) {
953                 if (interrupts[i])
954                         fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
955                 else
956                         fprintf (vFile, "\treti\n\t.ds\t7\n");
957         }
958     }
959 }
960
961 char *iComments1 =
962 {
963     ";--------------------------------------------------------\n"
964     "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
965
966 char *iComments2 =
967 {
968     ";--------------------------------------------------------\n"};
969
970
971 /*-----------------------------------------------------------------*/
972 /* initialComments - puts in some initial comments                 */
973 /*-----------------------------------------------------------------*/
974 void initialComments (FILE * afile)
975 {
976     time_t t;
977     time(&t);
978     fprintf (afile, "%s", iComments1);
979     fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
980     fprintf (afile, "%s", iComments2);
981 }
982
983 /*-----------------------------------------------------------------*/
984 /* printPublics - generates .global for publics                    */
985 /*-----------------------------------------------------------------*/
986 void printPublics (FILE * afile)
987 {
988     symbol *sym;
989     
990     fprintf (afile, "%s", iComments2);
991     fprintf (afile, "; Public variables in this module\n");
992     fprintf (afile, "%s", iComments2);
993     
994     for (sym = setFirstItem (publics); sym;
995          sym = setNextItem (publics))
996         tfprintf(afile, "\t!global\n", sym->rname);
997 }
998
999 /*-----------------------------------------------------------------*/
1000 /* printExterns - generates .global for externs                    */
1001 /*-----------------------------------------------------------------*/
1002 void printExterns (FILE * afile)
1003 {
1004     symbol *sym;
1005     
1006     fprintf (afile, "%s", iComments2);
1007     fprintf (afile, "; Externals used\n");
1008     fprintf (afile, "%s", iComments2);
1009     
1010     for (sym = setFirstItem (externs); sym;
1011          sym = setNextItem (externs))
1012         tfprintf(afile, "\t!global\n", sym->rname);
1013 }
1014
1015 /*-----------------------------------------------------------------*/
1016 /* emitOverlay - will emit code for the overlay stuff              */
1017 /*-----------------------------------------------------------------*/
1018 static void emitOverlay(FILE *afile)
1019 {
1020     set *ovrset;
1021     
1022     if (!elementsInSet(ovrSetSets))
1023         tfprintf(afile,"\t!area\n", port->mem.overlay_name);
1024
1025     /* for each of the sets in the overlay segment do */
1026     for (ovrset = setFirstItem(ovrSetSets); ovrset;
1027          ovrset = setNextItem(ovrSetSets)) {
1028
1029         symbol *sym ;
1030
1031         if (elementsInSet(ovrset)) {
1032             /* this dummy area is used to fool the assembler
1033                otherwise the assembler will append each of these
1034                declarations into one chunk and will not overlay 
1035                sad but true */
1036             fprintf(afile,"\t.area _DUMMY\n");
1037             /* output the area informtion */
1038             fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1039         }
1040         
1041         for (sym = setFirstItem(ovrset); sym;
1042              sym = setNextItem(ovrset)) {
1043
1044             /* if extern then add it to the publics tabledo nothing */
1045             if (IS_EXTERN (sym->etype))
1046                 continue;
1047             
1048             /* if allocation required check is needed
1049                then check if the symbol really requires
1050                allocation only for local variables */
1051             if (!IS_AGGREGATE(sym->type) &&
1052                 !(sym->_isparm && !IS_REGPARM(sym->etype))
1053                 && !sym->allocreq && sym->level)
1054                 continue ;
1055             
1056             /* if global variable & not static or extern 
1057                and addPublics allowed then add it to the public set */
1058             if ((sym->_isparm && !IS_REGPARM(sym->etype))
1059                 && !IS_STATIC (sym->etype))
1060                 addSetHead (&publics, sym);
1061             
1062             /* if extern then do nothing or is a function 
1063                then do nothing */
1064             if (IS_FUNC (sym->type))
1065                 continue;
1066
1067             /* print extra debug info if required */
1068             if ((options.debug || sym->level == 0) && !options.nodebug) {
1069                 
1070                 cdbSymbol(sym,cdbFile,FALSE,FALSE);
1071                 
1072                 if (!sym->level) { /* global */
1073                     if (IS_STATIC(sym->etype))
1074                         fprintf(afile,"F%s$",moduleName); /* scope is file */
1075                     else
1076                         fprintf(afile,"G$"); /* scope is global */
1077                 }
1078                 else
1079                     /* symbol is local */
1080                     fprintf(afile,"L%s$",
1081                             (sym->localof ? sym->localof->name : "-null-"));
1082                 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
1083             }
1084             
1085             /* if is has an absolute address then generate
1086                an equate for this no need to allocate space */
1087             if (SPEC_ABSA (sym->etype)) {
1088                 
1089                 if ((options.debug || sym->level == 0) && !options.nodebug)
1090                     fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));          
1091
1092                 fprintf (afile, "%s\t=\t0x%04x\n",
1093                          sym->rname,
1094                          SPEC_ADDR (sym->etype));
1095             }
1096             else {
1097                 if ((options.debug || sym->level == 0) && !options.nodebug)
1098                     fprintf(afile,"==.\n");
1099         
1100                 /* allocate space */
1101                 tfprintf(afile, "!labeldef\n", sym->rname);
1102                 tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
1103             }
1104             
1105         }
1106     }
1107 }
1108
1109 /*-----------------------------------------------------------------*/
1110 /* glue - the final glue that hold the whole thing together        */
1111 /*-----------------------------------------------------------------*/
1112 void glue ()
1113 {
1114     FILE *vFile;
1115     FILE *asmFile;
1116     FILE *ovrFile = tempfile();
1117     
1118     addSetHead(&tmpfileSet,ovrFile);
1119     /* print the global struct definitions */
1120     if (options.debug && !options.nodebug)
1121         cdbStructBlock (0,cdbFile);
1122
1123     vFile = tempfile();
1124     /* PENDING: this isnt the best place but it will do */
1125     if (port->general.glue_up_main) {
1126         /* create the interrupt vector table */
1127         createInterruptVect (vFile);
1128     }
1129
1130     addSetHead(&tmpfileSet,vFile);
1131     
1132     /* emit code for the all the variables declared */
1133     emitMaps ();
1134     /* do the overlay segments */
1135     emitOverlay(ovrFile);
1136
1137     /* now put it all together into the assembler file */
1138     /* create the assembler file name */
1139     
1140     if (!options.c1mode) {
1141         sprintf (buffer, srcFileName);
1142         strcat (buffer, ".asm");
1143     }
1144     else {
1145         strcpy(buffer, options.out_name);
1146     }
1147
1148     if (!(asmFile = fopen (buffer, "w"))) {
1149         werror (E_FILE_OPEN_ERR, buffer);
1150         exit (1);
1151     }
1152     
1153     /* initial comments */
1154     initialComments (asmFile);
1155     
1156     /* print module name */
1157     tfprintf(asmFile, "\t!module\n", moduleName);
1158     tfprintf(asmFile, "\t!fileprelude\n");
1159
1160     /* Let the port generate any global directives, etc. */
1161     if (port->genAssemblerPreamble)
1162     {
1163         port->genAssemblerPreamble(asmFile);
1164     }
1165     
1166     /* print the global variables in this module */
1167     printPublics (asmFile);
1168     if (port->assembler.externGlobal)
1169         printExterns (asmFile);
1170
1171     /* copy the sfr segment */
1172     fprintf (asmFile, "%s", iComments2);
1173     fprintf (asmFile, "; special function registers\n");
1174     fprintf (asmFile, "%s", iComments2);
1175     copyFile (asmFile, sfr->oFile);
1176     
1177     /* copy the sbit segment */
1178     fprintf (asmFile, "%s", iComments2);
1179     fprintf (asmFile, "; special function bits \n");
1180     fprintf (asmFile, "%s", iComments2);
1181     copyFile (asmFile, sfrbit->oFile);
1182     
1183     /* copy the data segment */
1184     fprintf (asmFile, "%s", iComments2);
1185     fprintf (asmFile, "; internal ram data\n");
1186     fprintf (asmFile, "%s", iComments2);
1187     copyFile (asmFile, data->oFile);
1188
1189
1190     /* create the overlay segments */
1191     fprintf (asmFile, "%s", iComments2);
1192     fprintf (asmFile, "; overlayable items in internal ram \n");
1193     fprintf (asmFile, "%s", iComments2);    
1194     copyFile (asmFile, ovrFile);
1195
1196     /* create the stack segment MOF */
1197     if (mainf && mainf->fbody) {
1198         fprintf (asmFile, "%s", iComments2);
1199         fprintf (asmFile, "; Stack segment in internal ram \n");
1200         fprintf (asmFile, "%s", iComments2);
1201         fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1202                  "__start__stack:\n\t.ds\t1\n\n");
1203     }
1204
1205     /* create the idata segment */
1206     fprintf (asmFile, "%s", iComments2);
1207     fprintf (asmFile, "; indirectly addressable internal ram data\n");
1208     fprintf (asmFile, "%s", iComments2);
1209     copyFile (asmFile, idata->oFile);
1210     
1211     /* copy the bit segment */
1212     fprintf (asmFile, "%s", iComments2);
1213     fprintf (asmFile, "; bit data\n");
1214     fprintf (asmFile, "%s", iComments2);
1215     copyFile (asmFile, bit->oFile);
1216
1217     /* if external stack then reserve space of it */
1218     if (mainf && mainf->fbody && options.useXstack ) {
1219         fprintf (asmFile, "%s", iComments2);
1220         fprintf (asmFile, "; external stack \n");
1221         fprintf (asmFile, "%s", iComments2);
1222         fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
1223         fprintf (asmFile,"\t.ds 256\n");
1224     }
1225         
1226         
1227     /* copy xtern ram data */
1228     fprintf (asmFile, "%s", iComments2);
1229     fprintf (asmFile, "; external ram data\n");
1230     fprintf (asmFile, "%s", iComments2);
1231     copyFile (asmFile, xdata->oFile);
1232     
1233     /* copy the interrupt vector table */
1234     if (mainf && mainf->fbody) {
1235         fprintf (asmFile, "%s", iComments2);
1236         fprintf (asmFile, "; interrupt vector \n");
1237         fprintf (asmFile, "%s", iComments2);
1238         copyFile (asmFile, vFile);
1239     }
1240     
1241     /* copy global & static initialisations */
1242     fprintf (asmFile, "%s", iComments2);
1243     fprintf (asmFile, "; global & static initialisations\n");
1244     fprintf (asmFile, "%s", iComments2);
1245     
1246     /* Everywhere we generate a reference to the static_name area, 
1247      * (which is currently only here), we immediately follow it with a 
1248      * definition of the post_static_name area. This guarantees that
1249      * the post_static_name area will immediately follow the static_name
1250      * area.
1251      */
1252     tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1253     tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1254     tfprintf(asmFile, "\t!area\n", port->mem.static_name);
1255     
1256     if (mainf && mainf->fbody) {
1257         fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1258         /* if external stack is specified then the
1259            higher order byte of the xdatalocation is
1260            going into P2 and the lower order going into
1261            spx */
1262         if (options.useXstack) {
1263             fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1264                     (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1265             fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1266                     (unsigned int)options.xdata_loc & 0xff);
1267         }
1268
1269         /* initialise the stack pointer */
1270         /* if the user specified a value then use it */
1271         if (options.stack_loc) 
1272             fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1273         else 
1274             /* no: we have to compute it */
1275             if (!options.stackOnData && maxRegBank <= 3)
1276                 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1); 
1277             else
1278                 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1279
1280         fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1281         fprintf (asmFile,"\tmov\ta,dpl\n");
1282         fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1283         fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1284         fprintf (asmFile,"__sdcc_init_data:\n");
1285         
1286     }
1287     copyFile (asmFile, statsg->oFile);
1288
1289     if (port->general.glue_up_main && mainf && mainf->fbody)
1290     {
1291         /* This code is generated in the post-static area.
1292          * This area is guaranteed to follow the static area
1293          * by the ugly shucking and jiving about 20 lines ago.
1294          */
1295         tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1296         fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1297     }
1298
1299     fprintf (asmFile,
1300              "%s"
1301              "; Home\n"
1302              "%s", iComments2, iComments2);
1303     tfprintf(asmFile, "\t!areahome\n", HOME_NAME);
1304     copyFile (asmFile, home->oFile);
1305
1306     /* copy over code */
1307     fprintf (asmFile, "%s", iComments2);
1308     fprintf (asmFile, "; code\n");
1309     fprintf (asmFile, "%s", iComments2);
1310     tfprintf(asmFile, "\t!areacode\n", CODE_NAME);
1311     if (mainf && mainf->fbody) {
1312         
1313         /* entry point @ start of CSEG */
1314         fprintf (asmFile,"__sdcc_program_startup:\n");
1315         
1316         /* put in the call to main */
1317         fprintf(asmFile,"\tlcall\t_main\n");
1318         if (options.mainreturn) {
1319
1320             fprintf(asmFile,";\treturn from main ; will return to caller\n");
1321             fprintf(asmFile,"\tret\n");
1322
1323         } else {
1324                    
1325             fprintf(asmFile,";\treturn from main will lock up\n");
1326             fprintf(asmFile,"\tsjmp     .\n");
1327         }
1328     }
1329     copyFile (asmFile, code->oFile);
1330     
1331     fclose (asmFile);
1332     applyToSet(tmpfileSet,closeTmpFiles);
1333     applyToSet(tmpfileNameSet, rmTmpFiles);
1334 }
1335
1336 /** Creates a temporary file a'la tmpfile which avoids the bugs
1337     in cygwin wrt c:\tmp.
1338     Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1339 */
1340 FILE *tempfile(void)
1341 {
1342     const char *tmpdir = NULL;
1343     if (getenv("TMP"))
1344         tmpdir = getenv("TMP");
1345     else if (getenv("TEMP"))
1346         tmpdir = getenv("TEMP");
1347     else if (getenv("TMPDIR"))
1348         tmpdir = getenv("TMPDIR");
1349     if (tmpdir) {
1350         char *name = tempnam(tmpdir, "sdcc");
1351         if (name) {
1352             FILE *fp = fopen(name, "w+b");
1353             if (fp)
1354             {
1355                 addSetHead(&tmpfileNameSet, name);
1356             }
1357             return fp;
1358         }
1359         return NULL;
1360     }
1361     return tmpfile();
1362 }
1363
1364 char *gc_strdup(const char *s)
1365 {
1366     char *ret;
1367     ALLOC_ATOMIC(ret, strlen(s)+1);
1368     strcpy(ret, s);
1369     return ret;
1370 }