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