625ea1036ee262e97cf580c16fc94afb1c1bbb97
[fw/sdcc] / src / z80 / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   
7          This program is free software; you can redistribute it and/or modify it
8          under the terms of the GNU General Public License as published by the
9          Free Software Foundation; either version 2, or (at your option) any
10          later version.
11          
12          This program is distributed in the hope that it will be useful,
13          but WITHOUT ANY WARRANTY; without even the implied warranty of
14          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15          GNU General Public License for more details.
16          
17          You should have received a copy of the GNU General Public License
18          along with this program; if not, write to the Free Software
19          Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20          
21          In other words, you are welcome to use, share and improve this program.
22          You are forbidden to forbid anyone else to use, share and improve
23          what you give them.   Help stamp out software-hoarding!
24
25 -------------------------------------------------------------------------*/
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include "SDCCglobl.h"
32
33 #ifdef HAVE_SYS_ISA_DEFS_H
34 #include <sys/isa_defs.h>
35 #endif
36
37 #include "SDCCast.h"
38 #include "SDCCmem.h"
39 #include "SDCCy.h"
40 #include "SDCChasht.h"
41 #include "SDCCbitv.h"
42 #include "SDCCset.h"
43 #include "SDCCicode.h"
44 #include "SDCClabel.h"
45 #include "SDCCBBlock.h"
46 #include "SDCCloop.h"
47 #include "SDCCcse.h"
48 #include "SDCCcflow.h"
49 #include "SDCCdflow.h"
50 #include "SDCClrange.h"
51 #include "ralloc.h"
52 #include "gen.h"
53 #include "SDCCpeeph.h"
54 #include "SDCCglue.h" /* drdani Jan 30 2000 */
55
56 /* this is the down and dirty file with all kinds of kludgy & hacky
57    stuff. This is what it is all about CODE GENERATION for a specific MCU.
58    Some of the routines may be reusable, will have to see */
59
60 static char *zero = "#0x00";
61 static char *one  = "#0x01";
62 static char *spname ;
63 static char *fReturn[] = {"l", "h", "e", "d" };
64 static char *accUse[] = {"a" };
65 short rbank = -1;
66 short accInUse = 0 ;
67 short inLine = 0;
68 short debugLine = 0;
69 short nregssaved = 0;
70 extern int ptrRegReq ;
71 extern int nRegs;
72 extern FILE *codeOutFile;
73 set *sendSet = NULL;
74 #define RESULTONSTACK(x) \
75                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
76                          IC_RESULT(x)->aop->type == AOP_STK )
77
78 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
79 #define CLRC    emitcode("xor","a,a");
80
81 #define LABEL_STR       "%05d$"
82
83 lineNode *lineHead = NULL;
84 lineNode *lineCurr = NULL;
85
86 unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
87 0xE0, 0xC0, 0x80, 0x00};
88 unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
89 0x07, 0x03, 0x01, 0x00};
90
91 static int _lastStack = 0;
92
93 #define LSB     0
94 #define MSB16   1
95 #define MSB24   2
96 #define MSB32   3
97
98 /* Stack frame:
99
100    IX+4         param0  LH
101    IX+2         ret     LH
102    IX+0         ix      LH
103    IX-2         temp0   LH
104 */
105
106 /*-----------------------------------------------------------------*/
107 /* emitcode - writes the code into a file : for now it is simple    */
108 /*-----------------------------------------------------------------*/
109 void emitcode (const char *inst, const char *fmt, ...)
110 {
111     va_list ap;
112     char lb[MAX_INLINEASM];  
113     char *lbp = lb;
114
115     va_start(ap,fmt);   
116
117     if (*inst != '\0') {
118         sprintf(lb,"%s\t",inst);
119         vsprintf(lb+(strlen(lb)),fmt,ap);
120     }  else 
121         vsprintf(lb,fmt,ap);
122
123     while (isspace(*lbp)) lbp++;
124
125     if (lbp && *lbp) 
126         lineCurr = (lineCurr ?
127                     connectLine(lineCurr,newLineNode(lb)) :
128                     (lineHead = newLineNode(lb)));
129     lineCurr->isInline = inLine;
130     lineCurr->isDebug  = debugLine;
131     va_end(ap);
132 }
133
134 const char *getPairName(asmop *aop)
135 {
136     if (aop->type == AOP_REG) {
137         switch (aop->aopu.aop_reg[0]->rIdx) {
138         case C_IDX:
139             return "bc";
140             break;
141         case E_IDX:
142             return "de";
143             break;
144         case L_IDX:
145             return "hl";
146             break;
147         }
148     }
149     else if (aop->type == AOP_STR) {
150         switch (*aop->aopu.aop_str[0]) {
151         case 'c':
152             return "bc";
153             break;
154         case 'e':
155             return "de";
156             break;
157         case 'l':
158             return "hl";
159             break;
160         }
161     }
162     assert(0);
163     return NULL;
164 }
165
166 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
167 bool isPair(asmop *aop)
168 {
169     if (aop->size == 2) {
170         if (aop->type == AOP_REG) {
171             if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
172                 return TRUE;
173             }
174             if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
175                 return TRUE;
176             }
177             if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
178                 return TRUE;
179             }
180         }
181         if (aop->type == AOP_STR) {
182             if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
183                 return TRUE;
184             }
185             if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
186                 return TRUE;
187             }
188             if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
189                 return TRUE;
190             }
191         }
192     }
193     return FALSE;
194 }
195
196 /** Push a register pair onto the stack */
197 void genPairPush(asmop *aop)
198 {
199     emitcode("push", "%s", getPairName(aop));
200 }
201
202 /*-----------------------------------------------------------------*/
203 /* newAsmop - creates a new asmOp                                  */
204 /*-----------------------------------------------------------------*/
205 static asmop *newAsmop (short type)
206 {
207     asmop *aop;
208
209     ALLOC(aop,sizeof(asmop));
210     aop->type = type;
211     return aop;
212 }
213
214 /*-----------------------------------------------------------------*/
215 /* aopForSym - for a true symbol                                   */
216 /*-----------------------------------------------------------------*/
217 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
218 {
219     asmop *aop;
220     memmap *space= SPEC_OCLS(sym->etype);
221
222     /* if already has one */
223     if (sym->aop)
224         return sym->aop;
225
226     /* Assign depending on the storage class */
227     if (sym->onStack || sym->iaccess) {
228         sym->aop = aop = newAsmop(AOP_STK);
229         aop->size = getSize(sym->type);
230
231         aop->aopu.aop_stk = sym->stack;
232         return aop;
233     }
234
235     /* special case for a function */
236     if (IS_FUNC(sym->type)) {   
237         sym->aop = aop = newAsmop(AOP_IMMD);    
238         ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
239         strcpy(aop->aopu.aop_immd,sym->rname);
240         aop->size = 2;
241         return aop;
242     }
243
244     /* only remaining is far space */
245     /* in which case DPTR gets the address */
246     sym->aop = aop = newAsmop(AOP_IY);
247     emitcode ("ld","iy,#%s", sym->rname);
248     aop->size = getSize(sym->type);
249     aop->aopu.aop_dir = sym->rname;
250
251     /* if it is in code space */
252     if (IN_CODESPACE(space))
253         aop->code = 1;
254
255     return aop;     
256 }
257
258 /*-----------------------------------------------------------------*/
259 /* aopForRemat - rematerialzes an object                           */
260 /*-----------------------------------------------------------------*/
261 static asmop *aopForRemat (symbol *sym)
262 {
263     char *s = buffer;   
264     iCode *ic = sym->rematiCode;
265     asmop *aop = newAsmop(AOP_IMMD);
266
267     while (1) {
268         /* if plus or minus print the right hand side */
269         if (ic->op == '+' || ic->op == '-') {
270             sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
271                     ic->op );
272             s += strlen(s);
273             ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
274             continue ;
275         }
276         /* we reached the end */
277         sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
278         break;
279     }
280
281     ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
282     strcpy(aop->aopu.aop_immd,buffer);    
283     return aop;        
284 }
285
286 /*-----------------------------------------------------------------*/
287 /* regsInCommon - two operands have some registers in common       */
288 /*-----------------------------------------------------------------*/
289 bool regsInCommon (operand *op1, operand *op2)
290 {
291     symbol *sym1, *sym2;
292     int i;
293
294     /* if they have registers in common */
295     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
296         return FALSE ;
297
298     sym1 = OP_SYMBOL(op1);
299     sym2 = OP_SYMBOL(op2);
300
301     if (sym1->nRegs == 0 || sym2->nRegs == 0)
302         return FALSE ;
303
304     for (i = 0 ; i < sym1->nRegs ; i++) {
305         int j;
306         if (!sym1->regs[i])
307             continue ;
308
309         for (j = 0 ; j < sym2->nRegs ;j++ ) {
310             if (!sym2->regs[j])
311                 continue ;
312
313             if (sym2->regs[j] == sym1->regs[i])
314                 return TRUE ;
315         }
316     }
317
318     return FALSE ;
319 }
320
321 /*-----------------------------------------------------------------*/
322 /* operandsEqu - equivalent                                        */
323 /*-----------------------------------------------------------------*/
324 bool operandsEqu ( operand *op1, operand *op2)
325 {
326     symbol *sym1, *sym2;
327
328     /* if they not symbols */
329     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
330         return FALSE;
331
332     sym1 = OP_SYMBOL(op1);
333     sym2 = OP_SYMBOL(op2);
334
335     /* if both are itemps & one is spilt
336        and the other is not then false */
337     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
338         sym1->isspilt != sym2->isspilt )
339         return FALSE ;
340
341     /* if they are the same */
342     if (sym1 == sym2)
343         return 1;
344
345     if (strcmp(sym1->rname,sym2->rname) == 0)
346         return 2;
347
348
349     /* if left is a tmp & right is not */
350     if (IS_ITEMP(op1)  && 
351         !IS_ITEMP(op2) &&
352         sym1->isspilt  &&
353         (sym1->usl.spillLoc == sym2))
354         return 3;
355
356     if (IS_ITEMP(op2)  && 
357         !IS_ITEMP(op1) &&
358         sym2->isspilt  &&
359         sym1->level > 0 &&
360         (sym2->usl.spillLoc == sym1))
361         return 4;
362
363     return FALSE;
364 }
365
366 /*-----------------------------------------------------------------*/
367 /* sameRegs - two asmops have the same registers                   */
368 /*-----------------------------------------------------------------*/
369 bool sameRegs (asmop *aop1, asmop *aop2 )
370 {
371     int i;
372
373     if (aop1 == aop2)
374         return TRUE ;
375
376     if (aop1->type != AOP_REG ||
377         aop2->type != AOP_REG )
378         return FALSE ;
379
380     if (aop1->size != aop2->size)
381         return FALSE ;
382
383     for (i = 0 ; i < aop1->size ; i++ )
384         if (aop1->aopu.aop_reg[i] !=
385             aop2->aopu.aop_reg[i] )
386             return FALSE ;
387
388     return TRUE ;
389 }
390
391 /*-----------------------------------------------------------------*/
392 /* aopOp - allocates an asmop for an operand  :                    */
393 /*-----------------------------------------------------------------*/
394 static void aopOp (operand *op, iCode *ic, bool result)
395 {
396     asmop *aop;
397     symbol *sym;
398     int i;
399
400     if (!op)
401         return ;
402
403     /* if this a literal */
404     if (IS_OP_LITERAL(op)) {
405         op->aop = aop = newAsmop(AOP_LIT);
406         aop->aopu.aop_lit = op->operand.valOperand;
407         aop->size = getSize(operandType(op));
408         return;
409     }
410
411     /* if already has a asmop then continue */
412     if (op->aop)
413         return ;
414
415     /* if the underlying symbol has a aop */
416     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
417         op->aop = OP_SYMBOL(op)->aop;
418         return;
419     }
420
421     /* if this is a true symbol */
422     if (IS_TRUE_SYMOP(op)) {    
423         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
424         return ;
425     }
426
427     /* this is a temporary : this has
428     only four choices :
429     a) register
430     b) spillocation
431     c) rematerialize 
432     d) conditional   
433     e) can be a return use only */
434
435     sym = OP_SYMBOL(op);
436
437     /* if the type is a conditional */
438     if (sym->regType == REG_CND) {
439         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
440         aop->size = 0;
441         return;
442     }
443
444     /* if it is spilt then two situations
445     a) is rematerialize 
446     b) has a spill location */
447     if (sym->isspilt || sym->nRegs == 0) {
448         /* rematerialize it NOW */
449         if (sym->remat) {
450             sym->aop = op->aop = aop =
451                                       aopForRemat (sym);
452             aop->size = getSize(sym->type);
453             return;
454         }
455
456         if (sym->accuse) {
457             int i;
458             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
459             aop->size = getSize(sym->type);
460             for ( i = 0 ; i < 2 ; i++ )
461                 aop->aopu.aop_str[i] = accUse[i];
462             return;  
463         }
464
465         if (sym->ruonly ) {
466             int i;
467             aop = op->aop = sym->aop = newAsmop(AOP_STR);
468             aop->size = getSize(sym->type);
469             for ( i = 0 ; i < 4 ; i++ )
470                 aop->aopu.aop_str[i] = fReturn[i];
471             return;
472         }
473
474         /* else spill location  */
475         sym->aop = op->aop = aop = 
476                                   aopForSym(ic,sym->usl.spillLoc,result);
477         aop->size = getSize(sym->type);
478         return;
479     }
480
481     /* must be in a register */
482     sym->aop = op->aop = aop = newAsmop(AOP_REG);
483     aop->size = sym->nRegs;
484     for ( i = 0 ; i < sym->nRegs ;i++)
485         aop->aopu.aop_reg[i] = sym->regs[i];
486 }
487
488 /*-----------------------------------------------------------------*/
489 /* freeAsmop - free up the asmop given to an operand               */
490 /*----------------------------------------------------------------*/
491 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
492 {   
493     asmop *aop ;
494
495     if (!op)
496         aop = aaop;
497     else 
498         aop = op->aop;
499
500     if (!aop)
501         return ;
502
503     if (aop->freed)
504         goto dealloc; 
505
506     aop->freed = 1;
507
508     switch (aop->type) {
509     case AOP_STK :
510         break;
511     }
512
513 dealloc:
514     /* all other cases just dealloc */
515     if (op ) {
516         op->aop = NULL;
517         if (IS_SYMOP(op)) {
518             OP_SYMBOL(op)->aop = NULL;    
519             /* if the symbol has a spill */
520             if (SPIL_LOC(op))
521                 SPIL_LOC(op)->aop = NULL;
522         }
523     }
524 }
525
526 char *aopGetWord(asmop *aop, int offset)
527 {
528     char *s = buffer ;
529     char *rs;
530
531     assert(aop->size == 2);
532     assert(offset == 0);
533
534     /* depending on type */
535     switch (aop->type) {
536     case AOP_IMMD:
537         sprintf (s,"#%s",aop->aopu.aop_immd);
538         ALLOC_ATOMIC(rs,strlen(s)+1);
539         strcpy(rs,s);   
540         return rs;
541         
542     case AOP_LIT: {
543         value * val = aop->aopu.aop_lit;
544         /* if it is a float then it gets tricky */
545         /* otherwise it is fairly simple */
546         if (!IS_FLOAT(val->type)) {
547             unsigned long v = floatFromVal(val);
548
549             sprintf(buffer,"#0x%04lx", v);
550             ALLOC_ATOMIC(rs,strlen(buffer)+1);
551             return strcpy (rs,buffer);
552         }
553         assert(0);
554         return NULL;
555     }
556     }
557     return NULL;
558 }
559
560 /*-----------------------------------------------------------------*/
561 /* aopGet - for fetching value of the aop                          */
562 /*-----------------------------------------------------------------*/
563 static char *aopGet (asmop *aop, int offset, bool bit16)
564 {
565     char *s = buffer ;
566     char *rs;
567
568     /* offset is greater than size then zero */
569     if (offset > (aop->size - 1) &&
570         aop->type != AOP_LIT)
571         return zero;
572
573     /* depending on type */
574     switch (aop->type) {
575     case AOP_IMMD:
576         if (bit16) 
577             sprintf (s,"#%s",aop->aopu.aop_immd);
578         else
579             if (offset) {
580                 assert(offset == 1);
581                 sprintf(s,"#>%s",
582                         aop->aopu.aop_immd);
583             }
584             else
585                 sprintf(s,"#<%s",
586                         aop->aopu.aop_immd);
587         ALLOC_ATOMIC(rs,strlen(s)+1);
588         strcpy(rs,s);   
589         return rs;
590         
591     case AOP_DIR:
592         assert(0);
593         emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
594         sprintf(s, "a");
595         ALLOC_ATOMIC(rs,strlen(s)+1);
596         strcpy(rs,s);   
597         return rs;
598         
599     case AOP_REG:
600         return aop->aopu.aop_reg[offset]->name;
601
602     case AOP_IY:
603         sprintf(s,"%d(iy)", offset);
604         ALLOC_ATOMIC(rs,strlen(s)+1);
605         strcpy(rs,s);   
606         return rs;
607
608     case AOP_STK:
609         sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
610         ALLOC_ATOMIC(rs,strlen(s)+1);
611         strcpy(rs,s);   
612         return rs;
613         
614     case AOP_CRY:
615         assert(0);
616         
617     case AOP_ACC:
618         if (!offset) {
619             return "a";
620         }
621         return "#0x00";
622
623     case AOP_LIT:
624         return aopLiteral (aop->aopu.aop_lit,offset);
625         
626     case AOP_STR:
627         aop->coff = offset;
628         return aop->aopu.aop_str[offset];
629     }
630
631     fprintf(stderr, "Type %u\n", aop->type);
632
633     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
634            "aopget got unsupported aop->type");
635     exit(0);
636 }
637
638 bool isRegString(char *s)
639 {
640     if (!strcmp(s, "b") ||
641         !strcmp(s, "c") ||
642         !strcmp(s, "d") ||
643         !strcmp(s, "e") ||
644         !strcmp(s, "a") ||
645         !strcmp(s, "h") ||
646         !strcmp(s, "l"))
647         return TRUE;
648     return FALSE;
649 }
650
651 bool isConstant(char *s)
652 {
653     return  (*s == '#');
654 }
655
656 bool canAssignToPtr(char *s)
657 {
658     if (isRegString(s))
659         return TRUE;
660     if (isConstant(s))
661         return TRUE;
662     return FALSE;
663 }
664
665 /*-----------------------------------------------------------------*/
666 /* aopPut - puts a string for a aop                                */
667 /*-----------------------------------------------------------------*/
668 static void aopPut (asmop *aop, char *s, int offset)
669 {
670     char *d = buffer ;
671
672     if (aop->size && offset > ( aop->size - 1)) {
673         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
674                "aopPut got offset > aop->size");
675         exit(0);
676     }
677
678     /* will assign value to value */
679     /* depending on where it is ofcourse */
680     switch (aop->type) {
681     case AOP_DIR:
682         assert(0);
683         /* Direct.  Hmmm. */
684         emitcode("ld", "a,%s", s);
685         emitcode("ld", "(%s+%d),a", d, offset);
686         break;
687         
688     case AOP_REG:
689         /* Dont bother if it's a ld x,x */
690         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
691             emitcode("ld","%s,%s",
692                      aop->aopu.aop_reg[offset]->name,s);
693         }
694         break;
695         
696     case AOP_IY:
697         if (!canAssignToPtr(s)) {
698             emitcode("ld", "a,%s", s);
699             emitcode("ld", "%d(iy),a", offset);
700         }
701         else
702             emitcode("ld", "%d(iy),%s", offset, s);
703         break;
704         
705     case AOP_STK:
706         if (!canAssignToPtr(s)) {
707             emitcode("ld", "a,%s", s);
708             emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
709         }
710         else
711             emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
712         break;
713         
714     case AOP_CRY:
715         /* if bit variable */
716         if (!aop->aopu.aop_dir) {
717             emitcode("ld", "a,#0");
718             emitcode("rla", "");
719         } else {
720             /* In bit space but not in C - cant happen */
721             assert(0);
722         }
723         break;
724         
725     case AOP_STR:
726         aop->coff = offset;
727         if (strcmp(aop->aopu.aop_str[offset],s)) {
728             emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
729         }
730         break;
731         
732     case AOP_ACC:
733         aop->coff = offset;
734         if (!offset && (strcmp(s,"acc") == 0))
735             break;
736         if (offset>0) {
737             emitcode("", "; Error aopPut AOP_ACC");
738         }
739         else {
740             if (strcmp(aop->aopu.aop_str[offset],s))
741                 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
742         }
743         break;
744
745     default :
746         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
747                "aopPut got unsupported aop->type");
748         exit(0);    
749     }    
750 }
751
752 #define AOP(op) op->aop
753 #define AOP_TYPE(op) AOP(op)->type
754 #define AOP_SIZE(op) AOP(op)->size
755 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
756
757 /*-----------------------------------------------------------------*/
758 /* getDataSize - get the operand data size                         */
759 /*-----------------------------------------------------------------*/
760 int getDataSize(operand *op)
761 {
762     int size;
763     size = AOP_SIZE(op);
764     if(size == 3) {
765         /* pointer */
766         assert(0);
767     }
768     return size;
769 }
770
771 /*-----------------------------------------------------------------*/
772 /* movLeft2Result - move byte from left to result                  */
773 /*-----------------------------------------------------------------*/
774 static void movLeft2Result (operand *left, int offl,
775                             operand *result, int offr, int sign)
776 {
777     char *l;
778     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
779         l = aopGet(AOP(left),offl,FALSE);
780
781         if (!sign) {
782             aopPut(AOP(result),l,offr);
783         }
784         else {
785             assert(0);
786         }
787     }
788 }
789
790
791 /** Put Acc into a register set 
792  */
793 void outAcc(operand *result)
794 {
795     int size, offset;
796     size = getDataSize(result);
797     if (size){
798         aopPut(AOP(result),"a",0);
799         size--;
800         offset = 1;
801         /* unsigned or positive */
802         while (size--){
803             aopPut(AOP(result),zero,offset++);
804         }
805     }
806 }
807
808 /** Take the value in carry and put it into a register
809  */
810 void outBitC(operand *result)
811 {
812     /* if the result is bit */
813     if (AOP_TYPE(result) == AOP_CRY) {
814         emitcode("", "; Note: outBitC form 1");
815         aopPut(AOP(result),"blah",0);
816     }
817     else {
818         emitcode("ld", "a,#0");
819         emitcode("rla", "");
820         outAcc(result);
821     }
822 }
823
824 /*-----------------------------------------------------------------*/
825 /* toBoolean - emit code for orl a,operator(sizeop)                */
826 /*-----------------------------------------------------------------*/
827 void toBoolean(operand *oper)
828 {
829     int size = AOP_SIZE(oper);
830     int offset = 0;
831     if (size>1) {
832         emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
833         size--;
834         while (size--) 
835             emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
836     }
837     else {
838         CLRC;
839         emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
840     }
841 }
842
843 /*-----------------------------------------------------------------*/
844 /* genNot - generate code for ! operation                          */
845 /*-----------------------------------------------------------------*/
846 static void genNot (iCode *ic)
847 {
848     link *optype = operandType(IC_LEFT(ic));
849
850     /* assign asmOps to operand & result */
851     aopOp (IC_LEFT(ic),ic,FALSE);
852     aopOp (IC_RESULT(ic),ic,TRUE);
853
854     /* if in bit space then a special case */
855     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
856         assert(0);
857     }
858
859     /* if type float then do float */
860     if (IS_FLOAT(optype)) {
861         assert(0);
862     }
863
864     toBoolean(IC_LEFT(ic));
865
866     /* Not of A:
867        If A == 0, !A = 1
868        else A = 0
869        So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
870     emitcode("sub", "a,#0x01");
871     outBitC(IC_RESULT(ic));
872
873     /* release the aops */
874     freeAsmop(IC_LEFT(ic),NULL,ic);
875     freeAsmop(IC_RESULT(ic),NULL,ic);
876 }
877
878 /*-----------------------------------------------------------------*/
879 /* genCpl - generate code for complement                           */
880 /*-----------------------------------------------------------------*/
881 static void genCpl (iCode *ic)
882 {
883     int offset = 0;
884     int size ;
885
886
887     /* assign asmOps to operand & result */
888     aopOp (IC_LEFT(ic),ic,FALSE);
889     aopOp (IC_RESULT(ic),ic,TRUE);
890
891     /* if both are in bit space then 
892     a special case */
893     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
894         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
895         assert(0);
896     } 
897
898     size = AOP_SIZE(IC_RESULT(ic));
899     while (size--) {
900         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
901         MOVA(l);       
902         emitcode("cpl","");
903         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
904     }
905
906     /* release the aops */
907     freeAsmop(IC_LEFT(ic),NULL,ic);
908     freeAsmop(IC_RESULT(ic),NULL,ic);
909 }
910
911 /*-----------------------------------------------------------------*/
912 /* genUminus - unary minus code generation                         */
913 /*-----------------------------------------------------------------*/
914 static void genUminus (iCode *ic)
915 {
916     assert(0);
917 }
918
919
920 /*-----------------------------------------------------------------*/
921 /* assignResultValue -                                             */
922 /*-----------------------------------------------------------------*/
923 void assignResultValue(operand * oper)
924 {
925     int offset = 0;
926     int size = AOP_SIZE(oper);
927     while (size--) {
928         aopPut(AOP(oper),fReturn[offset],offset);
929         offset++;
930     }
931 }
932
933 /*-----------------------------------------------------------------*/
934 /* genIpush - genrate code for pushing this gets a little complex  */
935 /*-----------------------------------------------------------------*/
936 static void genIpush (iCode *ic)
937 {
938     int size, offset = 0 ;
939     char *l;
940
941
942     /* if this is not a parm push : ie. it is spill push 
943        and spill push is always done on the local stack */
944     if (!ic->parmPush) {
945         /* and the item is spilt then do nothing */
946         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
947             return ;
948
949         aopOp(IC_LEFT(ic),ic,FALSE);
950         size = AOP_SIZE(IC_LEFT(ic));
951         /* push it on the stack */
952         if (isPair(AOP(IC_LEFT(ic)))) {
953             emitcode("push", getPairName(AOP(IC_LEFT(ic))));
954         }
955         else {
956             offset = size;
957             while (size--) {
958                 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
959                 /* Simple for now - load into A and PUSH AF */
960                 emitcode("ld", "a,%s", l);
961                 emitcode("push", "af");
962                 emitcode("inc", "sp");
963             }
964         }
965         return ;        
966     }
967
968     /* Hmmm... what about saving the currently used registers
969        at this point? */
970
971     /* then do the push */
972     aopOp(IC_LEFT(ic),ic,FALSE);
973
974     size = AOP_SIZE(IC_LEFT(ic));
975
976     if (isPair(AOP(IC_LEFT(ic)))) {
977         emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
978     }
979     else {
980         if (size == 2) {
981             char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
982             if (s) {
983                 emitcode("ld", "hl,%s", s);
984                 emitcode("push", "hl");
985                 goto release;
986             }
987         }
988         offset = size;
989         while (size--) {
990             l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
991             emitcode("ld", "a,%s", l);
992             emitcode("push", "af");
993             emitcode("inc", "sp");
994         }       
995     }
996  release:
997     freeAsmop(IC_LEFT(ic),NULL,ic);
998 }
999
1000 /*-----------------------------------------------------------------*/
1001 /* genIpop - recover the registers: can happen only for spilling   */
1002 /*-----------------------------------------------------------------*/
1003 static void genIpop (iCode *ic)
1004 {
1005     int size,offset ;
1006
1007
1008     /* if the temp was not pushed then */
1009     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1010         return ;
1011
1012     aopOp(IC_LEFT(ic),ic,FALSE);
1013     size = AOP_SIZE(IC_LEFT(ic));
1014     offset = (size-1);
1015     if (isPair(AOP(IC_LEFT(ic)))) {
1016         emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1017     }
1018     else {
1019         while (size--) {
1020             emitcode("dec", "sp");
1021             emitcode("pop", "hl");
1022             aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1023         }
1024     }
1025
1026     freeAsmop(IC_LEFT(ic),NULL,ic);
1027 }
1028
1029 /** Emit the code for a call statement 
1030  */
1031 static void emitCall (iCode *ic, bool ispcall)
1032 {
1033     /* if caller saves & we have not saved then */
1034     if (!ic->regsSaved) {
1035         /* PENDING */
1036     }
1037
1038     /* if send set is not empty then assign */
1039     if (sendSet) {
1040         iCode *sic ;
1041
1042         for (sic = setFirstItem(sendSet) ; sic ; 
1043              sic = setNextItem(sendSet)) {
1044             int size, offset = 0;
1045             aopOp(IC_LEFT(sic),sic,FALSE);
1046             size = AOP_SIZE(IC_LEFT(sic));
1047             while (size--) {
1048                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1049                                 FALSE);
1050                 if (strcmp(l,fReturn[offset]))
1051                     emitcode("ld","%s,%s",
1052                              fReturn[offset],
1053                              l);
1054                 offset++;
1055             }
1056             freeAsmop (IC_LEFT(sic),NULL,sic);
1057         }
1058         sendSet = NULL;
1059     }
1060
1061     if (ispcall) {
1062         symbol *rlbl = newiTempLabel(NULL);
1063
1064         emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1065         emitcode("push", "hl");
1066
1067         aopOp(IC_LEFT(ic),ic,FALSE);
1068         emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
1069         emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
1070         freeAsmop(IC_LEFT(ic),NULL,ic); 
1071         
1072         emitcode("jp", "(hl)");
1073         emitcode("","%05d$:",(rlbl->key+100));
1074     }
1075     else {
1076         /* make the call */
1077         emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1078                                 OP_SYMBOL(IC_LEFT(ic))->rname :
1079                                 OP_SYMBOL(IC_LEFT(ic))->name));
1080     }
1081
1082     /* if we need assign a result value */
1083     if ((IS_ITEMP(IC_RESULT(ic)) && 
1084          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1085           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1086         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1087
1088         accInUse++;
1089         aopOp(IC_RESULT(ic),ic,FALSE);
1090         accInUse--;
1091
1092         assignResultValue(IC_RESULT(ic));
1093                 
1094         freeAsmop(IC_RESULT(ic),NULL, ic);
1095     }
1096
1097     /* adjust the stack for parameters if required */
1098     if (IC_LEFT(ic)->parmBytes) {
1099         int i = IC_LEFT(ic)->parmBytes;
1100         /* PENDING: do better */
1101         while (i>1) {
1102             emitcode("pop", "hl");
1103             i-=2;
1104         }
1105         if (i) 
1106             emitcode("inc", "sp");
1107     }
1108
1109 }
1110
1111 /*-----------------------------------------------------------------*/
1112 /* genCall - generates a call statement                            */
1113 /*-----------------------------------------------------------------*/
1114 static void genCall (iCode *ic)
1115 {
1116     emitCall(ic, FALSE);
1117 }
1118
1119 /*-----------------------------------------------------------------*/
1120 /* genPcall - generates a call by pointer statement                */
1121 /*-----------------------------------------------------------------*/
1122 static void genPcall (iCode *ic)
1123 {
1124     emitCall(ic, TRUE);
1125 }
1126
1127 /*-----------------------------------------------------------------*/
1128 /* resultRemat - result  is rematerializable                       */
1129 /*-----------------------------------------------------------------*/
1130 static int resultRemat (iCode *ic)
1131 {
1132     if (SKIP_IC(ic) || ic->op == IFX)
1133         return 0;
1134
1135     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1136         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1137         if (sym->remat && !POINTER_SET(ic)) 
1138             return 1;
1139     }
1140
1141     return 0;
1142 }
1143
1144 /*-----------------------------------------------------------------*/
1145 /* genFunction - generated code for function entry                 */
1146 /*-----------------------------------------------------------------*/
1147 static void genFunction (iCode *ic)
1148 {
1149     symbol *sym;
1150     link *fetype;
1151
1152     nregssaved = 0;
1153     /* create the function header */
1154     emitcode(";","-----------------------------------------");
1155     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1156     emitcode(";","-----------------------------------------");
1157
1158     emitcode("","%s:",sym->rname);
1159     fetype = getSpec(operandType(IC_LEFT(ic)));
1160
1161     /* if critical function then turn interrupts off */
1162     if (SPEC_CRTCL(fetype))
1163         emitcode("di","");
1164
1165     /* if this is an interrupt service routine then
1166     save acc, b, dpl, dph  */
1167     if (IS_ISR(sym->etype)) {
1168         emitcode("push", "af");
1169         emitcode("push", "bc");
1170         emitcode("push", "de");
1171         emitcode("push", "hl");
1172     }
1173     /* PENDING: callee-save etc */
1174
1175     /* adjust the stack for the function */
1176     emitcode("push", "de"); 
1177     emitcode("push", "bc");
1178     emitcode("push", "ix");
1179     emitcode("ld", "ix,#0");
1180     emitcode("add", "ix,sp");
1181
1182     _lastStack = sym->stack;
1183
1184     if (sym->stack) {
1185         emitcode("ld", "hl,#-%d", sym->stack);
1186         emitcode("add", "hl,sp");
1187         emitcode("ld", "sp,hl");
1188     }    
1189 }
1190
1191 /*-----------------------------------------------------------------*/
1192 /* genEndFunction - generates epilogue for functions               */
1193 /*-----------------------------------------------------------------*/
1194 static void genEndFunction (iCode *ic)
1195 {
1196     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1197
1198     if (IS_ISR(sym->etype)) {
1199         assert(0);
1200     }
1201     else {
1202         if (SPEC_CRTCL(sym->etype))
1203             emitcode("ei", "");
1204         
1205         /* PENDING: calleeSave */
1206
1207         /* if debug then send end of function */
1208         if (options.debug && currFunc) { 
1209             debugLine = 1;
1210             emitcode("","C$%s$%d$%d$%d ==.",
1211                      ic->filename,currFunc->lastLine,
1212                      ic->level,ic->block); 
1213             if (IS_STATIC(currFunc->etype))         
1214                 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
1215             else
1216                 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1217             debugLine = 0;
1218         }
1219         emitcode("ld", "sp,ix");
1220         emitcode("pop", "ix");
1221         emitcode("pop", "bc");
1222         emitcode("pop", "de");
1223         emitcode("ret", "");
1224     }
1225
1226 }
1227
1228 /*-----------------------------------------------------------------*/
1229 /* genRet - generate code for return statement                     */
1230 /*-----------------------------------------------------------------*/
1231 static void genRet (iCode *ic)
1232 {
1233     char *l;
1234     /* Errk.  This is a hack until I can figure out how
1235        to cause dehl to spill on a call */
1236     int size,offset = 0;
1237     
1238     /* if we have no return value then
1239        just generate the "ret" */
1240     if (!IC_LEFT(ic)) 
1241         goto jumpret;       
1242     
1243     /* we have something to return then
1244        move the return value into place */
1245     aopOp(IC_LEFT(ic),ic,FALSE);
1246     size = AOP_SIZE(IC_LEFT(ic));
1247     
1248     if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1249             emitcode("ld", "hl,%s", l);
1250     }
1251     else {
1252         while (size--) {
1253             l = aopGet(AOP(IC_LEFT(ic)),offset,
1254                        FALSE);
1255             if (strcmp(fReturn[offset],l))
1256                 emitcode("ld","%s,%s",fReturn[offset++],l);
1257         }
1258     }
1259     freeAsmop (IC_LEFT(ic),NULL,ic);
1260     
1261  jumpret:
1262         /* generate a jump to the return label
1263            if the next is not the return statement */
1264     if (!(ic->next && ic->next->op == LABEL &&
1265           IC_LABEL(ic->next) == returnLabel))
1266         
1267         emitcode("jp",  LABEL_STR ,(returnLabel->key+100));
1268 }
1269
1270 /*-----------------------------------------------------------------*/
1271 /* genLabel - generates a label                                    */
1272 /*-----------------------------------------------------------------*/
1273 static void genLabel (iCode *ic)
1274 {
1275     /* special case never generate */
1276     if (IC_LABEL(ic) == entryLabel)
1277         return ;
1278
1279     emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1280 }
1281
1282 /*-----------------------------------------------------------------*/
1283 /* genGoto - generates a ljmp                                      */
1284 /*-----------------------------------------------------------------*/
1285 static void genGoto (iCode *ic)
1286 {
1287     emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1288 }
1289
1290 /*-----------------------------------------------------------------*/
1291 /* genPlusIncr :- does addition with increment if possible         */
1292 /*-----------------------------------------------------------------*/
1293 static bool genPlusIncr (iCode *ic)
1294 {
1295     unsigned int icount ;
1296     unsigned int size = getDataSize(IC_RESULT(ic));
1297     
1298     /* will try to generate an increment */
1299     /* if the right side is not a literal 
1300        we cannot */
1301     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1302         return FALSE;
1303     
1304     /* if the literal value of the right hand side
1305        is greater than 4 then it is not worth it */
1306     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
1307         return FALSE ;
1308
1309     /* Inc a pair */
1310     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1311         isPair(AOP(IC_RESULT(ic)))) {
1312         while (icount--) {
1313             emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1314         }
1315         return TRUE;
1316     }
1317     /* if increment 16 bits in register */
1318     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1319         (size > 1) &&
1320         (icount == 1)) {
1321         symbol *tlbl = newiTempLabel(NULL);
1322         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1323         emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1324     
1325         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1326         if(size == 4) {
1327             assert(0);
1328         }
1329         emitcode("", LABEL_STR ":",tlbl->key+100);
1330         return TRUE;
1331     }
1332
1333     /* If result is a pair */
1334     if (isPair(AOP(IC_RESULT(ic)))) {
1335         movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1336         movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1337         while (icount--)
1338             emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1339         return TRUE;
1340     }
1341
1342     /* if the sizes are greater than 1 then we cannot */
1343     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1344         AOP_SIZE(IC_LEFT(ic)) > 1   )
1345         return FALSE ;
1346     
1347     /* we can if the aops of the left & result match or
1348        if they are in registers and the registers are the
1349        same */
1350     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1351         while (icount--)
1352             emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1353         
1354         return TRUE ;
1355     }
1356     
1357     return FALSE ;
1358 }
1359
1360 /*-----------------------------------------------------------------*/
1361 /* outBitAcc - output a bit in acc                                 */
1362 /*-----------------------------------------------------------------*/
1363 void outBitAcc(operand *result)
1364 {
1365     symbol *tlbl = newiTempLabel(NULL);
1366     /* if the result is a bit */
1367     if (AOP_TYPE(result) == AOP_CRY){
1368         assert(0);
1369     }
1370     else {
1371         emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1372         emitcode("ld","a,%s",one);
1373         emitcode("", LABEL_STR ":",tlbl->key+100);
1374         outAcc(result);
1375     }
1376 }
1377
1378 /*-----------------------------------------------------------------*/
1379 /* genPlus - generates code for addition                           */
1380 /*-----------------------------------------------------------------*/
1381 static void genPlus (iCode *ic)
1382 {
1383     int size, offset = 0;
1384
1385     /* special cases :- */
1386
1387     aopOp (IC_LEFT(ic),ic,FALSE);
1388     aopOp (IC_RIGHT(ic),ic,FALSE);
1389     aopOp (IC_RESULT(ic),ic,TRUE);
1390
1391     /* Swap the left and right operands if:
1392
1393        if literal, literal on the right or
1394        if left requires ACC or right is already
1395        in ACC */
1396
1397     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1398         (AOP_NEEDSACC(IC_LEFT(ic))) ||
1399         AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1400         operand *t = IC_RIGHT(ic);
1401         IC_RIGHT(ic) = IC_LEFT(ic);
1402         IC_LEFT(ic) = t;
1403     }
1404
1405     /* if both left & right are in bit
1406     space */
1407     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1408         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1409         /* Cant happen */
1410         assert(0);
1411     }
1412
1413     /* if left in bit space & right literal */
1414     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1415         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1416         /* Can happen I guess */
1417         assert(0);
1418     }
1419
1420     /* if I can do an increment instead
1421     of add then GOOD for ME */
1422     if (genPlusIncr (ic) == TRUE)
1423         goto release;   
1424
1425     size = getDataSize(IC_RESULT(ic));
1426
1427     while(size--) {
1428         if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1429             MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1430             if(offset == 0)
1431                 emitcode("add","a,%s",
1432                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1433             else
1434                 emitcode("adc","a,%s",
1435                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1436         } else {
1437             MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1438             if(offset == 0)
1439                 emitcode("add","a,%s",
1440                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1441             else
1442                 emitcode("adc","a,%s",
1443                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1444         }
1445         aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
1446     }
1447
1448     /* Some kind of pointer arith. */
1449     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
1450         AOP_SIZE(IC_LEFT(ic)) == 3   &&
1451         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1452         assert(0);
1453
1454      if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
1455         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
1456         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1457          assert(0);
1458
1459    
1460 release:
1461     freeAsmop(IC_LEFT(ic),NULL,ic);
1462     freeAsmop(IC_RIGHT(ic),NULL,ic);
1463     freeAsmop(IC_RESULT(ic),NULL,ic);
1464     
1465 }
1466
1467 /*-----------------------------------------------------------------*/
1468 /* genMinusDec :- does subtraction with deccrement if possible     */
1469 /*-----------------------------------------------------------------*/
1470 static bool genMinusDec (iCode *ic)
1471 {
1472     unsigned int icount ;
1473     unsigned int size = getDataSize(IC_RESULT(ic));
1474
1475     /* will try to generate an increment */
1476     /* if the right side is not a literal we cannot */
1477     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1478         return FALSE ;
1479
1480     /* if the literal value of the right hand side
1481     is greater than 4 then it is not worth it */
1482     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1483         return FALSE;
1484
1485     size = getDataSize(IC_RESULT(ic));
1486     /* if decrement 16 bits in register */
1487     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1488         (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1489         while (icount--)
1490             emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1491         return TRUE;
1492     }
1493
1494     /* If result is a pair */
1495     if (isPair(AOP(IC_RESULT(ic)))) {
1496         movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1497         movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1498         while (icount--)
1499             emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1500         return TRUE;
1501     }
1502
1503     /* if the sizes are greater than 1 then we cannot */
1504     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1505         AOP_SIZE(IC_LEFT(ic)) > 1   )
1506         return FALSE ;
1507
1508     /* we can if the aops of the left & result match or if they are in
1509        registers and the registers are the same */
1510     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1511         while (icount--) 
1512             emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1513         return TRUE ;
1514     }
1515
1516     return FALSE ;
1517 }
1518
1519 /*-----------------------------------------------------------------*/
1520 /* genMinus - generates code for subtraction                       */
1521 /*-----------------------------------------------------------------*/
1522 static void genMinus (iCode *ic)
1523 {
1524     int size, offset = 0;
1525     unsigned long lit = 0L;
1526
1527     aopOp (IC_LEFT(ic),ic,FALSE);
1528     aopOp (IC_RIGHT(ic),ic,FALSE);
1529     aopOp (IC_RESULT(ic),ic,TRUE);
1530
1531     /* special cases :- */
1532     /* if both left & right are in bit space */
1533     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1534         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1535         assert(0);
1536         goto release ;
1537     }
1538
1539     /* if I can do an decrement instead of subtract then GOOD for ME */
1540     if (genMinusDec (ic) == TRUE)
1541         goto release;   
1542
1543     size = getDataSize(IC_RESULT(ic));   
1544
1545     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1546         CLRC;
1547     }
1548     else{
1549         lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1550         lit = - (long)lit;
1551     }
1552
1553
1554     /* if literal, add a,#-lit, else normal subb */
1555     while (size--) {
1556         MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));    
1557         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
1558             emitcode("sbc","a,%s",
1559                      aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1560         else{
1561             /* first add without previous c */
1562             if (!offset)
1563                 emitcode("add","a,#0x%02x",
1564                          (unsigned int)(lit & 0x0FFL));
1565             else
1566                 emitcode("adc","a,#0x%02x",
1567                          (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1568         }
1569         aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
1570     }
1571     
1572     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
1573         AOP_SIZE(IC_LEFT(ic)) == 3   &&
1574         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1575         assert(0);
1576
1577 release:
1578     freeAsmop(IC_LEFT(ic),NULL,ic);
1579     freeAsmop(IC_RIGHT(ic),NULL,ic);
1580     freeAsmop(IC_RESULT(ic),NULL,ic);
1581 }
1582
1583 /*-----------------------------------------------------------------*/
1584 /* genMult - generates code for multiplication                     */
1585 /*-----------------------------------------------------------------*/
1586 static void genMult (iCode *ic)
1587 {
1588     /* Shouldn't occur - all done through function calls */
1589     assert(0);
1590 }
1591
1592 /*-----------------------------------------------------------------*/
1593 /* genDiv - generates code for division                            */
1594 /*-----------------------------------------------------------------*/
1595 static void genDiv (iCode *ic)
1596 {
1597     /* Shouldn't occur - all done through function calls */
1598     assert(0);
1599 }
1600
1601 /*-----------------------------------------------------------------*/
1602 /* genMod - generates code for division                            */
1603 /*-----------------------------------------------------------------*/
1604 static void genMod (iCode *ic)
1605 {
1606     /* Shouldn't occur - all done through function calls */
1607     assert(0);
1608 }
1609
1610 /*-----------------------------------------------------------------*/
1611 /* genIfxJump :- will create a jump depending on the ifx           */
1612 /*-----------------------------------------------------------------*/
1613 static void genIfxJump (iCode *ic, char *jval)
1614 {
1615     symbol *jlbl ;
1616     const char *inst;
1617
1618     /* if true label then we jump if condition
1619     supplied is true */
1620     if ( IC_TRUE(ic) ) {
1621         jlbl = IC_TRUE(ic);
1622         if (!strcmp(jval, "a")) {
1623             inst = "nz";
1624         }
1625         else if (!strcmp(jval, "c")) {
1626             inst = "c";
1627         }
1628         else {
1629             /* The buffer contains the bit on A that we should test */
1630             inst = "nz";
1631         }
1632     }
1633     else {
1634         /* false label is present */
1635         jlbl = IC_FALSE(ic) ;
1636         if (!strcmp(jval, "a")) {
1637             inst = "z";
1638         }
1639         else if (!strcmp(jval, "c")) {
1640             inst = "nc";
1641         }
1642         else {
1643             /* The buffer contains the bit on A that we should test */
1644             inst = "z";
1645         }
1646     }
1647     /* Z80 can do a conditional long jump */
1648     if (!strcmp(jval, "a")) {
1649         emitcode("or", "a,a");
1650     }
1651     else if (!strcmp(jval, "c")) {
1652     }
1653     else {
1654         emitcode("bit", "%s,a", jval);
1655     }
1656     emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1657
1658     /* mark the icode as generated */
1659     ic->generated = 1;
1660 }
1661
1662 /** Generic compare for > or <
1663  */
1664 static void genCmp (operand *left,operand *right,
1665                     operand *result, iCode *ifx, int sign)
1666 {
1667     int size, offset = 0 ;
1668     unsigned long lit = 0L;
1669
1670     /* if left & right are bit variables */
1671     if (AOP_TYPE(left) == AOP_CRY &&
1672         AOP_TYPE(right) == AOP_CRY ) {
1673         /* Cant happen on the Z80 */
1674         assert(0);
1675     } else {
1676         /* subtract right from left if at the
1677         end the carry flag is set then we know that
1678         left is greater than right */
1679         size = max(AOP_SIZE(left),AOP_SIZE(right));
1680
1681         /* if unsigned char cmp with lit, just compare */
1682         if((size == 1) && !sign &&
1683            (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1684             emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1685             emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
1686         } 
1687         else {
1688             if(AOP_TYPE(right) == AOP_LIT) {
1689                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1690                 /* optimize if(x < 0) or if(x >= 0) */
1691                 if (lit == 0L){
1692                     if (!sign) {
1693                         /* No sign so it's always false */
1694                         CLRC;
1695                     }
1696                     else{
1697                         /* Just load in the top most bit */
1698                         MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1699                         if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1700                             genIfxJump (ifx,"7");
1701                             return;
1702                         }
1703                         else    
1704                             emitcode("rlc","a");
1705                     }
1706                     goto release;
1707                 }
1708             }
1709             while (size--) {
1710                 /* Do a long subtract */
1711                 MOVA(aopGet(AOP(left),offset,FALSE));
1712                 if (sign && size == 0) {
1713                     /* Case where it's signed and we've hit the end */
1714                     /* PENDING: This is almost certanitly wrong.
1715                        On the 8051 xrl doesnt change C, but xor does.
1716                     */
1717                     emitcode("xor","a,#0x80");
1718                     if (AOP_TYPE(right) == AOP_LIT){
1719                         unsigned long lit = (unsigned long)
1720                             floatFromVal(AOP(right)->aopu.aop_lit);
1721                         emitcode("sbc","a,#0x%02x",
1722                                  0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1723                     } else {
1724                         /* The bad way... */
1725                         emitcode("push", "af");
1726                         emitcode("ld","a,%s",aopGet(AOP(right),offset++,FALSE));
1727                         emitcode("xor", "a,#0x80");
1728                         emitcode("ld", "l,a");
1729                         emitcode("pop", "af");
1730                         emitcode("sbc","a,l");
1731                     }
1732                 } else {
1733                     /* Subtract through, propagating the carry */
1734                     if (offset==0) {
1735                         emitcode("sub","a,%s",aopGet(AOP(right),offset++,FALSE));
1736                     }
1737                     else
1738                         emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1739                 }
1740             }
1741         }
1742     }
1743
1744 release:
1745     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1746         outBitC(result);
1747     } else {
1748         /* if the result is used in the next
1749         ifx conditional branch then generate
1750         code a little differently */
1751         if (ifx )
1752             genIfxJump (ifx,"c");
1753         else
1754             outBitC(result);
1755         /* leave the result in acc */
1756     }
1757 }
1758
1759 /*-----------------------------------------------------------------*/
1760 /* genCmpGt :- greater than comparison                             */
1761 /*-----------------------------------------------------------------*/
1762 static void genCmpGt (iCode *ic, iCode *ifx)
1763 {
1764     operand *left, *right, *result;
1765     link *letype , *retype;
1766     int sign ;
1767
1768     left = IC_LEFT(ic);
1769     right= IC_RIGHT(ic);
1770     result = IC_RESULT(ic);
1771
1772     letype = getSpec(operandType(left));
1773     retype =getSpec(operandType(right));
1774     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1775     /* assign the amsops */
1776     aopOp (left,ic,FALSE);
1777     aopOp (right,ic,FALSE);
1778     aopOp (result,ic,TRUE);
1779
1780     genCmp(right, left, result, ifx, sign);
1781
1782     freeAsmop(left,NULL,ic);
1783     freeAsmop(right,NULL,ic);
1784     freeAsmop(result,NULL,ic);
1785 }
1786
1787 /*-----------------------------------------------------------------*/
1788 /* genCmpLt - less than comparisons                                */
1789 /*-----------------------------------------------------------------*/
1790 static void genCmpLt (iCode *ic, iCode *ifx)
1791 {
1792     operand *left, *right, *result;
1793     link *letype , *retype;
1794     int sign ;
1795
1796     left = IC_LEFT(ic);
1797     right= IC_RIGHT(ic);
1798     result = IC_RESULT(ic);
1799
1800     letype = getSpec(operandType(left));
1801     retype =getSpec(operandType(right));
1802     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1803
1804     /* assign the amsops */
1805     aopOp (left,ic,FALSE);
1806     aopOp (right,ic,FALSE);
1807     aopOp (result,ic,TRUE);
1808
1809     genCmp(left, right, result, ifx, sign);
1810
1811     freeAsmop(left,NULL,ic);
1812     freeAsmop(right,NULL,ic);
1813     freeAsmop(result,NULL,ic);
1814 }
1815
1816 /*-----------------------------------------------------------------*/
1817 /* gencjneshort - compare and jump if not equal                    */
1818 /*-----------------------------------------------------------------*/
1819 static void gencjneshort(operand *left, operand *right, symbol *lbl)
1820 {
1821     int size = max(AOP_SIZE(left),AOP_SIZE(right));
1822     int offset = 0;
1823     unsigned long lit = 0L;
1824
1825     /* Swap the left and right if it makes the computation easier */
1826     if (AOP_TYPE(left) == AOP_LIT) {
1827         operand *t = right;
1828         right = left;
1829         left = t;
1830     }
1831
1832     if(AOP_TYPE(right) == AOP_LIT)
1833         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1834
1835     /* if the right side is a literal then anything goes */
1836     if (AOP_TYPE(right) == AOP_LIT &&
1837         AOP_TYPE(left) != AOP_DIR ) {
1838         while (size--) {
1839             emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
1840             emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
1841             emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1842             offset++;
1843         }
1844     }
1845     /* if the right side is in a register or in direct space or
1846     if the left is a pointer register & right is not */    
1847     else if (AOP_TYPE(right) == AOP_REG ||
1848              AOP_TYPE(right) == AOP_DIR || 
1849              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
1850         while (size--) {
1851             MOVA(aopGet(AOP(left),offset,FALSE));
1852             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
1853                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
1854                 /* PENDING */
1855                 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
1856             else {
1857                 emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
1858                 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1859             }
1860             offset++;
1861         }
1862     } else {
1863         /* right is a pointer reg need both a & b */
1864         /* PENDING: is this required? */
1865         while(size--) {
1866             char *l = aopGet(AOP(left),offset,FALSE);
1867             MOVA(aopGet(AOP(right),offset,FALSE));
1868             emitcode("cp", "%s", l);
1869             emitcode("jr", "nz," LABEL_STR, lbl->key+100);
1870             offset++;
1871         }
1872     }
1873 }
1874
1875 /*-----------------------------------------------------------------*/
1876 /* gencjne - compare and jump if not equal                         */
1877 /*-----------------------------------------------------------------*/
1878 static void gencjne(operand *left, operand *right, symbol *lbl)
1879 {
1880     symbol *tlbl  = newiTempLabel(NULL);
1881
1882     gencjneshort(left, right, lbl);
1883
1884     /* PENDING: ?? */
1885     emitcode("ld","a,%s",one);
1886     emitcode("jp", LABEL_STR ,tlbl->key+100);
1887     emitcode("", LABEL_STR ":",lbl->key+100);
1888     emitcode("xor","a,a");
1889     emitcode("", LABEL_STR ":",tlbl->key+100);
1890 }
1891
1892 /*-----------------------------------------------------------------*/
1893 /* genCmpEq - generates code for equal to                          */
1894 /*-----------------------------------------------------------------*/
1895 static void genCmpEq (iCode *ic, iCode *ifx)
1896 {
1897     operand *left, *right, *result;
1898
1899     aopOp((left=IC_LEFT(ic)),ic,FALSE);
1900     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
1901     aopOp((result=IC_RESULT(ic)),ic,TRUE);
1902
1903     /* Swap operands if it makes the operation easier. ie if:
1904        1.  Left is a literal.
1905     */
1906     if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1907         operand *t = IC_RIGHT(ic);
1908         IC_RIGHT(ic) = IC_LEFT(ic);
1909         IC_LEFT(ic) = t;
1910     }
1911
1912     if (ifx && !AOP_SIZE(result)){
1913         symbol *tlbl;
1914         /* if they are both bit variables */
1915         if (AOP_TYPE(left) == AOP_CRY &&
1916             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1917             assert(0);
1918         } else {
1919             tlbl = newiTempLabel(NULL);
1920             gencjneshort(left, right, tlbl);
1921             if ( IC_TRUE(ifx) ) {
1922                 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
1923                 emitcode("", LABEL_STR ":",tlbl->key+100);                
1924             } else {
1925                 /* PENDING: do this better */
1926                 symbol *lbl = newiTempLabel(NULL);
1927                 emitcode("jp", LABEL_STR ,lbl->key+100);
1928                 emitcode("", LABEL_STR ":",tlbl->key+100);                
1929                 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
1930                 emitcode("", LABEL_STR ":",lbl->key+100);             
1931             }
1932         }
1933         /* mark the icode as generated */
1934         ifx->generated = 1;
1935         goto release ;
1936     }
1937
1938     /* if they are both bit variables */
1939     if (AOP_TYPE(left) == AOP_CRY &&
1940         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
1941         assert(0);
1942     } else {
1943         gencjne(left,right,newiTempLabel(NULL));    
1944         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1945             assert(0);
1946         }
1947         if (ifx) {
1948             genIfxJump(ifx,"a");
1949             goto release;
1950         }
1951         /* if the result is used in an arithmetic operation
1952         then put the result in place */
1953         if (AOP_TYPE(result) != AOP_CRY) {
1954             outAcc(result);
1955         }
1956         /* leave the result in acc */
1957     }
1958
1959 release:
1960     freeAsmop(left,NULL,ic);
1961     freeAsmop(right,NULL,ic);
1962     freeAsmop(result,NULL,ic);
1963 }
1964
1965 /*-----------------------------------------------------------------*/
1966 /* ifxForOp - returns the icode containing the ifx for operand     */
1967 /*-----------------------------------------------------------------*/
1968 static iCode *ifxForOp ( operand *op, iCode *ic )
1969 {
1970     /* if true symbol then needs to be assigned */
1971     if (IS_TRUE_SYMOP(op))
1972         return NULL ;
1973
1974     /* if this has register type condition and
1975     the next instruction is ifx with the same operand
1976     and live to of the operand is upto the ifx only then */
1977     if (ic->next &&
1978         ic->next->op == IFX &&
1979         IC_COND(ic->next)->key == op->key &&
1980         OP_SYMBOL(op)->liveTo <= ic->next->seq )
1981         return ic->next;
1982
1983     return NULL;
1984 }
1985
1986 /*-----------------------------------------------------------------*/
1987 /* genAndOp - for && operation                                     */
1988 /*-----------------------------------------------------------------*/
1989 static void genAndOp (iCode *ic)
1990 {
1991     operand *left,*right, *result;
1992     symbol *tlbl;
1993
1994     /* note here that && operations that are in an if statement are
1995        taken away by backPatchLabels only those used in arthmetic
1996        operations remain */
1997     aopOp((left=IC_LEFT(ic)),ic,FALSE);
1998     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
1999     aopOp((result=IC_RESULT(ic)),ic,FALSE);
2000
2001     /* if both are bit variables */
2002     if (AOP_TYPE(left) == AOP_CRY &&
2003         AOP_TYPE(right) == AOP_CRY ) {
2004         assert(0);
2005     } else {
2006         tlbl = newiTempLabel(NULL);
2007         toBoolean(left);    
2008         emitcode("jp","z," LABEL_STR ,tlbl->key+100);
2009         toBoolean(right);
2010         emitcode("", LABEL_STR ":",tlbl->key+100);
2011         outBitAcc(result);
2012     }
2013
2014     freeAsmop(left,NULL,ic);
2015     freeAsmop(right,NULL,ic);
2016     freeAsmop(result,NULL,ic);
2017 }
2018
2019 /*-----------------------------------------------------------------*/
2020 /* genOrOp - for || operation                                      */
2021 /*-----------------------------------------------------------------*/
2022 static void genOrOp (iCode *ic)
2023 {
2024     operand *left,*right, *result;
2025     symbol *tlbl;
2026
2027     /* note here that || operations that are in an
2028        if statement are taken away by backPatchLabels
2029        only those used in arthmetic operations remain */
2030     aopOp((left=IC_LEFT(ic)),ic,FALSE);
2031     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2032     aopOp((result=IC_RESULT(ic)),ic,FALSE);
2033
2034     /* if both are bit variables */
2035     if (AOP_TYPE(left) == AOP_CRY &&
2036         AOP_TYPE(right) == AOP_CRY ) {
2037         assert(0);
2038     } else {
2039         tlbl = newiTempLabel(NULL);
2040         toBoolean(left);
2041         emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2042         toBoolean(right);
2043         emitcode("", LABEL_STR,tlbl->key+100);
2044         outBitAcc(result);
2045     }
2046
2047     freeAsmop(left,NULL,ic);
2048     freeAsmop(right,NULL,ic);
2049     freeAsmop(result,NULL,ic);
2050 }
2051
2052 /*-----------------------------------------------------------------*/
2053 /* isLiteralBit - test if lit == 2^n                               */
2054 /*-----------------------------------------------------------------*/
2055 int isLiteralBit(unsigned long lit)
2056 {
2057     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2058     0x100L,0x200L,0x400L,0x800L,
2059     0x1000L,0x2000L,0x4000L,0x8000L,
2060     0x10000L,0x20000L,0x40000L,0x80000L,
2061     0x100000L,0x200000L,0x400000L,0x800000L,
2062     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2063     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2064     int idx;
2065     
2066     for(idx = 0; idx < 32; idx++)
2067         if(lit == pw[idx])
2068             return idx+1;
2069     return 0;
2070 }
2071
2072 /*-----------------------------------------------------------------*/
2073 /* genAnd  - code for and                                          */
2074 /*-----------------------------------------------------------------*/
2075 static void genAnd (iCode *ic, iCode *ifx)
2076 {
2077     operand *left, *right, *result;
2078     int size, offset=0;  
2079     unsigned long lit = 0L;
2080     int bytelit = 0;
2081
2082     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2083     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2084     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2085
2086 #ifdef DEBUG_TYPE
2087     emitcode("","; Type res[%d] = l[%d]&r[%d]",
2088              AOP_TYPE(result),
2089              AOP_TYPE(left), AOP_TYPE(right));
2090     emitcode("","; Size res[%d] = l[%d]&r[%d]",
2091              AOP_SIZE(result),
2092              AOP_SIZE(left), AOP_SIZE(right));
2093 #endif
2094
2095     /* if left is a literal & right is not then exchange them */
2096     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2097         AOP_NEEDSACC(left)) {
2098         operand *tmp = right ;
2099         right = left;
2100         left = tmp;
2101     }
2102
2103     /* if result = right then exchange them */
2104     if(sameRegs(AOP(result),AOP(right))){
2105         operand *tmp = right ;
2106         right = left;
2107         left = tmp;
2108     }
2109
2110     /* if right is bit then exchange them */
2111     if (AOP_TYPE(right) == AOP_CRY &&
2112         AOP_TYPE(left) != AOP_CRY){
2113         operand *tmp = right ;
2114         right = left;
2115         left = tmp;
2116     }
2117     if(AOP_TYPE(right) == AOP_LIT)
2118         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2119
2120     size = AOP_SIZE(result);
2121
2122     if (AOP_TYPE(left) == AOP_CRY){
2123         assert(0);
2124         goto release ;
2125     }
2126
2127     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
2128     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
2129     if((AOP_TYPE(right) == AOP_LIT) &&
2130        (AOP_TYPE(result) == AOP_CRY) &&
2131        (AOP_TYPE(left) != AOP_CRY)) {
2132         int posbit = isLiteralBit(lit);
2133         /* left &  2^n */
2134         if(posbit){
2135             posbit--;
2136             MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2137             // bit = left & 2^n
2138             if(size) {
2139                 assert(0);
2140                 emitcode("mov","c,acc.%d",posbit&0x07);
2141             }
2142             // if(left &  2^n)
2143             else{
2144                 if (ifx) {
2145                     sprintf(buffer, "%d", posbit&0x07);
2146                     genIfxJump(ifx, buffer);
2147                 }
2148                 else {
2149                     assert(0);
2150                 }
2151                 goto release;
2152             }
2153         } else {
2154             symbol *tlbl = newiTempLabel(NULL);
2155             int sizel = AOP_SIZE(left);
2156             if(size) {
2157                 assert(0);
2158                 emitcode("setb","c");
2159             }
2160             while(sizel--){
2161                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2162                     MOVA( aopGet(AOP(left),offset,FALSE));
2163                     // byte ==  2^n ?
2164                     if((posbit = isLiteralBit(bytelit)) != 0) {
2165                         assert(0);
2166                         emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2167                     }
2168                     else{
2169                         if(bytelit != 0x0FFL)
2170                             emitcode("and","a,%s",
2171                                      aopGet(AOP(right),offset,FALSE));
2172                         emitcode("jr","nz, %05d$",tlbl->key+100);
2173                     }
2174                 }
2175                 offset++;
2176             }
2177             // bit = left & literal
2178             if (size){
2179                 emitcode("clr","c");
2180                 emitcode("","%05d$:",tlbl->key+100);
2181             }
2182             // if(left & literal)
2183             else{
2184                 if(ifx)
2185 #if 0
2186                     jmpTrueOrFalse(ifx, tlbl);
2187 #else
2188                 assert(0);
2189 #endif
2190                 goto release ;
2191             }
2192         }
2193         outBitC(result);
2194         goto release ;
2195     }
2196
2197     /* if left is same as result */
2198     if(sameRegs(AOP(result),AOP(left))){
2199         for(;size--; offset++) {
2200             if(AOP_TYPE(right) == AOP_LIT){
2201                 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2202                     continue;
2203                 else {
2204                     if (bytelit == 0)
2205                         aopPut(AOP(result),zero,offset);
2206                     else {
2207                         MOVA(aopGet(AOP(left),offset,FALSE));
2208                         emitcode("and","a,%s",
2209                                  aopGet(AOP(right),offset,FALSE));
2210                         emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2211                     }
2212                 }
2213
2214             } else {
2215                 if (AOP_TYPE(left) == AOP_ACC) {
2216                     assert(0);
2217                 }
2218                 else {
2219                     MOVA(aopGet(AOP(right),offset,FALSE));
2220                     emitcode("and","%s,a",
2221                              aopGet(AOP(left),offset,FALSE));
2222                 }
2223             }
2224         }
2225     } else {
2226         // left & result in different registers
2227         if(AOP_TYPE(result) == AOP_CRY){
2228             assert(0);
2229         } else {
2230             for(;(size--);offset++) {
2231                 // normal case
2232                 // result = left & right
2233                 if(AOP_TYPE(right) == AOP_LIT){
2234                     if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2235                         aopPut(AOP(result),
2236                                aopGet(AOP(left),offset,FALSE),
2237                                offset);
2238                         continue;
2239                     } else if(bytelit == 0){
2240                         aopPut(AOP(result),zero,offset);
2241                         continue;
2242                     }
2243                 }
2244                 // faster than result <- left, anl result,right
2245                 // and better if result is SFR
2246                 if (AOP_TYPE(left) == AOP_ACC) 
2247                     emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2248                 else {
2249                     MOVA(aopGet(AOP(right),offset,FALSE));
2250                     emitcode("and","a,%s",
2251                              aopGet(AOP(left),offset,FALSE));
2252                 }
2253                 aopPut(AOP(result),"a",offset);
2254             }
2255         }
2256
2257     }
2258
2259 release :
2260     freeAsmop(left,NULL,ic);
2261     freeAsmop(right,NULL,ic);
2262     freeAsmop(result,NULL,ic);
2263 }
2264
2265 /*-----------------------------------------------------------------*/
2266 /* genOr  - code for or                                            */
2267 /*-----------------------------------------------------------------*/
2268 static void genOr (iCode *ic, iCode *ifx)
2269 {
2270     operand *left, *right, *result;
2271     int size, offset=0;
2272     unsigned long lit = 0L;
2273
2274     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2275     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2276     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2277
2278 #ifdef DEBUG_TYPE
2279     emitcode("","; Type res[%d] = l[%d]&r[%d]",
2280              AOP_TYPE(result),
2281              AOP_TYPE(left), AOP_TYPE(right));
2282     emitcode("","; Size res[%d] = l[%d]&r[%d]",
2283              AOP_SIZE(result),
2284              AOP_SIZE(left), AOP_SIZE(right));
2285 #endif
2286
2287     /* if left is a literal & right is not then exchange them */
2288     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2289         AOP_NEEDSACC(left)) {
2290         operand *tmp = right ;
2291         right = left;
2292         left = tmp;
2293     }
2294
2295     /* if result = right then exchange them */
2296     if(sameRegs(AOP(result),AOP(right))){
2297         operand *tmp = right ;
2298         right = left;
2299         left = tmp;
2300     }
2301
2302     /* if right is bit then exchange them */
2303     if (AOP_TYPE(right) == AOP_CRY &&
2304         AOP_TYPE(left) != AOP_CRY){
2305         operand *tmp = right ;
2306         right = left;
2307         left = tmp;
2308     }
2309     if(AOP_TYPE(right) == AOP_LIT)
2310         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2311
2312     size = AOP_SIZE(result);
2313
2314     if (AOP_TYPE(left) == AOP_CRY){
2315         assert(0);
2316         goto release ;
2317     }
2318
2319     if((AOP_TYPE(right) == AOP_LIT) &&
2320        (AOP_TYPE(result) == AOP_CRY) &&
2321        (AOP_TYPE(left) != AOP_CRY)){
2322         assert(0);
2323         goto release ;
2324     }
2325
2326     /* if left is same as result */
2327     if(sameRegs(AOP(result),AOP(left))){
2328         for(;size--; offset++) {
2329             if(AOP_TYPE(right) == AOP_LIT){
2330                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2331                     continue;
2332                 else 
2333                     emitcode("or","%s,%s",
2334                              aopGet(AOP(left),offset,FALSE),
2335                              aopGet(AOP(right),offset,FALSE));
2336             } else {
2337                 if (AOP_TYPE(left) == AOP_ACC) 
2338                     emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2339                 else {              
2340                     MOVA(aopGet(AOP(right),offset,FALSE));
2341                     emitcode("or","a,%s",
2342                              aopGet(AOP(left),offset,FALSE));
2343                     aopPut(AOP(result),"a",0);
2344                 }
2345             }
2346         }
2347     } else {
2348         // left & result in different registers
2349         if(AOP_TYPE(result) == AOP_CRY){
2350             assert(0);
2351         } else for(;(size--);offset++){
2352             // normal case
2353             // result = left & right
2354             if(AOP_TYPE(right) == AOP_LIT){
2355                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2356                     aopPut(AOP(result),
2357                            aopGet(AOP(left),offset,FALSE),
2358                            offset);
2359                     continue;
2360                 }
2361             }
2362             // faster than result <- left, anl result,right
2363             // and better if result is SFR
2364             if (AOP_TYPE(left) == AOP_ACC) 
2365                 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2366             else {
2367                 MOVA(aopGet(AOP(right),offset,FALSE));
2368                 emitcode("or","a,%s",
2369                          aopGet(AOP(left),offset,FALSE));
2370                 aopPut(AOP(result),"a",0);
2371             }
2372             aopPut(AOP(result),"a",offset);                     
2373         }
2374     }
2375
2376 release :
2377     freeAsmop(left,NULL,ic);
2378     freeAsmop(right,NULL,ic);
2379     freeAsmop(result,NULL,ic);
2380 }
2381
2382 /*-----------------------------------------------------------------*/
2383 /* genXor - code for xclusive or                                   */
2384 /*-----------------------------------------------------------------*/
2385 static void genXor (iCode *ic, iCode *ifx)
2386 {
2387     operand *left, *right, *result;
2388     int size, offset=0;
2389     unsigned long lit = 0L;
2390
2391     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2392     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2393     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2394
2395     /* if left is a literal & right is not then exchange them */
2396     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2397         AOP_NEEDSACC(left)) {
2398         operand *tmp = right ;
2399         right = left;
2400         left = tmp;
2401     }
2402
2403     /* if result = right then exchange them */
2404     if(sameRegs(AOP(result),AOP(right))){
2405         operand *tmp = right ;
2406         right = left;
2407         left = tmp;
2408     }
2409
2410     /* if right is bit then exchange them */
2411     if (AOP_TYPE(right) == AOP_CRY &&
2412         AOP_TYPE(left) != AOP_CRY){
2413         operand *tmp = right ;
2414         right = left;
2415         left = tmp;
2416     }
2417     if(AOP_TYPE(right) == AOP_LIT)
2418         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2419
2420     size = AOP_SIZE(result);
2421
2422     if (AOP_TYPE(left) == AOP_CRY){
2423         assert(0);
2424         goto release ;
2425     }
2426
2427     if((AOP_TYPE(right) == AOP_LIT) &&
2428        (AOP_TYPE(result) == AOP_CRY) &&
2429        (AOP_TYPE(left) != AOP_CRY)){
2430         assert(0);
2431         goto release ;
2432     }
2433
2434     /* if left is same as result */
2435     if(sameRegs(AOP(result),AOP(left))){
2436         for(;size--; offset++) {
2437             if(AOP_TYPE(right) == AOP_LIT){
2438                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2439                     continue;
2440                 else {
2441                     MOVA(aopGet(AOP(right),offset,FALSE));
2442                     emitcode("xor","a,%s",
2443                              aopGet(AOP(left),offset,FALSE));
2444                     aopPut(AOP(result),"a",0);
2445                 }
2446             } else {
2447                 if (AOP_TYPE(left) == AOP_ACC) 
2448                     emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2449                 else {              
2450                     MOVA(aopGet(AOP(right),offset,FALSE));
2451                     emitcode("xor","a,%s",
2452                              aopGet(AOP(left),offset,FALSE));
2453                     aopPut(AOP(result),"a",0);
2454                 }
2455             }
2456         }
2457     } else {
2458         // left & result in different registers
2459         if(AOP_TYPE(result) == AOP_CRY){
2460             assert(0);
2461         } else for(;(size--);offset++){
2462             // normal case
2463             // result = left & right
2464             if(AOP_TYPE(right) == AOP_LIT){
2465                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2466                     aopPut(AOP(result),
2467                            aopGet(AOP(left),offset,FALSE),
2468                            offset);
2469                     continue;
2470                 }
2471             }
2472             // faster than result <- left, anl result,right
2473             // and better if result is SFR
2474             if (AOP_TYPE(left) == AOP_ACC) 
2475                 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2476             else {
2477                 MOVA(aopGet(AOP(right),offset,FALSE));
2478                 emitcode("xor","a,%s",
2479                          aopGet(AOP(left),offset,FALSE));
2480                 aopPut(AOP(result),"a",0);
2481             }
2482             aopPut(AOP(result),"a",offset);                     
2483         }
2484     }
2485
2486 release :
2487     freeAsmop(left,NULL,ic);
2488     freeAsmop(right,NULL,ic);
2489     freeAsmop(result,NULL,ic);
2490 }
2491
2492 /*-----------------------------------------------------------------*/
2493 /* genInline - write the inline code out                           */
2494 /*-----------------------------------------------------------------*/
2495 static void genInline (iCode *ic)
2496 {
2497     char buffer[MAX_INLINEASM];
2498     char *bp = buffer;
2499     char *bp1= buffer;
2500     
2501     inLine += (!options.asmpeep);
2502     strcpy(buffer,IC_INLINE(ic));
2503
2504     /* emit each line as a code */
2505     while (*bp) {
2506         if (*bp == '\n') {
2507             *bp++ = '\0';
2508             emitcode(bp1,"");
2509             bp1 = bp;
2510         } else {
2511             if (*bp == ':') {
2512                 bp++;
2513                 *bp = '\0';
2514                 bp++;
2515                 emitcode(bp1,"");
2516                 bp1 = bp;
2517             } else
2518                 bp++;
2519         }
2520     }
2521     if (bp1 != bp)
2522         emitcode(bp1,"");
2523     /*     emitcode("",buffer); */
2524     inLine -= (!options.asmpeep);
2525 }
2526
2527 /*-----------------------------------------------------------------*/
2528 /* genRRC - rotate right with carry                                */
2529 /*-----------------------------------------------------------------*/
2530 static void genRRC (iCode *ic)
2531 {
2532     assert(0);
2533 }
2534
2535 /*-----------------------------------------------------------------*/
2536 /* genRLC - generate code for rotate left with carry               */
2537 /*-----------------------------------------------------------------*/
2538 static void genRLC (iCode *ic)
2539 {    
2540     assert(0);
2541 }
2542
2543 /*-----------------------------------------------------------------*/
2544 /* shiftR2Left2Result - shift right two bytes from left to result  */
2545 /*-----------------------------------------------------------------*/
2546 static void shiftR2Left2Result (operand *left, int offl,
2547                                 operand *result, int offr,
2548                                 int shCount, int sign)
2549 {
2550     if(sameRegs(AOP(result), AOP(left)) &&
2551        ((offl + MSB16) == offr)){
2552         assert(0);
2553     } else {
2554         movLeft2Result(left, offl, result, offr, 0);
2555         movLeft2Result(left, offl+1, result, offr+1, 0);
2556     }
2557
2558     if (sign) {
2559         assert(0);
2560     }
2561     else {
2562         /*      if (AOP(result)->type == AOP_REG) {*/
2563             int size = 2;
2564             int offset = 0;
2565             symbol *tlbl , *tlbl1;
2566             char *l;
2567
2568             /* Left is already in result - so now do the shift */
2569             if (shCount>1) {
2570                 emitcode("ld","a,#%u+1", shCount);
2571                 tlbl = newiTempLabel(NULL);
2572                 tlbl1 = newiTempLabel(NULL);
2573                 emitcode("jp", LABEL_STR ,tlbl1->key+100); 
2574                 emitcode("", LABEL_STR ":",tlbl->key+100);    
2575             }
2576
2577             emitcode("or", "a,a");
2578             offset = size;
2579             while (size--) {
2580                 l = aopGet(AOP(result), --offset, FALSE);
2581                 emitcode("rr","%s", l);         
2582             }
2583             if (shCount>1) {
2584                 emitcode("", LABEL_STR ":",tlbl1->key+100);
2585                 emitcode("dec", "a");
2586                 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2587             }
2588     }
2589 }
2590
2591 /*-----------------------------------------------------------------*/
2592 /* shiftL2Left2Result - shift left two bytes from left to result   */
2593 /*-----------------------------------------------------------------*/
2594 static void shiftL2Left2Result (operand *left, int offl,
2595                                 operand *result, int offr, int shCount)
2596 {
2597     if(sameRegs(AOP(result), AOP(left)) &&
2598        ((offl + MSB16) == offr)){
2599         assert(0);
2600     } else {
2601         /* Copy left into result */
2602         movLeft2Result(left,offl, result, offr, 0);
2603     }
2604     /* PENDING: for now just see if it'll work. */
2605     /*if (AOP(result)->type == AOP_REG) { */
2606     {
2607         int size = 2;
2608         int offset = 0;
2609         symbol *tlbl , *tlbl1;
2610         char *l;
2611
2612         /* Left is already in result - so now do the shift */
2613         if (shCount>1) {
2614             emitcode("ld","a,#%u+1", shCount);
2615             tlbl = newiTempLabel(NULL);
2616             tlbl1 = newiTempLabel(NULL);
2617             emitcode("jp", LABEL_STR ,tlbl1->key+100); 
2618             emitcode("", LABEL_STR ":",tlbl->key+100);    
2619         }
2620
2621         emitcode("or", "a,a");
2622         while (size--) {
2623             l = aopGet(AOP(result),offset++,FALSE);
2624             emitcode("rl","%s", l);         
2625         }
2626         if (shCount>1) {
2627             emitcode("", LABEL_STR ":",tlbl1->key+100);
2628             emitcode("dec", "a");
2629             emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2630         }
2631     }
2632 }
2633
2634 /*-----------------------------------------------------------------*/
2635 /* AccRol - rotate left accumulator by known count                 */
2636 /*-----------------------------------------------------------------*/
2637 static void AccRol (int shCount)
2638 {
2639     shCount &= 0x0007;              // shCount : 0..7
2640     switch(shCount){
2641         case 0 :
2642             break;
2643         case 1 :
2644             emitcode("rl","a");
2645             break;
2646         case 2 :
2647             emitcode("rl","a");
2648             emitcode("rl","a");
2649             break;
2650         case 3 :
2651             emitcode("rl","a");
2652             emitcode("rl","a");
2653             emitcode("rl","a");
2654             break;
2655         case 4 :
2656             emitcode("rl","a");
2657             emitcode("rl","a");
2658             emitcode("rl","a");
2659             emitcode("rl","a");
2660             break;
2661         case 5 :
2662             emitcode("rr","a");
2663             emitcode("rr","a");
2664             emitcode("rr","a");
2665             break;
2666         case 6 :
2667             emitcode("rr","a");
2668             emitcode("rr","a");
2669             break;
2670         case 7 :
2671             emitcode("rr","a");
2672             break;
2673     }
2674 }
2675
2676 /*-----------------------------------------------------------------*/
2677 /* AccLsh - left shift accumulator by known count                  */
2678 /*-----------------------------------------------------------------*/
2679 static void AccLsh (int shCount)
2680 {
2681     if(shCount != 0){
2682         if(shCount == 1)
2683             emitcode("add","a,a");
2684         else 
2685             if(shCount == 2) {
2686             emitcode("add","a,a");
2687             emitcode("add","a,a");
2688         } else {
2689             /* rotate left accumulator */
2690             AccRol(shCount);
2691             /* and kill the lower order bits */
2692             emitcode("and","a,#0x%02x", SLMask[shCount]);
2693         }
2694     }
2695 }
2696
2697 /*-----------------------------------------------------------------*/
2698 /* shiftL1Left2Result - shift left one byte from left to result    */
2699 /*-----------------------------------------------------------------*/
2700 static void shiftL1Left2Result (operand *left, int offl,
2701                                 operand *result, int offr, int shCount)
2702 {
2703     char *l;
2704     l = aopGet(AOP(left),offl,FALSE);
2705     MOVA(l);
2706     /* shift left accumulator */
2707     AccLsh(shCount);
2708     aopPut(AOP(result),"a",offr);
2709 }
2710
2711
2712 /*-----------------------------------------------------------------*/
2713 /* genlshTwo - left shift two bytes by known amount != 0           */
2714 /*-----------------------------------------------------------------*/
2715 static void genlshTwo (operand *result,operand *left, int shCount)
2716 {
2717     int size = AOP_SIZE(result);
2718
2719     assert(size==2);
2720
2721     /* if shCount >= 8 */
2722     if (shCount >= 8) {
2723         shCount -= 8 ;
2724
2725         if (size > 1){
2726             if (shCount) {
2727                 movLeft2Result(left, LSB, result, MSB16, 0);
2728                 aopPut(AOP(result),zero, 0);   
2729                 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2730             }
2731             else {
2732                 movLeft2Result(left, LSB, result, MSB16, 0);
2733                 aopPut(AOP(result),zero, 0);   
2734             }
2735         }
2736         aopPut(AOP(result),zero,LSB);   
2737     }
2738     /*  1 <= shCount <= 7 */
2739     else {  
2740         if(size == 1) {
2741             assert(0);
2742         }
2743         else {
2744             shiftL2Left2Result(left, LSB, result, LSB, shCount);
2745         }
2746     }
2747 }
2748
2749 /*-----------------------------------------------------------------*/
2750 /* genlshOne - left shift a one byte quantity by known count       */
2751 /*-----------------------------------------------------------------*/
2752 static void genlshOne (operand *result, operand *left, int shCount)
2753 {       
2754     shiftL1Left2Result(left, LSB, result, LSB, shCount);
2755 }
2756
2757 /*-----------------------------------------------------------------*/
2758 /* genLeftShiftLiteral - left shifting by known count              */
2759 /*-----------------------------------------------------------------*/
2760 static void genLeftShiftLiteral (operand *left,
2761                                  operand *right,
2762                                  operand *result,
2763                                  iCode *ic)
2764 {    
2765     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2766     int size;
2767
2768     freeAsmop(right,NULL,ic);
2769
2770     aopOp(left,ic,FALSE);
2771     aopOp(result,ic,FALSE);
2772
2773     size = getSize(operandType(result));
2774
2775 #if VIEW_SIZE
2776     emitcode("; shift left ","result %d, left %d",size,
2777              AOP_SIZE(left));
2778 #endif
2779
2780     /* I suppose that the left size >= result size */
2781     if (shCount == 0) {
2782         assert(0);
2783     }
2784
2785     else if(shCount >= (size * 8))
2786         while(size--)
2787             aopPut(AOP(result),zero,size);
2788     else{
2789         switch (size) {
2790         case 1:
2791             genlshOne (result,left,shCount);
2792             break;
2793         case 2:
2794             genlshTwo (result,left,shCount);
2795             break;
2796         case 4:
2797             assert(0);
2798             break;
2799         default:
2800             assert(0);
2801         }
2802     }
2803     freeAsmop(left,NULL,ic);
2804     freeAsmop(result,NULL,ic);
2805 }
2806
2807 /*-----------------------------------------------------------------*/
2808 /* genLeftShift - generates code for left shifting                 */
2809 /*-----------------------------------------------------------------*/
2810 static void genLeftShift (iCode *ic)
2811 {
2812     int size, offset;
2813     char *l;
2814     symbol *tlbl , *tlbl1;
2815     operand *left,*right, *result;
2816
2817     right = IC_RIGHT(ic);
2818     left  = IC_LEFT(ic);
2819     result = IC_RESULT(ic);
2820
2821     aopOp(right,ic,FALSE);
2822
2823     /* if the shift count is known then do it 
2824     as efficiently as possible */
2825     if (AOP_TYPE(right) == AOP_LIT) {
2826         genLeftShiftLiteral (left,right,result,ic);
2827         return ;
2828     }
2829
2830     /* shift count is unknown then we have to form a loop get the loop
2831        count in B : Note: we take only the lower order byte since
2832        shifting more that 32 bits make no sense anyway, ( the largest
2833        size of an object can be only 32 bits ) */
2834     emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
2835     emitcode("inc","a");
2836     freeAsmop (right,NULL,ic);
2837     aopOp(left,ic,FALSE);
2838     aopOp(result,ic,FALSE);
2839
2840     /* now move the left to the result if they are not the
2841        same */
2842 #if 1
2843     if (!sameRegs(AOP(left),AOP(result))) {
2844
2845         size = AOP_SIZE(result);
2846         offset = 0;
2847         while (size--) {
2848             l = aopGet(AOP(left),offset,FALSE);
2849             aopPut(AOP(result),l,offset);
2850             offset++;
2851         }
2852     }
2853 #else
2854     size = AOP_SIZE(result);
2855     offset = 0;
2856     while (size--) {
2857         l = aopGet(AOP(left),offset,FALSE);
2858         aopPut(AOP(result),l,offset);
2859         offset++;
2860     }
2861 #endif
2862
2863
2864     tlbl = newiTempLabel(NULL);
2865     size = AOP_SIZE(result);
2866     offset = 0 ;   
2867     tlbl1 = newiTempLabel(NULL);
2868
2869     emitcode("jp", LABEL_STR ,tlbl1->key+100); 
2870     emitcode("", LABEL_STR ":",tlbl->key+100);    
2871     l = aopGet(AOP(result),offset,FALSE);
2872     emitcode("or", "a,a");
2873     while (size--) {
2874         l = aopGet(AOP(result),offset++,FALSE);
2875         emitcode("rl","%s", l);         
2876     }
2877     emitcode("", LABEL_STR ":",tlbl1->key+100);
2878     emitcode("dec", "a");
2879     emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2880
2881     freeAsmop(left,NULL,ic);
2882     freeAsmop(result,NULL,ic);
2883 }
2884
2885 /* genlshTwo - left shift two bytes by known amount != 0           */
2886 /*-----------------------------------------------------------------*/
2887 static void genrshOne (operand *result,operand *left, int shCount)
2888 {
2889     /* Errk */
2890     int size = AOP_SIZE(result);
2891     char *l;
2892
2893     assert(size==1);
2894     assert(shCount<8);
2895
2896     l = aopGet(AOP(left),0,FALSE);
2897     if (AOP(result)->type == AOP_REG) {
2898         aopPut(AOP(result), l, 0);
2899         l = aopGet(AOP(result), 0, FALSE);
2900         while (shCount--) 
2901             emitcode("srl", "%s", l);
2902     }
2903     else {
2904         MOVA(l);
2905         while (shCount--) {
2906             emitcode("srl", "a");
2907         }
2908         aopPut(AOP(result),"a",0);
2909     }
2910 }
2911
2912 /*-----------------------------------------------------------------*/
2913 /* AccRsh - right shift accumulator by known count                 */
2914 /*-----------------------------------------------------------------*/
2915 static void AccRsh (int shCount)
2916 {
2917     if(shCount != 0){
2918         if(shCount == 1){
2919             CLRC;
2920             emitcode("rr","a");
2921         } else {
2922             /* rotate right accumulator */
2923             AccRol(8 - shCount);
2924             /* and kill the higher order bits */
2925             emitcode("and","a,#0x%02x", SRMask[shCount]);
2926         }
2927     }
2928 }
2929
2930 /*-----------------------------------------------------------------*/
2931 /* shiftR1Left2Result - shift right one byte from left to result   */
2932 /*-----------------------------------------------------------------*/
2933 static void shiftR1Left2Result (operand *left, int offl,
2934                                 operand *result, int offr,
2935                                 int shCount, int sign)
2936 {
2937     MOVA(aopGet(AOP(left),offl,FALSE));
2938     if (sign) {
2939         assert(0);
2940     }
2941     else {
2942         AccRsh(shCount);
2943     }
2944     aopPut(AOP(result),"a",offr);
2945 }
2946
2947 /*-----------------------------------------------------------------*/
2948 /* genrshTwo - right shift two bytes by known amount != 0          */
2949 /*-----------------------------------------------------------------*/
2950 static void genrshTwo (operand *result,operand *left,
2951                        int shCount, int sign)
2952 {
2953     /* if shCount >= 8 */
2954     if (shCount >= 8) {
2955         shCount -= 8 ;
2956         if (shCount) {
2957             assert(0);
2958             shiftR1Left2Result(left, MSB16, result, LSB,
2959                                shCount, sign);
2960         }
2961         else {
2962             movLeft2Result(left, MSB16, result, LSB, sign);
2963             aopPut(AOP(result),zero,1);
2964         }
2965     }
2966     /*  1 <= shCount <= 7 */
2967     else {
2968         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
2969     }
2970 }
2971
2972 /*-----------------------------------------------------------------*/
2973 /* genRightShiftLiteral - left shifting by known count              */
2974 /*-----------------------------------------------------------------*/
2975 static void genRightShiftLiteral (operand *left,
2976                                  operand *right,
2977                                  operand *result,
2978                                  iCode *ic)
2979 {    
2980     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2981     int size;
2982
2983     freeAsmop(right,NULL,ic);
2984
2985     aopOp(left,ic,FALSE);
2986     aopOp(result,ic,FALSE);
2987
2988     size = getSize(operandType(result));
2989
2990     emitcode("; shift right ","result %d, left %d",size,
2991              AOP_SIZE(left));
2992
2993     /* I suppose that the left size >= result size */
2994     if (shCount == 0) {
2995         assert(0);
2996     }
2997
2998     else if(shCount >= (size * 8))
2999         while(size--)
3000             aopPut(AOP(result),zero,size);
3001     else{
3002         switch (size) {
3003         case 1:
3004             genrshOne(result, left, shCount);
3005             break;
3006         case 2:
3007             /* PENDING: sign support */
3008             genrshTwo(result, left, shCount, FALSE);
3009             break;
3010         case 4:
3011             assert(0);
3012             break;
3013         default:
3014             assert(0);
3015         }
3016     }
3017     freeAsmop(left,NULL,ic);
3018     freeAsmop(result,NULL,ic);
3019 }
3020
3021 /*-----------------------------------------------------------------*/
3022 /* genRightShift - generate code for right shifting                */
3023 /*-----------------------------------------------------------------*/
3024 static void genRightShift (iCode *ic)
3025 {
3026     operand *left,*right, *result;
3027
3028     right = IC_RIGHT(ic);
3029     left  = IC_LEFT(ic);
3030     result = IC_RESULT(ic);
3031
3032     aopOp(right,ic,FALSE);
3033
3034     /* if the shift count is known then do it 
3035     as efficiently as possible */
3036     if (AOP_TYPE(right) == AOP_LIT) {
3037         genRightShiftLiteral (left,right,result,ic);
3038         return ;
3039     }
3040     else {
3041         assert(0);
3042     }
3043 }
3044
3045 /*-----------------------------------------------------------------*/
3046 /* genGenPointerGet - gget value from generic pointer space        */
3047 /*-----------------------------------------------------------------*/
3048 static void genGenPointerGet (operand *left,
3049                               operand *result, iCode *ic)
3050 {
3051     int size, offset ;
3052     link *retype = getSpec(operandType(result));
3053
3054     aopOp(left,ic,FALSE);
3055     aopOp(result,ic,FALSE);
3056
3057     if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3058         /* Just do it */
3059         emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3060         aopPut(AOP(result),"a", 0);
3061         freeAsmop(left,NULL,ic);
3062         goto release;
3063     }
3064
3065     /* For now we always load into IY */
3066     /* if this is remateriazable */
3067     if (AOP_TYPE(left) == AOP_IMMD)
3068         emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3069     else { /* we need to get it byte by byte */
3070         emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
3071         emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
3072     }
3073     /* so iy now contains the address */
3074     freeAsmop(left,NULL,ic);
3075
3076     /* if bit then unpack */
3077     if (IS_BITVAR(retype)) {
3078         assert(0);
3079     }
3080     else {
3081         size = AOP_SIZE(result);
3082         offset = 0 ;
3083
3084         while (size--) {
3085             /* PENDING: make this better */
3086             if (AOP(result)->type == AOP_REG) {
3087                 aopPut(AOP(result),"(hl)",offset++);
3088             }
3089             else {
3090                 emitcode("ld", "a,(hl)", offset);
3091                 aopPut(AOP(result),"a",offset++);
3092             }
3093             if (size) {
3094                 emitcode("inc", "hl");
3095             }
3096         }
3097     }
3098
3099  release:
3100     freeAsmop(result,NULL,ic);
3101 }
3102
3103 /*-----------------------------------------------------------------*/
3104 /* genPointerGet - generate code for pointer get                   */
3105 /*-----------------------------------------------------------------*/
3106 static void genPointerGet (iCode *ic)
3107 {
3108     operand *left, *result ;
3109     link *type, *etype;
3110
3111     left = IC_LEFT(ic);
3112     result = IC_RESULT(ic) ;
3113
3114     /* depending on the type of pointer we need to
3115     move it to the correct pointer register */
3116     type = operandType(left);
3117     etype = getSpec(type);
3118
3119     genGenPointerGet (left,result,ic);
3120 }
3121
3122 bool isRegOrLit(asmop *aop)
3123 {
3124     if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3125         return TRUE;
3126     return FALSE;
3127 }
3128
3129 /*-----------------------------------------------------------------*/
3130 /* genGenPointerSet - stores the value into a pointer location        */
3131 /*-----------------------------------------------------------------*/
3132 static void genGenPointerSet (operand *right,
3133                               operand *result, iCode *ic)
3134 {    
3135     int size, offset ;
3136     link *retype = getSpec(operandType(right));
3137
3138     aopOp(result,ic,FALSE);
3139     aopOp(right,ic,FALSE);
3140
3141     /* Handle the exceptions first */
3142     if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3143         /* Just do it */
3144         char *l = aopGet(AOP(right), 0, FALSE);
3145         MOVA(l);
3146         emitcode("ld", "(%s),a", getPairName(AOP(result)));
3147         freeAsmop(result,NULL,ic);
3148         goto release;
3149     }
3150         
3151     /* if the operand is already in dptr 
3152        then we do nothing else we move the value to dptr */
3153     if (AOP_TYPE(result) != AOP_STR) {
3154         /* if this is remateriazable */
3155         if (AOP_TYPE(result) == AOP_IMMD) {
3156             emitcode("", "; Error 2");
3157             emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3158         }
3159         else { /* we need to get it byte by byte */
3160             /* PENDING: do this better */
3161             emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
3162             emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
3163         }
3164     }
3165     /* so hl know contains the address */
3166     freeAsmop(result,NULL,ic);
3167
3168     /* if bit then unpack */
3169     if (IS_BITVAR(retype)) {
3170         assert(0);
3171     }
3172     else {
3173         size = AOP_SIZE(right);
3174         offset = 0 ;
3175
3176         while (size--) {
3177             char *l = aopGet(AOP(right),offset,FALSE);
3178
3179             if (isRegOrLit(AOP(right))) {
3180                 emitcode("ld", "(hl),%s", l);
3181             }
3182             else {
3183                 MOVA(l);
3184                 emitcode("ld", "(hl),a", offset);
3185             }
3186             if (size) {
3187                 emitcode("inc", "hl");
3188             }
3189             offset++;
3190         }
3191     }
3192     release:
3193     freeAsmop(right,NULL,ic);
3194 }
3195
3196 /*-----------------------------------------------------------------*/
3197 /* genPointerSet - stores the value into a pointer location        */
3198 /*-----------------------------------------------------------------*/
3199 static void genPointerSet (iCode *ic)
3200 {    
3201     operand *right, *result ;
3202     link *type, *etype;
3203
3204     right = IC_RIGHT(ic);
3205     result = IC_RESULT(ic) ;
3206
3207     /* depending on the type of pointer we need to
3208     move it to the correct pointer register */
3209     type = operandType(result);
3210     etype = getSpec(type);
3211     
3212     genGenPointerSet (right,result,ic);
3213 }
3214
3215 /*-----------------------------------------------------------------*/
3216 /* genIfx - generate code for Ifx statement                        */
3217 /*-----------------------------------------------------------------*/
3218 static void genIfx (iCode *ic, iCode *popIc)
3219 {
3220     operand *cond = IC_COND(ic);
3221     int isbit =0;
3222
3223     aopOp(cond,ic,FALSE);
3224
3225     /* get the value into acc */
3226     if (AOP_TYPE(cond) != AOP_CRY)
3227         toBoolean(cond);
3228     else
3229         isbit = 1;
3230     /* the result is now in the accumulator */
3231     freeAsmop(cond,NULL,ic);
3232
3233     /* if there was something to be popped then do it */
3234     if (popIc)
3235         genIpop(popIc);
3236
3237     /* if the condition is  a bit variable */
3238     if (isbit && IS_ITEMP(cond) && 
3239         SPIL_LOC(cond))
3240         genIfxJump(ic,SPIL_LOC(cond)->rname);
3241     else
3242         if (isbit && !IS_ITEMP(cond))
3243             genIfxJump(ic,OP_SYMBOL(cond)->rname);
3244         else
3245             genIfxJump(ic,"a");
3246
3247     ic->generated = 1;
3248 }
3249
3250 /*-----------------------------------------------------------------*/
3251 /* genAddrOf - generates code for address of                       */
3252 /*-----------------------------------------------------------------*/
3253 static void genAddrOf (iCode *ic)
3254 {
3255     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3256
3257     aopOp(IC_RESULT(ic),ic,FALSE);
3258
3259     /* if the operand is on the stack then we 
3260     need to get the stack offset of this
3261     variable */
3262     if (sym->onStack) {
3263         /* if it has an offset  then we need to compute it */
3264         emitcode("push", "de");
3265         emitcode("push", "ix");
3266         emitcode("pop", "hl");
3267         emitcode("ld", "de,#%d", sym->stack);
3268         emitcode("add", "hl,de");
3269         emitcode("pop", "de");
3270     }
3271     else {
3272         emitcode("ld", "hl,#%s", sym->rname);
3273     }
3274     aopPut(AOP(IC_RESULT(ic)), "l", 0);
3275     aopPut(AOP(IC_RESULT(ic)), "h", 1);
3276
3277     freeAsmop(IC_RESULT(ic),NULL,ic);
3278 }
3279
3280 /*-----------------------------------------------------------------*/
3281 /* genAssign - generate code for assignment                        */
3282 /*-----------------------------------------------------------------*/
3283 static void genAssign (iCode *ic)
3284 {
3285     operand *result, *right;
3286     int size, offset ;
3287     unsigned long lit = 0L;
3288
3289     result = IC_RESULT(ic);
3290     right  = IC_RIGHT(ic) ;
3291
3292 #if 1
3293     /* Dont bother assigning if they are the same */
3294     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3295         emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3296         return;
3297     }
3298 #endif
3299
3300     aopOp(right,ic,FALSE);
3301     aopOp(result,ic,TRUE);
3302
3303     /* if they are the same registers */
3304     if (sameRegs(AOP(right),AOP(result))) {
3305         emitcode("", "; (registers are the same)");
3306         goto release;
3307     }
3308
3309     /* if the result is a bit */
3310     if (AOP_TYPE(result) == AOP_CRY) {
3311         assert(0);
3312     }
3313
3314     /* general case */
3315     size = AOP_SIZE(result);
3316     offset = 0;
3317
3318     if(AOP_TYPE(right) == AOP_LIT)
3319         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3320     if((size > 1) &&
3321        (AOP_TYPE(result) != AOP_REG) &&
3322        (AOP_TYPE(right) == AOP_LIT) &&
3323        !IS_FLOAT(operandType(right)) &&
3324        (lit < 256L)){
3325         emitcode("xor","a,a");
3326         /* Work from the top down.
3327            Done this way so that we can use the cached copy of 0
3328            in A for a fast clear */
3329         while (size--) {
3330             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
3331                 aopPut(AOP(result),"a",size);
3332             else
3333                 aopPut(AOP(result),
3334                        aopGet(AOP(right),size,FALSE),
3335                        size);
3336         }
3337     } else {
3338         while (size--) {
3339             aopPut(AOP(result),
3340                    aopGet(AOP(right),offset,FALSE),
3341                    offset);
3342             offset++;
3343         }
3344     }
3345     
3346 release:
3347     freeAsmop(right,NULL,ic);
3348     freeAsmop(result,NULL,ic);
3349 }   
3350
3351 /*-----------------------------------------------------------------*/
3352 /* genJumpTab - genrates code for jump table                       */
3353 /*-----------------------------------------------------------------*/
3354 static void genJumpTab (iCode *ic)
3355 {
3356     symbol *jtab;
3357     char *l;
3358
3359     aopOp(IC_JTCOND(ic),ic,FALSE);
3360     /* get the condition into accumulator */
3361     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3362     MOVA(l);
3363     emitcode("push", "de");
3364     emitcode("ld", "e,%s", l);
3365     emitcode("ld", "d,#0");
3366     jtab = newiTempLabel(NULL);
3367     emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3368     emitcode("add", "hl,de");
3369     emitcode("add", "hl,de");
3370     freeAsmop(IC_JTCOND(ic),NULL,ic);
3371     emitcode("pop", "de");
3372     emitcode("jp", "(hl)");
3373     emitcode("","%05d$:",jtab->key+100);
3374     /* now generate the jump labels */
3375     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3376          jtab = setNextItem(IC_JTLABELS(ic)))
3377         emitcode("jp", LABEL_STR, jtab->key+100);
3378 }
3379
3380 /*-----------------------------------------------------------------*/
3381 /* genCast - gen code for casting                                  */
3382 /*-----------------------------------------------------------------*/
3383 static void genCast (iCode *ic)
3384 {
3385     operand *result = IC_RESULT(ic);
3386     link *ctype = operandType(IC_LEFT(ic));
3387     operand *right = IC_RIGHT(ic);
3388     int size, offset ;
3389
3390     /* if they are equivalent then do nothing */
3391     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3392         return ;
3393
3394     aopOp(right,ic,FALSE) ;
3395     aopOp(result,ic,FALSE);
3396
3397     /* if the result is a bit */
3398     if (AOP_TYPE(result) == AOP_CRY) {
3399         assert(0);
3400     }
3401
3402     /* if they are the same size : or less */
3403     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3404
3405         /* if they are in the same place */
3406         if (sameRegs(AOP(right),AOP(result)))
3407             goto release;
3408
3409         /* if they in different places then copy */
3410         size = AOP_SIZE(result);
3411         offset = 0 ;
3412         while (size--) {
3413             aopPut(AOP(result),
3414                    aopGet(AOP(right),offset,FALSE),
3415                    offset);
3416             offset++;
3417         }
3418         goto release;
3419     }
3420
3421     /* if the result is of type pointer */
3422     if (IS_PTR(ctype)) {
3423         assert(0);
3424     }
3425     
3426     /* so we now know that the size of destination is greater
3427     than the size of the source */
3428     /* we move to result for the size of source */
3429     size = AOP_SIZE(right);
3430     offset = 0 ;
3431     while (size--) {
3432         aopPut(AOP(result),
3433                aopGet(AOP(right),offset,FALSE),
3434                offset);
3435         offset++;
3436     }
3437
3438     /* now depending on the sign of the destination */
3439     size = AOP_SIZE(result) - AOP_SIZE(right);
3440     /* Unsigned or not an integral type - right fill with zeros */
3441     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3442         while (size--)
3443             aopPut(AOP(result),zero,offset++);
3444     } else {
3445         /* we need to extend the sign :{ */
3446         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3447                          FALSE);
3448         MOVA(l);
3449         emitcode("", "; genCast: sign extend untested.");
3450         emitcode("rla", "");
3451         emitcode("sbc", "a,a");
3452         while (size--)
3453             aopPut(AOP(result),"a",offset++);   
3454     }
3455
3456 release:
3457     freeAsmop(right, NULL, ic);
3458     freeAsmop(result, NULL, ic);
3459 }
3460
3461 /*-----------------------------------------------------------------*/
3462 /* genReceive - generate code for a receive iCode                  */
3463 /*-----------------------------------------------------------------*/
3464 static void genReceive (iCode *ic)
3465 {    
3466     if (isOperandInFarSpace(IC_RESULT(ic)) && 
3467         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3468           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3469         assert(0);
3470     } else {
3471         accInUse++;
3472         aopOp(IC_RESULT(ic),ic,FALSE);  
3473         accInUse--;
3474         assignResultValue(IC_RESULT(ic));       
3475     }
3476
3477     freeAsmop(IC_RESULT(ic),NULL,ic);
3478 }
3479
3480 /*-----------------------------------------------------------------*/
3481 /* genZ80Code - generate code for Z80 based controllers            */
3482 /*-----------------------------------------------------------------*/
3483 void genZ80Code (iCode *lic)
3484 {
3485     iCode *ic;
3486     int cln = 0;
3487
3488     lineHead = lineCurr = NULL;
3489
3490     /* if debug information required */
3491     if (options.debug && currFunc) { 
3492         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3493         debugLine = 1;
3494         if (IS_STATIC(currFunc->etype))
3495             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
3496         else
3497             emitcode("","G$%s$0$0 ==.",currFunc->name);
3498         debugLine = 0;
3499     }
3500     /* stack pointer name */
3501     spname = "sp";
3502     
3503  
3504     for (ic = lic ; ic ; ic = ic->next ) {
3505         
3506         if ( cln != ic->lineno ) {
3507             if ( options.debug ) {
3508                 debugLine = 1;
3509                 emitcode("","C$%s$%d$%d$%d ==.",
3510                          ic->filename,ic->lineno,
3511                          ic->level,ic->block);
3512                 debugLine = 0;
3513             }
3514             emitcode(";","%s %d",ic->filename,ic->lineno);
3515             cln = ic->lineno ;
3516         }
3517         /* if the result is marked as
3518            spilt and rematerializable or code for
3519            this has already been generated then
3520            do nothing */
3521         if (resultRemat(ic) || ic->generated ) 
3522             continue ;
3523         
3524         /* depending on the operation */
3525         switch (ic->op) {
3526         case '!' :
3527             emitcode("", "; genNot");
3528             genNot(ic);
3529             break;
3530             
3531         case '~' :
3532             emitcode("", "; genCpl");
3533             genCpl(ic);
3534             break;
3535             
3536         case UNARYMINUS:
3537             emitcode("", "; genUminus");
3538             genUminus (ic);
3539             break;
3540             
3541         case IPUSH:
3542             emitcode("", "; genIpush");
3543             genIpush (ic);
3544             break;
3545             
3546         case IPOP:
3547             /* IPOP happens only when trying to restore a 
3548                spilt live range, if there is an ifx statement
3549                following this pop then the if statement might
3550                be using some of the registers being popped which
3551                would destory the contents of the register so
3552                we need to check for this condition and handle it */
3553             if (ic->next            && 
3554                 ic->next->op == IFX &&
3555                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3556                 emitcode("", "; genIfx");
3557                 genIfx (ic->next,ic);
3558             }
3559             else {
3560                 emitcode("", "; genIpop");
3561                 genIpop (ic);
3562             }
3563             break; 
3564             
3565         case CALL:
3566             emitcode("", "; genCall");
3567             genCall (ic);
3568             break;
3569             
3570         case PCALL:
3571             emitcode("", "; genPcall");
3572             genPcall (ic);
3573             break;
3574             
3575         case FUNCTION:
3576             emitcode("", "; genFunction");
3577             genFunction (ic);
3578             break;
3579             
3580         case ENDFUNCTION:
3581             emitcode("", "; genEndFunction");
3582             genEndFunction (ic);
3583             break;
3584             
3585         case RETURN:
3586             emitcode("", "; genRet");
3587             genRet (ic);
3588             break;
3589             
3590         case LABEL:
3591             emitcode("", "; genLabel");
3592             genLabel (ic);
3593             break;
3594             
3595         case GOTO:
3596             emitcode("", "; genGoto");
3597             genGoto (ic);
3598             break;
3599             
3600         case '+' :
3601             emitcode("", "; genPlus");
3602             genPlus (ic) ;
3603             break;
3604             
3605         case '-' :
3606             emitcode("", "; genMinus");
3607             genMinus (ic);
3608             break;
3609             
3610         case '*' :
3611             emitcode("", "; genMult");
3612             genMult (ic);
3613             break;
3614             
3615         case '/' :
3616             emitcode("", "; genDiv");
3617             genDiv (ic) ;
3618             break;
3619             
3620         case '%' :
3621             emitcode("", "; genMod");
3622             genMod (ic);
3623             break;
3624             
3625         case '>' :
3626             emitcode("", "; genCmpGt");
3627             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
3628             break;
3629             
3630         case '<' :
3631             emitcode("", "; genCmpLt");
3632             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3633             break;
3634             
3635         case LE_OP:
3636         case GE_OP:
3637         case NE_OP:
3638             
3639             /* note these two are xlated by algebraic equivalence
3640                during parsing SDCC.y */
3641             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3642                    "got '>=' or '<=' shouldn't have come here");
3643             break;      
3644             
3645         case EQ_OP:
3646             emitcode("", "; genCmpEq");
3647             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3648             break;          
3649             
3650         case AND_OP:
3651             emitcode("", "; genAndOp");
3652             genAndOp (ic);
3653             break;
3654             
3655         case OR_OP:
3656             emitcode("", "; genOrOp");
3657             genOrOp (ic);
3658             break;
3659             
3660         case '^' :
3661             emitcode("", "; genXor");
3662             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3663             break;
3664             
3665         case '|' :
3666             emitcode("", "; genOr");
3667             genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3668             break;
3669             
3670         case BITWISEAND:
3671             emitcode("", "; genAnd");
3672             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3673             break;
3674             
3675         case INLINEASM:
3676             emitcode("", "; genInline");
3677             genInline (ic);
3678             break;
3679             
3680         case RRC:
3681             emitcode("", "; genRRC");
3682             genRRC (ic);
3683             break;
3684             
3685         case RLC:
3686             emitcode("", "; genRLC");
3687             genRLC (ic);
3688             break;
3689             
3690         case GETHBIT:
3691             emitcode("", "; genHBIT");
3692             assert(0);
3693             
3694         case LEFT_OP:
3695             emitcode("", "; genLeftShift");
3696             genLeftShift (ic);
3697             break;
3698             
3699         case RIGHT_OP:
3700             emitcode("", "; genRightShift");
3701             genRightShift (ic);
3702             break;
3703             
3704         case GET_VALUE_AT_ADDRESS:
3705             emitcode("", "; genPointerGet");
3706             genPointerGet(ic);
3707             break;
3708             
3709         case '=' :
3710
3711             if (POINTER_SET(ic)) {
3712                 emitcode("", "; genAssign (pointer)");
3713                 genPointerSet(ic);
3714             }
3715             else {
3716                 emitcode("", "; genAssign");
3717                 genAssign(ic);
3718             }
3719             break;
3720             
3721         case IFX:
3722             emitcode("", "; genIfx");
3723             genIfx (ic,NULL);
3724             break;
3725             
3726         case ADDRESS_OF:
3727             emitcode("", "; genAddrOf");
3728             genAddrOf (ic);
3729             break;
3730             
3731         case JUMPTABLE:
3732             emitcode("", "; genJumpTab");
3733             genJumpTab (ic);
3734             break;
3735             
3736         case CAST:
3737             emitcode("", "; genCast");
3738             genCast (ic);
3739             break;
3740             
3741         case RECEIVE:
3742             emitcode("", "; genReceive");
3743             genReceive(ic);
3744             break;
3745             
3746         case SEND:
3747             emitcode("", "; addSet");
3748             addSet(&sendSet,ic);
3749             break;
3750
3751         default :
3752             ic = ic;
3753             /*      piCode(ic,stdout); */
3754             
3755         }
3756     }
3757     
3758
3759     /* now we are ready to call the 
3760        peep hole optimizer */
3761     /*    if (!options.nopeep)
3762           peepHole (&lineHead); */
3763
3764     /* now do the actual printing */
3765     printLine (lineHead,codeOutFile);
3766     return;
3767 }