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