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