* Added common.h
[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
55 /* this is the down and dirty file with all kinds of kludgy & hacky
56    stuff. This is what it is all about CODE GENERATION for a specific MCU.
57    Some of the routines may be reusable, will have to see */
58
59 static char *zero = "#0x00";
60 static char *one  = "#0x01";
61 static char *spname ;
62 static char *fReturn[] = {"l", "h", "e", "d" };
63 static char *accUse[] = {"a" };
64 short rbank = -1;
65 short accInUse = 0 ;
66 short inLine = 0;
67 short debugLine = 0;
68 short nregssaved = 0;
69 extern int ptrRegReq ;
70 extern int nRegs;
71 extern FILE *codeOutFile;
72 set *sendSet = NULL;
73 #define RESULTONSTACK(x) \
74                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
75                          IC_RESULT(x)->aop->type == AOP_STK )
76
77 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
78 #define CLRC    emitcode("xor","a,a");
79
80 #define LABEL_STR       "%05d$"
81
82 lineNode *lineHead = NULL;
83 lineNode *lineCurr = NULL;
84
85 unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
86 0xE0, 0xC0, 0x80, 0x00};
87 unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
88 0x07, 0x03, 0x01, 0x00};
89
90 static int _lastStack = 0;
91
92 #define LSB     0
93 #define MSB16   1
94 #define MSB24   2
95 #define MSB32   3
96
97 /* Stack frame:
98
99    IX+4         param0  LH
100    IX+2         ret     LH
101    IX+0         ix      LH
102    IX-2         temp0   LH
103 */
104
105 /*-----------------------------------------------------------------*/
106 /* emitcode - writes the code into a file : for now it is simple    */
107 /*-----------------------------------------------------------------*/
108 void emitcode (const char *inst, const char *fmt, ...)
109 {
110     va_list ap;
111     char lb[MAX_INLINEASM];  
112     char *lbp = lb;
113
114     va_start(ap,fmt);   
115
116     if (*inst != '\0') {
117         sprintf(lb,"%s\t",inst);
118         vsprintf(lb+(strlen(lb)),fmt,ap);
119     }  else 
120         vsprintf(lb,fmt,ap);
121
122     while (isspace(*lbp)) lbp++;
123
124     if (lbp && *lbp) 
125         lineCurr = (lineCurr ?
126                     connectLine(lineCurr,newLineNode(lb)) :
127                     (lineHead = newLineNode(lb)));
128     lineCurr->isInline = inLine;
129     lineCurr->isDebug  = debugLine;
130     va_end(ap);
131 }
132
133 const char *getPairName(asmop *aop)
134 {
135     if (aop->type == AOP_REG) {
136         switch (aop->aopu.aop_reg[0]->rIdx) {
137         case C_IDX:
138             return "bc";
139             break;
140         case E_IDX:
141             return "de";
142             break;
143         case L_IDX:
144             return "hl";
145             break;
146         }
147     }
148     else if (aop->type == AOP_STR) {
149         switch (*aop->aopu.aop_str[0]) {
150         case 'c':
151             return "bc";
152             break;
153         case 'e':
154             return "de";
155             break;
156         case 'l':
157             return "hl";
158             break;
159         }
160     }
161     assert(0);
162     return NULL;
163 }
164
165 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
166 bool isPair(asmop *aop)
167 {
168     if (aop->size == 2) {
169         if (aop->type == AOP_REG) {
170             if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
171                 return TRUE;
172             }
173             if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
174                 return TRUE;
175             }
176             if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
177                 return TRUE;
178             }
179         }
180         if (aop->type == AOP_STR) {
181             if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
182                 return TRUE;
183             }
184             if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
185                 return TRUE;
186             }
187             if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
188                 return TRUE;
189             }
190         }
191     }
192     return FALSE;
193 }
194
195 /** Push a register pair onto the stack */
196 void genPairPush(asmop *aop)
197 {
198     emitcode("push", "%s", getPairName(aop));
199 }
200
201 /*-----------------------------------------------------------------*/
202 /* newAsmop - creates a new asmOp                                  */
203 /*-----------------------------------------------------------------*/
204 static asmop *newAsmop (short type)
205 {
206     asmop *aop;
207
208     ALLOC(aop,sizeof(asmop));
209     aop->type = type;
210     return aop;
211 }
212
213 /*-----------------------------------------------------------------*/
214 /* aopForSym - for a true symbol                                   */
215 /*-----------------------------------------------------------------*/
216 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
217 {
218     asmop *aop;
219     memmap *space= SPEC_OCLS(sym->etype);
220
221     /* if already has one */
222     if (sym->aop)
223         return sym->aop;
224
225     /* Assign depending on the storage class */
226     if (sym->onStack || sym->iaccess) {
227         sym->aop = aop = newAsmop(AOP_STK);
228         aop->size = getSize(sym->type);
229
230         aop->aopu.aop_stk = sym->stack;
231         return aop;
232     }
233
234     /* special case for a function */
235     if (IS_FUNC(sym->type)) {   
236         sym->aop = aop = newAsmop(AOP_IMMD);    
237         ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
238         strcpy(aop->aopu.aop_immd,sym->rname);
239         aop->size = 2;
240         return aop;
241     }
242
243     /* only remaining is far space */
244     /* in which case DPTR gets the address */
245     sym->aop = aop = newAsmop(AOP_IY);
246     emitcode ("ld","iy,#%s", sym->rname);
247     aop->size = getSize(sym->type);
248     aop->aopu.aop_dir = sym->rname;
249
250     /* if it is in code space */
251     if (IN_CODESPACE(space))
252         aop->code = 1;
253
254     return aop;     
255 }
256
257 /*-----------------------------------------------------------------*/
258 /* aopForRemat - rematerialzes an object                           */
259 /*-----------------------------------------------------------------*/
260 static asmop *aopForRemat (symbol *sym)
261 {
262     char *s = buffer;   
263     iCode *ic = sym->rematiCode;
264     asmop *aop = newAsmop(AOP_IMMD);
265
266     while (1) {
267         /* if plus or minus print the right hand side */
268         if (ic->op == '+' || ic->op == '-') {
269             sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
270                     ic->op );
271             s += strlen(s);
272             ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
273             continue ;
274         }
275         /* we reached the end */
276         sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
277         break;
278     }
279
280     ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
281     strcpy(aop->aopu.aop_immd,buffer);    
282     return aop;        
283 }
284
285 /*-----------------------------------------------------------------*/
286 /* regsInCommon - two operands have some registers in common       */
287 /*-----------------------------------------------------------------*/
288 bool regsInCommon (operand *op1, operand *op2)
289 {
290     symbol *sym1, *sym2;
291     int i;
292
293     /* if they have registers in common */
294     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
295         return FALSE ;
296
297     sym1 = OP_SYMBOL(op1);
298     sym2 = OP_SYMBOL(op2);
299
300     if (sym1->nRegs == 0 || sym2->nRegs == 0)
301         return FALSE ;
302
303     for (i = 0 ; i < sym1->nRegs ; i++) {
304         int j;
305         if (!sym1->regs[i])
306             continue ;
307
308         for (j = 0 ; j < sym2->nRegs ;j++ ) {
309             if (!sym2->regs[j])
310                 continue ;
311
312             if (sym2->regs[j] == sym1->regs[i])
313                 return TRUE ;
314         }
315     }
316
317     return FALSE ;
318 }
319
320 /*-----------------------------------------------------------------*/
321 /* operandsEqu - equivalent                                        */
322 /*-----------------------------------------------------------------*/
323 bool operandsEqu ( operand *op1, operand *op2)
324 {
325     symbol *sym1, *sym2;
326
327     /* if they not symbols */
328     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
329         return FALSE;
330
331     sym1 = OP_SYMBOL(op1);
332     sym2 = OP_SYMBOL(op2);
333
334     /* if both are itemps & one is spilt
335        and the other is not then false */
336     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
337         sym1->isspilt != sym2->isspilt )
338         return FALSE ;
339
340     /* if they are the same */
341     if (sym1 == sym2)
342         return TRUE ;
343
344     if (strcmp(sym1->rname,sym2->rname) == 0)
345         return TRUE;
346
347
348     /* if left is a tmp & right is not */
349     if (IS_ITEMP(op1)  && 
350         !IS_ITEMP(op2) &&
351         sym1->isspilt  &&
352         (sym1->usl.spillLoc == sym2))
353         return TRUE;
354
355     if (IS_ITEMP(op2)  && 
356         !IS_ITEMP(op1) &&
357         sym2->isspilt  &&
358         (sym2->usl.spillLoc == sym1))
359         return TRUE ;
360
361     return FALSE ;
362 }
363
364 /*-----------------------------------------------------------------*/
365 /* sameRegs - two asmops have the same registers                   */
366 /*-----------------------------------------------------------------*/
367 bool sameRegs (asmop *aop1, asmop *aop2 )
368 {
369     int i;
370
371     if (aop1 == aop2)
372         return TRUE ;
373
374     if (aop1->type != AOP_REG ||
375         aop2->type != AOP_REG )
376         return FALSE ;
377
378     if (aop1->size != aop2->size)
379         return FALSE ;
380
381     for (i = 0 ; i < aop1->size ; i++ )
382         if (aop1->aopu.aop_reg[i] !=
383             aop2->aopu.aop_reg[i] )
384             return FALSE ;
385
386     return TRUE ;
387 }
388
389 /*-----------------------------------------------------------------*/
390 /* aopOp - allocates an asmop for an operand  :                    */
391 /*-----------------------------------------------------------------*/
392 static void aopOp (operand *op, iCode *ic, bool result)
393 {
394     asmop *aop;
395     symbol *sym;
396     int i;
397
398     if (!op)
399         return ;
400
401     /* if this a literal */
402     if (IS_OP_LITERAL(op)) {
403         op->aop = aop = newAsmop(AOP_LIT);
404         aop->aopu.aop_lit = op->operand.valOperand;
405         aop->size = getSize(operandType(op));
406         return;
407     }
408
409     /* if already has a asmop then continue */
410     if (op->aop)
411         return ;
412
413     /* if the underlying symbol has a aop */
414     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
415         op->aop = OP_SYMBOL(op)->aop;
416         return;
417     }
418
419     /* if this is a true symbol */
420     if (IS_TRUE_SYMOP(op)) {    
421         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
422         return ;
423     }
424
425     /* this is a temporary : this has
426     only four choices :
427     a) register
428     b) spillocation
429     c) rematerialize 
430     d) conditional   
431     e) can be a return use only */
432
433     sym = OP_SYMBOL(op);
434
435     /* if the type is a conditional */
436     if (sym->regType == REG_CND) {
437         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
438         aop->size = 0;
439         return;
440     }
441
442     /* if it is spilt then two situations
443     a) is rematerialize 
444     b) has a spill location */
445     if (sym->isspilt || sym->nRegs == 0) {
446         /* rematerialize it NOW */
447         if (sym->remat) {
448             sym->aop = op->aop = aop =
449                                       aopForRemat (sym);
450             aop->size = getSize(sym->type);
451             return;
452         }
453
454         if (sym->accuse) {
455             int i;
456             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
457             aop->size = getSize(sym->type);
458             for ( i = 0 ; i < 2 ; i++ )
459                 aop->aopu.aop_str[i] = accUse[i];
460             return;  
461         }
462
463         if (sym->ruonly ) {
464             int i;
465             aop = op->aop = sym->aop = newAsmop(AOP_STR);
466             aop->size = getSize(sym->type);
467             for ( i = 0 ; i < 4 ; i++ )
468                 aop->aopu.aop_str[i] = fReturn[i];
469             return;
470         }
471
472         /* else spill location  */
473         sym->aop = op->aop = aop = 
474                                   aopForSym(ic,sym->usl.spillLoc,result);
475         aop->size = getSize(sym->type);
476         return;
477     }
478
479     /* must be in a register */
480     sym->aop = op->aop = aop = newAsmop(AOP_REG);
481     aop->size = sym->nRegs;
482     for ( i = 0 ; i < sym->nRegs ;i++)
483         aop->aopu.aop_reg[i] = sym->regs[i];
484 }
485
486 /*-----------------------------------------------------------------*/
487 /* freeAsmop - free up the asmop given to an operand               */
488 /*----------------------------------------------------------------*/
489 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
490 {   
491     asmop *aop ;
492
493     if (!op)
494         aop = aaop;
495     else 
496         aop = op->aop;
497
498     if (!aop)
499         return ;
500
501     if (aop->freed)
502         goto dealloc; 
503
504     aop->freed = 1;
505
506     switch (aop->type) {
507     case AOP_STK :
508         break;
509     }
510
511 dealloc:
512     /* all other cases just dealloc */
513     if (op ) {
514         op->aop = NULL;
515         if (IS_SYMOP(op)) {
516             OP_SYMBOL(op)->aop = NULL;    
517             /* if the symbol has a spill */
518             if (SPIL_LOC(op))
519                 SPIL_LOC(op)->aop = NULL;
520         }
521     }
522 }
523
524 /*-----------------------------------------------------------------*/
525 /* aopLiteral - string from a literal value                        */
526 /*-----------------------------------------------------------------*/
527 char *aopLiteral (value *val, int offset)
528 {
529     char *rs;
530
531     /* if it is a float then it gets tricky */
532     /* otherwise it is fairly simple */
533     if (!IS_FLOAT(val->type)) {
534         unsigned long v = floatFromVal(val);
535
536         v >>= (offset * 8);
537         sprintf(buffer,"#0x%02x",((char) v) & 0xff);
538         ALLOC_ATOMIC(rs,strlen(buffer)+1);
539         return strcpy (rs,buffer);
540     }
541
542     assert(0);
543 }
544
545 char *aopGetWord(asmop *aop, int offset)
546 {
547     char *s = buffer ;
548     char *rs;
549
550     assert(aop->size == 2);
551     assert(offset == 0);
552
553     /* depending on type */
554     switch (aop->type) {
555     case AOP_IMMD:
556         sprintf (s,"#%s",aop->aopu.aop_immd);
557         ALLOC_ATOMIC(rs,strlen(s)+1);
558         strcpy(rs,s);   
559         return rs;
560         
561     case AOP_LIT: {
562         value * val = aop->aopu.aop_lit;
563         /* if it is a float then it gets tricky */
564         /* otherwise it is fairly simple */
565         if (!IS_FLOAT(val->type)) {
566             unsigned long v = floatFromVal(val);
567
568             sprintf(buffer,"#0x%04lx", v);
569             ALLOC_ATOMIC(rs,strlen(buffer)+1);
570             return strcpy (rs,buffer);
571         }
572         assert(0);
573         return NULL;
574     }
575     }
576     return NULL;
577 }
578
579 /*-----------------------------------------------------------------*/
580 /* aopGet - for fetching value of the aop                          */
581 /*-----------------------------------------------------------------*/
582 static char *aopGet (asmop *aop, int offset, bool bit16)
583 {
584     char *s = buffer ;
585     char *rs;
586
587     /* offset is greater than size then zero */
588     if (offset > (aop->size - 1) &&
589         aop->type != AOP_LIT)
590         return zero;
591
592     /* depending on type */
593     switch (aop->type) {
594     case AOP_IMMD:
595         if (bit16) 
596             sprintf (s,"#%s",aop->aopu.aop_immd);
597         else
598             if (offset) {
599                 assert(offset == 1);
600                 sprintf(s,"#>%s",
601                         aop->aopu.aop_immd);
602             }
603             else
604                 sprintf(s,"#<%s",
605                         aop->aopu.aop_immd);
606         ALLOC_ATOMIC(rs,strlen(s)+1);
607         strcpy(rs,s);   
608         return rs;
609         
610     case AOP_DIR:
611         assert(0);
612         emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
613         sprintf(s, "a");
614         ALLOC_ATOMIC(rs,strlen(s)+1);
615         strcpy(rs,s);   
616         return rs;
617         
618     case AOP_REG:
619         return aop->aopu.aop_reg[offset]->name;
620
621     case AOP_IY:
622         sprintf(s,"%d(iy)", offset);
623         ALLOC_ATOMIC(rs,strlen(s)+1);
624         strcpy(rs,s);   
625         return rs;
626
627     case AOP_STK:
628         sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
629         ALLOC_ATOMIC(rs,strlen(s)+1);
630         strcpy(rs,s);   
631         return rs;
632         
633     case AOP_CRY:
634         assert(0);
635         
636     case AOP_ACC:
637         if (!offset) {
638             return "a";
639         }
640         return "#0x00";
641
642     case AOP_LIT:
643         return aopLiteral (aop->aopu.aop_lit,offset);
644         
645     case AOP_STR:
646         aop->coff = offset;
647         return aop->aopu.aop_str[offset];
648     }
649
650     fprintf(stderr, "Type %u\n", aop->type);
651
652     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
653            "aopget got unsupported aop->type");
654     exit(0);
655 }
656
657 bool isRegString(char *s)
658 {
659     if (!strcmp(s, "b") ||
660         !strcmp(s, "c") ||
661         !strcmp(s, "d") ||
662         !strcmp(s, "e") ||
663         !strcmp(s, "a") ||
664         !strcmp(s, "h") ||
665         !strcmp(s, "l"))
666         return TRUE;
667     return FALSE;
668 }
669
670 bool isConstant(char *s)
671 {
672     return  (*s == '#');
673 }
674
675 bool canAssignToPtr(char *s)
676 {
677     if (isRegString(s))
678         return TRUE;
679     if (isConstant(s))
680         return TRUE;
681     return FALSE;
682 }
683
684 /*-----------------------------------------------------------------*/
685 /* aopPut - puts a string for a aop                                */
686 /*-----------------------------------------------------------------*/
687 static void aopPut (asmop *aop, char *s, int offset)
688 {
689     char *d = buffer ;
690
691     if (aop->size && offset > ( aop->size - 1)) {
692         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
693                "aopPut got offset > aop->size");
694         exit(0);
695     }
696
697     /* will assign value to value */
698     /* depending on where it is ofcourse */
699     switch (aop->type) {
700     case AOP_DIR:
701         assert(0);
702         /* Direct.  Hmmm. */
703         emitcode("ld", "a,%s", s);
704         emitcode("ld", "(%s+%d),a", d, offset);
705         break;
706         
707     case AOP_REG:
708         /* Dont bother if it's a ld x,x */
709         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
710             emitcode("ld","%s,%s",
711                      aop->aopu.aop_reg[offset]->name,s);
712         }
713         break;
714         
715     case AOP_IY:
716         if (!canAssignToPtr(s)) {
717             emitcode("ld", "a,%s", s);
718             emitcode("ld", "%d(iy),a", offset);
719         }
720         else
721             emitcode("ld", "%d(iy),%s", offset, s);
722         break;
723         
724     case AOP_STK:
725         if (!canAssignToPtr(s)) {
726             emitcode("ld", "a,%s", s);
727             emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
728         }
729         else
730             emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
731         break;
732         
733     case AOP_CRY:
734         /* if bit variable */
735         if (!aop->aopu.aop_dir) {
736             emitcode("ld", "a,#0");
737             emitcode("rla", "");
738         } else {
739             /* In bit space but not in C - cant happen */
740             assert(0);
741         }
742         break;
743         
744     case AOP_STR:
745         aop->coff = offset;
746         if (strcmp(aop->aopu.aop_str[offset],s)) {
747             emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
748         }
749         break;
750         
751     case AOP_ACC:
752         aop->coff = offset;
753         if (!offset && (strcmp(s,"acc") == 0))
754             break;
755         if (offset>0) {
756             emitcode("", "; Error aopPut AOP_ACC");
757         }
758         else {
759             if (strcmp(aop->aopu.aop_str[offset],s))
760                 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
761         }
762         break;
763
764     default :
765         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
766                "aopPut got unsupported aop->type");
767         exit(0);    
768     }    
769 }
770
771 #define AOP(op) op->aop
772 #define AOP_TYPE(op) AOP(op)->type
773 #define AOP_SIZE(op) AOP(op)->size
774 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
775
776 /*-----------------------------------------------------------------*/
777 /* getDataSize - get the operand data size                         */
778 /*-----------------------------------------------------------------*/
779 int getDataSize(operand *op)
780 {
781     int size;
782     size = AOP_SIZE(op);
783     if(size == 3) {
784         /* pointer */
785         assert(0);
786     }
787     return size;
788 }
789
790 /*-----------------------------------------------------------------*/
791 /* movLeft2Result - move byte from left to result                  */
792 /*-----------------------------------------------------------------*/
793 static void movLeft2Result (operand *left, int offl,
794                             operand *result, int offr, int sign)
795 {
796     char *l;
797     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
798         l = aopGet(AOP(left),offl,FALSE);
799
800         if (!sign) {
801             aopPut(AOP(result),l,offr);
802         }
803         else {
804             assert(0);
805         }
806     }
807 }
808
809
810 /** Put Acc into a register set 
811  */
812 void outAcc(operand *result)
813 {
814     int size, offset;
815     size = getDataSize(result);
816     if (size){
817         aopPut(AOP(result),"a",0);
818         size--;
819         offset = 1;
820         /* unsigned or positive */
821         while (size--){
822             aopPut(AOP(result),zero,offset++);
823         }
824     }
825 }
826
827 /** Take the value in carry and put it into a register
828  */
829 void outBitC(operand *result)
830 {
831     /* if the result is bit */
832     if (AOP_TYPE(result) == AOP_CRY) {
833         emitcode("", "; Note: outBitC form 1");
834         aopPut(AOP(result),"blah",0);
835     }
836     else {
837         emitcode("ld", "a,#0");
838         emitcode("rla", "");
839         outAcc(result);
840     }
841 }
842
843 /*-----------------------------------------------------------------*/
844 /* toBoolean - emit code for orl a,operator(sizeop)                */
845 /*-----------------------------------------------------------------*/
846 void toBoolean(operand *oper)
847 {
848     int size = AOP_SIZE(oper);
849     int offset = 0;
850     if (size>1) {
851         emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
852         size--;
853         while (size--) 
854             emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
855     }
856     else {
857         CLRC;
858         emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
859     }
860 }
861
862 /*-----------------------------------------------------------------*/
863 /* genNot - generate code for ! operation                          */
864 /*-----------------------------------------------------------------*/
865 static void genNot (iCode *ic)
866 {
867     link *optype = operandType(IC_LEFT(ic));
868
869     /* assign asmOps to operand & result */
870     aopOp (IC_LEFT(ic),ic,FALSE);
871     aopOp (IC_RESULT(ic),ic,TRUE);
872
873     /* if in bit space then a special case */
874     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
875         assert(0);
876     }
877
878     /* if type float then do float */
879     if (IS_FLOAT(optype)) {
880         assert(0);
881     }
882
883     toBoolean(IC_LEFT(ic));
884
885     /* Not of A:
886        If A == 0, !A = 1
887        else A = 0
888        So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
889     emitcode("sub", "a,#0x01");
890     outBitC(IC_RESULT(ic));
891
892     /* release the aops */
893     freeAsmop(IC_LEFT(ic),NULL,ic);
894     freeAsmop(IC_RESULT(ic),NULL,ic);
895 }
896
897 /*-----------------------------------------------------------------*/
898 /* genCpl - generate code for complement                           */
899 /*-----------------------------------------------------------------*/
900 static void genCpl (iCode *ic)
901 {
902     int offset = 0;
903     int size ;
904
905
906     /* assign asmOps to operand & result */
907     aopOp (IC_LEFT(ic),ic,FALSE);
908     aopOp (IC_RESULT(ic),ic,TRUE);
909
910     /* if both are in bit space then 
911     a special case */
912     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
913         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
914         assert(0);
915     } 
916
917     size = AOP_SIZE(IC_RESULT(ic));
918     while (size--) {
919         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
920         MOVA(l);       
921         emitcode("cpl","");
922         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
923     }
924
925     /* release the aops */
926     freeAsmop(IC_LEFT(ic),NULL,ic);
927     freeAsmop(IC_RESULT(ic),NULL,ic);
928 }
929
930 /*-----------------------------------------------------------------*/
931 /* genUminus - unary minus code generation                         */
932 /*-----------------------------------------------------------------*/
933 static void genUminus (iCode *ic)
934 {
935     assert(0);
936 }
937
938
939 /*-----------------------------------------------------------------*/
940 /* assignResultValue -                                             */
941 /*-----------------------------------------------------------------*/
942 void assignResultValue(operand * oper)
943 {
944     int offset = 0;
945     int size = AOP_SIZE(oper);
946     while (size--) {
947         aopPut(AOP(oper),fReturn[offset],offset);
948         offset++;
949     }
950 }
951
952 /*-----------------------------------------------------------------*/
953 /* genIpush - genrate code for pushing this gets a little complex  */
954 /*-----------------------------------------------------------------*/
955 static void genIpush (iCode *ic)
956 {
957     int size, offset = 0 ;
958     char *l;
959
960
961     /* if this is not a parm push : ie. it is spill push 
962        and spill push is always done on the local stack */
963     if (!ic->parmPush) {
964         /* and the item is spilt then do nothing */
965         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
966             return ;
967
968         aopOp(IC_LEFT(ic),ic,FALSE);
969         size = AOP_SIZE(IC_LEFT(ic));
970         /* push it on the stack */
971         if (isPair(AOP(IC_LEFT(ic)))) {
972             emitcode("push", getPairName(AOP(IC_LEFT(ic))));
973         }
974         else {
975             offset = size;
976             while (size--) {
977                 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
978                 /* Simple for now - load into A and PUSH AF */
979                 emitcode("ld", "a,%s", l);
980                 emitcode("push", "af");
981                 emitcode("inc", "sp");
982             }
983         }
984         return ;        
985     }
986
987     /* Hmmm... what about saving the currently used registers
988        at this point? */
989
990     /* then do the push */
991     aopOp(IC_LEFT(ic),ic,FALSE);
992
993     size = AOP_SIZE(IC_LEFT(ic));
994
995     if (isPair(AOP(IC_LEFT(ic)))) {
996         emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
997     }
998     else {
999         if (size == 2) {
1000             char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
1001             if (s) {
1002                 emitcode("ld", "hl,%s", s);
1003                 emitcode("push", "hl");
1004                 goto release;
1005             }
1006         }
1007         offset = size;
1008         while (size--) {
1009             l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1010             emitcode("ld", "a,%s", l);
1011             emitcode("push", "af");
1012             emitcode("inc", "sp");
1013         }       
1014     }
1015  release:
1016     freeAsmop(IC_LEFT(ic),NULL,ic);
1017 }
1018
1019 /*-----------------------------------------------------------------*/
1020 /* genIpop - recover the registers: can happen only for spilling   */
1021 /*-----------------------------------------------------------------*/
1022 static void genIpop (iCode *ic)
1023 {
1024     int size,offset ;
1025
1026
1027     /* if the temp was not pushed then */
1028     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1029         return ;
1030
1031     aopOp(IC_LEFT(ic),ic,FALSE);
1032     size = AOP_SIZE(IC_LEFT(ic));
1033     offset = (size-1);
1034     if (isPair(AOP(IC_LEFT(ic)))) {
1035         emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1036     }
1037     else {
1038         while (size--) {
1039             emitcode("dec", "sp");
1040             emitcode("pop", "hl");
1041             aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1042         }
1043     }
1044
1045     freeAsmop(IC_LEFT(ic),NULL,ic);
1046 }
1047
1048 /** Emit the code for a call statement 
1049  */
1050 static void emitCall (iCode *ic, bool ispcall)
1051 {
1052     /* if caller saves & we have not saved then */
1053     if (!ic->regsSaved) {
1054         /* PENDING */
1055     }
1056
1057     /* if send set is not empty then assign */
1058     if (sendSet) {
1059         iCode *sic ;
1060
1061         for (sic = setFirstItem(sendSet) ; sic ; 
1062              sic = setNextItem(sendSet)) {
1063             int size, offset = 0;
1064             aopOp(IC_LEFT(sic),sic,FALSE);
1065             size = AOP_SIZE(IC_LEFT(sic));
1066             while (size--) {
1067                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1068                                 FALSE);
1069                 if (strcmp(l,fReturn[offset]))
1070                     emitcode("ld","%s,%s",
1071                              fReturn[offset],
1072                              l);
1073                 offset++;
1074             }
1075             freeAsmop (IC_LEFT(sic),NULL,sic);
1076         }
1077         sendSet = NULL;
1078     }
1079
1080     if (ispcall) {
1081         symbol *rlbl = newiTempLabel(NULL);
1082
1083         emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1084         emitcode("push", "hl");
1085
1086         aopOp(IC_LEFT(ic),ic,FALSE);
1087         emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
1088         emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
1089         freeAsmop(IC_LEFT(ic),NULL,ic); 
1090         
1091         emitcode("jp", "(hl)");
1092         emitcode("","%05d$:",(rlbl->key+100));
1093     }
1094     else {
1095         /* make the call */
1096         emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1097                                 OP_SYMBOL(IC_LEFT(ic))->rname :
1098                                 OP_SYMBOL(IC_LEFT(ic))->name));
1099     }
1100
1101     /* if we need assign a result value */
1102     if ((IS_ITEMP(IC_RESULT(ic)) && 
1103          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1104           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1105         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1106
1107         accInUse++;
1108         aopOp(IC_RESULT(ic),ic,FALSE);
1109         accInUse--;
1110
1111         assignResultValue(IC_RESULT(ic));
1112                 
1113         freeAsmop(IC_RESULT(ic),NULL, ic);
1114     }
1115
1116     /* adjust the stack for parameters if required */
1117     if (IC_LEFT(ic)->parmBytes) {
1118         int i = IC_LEFT(ic)->parmBytes;
1119         /* PENDING: do better */
1120         while (i>1) {
1121             emitcode("pop", "hl");
1122             i-=2;
1123         }
1124         if (i) 
1125             emitcode("inc", "sp");
1126     }
1127
1128 }
1129
1130 /*-----------------------------------------------------------------*/
1131 /* genCall - generates a call statement                            */
1132 /*-----------------------------------------------------------------*/
1133 static void genCall (iCode *ic)
1134 {
1135     emitCall(ic, FALSE);
1136 }
1137
1138 /*-----------------------------------------------------------------*/
1139 /* genPcall - generates a call by pointer statement                */
1140 /*-----------------------------------------------------------------*/
1141 static void genPcall (iCode *ic)
1142 {
1143     emitCall(ic, TRUE);
1144 }
1145
1146 /*-----------------------------------------------------------------*/
1147 /* resultRemat - result  is rematerializable                       */
1148 /*-----------------------------------------------------------------*/
1149 static int resultRemat (iCode *ic)
1150 {
1151     if (SKIP_IC(ic) || ic->op == IFX)
1152         return 0;
1153
1154     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1155         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1156         if (sym->remat && !POINTER_SET(ic)) 
1157             return 1;
1158     }
1159
1160     return 0;
1161 }
1162
1163 /*-----------------------------------------------------------------*/
1164 /* genFunction - generated code for function entry                 */
1165 /*-----------------------------------------------------------------*/
1166 static void genFunction (iCode *ic)
1167 {
1168     symbol *sym;
1169     link *fetype;
1170
1171     nregssaved = 0;
1172     /* create the function header */
1173     emitcode(";","-----------------------------------------");
1174     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1175     emitcode(";","-----------------------------------------");
1176
1177     emitcode("","%s:",sym->rname);
1178     fetype = getSpec(operandType(IC_LEFT(ic)));
1179
1180     /* if critical function then turn interrupts off */
1181     if (SPEC_CRTCL(fetype))
1182         emitcode("di","");
1183
1184     /* if this is an interrupt service routine then
1185     save acc, b, dpl, dph  */
1186     if (IS_ISR(sym->etype)) {
1187         emitcode("push", "af");
1188         emitcode("push", "bc");
1189         emitcode("push", "de");
1190         emitcode("push", "hl");
1191     }
1192     /* PENDING: callee-save etc */
1193
1194     /* adjust the stack for the function */
1195     emitcode("push", "de"); 
1196     emitcode("push", "bc");
1197     emitcode("push", "ix");
1198     emitcode("ld", "ix,#0");
1199     emitcode("add", "ix,sp");
1200
1201     _lastStack = sym->stack;
1202
1203     if (sym->stack) {
1204         emitcode("ld", "hl,#-%d", sym->stack);
1205         emitcode("add", "hl,sp");
1206         emitcode("ld", "sp,hl");
1207     }    
1208 }
1209
1210 /*-----------------------------------------------------------------*/
1211 /* genEndFunction - generates epilogue for functions               */
1212 /*-----------------------------------------------------------------*/
1213 static void genEndFunction (iCode *ic)
1214 {
1215     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1216
1217     if (IS_ISR(sym->etype)) {
1218         assert(0);
1219     }
1220     else {
1221         if (SPEC_CRTCL(sym->etype))
1222             emitcode("ei", "");
1223         
1224         if (sym->calleeSave) {
1225             /* Handled by cret */
1226         }
1227         else {
1228             assert(0);
1229         }
1230
1231         /* if debug then send end of function */
1232         if (options.debug && currFunc) { 
1233             debugLine = 1;
1234             emitcode("","C$%s$%d$%d$%d ==.",
1235                      ic->filename,currFunc->lastLine,
1236                      ic->level,ic->block); 
1237             if (IS_STATIC(currFunc->etype))         
1238                 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
1239             else
1240                 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1241             debugLine = 0;
1242         }
1243         emitcode("ld", "sp,ix");
1244         emitcode("pop", "ix");
1245         emitcode("pop", "bc");
1246         emitcode("pop", "de");
1247         emitcode("ret", "");
1248     }
1249
1250 }
1251
1252 /*-----------------------------------------------------------------*/
1253 /* genRet - generate code for return statement                     */
1254 /*-----------------------------------------------------------------*/
1255 static void genRet (iCode *ic)
1256 {
1257     char *l;
1258     /* Errk.  This is a hack until I can figure out how
1259        to cause dehl to spill on a call */
1260     int size,offset = 0;
1261     
1262     /* if we have no return value then
1263        just generate the "ret" */
1264     if (!IC_LEFT(ic)) 
1265         goto jumpret;       
1266     
1267     /* we have something to return then
1268        move the return value into place */
1269     aopOp(IC_LEFT(ic),ic,FALSE);
1270     size = AOP_SIZE(IC_LEFT(ic));
1271     
1272     if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1273             emitcode("ld", "hl,%s", l);
1274     }
1275     else {
1276         while (size--) {
1277             l = aopGet(AOP(IC_LEFT(ic)),offset,
1278                        FALSE);
1279             if (strcmp(fReturn[offset],l))
1280                 emitcode("ld","%s,%s",fReturn[offset++],l);
1281         }
1282     }
1283     freeAsmop (IC_LEFT(ic),NULL,ic);
1284     
1285  jumpret:
1286         /* generate a jump to the return label
1287            if the next is not the return statement */
1288     if (!(ic->next && ic->next->op == LABEL &&
1289           IC_LABEL(ic->next) == returnLabel))
1290         
1291         emitcode("jp",  LABEL_STR ,(returnLabel->key+100));
1292 }
1293
1294 /*-----------------------------------------------------------------*/
1295 /* genLabel - generates a label                                    */
1296 /*-----------------------------------------------------------------*/
1297 static void genLabel (iCode *ic)
1298 {
1299     /* special case never generate */
1300     if (IC_LABEL(ic) == entryLabel)
1301         return ;
1302
1303     emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1304 }
1305
1306 /*-----------------------------------------------------------------*/
1307 /* genGoto - generates a ljmp                                      */
1308 /*-----------------------------------------------------------------*/
1309 static void genGoto (iCode *ic)
1310 {
1311     emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1312 }
1313
1314 /*-----------------------------------------------------------------*/
1315 /* genPlusIncr :- does addition with increment if possible         */
1316 /*-----------------------------------------------------------------*/
1317 static bool genPlusIncr (iCode *ic)
1318 {
1319     unsigned int icount ;
1320     unsigned int size = getDataSize(IC_RESULT(ic));
1321     
1322     /* will try to generate an increment */
1323     /* if the right side is not a literal 
1324        we cannot */
1325     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1326         return FALSE;
1327     
1328     /* if the literal value of the right hand side
1329        is greater than 4 then it is not worth it */
1330     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
1331         return FALSE ;
1332
1333     /* Inc a pair */
1334     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1335         isPair(AOP(IC_RESULT(ic)))) {
1336         while (icount--) {
1337             emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1338         }
1339         return TRUE;
1340     }
1341     /* if increment 16 bits in register */
1342     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1343         (size > 1) &&
1344         (icount == 1)) {
1345         symbol *tlbl = newiTempLabel(NULL);
1346         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1347         emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1348     
1349         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1350         if(size == 4) {
1351             assert(0);
1352         }
1353         emitcode("", LABEL_STR ":",tlbl->key+100);
1354         return TRUE;
1355     }
1356
1357     /* If result is a pair */
1358     if (isPair(AOP(IC_RESULT(ic)))) {
1359         movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1360         movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1361         while (icount--)
1362             emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1363         return TRUE;
1364     }
1365
1366     /* if the sizes are greater than 1 then we cannot */
1367     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1368         AOP_SIZE(IC_LEFT(ic)) > 1   )
1369         return FALSE ;
1370     
1371     /* we can if the aops of the left & result match or
1372        if they are in registers and the registers are the
1373        same */
1374     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1375         while (icount--)
1376             emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1377         
1378         return TRUE ;
1379     }
1380     
1381     return FALSE ;
1382 }
1383
1384 /*-----------------------------------------------------------------*/
1385 /* outBitAcc - output a bit in acc                                 */
1386 /*-----------------------------------------------------------------*/
1387 void outBitAcc(operand *result)
1388 {
1389     symbol *tlbl = newiTempLabel(NULL);
1390     /* if the result is a bit */
1391     if (AOP_TYPE(result) == AOP_CRY){
1392         assert(0);
1393     }
1394     else {
1395         emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1396         emitcode("ld","a,%s",one);
1397         emitcode("", LABEL_STR ":",tlbl->key+100);
1398         outAcc(result);
1399     }
1400 }
1401
1402 /*-----------------------------------------------------------------*/
1403 /* genPlus - generates code for addition                           */
1404 /*-----------------------------------------------------------------*/
1405 static void genPlus (iCode *ic)
1406 {
1407     int size, offset = 0;
1408
1409     /* special cases :- */
1410
1411     aopOp (IC_LEFT(ic),ic,FALSE);
1412     aopOp (IC_RIGHT(ic),ic,FALSE);
1413     aopOp (IC_RESULT(ic),ic,TRUE);
1414
1415     /* Swap the left and right operands if:
1416
1417        if literal, literal on the right or
1418        if left requires ACC or right is already
1419        in ACC */
1420
1421     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1422         (AOP_NEEDSACC(IC_LEFT(ic))) ||
1423         AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1424         operand *t = IC_RIGHT(ic);
1425         IC_RIGHT(ic) = IC_LEFT(ic);
1426         IC_LEFT(ic) = t;
1427     }
1428
1429     /* if both left & right are in bit
1430     space */
1431     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1432         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1433         /* Cant happen */
1434         assert(0);
1435     }
1436
1437     /* if left in bit space & right literal */
1438     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1439         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1440         /* Can happen I guess */
1441         assert(0);
1442     }
1443
1444     /* if I can do an increment instead
1445     of add then GOOD for ME */
1446     if (genPlusIncr (ic) == TRUE)
1447         goto release;   
1448
1449     size = getDataSize(IC_RESULT(ic));
1450
1451     while(size--) {
1452         if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1453             MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1454             if(offset == 0)
1455                 emitcode("add","a,%s",
1456                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1457             else
1458                 emitcode("adc","a,%s",
1459                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1460         } else {
1461             MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1462             if(offset == 0)
1463                 emitcode("add","a,%s",
1464                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1465             else
1466                 emitcode("adc","a,%s",
1467                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1468         }
1469         aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
1470     }
1471
1472     /* Some kind of pointer arith. */
1473     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
1474         AOP_SIZE(IC_LEFT(ic)) == 3   &&
1475         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1476         assert(0);
1477
1478      if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
1479         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
1480         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1481          assert(0);
1482
1483    
1484 release:
1485     freeAsmop(IC_LEFT(ic),NULL,ic);
1486     freeAsmop(IC_RIGHT(ic),NULL,ic);
1487     freeAsmop(IC_RESULT(ic),NULL,ic);
1488     
1489 }
1490
1491 /*-----------------------------------------------------------------*/
1492 /* genMinusDec :- does subtraction with deccrement if possible     */
1493 /*-----------------------------------------------------------------*/
1494 static bool genMinusDec (iCode *ic)
1495 {
1496     unsigned int icount ;
1497     unsigned int size = getDataSize(IC_RESULT(ic));
1498
1499     /* will try to generate an increment */
1500     /* if the right side is not a literal we cannot */
1501     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1502         return FALSE ;
1503
1504     /* if the literal value of the right hand side
1505     is greater than 4 then it is not worth it */
1506     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1507         return FALSE;
1508
1509     size = getDataSize(IC_RESULT(ic));
1510     /* if decrement 16 bits in register */
1511     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1512         (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1513         while (icount--)
1514             emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1515         return TRUE;
1516     }
1517
1518     /* If result is a pair */
1519     if (isPair(AOP(IC_RESULT(ic)))) {
1520         movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1521         movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1522         while (icount--)
1523             emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1524         return TRUE;
1525     }
1526
1527     /* if the sizes are greater than 1 then we cannot */
1528     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1529         AOP_SIZE(IC_LEFT(ic)) > 1   )
1530         return FALSE ;
1531
1532     /* we can if the aops of the left & result match or if they are in
1533        registers and the registers are the same */
1534     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1535         while (icount--) 
1536             emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1537         return TRUE ;
1538     }
1539
1540     return FALSE ;
1541 }
1542
1543 /*-----------------------------------------------------------------*/
1544 /* genMinus - generates code for subtraction                       */
1545 /*-----------------------------------------------------------------*/
1546 static void genMinus (iCode *ic)
1547 {
1548     int size, offset = 0;
1549     unsigned long lit = 0L;
1550
1551     aopOp (IC_LEFT(ic),ic,FALSE);
1552     aopOp (IC_RIGHT(ic),ic,FALSE);
1553     aopOp (IC_RESULT(ic),ic,TRUE);
1554
1555     /* special cases :- */
1556     /* if both left & right are in bit space */
1557     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1558         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1559         assert(0);
1560         goto release ;
1561     }
1562
1563     /* if I can do an decrement instead of subtract then GOOD for ME */
1564     if (genMinusDec (ic) == TRUE)
1565         goto release;   
1566
1567     size = getDataSize(IC_RESULT(ic));   
1568
1569     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1570         CLRC;
1571     }
1572     else{
1573         lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1574         lit = - (long)lit;
1575     }
1576
1577
1578     /* if literal, add a,#-lit, else normal subb */
1579     while (size--) {
1580         MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));    
1581         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
1582             emitcode("sbc","a,%s",
1583                      aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1584         else{
1585             /* first add without previous c */
1586             if (!offset)
1587                 emitcode("add","a,#0x%02x",
1588                          (unsigned int)(lit & 0x0FFL));
1589             else
1590                 emitcode("adc","a,#0x%02x",
1591                          (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1592         }
1593         aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
1594     }
1595     
1596     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
1597         AOP_SIZE(IC_LEFT(ic)) == 3   &&
1598         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1599         assert(0);
1600
1601 release:
1602     freeAsmop(IC_LEFT(ic),NULL,ic);
1603     freeAsmop(IC_RIGHT(ic),NULL,ic);
1604     freeAsmop(IC_RESULT(ic),NULL,ic);
1605 }
1606
1607 /*-----------------------------------------------------------------*/
1608 /* genMult - generates code for multiplication                     */
1609 /*-----------------------------------------------------------------*/
1610 static void genMult (iCode *ic)
1611 {
1612     /* Shouldn't occur - all done through function calls */
1613     assert(0);
1614 }
1615
1616 /*-----------------------------------------------------------------*/
1617 /* genDiv - generates code for division                            */
1618 /*-----------------------------------------------------------------*/
1619 static void genDiv (iCode *ic)
1620 {
1621     /* Shouldn't occur - all done through function calls */
1622     assert(0);
1623 }
1624
1625 /*-----------------------------------------------------------------*/
1626 /* genMod - generates code for division                            */
1627 /*-----------------------------------------------------------------*/
1628 static void genMod (iCode *ic)
1629 {
1630     /* Shouldn't occur - all done through function calls */
1631     assert(0);
1632 }
1633
1634 /*-----------------------------------------------------------------*/
1635 /* genIfxJump :- will create a jump depending on the ifx           */
1636 /*-----------------------------------------------------------------*/
1637 static void genIfxJump (iCode *ic, char *jval)
1638 {
1639     symbol *jlbl ;
1640     const char *inst;
1641
1642     /* if true label then we jump if condition
1643     supplied is true */
1644     if ( IC_TRUE(ic) ) {
1645         jlbl = IC_TRUE(ic);
1646         if (!strcmp(jval, "a")) {
1647             inst = "nz";
1648         }
1649         else if (!strcmp(jval, "c")) {
1650             inst = "c";
1651         }
1652         else {
1653             /* The buffer contains the bit on A that we should test */
1654             inst = "nz";
1655         }
1656     }
1657     else {
1658         /* false label is present */
1659         jlbl = IC_FALSE(ic) ;
1660         if (!strcmp(jval, "a")) {
1661             inst = "z";
1662         }
1663         else if (!strcmp(jval, "c")) {
1664             inst = "nc";
1665         }
1666         else {
1667             /* The buffer contains the bit on A that we should test */
1668             inst = "z";
1669         }
1670     }
1671     /* Z80 can do a conditional long jump */
1672     if (!strcmp(jval, "a")) {
1673         emitcode("or", "a,a");
1674     }
1675     else if (!strcmp(jval, "c")) {
1676     }
1677     else {
1678         emitcode("bit", "%s,a", jval);
1679     }
1680     emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1681
1682     /* mark the icode as generated */
1683     ic->generated = 1;
1684 }
1685
1686 /** Generic compare for > or <
1687  */
1688 static void genCmp (operand *left,operand *right,
1689                     operand *result, iCode *ifx, int sign)
1690 {
1691     int size, offset = 0 ;
1692     unsigned long lit = 0L;
1693
1694     /* if left & right are bit variables */
1695     if (AOP_TYPE(left) == AOP_CRY &&
1696         AOP_TYPE(right) == AOP_CRY ) {
1697         /* Cant happen on the Z80 */
1698         assert(0);
1699     } else {
1700         /* subtract right from left if at the
1701         end the carry flag is set then we know that
1702         left is greater than right */
1703         size = max(AOP_SIZE(left),AOP_SIZE(right));
1704
1705         /* if unsigned char cmp with lit, just compare */
1706         if((size == 1) && !sign &&
1707            (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1708             emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1709             emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
1710         } 
1711         else {
1712             if(AOP_TYPE(right) == AOP_LIT) {
1713                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1714                 /* optimize if(x < 0) or if(x >= 0) */
1715                 if (lit == 0L){
1716                     if (!sign) {
1717                         /* No sign so it's always false */
1718                         CLRC;
1719                     }
1720                     else{
1721                         /* Just load in the top most bit */
1722                         MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1723                         if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1724                             assert(0);
1725                             genIfxJump (ifx,"acc.7");
1726                             return;
1727                         }
1728                         else    
1729                             emitcode("rlc","a");
1730                     }
1731                     goto release;
1732                 }
1733             }
1734             while (size--) {
1735                 /* Do a long subtract */
1736                 MOVA(aopGet(AOP(left),offset,FALSE));
1737                 if (sign && size == 0) {
1738                     /* Case where it's signed and we've hit the end */
1739                     assert(0);
1740                 } else {
1741                     /* Subtract through, propagating the carry */
1742                     if (offset==0) {
1743                         emitcode("sub","a,%s",aopGet(AOP(right),offset++,FALSE));
1744                     }
1745                     else
1746                         emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1747                 }
1748             }
1749         }
1750     }
1751
1752 release:
1753     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1754         outBitC(result);
1755     } else {
1756         /* if the result is used in the next
1757         ifx conditional branch then generate
1758         code a little differently */
1759         if (ifx )
1760             genIfxJump (ifx,"c");
1761         else
1762             outBitC(result);
1763         /* leave the result in acc */
1764     }
1765 }
1766
1767 /*-----------------------------------------------------------------*/
1768 /* genCmpGt :- greater than comparison                             */
1769 /*-----------------------------------------------------------------*/
1770 static void genCmpGt (iCode *ic, iCode *ifx)
1771 {
1772     operand *left, *right, *result;
1773     link *letype , *retype;
1774     int sign ;
1775
1776     left = IC_LEFT(ic);
1777     right= IC_RIGHT(ic);
1778     result = IC_RESULT(ic);
1779
1780     letype = getSpec(operandType(left));
1781     retype =getSpec(operandType(right));
1782     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1783     /* assign the amsops */
1784     aopOp (left,ic,FALSE);
1785     aopOp (right,ic,FALSE);
1786     aopOp (result,ic,TRUE);
1787
1788     genCmp(right, left, result, ifx, sign);
1789
1790     freeAsmop(left,NULL,ic);
1791     freeAsmop(right,NULL,ic);
1792     freeAsmop(result,NULL,ic);
1793 }
1794
1795 /*-----------------------------------------------------------------*/
1796 /* genCmpLt - less than comparisons                                */
1797 /*-----------------------------------------------------------------*/
1798 static void genCmpLt (iCode *ic, iCode *ifx)
1799 {
1800     operand *left, *right, *result;
1801     link *letype , *retype;
1802     int sign ;
1803
1804     left = IC_LEFT(ic);
1805     right= IC_RIGHT(ic);
1806     result = IC_RESULT(ic);
1807
1808     letype = getSpec(operandType(left));
1809     retype =getSpec(operandType(right));
1810     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1811
1812     /* assign the amsops */
1813     aopOp (left,ic,FALSE);
1814     aopOp (right,ic,FALSE);
1815     aopOp (result,ic,TRUE);
1816
1817     genCmp(left, right, result, ifx, sign);
1818
1819     freeAsmop(left,NULL,ic);
1820     freeAsmop(right,NULL,ic);
1821     freeAsmop(result,NULL,ic);
1822 }
1823
1824 /*-----------------------------------------------------------------*/
1825 /* gencjneshort - compare and jump if not equal                    */
1826 /*-----------------------------------------------------------------*/
1827 static void gencjneshort(operand *left, operand *right, symbol *lbl)
1828 {
1829     int size = max(AOP_SIZE(left),AOP_SIZE(right));
1830     int offset = 0;
1831     unsigned long lit = 0L;
1832
1833     /* Swap the left and right if it makes the computation easier */
1834     if (AOP_TYPE(left) == AOP_LIT) {
1835         operand *t = right;
1836         right = left;
1837         left = t;
1838     }
1839
1840     if(AOP_TYPE(right) == AOP_LIT)
1841         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1842
1843     /* if the right side is a literal then anything goes */
1844     if (AOP_TYPE(right) == AOP_LIT &&
1845         AOP_TYPE(left) != AOP_DIR ) {
1846         while (size--) {
1847             emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
1848             emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
1849             emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1850             offset++;
1851         }
1852     }
1853     /* if the right side is in a register or in direct space or
1854     if the left is a pointer register & right is not */    
1855     else if (AOP_TYPE(right) == AOP_REG ||
1856              AOP_TYPE(right) == AOP_DIR || 
1857              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
1858         while (size--) {
1859             MOVA(aopGet(AOP(left),offset,FALSE));
1860             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
1861                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
1862                 /* PENDING */
1863                 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
1864             else {
1865                 emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
1866                 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1867             }
1868             offset++;
1869         }
1870     } else {
1871         assert(0);
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     if (AOP(result)->type == AOP_REG) {
2605         int size = 2;
2606         int offset = 0;
2607         symbol *tlbl , *tlbl1;
2608         char *l;
2609
2610         /* Left is already in result - so now do the shift */
2611         if (shCount>1) {
2612             emitcode("ld","a,#%u+1", shCount);
2613             tlbl = newiTempLabel(NULL);
2614             tlbl1 = newiTempLabel(NULL);
2615             emitcode("jp", LABEL_STR ,tlbl1->key+100); 
2616             emitcode("", LABEL_STR ":",tlbl->key+100);    
2617         }
2618
2619         emitcode("or", "a,a");
2620         while (size--) {
2621             l = aopGet(AOP(result),offset++,FALSE);
2622             emitcode("rl","%s", l);         
2623         }
2624         if (shCount>1) {
2625             emitcode("", LABEL_STR ":",tlbl1->key+100);
2626             emitcode("dec", "a");
2627             emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2628         }
2629     }
2630     else {
2631         /* PENDING: do something */
2632         assert(0);
2633     }
2634 }
2635
2636 /*-----------------------------------------------------------------*/
2637 /* AccRol - rotate left accumulator by known count                 */
2638 /*-----------------------------------------------------------------*/
2639 static void AccRol (int shCount)
2640 {
2641     shCount &= 0x0007;              // shCount : 0..7
2642     switch(shCount){
2643         case 0 :
2644             break;
2645         case 1 :
2646             emitcode("rl","a");
2647             break;
2648         case 2 :
2649             emitcode("rl","a");
2650             emitcode("rl","a");
2651             break;
2652         case 3 :
2653             emitcode("rl","a");
2654             emitcode("rl","a");
2655             emitcode("rl","a");
2656             break;
2657         case 4 :
2658             emitcode("rl","a");
2659             emitcode("rl","a");
2660             emitcode("rl","a");
2661             emitcode("rl","a");
2662             break;
2663         case 5 :
2664             emitcode("rr","a");
2665             emitcode("rr","a");
2666             emitcode("rr","a");
2667             break;
2668         case 6 :
2669             emitcode("rr","a");
2670             emitcode("rr","a");
2671             break;
2672         case 7 :
2673             emitcode("rr","a");
2674             break;
2675     }
2676 }
2677
2678 /*-----------------------------------------------------------------*/
2679 /* AccLsh - left shift accumulator by known count                  */
2680 /*-----------------------------------------------------------------*/
2681 static void AccLsh (int shCount)
2682 {
2683     if(shCount != 0){
2684         if(shCount == 1)
2685             emitcode("add","a,a");
2686         else 
2687             if(shCount == 2) {
2688             emitcode("add","a,a");
2689             emitcode("add","a,a");
2690         } else {
2691             /* rotate left accumulator */
2692             AccRol(shCount);
2693             /* and kill the lower order bits */
2694             emitcode("and","a,#0x%02x", SLMask[shCount]);
2695         }
2696     }
2697 }
2698
2699 /*-----------------------------------------------------------------*/
2700 /* shiftL1Left2Result - shift left one byte from left to result    */
2701 /*-----------------------------------------------------------------*/
2702 static void shiftL1Left2Result (operand *left, int offl,
2703                                 operand *result, int offr, int shCount)
2704 {
2705     char *l;
2706     l = aopGet(AOP(left),offl,FALSE);
2707     MOVA(l);
2708     /* shift left accumulator */
2709     AccLsh(shCount);
2710     aopPut(AOP(result),"a",offr);
2711 }
2712
2713
2714 /*-----------------------------------------------------------------*/
2715 /* genlshTwo - left shift two bytes by known amount != 0           */
2716 /*-----------------------------------------------------------------*/
2717 static void genlshTwo (operand *result,operand *left, int shCount)
2718 {
2719     int size = AOP_SIZE(result);
2720
2721     assert(size==2);
2722
2723     /* if shCount >= 8 */
2724     if (shCount >= 8) {
2725         shCount -= 8 ;
2726
2727         if (size > 1){
2728             if (shCount) {
2729                 movLeft2Result(left, LSB, result, MSB16, 0);
2730                 aopPut(AOP(result),zero, 0);   
2731                 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2732             }
2733             else {
2734                 movLeft2Result(left, LSB, result, MSB16, 0);
2735                 aopPut(AOP(result),zero, 0);   
2736             }
2737         }
2738         aopPut(AOP(result),zero,LSB);   
2739     }
2740     /*  1 <= shCount <= 7 */
2741     else {  
2742         if(size == 1) {
2743             assert(0);
2744         }
2745         else {
2746             shiftL2Left2Result(left, LSB, result, LSB, shCount);
2747         }
2748     }
2749 }
2750
2751 /*-----------------------------------------------------------------*/
2752 /* genlshOne - left shift a one byte quantity by known count       */
2753 /*-----------------------------------------------------------------*/
2754 static void genlshOne (operand *result, operand *left, int shCount)
2755 {       
2756     shiftL1Left2Result(left, LSB, result, LSB, shCount);
2757 }
2758
2759 /*-----------------------------------------------------------------*/
2760 /* genLeftShiftLiteral - left shifting by known count              */
2761 /*-----------------------------------------------------------------*/
2762 static void genLeftShiftLiteral (operand *left,
2763                                  operand *right,
2764                                  operand *result,
2765                                  iCode *ic)
2766 {    
2767     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2768     int size;
2769
2770     freeAsmop(right,NULL,ic);
2771
2772     aopOp(left,ic,FALSE);
2773     aopOp(result,ic,FALSE);
2774
2775     size = getSize(operandType(result));
2776
2777 #if VIEW_SIZE
2778     emitcode("; shift left ","result %d, left %d",size,
2779              AOP_SIZE(left));
2780 #endif
2781
2782     /* I suppose that the left size >= result size */
2783     if (shCount == 0) {
2784         assert(0);
2785     }
2786
2787     else if(shCount >= (size * 8))
2788         while(size--)
2789             aopPut(AOP(result),zero,size);
2790     else{
2791         switch (size) {
2792         case 1:
2793             genlshOne (result,left,shCount);
2794             break;
2795         case 2:
2796             genlshTwo (result,left,shCount);
2797             break;
2798         case 4:
2799             assert(0);
2800             break;
2801         default:
2802             assert(0);
2803         }
2804     }
2805     freeAsmop(left,NULL,ic);
2806     freeAsmop(result,NULL,ic);
2807 }
2808
2809 /*-----------------------------------------------------------------*/
2810 /* genLeftShift - generates code for left shifting                 */
2811 /*-----------------------------------------------------------------*/
2812 static void genLeftShift (iCode *ic)
2813 {
2814     int size, offset;
2815     char *l;
2816     symbol *tlbl , *tlbl1;
2817     operand *left,*right, *result;
2818
2819     right = IC_RIGHT(ic);
2820     left  = IC_LEFT(ic);
2821     result = IC_RESULT(ic);
2822
2823     aopOp(right,ic,FALSE);
2824
2825     /* if the shift count is known then do it 
2826     as efficiently as possible */
2827     if (AOP_TYPE(right) == AOP_LIT) {
2828         genLeftShiftLiteral (left,right,result,ic);
2829         return ;
2830     }
2831
2832     /* shift count is unknown then we have to form a loop get the loop
2833        count in B : Note: we take only the lower order byte since
2834        shifting more that 32 bits make no sense anyway, ( the largest
2835        size of an object can be only 32 bits ) */
2836     emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
2837     emitcode("inc","a");
2838     freeAsmop (right,NULL,ic);
2839     aopOp(left,ic,FALSE);
2840     aopOp(result,ic,FALSE);
2841
2842     /* now move the left to the result if they are not the
2843        same */
2844 #if 1
2845     if (!sameRegs(AOP(left),AOP(result))) {
2846
2847         size = AOP_SIZE(result);
2848         offset = 0;
2849         while (size--) {
2850             l = aopGet(AOP(left),offset,FALSE);
2851             aopPut(AOP(result),l,offset);
2852             offset++;
2853         }
2854     }
2855 #else
2856     size = AOP_SIZE(result);
2857     offset = 0;
2858     while (size--) {
2859         l = aopGet(AOP(left),offset,FALSE);
2860         aopPut(AOP(result),l,offset);
2861         offset++;
2862     }
2863 #endif
2864
2865
2866     tlbl = newiTempLabel(NULL);
2867     size = AOP_SIZE(result);
2868     offset = 0 ;   
2869     tlbl1 = newiTempLabel(NULL);
2870
2871     emitcode("jp", LABEL_STR ,tlbl1->key+100); 
2872     emitcode("", LABEL_STR ":",tlbl->key+100);    
2873     l = aopGet(AOP(result),offset,FALSE);
2874     emitcode("or", "a,a");
2875     while (size--) {
2876         l = aopGet(AOP(result),offset++,FALSE);
2877         emitcode("rl","%s", l);         
2878     }
2879     emitcode("", LABEL_STR ":",tlbl1->key+100);
2880     emitcode("dec", "a");
2881     emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2882
2883     freeAsmop(left,NULL,ic);
2884     freeAsmop(result,NULL,ic);
2885 }
2886
2887 /* genlshTwo - left shift two bytes by known amount != 0           */
2888 /*-----------------------------------------------------------------*/
2889 static void genrshOne (operand *result,operand *left, int shCount)
2890 {
2891     /* Errk */
2892     int size = AOP_SIZE(result);
2893     char *l;
2894
2895     assert(size==1);
2896     assert(shCount<8);
2897
2898     l = aopGet(AOP(left),0,FALSE);
2899     if (AOP(result)->type == AOP_REG) {
2900         aopPut(AOP(result), l, 0);
2901         l = aopGet(AOP(result), 0, FALSE);
2902         while (shCount--) 
2903             emitcode("srl", "%s", l);
2904     }
2905     else {
2906         MOVA(l);
2907         while (shCount--) {
2908             emitcode("srl", "a");
2909         }
2910         aopPut(AOP(result),"a",0);
2911     }
2912 }
2913
2914 /*-----------------------------------------------------------------*/
2915 /* AccRsh - right shift accumulator by known count                 */
2916 /*-----------------------------------------------------------------*/
2917 static void AccRsh (int shCount)
2918 {
2919     if(shCount != 0){
2920         if(shCount == 1){
2921             CLRC;
2922             emitcode("rr","a");
2923         } else {
2924             /* rotate right accumulator */
2925             AccRol(8 - shCount);
2926             /* and kill the higher order bits */
2927             emitcode("and","a,#0x%02x", SRMask[shCount]);
2928         }
2929     }
2930 }
2931
2932 /*-----------------------------------------------------------------*/
2933 /* shiftR1Left2Result - shift right one byte from left to result   */
2934 /*-----------------------------------------------------------------*/
2935 static void shiftR1Left2Result (operand *left, int offl,
2936                                 operand *result, int offr,
2937                                 int shCount, int sign)
2938 {
2939     MOVA(aopGet(AOP(left),offl,FALSE));
2940     if (sign) {
2941         assert(0);
2942     }
2943     else {
2944         AccRsh(shCount);
2945     }
2946     aopPut(AOP(result),"a",offr);
2947 }
2948
2949 /*-----------------------------------------------------------------*/
2950 /* genrshTwo - right shift two bytes by known amount != 0          */
2951 /*-----------------------------------------------------------------*/
2952 static void genrshTwo (operand *result,operand *left,
2953                        int shCount, int sign)
2954 {
2955     /* if shCount >= 8 */
2956     if (shCount >= 8) {
2957         shCount -= 8 ;
2958         if (shCount) {
2959             assert(0);
2960             shiftR1Left2Result(left, MSB16, result, LSB,
2961                                shCount, sign);
2962         }
2963         else {
2964             movLeft2Result(left, MSB16, result, LSB, sign);
2965             aopPut(AOP(result),zero,1);
2966         }
2967     }
2968     /*  1 <= shCount <= 7 */
2969     else {
2970         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
2971     }
2972 }
2973
2974 /*-----------------------------------------------------------------*/
2975 /* genRightShiftLiteral - left shifting by known count              */
2976 /*-----------------------------------------------------------------*/
2977 static void genRightShiftLiteral (operand *left,
2978                                  operand *right,
2979                                  operand *result,
2980                                  iCode *ic)
2981 {    
2982     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2983     int size;
2984
2985     freeAsmop(right,NULL,ic);
2986
2987     aopOp(left,ic,FALSE);
2988     aopOp(result,ic,FALSE);
2989
2990     size = getSize(operandType(result));
2991
2992     emitcode("; shift right ","result %d, left %d",size,
2993              AOP_SIZE(left));
2994
2995     /* I suppose that the left size >= result size */
2996     if (shCount == 0) {
2997         assert(0);
2998     }
2999
3000     else if(shCount >= (size * 8))
3001         while(size--)
3002             aopPut(AOP(result),zero,size);
3003     else{
3004         switch (size) {
3005         case 1:
3006             genrshOne(result, left, shCount);
3007             break;
3008         case 2:
3009             /* PENDING: sign support */
3010             genrshTwo(result, left, shCount, FALSE);
3011             break;
3012         case 4:
3013             assert(0);
3014             break;
3015         default:
3016             assert(0);
3017         }
3018     }
3019     freeAsmop(left,NULL,ic);
3020     freeAsmop(result,NULL,ic);
3021 }
3022
3023 /*-----------------------------------------------------------------*/
3024 /* genRightShift - generate code for right shifting                */
3025 /*-----------------------------------------------------------------*/
3026 static void genRightShift (iCode *ic)
3027 {
3028     operand *left,*right, *result;
3029
3030     right = IC_RIGHT(ic);
3031     left  = IC_LEFT(ic);
3032     result = IC_RESULT(ic);
3033
3034     aopOp(right,ic,FALSE);
3035
3036     /* if the shift count is known then do it 
3037     as efficiently as possible */
3038     if (AOP_TYPE(right) == AOP_LIT) {
3039         genRightShiftLiteral (left,right,result,ic);
3040         return ;
3041     }
3042     else {
3043         assert(0);
3044     }
3045 }
3046
3047 /*-----------------------------------------------------------------*/
3048 /* genGenPointerGet - gget value from generic pointer space        */
3049 /*-----------------------------------------------------------------*/
3050 static void genGenPointerGet (operand *left,
3051                               operand *result, iCode *ic)
3052 {
3053     int size, offset ;
3054     link *retype = getSpec(operandType(result));
3055
3056     aopOp(left,ic,FALSE);
3057     aopOp(result,ic,FALSE);
3058
3059     if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3060         /* Just do it */
3061         emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3062         aopPut(AOP(result),"a", 0);
3063         freeAsmop(left,NULL,ic);
3064         goto release;
3065     }
3066
3067     /* For now we always load into IY */
3068     /* if this is remateriazable */
3069     if (AOP_TYPE(left) == AOP_IMMD)
3070         emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3071     else { /* we need to get it byte by byte */
3072         emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
3073         emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
3074     }
3075     /* so iy now contains the address */
3076     freeAsmop(left,NULL,ic);
3077
3078     /* if bit then unpack */
3079     if (IS_BITVAR(retype)) {
3080         assert(0);
3081     }
3082     else {
3083         size = AOP_SIZE(result);
3084         offset = 0 ;
3085
3086         while (size--) {
3087             /* PENDING: make this better */
3088             if (AOP(result)->type == AOP_REG) {
3089                 aopPut(AOP(result),"(hl)",offset++);
3090             }
3091             else {
3092                 emitcode("ld", "a,(hl)", offset);
3093                 aopPut(AOP(result),"a",offset++);
3094             }
3095             if (size) {
3096                 emitcode("inc", "hl");
3097             }
3098         }
3099     }
3100
3101  release:
3102     freeAsmop(result,NULL,ic);
3103 }
3104
3105 /*-----------------------------------------------------------------*/
3106 /* genPointerGet - generate code for pointer get                   */
3107 /*-----------------------------------------------------------------*/
3108 static void genPointerGet (iCode *ic)
3109 {
3110     operand *left, *result ;
3111     link *type, *etype;
3112
3113     left = IC_LEFT(ic);
3114     result = IC_RESULT(ic) ;
3115
3116     /* depending on the type of pointer we need to
3117     move it to the correct pointer register */
3118     type = operandType(left);
3119     etype = getSpec(type);
3120
3121     genGenPointerGet (left,result,ic);
3122 }
3123
3124 bool isRegOrLit(asmop *aop)
3125 {
3126     if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3127         return TRUE;
3128     return FALSE;
3129 }
3130
3131 /*-----------------------------------------------------------------*/
3132 /* genGenPointerSet - stores the value into a pointer location        */
3133 /*-----------------------------------------------------------------*/
3134 static void genGenPointerSet (operand *right,
3135                               operand *result, iCode *ic)
3136 {    
3137     int size, offset ;
3138     link *retype = getSpec(operandType(right));
3139
3140     aopOp(result,ic,FALSE);
3141     aopOp(right,ic,FALSE);
3142
3143     /* Handle the exceptions first */
3144     if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3145         /* Just do it */
3146         char *l = aopGet(AOP(right), 0, FALSE);
3147         MOVA(l);
3148         emitcode("ld", "(%s),a", getPairName(AOP(result)));
3149         freeAsmop(result,NULL,ic);
3150         goto release;
3151     }
3152         
3153     /* if the operand is already in dptr 
3154        then we do nothing else we move the value to dptr */
3155     if (AOP_TYPE(result) != AOP_STR) {
3156         /* if this is remateriazable */
3157         if (AOP_TYPE(result) == AOP_IMMD) {
3158             emitcode("", "; Error 2");
3159             emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3160         }
3161         else { /* we need to get it byte by byte */
3162             /* PENDING: do this better */
3163             emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
3164             emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
3165         }
3166     }
3167     /* so hl know contains the address */
3168     freeAsmop(result,NULL,ic);
3169
3170     /* if bit then unpack */
3171     if (IS_BITVAR(retype)) {
3172         assert(0);
3173     }
3174     else {
3175         size = AOP_SIZE(right);
3176         offset = 0 ;
3177
3178         while (size--) {
3179             char *l = aopGet(AOP(right),offset,FALSE);
3180
3181             if (isRegOrLit(AOP(right))) {
3182                 emitcode("ld", "(hl),%s", l);
3183             }
3184             else {
3185                 MOVA(l);
3186                 emitcode("ld", "(hl),a", offset);
3187             }
3188             if (size) {
3189                 emitcode("inc", "hl");
3190             }
3191             offset++;
3192         }
3193     }
3194     release:
3195     freeAsmop(right,NULL,ic);
3196 }
3197
3198 /*-----------------------------------------------------------------*/
3199 /* genPointerSet - stores the value into a pointer location        */
3200 /*-----------------------------------------------------------------*/
3201 static void genPointerSet (iCode *ic)
3202 {    
3203     operand *right, *result ;
3204     link *type, *etype;
3205
3206     right = IC_RIGHT(ic);
3207     result = IC_RESULT(ic) ;
3208
3209     /* depending on the type of pointer we need to
3210     move it to the correct pointer register */
3211     type = operandType(result);
3212     etype = getSpec(type);
3213     
3214     genGenPointerSet (right,result,ic);
3215 }
3216
3217 /*-----------------------------------------------------------------*/
3218 /* genIfx - generate code for Ifx statement                        */
3219 /*-----------------------------------------------------------------*/
3220 static void genIfx (iCode *ic, iCode *popIc)
3221 {
3222     operand *cond = IC_COND(ic);
3223     int isbit =0;
3224
3225     aopOp(cond,ic,FALSE);
3226
3227     /* get the value into acc */
3228     if (AOP_TYPE(cond) != AOP_CRY)
3229         toBoolean(cond);
3230     else
3231         isbit = 1;
3232     /* the result is now in the accumulator */
3233     freeAsmop(cond,NULL,ic);
3234
3235     /* if there was something to be popped then do it */
3236     if (popIc)
3237         genIpop(popIc);
3238
3239     /* if the condition is  a bit variable */
3240     if (isbit && IS_ITEMP(cond) && 
3241         SPIL_LOC(cond))
3242         genIfxJump(ic,SPIL_LOC(cond)->rname);
3243     else
3244         if (isbit && !IS_ITEMP(cond))
3245             genIfxJump(ic,OP_SYMBOL(cond)->rname);
3246         else
3247             genIfxJump(ic,"a");
3248
3249     ic->generated = 1;
3250 }
3251
3252 /*-----------------------------------------------------------------*/
3253 /* genAddrOf - generates code for address of                       */
3254 /*-----------------------------------------------------------------*/
3255 static void genAddrOf (iCode *ic)
3256 {
3257     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3258
3259     aopOp(IC_RESULT(ic),ic,FALSE);
3260
3261     /* if the operand is on the stack then we 
3262     need to get the stack offset of this
3263     variable */
3264     if (sym->onStack) {
3265         /* if it has an offset  then we need to compute it */
3266         emitcode("push", "de");
3267         emitcode("push", "ix");
3268         emitcode("pop", "hl");
3269         emitcode("ld", "de,#%d", sym->stack);
3270         emitcode("add", "hl,de");
3271         emitcode("pop", "de");
3272     }
3273     else {
3274         emitcode("ld", "hl,#%s", sym->rname);
3275     }
3276     aopPut(AOP(IC_RESULT(ic)), "l", 0);
3277     aopPut(AOP(IC_RESULT(ic)), "h", 1);
3278
3279     freeAsmop(IC_RESULT(ic),NULL,ic);
3280 }
3281
3282 /*-----------------------------------------------------------------*/
3283 /* genAssign - generate code for assignment                        */
3284 /*-----------------------------------------------------------------*/
3285 static void genAssign (iCode *ic)
3286 {
3287     operand *result, *right;
3288     int size, offset ;
3289     unsigned long lit = 0L;
3290
3291     result = IC_RESULT(ic);
3292     right  = IC_RIGHT(ic) ;
3293
3294     /* Dont bother assigning if they are the same */
3295     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3296         emitcode("", "; (operands are equal)");
3297         return;
3298     }
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     assert(0);
3357 }
3358
3359 /*-----------------------------------------------------------------*/
3360 /* genCast - gen code for casting                                  */
3361 /*-----------------------------------------------------------------*/
3362 static void genCast (iCode *ic)
3363 {
3364     operand *result = IC_RESULT(ic);
3365     link *ctype = operandType(IC_LEFT(ic));
3366     operand *right = IC_RIGHT(ic);
3367     int size, offset ;
3368
3369     /* if they are equivalent then do nothing */
3370     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3371         return ;
3372
3373     aopOp(right,ic,FALSE) ;
3374     aopOp(result,ic,FALSE);
3375
3376     /* if the result is a bit */
3377     if (AOP_TYPE(result) == AOP_CRY) {
3378         assert(0);
3379     }
3380
3381     /* if they are the same size : or less */
3382     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3383
3384         /* if they are in the same place */
3385         if (sameRegs(AOP(right),AOP(result)))
3386             goto release;
3387
3388         /* if they in different places then copy */
3389         size = AOP_SIZE(result);
3390         offset = 0 ;
3391         while (size--) {
3392             aopPut(AOP(result),
3393                    aopGet(AOP(right),offset,FALSE),
3394                    offset);
3395             offset++;
3396         }
3397         goto release;
3398     }
3399
3400     /* if the result is of type pointer */
3401     if (IS_PTR(ctype)) {
3402         assert(0);
3403     }
3404     
3405     /* so we now know that the size of destination is greater
3406     than the size of the source */
3407     /* we move to result for the size of source */
3408     size = AOP_SIZE(right);
3409     offset = 0 ;
3410     while (size--) {
3411         aopPut(AOP(result),
3412                aopGet(AOP(right),offset,FALSE),
3413                offset);
3414         offset++;
3415     }
3416
3417     /* now depending on the sign of the destination */
3418     size = AOP_SIZE(result) - AOP_SIZE(right);
3419     /* Unsigned or not an integral type - right fill with zeros */
3420     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3421         while (size--)
3422             aopPut(AOP(result),zero,offset++);
3423     } else {
3424         /* we need to extend the sign :{ */
3425         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3426                          FALSE);
3427         MOVA(l);
3428         emitcode("", "; genCast: sign extend untested.");
3429         emitcode("rla", "");
3430         emitcode("sbc", "a,a");
3431         while (size--)
3432             aopPut(AOP(result),"a",offset++);   
3433     }
3434
3435 release:
3436     freeAsmop(right, NULL, ic);
3437     freeAsmop(result, NULL, ic);
3438 }
3439
3440 /*-----------------------------------------------------------------*/
3441 /* genReceive - generate code for a receive iCode                  */
3442 /*-----------------------------------------------------------------*/
3443 static void genReceive (iCode *ic)
3444 {    
3445     if (isOperandInFarSpace(IC_RESULT(ic)) && 
3446         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3447           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3448         assert(0);
3449     } else {
3450         accInUse++;
3451         aopOp(IC_RESULT(ic),ic,FALSE);  
3452         accInUse--;
3453         assignResultValue(IC_RESULT(ic));       
3454     }
3455
3456     freeAsmop(IC_RESULT(ic),NULL,ic);
3457 }
3458
3459 /*-----------------------------------------------------------------*/
3460 /* genZ80Code - generate code for Z80 based controllers            */
3461 /*-----------------------------------------------------------------*/
3462 void genZ80Code (iCode *lic)
3463 {
3464     iCode *ic;
3465     int cln = 0;
3466
3467     lineHead = lineCurr = NULL;
3468
3469     /* if debug information required */
3470     if (options.debug && currFunc) { 
3471         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3472         debugLine = 1;
3473         if (IS_STATIC(currFunc->etype))
3474             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
3475         else
3476             emitcode("","G$%s$0$0 ==.",currFunc->name);
3477         debugLine = 0;
3478     }
3479     /* stack pointer name */
3480     spname = "sp";
3481     
3482  
3483     for (ic = lic ; ic ; ic = ic->next ) {
3484         
3485         if ( cln != ic->lineno ) {
3486             if ( options.debug ) {
3487                 debugLine = 1;
3488                 emitcode("","C$%s$%d$%d$%d ==.",
3489                          ic->filename,ic->lineno,
3490                          ic->level,ic->block);
3491                 debugLine = 0;
3492             }
3493             emitcode(";","%s %d",ic->filename,ic->lineno);
3494             cln = ic->lineno ;
3495         }
3496         /* if the result is marked as
3497            spilt and rematerializable or code for
3498            this has already been generated then
3499            do nothing */
3500         if (resultRemat(ic) || ic->generated ) 
3501             continue ;
3502         
3503         /* depending on the operation */
3504         switch (ic->op) {
3505         case '!' :
3506             emitcode("", "; genNot");
3507             genNot(ic);
3508             break;
3509             
3510         case '~' :
3511             emitcode("", "; genCpl");
3512             genCpl(ic);
3513             break;
3514             
3515         case UNARYMINUS:
3516             emitcode("", "; genUminus");
3517             genUminus (ic);
3518             break;
3519             
3520         case IPUSH:
3521             emitcode("", "; genIpush");
3522             genIpush (ic);
3523             break;
3524             
3525         case IPOP:
3526             /* IPOP happens only when trying to restore a 
3527                spilt live range, if there is an ifx statement
3528                following this pop then the if statement might
3529                be using some of the registers being popped which
3530                would destory the contents of the register so
3531                we need to check for this condition and handle it */
3532             if (ic->next            && 
3533                 ic->next->op == IFX &&
3534                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3535                 emitcode("", "; genIfx");
3536                 genIfx (ic->next,ic);
3537             }
3538             else {
3539                 emitcode("", "; genIpop");
3540                 genIpop (ic);
3541             }
3542             break; 
3543             
3544         case CALL:
3545             emitcode("", "; genCall");
3546             genCall (ic);
3547             break;
3548             
3549         case PCALL:
3550             emitcode("", "; genPcall");
3551             genPcall (ic);
3552             break;
3553             
3554         case FUNCTION:
3555             emitcode("", "; genFunction");
3556             genFunction (ic);
3557             break;
3558             
3559         case ENDFUNCTION:
3560             emitcode("", "; genEndFunction");
3561             genEndFunction (ic);
3562             break;
3563             
3564         case RETURN:
3565             emitcode("", "; genRet");
3566             genRet (ic);
3567             break;
3568             
3569         case LABEL:
3570             emitcode("", "; genLabel");
3571             genLabel (ic);
3572             break;
3573             
3574         case GOTO:
3575             emitcode("", "; genGoto");
3576             genGoto (ic);
3577             break;
3578             
3579         case '+' :
3580             emitcode("", "; genPlus");
3581             genPlus (ic) ;
3582             break;
3583             
3584         case '-' :
3585             emitcode("", "; genMinus");
3586             genMinus (ic);
3587             break;
3588             
3589         case '*' :
3590             emitcode("", "; genMult");
3591             genMult (ic);
3592             break;
3593             
3594         case '/' :
3595             emitcode("", "; genDiv");
3596             genDiv (ic) ;
3597             break;
3598             
3599         case '%' :
3600             emitcode("", "; genMod");
3601             genMod (ic);
3602             break;
3603             
3604         case '>' :
3605             emitcode("", "; genCmpGt");
3606             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
3607             break;
3608             
3609         case '<' :
3610             emitcode("", "; genCmpLt");
3611             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3612             break;
3613             
3614         case LE_OP:
3615         case GE_OP:
3616         case NE_OP:
3617             
3618             /* note these two are xlated by algebraic equivalence
3619                during parsing SDCC.y */
3620             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3621                    "got '>=' or '<=' shouldn't have come here");
3622             break;      
3623             
3624         case EQ_OP:
3625             emitcode("", "; genCmpEq");
3626             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3627             break;          
3628             
3629         case AND_OP:
3630             emitcode("", "; genAndOp");
3631             genAndOp (ic);
3632             break;
3633             
3634         case OR_OP:
3635             emitcode("", "; genOrOp");
3636             genOrOp (ic);
3637             break;
3638             
3639         case '^' :
3640             emitcode("", "; genXor");
3641             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3642             break;
3643             
3644         case '|' :
3645             emitcode("", "; genOr");
3646             genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3647             break;
3648             
3649         case BITWISEAND:
3650             emitcode("", "; genAnd");
3651             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3652             break;
3653             
3654         case INLINEASM:
3655             emitcode("", "; genInline");
3656             genInline (ic);
3657             break;
3658             
3659         case RRC:
3660             emitcode("", "; genRRC");
3661             genRRC (ic);
3662             break;
3663             
3664         case RLC:
3665             emitcode("", "; genRLC");
3666             genRLC (ic);
3667             break;
3668             
3669         case GETHBIT:
3670             emitcode("", "; genHBIT");
3671             assert(0);
3672             
3673         case LEFT_OP:
3674             emitcode("", "; genLeftShift");
3675             genLeftShift (ic);
3676             break;
3677             
3678         case RIGHT_OP:
3679             emitcode("", "; genRightShift");
3680             genRightShift (ic);
3681             break;
3682             
3683         case GET_VALUE_AT_ADDRESS:
3684             emitcode("", "; genPointerGet");
3685             genPointerGet(ic);
3686             break;
3687             
3688         case '=' :
3689
3690             if (POINTER_SET(ic)) {
3691                 emitcode("", "; genAssign (pointer)");
3692                 genPointerSet(ic);
3693             }
3694             else {
3695                 emitcode("", "; genAssign");
3696                 genAssign(ic);
3697             }
3698             break;
3699             
3700         case IFX:
3701             emitcode("", "; genIfx");
3702             genIfx (ic,NULL);
3703             break;
3704             
3705         case ADDRESS_OF:
3706             emitcode("", "; genAddrOf");
3707             genAddrOf (ic);
3708             break;
3709             
3710         case JUMPTABLE:
3711             emitcode("", "; genJumpTab");
3712             genJumpTab (ic);
3713             break;
3714             
3715         case CAST:
3716             emitcode("", "; genCast");
3717             genCast (ic);
3718             break;
3719             
3720         case RECEIVE:
3721             emitcode("", "; genReceive");
3722             genReceive(ic);
3723             break;
3724             
3725         case SEND:
3726             emitcode("", "; addSet");
3727             addSet(&sendSet,ic);
3728             break;
3729
3730         default :
3731             ic = ic;
3732             /*      piCode(ic,stdout); */
3733             
3734         }
3735     }
3736     
3737
3738     /* now we are ready to call the 
3739        peep hole optimizer */
3740     /*    if (!options.nopeep)
3741           peepHole (&lineHead); */
3742
3743     /* now do the actual printing */
3744     printLine (lineHead,codeOutFile);
3745     return;
3746 }