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