Fixed increase of a DWORD in registers
[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         ) {
1792         int offset = 0;
1793         symbol *tlbl = NULL;
1794         while (size--) {
1795             if (offset) {
1796                 emitLabel(tlbl->key+100);
1797             }
1798             emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)), offset++, FALSE));
1799             if (size) {
1800                 tlbl = newiTempLabel(NULL);
1801                 emit2("!shortjp nz,!tlabel", tlbl->key+100);
1802             }
1803         }
1804         return TRUE;
1805     }
1806
1807     /* if the sizes are greater than 1 then we cannot */
1808     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1809         AOP_SIZE(IC_LEFT(ic)) > 1   )
1810         return FALSE ;
1811     
1812     /* we can if the aops of the left & result match or
1813        if they are in registers and the registers are the
1814        same */
1815     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1816         while (icount--)
1817             emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1818         
1819         return TRUE ;
1820     }
1821     
1822     return FALSE ;
1823 }
1824
1825 /*-----------------------------------------------------------------*/
1826 /* outBitAcc - output a bit in acc                                 */
1827 /*-----------------------------------------------------------------*/
1828 void outBitAcc(operand *result)
1829 {
1830     symbol *tlbl = newiTempLabel(NULL);
1831     /* if the result is a bit */
1832     if (AOP_TYPE(result) == AOP_CRY){
1833         wassert(0);
1834     }
1835     else {
1836         emit2("!shortjp z,!tlabel", tlbl->key+100);
1837         emit2("ld a,!one");
1838         emitLabel(tlbl->key+100);
1839         outAcc(result);
1840     }
1841 }
1842
1843 /*-----------------------------------------------------------------*/
1844 /* genPlus - generates code for addition                           */
1845 /*-----------------------------------------------------------------*/
1846 static void genPlus (iCode *ic)
1847 {
1848     int size, offset = 0;
1849
1850     /* special cases :- */
1851
1852     aopOp (IC_LEFT(ic),ic,FALSE);
1853     aopOp (IC_RIGHT(ic),ic,FALSE);
1854     aopOp (IC_RESULT(ic),ic,TRUE);
1855
1856     /* Swap the left and right operands if:
1857
1858        if literal, literal on the right or
1859        if left requires ACC or right is already
1860        in ACC */
1861
1862     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1863         (AOP_NEEDSACC(IC_LEFT(ic))) ||
1864         AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1865         operand *t = IC_RIGHT(ic);
1866         IC_RIGHT(ic) = IC_LEFT(ic);
1867         IC_LEFT(ic) = t;
1868     }
1869
1870     /* if both left & right are in bit
1871     space */
1872     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1873         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1874         /* Cant happen */
1875         wassert(0);
1876     }
1877
1878     /* if left in bit space & right literal */
1879     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1880         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1881         /* Can happen I guess */
1882         wassert(0);
1883     }
1884
1885     /* if I can do an increment instead
1886     of add then GOOD for ME */
1887     if (genPlusIncr (ic) == TRUE)
1888         goto release;   
1889
1890     size = getDataSize(IC_RESULT(ic));
1891
1892     /* Special case when left and right are constant */
1893     if (isPair(AOP(IC_RESULT(ic)))) {
1894         char *left, *right;
1895         
1896         left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1897         right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1898         if (left && right) {
1899             /* It's a pair */
1900             /* PENDING: fix */
1901             char buffer[100];
1902             sprintf(buffer, "#(%s + %s)", left, right);
1903             emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1904             goto release;
1905         }
1906     }
1907
1908     if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
1909         /* Fetch into HL then do the add */
1910         spillPair(PAIR_HL);
1911         fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
1912         emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
1913         goto release;
1914     }
1915
1916     while(size--) {
1917         if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1918             MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1919             if(offset == 0)
1920                 emitcode("add","a,%s",
1921                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1922             else
1923                 emitcode("adc","a,%s",
1924                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1925         } else {
1926             MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1927             if(offset == 0)
1928                 emitcode("add","a,%s",
1929                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1930             else
1931                 emitcode("adc","a,%s",
1932                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1933         }
1934         aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
1935     }
1936
1937     /* Some kind of pointer arith. */
1938     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
1939         AOP_SIZE(IC_LEFT(ic)) == 3   &&
1940         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1941         wassert(0);
1942
1943      if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
1944         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
1945         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1946          wassert(0);
1947
1948    
1949 release:
1950     freeAsmop(IC_LEFT(ic),NULL,ic);
1951     freeAsmop(IC_RIGHT(ic),NULL,ic);
1952     freeAsmop(IC_RESULT(ic),NULL,ic);
1953     
1954 }
1955
1956 /*-----------------------------------------------------------------*/
1957 /* genMinusDec :- does subtraction with deccrement if possible     */
1958 /*-----------------------------------------------------------------*/
1959 static bool genMinusDec (iCode *ic)
1960 {
1961     unsigned int icount ;
1962     unsigned int size = getDataSize(IC_RESULT(ic));
1963
1964     /* will try to generate an increment */
1965     /* if the right side is not a literal we cannot */
1966     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1967         return FALSE ;
1968
1969     /* if the literal value of the right hand side
1970     is greater than 4 then it is not worth it */
1971     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1972         return FALSE;
1973
1974     size = getDataSize(IC_RESULT(ic));
1975
1976 #if 0
1977     /* if increment 16 bits in register */
1978     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1979         (size > 1) &&
1980         (icount == 1)) {
1981         symbol *tlbl = newiTempLabel(NULL);
1982         emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1983         emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
1984     
1985         emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1986         if(size == 4) {
1987             wassert(0);
1988         }
1989         emitLabel(tlbl->key+100);
1990         return TRUE;
1991     }
1992 #endif
1993
1994     /* if decrement 16 bits in register */
1995     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1996         (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1997         while (icount--)
1998             emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1999         return TRUE;
2000     }
2001
2002     /* If result is a pair */
2003     if (isPair(AOP(IC_RESULT(ic)))) {
2004         movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2005         movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2006         while (icount--)
2007             emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2008         return TRUE;
2009     }
2010
2011     /* if the sizes are greater than 1 then we cannot */
2012     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2013         AOP_SIZE(IC_LEFT(ic)) > 1   )
2014         return FALSE ;
2015
2016     /* we can if the aops of the left & result match or if they are in
2017        registers and the registers are the same */
2018     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2019         while (icount--) 
2020             emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
2021         return TRUE ;
2022     }
2023
2024     return FALSE ;
2025 }
2026
2027 /*-----------------------------------------------------------------*/
2028 /* genMinus - generates code for subtraction                       */
2029 /*-----------------------------------------------------------------*/
2030 static void genMinus (iCode *ic)
2031 {
2032     int size, offset = 0;
2033     unsigned long lit = 0L;
2034
2035     aopOp (IC_LEFT(ic),ic,FALSE);
2036     aopOp (IC_RIGHT(ic),ic,FALSE);
2037     aopOp (IC_RESULT(ic),ic,TRUE);
2038
2039     /* special cases :- */
2040     /* if both left & right are in bit space */
2041     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2042         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2043         wassert(0);
2044         goto release ;
2045     }
2046
2047     /* if I can do an decrement instead of subtract then GOOD for ME */
2048     if (genMinusDec (ic) == TRUE)
2049         goto release;   
2050
2051     size = getDataSize(IC_RESULT(ic));   
2052
2053     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2054     }
2055     else{
2056         lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2057         lit = - (long)lit;
2058     }
2059
2060
2061     /* if literal, add a,#-lit, else normal subb */
2062     while (size--) {
2063         MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));    
2064         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
2065             if (!offset)
2066                 emitcode("sub","a,%s",
2067                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2068             else
2069                 emitcode("sbc","a,%s",
2070                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2071         }
2072         else{
2073             /* first add without previous c */
2074             if (!offset)
2075                 emit2("add a,!immedbyte", (unsigned int)(lit & 0x0FFL));
2076             else
2077                 emit2("adc a,!immedbyte", (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2078         }
2079         aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
2080     }
2081     
2082     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
2083         AOP_SIZE(IC_LEFT(ic)) == 3   &&
2084         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2085         wassert(0);
2086
2087 release:
2088     freeAsmop(IC_LEFT(ic),NULL,ic);
2089     freeAsmop(IC_RIGHT(ic),NULL,ic);
2090     freeAsmop(IC_RESULT(ic),NULL,ic);
2091 }
2092
2093 /*-----------------------------------------------------------------*/
2094 /* genMult - generates code for multiplication                     */
2095 /*-----------------------------------------------------------------*/
2096 static void genMult (iCode *ic)
2097 {
2098     /* Shouldn't occur - all done through function calls */
2099     wassert(0);
2100 }
2101
2102 /*-----------------------------------------------------------------*/
2103 /* genDiv - generates code for division                            */
2104 /*-----------------------------------------------------------------*/
2105 static void genDiv (iCode *ic)
2106 {
2107     /* Shouldn't occur - all done through function calls */
2108     wassert(0);
2109 }
2110
2111 /*-----------------------------------------------------------------*/
2112 /* genMod - generates code for division                            */
2113 /*-----------------------------------------------------------------*/
2114 static void genMod (iCode *ic)
2115 {
2116     /* Shouldn't occur - all done through function calls */
2117     wassert(0);
2118 }
2119
2120 /*-----------------------------------------------------------------*/
2121 /* genIfxJump :- will create a jump depending on the ifx           */
2122 /*-----------------------------------------------------------------*/
2123 static void genIfxJump (iCode *ic, char *jval)
2124 {
2125     symbol *jlbl ;
2126     const char *inst;
2127
2128     /* if true label then we jump if condition
2129     supplied is true */
2130     if ( IC_TRUE(ic) ) {
2131         jlbl = IC_TRUE(ic);
2132         if (!strcmp(jval, "a")) {
2133             inst = "nz";
2134         }
2135         else if (!strcmp(jval, "c")) {
2136             inst = "c";
2137         }
2138         else {
2139             /* The buffer contains the bit on A that we should test */
2140             inst = "nz";
2141         }
2142     }
2143     else {
2144         /* false label is present */
2145         jlbl = IC_FALSE(ic) ;
2146         if (!strcmp(jval, "a")) {
2147             inst = "z";
2148         }
2149         else if (!strcmp(jval, "c")) {
2150             inst = "nc";
2151         }
2152         else {
2153             /* The buffer contains the bit on A that we should test */
2154             inst = "z";
2155         }
2156     }
2157     /* Z80 can do a conditional long jump */
2158     if (!strcmp(jval, "a")) {
2159         emitcode("or", "a,a");
2160     }
2161     else if (!strcmp(jval, "c")) {
2162     }
2163     else {
2164         emitcode("bit", "%s,a", jval);
2165     }
2166     emit2("jp %s,!tlabel", inst, jlbl->key+100);
2167
2168     /* mark the icode as generated */
2169     ic->generated = 1;
2170 }
2171
2172 /** Generic compare for > or <
2173  */
2174 static void genCmp (operand *left,operand *right,
2175                     operand *result, iCode *ifx, int sign)
2176 {
2177     int size, offset = 0 ;
2178     unsigned long lit = 0L;
2179
2180     /* if left & right are bit variables */
2181     if (AOP_TYPE(left) == AOP_CRY &&
2182         AOP_TYPE(right) == AOP_CRY ) {
2183         /* Cant happen on the Z80 */
2184         wassert(0);
2185     } else {
2186         /* subtract right from left if at the
2187         end the carry flag is set then we know that
2188         left is greater than right */
2189         size = max(AOP_SIZE(left),AOP_SIZE(right));
2190
2191         /* if unsigned char cmp with lit, just compare */
2192         if((size == 1) && 
2193            (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2194             emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2195             if (sign) {
2196                 emit2("xor a,!immedbyte", 0x80);
2197                 emit2("cp %s^!constbyte", aopGet(AOP(right), offset, FALSE), 0x80);
2198             }
2199             else 
2200                 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
2201         } 
2202         else {
2203             if(AOP_TYPE(right) == AOP_LIT) {
2204                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2205                 /* optimize if(x < 0) or if(x >= 0) */
2206                 if (lit == 0L){
2207                     if (!sign) {
2208                         /* No sign so it's always false */
2209                         CLRC;
2210                     }
2211                     else{
2212                         /* Just load in the top most bit */
2213                         MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2214                         if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2215                             genIfxJump (ifx,"7");
2216                             return;
2217                         }
2218                         else    
2219                             emitcode("rlc","a");
2220                     }
2221                     goto release;
2222                 }
2223             }
2224             if (sign) {
2225                 /* First setup h and l contaning the top most bytes XORed */
2226                 bool fDidXor = FALSE;
2227                 if (AOP_TYPE(left) == AOP_LIT){
2228                     unsigned long lit = (unsigned long)
2229                         floatFromVal(AOP(left)->aopu.aop_lit);
2230                     emit2("ld %s,!immedbyte", _fTmp[0],
2231                              0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2232                 }
2233                 else {
2234                     emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2235                     emit2("xor a,!immedbyte", 0x80);
2236                     emitcode("ld", "%s,a", _fTmp[0]);
2237                     fDidXor = TRUE;
2238                 }
2239                 if (AOP_TYPE(right) == AOP_LIT) {
2240                     unsigned long lit = (unsigned long)
2241                         floatFromVal(AOP(right)->aopu.aop_lit);
2242                     emit2("ld %s,!immedbyte", _fTmp[1],
2243                              0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2244                 }
2245                 else {
2246                     emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2247                     emit2("xor a,!immedbyte", 0x80);
2248                     emitcode("ld", "%s,a", _fTmp[1]);
2249                     fDidXor = TRUE;
2250                 }
2251                 if (!fDidXor)
2252                     CLRC;
2253             }
2254             else {
2255                 CLRC;
2256             }
2257             while (size--) {
2258                 /* Do a long subtract */
2259                 if (!sign || size ) {
2260                     MOVA(aopGet(AOP(left),offset,FALSE));
2261                 }
2262                 if (sign && size == 0) {
2263                     emitcode("ld", "a,%s", _fTmp[0]);
2264                     emitcode("sbc", "a,%s", _fTmp[1]);
2265                 }
2266                 else {
2267                     /* Subtract through, propagating the carry */
2268                     emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2269                 }
2270             }
2271         }
2272     }
2273
2274 release:
2275     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2276         outBitC(result);
2277     } else {
2278         /* if the result is used in the next
2279         ifx conditional branch then generate
2280         code a little differently */
2281         if (ifx )
2282             genIfxJump (ifx,"c");
2283         else
2284             outBitC(result);
2285         /* leave the result in acc */
2286     }
2287 }
2288
2289 /*-----------------------------------------------------------------*/
2290 /* genCmpGt :- greater than comparison                             */
2291 /*-----------------------------------------------------------------*/
2292 static void genCmpGt (iCode *ic, iCode *ifx)
2293 {
2294     operand *left, *right, *result;
2295     link *letype , *retype;
2296     int sign ;
2297
2298     left = IC_LEFT(ic);
2299     right= IC_RIGHT(ic);
2300     result = IC_RESULT(ic);
2301
2302     letype = getSpec(operandType(left));
2303     retype =getSpec(operandType(right));
2304     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2305     /* assign the amsops */
2306     aopOp (left,ic,FALSE);
2307     aopOp (right,ic,FALSE);
2308     aopOp (result,ic,TRUE);
2309
2310     genCmp(right, left, result, ifx, sign);
2311
2312     freeAsmop(left,NULL,ic);
2313     freeAsmop(right,NULL,ic);
2314     freeAsmop(result,NULL,ic);
2315 }
2316
2317 /*-----------------------------------------------------------------*/
2318 /* genCmpLt - less than comparisons                                */
2319 /*-----------------------------------------------------------------*/
2320 static void genCmpLt (iCode *ic, iCode *ifx)
2321 {
2322     operand *left, *right, *result;
2323     link *letype , *retype;
2324     int sign ;
2325
2326     left = IC_LEFT(ic);
2327     right= IC_RIGHT(ic);
2328     result = IC_RESULT(ic);
2329
2330     letype = getSpec(operandType(left));
2331     retype =getSpec(operandType(right));
2332     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2333
2334     /* assign the amsops */
2335     aopOp (left,ic,FALSE);
2336     aopOp (right,ic,FALSE);
2337     aopOp (result,ic,TRUE);
2338
2339     genCmp(left, right, result, ifx, sign);
2340
2341     freeAsmop(left,NULL,ic);
2342     freeAsmop(right,NULL,ic);
2343     freeAsmop(result,NULL,ic);
2344 }
2345
2346 /*-----------------------------------------------------------------*/
2347 /* gencjneshort - compare and jump if not equal                    */
2348 /*-----------------------------------------------------------------*/
2349 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2350 {
2351     int size = max(AOP_SIZE(left),AOP_SIZE(right));
2352     int offset = 0;
2353     unsigned long lit = 0L;
2354
2355     /* Swap the left and right if it makes the computation easier */
2356     if (AOP_TYPE(left) == AOP_LIT) {
2357         operand *t = right;
2358         right = left;
2359         left = t;
2360     }
2361
2362     if(AOP_TYPE(right) == AOP_LIT)
2363         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2364
2365     /* if the right side is a literal then anything goes */
2366     if (AOP_TYPE(right) == AOP_LIT &&
2367         AOP_TYPE(left) != AOP_DIR ) {
2368         if (lit == 0) {
2369             emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2370             if (size > 1) {
2371                 size--;
2372                 offset++;
2373                 while (size--) {
2374                     emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2375                 }
2376             }
2377             else {
2378                 emitcode("or", "a,a");
2379             }
2380             emit2("jp nz,!tlabel", lbl->key+100);
2381         }
2382         else {
2383             while (size--) {
2384                 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2385                 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2386                     emitcode("or", "a,a");
2387                 else 
2388                     emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2389                 emit2("jp nz,!tlabel", lbl->key+100);
2390                 offset++;
2391             }
2392         }
2393     }
2394     /* if the right side is in a register or in direct space or
2395     if the left is a pointer register & right is not */    
2396     else if (AOP_TYPE(right) == AOP_REG ||
2397              AOP_TYPE(right) == AOP_DIR || 
2398              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2399         while (size--) {
2400             MOVA(aopGet(AOP(left),offset,FALSE));
2401             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2402                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2403                 /* PENDING */
2404                 emit2("jp nz,!tlabel", lbl->key+100);
2405             else {
2406                 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2407                 emit2("jp nz,!tlabel", lbl->key+100);
2408             }
2409             offset++;
2410         }
2411     } else {
2412         /* right is a pointer reg need both a & b */
2413         /* PENDING: is this required? */
2414         while(size--) {
2415             MOVA(aopGet(AOP(right),offset,FALSE));
2416             emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2417             emit2("!shortjp nz,!tlabel", lbl->key+100);
2418             offset++;
2419         }
2420     }
2421 }
2422
2423 /*-----------------------------------------------------------------*/
2424 /* gencjne - compare and jump if not equal                         */
2425 /*-----------------------------------------------------------------*/
2426 static void gencjne(operand *left, operand *right, symbol *lbl)
2427 {
2428     symbol *tlbl  = newiTempLabel(NULL);
2429
2430     gencjneshort(left, right, lbl);
2431
2432     /* PENDING: ?? */
2433     emit2("ld a,!one");
2434     emit2("!shortjp !tlabel", tlbl->key+100);
2435     emitLabel(lbl->key+100);
2436     emitcode("xor","a,a");
2437     emitLabel(tlbl->key+100);
2438 }
2439
2440 /*-----------------------------------------------------------------*/
2441 /* genCmpEq - generates code for equal to                          */
2442 /*-----------------------------------------------------------------*/
2443 static void genCmpEq (iCode *ic, iCode *ifx)
2444 {
2445     operand *left, *right, *result;
2446
2447     aopOp((left=IC_LEFT(ic)),ic,FALSE);
2448     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2449     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2450
2451     /* Swap operands if it makes the operation easier. ie if:
2452        1.  Left is a literal.
2453     */
2454     if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2455         operand *t = IC_RIGHT(ic);
2456         IC_RIGHT(ic) = IC_LEFT(ic);
2457         IC_LEFT(ic) = t;
2458     }
2459
2460     if (ifx && !AOP_SIZE(result)){
2461         symbol *tlbl;
2462         /* if they are both bit variables */
2463         if (AOP_TYPE(left) == AOP_CRY &&
2464             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2465             wassert(0);
2466         } else {
2467             tlbl = newiTempLabel(NULL);
2468             gencjneshort(left, right, tlbl);
2469             if ( IC_TRUE(ifx) ) {
2470                 emit2("jp !tlabel", IC_TRUE(ifx)->key+100);
2471                 emitLabel(tlbl->key+100);
2472             } else {
2473                 /* PENDING: do this better */
2474                 symbol *lbl = newiTempLabel(NULL);
2475                 emit2("!shortjp !tlabel", lbl->key+100);
2476                 emitLabel(tlbl->key+100);
2477                 emit2("jp !tlabel", IC_FALSE(ifx)->key+100);
2478                 emitLabel(lbl->key+100);             
2479             }
2480         }
2481         /* mark the icode as generated */
2482         ifx->generated = 1;
2483         goto release ;
2484     }
2485
2486     /* if they are both bit variables */
2487     if (AOP_TYPE(left) == AOP_CRY &&
2488         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2489         wassert(0);
2490     } else {
2491         gencjne(left,right,newiTempLabel(NULL));    
2492         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2493             wassert(0);
2494         }
2495         if (ifx) {
2496             genIfxJump(ifx,"a");
2497             goto release;
2498         }
2499         /* if the result is used in an arithmetic operation
2500         then put the result in place */
2501         if (AOP_TYPE(result) != AOP_CRY) {
2502             outAcc(result);
2503         }
2504         /* leave the result in acc */
2505     }
2506
2507 release:
2508     freeAsmop(left,NULL,ic);
2509     freeAsmop(right,NULL,ic);
2510     freeAsmop(result,NULL,ic);
2511 }
2512
2513 /*-----------------------------------------------------------------*/
2514 /* ifxForOp - returns the icode containing the ifx for operand     */
2515 /*-----------------------------------------------------------------*/
2516 static iCode *ifxForOp ( operand *op, iCode *ic )
2517 {
2518     /* if true symbol then needs to be assigned */
2519     if (IS_TRUE_SYMOP(op))
2520         return NULL ;
2521
2522     /* if this has register type condition and
2523     the next instruction is ifx with the same operand
2524     and live to of the operand is upto the ifx only then */
2525     if (ic->next &&
2526         ic->next->op == IFX &&
2527         IC_COND(ic->next)->key == op->key &&
2528         OP_SYMBOL(op)->liveTo <= ic->next->seq )
2529         return ic->next;
2530
2531     return NULL;
2532 }
2533
2534 /*-----------------------------------------------------------------*/
2535 /* genAndOp - for && operation                                     */
2536 /*-----------------------------------------------------------------*/
2537 static void genAndOp (iCode *ic)
2538 {
2539     operand *left,*right, *result;
2540     symbol *tlbl;
2541
2542     /* note here that && operations that are in an if statement are
2543        taken away by backPatchLabels only those used in arthmetic
2544        operations remain */
2545     aopOp((left=IC_LEFT(ic)),ic,FALSE);
2546     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2547     aopOp((result=IC_RESULT(ic)),ic,FALSE);
2548
2549     /* if both are bit variables */
2550     if (AOP_TYPE(left) == AOP_CRY &&
2551         AOP_TYPE(right) == AOP_CRY ) {
2552         wassert(0);
2553     } else {
2554         tlbl = newiTempLabel(NULL);
2555         toBoolean(left);    
2556         emit2("!shortjp z,!tlabel", tlbl->key+100);
2557         toBoolean(right);
2558         emitLabel(tlbl->key+100);
2559         outBitAcc(result);
2560     }
2561
2562     freeAsmop(left,NULL,ic);
2563     freeAsmop(right,NULL,ic);
2564     freeAsmop(result,NULL,ic);
2565 }
2566
2567 /*-----------------------------------------------------------------*/
2568 /* genOrOp - for || operation                                      */
2569 /*-----------------------------------------------------------------*/
2570 static void genOrOp (iCode *ic)
2571 {
2572     operand *left,*right, *result;
2573     symbol *tlbl;
2574
2575     /* note here that || operations that are in an
2576        if statement are taken away by backPatchLabels
2577        only those used in arthmetic operations remain */
2578     aopOp((left=IC_LEFT(ic)),ic,FALSE);
2579     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2580     aopOp((result=IC_RESULT(ic)),ic,FALSE);
2581
2582     /* if both are bit variables */
2583     if (AOP_TYPE(left) == AOP_CRY &&
2584         AOP_TYPE(right) == AOP_CRY ) {
2585         wassert(0);
2586     } else {
2587         tlbl = newiTempLabel(NULL);
2588         toBoolean(left);
2589         emit2("!shortjp nz,!tlabel", tlbl->key+100);
2590         toBoolean(right);
2591         emitLabel(tlbl->key+100);
2592         outBitAcc(result);
2593     }
2594
2595     freeAsmop(left,NULL,ic);
2596     freeAsmop(right,NULL,ic);
2597     freeAsmop(result,NULL,ic);
2598 }
2599
2600 /*-----------------------------------------------------------------*/
2601 /* isLiteralBit - test if lit == 2^n                               */
2602 /*-----------------------------------------------------------------*/
2603 int isLiteralBit(unsigned long lit)
2604 {
2605     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2606     0x100L,0x200L,0x400L,0x800L,
2607     0x1000L,0x2000L,0x4000L,0x8000L,
2608     0x10000L,0x20000L,0x40000L,0x80000L,
2609     0x100000L,0x200000L,0x400000L,0x800000L,
2610     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2611     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2612     int idx;
2613     
2614     for(idx = 0; idx < 32; idx++)
2615         if(lit == pw[idx])
2616             return idx+1;
2617     return 0;
2618 }
2619
2620 /*-----------------------------------------------------------------*/
2621 /* jmpTrueOrFalse -                                                */
2622 /*-----------------------------------------------------------------*/
2623 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
2624 {
2625     // ugly but optimized by peephole
2626     if(IC_TRUE(ic)){
2627         symbol *nlbl = newiTempLabel(NULL);
2628         emit2("jp !tlabel", nlbl->key+100);                 
2629         emitLabel(tlbl->key+100);
2630         emit2("jp !tlabel", IC_TRUE(ic)->key+100);
2631         emitLabel(nlbl->key+100);
2632     }
2633     else{
2634         emit2("jp !tlabel", IC_FALSE(ic)->key+100);
2635         emitLabel(tlbl->key+100);
2636     }
2637     ic->generated = 1;
2638 }
2639
2640 /*-----------------------------------------------------------------*/
2641 /* genAnd  - code for and                                          */
2642 /*-----------------------------------------------------------------*/
2643 static void genAnd (iCode *ic, iCode *ifx)
2644 {
2645     operand *left, *right, *result;
2646     int size, offset=0;  
2647     unsigned long lit = 0L;
2648     int bytelit = 0;
2649
2650     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2651     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2652     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2653
2654 #ifdef DEBUG_TYPE
2655     emitcode("","; Type res[%d] = l[%d]&r[%d]",
2656              AOP_TYPE(result),
2657              AOP_TYPE(left), AOP_TYPE(right));
2658     emitcode("","; Size res[%d] = l[%d]&r[%d]",
2659              AOP_SIZE(result),
2660              AOP_SIZE(left), AOP_SIZE(right));
2661 #endif
2662
2663     /* if left is a literal & right is not then exchange them */
2664     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2665         AOP_NEEDSACC(left)) {
2666         operand *tmp = right ;
2667         right = left;
2668         left = tmp;
2669     }
2670
2671     /* if result = right then exchange them */
2672     if(sameRegs(AOP(result),AOP(right))){
2673         operand *tmp = right ;
2674         right = left;
2675         left = tmp;
2676     }
2677
2678     /* if right is bit then exchange them */
2679     if (AOP_TYPE(right) == AOP_CRY &&
2680         AOP_TYPE(left) != AOP_CRY){
2681         operand *tmp = right ;
2682         right = left;
2683         left = tmp;
2684     }
2685     if(AOP_TYPE(right) == AOP_LIT)
2686         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2687
2688     size = AOP_SIZE(result);
2689
2690     if (AOP_TYPE(left) == AOP_CRY){
2691         wassert(0);
2692         goto release ;
2693     }
2694
2695     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
2696     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
2697     if((AOP_TYPE(right) == AOP_LIT) &&
2698        (AOP_TYPE(result) == AOP_CRY) &&
2699        (AOP_TYPE(left) != AOP_CRY)) {
2700         int posbit = isLiteralBit(lit);
2701         /* left &  2^n */
2702         if(posbit){
2703             posbit--;
2704             MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2705             // bit = left & 2^n
2706             if(size) {
2707                 wassert(0);
2708                 emitcode("mov","c,acc.%d",posbit&0x07);
2709             }
2710             // if(left &  2^n)
2711             else{
2712                 if (ifx) {
2713                     sprintf(buffer, "%d", posbit&0x07);
2714                     genIfxJump(ifx, buffer);
2715                 }
2716                 else {
2717                     wassert(0);
2718                 }
2719                 goto release;
2720             }
2721         } else {
2722             symbol *tlbl = newiTempLabel(NULL);
2723             int sizel = AOP_SIZE(left);
2724             if(size) {
2725                 wassert(0);
2726                 emitcode("setb","c");
2727             }
2728             while(sizel--){
2729                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2730                     MOVA( aopGet(AOP(left),offset,FALSE));
2731                     // byte ==  2^n ?
2732                     if((posbit = isLiteralBit(bytelit)) != 0) {
2733                         wassert(0);
2734                         emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2735                     }
2736                     else{
2737                         if(bytelit != 0x0FFL)
2738                             emitcode("and","a,%s",
2739                                      aopGet(AOP(right),offset,FALSE));
2740                         emit2("!shortjp nz,!tlabel", tlbl->key+100);
2741                     }
2742                 }
2743                 offset++;
2744             }
2745             // bit = left & literal
2746             if (size){
2747                 emitcode("clr","c");
2748                 emit2("!tlabeldef", tlbl->key+100);
2749             }
2750             // if(left & literal)
2751             else{
2752                 if(ifx)
2753                     jmpTrueOrFalse(ifx, tlbl);
2754                 goto release ;
2755             }
2756         }
2757         outBitC(result);
2758         goto release ;
2759     }
2760
2761     /* if left is same as result */
2762     if(sameRegs(AOP(result),AOP(left))){
2763         for(;size--; offset++) {
2764             if(AOP_TYPE(right) == AOP_LIT){
2765                 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2766                     continue;
2767                 else {
2768                     if (bytelit == 0)
2769                         aopPut(AOP(result),zero,offset);
2770                     else {
2771                         MOVA(aopGet(AOP(left),offset,FALSE));
2772                         emitcode("and","a,%s",
2773                                  aopGet(AOP(right),offset,FALSE));
2774                         emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2775                     }
2776                 }
2777
2778             } else {
2779                 if (AOP_TYPE(left) == AOP_ACC) {
2780                     wassert(0);
2781                 }
2782                 else {
2783                     MOVA(aopGet(AOP(left),offset,FALSE));
2784                     emitcode("and","a,%s",
2785                              aopGet(AOP(right),offset,FALSE));
2786                     emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2787                 }
2788             }
2789         }
2790     } else {
2791         // left & result in different registers
2792         if(AOP_TYPE(result) == AOP_CRY){
2793             wassert(0);
2794         } else {
2795             for(;(size--);offset++) {
2796                 // normal case
2797                 // result = left & right
2798                 if(AOP_TYPE(right) == AOP_LIT){
2799                     if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2800                         aopPut(AOP(result),
2801                                aopGet(AOP(left),offset,FALSE),
2802                                offset);
2803                         continue;
2804                     } else if(bytelit == 0){
2805                         aopPut(AOP(result),zero,offset);
2806                         continue;
2807                     }
2808                 }
2809                 // faster than result <- left, anl result,right
2810                 // and better if result is SFR
2811                 if (AOP_TYPE(left) == AOP_ACC) 
2812                     emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2813                 else {
2814                     MOVA(aopGet(AOP(right),offset,FALSE));
2815                     emitcode("and","a,%s",
2816                              aopGet(AOP(left),offset,FALSE));
2817                 }
2818                 aopPut(AOP(result),"a",offset);
2819             }
2820         }
2821
2822     }
2823
2824 release :
2825     freeAsmop(left,NULL,ic);
2826     freeAsmop(right,NULL,ic);
2827     freeAsmop(result,NULL,ic);
2828 }
2829
2830 /*-----------------------------------------------------------------*/
2831 /* genOr  - code for or                                            */
2832 /*-----------------------------------------------------------------*/
2833 static void genOr (iCode *ic, iCode *ifx)
2834 {
2835     operand *left, *right, *result;
2836     int size, offset=0;
2837     unsigned long lit = 0L;
2838
2839     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2840     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2841     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2842
2843 #if 1
2844     emitcode("","; Type res[%d] = l[%d]&r[%d]",
2845              AOP_TYPE(result),
2846              AOP_TYPE(left), AOP_TYPE(right));
2847     emitcode("","; Size res[%d] = l[%d]&r[%d]",
2848              AOP_SIZE(result),
2849              AOP_SIZE(left), AOP_SIZE(right));
2850 #endif
2851
2852     /* if left is a literal & right is not then exchange them */
2853     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2854         AOP_NEEDSACC(left)) {
2855         operand *tmp = right ;
2856         right = left;
2857         left = tmp;
2858     }
2859
2860     /* if result = right then exchange them */
2861     if(sameRegs(AOP(result),AOP(right))){
2862         operand *tmp = right ;
2863         right = left;
2864         left = tmp;
2865     }
2866
2867     /* if right is bit then exchange them */
2868     if (AOP_TYPE(right) == AOP_CRY &&
2869         AOP_TYPE(left) != AOP_CRY){
2870         operand *tmp = right ;
2871         right = left;
2872         left = tmp;
2873     }
2874     if(AOP_TYPE(right) == AOP_LIT)
2875         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2876
2877     size = AOP_SIZE(result);
2878
2879     if (AOP_TYPE(left) == AOP_CRY){
2880         wassert(0);
2881         goto release ;
2882     }
2883
2884     if((AOP_TYPE(right) == AOP_LIT) &&
2885        (AOP_TYPE(result) == AOP_CRY) &&
2886        (AOP_TYPE(left) != AOP_CRY)){
2887         wassert(0);
2888         goto release ;
2889     }
2890
2891     /* if left is same as result */
2892     if(sameRegs(AOP(result),AOP(left))){
2893         for(;size--; offset++) {
2894             if(AOP_TYPE(right) == AOP_LIT){
2895                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2896                     continue;
2897                 else {
2898                     MOVA(aopGet(AOP(right),offset,FALSE));
2899                     emitcode("or","a,%s; 5",
2900                              aopGet(AOP(left),offset,FALSE));
2901                     aopPut(AOP(result),"a ; 8", offset);
2902                 }
2903             } else {
2904                 if (AOP_TYPE(left) == AOP_ACC) 
2905                     emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2906                 else {              
2907                     MOVA(aopGet(AOP(right),offset,FALSE));
2908                     emitcode("or","a,%s ; 7",
2909                              aopGet(AOP(left),offset,FALSE));
2910                     aopPut(AOP(result),"a ; 8", offset);
2911                 }
2912             }
2913         }
2914     } else {
2915         // left & result in different registers
2916         if(AOP_TYPE(result) == AOP_CRY){
2917             wassert(0);
2918         } else for(;(size--);offset++){
2919             // normal case
2920             // result = left & right
2921             if(AOP_TYPE(right) == AOP_LIT){
2922                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2923                     aopPut(AOP(result),
2924                            aopGet(AOP(left),offset,FALSE),
2925                            offset);
2926                     continue;
2927                 }
2928             }
2929             // faster than result <- left, anl result,right
2930             // and better if result is SFR
2931             if (AOP_TYPE(left) == AOP_ACC) 
2932                 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2933             else {
2934                 MOVA(aopGet(AOP(right),offset,FALSE));
2935                 emitcode("or","a,%s",
2936                          aopGet(AOP(left),offset,FALSE));
2937             }
2938             aopPut(AOP(result),"a",offset);                     
2939             /* PENDING: something weird is going on here.  Add exception. */
2940             if (AOP_TYPE(result) == AOP_ACC)
2941                 break;
2942         }
2943     }
2944
2945 release :
2946     freeAsmop(left,NULL,ic);
2947     freeAsmop(right,NULL,ic);
2948     freeAsmop(result,NULL,ic);
2949 }
2950
2951 /*-----------------------------------------------------------------*/
2952 /* genXor - code for xclusive or                                   */
2953 /*-----------------------------------------------------------------*/
2954 static void genXor (iCode *ic, iCode *ifx)
2955 {
2956     operand *left, *right, *result;
2957     int size, offset=0;
2958     unsigned long lit = 0L;
2959
2960     aopOp((left = IC_LEFT(ic)),ic,FALSE);
2961     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2962     aopOp((result=IC_RESULT(ic)),ic,TRUE);
2963
2964     /* if left is a literal & right is not then exchange them */
2965     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2966         AOP_NEEDSACC(left)) {
2967         operand *tmp = right ;
2968         right = left;
2969         left = tmp;
2970     }
2971
2972     /* if result = right then exchange them */
2973     if(sameRegs(AOP(result),AOP(right))){
2974         operand *tmp = right ;
2975         right = left;
2976         left = tmp;
2977     }
2978
2979     /* if right is bit then exchange them */
2980     if (AOP_TYPE(right) == AOP_CRY &&
2981         AOP_TYPE(left) != AOP_CRY){
2982         operand *tmp = right ;
2983         right = left;
2984         left = tmp;
2985     }
2986     if(AOP_TYPE(right) == AOP_LIT)
2987         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2988
2989     size = AOP_SIZE(result);
2990
2991     if (AOP_TYPE(left) == AOP_CRY){
2992         wassert(0);
2993         goto release ;
2994     }
2995
2996     if((AOP_TYPE(right) == AOP_LIT) &&
2997        (AOP_TYPE(result) == AOP_CRY) &&
2998        (AOP_TYPE(left) != AOP_CRY)){
2999         wassert(0);
3000         goto release ;
3001     }
3002
3003     /* if left is same as result */
3004     if(sameRegs(AOP(result),AOP(left))){
3005         for(;size--; offset++) {
3006             if(AOP_TYPE(right) == AOP_LIT){
3007                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3008                     continue;
3009                 else {
3010                     MOVA(aopGet(AOP(right),offset,FALSE));
3011                     emitcode("xor","a,%s",
3012                              aopGet(AOP(left),offset,FALSE));
3013                     aopPut(AOP(result),"a",0);
3014                 }
3015             } else {
3016                 if (AOP_TYPE(left) == AOP_ACC) 
3017                     emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3018                 else {              
3019                     MOVA(aopGet(AOP(right),offset,FALSE));
3020                     emitcode("xor","a,%s",
3021                              aopGet(AOP(left),offset,FALSE));
3022                     aopPut(AOP(result),"a",0);
3023                 }
3024             }
3025         }
3026     } else {
3027         // left & result in different registers
3028         if(AOP_TYPE(result) == AOP_CRY){
3029             wassert(0);
3030         } else for(;(size--);offset++){
3031             // normal case
3032             // result = left & right
3033             if(AOP_TYPE(right) == AOP_LIT){
3034                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3035                     aopPut(AOP(result),
3036                            aopGet(AOP(left),offset,FALSE),
3037                            offset);
3038                     continue;
3039                 }
3040             }
3041             // faster than result <- left, anl result,right
3042             // and better if result is SFR
3043             if (AOP_TYPE(left) == AOP_ACC) 
3044                 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3045             else {
3046                 MOVA(aopGet(AOP(right),offset,FALSE));
3047                 emitcode("xor","a,%s",
3048                          aopGet(AOP(left),offset,FALSE));
3049                 aopPut(AOP(result),"a",0);
3050             }
3051             aopPut(AOP(result),"a",offset);                     
3052         }
3053     }
3054
3055 release :
3056     freeAsmop(left,NULL,ic);
3057     freeAsmop(right,NULL,ic);
3058     freeAsmop(result,NULL,ic);
3059 }
3060
3061 /*-----------------------------------------------------------------*/
3062 /* genInline - write the inline code out                           */
3063 /*-----------------------------------------------------------------*/
3064 static void genInline (iCode *ic)
3065 {
3066     char buffer[MAX_INLINEASM];
3067     char *bp = buffer;
3068     char *bp1= buffer;
3069     
3070     inLine += (!options.asmpeep);
3071     strcpy(buffer,IC_INLINE(ic));
3072
3073     /* emit each line as a code */
3074     while (*bp) {
3075         if (*bp == '\n') {
3076             *bp++ = '\0';
3077             emitcode(bp1,"");
3078             bp1 = bp;
3079         } else {
3080             if (*bp == ':') {
3081                 bp++;
3082                 *bp = '\0';
3083                 bp++;
3084                 emitcode(bp1,"");
3085                 bp1 = bp;
3086             } else
3087                 bp++;
3088         }
3089     }
3090     if (bp1 != bp)
3091         emitcode(bp1,"");
3092     /*     emitcode("",buffer); */
3093     inLine -= (!options.asmpeep);
3094 }
3095
3096 /*-----------------------------------------------------------------*/
3097 /* genRRC - rotate right with carry                                */
3098 /*-----------------------------------------------------------------*/
3099 static void genRRC (iCode *ic)
3100 {
3101     wassert(0);
3102 }
3103
3104 /*-----------------------------------------------------------------*/
3105 /* genRLC - generate code for rotate left with carry               */
3106 /*-----------------------------------------------------------------*/
3107 static void genRLC (iCode *ic)
3108 {    
3109     wassert(0);
3110 }
3111
3112 /*-----------------------------------------------------------------*/
3113 /* shiftR2Left2Result - shift right two bytes from left to result  */
3114 /*-----------------------------------------------------------------*/
3115 static void shiftR2Left2Result (operand *left, int offl,
3116                                 operand *result, int offr,
3117                                 int shCount, int sign)
3118 {
3119     if(sameRegs(AOP(result), AOP(left)) &&
3120        ((offl + MSB16) == offr)){
3121         wassert(0);
3122     } else {
3123         movLeft2Result(left, offl, result, offr, 0);
3124         movLeft2Result(left, offl+1, result, offr+1, 0);
3125     }
3126
3127     if (sign) {
3128         wassert(0);
3129     }
3130     else {
3131         /*      if (AOP(result)->type == AOP_REG) {*/
3132             int size = 2;
3133             int offset = 0;
3134             symbol *tlbl , *tlbl1;
3135             char *l;
3136
3137             /* Left is already in result - so now do the shift */
3138             if (shCount>1) {
3139                 emit2("ld a,!immedbyte+1", shCount);
3140                 tlbl = newiTempLabel(NULL);
3141                 tlbl1 = newiTempLabel(NULL);
3142                 emit2("!shortjp !tlabel", tlbl1->key+100); 
3143                 emitLabel(tlbl->key+100);    
3144             }
3145
3146             emitcode("or", "a,a");
3147             offset = size;
3148             while (size--) {
3149                 l = aopGet(AOP(result), --offset, FALSE);
3150                 emitcode("rr","%s", l);         
3151             }
3152             if (shCount>1) {
3153                 emitLabel(tlbl1->key+100);
3154                 emitcode("dec", "a");
3155                 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3156             }
3157     }
3158 }
3159
3160 /*-----------------------------------------------------------------*/
3161 /* shiftL2Left2Result - shift left two bytes from left to result   */
3162 /*-----------------------------------------------------------------*/
3163 static void shiftL2Left2Result (operand *left, int offl,
3164                                 operand *result, int offr, int shCount)
3165 {
3166     if(sameRegs(AOP(result), AOP(left)) &&
3167        ((offl + MSB16) == offr)){
3168         wassert(0);
3169     } else {
3170         /* Copy left into result */
3171         movLeft2Result(left, offl, result, offr, 0);
3172         movLeft2Result(left, offl+1, result, offr+1, 0);
3173     }
3174     /* PENDING: for now just see if it'll work. */
3175     /*if (AOP(result)->type == AOP_REG) { */
3176     {
3177         int size = 2;
3178         int offset = 0;
3179         symbol *tlbl , *tlbl1;
3180         char *l;
3181
3182         /* Left is already in result - so now do the shift */
3183         if (shCount>1) {
3184             emit2("ld a,!immedbyte+1", shCount);
3185             tlbl = newiTempLabel(NULL);
3186             tlbl1 = newiTempLabel(NULL);
3187             emit2("!shortjp !tlabel", tlbl1->key+100); 
3188             emitLabel(tlbl->key+100);    
3189         }
3190
3191         emitcode("or", "a,a");
3192         while (size--) {
3193             l = aopGet(AOP(result),offset++,FALSE);
3194             emitcode("rl","%s", l);         
3195         }
3196         if (shCount>1) {
3197             emitLabel(tlbl1->key+100);
3198             emitcode("dec", "a");
3199             emit2("!shortjp nz,!tlabel", tlbl->key+100);
3200         }
3201     }
3202 }
3203
3204 /*-----------------------------------------------------------------*/
3205 /* AccRol - rotate left accumulator by known count                 */
3206 /*-----------------------------------------------------------------*/
3207 static void AccRol (int shCount)
3208 {
3209     shCount &= 0x0007;              // shCount : 0..7
3210     switch(shCount){
3211         case 0 :
3212             break;
3213         case 1 :
3214             emitcode("rl","a");
3215             break;
3216         case 2 :
3217             emitcode("rl","a");
3218             emitcode("rl","a");
3219             break;
3220         case 3 :
3221             emitcode("rl","a");
3222             emitcode("rl","a");
3223             emitcode("rl","a");
3224             break;
3225         case 4 :
3226             emitcode("rl","a");
3227             emitcode("rl","a");
3228             emitcode("rl","a");
3229             emitcode("rl","a");
3230             break;
3231         case 5 :
3232             emitcode("rr","a");
3233             emitcode("rr","a");
3234             emitcode("rr","a");
3235             break;
3236         case 6 :
3237             emitcode("rr","a");
3238             emitcode("rr","a");
3239             break;
3240         case 7 :
3241             emitcode("rr","a");
3242             break;
3243     }
3244 }
3245
3246 /*-----------------------------------------------------------------*/
3247 /* AccLsh - left shift accumulator by known count                  */
3248 /*-----------------------------------------------------------------*/
3249 static void AccLsh (int shCount)
3250 {
3251     if(shCount != 0){
3252         if(shCount == 1)
3253             emitcode("add","a,a");
3254         else 
3255             if(shCount == 2) {
3256             emitcode("add","a,a");
3257             emitcode("add","a,a");
3258         } else {
3259             /* rotate left accumulator */
3260             AccRol(shCount);
3261             /* and kill the lower order bits */
3262             emit2("and a,!immedbyte", SLMask[shCount]);
3263         }
3264     }
3265 }
3266
3267 /*-----------------------------------------------------------------*/
3268 /* shiftL1Left2Result - shift left one byte from left to result    */
3269 /*-----------------------------------------------------------------*/
3270 static void shiftL1Left2Result (operand *left, int offl,
3271                                 operand *result, int offr, int shCount)
3272 {
3273     char *l;
3274     l = aopGet(AOP(left),offl,FALSE);
3275     MOVA(l);
3276     /* shift left accumulator */
3277     AccLsh(shCount);
3278     aopPut(AOP(result),"a",offr);
3279 }
3280
3281
3282 /*-----------------------------------------------------------------*/
3283 /* genlshTwo - left shift two bytes by known amount != 0           */
3284 /*-----------------------------------------------------------------*/
3285 static void genlshTwo (operand *result,operand *left, int shCount)
3286 {
3287     int size = AOP_SIZE(result);
3288
3289     wassert(size==2);
3290
3291     /* if shCount >= 8 */
3292     if (shCount >= 8) {
3293         shCount -= 8 ;
3294
3295         if (size > 1){
3296             if (shCount) {
3297                 movLeft2Result(left, LSB, result, MSB16, 0);
3298                 aopPut(AOP(result),zero, 0);   
3299                 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
3300             }
3301             else {
3302                 movLeft2Result(left, LSB, result, MSB16, 0);
3303                 aopPut(AOP(result),zero, 0);   
3304             }
3305         }
3306         aopPut(AOP(result),zero,LSB);   
3307     }
3308     /*  1 <= shCount <= 7 */
3309     else {  
3310         if(size == 1) {
3311             wassert(0);
3312         }
3313         else {
3314             shiftL2Left2Result(left, LSB, result, LSB, shCount);
3315         }
3316     }
3317 }
3318
3319 /*-----------------------------------------------------------------*/
3320 /* genlshOne - left shift a one byte quantity by known count       */
3321 /*-----------------------------------------------------------------*/
3322 static void genlshOne (operand *result, operand *left, int shCount)
3323 {       
3324     shiftL1Left2Result(left, LSB, result, LSB, shCount);
3325 }
3326
3327 /*-----------------------------------------------------------------*/
3328 /* genLeftShiftLiteral - left shifting by known count              */
3329 /*-----------------------------------------------------------------*/
3330 static void genLeftShiftLiteral (operand *left,
3331                                  operand *right,
3332                                  operand *result,
3333                                  iCode *ic)
3334 {    
3335     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3336     int size;
3337
3338     freeAsmop(right,NULL,ic);
3339
3340     aopOp(left,ic,FALSE);
3341     aopOp(result,ic,FALSE);
3342
3343     size = getSize(operandType(result));
3344
3345 #if VIEW_SIZE
3346     emitcode("; shift left ","result %d, left %d",size,
3347              AOP_SIZE(left));
3348 #endif
3349
3350     /* I suppose that the left size >= result size */
3351     if (shCount == 0) {
3352         wassert(0);
3353     }
3354
3355     else if(shCount >= (size * 8))
3356         while(size--)
3357             aopPut(AOP(result),zero,size);
3358     else{
3359         switch (size) {
3360         case 1:
3361             genlshOne (result,left,shCount);
3362             break;
3363         case 2:
3364             genlshTwo (result,left,shCount);
3365             break;
3366         case 4:
3367             wassert(0);
3368             break;
3369         default:
3370             wassert(0);
3371         }
3372     }
3373     freeAsmop(left,NULL,ic);
3374     freeAsmop(result,NULL,ic);
3375 }
3376
3377 /*-----------------------------------------------------------------*/
3378 /* genLeftShift - generates code for left shifting                 */
3379 /*-----------------------------------------------------------------*/
3380 static void genLeftShift (iCode *ic)
3381 {
3382     int size, offset;
3383     char *l;
3384     symbol *tlbl , *tlbl1;
3385     operand *left,*right, *result;
3386
3387     right = IC_RIGHT(ic);
3388     left  = IC_LEFT(ic);
3389     result = IC_RESULT(ic);
3390
3391     aopOp(right,ic,FALSE);
3392
3393     /* if the shift count is known then do it 
3394     as efficiently as possible */
3395     if (AOP_TYPE(right) == AOP_LIT) {
3396         genLeftShiftLiteral (left,right,result,ic);
3397         return ;
3398     }
3399
3400     /* shift count is unknown then we have to form a loop get the loop
3401        count in B : Note: we take only the lower order byte since
3402        shifting more that 32 bits make no sense anyway, ( the largest
3403        size of an object can be only 32 bits ) */
3404     emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3405     emitcode("inc","a");
3406     freeAsmop (right,NULL,ic);
3407     aopOp(left,ic,FALSE);
3408     aopOp(result,ic,FALSE);
3409
3410     /* now move the left to the result if they are not the
3411        same */
3412 #if 1
3413     if (!sameRegs(AOP(left),AOP(result))) {
3414
3415         size = AOP_SIZE(result);
3416         offset = 0;
3417         while (size--) {
3418             l = aopGet(AOP(left),offset,FALSE);
3419             aopPut(AOP(result),l,offset);
3420             offset++;
3421         }
3422     }
3423 #else
3424     size = AOP_SIZE(result);
3425     offset = 0;
3426     while (size--) {
3427         l = aopGet(AOP(left),offset,FALSE);
3428         aopPut(AOP(result),l,offset);
3429         offset++;
3430     }
3431 #endif
3432
3433
3434     tlbl = newiTempLabel(NULL);
3435     size = AOP_SIZE(result);
3436     offset = 0 ;   
3437     tlbl1 = newiTempLabel(NULL);
3438
3439     emit2("!shortjp !tlabel", tlbl1->key+100); 
3440     emitLabel(tlbl->key+100);    
3441     l = aopGet(AOP(result),offset,FALSE);
3442     emitcode("or", "a,a");
3443     while (size--) {
3444         l = aopGet(AOP(result),offset++,FALSE);
3445         emitcode("rl","%s", l);         
3446     }
3447     emitLabel(tlbl1->key+100);
3448     emitcode("dec", "a");
3449     emit2("!shortjp nz,!tlabel", tlbl->key+100);
3450
3451     freeAsmop(left,NULL,ic);
3452     freeAsmop(result,NULL,ic);
3453 }
3454
3455 /*-----------------------------------------------------------------*/
3456 /* genlshTwo - left shift two bytes by known amount != 0           */
3457 /*-----------------------------------------------------------------*/
3458 static void genrshOne (operand *result,operand *left, int shCount)
3459 {
3460     /* Errk */
3461     int size = AOP_SIZE(result);
3462     char *l;
3463
3464     wassert(size==1);
3465     wassert(shCount<8);
3466
3467     l = aopGet(AOP(left),0,FALSE);
3468     if (AOP(result)->type == AOP_REG) {
3469         aopPut(AOP(result), l, 0);
3470         l = aopGet(AOP(result), 0, FALSE);
3471         while (shCount--) 
3472             emitcode("srl", "%s", l);
3473     }
3474     else {
3475         MOVA(l);
3476         while (shCount--) {
3477             emitcode("srl", "a");
3478         }
3479         aopPut(AOP(result),"a",0);
3480     }
3481 }
3482
3483 /*-----------------------------------------------------------------*/
3484 /* AccRsh - right shift accumulator by known count                 */
3485 /*-----------------------------------------------------------------*/
3486 static void AccRsh (int shCount)
3487 {
3488     if(shCount != 0){
3489         if(shCount == 1){
3490             CLRC;
3491             emitcode("rr","a");
3492         } else {
3493             /* rotate right accumulator */
3494             AccRol(8 - shCount);
3495             /* and kill the higher order bits */
3496             emit2("and a,!immedbyte", SRMask[shCount]);
3497         }
3498     }
3499 }
3500
3501 /*-----------------------------------------------------------------*/
3502 /* shiftR1Left2Result - shift right one byte from left to result   */
3503 /*-----------------------------------------------------------------*/
3504 static void shiftR1Left2Result (operand *left, int offl,
3505                                 operand *result, int offr,
3506                                 int shCount, int sign)
3507 {
3508     MOVA(aopGet(AOP(left),offl,FALSE));
3509     if (sign) {
3510         wassert(0);
3511     }
3512     else {
3513         AccRsh(shCount);
3514     }
3515     aopPut(AOP(result),"a",offr);
3516 }
3517
3518 /*-----------------------------------------------------------------*/
3519 /* genrshTwo - right shift two bytes by known amount != 0          */
3520 /*-----------------------------------------------------------------*/
3521 static void genrshTwo (operand *result,operand *left,
3522                        int shCount, int sign)
3523 {
3524     /* if shCount >= 8 */
3525     if (shCount >= 8) {
3526         shCount -= 8 ;
3527         if (shCount) {
3528             wassert(0);
3529             shiftR1Left2Result(left, MSB16, result, LSB,
3530                                shCount, sign);
3531         }
3532         else {
3533             movLeft2Result(left, MSB16, result, LSB, sign);
3534             aopPut(AOP(result),zero,1);
3535         }
3536     }
3537     /*  1 <= shCount <= 7 */
3538     else {
3539         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
3540     }
3541 }
3542
3543 /*-----------------------------------------------------------------*/
3544 /* genRightShiftLiteral - left shifting by known count              */
3545 /*-----------------------------------------------------------------*/
3546 static void genRightShiftLiteral (operand *left,
3547                                  operand *right,
3548                                  operand *result,
3549                                  iCode *ic)
3550 {    
3551     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3552     int size;
3553
3554     freeAsmop(right,NULL,ic);
3555
3556     aopOp(left,ic,FALSE);
3557     aopOp(result,ic,FALSE);
3558
3559     size = getSize(operandType(result));
3560
3561     emitcode("; shift right ","result %d, left %d",size,
3562              AOP_SIZE(left));
3563
3564     /* I suppose that the left size >= result size */
3565     if (shCount == 0) {
3566         wassert(0);
3567     }
3568
3569     else if(shCount >= (size * 8))
3570         while(size--)
3571             aopPut(AOP(result),zero,size);
3572     else{
3573         switch (size) {
3574         case 1:
3575             genrshOne(result, left, shCount);
3576             break;
3577         case 2:
3578             /* PENDING: sign support */
3579             genrshTwo(result, left, shCount, FALSE);
3580             break;
3581         case 4:
3582             wassert(0);
3583             break;
3584         default:
3585             wassert(0);
3586         }
3587     }
3588     freeAsmop(left,NULL,ic);
3589     freeAsmop(result,NULL,ic);
3590 }
3591
3592 /*-----------------------------------------------------------------*/
3593 /* genRightShift - generate code for right shifting                */
3594 /*-----------------------------------------------------------------*/
3595 static void genRightShift (iCode *ic)
3596 {
3597     operand *right, *left, *result;
3598     link *retype ;
3599     int size, offset, first = 1;
3600     char *l;
3601     bool is_signed;
3602
3603     symbol *tlbl, *tlbl1 ;
3604
3605     /* if signed then we do it the hard way preserve the
3606     sign bit moving it inwards */
3607     retype = getSpec(operandType(IC_RESULT(ic)));
3608
3609     is_signed = !SPEC_USIGN(retype);
3610
3611     /* signed & unsigned types are treated the same : i.e. the
3612     signed is NOT propagated inwards : quoting from the
3613     ANSI - standard : "for E1 >> E2, is equivalent to division
3614     by 2**E2 if unsigned or if it has a non-negative value,
3615     otherwise the result is implementation defined ", MY definition
3616     is that the sign does not get propagated */
3617
3618     right = IC_RIGHT(ic);
3619     left  = IC_LEFT(ic);
3620     result = IC_RESULT(ic);
3621
3622     aopOp(right,ic,FALSE);
3623
3624     /* if the shift count is known then do it 
3625     as efficiently as possible */
3626     if (AOP_TYPE(right) == AOP_LIT) {
3627         genRightShiftLiteral(left,right,result,ic);
3628         return;
3629     }
3630
3631     aopOp(left,ic,FALSE);
3632     aopOp(result,ic,FALSE);
3633
3634     /* now move the left to the result if they are not the
3635     same */
3636     if (!sameRegs(AOP(left),AOP(result)) && 
3637         AOP_SIZE(result) > 1) {
3638
3639         size = AOP_SIZE(result);
3640         offset=0;
3641         while (size--) {
3642             l = aopGet(AOP(left),offset,FALSE);
3643             aopPut(AOP(result),l,offset);
3644             offset++;
3645         }
3646     }
3647
3648     emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE));
3649     emitcode("inc","a");
3650     freeAsmop (right, NULL, ic);
3651
3652     tlbl = newiTempLabel(NULL);
3653     tlbl1= newiTempLabel(NULL);
3654     size = AOP_SIZE(result);
3655     offset = size - 1;
3656
3657     emit2("!shortjp !tlabel", tlbl1->key+100);
3658     emitLabel(tlbl->key+100);
3659     while (size--) {
3660         l = aopGet(AOP(result),offset--,FALSE);
3661         if (first) {
3662             if (is_signed)
3663                 emitcode("sra", "%s", l);
3664             else
3665                 emitcode("srl", "%s", l);
3666             first = 0;
3667         }
3668         else
3669             emitcode("rr", "%s", l);
3670     }
3671     emitLabel(tlbl1->key+100);
3672     emitcode("dec", "a");
3673     emit2("!shortjp nz,!tlabel", tlbl->key+100);
3674
3675     freeAsmop(left,NULL,ic);
3676     freeAsmop(result,NULL,ic);
3677 }
3678
3679 /*-----------------------------------------------------------------*/
3680 /* genGenPointerGet - gget value from generic pointer space        */
3681 /*-----------------------------------------------------------------*/
3682 static void genGenPointerGet (operand *left,
3683                               operand *result, iCode *ic)
3684 {
3685     int size, offset ;
3686     link *retype = getSpec(operandType(result));
3687     int pair = PAIR_HL;
3688
3689     if (IS_GB)
3690         pair = PAIR_DE;
3691
3692     aopOp(left,ic,FALSE);
3693     aopOp(result,ic,FALSE);
3694     
3695     if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
3696         /* Just do it */
3697         if (isPtrPair(AOP(left))) 
3698             {
3699                 tsprintf(buffer, "!*pair", getPairName(AOP(left)));
3700                 aopPut(AOP(result), buffer, 0);
3701             }
3702         else {
3703             emit2("ld a,!*pair", getPairName(AOP(left)));
3704             aopPut(AOP(result),"a", 0);
3705         }
3706         freeAsmop(left,NULL,ic);
3707         goto release;
3708     }
3709
3710     /* For now we always load into IY */
3711     /* if this is remateriazable */
3712     fetchPair(pair, AOP(left));
3713
3714     /* so iy now contains the address */
3715     freeAsmop(left,NULL,ic);
3716
3717     /* if bit then unpack */
3718     if (IS_BITVAR(retype)) {
3719         wassert(0);
3720     }
3721     else {
3722         size = AOP_SIZE(result);
3723         offset = 0 ;
3724
3725         while (size--) {
3726             /* PENDING: make this better */
3727             if (!IS_GB && AOP(result)->type == AOP_REG) {
3728                 aopPut(AOP(result), "!*hl", offset++);
3729             }
3730             else {
3731                 emit2("ld a,!*pair", _pairs[pair].name);
3732                 aopPut(AOP(result),"a",offset++);
3733             }
3734             if (size) {
3735                 emit2("inc %s", _pairs[pair].name);
3736             }
3737         }
3738     }
3739
3740  release:
3741     freeAsmop(result,NULL,ic);
3742 }
3743
3744 /*-----------------------------------------------------------------*/
3745 /* genPointerGet - generate code for pointer get                   */
3746 /*-----------------------------------------------------------------*/
3747 static void genPointerGet (iCode *ic)
3748 {
3749     operand *left, *result ;
3750     link *type, *etype;
3751
3752     left = IC_LEFT(ic);
3753     result = IC_RESULT(ic) ;
3754
3755     /* depending on the type of pointer we need to
3756     move it to the correct pointer register */
3757     type = operandType(left);
3758     etype = getSpec(type);
3759
3760     genGenPointerGet (left,result,ic);
3761 }
3762
3763 bool isRegOrLit(asmop *aop)
3764 {
3765     if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3766         return TRUE;
3767     return FALSE;
3768 }
3769
3770 /*-----------------------------------------------------------------*/
3771 /* genGenPointerSet - stores the value into a pointer location        */
3772 /*-----------------------------------------------------------------*/
3773 static void genGenPointerSet (operand *right,
3774                               operand *result, iCode *ic)
3775 {    
3776     int size, offset ;
3777     link *retype = getSpec(operandType(right));
3778     PAIR_ID pairId = PAIR_HL;
3779
3780     aopOp(result,ic,FALSE);
3781     aopOp(right,ic,FALSE);
3782
3783     if (IS_GB)
3784         pairId = PAIR_DE;
3785
3786     /* Handle the exceptions first */
3787     if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3788         /* Just do it */
3789         char *l = aopGet(AOP(right), 0, FALSE);
3790         const char *pair = getPairName(AOP(result));
3791         if (canAssignToPtr(l) && isPtr(pair)) {
3792             emit2("ld !*pair,%s", pair, l);
3793         }
3794         else {
3795             MOVA(l);
3796             emit2("ld !*pair,a", pair);
3797         }
3798         goto release;
3799     }
3800         
3801     /* if the operand is already in dptr 
3802        then we do nothing else we move the value to dptr */
3803     if (AOP_TYPE(result) != AOP_STR) {
3804         fetchPair(pairId, AOP(result));
3805     }
3806     /* so hl know contains the address */
3807     freeAsmop(result,NULL,ic);
3808
3809     /* if bit then unpack */
3810     if (IS_BITVAR(retype)) {
3811         wassert(0);
3812     }
3813     else {
3814         size = AOP_SIZE(right);
3815         offset = 0 ;
3816
3817         while (size--) {
3818             char *l = aopGet(AOP(right),offset,FALSE);
3819             if (isRegOrLit(AOP(right)) && !IS_GB) {
3820                 emit2("ld !*pair,%s", _pairs[pairId].name, l);
3821             }
3822             else {
3823                 MOVA(l);
3824                 emit2("ld !*pair,a", _pairs[pairId].name);
3825             }
3826             if (size) {
3827                 emitcode("inc", _pairs[pairId].name);
3828             }
3829             offset++;
3830         }
3831     }
3832     release:
3833     freeAsmop(right,NULL,ic);
3834 }
3835
3836 /*-----------------------------------------------------------------*/
3837 /* genPointerSet - stores the value into a pointer location        */
3838 /*-----------------------------------------------------------------*/
3839 static void genPointerSet (iCode *ic)
3840 {    
3841     operand *right, *result ;
3842     link *type, *etype;
3843
3844     right = IC_RIGHT(ic);
3845     result = IC_RESULT(ic) ;
3846
3847     /* depending on the type of pointer we need to
3848     move it to the correct pointer register */
3849     type = operandType(result);
3850     etype = getSpec(type);
3851     
3852     genGenPointerSet (right,result,ic);
3853 }
3854
3855 /*-----------------------------------------------------------------*/
3856 /* genIfx - generate code for Ifx statement                        */
3857 /*-----------------------------------------------------------------*/
3858 static void genIfx (iCode *ic, iCode *popIc)
3859 {
3860     operand *cond = IC_COND(ic);
3861     int isbit =0;
3862
3863     aopOp(cond,ic,FALSE);
3864
3865     /* get the value into acc */
3866     if (AOP_TYPE(cond) != AOP_CRY)
3867         toBoolean(cond);
3868     else
3869         isbit = 1;
3870     /* the result is now in the accumulator */
3871     freeAsmop(cond,NULL,ic);
3872
3873     /* if there was something to be popped then do it */
3874     if (popIc)
3875         genIpop(popIc);
3876
3877     /* if the condition is  a bit variable */
3878     if (isbit && IS_ITEMP(cond) && 
3879         SPIL_LOC(cond))
3880         genIfxJump(ic,SPIL_LOC(cond)->rname);
3881     else
3882         if (isbit && !IS_ITEMP(cond))
3883             genIfxJump(ic,OP_SYMBOL(cond)->rname);
3884         else
3885             genIfxJump(ic,"a");
3886
3887     ic->generated = 1;
3888 }
3889
3890 /*-----------------------------------------------------------------*/
3891 /* genAddrOf - generates code for address of                       */
3892 /*-----------------------------------------------------------------*/
3893 static void genAddrOf (iCode *ic)
3894 {
3895     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3896
3897     aopOp(IC_RESULT(ic),ic,FALSE);
3898
3899     /* if the operand is on the stack then we 
3900     need to get the stack offset of this
3901     variable */
3902     if (IS_GB) {
3903         if (sym->onStack) {
3904             spillCached();
3905             emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
3906             emitcode("ld", "d,h");
3907             emitcode("ld", "e,l");
3908         }
3909         else {
3910             emitcode("ld", "de,#%s", sym->rname);
3911         }
3912         aopPut(AOP(IC_RESULT(ic)), "e", 0);
3913         aopPut(AOP(IC_RESULT(ic)), "d", 1);
3914     }
3915     else {
3916         spillCached();
3917         if (sym->onStack) {
3918             /* if it has an offset  then we need to compute it */
3919             emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
3920             emitcode("add", "hl,sp");
3921         }
3922         else {
3923             emitcode("ld", "hl,#%s", sym->rname);
3924         }
3925         aopPut(AOP(IC_RESULT(ic)), "l", 0);
3926         aopPut(AOP(IC_RESULT(ic)), "h", 1);
3927     }
3928     freeAsmop(IC_RESULT(ic),NULL,ic);
3929 }
3930
3931 /*-----------------------------------------------------------------*/
3932 /* genAssign - generate code for assignment                        */
3933 /*-----------------------------------------------------------------*/
3934 static void genAssign (iCode *ic)
3935 {
3936     operand *result, *right;
3937     int size, offset ;
3938     unsigned long lit = 0L;
3939
3940     result = IC_RESULT(ic);
3941     right  = IC_RIGHT(ic) ;
3942
3943 #if 1
3944     /* Dont bother assigning if they are the same */
3945     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3946         emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3947         return;
3948     }
3949 #endif
3950
3951     aopOp(right,ic,FALSE);
3952     aopOp(result,ic,TRUE);
3953
3954     /* if they are the same registers */
3955     if (sameRegs(AOP(right),AOP(result))) {
3956         emitcode("", "; (registers are the same)");
3957         goto release;
3958     }
3959
3960     /* if the result is a bit */
3961     if (AOP_TYPE(result) == AOP_CRY) {
3962         wassert(0);
3963     }
3964
3965     /* general case */
3966     size = AOP_SIZE(result);
3967     offset = 0;
3968
3969     if(AOP_TYPE(right) == AOP_LIT)
3970         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3971     if (isPair(AOP(result)) && isLitWord(AOP(right))) {
3972         emitcode("ld", "%s,%s", getPairName(AOP(result)), aopGetWord(AOP(right), 0));
3973     }
3974     else if((size > 1) &&
3975        (AOP_TYPE(result) != AOP_REG) &&
3976        (AOP_TYPE(right) == AOP_LIT) &&
3977        !IS_FLOAT(operandType(right)) &&
3978        (lit < 256L)) {
3979         bool fXored = FALSE;
3980         offset = 0;
3981         /* Work from the top down.
3982            Done this way so that we can use the cached copy of 0
3983            in A for a fast clear */
3984         while (size--) {
3985             if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3986                 if (!fXored && size>1) {
3987                     emitcode("xor", "a,a");
3988                     fXored = TRUE;
3989                 }
3990                 if (fXored) {
3991                     aopPut(AOP(result),"a",offset);
3992                 }
3993                 else {
3994                     aopPut(AOP(result), zero, offset);
3995                 }
3996             }
3997             else
3998                 aopPut(AOP(result),
3999                        aopGet(AOP(right),offset,FALSE),
4000                        offset);
4001             offset++;
4002         }
4003     }
4004     else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
4005         /* Special case.  Load into a and d, then load out. */
4006         MOVA(aopGet(AOP(right), 0, FALSE));
4007         emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
4008         aopPut(AOP(result), "a", 0);
4009         aopPut(AOP(result), "e", 1);
4010     } else {
4011         while (size--) {
4012             /* PENDING: do this check better */
4013             if (requiresHL(AOP(right)) && requiresHL(AOP(result))) {
4014                 MOVA(aopGet(AOP(right), offset, FALSE));
4015                 aopPut(AOP(result), "a", offset);
4016             }
4017             else 
4018                 aopPut(AOP(result),
4019                        aopGet(AOP(right),offset,FALSE),
4020                        offset);
4021             offset++;
4022         }
4023     }
4024     
4025 release:
4026     freeAsmop(right,NULL,ic);
4027     freeAsmop(result,NULL,ic);
4028 }   
4029
4030 /*-----------------------------------------------------------------*/
4031 /* genJumpTab - genrates code for jump table                       */
4032 /*-----------------------------------------------------------------*/
4033 static void genJumpTab (iCode *ic)
4034 {
4035     symbol *jtab;
4036     char *l;
4037
4038     aopOp(IC_JTCOND(ic),ic,FALSE);
4039     /* get the condition into accumulator */
4040     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
4041     if (!IS_GB)
4042         emitcode("push", "de");
4043     emitcode("ld", "e,%s", l);
4044     emit2("ld d,!zero");
4045     jtab = newiTempLabel(NULL);
4046     spillCached();
4047     emit2("ld hl,!immed!tlabel", jtab->key+100);
4048     emitcode("add", "hl,de");
4049     emitcode("add", "hl,de");
4050     emitcode("add", "hl,de");
4051     freeAsmop(IC_JTCOND(ic),NULL,ic);
4052     if (!IS_GB)
4053         emitcode("pop", "de");
4054     emit2("jp !*hl");
4055     emitLabel(jtab->key+100);
4056     /* now generate the jump labels */
4057     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4058          jtab = setNextItem(IC_JTLABELS(ic)))
4059         emit2("jp !tlabel", jtab->key+100);
4060 }
4061
4062 /*-----------------------------------------------------------------*/
4063 /* genCast - gen code for casting                                  */
4064 /*-----------------------------------------------------------------*/
4065 static void genCast (iCode *ic)
4066 {
4067     operand *result = IC_RESULT(ic);
4068     link *ctype = operandType(IC_LEFT(ic));
4069     operand *right = IC_RIGHT(ic);
4070     int size, offset ;
4071
4072     /* if they are equivalent then do nothing */
4073     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4074         return ;
4075
4076     aopOp(right,ic,FALSE) ;
4077     aopOp(result,ic,FALSE);
4078
4079     /* if the result is a bit */
4080     if (AOP_TYPE(result) == AOP_CRY) {
4081         wassert(0);
4082     }
4083
4084     /* if they are the same size : or less */
4085     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4086
4087         /* if they are in the same place */
4088         if (sameRegs(AOP(right),AOP(result)))
4089             goto release;
4090
4091         /* if they in different places then copy */
4092         size = AOP_SIZE(result);
4093         offset = 0 ;
4094         while (size--) {
4095             aopPut(AOP(result),
4096                    aopGet(AOP(right),offset,FALSE),
4097                    offset);
4098             offset++;
4099         }
4100         goto release;
4101     }
4102
4103     /* PENDING: should be OK. */
4104 #if 0
4105     /* if the result is of type pointer */
4106     if (IS_PTR(ctype)) {
4107         wassert(0);
4108     }
4109 #endif
4110     
4111     /* so we now know that the size of destination is greater
4112     than the size of the source */
4113     /* we move to result for the size of source */
4114     size = AOP_SIZE(right);
4115     offset = 0 ;
4116     while (size--) {
4117         aopPut(AOP(result),
4118                aopGet(AOP(right),offset,FALSE),
4119                offset);
4120         offset++;
4121     }
4122
4123     /* now depending on the sign of the destination */
4124     size = AOP_SIZE(result) - AOP_SIZE(right);
4125     /* Unsigned or not an integral type - right fill with zeros */
4126     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
4127         while (size--)
4128             aopPut(AOP(result),zero,offset++);
4129     } else {
4130         /* we need to extend the sign :{ */
4131         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
4132                          FALSE);
4133         MOVA(l);
4134         emitcode("", "; genCast: sign extend untested.");
4135         emitcode("rla", "");
4136         emitcode("sbc", "a,a");
4137         while (size--)
4138             aopPut(AOP(result),"a",offset++);   
4139     }
4140
4141 release:
4142     freeAsmop(right, NULL, ic);
4143     freeAsmop(result, NULL, ic);
4144 }
4145
4146 /*-----------------------------------------------------------------*/
4147 /* genReceive - generate code for a receive iCode                  */
4148 /*-----------------------------------------------------------------*/
4149 static void genReceive (iCode *ic)
4150 {    
4151     if (isOperandInFarSpace(IC_RESULT(ic)) && 
4152         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
4153           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
4154         wassert(0);
4155     } else {
4156         accInUse++;
4157         aopOp(IC_RESULT(ic),ic,FALSE);  
4158         accInUse--;
4159         assignResultValue(IC_RESULT(ic));       
4160     }
4161
4162     freeAsmop(IC_RESULT(ic),NULL,ic);
4163 }
4164
4165 /*-----------------------------------------------------------------*/
4166 /* genZ80Code - generate code for Z80 based controllers            */
4167 /*-----------------------------------------------------------------*/
4168 void genZ80Code (iCode *lic)
4169 {
4170     iCode *ic;
4171     int cln = 0;
4172
4173     /* HACK */
4174     if (IS_GB) {
4175         _fReturn = _gbz80_return;
4176         _fTmp = _gbz80_return;
4177     }
4178     else {
4179         _fReturn = _z80_return;
4180         _fTmp = _z80_return;
4181     }
4182     tsprintf(zero, "!zero");
4183
4184     lineHead = lineCurr = NULL;
4185
4186     /* if debug information required */
4187     if (options.debug && currFunc) { 
4188         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4189         debugLine = 1;
4190         if (IS_STATIC(currFunc->etype))
4191             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
4192         else
4193             emitcode("","G$%s$0$0 ==.",currFunc->name);
4194         debugLine = 0;
4195     }
4196     /* stack pointer name */
4197     spname = "sp";
4198     
4199  
4200     for (ic = lic ; ic ; ic = ic->next ) {
4201         
4202         if ( cln != ic->lineno ) {
4203             if ( options.debug ) {
4204                 debugLine = 1;
4205                 emitcode("","C$%s$%d$%d$%d ==.",
4206                          ic->filename,ic->lineno,
4207                          ic->level,ic->block);
4208                 debugLine = 0;
4209             }
4210             emitcode(";","%s %d",ic->filename,ic->lineno);
4211             cln = ic->lineno ;
4212         }
4213         /* if the result is marked as
4214            spilt and rematerializable or code for
4215            this has already been generated then
4216            do nothing */
4217         if (resultRemat(ic) || ic->generated ) 
4218             continue ;
4219         
4220         /* depending on the operation */
4221         switch (ic->op) {
4222         case '!' :
4223             emitcode("", "; genNot");
4224             genNot(ic);
4225             break;
4226             
4227         case '~' :
4228             emitcode("", "; genCpl");
4229             genCpl(ic);
4230             break;
4231             
4232         case UNARYMINUS:
4233             emitcode("", "; genUminus");
4234             genUminus (ic);
4235             break;
4236             
4237         case IPUSH:
4238             emitcode("", "; genIpush");
4239             genIpush (ic);
4240             break;
4241             
4242         case IPOP:
4243             /* IPOP happens only when trying to restore a 
4244                spilt live range, if there is an ifx statement
4245                following this pop then the if statement might
4246                be using some of the registers being popped which
4247                would destory the contents of the register so
4248                we need to check for this condition and handle it */
4249             if (ic->next            && 
4250                 ic->next->op == IFX &&
4251                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4252                 emitcode("", "; genIfx");
4253                 genIfx (ic->next,ic);
4254             }
4255             else {
4256                 emitcode("", "; genIpop");
4257                 genIpop (ic);
4258             }
4259             break; 
4260             
4261         case CALL:
4262             emitcode("", "; genCall");
4263             genCall (ic);
4264             break;
4265             
4266         case PCALL:
4267             emitcode("", "; genPcall");
4268             genPcall (ic);
4269             break;
4270             
4271         case FUNCTION:
4272             emitcode("", "; genFunction");
4273             genFunction (ic);
4274             break;
4275             
4276         case ENDFUNCTION:
4277             emitcode("", "; genEndFunction");
4278             genEndFunction (ic);
4279             break;
4280             
4281         case RETURN:
4282             emitcode("", "; genRet");
4283             genRet (ic);
4284             break;
4285             
4286         case LABEL:
4287             emitcode("", "; genLabel");
4288             genLabel (ic);
4289             break;
4290             
4291         case GOTO:
4292             emitcode("", "; genGoto");
4293             genGoto (ic);
4294             break;
4295             
4296         case '+' :
4297             emitcode("", "; genPlus");
4298             genPlus (ic) ;
4299             break;
4300             
4301         case '-' :
4302             emitcode("", "; genMinus");
4303             genMinus (ic);
4304             break;
4305             
4306         case '*' :
4307             emitcode("", "; genMult");
4308             genMult (ic);
4309             break;
4310             
4311         case '/' :
4312             emitcode("", "; genDiv");
4313             genDiv (ic) ;
4314             break;
4315             
4316         case '%' :
4317             emitcode("", "; genMod");
4318             genMod (ic);
4319             break;
4320             
4321         case '>' :
4322             emitcode("", "; genCmpGt");
4323             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
4324             break;
4325             
4326         case '<' :
4327             emitcode("", "; genCmpLt");
4328             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4329             break;
4330             
4331         case LE_OP:
4332         case GE_OP:
4333         case NE_OP:
4334             
4335             /* note these two are xlated by algebraic equivalence
4336                during parsing SDCC.y */
4337             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4338                    "got '>=' or '<=' shouldn't have come here");
4339             break;      
4340             
4341         case EQ_OP:
4342             emitcode("", "; genCmpEq");
4343             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4344             break;          
4345             
4346         case AND_OP:
4347             emitcode("", "; genAndOp");
4348             genAndOp (ic);
4349             break;
4350             
4351         case OR_OP:
4352             emitcode("", "; genOrOp");
4353             genOrOp (ic);
4354             break;
4355             
4356         case '^' :
4357             emitcode("", "; genXor");
4358             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4359             break;
4360             
4361         case '|' :
4362             emitcode("", "; genOr");
4363             genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4364             break;
4365             
4366         case BITWISEAND:
4367             emitcode("", "; genAnd");
4368             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4369             break;
4370             
4371         case INLINEASM:
4372             emitcode("", "; genInline");
4373             genInline (ic);
4374             break;
4375             
4376         case RRC:
4377             emitcode("", "; genRRC");
4378             genRRC (ic);
4379             break;
4380             
4381         case RLC:
4382             emitcode("", "; genRLC");
4383             genRLC (ic);
4384             break;
4385             
4386         case GETHBIT:
4387             emitcode("", "; genHBIT");
4388             wassert(0);
4389             
4390         case LEFT_OP:
4391             emitcode("", "; genLeftShift");
4392             genLeftShift (ic);
4393             break;
4394             
4395         case RIGHT_OP:
4396             emitcode("", "; genRightShift");
4397             genRightShift (ic);
4398             break;
4399             
4400         case GET_VALUE_AT_ADDRESS:
4401             emitcode("", "; genPointerGet");
4402             genPointerGet(ic);
4403             break;
4404             
4405         case '=' :
4406
4407             if (POINTER_SET(ic)) {
4408                 emitcode("", "; genAssign (pointer)");
4409                 genPointerSet(ic);
4410             }
4411             else {
4412                 emitcode("", "; genAssign");
4413                 genAssign(ic);
4414             }
4415             break;
4416             
4417         case IFX:
4418             emitcode("", "; genIfx");
4419             genIfx (ic,NULL);
4420             break;
4421             
4422         case ADDRESS_OF:
4423             emitcode("", "; genAddrOf");
4424             genAddrOf (ic);
4425             break;
4426             
4427         case JUMPTABLE:
4428             emitcode("", "; genJumpTab");
4429             genJumpTab (ic);
4430             break;
4431             
4432         case CAST:
4433             emitcode("", "; genCast");
4434             genCast (ic);
4435             break;
4436             
4437         case RECEIVE:
4438             emitcode("", "; genReceive");
4439             genReceive(ic);
4440             break;
4441             
4442         case SEND:
4443             emitcode("", "; addSet");
4444             addSet(&sendSet,ic);
4445             break;
4446
4447         default :
4448             ic = ic;
4449             /*      piCode(ic,stdout); */
4450             
4451         }
4452     }
4453     
4454
4455     /* now we are ready to call the 
4456        peep hole optimizer */
4457     if (!options.nopeep)
4458         peepHole (&lineHead);
4459
4460     /* now do the actual printing */
4461     printLine (lineHead,codeOutFile);
4462     return;
4463 }