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