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