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