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