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