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