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