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