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