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