* src/SDCCmain.c (setParseWithComma): fixed bug #816685
[fw/sdcc] / src / z80 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - Z80 specific code generator.
3      
4   Michael Hope <michaelh@juju.net.nz> 2000
5   Based on the mcs51 generator -
6       Sandeep Dutta . sandeep.dutta@usa.net (1998)
7    and -  Jean-Louis VERN.jlvern@writeme.com (1999)
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27
28 -------------------------------------------------------------------------*/
29
30 /*
31   Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
32                                        ticks dhry  size
33   Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
34   Improved WORD push                    22784 144 19AE
35   With label1 on                        22694 144 197E
36   With label2 on                        22743 144 198A
37   With label3 on                        22776 144 1999
38   With label4 on                        22776 144 1999
39   With all 'label' on                   22661 144 196F
40   With loopInvariant on                 20919 156 19AB
41   With loopInduction on                 Breaks    198B
42   With all working on                   20796 158 196C
43   Slightly better genCmp(signed)        20597 159 195B
44   Better reg packing, first peephole    20038 163 1873
45   With assign packing                   19281 165 1849
46   5/3/00                                17741 185 17B6
47   With reg params for mul and div       16234 202 162D
48
49   1. Starting again at 3 Aug 01         34965  93 219C
50    No asm strings
51    Includes long mul/div in code
52   2. Optimised memcpy for acc use       32102 102 226B
53   3. Optimised strcpy for acc use       27819 117 2237
54   3a Optimised memcpy fun
55   4. Optimised strcmp fun               21999 149 2294
56   5. Optimised strcmp further           21660 151 228C
57   6. Optimised memcpy by unroling       20885 157 2201
58   7. After turning loop induction on    19862 165 236D
59   8. Same as 7 but with more info       
60   9. With asm optimised strings         17030 192 2223
61
62   10 and below are with asm strings off.
63
64   10 Mucho optimisations                13562 201 1FCC
65
66   Apparent advantage of turning on regparams:
67   1.  Cost of push
68         Decent case is push of a constant 
69           - ld hl,#n; push hl: (10+11)*nargs
70   2.  Cost of pull from stack
71         Using asm with ld hl, etc
72           - ld hl,#2; add hl,sp; (ld bc,(hl); hl+=2)*nargs
73             10+11+(7+6+7+6)*nargs
74   3.  Cost of fixing stack
75           - pop hl*nargs
76             10*nargs
77   
78   So cost is (10+11+7+6+7+10)*nargs+10+11 
79       = 51*nargs+21
80       = 123 for mul, div, strcmp, strcpy
81   Saving of (98298+32766+32766+32766)*123 = 24181308
82   At 192 d/s for 682411768t, speed up to 199.  Hmm.
83 */
84
85 #include <stdio.h>
86 #include <stdlib.h>
87 #include <string.h>
88 #include <ctype.h>
89
90 #if defined(__BORLANDC__) || defined(_MSC_VER)
91 #define STRCASECMP stricmp
92 #else
93 #define STRCASECMP strcasecmp
94 #endif
95
96 #include "z80.h"
97 #include "SDCCglobl.h"
98 #include "SDCCpeeph.h"
99 #include "gen.h"
100 #include "SDCCglue.h"
101 #include "newalloc.h"
102
103 /* This is the down and dirty file with all kinds of kludgy & hacky
104    stuff. This is what it is all about CODE GENERATION for a specific MCU.
105    Some of the routines may be reusable, will have to see */
106
107 /* Z80 calling convention description.
108    Parameters are passed right to left.  As the stack grows downwards,
109    the parameters are arranged in left to right in memory.
110    Parameters may be passed in the HL and DE registers with one
111    parameter per pair.
112    PENDING: What if the parameter is a long?
113    Everything is caller saves. i.e. the caller must save any registers
114    that it wants to preserve over the call.
115    GB: The return value is returned in DEHL.  DE is normally used as a
116    working register pair.  Caller saves allows it to be used for a
117    return value.
118    va args functions do not use register parameters.  All arguments
119    are passed on the stack.
120    IX is used as an index register to the top of the local variable
121    area.  ix-0 is the top most local variable.
122 */
123
124 enum 
125 {
126   /* Set to enable debugging trace statements in the output assembly code. */
127   DISABLE_DEBUG = 0
128 };
129
130 static char *_z80_return[] =
131 {"l", "h", "e", "d"};
132 static char *_gbz80_return[] =
133 {"e", "d", "l", "h"};
134 static char *_fReceive[] =
135   { "c", "b", "e", "d" };
136
137 static char **_fReturn;
138 static char **_fTmp;
139
140 extern FILE *codeOutFile;
141
142 enum
143   {
144     INT8MIN = -128,
145     INT8MAX = 127
146   };
147
148 /** Enum covering all the possible register pairs.
149  */
150 typedef enum
151   {
152     PAIR_INVALID,
153     PAIR_AF,
154     PAIR_BC,
155     PAIR_DE,
156     PAIR_HL,
157     PAIR_IY,
158     PAIR_IX,
159     NUM_PAIRS
160   } PAIR_ID;
161
162 static struct
163 {
164   const char *name;
165   const char *l;
166   const char *h;
167 } _pairs[NUM_PAIRS] = {
168   {    "??1", "?2", "?3" },
169   {    "af", "f", "a" },
170   {    "bc", "c", "b" },
171   {    "de", "e", "d" },
172   {    "hl", "l", "h" },
173   {    "iy", "iyl", "iyh" },
174   {    "ix", "ixl", "ixh" }
175 };
176
177 // PENDING
178 #define ACC_NAME        _pairs[PAIR_AF].h
179
180 enum 
181   {
182     LSB,
183     MSB16,
184     MSB24,
185     MSB32
186   };
187
188 /** Code generator persistent data.
189  */
190 static struct 
191 {
192   /** Used to optimised setting up of a pair by remebering what it
193       contains and adjusting instead of reloading where possible.
194   */
195   struct 
196   {
197     AOP_TYPE last_type;
198     const char *base;
199     int offset;
200   } pairs[NUM_PAIRS];
201   struct 
202   {
203     int last;
204     int pushed;
205     int param_offset;
206     int offset;
207     int pushedBC;
208     int pushedDE;
209   } stack;
210
211   struct
212   {
213     int pushedBC;
214     int pushedDE;
215   } calleeSaves;
216
217   bool omitFramePtr;
218   int frameId;
219   int receiveOffset;
220   bool flushStatics;
221   bool in_home;
222   const char *lastFunctionName;
223   iCode *current_iCode;
224   
225   set *sendSet;
226
227   struct
228   {
229     /** TRUE if the registers have already been saved. */
230     bool saved;
231   } saves;
232
233   struct 
234   {
235     lineNode *head;
236     lineNode *current;
237     int isInline;
238     int isDebug;
239     allocTrace trace;
240   } lines;
241
242   struct
243   {
244     allocTrace aops;
245   } trace;
246 } _G;
247
248 static const char *aopGet (asmop * aop, int offset, bool bit16);
249
250 static const char *aopNames[] = {
251   "AOP_INVALID",
252   "AOP_LIT",
253   "AOP_REG",
254   "AOP_DIR",
255   "AOP_SFR",
256   "AOP_STK",
257   "AOP_IMMD",
258   "AOP_STR",
259   "AOP_CRY",
260   "AOP_IY",
261   "AOP_HL",
262   "AOP_ACC",
263   "AOP_HLREG",
264   "AOP_SIMPLELIT",
265   "AOP_EXSTK",
266   "AOP_PAIRPT",
267   "AOP_DUMMY"
268 };
269
270 static bool
271 isLastUse (iCode *ic, operand *op)
272 {
273   bitVect *uses = bitVectCopy (OP_USES (op));
274
275   while (!bitVectIsZero (uses))
276     {
277       if (bitVectFirstBit (uses) == ic->key)
278         {
279           if (bitVectnBitsOn (uses) == 1)
280             {
281               return TRUE;
282             }
283           else
284             {
285               return FALSE;
286             }
287         }
288       bitVectUnSetBit (uses, bitVectFirstBit (uses));
289     }
290
291   return FALSE;
292 }
293
294 static PAIR_ID
295 _getTempPairId(void)
296 {
297   if (IS_GB)
298     {
299       return PAIR_DE;
300     }
301   else
302     {
303       return PAIR_HL;
304     }
305 }
306
307 static const char *
308 _getTempPairName(void)
309 {
310   return _pairs[_getTempPairId()].name;
311 }
312
313 static bool
314 isPairInUse (PAIR_ID id, iCode *ic)
315 {
316   if (id == PAIR_DE)
317     {
318       return bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
319     }
320   else if (id == PAIR_BC)
321     {
322       return bitVectBitValue (ic->rMask, B_IDX) || bitVectBitValue(ic->rMask, C_IDX);
323     }
324   else
325     {
326       wassertl (0, "Only implemented for DE and BC");
327       return TRUE;
328     }
329 }
330
331 static bool
332 isPairInUseNotInRet(PAIR_ID id, iCode *ic)
333 {
334   bitVect *rInUse;
335   
336   rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
337   
338   if (id == PAIR_DE)
339     {
340       return bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
341     }
342   else
343     {
344       wassertl (0, "Only implemented for DE");
345       return TRUE;
346     }
347 }
348
349 static PAIR_ID
350 getFreePairId (iCode *ic)
351 {
352   if (!isPairInUse (PAIR_BC, ic))
353     {
354       return PAIR_BC;
355     }
356   else if (IS_Z80 && !isPairInUse (PAIR_DE, ic))
357     {
358       return PAIR_DE;
359     }
360   else
361     {
362       return PAIR_INVALID;
363     }
364 }         
365
366 static void
367 _tidyUp (char *buf)
368 {
369   /* Clean up the line so that it is 'prettier' */
370   if (strchr (buf, ':'))
371     {
372       /* Is a label - cant do anything */
373       return;
374     }
375   /* Change the first (and probably only) ' ' to a tab so
376      everything lines up.
377   */
378   while (*buf)
379     {
380       if (*buf == ' ')
381         {
382           *buf = '\t';
383           break;
384         }
385       buf++;
386     }
387 }
388
389 static lineNode *
390 _newLineNode (char *line)
391 {
392   lineNode *pl;
393
394   pl = traceAlloc(&_G.lines.trace, Safe_alloc ( sizeof (lineNode)));
395   pl->line = traceAlloc(&_G.lines.trace, Safe_strdup (line));
396
397   return pl;
398 }
399
400 static void
401 _vemit2 (const char *szFormat, va_list ap)
402 {
403   char buffer[INITIAL_INLINEASM];
404
405   tvsprintf (buffer, sizeof(buffer), szFormat, ap);
406
407   _tidyUp (buffer);
408   _G.lines.current = (_G.lines.current ?
409               connectLine (_G.lines.current, _newLineNode (buffer)) :
410               (_G.lines.head = _newLineNode (buffer)));
411
412   _G.lines.current->isInline = _G.lines.isInline;
413   _G.lines.current->isDebug = _G.lines.isDebug;
414   _G.lines.current->ic = _G.current_iCode;
415 }
416
417 static void
418 emit2 (const char *szFormat,...)
419 {
420   va_list ap;
421
422   va_start (ap, szFormat);
423
424   _vemit2 (szFormat, ap);
425
426   va_end (ap);
427 }
428
429 static void
430 emitDebug (const char *szFormat,...)
431 {
432   if (!DISABLE_DEBUG)
433     {
434       va_list ap;
435
436       va_start (ap, szFormat);
437
438       _vemit2 (szFormat, ap);
439
440       va_end (ap);
441     }
442 }
443
444 /*-----------------------------------------------------------------*/
445 /* emit2 - writes the code into a file : for now it is simple    */
446 /*-----------------------------------------------------------------*/
447 void
448 _emit2 (const char *inst, const char *fmt,...)
449 {
450   va_list ap;
451   char lb[INITIAL_INLINEASM];
452   char *lbp = lb;
453
454   va_start (ap, fmt);
455
456   if (*inst != '\0')
457     {
458       sprintf (lb, "%s\t", inst);
459       vsprintf (lb + (strlen (lb)), fmt, ap);
460     }
461   else
462     vsprintf (lb, fmt, ap);
463
464   while (isspace (*lbp))
465     lbp++;
466
467   if (lbp && *lbp)
468     {
469       _G.lines.current = (_G.lines.current ?
470                   connectLine (_G.lines.current, _newLineNode (lb)) :
471                   (_G.lines.head = _newLineNode (lb)));
472     }
473   _G.lines.current->isInline = _G.lines.isInline;
474   _G.lines.current->ic = _G.current_iCode;
475   va_end (ap);
476 }
477
478 static void
479 _emitMove(const char *to, const char *from)
480 {
481   if (STRCASECMP(to, from) != 0) 
482     {
483       emit2("ld %s,%s", to, from);
484     }
485   else 
486     {
487       // Optimise it out.
488       // Could leave this to the peephole, but sometimes the peephole is inhibited.
489     }
490 }
491
492 void
493 aopDump(const char *plabel, asmop *aop)
494 {
495   int i;
496   char regbuf[9];
497   char *rbp = regbuf;
498   
499   emitDebug("; Dump of %s: type %s size %u", plabel, aopNames[aop->type], aop->size);
500   switch (aop->type)
501     {
502     case AOP_EXSTK:
503     case AOP_STK:
504       emitDebug(";  aop_stk %d", aop->aopu.aop_stk);
505       break;
506     case AOP_REG:
507       for (i=aop->size-1;i>=0;i--)
508         *rbp++ = *(aop->aopu.aop_reg[i]->name);
509       *rbp = '\0';
510       emitDebug(";  reg = %s", regbuf);
511       break;
512     case AOP_PAIRPTR:
513       emitDebug(";  pairptr = (%s)", _pairs[aop->aopu.aop_pairId].name);
514         
515     default:
516       /* No information. */
517       break;
518     }
519 }
520
521 static void
522 _moveA(const char *moveFrom)
523 {
524     // Let the peephole optimiser take care of redundent loads
525     _emitMove(ACC_NAME, moveFrom);
526 }
527
528 static void
529 _clearCarry(void)
530 {
531     emit2("xor a,a");
532 }
533
534 const char *
535 getPairName (asmop * aop)
536 {
537   if (aop->type == AOP_REG)
538     {
539       switch (aop->aopu.aop_reg[0]->rIdx)
540         {
541         case C_IDX:
542           return "bc";
543           break;
544         case E_IDX:
545           return "de";
546           break;
547         case L_IDX:
548           return "hl";
549           break;
550         }
551     }
552   else if (aop->type == AOP_STR || aop->type == AOP_HLREG)
553     {
554       int i;
555       for (i = 0; i < NUM_PAIRS; i++)
556         {
557           if (strcmp(aop->aopu.aop_str[0], _pairs[i].l) == 0)
558             {
559               return _pairs[i].name;
560             }
561         }
562     }
563   wassertl (0, "Tried to get the pair name of something that isn't a pair");
564   return NULL;
565 }
566
567 static PAIR_ID
568 getPairId (asmop * aop)
569 {
570   if (aop->size == 2)
571     {
572       if (aop->type == AOP_REG)
573         {
574           if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
575             {
576               return PAIR_BC;
577             }
578           if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
579             {
580               return PAIR_DE;
581             }
582           if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
583             {
584               return PAIR_HL;
585             }
586         }
587       else if (aop->type == AOP_STR || aop->type == AOP_HLREG)
588         {
589           int i;
590           for (i = 0; i < NUM_PAIRS; i++)
591             {
592               if (!strcmp (aop->aopu.aop_str[0], _pairs[i].l) && !strcmp (aop->aopu.aop_str[1], _pairs[i].h))
593                 {
594                   return i;
595                 }
596             }
597         }
598     }
599   return PAIR_INVALID;
600 }
601
602 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
603 bool
604 isPair (asmop * aop)
605 {
606   return (getPairId (aop) != PAIR_INVALID);
607 }
608
609 /** Returns TRUE if the registers used in aop cannot be split into high
610     and low halves */
611 bool
612 isUnsplitable (asmop * aop)
613 {
614   switch (getPairId (aop))
615     {
616     case PAIR_IX:
617     case PAIR_IY:
618       return TRUE;
619     default:
620       return FALSE;
621     }
622   return FALSE;
623 }
624
625 bool
626 isPtrPair (asmop * aop)
627 {
628   PAIR_ID pairId = getPairId (aop);
629   switch (pairId)
630     {
631     case PAIR_HL:
632     case PAIR_IY:
633     case PAIR_IX:
634       return TRUE;
635     default:
636       return FALSE;
637     }
638 }
639
640 static void
641 spillPair (PAIR_ID pairId)
642 {
643   _G.pairs[pairId].last_type = AOP_INVALID;
644   _G.pairs[pairId].base = NULL;
645 }
646
647 /* Given a register name, spill the pair (if any) the register is part of */
648 static void
649 spillPairReg (const char *regname)
650 {      
651   if (strlen(regname)==1)
652     {
653       switch (*regname)
654         {
655         case 'h':
656         case 'l':
657           spillPair(PAIR_HL);
658           break;
659         case 'd':
660         case 'e':
661           spillPair(PAIR_DE);
662           break;
663         case 'b':
664         case 'c':
665           spillPair(PAIR_BC);
666           break;
667         }
668     }
669 }
670
671 /** Push a register pair onto the stack */
672 void
673 genPairPush (asmop * aop)
674 {
675   emit2 ("push %s", getPairName (aop));
676 }
677
678 static void
679 _push (PAIR_ID pairId)
680 {
681   emit2 ("push %s", _pairs[pairId].name);
682   _G.stack.pushed += 2;
683 }
684
685 static void
686 _pop (PAIR_ID pairId)
687 {
688   emit2 ("pop %s", _pairs[pairId].name);
689   _G.stack.pushed -= 2;
690   spillPair (pairId);
691 }
692
693 void
694 genMovePairPair (PAIR_ID srcPair, PAIR_ID dstPair)
695 {
696   switch (dstPair)
697     {
698     case PAIR_IX:
699     case PAIR_IY:
700     case PAIR_AF:
701       _push(srcPair);
702       _pop(dstPair);
703       break;
704     case PAIR_BC:
705     case PAIR_DE:
706     case PAIR_HL:
707       if (srcPair == PAIR_IX || srcPair == PAIR_IY)
708         {
709           _push(srcPair);
710           _pop(dstPair);
711         }
712       else
713         {
714           emit2("ld %s,%s",_pairs[dstPair].l,_pairs[srcPair].l);
715           emit2("ld %s,%s",_pairs[dstPair].h,_pairs[srcPair].h);
716         }
717      default:
718        wassertl (0, "Tried to move a nonphysical pair");
719     }
720   _G.pairs[dstPair].last_type = _G.pairs[srcPair].last_type;
721   _G.pairs[dstPair].base = _G.pairs[srcPair].base;
722   _G.pairs[dstPair].offset = _G.pairs[srcPair].offset;
723 }
724
725
726 /*-----------------------------------------------------------------*/
727 /* newAsmop - creates a new asmOp                                  */
728 /*-----------------------------------------------------------------*/
729 static asmop *
730 newAsmop (short type)
731 {
732   asmop *aop;
733
734   aop = traceAlloc(&_G.trace.aops, Safe_alloc (sizeof (asmop)));
735   aop->type = type;
736   return aop;
737 }
738
739 /*-----------------------------------------------------------------*/
740 /* aopForSym - for a true symbol                                   */
741 /*-----------------------------------------------------------------*/
742 static asmop *
743 aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
744 {
745   asmop *aop;
746   memmap *space;
747
748   wassert (ic);
749   wassert (sym);
750   wassert (sym->etype);
751
752   space = SPEC_OCLS (sym->etype);
753
754   /* if already has one */
755   if (sym->aop)
756     {
757       return sym->aop;
758     }
759
760   /* Assign depending on the storage class */
761   if (sym->onStack || sym->iaccess)
762     {
763       /* The pointer that is used depends on how big the offset is.
764          Normally everything is AOP_STK, but for offsets of < -128 or
765          > 127 on the Z80 an extended stack pointer is used.
766       */
767       if (IS_Z80 && (_G.omitFramePtr || sym->stack < INT8MIN || sym->stack > (int)(INT8MAX-getSize (sym->type))))
768         {
769           emitDebug ("; AOP_EXSTK for %s", sym->rname);
770           sym->aop = aop = newAsmop (AOP_EXSTK);
771         }
772       else
773         {
774           emitDebug ("; AOP_STK for %s", sym->rname);
775           sym->aop = aop = newAsmop (AOP_STK);
776         }
777
778       aop->size = getSize (sym->type);
779       aop->aopu.aop_stk = sym->stack;
780       return aop;
781     }
782
783   /* special case for a function */
784   if (IS_FUNC (sym->type))
785     {
786       sym->aop = aop = newAsmop (AOP_IMMD);
787       aop->aopu.aop_immd = traceAlloc(&_G.trace.aops, Safe_strdup (sym->rname));
788       aop->size = 2;
789       return aop;
790     }
791
792   if (IS_GB)
793     {
794       /* if it is in direct space */
795       if (IN_REGSP (space) && !requires_a)
796         {
797           sym->aop = aop = newAsmop (AOP_SFR);
798           aop->aopu.aop_dir = sym->rname;
799           aop->size = getSize (sym->type);
800           emitDebug ("; AOP_SFR for %s", sym->rname);
801           return aop;
802         }
803     }
804
805   /* only remaining is far space */
806   /* in which case DPTR gets the address */
807   if (IS_GB)
808     {
809       emitDebug ("; AOP_HL for %s", sym->rname);
810       sym->aop = aop = newAsmop (AOP_HL);
811     }
812   else
813     {
814       sym->aop = aop = newAsmop (AOP_IY);
815     }
816   aop->size = getSize (sym->type);
817   aop->aopu.aop_dir = sym->rname;
818
819   /* if it is in code space */
820   if (IN_CODESPACE (space))
821     aop->code = 1;
822
823   return aop;
824 }
825
826 /*-----------------------------------------------------------------*/
827 /* aopForRemat - rematerialzes an object                           */
828 /*-----------------------------------------------------------------*/
829 static asmop *
830 aopForRemat (symbol * sym)
831 {
832   char *s = buffer;
833   iCode *ic = sym->rematiCode;
834   asmop *aop = newAsmop (AOP_IMMD);
835
836   while (1)
837     {
838       /* if plus or minus print the right hand side */
839       if (ic->op == '+' || ic->op == '-')
840         {
841           /* PENDING: for re-target */
842           sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
843                    ic->op);
844           s += strlen (s);
845           ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
846           continue;
847         }
848       /* we reached the end */
849       sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
850       break;
851     }
852
853   aop->aopu.aop_immd = traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
854   return aop;
855 }
856
857 /*-----------------------------------------------------------------*/
858 /* regsInCommon - two operands have some registers in common       */
859 /*-----------------------------------------------------------------*/
860 bool
861 regsInCommon (operand * op1, operand * op2)
862 {
863   symbol *sym1, *sym2;
864   int i;
865
866   /* if they have registers in common */
867   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
868     return FALSE;
869
870   sym1 = OP_SYMBOL (op1);
871   sym2 = OP_SYMBOL (op2);
872
873   if (sym1->nRegs == 0 || sym2->nRegs == 0)
874     return FALSE;
875
876   for (i = 0; i < sym1->nRegs; i++)
877     {
878       int j;
879       if (!sym1->regs[i])
880         continue;
881
882       for (j = 0; j < sym2->nRegs; j++)
883         {
884           if (!sym2->regs[j])
885             continue;
886
887           if (sym2->regs[j] == sym1->regs[i])
888             return TRUE;
889         }
890     }
891
892   return FALSE;
893 }
894
895 /*-----------------------------------------------------------------*/
896 /* operandsEqu - equivalent                                        */
897 /*-----------------------------------------------------------------*/
898 bool
899 operandsEqu (operand * op1, operand * op2)
900 {
901   symbol *sym1, *sym2;
902
903   /* if they not symbols */
904   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
905     return FALSE;
906
907   sym1 = OP_SYMBOL (op1);
908   sym2 = OP_SYMBOL (op2);
909
910   /* if both are itemps & one is spilt
911      and the other is not then false */
912   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
913       sym1->isspilt != sym2->isspilt)
914     return FALSE;
915
916   /* if they are the same */
917   if (sym1 == sym2)
918     return 1;
919
920   if (strcmp (sym1->rname, sym2->rname) == 0)
921     return 2;
922
923
924   /* if left is a tmp & right is not */
925   if (IS_ITEMP (op1) &&
926       !IS_ITEMP (op2) &&
927       sym1->isspilt &&
928       (sym1->usl.spillLoc == sym2))
929     return 3;
930
931   if (IS_ITEMP (op2) &&
932       !IS_ITEMP (op1) &&
933       sym2->isspilt &&
934       sym1->level > 0 &&
935       (sym2->usl.spillLoc == sym1))
936     return 4;
937
938   return FALSE;
939 }
940
941 /*-----------------------------------------------------------------*/
942 /* sameRegs - two asmops have the same registers                   */
943 /*-----------------------------------------------------------------*/
944 bool
945 sameRegs (asmop * aop1, asmop * aop2)
946 {
947   int i;
948
949   if (aop1->type == AOP_SFR ||
950       aop2->type == AOP_SFR)
951     return FALSE;
952
953   if (aop1 == aop2)
954     return TRUE;
955
956   if (aop1->type != AOP_REG ||
957       aop2->type != AOP_REG)
958     return FALSE;
959
960   if (aop1->size != aop2->size)
961     return FALSE;
962
963   for (i = 0; i < aop1->size; i++)
964     if (aop1->aopu.aop_reg[i] !=
965         aop2->aopu.aop_reg[i])
966       return FALSE;
967
968   return TRUE;
969 }
970
971 /*-----------------------------------------------------------------*/
972 /* aopOp - allocates an asmop for an operand  :                    */
973 /*-----------------------------------------------------------------*/
974 static void
975 aopOp (operand * op, iCode * ic, bool result, bool requires_a)
976 {
977   asmop *aop;
978   symbol *sym;
979   int i;
980
981   if (!op)
982     return;
983
984   /* if this a literal */
985   if (IS_OP_LITERAL (op))
986     {
987       op->aop = aop = newAsmop (AOP_LIT);
988       aop->aopu.aop_lit = op->operand.valOperand;
989       aop->size = getSize (operandType (op));
990       return;
991     }
992
993   /* if already has a asmop then continue */
994   if (op->aop)
995     {
996       return;
997     }
998
999   /* if the underlying symbol has a aop */
1000   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1001     {
1002       op->aop = OP_SYMBOL (op)->aop;
1003       return;
1004     }
1005
1006   /* if this is a true symbol */
1007   if (IS_TRUE_SYMOP (op))
1008     {
1009       op->aop = aopForSym (ic, OP_SYMBOL (op), result, requires_a);
1010       return;
1011     }
1012
1013   /* this is a temporary : this has
1014      only four choices :
1015      a) register
1016      b) spillocation
1017      c) rematerialize
1018      d) conditional
1019      e) can be a return use only */
1020
1021   sym = OP_SYMBOL (op);
1022
1023   /* if the type is a conditional */
1024   if (sym->regType == REG_CND)
1025     {
1026       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1027       aop->size = 0;
1028       return;
1029     }
1030
1031   /* if it is spilt then two situations
1032      a) is rematerialize
1033      b) has a spill location */
1034   if (sym->isspilt || sym->nRegs == 0)
1035     {
1036       /* rematerialize it NOW */
1037       if (sym->remat)
1038         {
1039           sym->aop = op->aop = aop =
1040             aopForRemat (sym);
1041           aop->size = getSize (sym->type);
1042           return;
1043         }
1044
1045       if (sym->ruonly)
1046         {
1047           int i;
1048           aop = op->aop = sym->aop = newAsmop (AOP_STR);
1049           aop->size = getSize (sym->type);
1050           for (i = 0; i < 4; i++)
1051             aop->aopu.aop_str[i] = _fReturn[i];
1052           return;
1053         }
1054
1055       if (sym->accuse)
1056         {
1057           if (sym->accuse == ACCUSE_A)
1058             {
1059               aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1060               aop->size = getSize (sym->type);
1061               wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
1062
1063               aop->aopu.aop_str[0] = _pairs[PAIR_AF].h;
1064             }
1065           else if (sym->accuse == ACCUSE_SCRATCH)
1066             {
1067               aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
1068               aop->size = getSize (sym->type);
1069               wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL");
1070               aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
1071               aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
1072             }
1073           else if (sym->accuse == ACCUSE_IY)
1074             {
1075               aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
1076               aop->size = getSize (sym->type);
1077               wassertl(aop->size <= 2, "Internal error: Caching in IY, but too big to fit in IY");
1078               aop->aopu.aop_str[0] = _pairs[PAIR_IY].l;
1079               aop->aopu.aop_str[1] = _pairs[PAIR_IY].h;
1080             }
1081           else 
1082               {
1083                   wassertl (0, "Marked as being allocated into A or HL but is actually in neither");
1084               }
1085           return;
1086         }
1087
1088       if (sym->usl.spillLoc)
1089         {
1090           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1091             {
1092               /* force a new aop if sizes differ */
1093               sym->usl.spillLoc->aop = NULL;
1094             }
1095           sym->aop = op->aop = aop =
1096                      aopForSym (ic, sym->usl.spillLoc, result, requires_a);
1097           aop->size = getSize (sym->type);
1098           return;
1099         }
1100       
1101       /* else must be a dummy iTemp */
1102       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1103       aop->size = getSize (sym->type);
1104       return;
1105     }
1106
1107   /* must be in a register */
1108   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1109   aop->size = sym->nRegs;
1110   for (i = 0; i < sym->nRegs; i++)
1111     aop->aopu.aop_reg[i] = sym->regs[i];
1112 }
1113
1114 /*-----------------------------------------------------------------*/
1115 /* freeAsmop - free up the asmop given to an operand               */
1116 /*----------------------------------------------------------------*/
1117 static void
1118 freeAsmop (operand * op, asmop * aaop, iCode * ic)
1119 {
1120   asmop *aop;
1121
1122   if (!op)
1123     aop = aaop;
1124   else
1125     aop = op->aop;
1126
1127   if (!aop)
1128     return;
1129
1130   if (aop->freed)
1131     goto dealloc;
1132
1133   aop->freed = 1;
1134
1135   if (aop->type == AOP_PAIRPTR && IS_Z80 && aop->aopu.aop_pairId == PAIR_DE)
1136     {
1137       _pop (aop->aopu.aop_pairId);
1138     }
1139
1140   if (getPairId (aop) == PAIR_HL)
1141     {
1142       spillPair (PAIR_HL);
1143     }
1144
1145 dealloc:
1146   /* all other cases just dealloc */
1147   if (op)
1148     {
1149       op->aop = NULL;
1150       if (IS_SYMOP (op))
1151         {
1152           OP_SYMBOL (op)->aop = NULL;
1153           /* if the symbol has a spill */
1154           if (SPIL_LOC (op))
1155             SPIL_LOC (op)->aop = NULL;
1156         }
1157     }
1158
1159 }
1160
1161 bool
1162 isLitWord (asmop * aop)
1163 {
1164   /*    if (aop->size != 2)
1165      return FALSE; */
1166   switch (aop->type)
1167     {
1168     case AOP_IMMD:
1169     case AOP_LIT:
1170       return TRUE;
1171     default:
1172       return FALSE;
1173     }
1174 }
1175
1176 char *
1177 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
1178 {
1179   /* depending on type */
1180   switch (aop->type)
1181     {
1182     case AOP_HL:
1183     case AOP_IY:
1184     case AOP_IMMD:
1185       /* PENDING: for re-target */
1186       if (with_hash)
1187         {
1188           tsprintf (buffer, sizeof(buffer), 
1189                     "!hashedstr + %d", aop->aopu.aop_immd, offset);
1190         }
1191       else if (offset == 0)
1192         {
1193           tsprintf (buffer, sizeof(buffer),
1194                     "%s", aop->aopu.aop_immd);
1195         }
1196       else
1197         {
1198           tsprintf (buffer, sizeof(buffer), 
1199                     "%s + %d", aop->aopu.aop_immd, offset);
1200         }
1201       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1202
1203     case AOP_LIT:
1204       {
1205         value *val = aop->aopu.aop_lit;
1206         /* if it is a float then it gets tricky */
1207         /* otherwise it is fairly simple */
1208         if (!IS_FLOAT (val->type))
1209           {
1210             unsigned long v = (unsigned long) floatFromVal (val);
1211
1212             if (offset == 2)
1213               {
1214                 v >>= 16;
1215               }
1216             else if (offset == 0)
1217               {
1218                 // OK
1219               }
1220             else 
1221               {
1222                 wassertl(0, "Encountered an invalid offset while fetching a literal");
1223               }
1224
1225             if (with_hash)
1226               tsprintf (buffer, sizeof(buffer), "!immedword", v);
1227             else
1228               tsprintf (buffer, sizeof(buffer), "!constword", v);
1229
1230             return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1231           }
1232         else
1233           {
1234             union {
1235               float f;
1236               unsigned char c[4];
1237             }
1238             fl;
1239             unsigned int i;
1240
1241             /* it is type float */
1242             fl.f = (float) floatFromVal (val);
1243
1244 #ifdef WORDS_BIGENDIAN
1245             i = fl.c[3-offset] | (fl.c[3-offset-1]<<8);
1246 #else
1247             i = fl.c[offset] | (fl.c[offset+1]<<8);
1248 #endif
1249             if (with_hash)
1250               tsprintf (buffer, sizeof(buffer), "!immedword", i);
1251             else
1252               tsprintf (buffer, sizeof(buffer), "!constword", i);
1253
1254             return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1255           }
1256       }
1257     default:
1258       return NULL;
1259     }
1260 }
1261
1262 char *
1263 aopGetWord (asmop * aop, int offset)
1264 {
1265   return aopGetLitWordLong (aop, offset, TRUE);
1266 }
1267
1268 bool
1269 isPtr (const char *s)
1270 {
1271   if (!strcmp (s, "hl"))
1272     return TRUE;
1273   if (!strcmp (s, "ix"))
1274     return TRUE;
1275   if (!strcmp (s, "iy"))
1276     return TRUE;
1277   return FALSE;
1278 }
1279
1280 static void
1281 adjustPair (const char *pair, int *pold, int new)
1282 {
1283   wassert (pair);
1284
1285   while (*pold < new)
1286     {
1287       emit2 ("inc %s", pair);
1288       (*pold)++;
1289     }
1290   while (*pold > new)
1291     {
1292       emit2 ("dec %s", pair);
1293       (*pold)--;
1294     }
1295 }
1296
1297 static void
1298 spillCached (void)
1299 {
1300   spillPair (PAIR_HL);
1301   spillPair (PAIR_IY);
1302 }
1303
1304 static bool
1305 requiresHL (asmop * aop)
1306 {
1307   switch (aop->type)
1308     {
1309     case AOP_IY:
1310     case AOP_HL:
1311     case AOP_STK:
1312     case AOP_EXSTK:
1313     case AOP_HLREG:
1314       return TRUE;
1315     default:
1316       return FALSE;
1317     }
1318 }
1319
1320 static void
1321 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
1322 {
1323   const char *l, *base;
1324   const char *pair = _pairs[pairId].name;
1325   l = aopGetLitWordLong (left, offset, FALSE);
1326   base = aopGetLitWordLong (left, 0, FALSE);
1327   wassert (l && pair && base);
1328
1329   if (isPtr (pair))
1330     {
1331       if (pairId == PAIR_HL || pairId == PAIR_IY)
1332         {
1333           if (_G.pairs[pairId].last_type == left->type)
1334             {
1335               if (_G.pairs[pairId].base && !strcmp (_G.pairs[pairId].base, base))
1336                 {
1337                   if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
1338                     {
1339                       adjustPair (pair, &_G.pairs[pairId].offset, offset);
1340                       return;
1341                     }
1342                   if (pairId == PAIR_IY && (offset >= INT8MIN && offset <= INT8MAX))
1343                     {
1344                       return;
1345                     }
1346                 }
1347             }
1348         }
1349       _G.pairs[pairId].last_type = left->type;
1350       _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base));
1351       _G.pairs[pairId].offset = offset;
1352     }
1353   /* Both a lit on the right and a true symbol on the left */
1354   emit2 ("ld %s,!hashedstr", pair, l);
1355 }
1356
1357 static PAIR_ID
1358 makeFreePairId (iCode *ic, bool *pisUsed)
1359 {
1360   *pisUsed = FALSE;
1361
1362   if (ic != NULL)
1363     {
1364       if (!bitVectBitValue (ic->rMask, B_IDX) && !bitVectBitValue(ic->rMask, C_IDX))
1365         {
1366           return PAIR_BC;
1367         }
1368       else if (IS_Z80 && !bitVectBitValue (ic->rMask, D_IDX) && !bitVectBitValue(ic->rMask, E_IDX))
1369         {
1370           return PAIR_DE;
1371         }
1372       else
1373         {
1374           *pisUsed = TRUE;
1375           return PAIR_HL;
1376         }
1377     }
1378   else
1379     {
1380       *pisUsed = TRUE;
1381       return PAIR_HL;
1382     }
1383 }
1384
1385 static void
1386 fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset)
1387 {
1388     /* if this is remateriazable */
1389     if (isLitWord (aop)) {
1390         fetchLitPair (pairId, aop, offset);
1391     }
1392     else 
1393       {
1394         if (getPairId (aop) == pairId)
1395           {
1396             /* Do nothing */
1397           }
1398         /* we need to get it byte by byte */
1399         else if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
1400             aopGet (aop, offset, FALSE);
1401             switch (aop->size - offset) {
1402             case 1:
1403                 emit2 ("ld l,!*hl");
1404                 emit2 ("ld h,!immedbyte", 0);
1405                             break;
1406             case 2:
1407               // PENDING: Requires that you are only fetching two bytes.
1408             case 4:
1409                 emit2 ("!ldahli");
1410                 emit2 ("ld h,!*hl");
1411                 emit2 ("ld l,a");
1412                 break;
1413             default:
1414               wassertl (0, "Attempted to fetch too much data into HL");
1415               break;
1416             }
1417         }
1418         else if (IS_Z80 && aop->type == AOP_IY) {
1419             /* Instead of fetching relative to IY, just grab directly
1420                from the address IY refers to */
1421             char *l = aopGetLitWordLong (aop, offset, FALSE);
1422             wassert (l);
1423             emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
1424
1425             if (aop->size < 2) {
1426                 emit2("ld %s,!zero", _pairs[pairId].h);
1427             }
1428         }
1429         else if (pairId == PAIR_IY)
1430           {
1431             if (isPair (aop))
1432               {
1433                 emit2 ("push %s", _pairs[getPairId(aop)].name);
1434                 emit2 ("pop iy");
1435               }
1436             else
1437               {
1438                 bool isUsed;
1439                 PAIR_ID id = makeFreePairId (ic, &isUsed);
1440                 if (isUsed)
1441                   _push (id);
1442                 /* Can't load into parts, so load into HL then exchange. */
1443                 emit2 ("ld %s,%s", _pairs[id].l, aopGet (aop, offset, FALSE));
1444                 emit2 ("ld %s,%s", _pairs[id].h, aopGet (aop, offset + 1, FALSE));
1445                 emit2 ("push %s", _pairs[id].name);
1446                 emit2 ("pop iy");
1447                 if (isUsed)
1448                   _pop (id);
1449               }
1450           }
1451         else if (isUnsplitable(aop))
1452           {
1453             emit2("push %s", _pairs[getPairId(aop)].name);
1454             emit2("pop %s", _pairs[pairId].name);
1455           }
1456         else 
1457           {
1458             emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
1459             emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
1460           }
1461         /* PENDING: check? */
1462         if (pairId == PAIR_HL)
1463             spillPair (PAIR_HL);
1464     }
1465 }
1466
1467 static void
1468 fetchPair (PAIR_ID pairId, asmop * aop)
1469 {
1470   fetchPairLong (pairId, aop, NULL, 0);
1471 }
1472
1473 static void
1474 fetchHL (asmop * aop)
1475 {
1476   fetchPair (PAIR_HL, aop);
1477 }
1478
1479 static void
1480 setupPairFromSP (PAIR_ID id, int offset)
1481 {
1482   wassertl (id == PAIR_HL, "Setup relative to SP only implemented for HL");
1483
1484   if (offset < INT8MIN || offset > INT8MAX)
1485     {
1486       emit2 ("ld hl,!immedword", offset);
1487       emit2 ("add hl,sp");
1488     }
1489   else
1490     {
1491       emit2 ("!ldahlsp", offset);
1492     }
1493 }
1494
1495 static void
1496 setupPair (PAIR_ID pairId, asmop * aop, int offset)
1497 {
1498   switch (aop->type)
1499     {
1500     case AOP_IY:
1501       wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "AOP_IY must be in IY or HL");
1502       fetchLitPair (pairId, aop, 0);
1503       break;
1504
1505     case AOP_HL:
1506       wassertl (pairId == PAIR_HL, "AOP_HL must be in HL");
1507       
1508       fetchLitPair (pairId, aop, offset);
1509       _G.pairs[pairId].offset = offset;
1510       break;
1511
1512     case AOP_EXSTK:
1513       wassertl (IS_Z80, "Only the Z80 has an extended stack");
1514       wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "The Z80 extended stack must be in IY or HL");
1515
1516       {
1517         int offset = aop->aopu.aop_stk + _G.stack.offset;
1518
1519         if (_G.pairs[pairId].last_type == aop->type &&
1520             _G.pairs[pairId].offset == offset)
1521           {
1522             /* Already setup */
1523           }
1524         else
1525           {
1526             /* PENDING: Do this better. */
1527             sprintf (buffer, "%d", offset + _G.stack.pushed);
1528             emit2 ("ld %s,!hashedstr", _pairs[pairId].name, buffer);
1529             emit2 ("add %s,sp", _pairs[pairId].name);
1530             _G.pairs[pairId].last_type = aop->type;
1531             _G.pairs[pairId].offset = offset;
1532           }
1533       }
1534       break;
1535
1536     case AOP_STK:
1537       {
1538         /* Doesnt include _G.stack.pushed */
1539         int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
1540
1541         if (aop->aopu.aop_stk > 0)
1542           {
1543             abso += _G.stack.param_offset;
1544           }
1545         assert (pairId == PAIR_HL);
1546         /* In some cases we can still inc or dec hl */
1547         if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
1548           {
1549             adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
1550           }
1551         else
1552           {
1553             setupPairFromSP (PAIR_HL, abso + _G.stack.pushed);
1554           }
1555         _G.pairs[pairId].offset = abso;
1556         break;
1557       }
1558
1559     case AOP_PAIRPTR:
1560       if (pairId != aop->aopu.aop_pairId)
1561         genMovePairPair(aop->aopu.aop_pairId, pairId);
1562       adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, offset);
1563       break;
1564       
1565     default:
1566       wassert (0);
1567     }
1568   _G.pairs[pairId].last_type = aop->type;
1569 }
1570
1571 static void
1572 emitLabel (int key)
1573 {
1574   emit2 ("!tlabeldef", key);
1575   spillCached ();
1576 }
1577
1578 /*-----------------------------------------------------------------*/
1579 /* aopGet - for fetching value of the aop                          */
1580 /*-----------------------------------------------------------------*/
1581 static const char *
1582 aopGet (asmop * aop, int offset, bool bit16)
1583 {
1584   // char *s = buffer;
1585
1586   /* offset is greater than size then zero */
1587   /* PENDING: this seems a bit screwed in some pointer cases. */
1588   if (offset > (aop->size - 1) &&
1589       aop->type != AOP_LIT) 
1590     {
1591       tsprintf (buffer, sizeof(buffer), "!zero");
1592       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1593     }
1594
1595   /* depending on type */
1596   switch (aop->type)
1597     {
1598     case AOP_DUMMY:
1599       tsprintf (buffer, sizeof(buffer), "!zero");
1600       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1601     
1602     case AOP_IMMD:
1603       /* PENDING: re-target */
1604       if (bit16)
1605         tsprintf (buffer, sizeof(buffer), "!immedwords", aop->aopu.aop_immd);
1606       else
1607         switch (offset)
1608           {
1609           case 2:
1610             tsprintf (buffer, sizeof(buffer), "!bankimmeds", aop->aopu.aop_immd);
1611             break;
1612           case 1:
1613             tsprintf (buffer, sizeof(buffer), "!msbimmeds", aop->aopu.aop_immd);
1614             break;
1615           case 0:
1616             tsprintf (buffer, sizeof(buffer), "!lsbimmeds", aop->aopu.aop_immd);
1617             break;
1618           default:
1619             wassertl (0, "Fetching from beyond the limits of an immediate value.");
1620           }
1621
1622       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1623
1624     case AOP_DIR:
1625       wassert (IS_GB);
1626       emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset);
1627       SNPRINTF (buffer, sizeof(buffer), "a");
1628
1629       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1630
1631     case AOP_SFR:
1632       wassert (IS_GB);
1633       emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
1634       SNPRINTF (buffer, sizeof(buffer), "a");
1635
1636       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1637
1638     case AOP_REG:
1639       return aop->aopu.aop_reg[offset]->name;
1640
1641     case AOP_HL:
1642       wassert (IS_GB);
1643       setupPair (PAIR_HL, aop, offset);
1644       tsprintf (buffer, sizeof(buffer), "!*hl");
1645
1646       return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
1647
1648     case AOP_IY:
1649       wassert (IS_Z80);
1650       setupPair (PAIR_IY, aop, offset);
1651       tsprintf (buffer, sizeof(buffer), "!*iyx", offset);
1652
1653       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1654
1655     case AOP_EXSTK:
1656       wassert (IS_Z80);
1657       setupPair (PAIR_IY, aop, offset);
1658       tsprintf (buffer, sizeof(buffer), "!*iyx", offset, offset);
1659
1660       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1661
1662     case AOP_STK:
1663       if (IS_GB)
1664         {
1665           setupPair (PAIR_HL, aop, offset);
1666           tsprintf (buffer, sizeof(buffer), "!*hl");
1667         }
1668       else
1669         {
1670           if (aop->aopu.aop_stk >= 0)
1671             offset += _G.stack.param_offset;
1672           tsprintf (buffer, sizeof(buffer),
1673                     "!*ixx", aop->aopu.aop_stk + offset);
1674         }
1675
1676       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1677
1678     case AOP_CRY:
1679       wassertl (0, "Tried to fetch from a bit variable");
1680
1681     case AOP_ACC:
1682       if (!offset)
1683         {
1684           return "a";
1685         }
1686       else
1687         {
1688           tsprintf(buffer, sizeof(buffer), "!zero");
1689           return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1690         }
1691
1692     case AOP_HLREG:
1693       wassert (offset < 2);
1694       return aop->aopu.aop_str[offset];
1695
1696     case AOP_LIT:
1697       return aopLiteral (aop->aopu.aop_lit, offset);
1698
1699     case AOP_SIMPLELIT:
1700       {
1701         unsigned long v = aop->aopu.aop_simplelit;
1702         
1703         v >>= (offset * 8);
1704         tsprintf (buffer, sizeof(buffer), 
1705                   "!immedbyte", (unsigned int) v & 0xff);
1706         
1707         return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1708       }
1709     case AOP_STR:
1710       aop->coff = offset;
1711       return aop->aopu.aop_str[offset];
1712
1713     case AOP_PAIRPTR:
1714       setupPair (aop->aopu.aop_pairId, aop, offset);
1715       if (aop->aopu.aop_pairId==PAIR_IX)
1716         SNPRINTF (buffer, sizeof(buffer), 
1717                   "!*ixx", 0);
1718       else if (aop->aopu.aop_pairId==PAIR_IY)
1719         SNPRINTF (buffer, sizeof(buffer), 
1720                   "!*iyx", 0);
1721       else
1722         SNPRINTF (buffer, sizeof(buffer), 
1723                   "(%s)", _pairs[aop->aopu.aop_pairId].name);
1724
1725       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
1726
1727     default:
1728       break;
1729     }
1730   wassertl (0, "aopget got unsupported aop->type");
1731   exit (0);
1732 }
1733
1734 bool
1735 isRegString (const char *s)
1736 {
1737   if (!strcmp (s, "b") ||
1738       !strcmp (s, "c") ||
1739       !strcmp (s, "d") ||
1740       !strcmp (s, "e") ||
1741       !strcmp (s, "a") ||
1742       !strcmp (s, "h") ||
1743       !strcmp (s, "l"))
1744     return TRUE;
1745   return FALSE;
1746 }
1747
1748 bool
1749 isConstant (const char *s)
1750 {
1751   /* This is a bit of a hack... */
1752   return (*s == '#' || *s == '$');
1753 }
1754
1755 bool
1756 canAssignToPtr (const char *s)
1757 {
1758   if (isRegString (s))
1759     return TRUE;
1760   if (isConstant (s))
1761     return TRUE;
1762   return FALSE;
1763 }
1764
1765 /*-----------------------------------------------------------------*/
1766 /* aopPut - puts a string for a aop                                */
1767 /*-----------------------------------------------------------------*/
1768 static void
1769 aopPut (asmop * aop, const char *s, int offset)
1770 {
1771   char buffer2[256];
1772
1773   if (aop->size && offset > (aop->size - 1))
1774     {
1775       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1776               "aopPut got offset > aop->size");
1777       exit (0);
1778     }
1779
1780   // PENDING
1781   tsprintf(buffer2, sizeof(buffer2), s);
1782   s = buffer2;
1783
1784   /* will assign value to value */
1785   /* depending on where it is ofcourse */
1786   switch (aop->type)
1787     {
1788     case AOP_DUMMY:
1789       _moveA (s);  /* in case s is volatile */
1790       break;
1791       
1792     case AOP_DIR:
1793       /* Direct.  Hmmm. */
1794       wassert (IS_GB);
1795       if (strcmp (s, "a"))
1796         emit2 ("ld a,%s", s);
1797       emit2 ("ld (%s+%d),a", aop->aopu.aop_dir, offset);
1798       break;
1799
1800     case AOP_SFR:
1801       wassert (IS_GB);
1802       if (strcmp (s, "a"))
1803         emit2 ("ld a,%s", s);
1804       emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
1805       break;
1806
1807     case AOP_REG:
1808       if (!strcmp (s, "!*hl"))
1809         emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1810       else
1811         emit2 ("ld %s,%s",
1812                aop->aopu.aop_reg[offset]->name, s);
1813       spillPairReg(aop->aopu.aop_reg[offset]->name);
1814       break;
1815
1816     case AOP_IY:
1817       wassert (!IS_GB);
1818       if (!canAssignToPtr (s))
1819         {
1820           emit2 ("ld a,%s", s);
1821           setupPair (PAIR_IY, aop, offset);
1822           emit2 ("ld !*iyx,a", offset);
1823         }
1824       else
1825         {
1826           setupPair (PAIR_IY, aop, offset);
1827           emit2 ("ld !*iyx,%s", offset, s);
1828         }
1829       break;
1830
1831     case AOP_HL:
1832       wassert (IS_GB);
1833       /* PENDING: for re-target */
1834       if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1835         {
1836           emit2 ("ld a,!*hl");
1837           s = "a";
1838         }
1839       setupPair (PAIR_HL, aop, offset);
1840
1841       emit2 ("ld !*hl,%s", s);
1842       break;
1843
1844     case AOP_EXSTK:
1845       wassert (!IS_GB);
1846       if (!canAssignToPtr (s))
1847         {
1848           emit2 ("ld a,%s", s);
1849           setupPair (PAIR_IY, aop, offset);
1850           emit2 ("ld !*iyx,a", offset);
1851         }
1852       else
1853         {
1854           setupPair (PAIR_IY, aop, offset);
1855           emit2 ("ld !*iyx,%s", offset, s);
1856         }
1857       break;
1858
1859     case AOP_STK:
1860       if (IS_GB)
1861         {
1862           /* PENDING: re-target */
1863           if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1864             {
1865               emit2 ("ld a,!*hl");
1866               s = "a";
1867             }
1868           setupPair (PAIR_HL, aop, offset);
1869           if (!canAssignToPtr (s))
1870             {
1871               emit2 ("ld a,%s", s);
1872               emit2 ("ld !*hl,a");
1873             }
1874           else
1875             emit2 ("ld !*hl,%s", s);
1876         }
1877       else
1878         {
1879           if (aop->aopu.aop_stk >= 0)
1880             offset += _G.stack.param_offset;
1881           if (!canAssignToPtr (s))
1882             {
1883               emit2 ("ld a,%s", s);
1884               emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
1885             }
1886           else
1887             {
1888               emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
1889             }
1890         }
1891       break;
1892
1893     case AOP_CRY:
1894       /* if bit variable */
1895       if (!aop->aopu.aop_dir)
1896         {
1897           emit2 ("ld a,!zero");
1898           emit2 ("rla");
1899         }
1900       else
1901         {
1902           /* In bit space but not in C - cant happen */
1903           wassertl (0, "Tried to write into a bit variable");
1904         }
1905       break;
1906
1907     case AOP_STR:
1908       aop->coff = offset;
1909       if (strcmp (aop->aopu.aop_str[offset], s))
1910         {
1911           emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1912         }
1913       spillPairReg(aop->aopu.aop_str[offset]);
1914       break;
1915
1916     case AOP_ACC:
1917       aop->coff = offset;
1918       if (!offset && (strcmp (s, "acc") == 0))
1919         break;
1920       if (offset > 0)
1921         {
1922           wassertl (0, "Tried to access past the end of A");
1923         }
1924       else
1925         {
1926           if (strcmp (aop->aopu.aop_str[offset], s))
1927             {
1928               emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1929               spillPairReg(aop->aopu.aop_str[offset]);
1930             }
1931         }
1932       break;
1933
1934     case AOP_HLREG:
1935       wassert (offset < 2);
1936       emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1937       spillPairReg(aop->aopu.aop_str[offset]);
1938       break;
1939
1940     case AOP_PAIRPTR:
1941       setupPair (aop->aopu.aop_pairId, aop, offset);
1942       if (aop->aopu.aop_pairId==PAIR_IX)
1943         emit2 ("ld !*ixx,%s", 0, s);
1944       else if (aop->aopu.aop_pairId==PAIR_IY)
1945         emit2 ("ld !*ixy,%s", 0, s);
1946       else
1947         emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
1948       break;
1949
1950     default:
1951       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1952               "aopPut got unsupported aop->type");
1953       exit (0);
1954     }
1955 }
1956
1957 #define AOP(op) op->aop
1958 #define AOP_TYPE(op) AOP(op)->type
1959 #define AOP_SIZE(op) AOP(op)->size
1960 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1961
1962 static void
1963 commitPair (asmop * aop, PAIR_ID id)
1964 {
1965   /* PENDING: Verify this. */
1966   if (id == PAIR_HL && requiresHL (aop) && IS_GB)
1967     {
1968       emit2 ("ld a,l");
1969       emit2 ("ld d,h");
1970       aopPut (aop, "a", 0);
1971       aopPut (aop, "d", 1);
1972     }
1973   else
1974     {
1975       /* Special cases */
1976       if (id == PAIR_HL && aop->type == AOP_IY && aop->size == 2)
1977         {
1978           char *l = aopGetLitWordLong (aop, 0, FALSE);
1979           wassert (l);
1980
1981           emit2 ("ld (%s),%s", l, _pairs[id].name);
1982         }
1983       else
1984         {
1985           aopPut (aop, _pairs[id].l, 0);
1986           aopPut (aop, _pairs[id].h, 1);
1987         }
1988     }
1989 }
1990
1991 /*-----------------------------------------------------------------*/
1992 /* getDataSize - get the operand data size                         */
1993 /*-----------------------------------------------------------------*/
1994 int
1995 getDataSize (operand * op)
1996 {
1997   int size;
1998   size = AOP_SIZE (op);
1999   if (size == 3)
2000     {
2001       /* pointer */
2002       wassertl (0, "Somehow got a three byte data pointer");
2003     }
2004   return size;
2005 }
2006
2007 /*-----------------------------------------------------------------*/
2008 /* movLeft2Result - move byte from left to result                  */
2009 /*-----------------------------------------------------------------*/
2010 static void
2011 movLeft2Result (operand * left, int offl,
2012                 operand * result, int offr, int sign)
2013 {
2014   const char *l;
2015
2016   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
2017     {
2018       l = aopGet (AOP (left), offl, FALSE);
2019
2020       if (!sign)
2021         {
2022           aopPut (AOP (result), l, offr);
2023         }
2024       else
2025         {
2026           if (getDataSize (left) == offl + 1)
2027             {
2028               emit2 ("ld a,%s", l);
2029               aopPut (AOP (result), "a", offr);
2030             }
2031         }
2032     }
2033 }
2034
2035 static void
2036 movLeft2ResultLong (operand * left, int offl,
2037                 operand * result, int offr, int sign,
2038                 int size)
2039 {
2040   if (size == 1)
2041     {
2042       movLeft2Result (left, offl, result, offr, sign);
2043     }
2044   else
2045     {
2046       wassertl (offl == 0 && offr == 0, "Only implemented for zero offset");
2047       wassertl (size == 2, "Only implemented for two bytes or one");
2048
2049       if ( IS_GB && requiresHL ( AOP (left)) && getPairId ( AOP (result)) == PAIR_HL)
2050         {
2051           emit2 ("ld a,%s", aopGet (AOP (left), LSB, FALSE));
2052           emit2 ("ld h,%s", aopGet (AOP (left), MSB16, FALSE));
2053           emit2 ("ld l,a");
2054           spillPair (PAIR_HL);
2055         }
2056       else if ( getPairId ( AOP (result)) == PAIR_IY)
2057         {
2058           PAIR_ID id = getPairId (AOP (left));
2059           if (id != PAIR_INVALID) 
2060             {
2061               emit2("push %s", _pairs[id].name);
2062               emit2("pop iy");
2063             }
2064           else
2065             {
2066               /* PENDING */
2067               emitDebug("Error");
2068             }
2069         }
2070       else
2071         {
2072           movLeft2Result (left, offl, result, offr, sign);
2073           movLeft2Result (left, offl+1, result, offr+1, sign);
2074         }
2075     }
2076 }
2077
2078 /** Put Acc into a register set
2079  */
2080 void
2081 outAcc (operand * result)
2082 {
2083   int size, offset;
2084   size = getDataSize (result);
2085   if (size)
2086     {
2087       aopPut (AOP (result), "a", 0);
2088       size--;
2089       offset = 1;
2090       /* unsigned or positive */
2091       while (size--)
2092         {
2093           aopPut (AOP (result), "!zero", offset++);
2094         }
2095     }
2096 }
2097
2098 /** Take the value in carry and put it into a register
2099  */
2100 void
2101 outBitCLong (operand * result, bool swap_sense)
2102 {
2103   /* if the result is bit */
2104   if (AOP_TYPE (result) == AOP_CRY)
2105     {
2106       wassertl (0, "Tried to write carry to a bit");
2107     }
2108   else
2109     {
2110       emit2 ("ld a,!zero");
2111       emit2 ("rla");
2112       if (swap_sense)
2113         emit2 ("xor a,!immedbyte", 1);
2114       outAcc (result);
2115     }
2116 }
2117
2118 void
2119 outBitC (operand * result)
2120 {
2121   outBitCLong (result, FALSE);
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* toBoolean - emit code for orl a,operator(sizeop)                */
2126 /*-----------------------------------------------------------------*/
2127 void
2128 _toBoolean (operand * oper)
2129 {
2130   int size = AOP_SIZE (oper);
2131   int offset = 0;
2132   if (size > 1)
2133     {
2134       emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE));
2135       size--;
2136       while (size--)
2137         emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
2138     }
2139   else
2140     {
2141       if (AOP (oper)->type != AOP_ACC)
2142         {
2143           _clearCarry();
2144           emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
2145         }
2146     }
2147 }
2148
2149
2150 /*-----------------------------------------------------------------*/
2151 /* genNot - generate code for ! operation                          */
2152 /*-----------------------------------------------------------------*/
2153 static void
2154 genNot (iCode * ic)
2155 {
2156
2157   /* assign asmOps to operand & result */
2158   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2159   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2160
2161   /* if in bit space then a special case */
2162   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2163     {
2164       wassertl (0, "Tried to negate a bit");
2165     }
2166
2167   _toBoolean (IC_LEFT (ic));
2168
2169   /* Not of A:
2170      If A == 0, !A = 1
2171      else A = 0
2172      So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
2173   emit2 ("sub a,!one");
2174   outBitC (IC_RESULT (ic));
2175
2176   /* release the aops */
2177   freeAsmop (IC_LEFT (ic), NULL, ic);
2178   freeAsmop (IC_RESULT (ic), NULL, ic);
2179 }
2180
2181 /*-----------------------------------------------------------------*/
2182 /* genCpl - generate code for complement                           */
2183 /*-----------------------------------------------------------------*/
2184 static void
2185 genCpl (iCode * ic)
2186 {
2187   int offset = 0;
2188   int size;
2189
2190
2191   /* assign asmOps to operand & result */
2192   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2193   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2194
2195   /* if both are in bit space then
2196      a special case */
2197   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2198       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2199     {
2200       wassertl (0, "Left and the result are in bit space");
2201     }
2202
2203   size = AOP_SIZE (IC_RESULT (ic));
2204   while (size--)
2205     {
2206       const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
2207       _moveA (l);
2208       emit2("cpl");
2209       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2210     }
2211
2212   /* release the aops */
2213   freeAsmop (IC_LEFT (ic), NULL, ic);
2214   freeAsmop (IC_RESULT (ic), NULL, ic);
2215 }
2216
2217 static void
2218 _gbz80_emitAddSubLongLong (iCode *ic, asmop *left, asmop *right, bool isAdd)
2219 {
2220   /* Logic:
2221        ld de,right.lw
2222        setup hl to left
2223        de = hl - de
2224        push flags
2225        store de into result
2226        pop flags
2227        ld de,right.hw
2228        setup hl
2229        de = hl -de
2230        store de into result
2231   */
2232   const char *first = isAdd ? "add" : "sub";
2233   const char *later = isAdd ? "adc" : "sbc";
2234
2235   wassertl (IS_GB, "Code is only relevent to the gbz80");
2236   wassertl (AOP( IC_RESULT (ic))->size == 4, "Only works for four bytes");
2237
2238   fetchPair (PAIR_DE, left);
2239
2240   emit2 ("ld a,e");
2241   emit2 ("%s a,%s", first, aopGet( right, LSB, FALSE));
2242   emit2 ("ld e,a");
2243   emit2 ("ld a,d");
2244   emit2 ("%s a,%s", later, aopGet( right, MSB16, FALSE));
2245
2246   _push (PAIR_AF);
2247   aopPut ( AOP (IC_RESULT (ic)), "a", MSB16);
2248   aopPut ( AOP (IC_RESULT (ic)), "e", LSB);
2249
2250   fetchPairLong (PAIR_DE, left, NULL, MSB24);
2251   aopGet (right, MSB24, FALSE);
2252
2253   _pop (PAIR_AF);
2254   emit2 ("ld a,e");
2255   emit2 ("%s a,%s", later, aopGet( right, MSB24, FALSE));
2256   emit2 ("ld e,a");
2257   emit2 ("ld a,d");
2258   emit2 ("%s a,%s", later, aopGet( right, MSB32, FALSE));
2259
2260   aopPut ( AOP (IC_RESULT (ic)), "a", MSB32);
2261   aopPut ( AOP (IC_RESULT (ic)), "e", MSB24);
2262 }
2263
2264 static void
2265 _gbz80_emitAddSubLong (iCode *ic, bool isAdd)
2266 {
2267   _gbz80_emitAddSubLongLong (ic, AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)), isAdd);
2268 }
2269
2270 /*-----------------------------------------------------------------*/
2271 /* genUminusFloat - unary minus for floating points                */
2272 /*-----------------------------------------------------------------*/
2273 static void
2274 genUminusFloat (operand * op, operand * result)
2275 {
2276   int size, offset = 0;
2277
2278   emitDebug("; genUminusFloat");
2279
2280   /* for this we just need to flip the
2281      first it then copy the rest in place */
2282   size = AOP_SIZE (op) - 1;
2283
2284   _moveA(aopGet (AOP (op), MSB32, FALSE));
2285
2286   emit2("xor a,!immedbyte", 0x80);
2287   aopPut (AOP (result), "a", MSB32);
2288
2289   while (size--)
2290     {
2291       aopPut (AOP (result), aopGet (AOP (op), offset, FALSE), offset);
2292       offset++;
2293     }
2294 }
2295
2296 /*-----------------------------------------------------------------*/
2297 /* genUminus - unary minus code generation                         */
2298 /*-----------------------------------------------------------------*/
2299 static void
2300 genUminus (iCode * ic)
2301 {
2302   int offset, size;
2303   sym_link *optype, *rtype;
2304
2305   /* assign asmops */
2306   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2307   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2308
2309   /* if both in bit space then special
2310      case */
2311   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2312       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2313     {
2314       wassertl (0, "Left and right are in bit space");
2315       goto release;
2316     }
2317
2318   optype = operandType (IC_LEFT (ic));
2319   rtype = operandType (IC_RESULT (ic));
2320
2321   /* if float then do float stuff */
2322   if (IS_FLOAT (optype))
2323     {
2324       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2325       goto release;
2326     }
2327
2328   /* otherwise subtract from zero */
2329   size = AOP_SIZE (IC_LEFT (ic));
2330
2331   if (AOP_SIZE (IC_RESULT (ic)) == 4 && IS_GB)
2332     {
2333       /* Create a new asmop with value zero */
2334       asmop *azero = newAsmop (AOP_SIMPLELIT);
2335       azero->aopu.aop_simplelit = 0;
2336       azero->size = size;
2337       _gbz80_emitAddSubLongLong (ic, azero, AOP (IC_LEFT (ic)), FALSE);
2338       goto release;
2339     }
2340
2341   offset = 0;
2342   _clearCarry();
2343   while (size--)
2344     {
2345       const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
2346       emit2 ("ld a,!zero");
2347       emit2 ("sbc a,%s", l);
2348       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2349     }
2350
2351   /* if any remaining bytes in the result */
2352   /* we just need to propagate the sign   */
2353   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2354     {
2355       emit2 ("rlc a");
2356       emit2 ("sbc a,a");
2357       while (size--)
2358         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2359     }
2360
2361 release:
2362   /* release the aops */
2363   freeAsmop (IC_LEFT (ic), NULL, ic);
2364   freeAsmop (IC_RESULT (ic), NULL, ic);
2365 }
2366
2367 /*-----------------------------------------------------------------*/
2368 /* assignResultValue -               */
2369 /*-----------------------------------------------------------------*/
2370 void
2371 assignResultValue (operand * oper)
2372 {
2373   int size = AOP_SIZE (oper);
2374   bool topInA = 0;
2375
2376   wassertl (size <= 4, "Got a result that is bigger than four bytes");
2377   topInA = requiresHL (AOP (oper));
2378
2379   if (IS_GB && size == 4 && requiresHL (AOP (oper)))
2380     {
2381       /* We do it the hard way here. */
2382       _push (PAIR_HL);
2383       aopPut (AOP (oper), _fReturn[0], 0);
2384       aopPut (AOP (oper), _fReturn[1], 1);
2385       _pop (PAIR_DE);
2386       aopPut (AOP (oper), _fReturn[0], 2);
2387       aopPut (AOP (oper), _fReturn[1], 3);
2388     }
2389   else
2390     {
2391       while (size--)
2392         {
2393           aopPut (AOP (oper), _fReturn[size], size);
2394         }
2395     }
2396 }
2397
2398 /** Simple restore that doesn't take into account what is used in the
2399     return.
2400 */
2401 static void
2402 _restoreRegsAfterCall(void)
2403 {
2404   if (_G.stack.pushedDE)
2405     {
2406       _pop ( PAIR_DE);
2407       _G.stack.pushedDE = FALSE;
2408     }
2409   if (_G.stack.pushedBC)
2410     {
2411       _pop ( PAIR_BC);
2412       _G.stack.pushedBC = FALSE;
2413     }
2414   _G.saves.saved = FALSE;
2415 }
2416
2417 static void
2418 _saveRegsForCall(iCode *ic, int sendSetSize)
2419 {
2420   /* Rules:
2421       o Stack parameters are pushed before this function enters
2422       o DE and BC may be used in this function.
2423       o HL and DE may be used to return the result.
2424       o HL and DE may be used to send variables.
2425       o DE and BC may be used to store the result value.
2426       o HL may be used in computing the sent value of DE
2427       o The iPushes for other parameters occur before any addSets
2428
2429      Logic: (to be run inside the first iPush or if none, before sending)
2430       o Compute if DE and/or BC are in use over the call
2431       o Compute if DE is used in the send set
2432       o Compute if DE and/or BC are used to hold the result value
2433       o If (DE is used, or in the send set) and is not used in the result, push.
2434       o If BC is used and is not in the result, push
2435       o 
2436       o If DE is used in the send set, fetch
2437       o If HL is used in the send set, fetch
2438       o Call
2439       o ...
2440   */
2441   if (_G.saves.saved == FALSE) {
2442     bool deInUse, bcInUse;
2443     bool deSending;
2444     bool bcInRet = FALSE, deInRet = FALSE;
2445     bitVect *rInUse;
2446
2447     rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), 
2448                             z80_rUmaskForOp (IC_RESULT(ic)));
2449
2450     deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
2451     bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
2452
2453     deSending = (sendSetSize > 1);
2454
2455     emitDebug ("; _saveRegsForCall: sendSetSize: %u deInUse: %u bcInUse: %u deSending: %u", sendSetSize, deInUse, bcInUse, deSending);
2456
2457     if (bcInUse && bcInRet == FALSE) {
2458       _push(PAIR_BC);
2459       _G.stack.pushedBC = TRUE;
2460     }
2461     if (deInUse && deInRet == FALSE) {
2462       _push(PAIR_DE);
2463       _G.stack.pushedDE = TRUE;
2464     }
2465
2466     _G.saves.saved = TRUE;
2467   }
2468   else {
2469     /* Already saved. */
2470   }
2471 }
2472
2473 /*-----------------------------------------------------------------*/
2474 /* genIpush - genrate code for pushing this gets a little complex  */
2475 /*-----------------------------------------------------------------*/
2476 static void
2477 genIpush (iCode * ic)
2478 {
2479   int size, offset = 0;
2480   const char *l;
2481
2482   /* if this is not a parm push : ie. it is spill push
2483      and spill push is always done on the local stack */
2484   if (!ic->parmPush)
2485     {
2486       wassertl(0, "Encountered an unsupported spill push.");
2487       return;
2488     }
2489
2490   if (_G.saves.saved == FALSE) {
2491     /* Caller saves, and this is the first iPush. */
2492     /* Scan ahead until we find the function that we are pushing parameters to.
2493        Count the number of addSets on the way to figure out what registers
2494        are used in the send set.
2495     */
2496     int nAddSets = 0;
2497     iCode *walk = ic->next;
2498     
2499     while (walk) {
2500       if (walk->op == SEND) {
2501         nAddSets++;
2502       }
2503       else if (walk->op == CALL || walk->op == PCALL) {
2504         /* Found it. */
2505         break;
2506       }
2507       else {
2508         /* Keep looking. */
2509       }
2510       walk = walk->next;
2511     }
2512     _saveRegsForCall(walk, nAddSets);
2513   }
2514   else {
2515     /* Already saved by another iPush. */
2516   }
2517
2518   /* then do the push */
2519   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2520
2521   size = AOP_SIZE (IC_LEFT (ic));
2522
2523   if (isPair (AOP (IC_LEFT (ic))) && size == 2)
2524     {
2525       _G.stack.pushed += 2;
2526       emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
2527     }
2528   else
2529     {
2530       if (size == 2)
2531         {
2532           fetchHL (AOP (IC_LEFT (ic)));
2533           emit2 ("push hl");
2534           spillPair (PAIR_HL);
2535           _G.stack.pushed += 2;
2536           goto release;
2537         }
2538       if (size == 4)
2539         {
2540           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
2541           emit2 ("push hl");
2542           spillPair (PAIR_HL);
2543           _G.stack.pushed += 2;
2544           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0);
2545           emit2 ("push hl");
2546           spillPair (PAIR_HL);
2547           _G.stack.pushed += 2;
2548           goto release;
2549         }
2550       offset = size;
2551       while (size--)
2552         {
2553           if (AOP (IC_LEFT (ic))->type == AOP_IY)
2554             {
2555               char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
2556               wassert (l);
2557               emit2 ("ld a,(%s)", l);
2558             }
2559           else
2560             {
2561               l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
2562               emit2 ("ld a,%s", l);
2563             }
2564           emit2 ("push af");
2565           emit2 ("inc sp");
2566           _G.stack.pushed++;
2567         }
2568     }
2569 release:
2570   freeAsmop (IC_LEFT (ic), NULL, ic);
2571 }
2572
2573 /*-----------------------------------------------------------------*/
2574 /* genIpop - recover the registers: can happen only for spilling   */
2575 /*-----------------------------------------------------------------*/
2576 static void
2577 genIpop (iCode * ic)
2578 {
2579   int size, offset;
2580
2581
2582   /* if the temp was not pushed then */
2583   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2584     return;
2585
2586   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2587   size = AOP_SIZE (IC_LEFT (ic));
2588   offset = (size - 1);
2589   if (isPair (AOP (IC_LEFT (ic))))
2590     {
2591       emit2 ("pop %s", getPairName (AOP (IC_LEFT (ic))));
2592     }
2593   else
2594     {
2595       while (size--)
2596         {
2597           emit2 ("dec sp");
2598           emit2 ("pop hl");
2599           spillPair (PAIR_HL);
2600           aopPut (AOP (IC_LEFT (ic)), "l", offset--);
2601         }
2602     }
2603
2604   freeAsmop (IC_LEFT (ic), NULL, ic);
2605 }
2606
2607 /* This is quite unfortunate */
2608 static void
2609 setArea (int inHome)
2610 {
2611   /*
2612     static int lastArea = 0;
2613
2614      if (_G.in_home != inHome) {
2615      if (inHome) {
2616      const char *sz = port->mem.code_name;
2617      port->mem.code_name = "HOME";
2618      emit2("!area", CODE_NAME);
2619      port->mem.code_name = sz;
2620      }
2621      else
2622      emit2("!area", CODE_NAME); */
2623   _G.in_home = inHome;
2624   //    }
2625 }
2626
2627 static bool
2628 isInHome (void)
2629 {
2630   return _G.in_home;
2631 }
2632
2633 static int
2634 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
2635 {
2636   int ret = 0;
2637   asmop *aop;
2638   symbol *sym = OP_SYMBOL (op);
2639
2640   if (sym->isspilt || sym->nRegs == 0)
2641     return 0;
2642
2643   aopOp (op, ic, FALSE, FALSE);
2644
2645   aop = AOP (op);
2646   if (aop->type == AOP_REG)
2647     {
2648       int i;
2649       for (i = 0; i < aop->size; i++)
2650         {
2651           if (pairId == PAIR_DE)
2652             {
2653               emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
2654               if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
2655                 ret++;
2656               if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
2657                 ret++;
2658             }
2659           else if (pairId == PAIR_BC)
2660             {
2661               emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
2662               if (!strcmp (aop->aopu.aop_reg[i]->name, "c"))
2663                 ret++;
2664               if (!strcmp (aop->aopu.aop_reg[i]->name, "b"))
2665                 ret++;
2666             }
2667           else
2668             {
2669               wassert (0);
2670             }
2671         }
2672     }
2673
2674   freeAsmop (IC_LEFT (ic), NULL, ic);
2675   return ret;
2676 }
2677
2678 /** Emit the code for a call statement
2679  */
2680 static void
2681 emitCall (iCode * ic, bool ispcall)
2682 {
2683   bool bInRet, cInRet, dInRet, eInRet;
2684   sym_link *dtype = operandType (IC_LEFT (ic));
2685
2686   /* if caller saves & we have not saved then */
2687   if (!ic->regsSaved)
2688     {
2689       /* PENDING */
2690     }
2691
2692   _saveRegsForCall(ic, _G.sendSet ? elementsInSet(_G.sendSet) : 0);
2693
2694   /* if send set is not empty then assign */
2695   if (_G.sendSet)
2696     {
2697       iCode *sic;
2698       int send = 0;
2699       int nSend = elementsInSet(_G.sendSet);
2700       bool swapped = FALSE;
2701
2702       int _z80_sendOrder[] = {
2703         PAIR_BC, PAIR_DE
2704       };
2705
2706       if (nSend > 1) {
2707         /* Check if the parameters are swapped.  If so route through hl instead. */
2708         wassertl (nSend == 2, "Pedantic check.  Code only checks for the two send items case.");
2709
2710         sic = setFirstItem(_G.sendSet);
2711         sic = setNextItem(_G.sendSet);
2712
2713         if (_opUsesPair (IC_LEFT(sic), sic, _z80_sendOrder[0])) {
2714           /* The second send value is loaded from one the one that holds the first
2715              send, i.e. it is overwritten. */
2716           /* Cache the first in HL, and load the second from HL instead. */
2717           emit2 ("ld h,%s", _pairs[_z80_sendOrder[0]].h);
2718           emit2 ("ld l,%s", _pairs[_z80_sendOrder[0]].l);
2719
2720           swapped = TRUE;
2721         }
2722       }
2723
2724       for (sic = setFirstItem (_G.sendSet); sic;
2725            sic = setNextItem (_G.sendSet))
2726         {
2727           int size;
2728           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2729
2730           size = AOP_SIZE (IC_LEFT (sic));
2731           wassertl (size <= 2, "Tried to send a parameter that is bigger than two bytes");
2732           wassertl (_z80_sendOrder[send] != PAIR_INVALID, "Tried to send more parameters than we have registers for");
2733
2734           // PENDING: Mild hack
2735           if (swapped == TRUE && send == 1) {
2736             if (size > 1) {
2737               emit2 ("ld %s,h", _pairs[_z80_sendOrder[send]].h);
2738             }
2739             else {
2740               emit2 ("ld %s,!zero", _pairs[_z80_sendOrder[send]].h);
2741             }
2742             emit2 ("ld %s,l", _pairs[_z80_sendOrder[send]].l);
2743           }
2744           else {
2745             fetchPair(_z80_sendOrder[send], AOP (IC_LEFT (sic)));
2746           }
2747
2748           send++;
2749           freeAsmop (IC_LEFT (sic), NULL, sic);
2750         }
2751       _G.sendSet = NULL;
2752     }
2753
2754   if (ispcall)
2755     {
2756       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2757         {
2758           werror (W_INDIR_BANKED);
2759         }
2760       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2761
2762       if (isLitWord (AOP (IC_LEFT (ic))))
2763         {
2764           emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2765         }
2766       else
2767         {
2768           symbol *rlbl = newiTempLabel (NULL);
2769           spillPair (PAIR_HL);
2770           emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2771           emit2 ("push hl");
2772           _G.stack.pushed += 2;
2773
2774           fetchHL (AOP (IC_LEFT (ic)));
2775           emit2 ("jp !*hl");
2776           emit2 ("!tlabeldef", (rlbl->key + 100));
2777           _G.stack.pushed -= 2;
2778         }
2779       freeAsmop (IC_LEFT (ic), NULL, ic);
2780     }
2781   else
2782     {
2783       char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2784       OP_SYMBOL (IC_LEFT (ic))->rname :
2785       OP_SYMBOL (IC_LEFT (ic))->name;
2786       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2787         {
2788           emit2 ("call banked_call");
2789           emit2 ("!dws", name);
2790           emit2 ("!dw !bankimmeds", name);
2791         }
2792       else
2793         {
2794           /* make the call */
2795           emit2 ("call %s", name);
2796         }
2797     }
2798   spillCached ();
2799
2800   /* Mark the regsiters as restored. */
2801   _G.saves.saved = FALSE;
2802
2803   /* if we need assign a result value */
2804   if ((IS_ITEMP (IC_RESULT (ic)) &&
2805        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2806         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2807       IS_TRUE_SYMOP (IC_RESULT (ic)))
2808     {
2809
2810       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2811
2812       assignResultValue (IC_RESULT (ic));
2813
2814       freeAsmop (IC_RESULT (ic), NULL, ic);
2815     }
2816
2817   /* adjust the stack for parameters if required */
2818   if (ic->parmBytes)
2819     {
2820       int i = ic->parmBytes;
2821
2822       _G.stack.pushed -= i;
2823       if (IS_GB)
2824         {
2825           emit2 ("!ldaspsp", i);
2826         }
2827       else
2828         {
2829           spillCached ();
2830           if (i > 8)
2831             {
2832               emit2 ("ld iy,!immedword", i);
2833               emit2 ("add iy,sp");
2834               emit2 ("ld sp,iy");
2835             }
2836           else
2837             {
2838               while (i > 1)
2839                 {
2840                   emit2 ("pop af");
2841                   i -= 2;
2842                 }
2843               if (i)
2844                 {
2845                   emit2 ("inc sp");
2846                 }
2847             }
2848         }
2849     }
2850
2851   spillCached ();
2852   if (IC_RESULT (ic))
2853     {
2854       bitVect *result = z80_rUmaskForOp (IC_RESULT (ic));
2855       bInRet = bitVectBitValue(result, B_IDX);
2856       cInRet = bitVectBitValue(result, C_IDX);
2857       dInRet = bitVectBitValue(result, D_IDX);
2858       eInRet = bitVectBitValue(result, E_IDX);
2859     }
2860   else
2861     {
2862       bInRet = FALSE;
2863       cInRet = FALSE;
2864       dInRet = FALSE;
2865       eInRet = FALSE;
2866     }
2867
2868   if (_G.stack.pushedDE) 
2869     {
2870       if (dInRet && eInRet)
2871         {
2872           wassertl (0, "Shouldn't push DE if it's wiped out by the return");
2873         }
2874       else if (dInRet)
2875         {
2876           /* Only restore E */
2877           emit2 ("ld a,d");
2878           _pop (PAIR_DE);
2879           emit2 ("ld d,a");
2880         }
2881       else if (eInRet)
2882         {
2883           /* Only restore D */
2884           _pop (PAIR_AF);
2885           emit2 ("ld d,a");
2886         }
2887       else
2888         {
2889           _pop (PAIR_DE);
2890         }
2891       _G.stack.pushedDE = FALSE;
2892     }
2893   
2894   if (_G.stack.pushedBC) 
2895     {
2896       if (bInRet && cInRet)
2897         {
2898           wassertl (0, "Shouldn't push BC if it's wiped out by the return");
2899         }
2900       else if (bInRet)
2901         {
2902           /* Only restore C */
2903           emit2 ("ld a,b");
2904           _pop (PAIR_BC);
2905           emit2 ("ld b,a");
2906         }
2907       else if (cInRet)
2908         {
2909           /* Only restore B */
2910           _pop (PAIR_AF);
2911           emit2 ("ld b,a");
2912         }
2913       else
2914         {
2915           _pop (PAIR_BC);
2916         }
2917       _G.stack.pushedBC = FALSE;
2918     }
2919 }
2920
2921 /*-----------------------------------------------------------------*/
2922 /* genCall - generates a call statement                            */
2923 /*-----------------------------------------------------------------*/
2924 static void
2925 genCall (iCode * ic)
2926 {
2927   emitCall (ic, FALSE);
2928 }
2929
2930 /*-----------------------------------------------------------------*/
2931 /* genPcall - generates a call by pointer statement                */
2932 /*-----------------------------------------------------------------*/
2933 static void
2934 genPcall (iCode * ic)
2935 {
2936   emitCall (ic, TRUE);
2937 }
2938
2939 /*-----------------------------------------------------------------*/
2940 /* resultRemat - result  is rematerializable                       */
2941 /*-----------------------------------------------------------------*/
2942 static int
2943 resultRemat (iCode * ic)
2944 {
2945   if (SKIP_IC (ic) || ic->op == IFX)
2946     return 0;
2947
2948   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2949     {
2950       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2951       if (sym->remat && !POINTER_SET (ic))
2952         return 1;
2953     }
2954
2955   return 0;
2956 }
2957
2958 extern set *publics;
2959
2960 /*-----------------------------------------------------------------*/
2961 /* genFunction - generated code for function entry                 */
2962 /*-----------------------------------------------------------------*/
2963 static void
2964 genFunction (iCode * ic)
2965 {
2966   bool stackParm;
2967   
2968   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2969   sym_link *ftype;
2970
2971   bool bcInUse = FALSE;
2972   bool deInUse = FALSE;
2973
2974   setArea (IFFUNC_NONBANKED (sym->type));
2975
2976   /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere
2977      else.
2978   */
2979   _G.receiveOffset = 0;
2980
2981   /* Record the last function name for debugging. */
2982   _G.lastFunctionName = sym->rname;
2983   
2984   /* Create the function header */
2985   emit2 ("!functionheader", sym->name);
2986   sprintf (buffer, "%s_start", sym->rname);
2987   emit2 ("!labeldef", buffer);
2988   emit2 ("!functionlabeldef", sym->rname);
2989
2990   if (options.profile) 
2991     {
2992       emit2 ("!profileenter");
2993     }
2994
2995   ftype = operandType (IC_LEFT (ic));
2996
2997   /* if critical function then turn interrupts off */
2998   if (IFFUNC_ISCRITICAL (ftype))
2999     emit2 ("!di");
3000
3001   /* if this is an interrupt service routine then save all potentially used registers. */
3002   if (IFFUNC_ISISR (sym->type))
3003     {
3004       emit2 ("!pusha");
3005     }
3006
3007   /* PENDING: callee-save etc */
3008
3009   _G.stack.param_offset = 0;
3010
3011   if (z80_opts.calleeSavesBC)
3012     {
3013       bcInUse = TRUE;
3014     }
3015
3016   /* Detect which registers are used. */
3017   if (IFFUNC_CALLEESAVES(sym->type) && sym->regsUsed)
3018     {
3019       int i;
3020       for (i = 0; i < sym->regsUsed->size; i++)
3021         {
3022           if (bitVectBitValue (sym->regsUsed, i))
3023             {
3024               switch (i)
3025                 {
3026                 case C_IDX:
3027                 case B_IDX:
3028                   bcInUse = TRUE;
3029                   break;
3030                 case D_IDX:
3031                 case E_IDX:
3032                   if (IS_Z80) {
3033                     deInUse = TRUE;
3034                   }
3035                   else {
3036                     /* Other systems use DE as a temporary. */
3037                   }
3038                   break;
3039                 }
3040             }
3041         }
3042     }
3043
3044   if (bcInUse) 
3045     {
3046       emit2 ("push bc");
3047       _G.stack.param_offset += 2;
3048     }
3049
3050   _G.calleeSaves.pushedBC = bcInUse;
3051
3052   if (deInUse)
3053     {
3054       emit2 ("push de");
3055       _G.stack.param_offset += 2;
3056     }
3057
3058   _G.calleeSaves.pushedDE = deInUse;
3059
3060   /* adjust the stack for the function */
3061   _G.stack.last = sym->stack;
3062   
3063   stackParm = FALSE;
3064   for (sym = setFirstItem (istack->syms); sym;
3065        sym = setNextItem (istack->syms))
3066     {
3067       if (sym->_isparm && !IS_REGPARM (sym->etype))
3068         {
3069           stackParm = TRUE;
3070           break;
3071         }
3072     }
3073   sym = OP_SYMBOL (IC_LEFT (ic));
3074   
3075   _G.omitFramePtr = options.ommitFramePtr;
3076   if (IS_Z80 && !stackParm && !sym->stack)
3077     {
3078       /* When the conflicts between AOP_EXSTK && AOP_HLREG are fixed, */
3079       /* the above !sym->stack condition can be removed. -- EEP       */
3080       if (sym->stack)
3081         emit2 ("!ldaspsp", -sym->stack);
3082       _G.omitFramePtr = TRUE;
3083     }
3084   else if (sym->stack && IS_GB && sym->stack > -INT8MIN)
3085     emit2 ("!enterxl", sym->stack);
3086   else if (sym->stack)
3087     emit2 ("!enterx", sym->stack);
3088   else
3089     emit2 ("!enter");
3090   _G.stack.offset = sym->stack;
3091 }
3092
3093 /*-----------------------------------------------------------------*/
3094 /* genEndFunction - generates epilogue for functions               */
3095 /*-----------------------------------------------------------------*/
3096 static void
3097 genEndFunction (iCode * ic)
3098 {
3099   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3100
3101   if (IFFUNC_ISISR (sym->type))
3102     {
3103       wassertl (0, "Tried to close an interrupt support function");
3104     }
3105   else
3106     {
3107       if (IFFUNC_ISCRITICAL (sym->type))
3108         emit2 ("!ei");
3109
3110       /* PENDING: calleeSave */
3111
3112       if (IS_Z80 && _G.omitFramePtr)
3113         {
3114           if (_G.stack.offset)
3115             emit2 ("!ldaspsp", _G.stack.offset);
3116         }
3117       else if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX)
3118         {
3119           emit2 ("!leavexl", _G.stack.offset);
3120         }
3121       else if (_G.stack.offset)
3122         {
3123           emit2 ("!leavex", _G.stack.offset);
3124         }
3125       else
3126         {
3127           emit2 ("!leave");
3128         }
3129
3130       if (_G.calleeSaves.pushedDE) 
3131         {
3132           emit2 ("pop de");
3133           _G.calleeSaves.pushedDE = FALSE;
3134         }
3135
3136       if (_G.calleeSaves.pushedBC) 
3137         {
3138           emit2 ("pop bc");
3139           _G.calleeSaves.pushedBC = FALSE;
3140         }
3141
3142       if (options.profile) 
3143         {
3144           emit2 ("!profileexit");
3145         }
3146
3147
3148       if (options.debug && currFunc)
3149         {
3150           _G.lines.isDebug = 1;
3151           sprintf (buffer, "C$%s$%d$%d$%d",
3152                     FileBaseName (ic->filename), currFunc->lastLine,
3153                     ic->level, ic->block);
3154           emit2 ("!labeldef", buffer);
3155           if (IS_STATIC (currFunc->etype))
3156             sprintf (buffer, "XF%s$%s$0$0", moduleName, currFunc->name);
3157           else
3158             sprintf (buffer, "XG$%s$0$0", currFunc->name);
3159           emit2 ("!labeldef", buffer);
3160           _G.lines.isDebug = 0;
3161         }
3162       
3163       /* Both banked and non-banked just ret */
3164       emit2 ("ret");
3165
3166       sprintf (buffer, "%s_end", sym->rname);
3167       emit2 ("!labeldef", buffer);
3168     }
3169   _G.flushStatics = 1;
3170   _G.stack.pushed = 0;
3171   _G.stack.offset = 0;
3172 }
3173
3174 /*-----------------------------------------------------------------*/
3175 /* genRet - generate code for return statement                     */
3176 /*-----------------------------------------------------------------*/
3177 static void
3178 genRet (iCode * ic)
3179 {
3180     const char *l;
3181   /* Errk.  This is a hack until I can figure out how
3182      to cause dehl to spill on a call */
3183   int size, offset = 0;
3184
3185   /* if we have no return value then
3186      just generate the "ret" */
3187   if (!IC_LEFT (ic))
3188     goto jumpret;
3189
3190   /* we have something to return then
3191      move the return value into place */
3192   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3193   size = AOP_SIZE (IC_LEFT (ic));
3194
3195   aopDump("IC_LEFT", AOP(IC_LEFT(ic)));
3196
3197   #if 0  
3198   if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
3199     {
3200       if (IS_GB)
3201         {
3202           emit2 ("ld de,%s", l);
3203         }
3204       else
3205         {
3206           emit2 ("ld hl,%s", l);
3207         }
3208     }
3209   #endif
3210   if (size==2)
3211     {
3212       fetchPair(IS_GB ? PAIR_DE : PAIR_HL, AOP (IC_LEFT (ic)));
3213     }
3214   else
3215     {
3216       if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
3217         {
3218           fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
3219           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
3220         }
3221       else
3222         {
3223           while (size--)
3224             {
3225               l = aopGet (AOP (IC_LEFT (ic)), offset,
3226                           FALSE);
3227               if (strcmp (_fReturn[offset], l))
3228                 emit2 ("ld %s,%s", _fReturn[offset], l);
3229               offset++;
3230             }
3231         }
3232     }
3233   freeAsmop (IC_LEFT (ic), NULL, ic);
3234
3235 jumpret:
3236   /* generate a jump to the return label
3237      if the next is not the return statement */
3238   if (!(ic->next && ic->next->op == LABEL &&
3239         IC_LABEL (ic->next) == returnLabel))
3240
3241     emit2 ("jp !tlabel", returnLabel->key + 100);
3242 }
3243
3244 /*-----------------------------------------------------------------*/
3245 /* genLabel - generates a label                                    */
3246 /*-----------------------------------------------------------------*/
3247 static void
3248 genLabel (iCode * ic)
3249 {
3250   /* special case never generate */
3251   if (IC_LABEL (ic) == entryLabel)
3252     return;
3253
3254   emitLabel (IC_LABEL (ic)->key + 100);
3255 }
3256
3257 /*-----------------------------------------------------------------*/
3258 /* genGoto - generates a ljmp                                      */
3259 /*-----------------------------------------------------------------*/
3260 static void
3261 genGoto (iCode * ic)
3262 {
3263   emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
3264 }
3265
3266 /*-----------------------------------------------------------------*/
3267 /* genPlusIncr :- does addition with increment if possible         */
3268 /*-----------------------------------------------------------------*/
3269 static bool
3270 genPlusIncr (iCode * ic)
3271 {
3272   unsigned int icount;
3273   unsigned int size = getDataSize (IC_RESULT (ic));
3274   PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
3275
3276   /* will try to generate an increment */
3277   /* if the right side is not a literal
3278      we cannot */
3279   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3280     return FALSE;
3281
3282   emitDebug ("; genPlusIncr");
3283
3284   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3285
3286   /* If result is a pair */
3287   if (resultId != PAIR_INVALID)
3288     {
3289       if (isLitWord (AOP (IC_LEFT (ic))))
3290         {
3291           fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
3292           return TRUE;
3293         }
3294       if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
3295         {
3296           if (getPairId (AOP (IC_LEFT (ic))) == PAIR_HL)
3297             {
3298               PAIR_ID freep = getFreePairId (ic);
3299               if (freep != PAIR_INVALID)
3300                 {
3301                   fetchPair (freep, AOP (IC_RIGHT (ic)));
3302                   emit2 ("add hl,%s", _pairs[freep].name);
3303                   return TRUE;
3304                 }
3305             }
3306           else
3307             {
3308               fetchPair (resultId, AOP (IC_RIGHT (ic)));
3309               emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
3310               return TRUE;
3311             }
3312         }
3313       if (icount > 5)
3314         return FALSE;
3315       /* Inc a pair */
3316       if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3317         {
3318           if (icount > 2)
3319             return FALSE;
3320           movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2);
3321         }
3322       while (icount--)
3323         {
3324           emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
3325         }
3326       return TRUE;
3327     }
3328
3329   if (IS_Z80 && isLitWord (AOP (IC_LEFT (ic))) && size == 2)
3330     {
3331       fetchLitPair (PAIR_HL, AOP (IC_LEFT (ic)), icount);
3332       commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
3333       return TRUE;
3334     }
3335
3336   /* if the literal value of the right hand side
3337      is greater than 4 then it is not worth it */
3338   if (icount > 4)
3339     return FALSE;
3340
3341   /* if increment 16 bits in register */
3342   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3343       size > 1 &&
3344       icount == 1
3345     )
3346     {
3347       int offset = 0;
3348       symbol *tlbl = NULL;
3349       tlbl = newiTempLabel (NULL);
3350       while (size--)
3351         {
3352           emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
3353           if (size)
3354             {
3355               emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3356             }
3357         }
3358       emitLabel (tlbl->key + 100);
3359       return TRUE;
3360     }
3361
3362   /* if the sizes are greater than 1 then we cannot */
3363   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3364       AOP_SIZE (IC_LEFT (ic)) > 1)
3365     return FALSE;
3366
3367   /* If the result is in a register then we can load then increment.
3368    */
3369   if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG)
3370     {
3371       aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), LSB, FALSE), LSB);
3372       while (icount--)
3373         {
3374           emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
3375         }
3376       return TRUE;
3377     }
3378
3379   /* we can if the aops of the left & result match or
3380      if they are in registers and the registers are the
3381      same */
3382   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3383     {
3384       while (icount--)
3385         {
3386           emit2 ("inc %s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
3387         }
3388       return TRUE;
3389     }
3390
3391   return FALSE;
3392 }
3393
3394 /*-----------------------------------------------------------------*/
3395 /* outBitAcc - output a bit in acc                                 */
3396 /*-----------------------------------------------------------------*/
3397 void
3398 outBitAcc (operand * result)
3399 {
3400   symbol *tlbl = newiTempLabel (NULL);
3401   /* if the result is a bit */
3402   if (AOP_TYPE (result) == AOP_CRY)
3403     {
3404       wassertl (0, "Tried to write A into a bit");
3405     }
3406   else
3407     {
3408       emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
3409       emit2 ("ld a,!one");
3410       emitLabel (tlbl->key + 100);
3411       outAcc (result);
3412     }
3413 }
3414
3415 bool
3416 couldDestroyCarry (asmop *aop)
3417 {
3418   if (aop)
3419     {
3420       if (aop->type == AOP_EXSTK || aop->type == AOP_IY)
3421         {
3422           return TRUE;
3423         }
3424     }
3425   return FALSE;
3426 }
3427
3428 static void
3429 shiftIntoPair (int idx, asmop *aop)
3430 {
3431   PAIR_ID id = PAIR_INVALID;
3432
3433   wassertl (IS_Z80, "Only implemented for the Z80");
3434   //  wassertl (aop->type == AOP_EXSTK, "Only implemented for EXSTK");
3435
3436   switch (idx) 
3437     {
3438     case 0:
3439       id = PAIR_HL;
3440       break;
3441     case 1:
3442       id = PAIR_DE;
3443       _push (PAIR_DE);
3444       break;
3445     default:
3446       wassertl (0, "Internal error - hit default case");
3447     }
3448
3449   emitDebug ("; Shift into pair idx %u", idx);
3450
3451   if (id == PAIR_HL)
3452     {
3453       setupPair (PAIR_HL, aop, 0);
3454     }
3455   else
3456     {
3457       setupPair (PAIR_IY, aop, 0);
3458       emit2 ("push iy");
3459       emit2 ("pop %s", _pairs[id].name);
3460     }
3461
3462   aop->type = AOP_PAIRPTR;
3463   aop->aopu.aop_pairId = id;
3464   _G.pairs[id].offset = 0;
3465   _G.pairs[id].last_type = aop->type;
3466 }
3467
3468 static void 
3469 setupToPreserveCarry (asmop *result, asmop *left, asmop *right)
3470 {
3471   wassert (left && right);
3472
3473   if (IS_Z80)
3474     {
3475       if (couldDestroyCarry (right) && couldDestroyCarry (result))
3476         {
3477           shiftIntoPair (0, right);
3478           /* check result again, in case right == result */
3479           if (couldDestroyCarry (result))
3480             shiftIntoPair (1, result);
3481         }
3482       else if (couldDestroyCarry (right))
3483         {
3484           shiftIntoPair (0, right);
3485         }
3486       else if (couldDestroyCarry (result))
3487         {
3488           shiftIntoPair (0, result);
3489         }
3490       else
3491         {
3492           /* Fine */
3493         }
3494     }
3495 }
3496
3497 /*-----------------------------------------------------------------*/
3498 /* genPlus - generates code for addition                           */
3499 /*-----------------------------------------------------------------*/
3500 static void
3501 genPlus (iCode * ic)
3502 {
3503   int size, offset = 0;
3504
3505   /* special cases :- */
3506
3507   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3508   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
3509   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3510
3511   /* Swap the left and right operands if:
3512
3513      if literal, literal on the right or
3514      if left requires ACC or right is already
3515      in ACC */
3516
3517   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3518       (AOP_NEEDSACC (IC_LEFT (ic))) ||
3519       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3520     {
3521       operand *t = IC_RIGHT (ic);
3522       IC_RIGHT (ic) = IC_LEFT (ic);
3523       IC_LEFT (ic) = t;
3524     }
3525
3526   /* if both left & right are in bit
3527      space */
3528   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3529       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3530     {
3531       /* Cant happen */
3532       wassertl (0, "Tried to add two bits");
3533     }
3534
3535   /* if left in bit space & right literal */
3536   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3537       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3538     {
3539       /* Can happen I guess */
3540       wassertl (0, "Tried to add a bit to a literal");
3541     }
3542
3543   /* if I can do an increment instead
3544      of add then GOOD for ME */
3545   if (genPlusIncr (ic) == TRUE)
3546     goto release;
3547
3548   emitDebug ("; Can't optimise plus by inc, falling back to the normal way");
3549
3550   size = getDataSize (IC_RESULT (ic));
3551
3552   /* Special case when left and right are constant */
3553   if (isPair (AOP (IC_RESULT (ic))))
3554     {
3555       char *left, *right;
3556       left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
3557       right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
3558
3559       if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT && AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT &&
3560           left && right)
3561         {
3562           /* It's a pair */
3563           /* PENDING: fix */
3564           char buffer[100];
3565           sprintf (buffer, "#(%s + %s)", left, right);
3566           emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
3567           goto release;
3568         }
3569     }
3570
3571   if ((isPair (AOP (IC_RIGHT (ic))) || isPair (AOP (IC_LEFT (ic)))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
3572     {
3573       /* Fetch into HL then do the add */
3574       PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
3575       PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
3576
3577       spillPair (PAIR_HL);
3578       
3579       if (left == PAIR_HL && right != PAIR_INVALID)
3580         {
3581           emit2 ("add hl,%s", _pairs[right].name);
3582           goto release;
3583         }
3584       else if (right == PAIR_HL && left != PAIR_INVALID)
3585         {
3586           emit2 ("add hl,%s", _pairs[left].name);
3587           goto release;
3588         }
3589       else if (right != PAIR_INVALID && right != PAIR_HL)
3590         {
3591           fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
3592           emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
3593           goto release;
3594         }
3595       else if (left != PAIR_INVALID && left != PAIR_HL)
3596         { 
3597           fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3598           emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
3599           goto release;
3600         }
3601       else
3602         {
3603           /* Can't do it */
3604         }
3605     }
3606
3607   if (isPair (AOP (IC_RIGHT (ic))) && AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD && getPairId (AOP (IC_RIGHT (ic))) != PAIR_HL)
3608     {
3609       fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
3610       emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
3611       spillCached();
3612       commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
3613       goto release;
3614     }
3615
3616   /* Special case:
3617      ld hl,sp+n trashes C so we cant afford to do it during an
3618      add with stack based varibles.  Worst case is:
3619      ld  hl,sp+left
3620      ld  a,(hl)
3621      ld  hl,sp+right
3622      add (hl)
3623      ld  hl,sp+result
3624      ld  (hl),a
3625      ld  hl,sp+left+1
3626      ld  a,(hl)
3627      ld  hl,sp+right+1
3628      adc (hl)
3629      ld  hl,sp+result+1
3630      ld  (hl),a
3631      So you cant afford to load up hl if either left, right, or result
3632      is on the stack (*sigh*)  The alt is:
3633      ld  hl,sp+left
3634      ld  de,(hl)
3635      ld  hl,sp+right
3636      ld  hl,(hl)
3637      add hl,de
3638      ld  hl,sp+result
3639      ld  (hl),hl
3640      Combinations in here are:
3641      * If left or right are in bc then the loss is small - trap later
3642      * If the result is in bc then the loss is also small
3643    */
3644   if (IS_GB)
3645     {
3646       if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
3647           AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
3648           AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
3649         {
3650           if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
3651                AOP_SIZE (IC_RIGHT (ic)) == 2) &&
3652               (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
3653                AOP_SIZE (IC_RIGHT (ic)) <= 2))
3654             {
3655               if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
3656                 {
3657                   /* Swap left and right */
3658                   operand *t = IC_RIGHT (ic);
3659                   IC_RIGHT (ic) = IC_LEFT (ic);
3660                   IC_LEFT (ic) = t;
3661                 }
3662               if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
3663                 {
3664                   fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3665                   emit2 ("add hl,bc");
3666                 }
3667               else
3668                 {
3669                   fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
3670                   fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3671                   emit2 ("add hl,de");
3672                 }
3673               commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
3674               goto release;
3675             }
3676         }
3677       if (size == 4)
3678         {
3679           /* Be paranoid on the GB with 4 byte variables due to how C
3680              can be trashed by lda hl,n(sp).
3681           */
3682           _gbz80_emitAddSubLong (ic, TRUE);
3683           goto release;
3684         }
3685     }
3686   
3687   setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
3688
3689   while (size--)
3690     {
3691       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3692         {
3693           _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3694           if (offset == 0)
3695             emit2 ("add a,%s",
3696                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3697           else
3698             emit2 ("adc a,%s",
3699                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3700         }
3701       else
3702         {
3703           _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3704           if (offset == 0)
3705             emit2 ("add a,%s",
3706                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3707           else
3708             emit2 ("adc a,%s",
3709                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3710         }
3711       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3712     }
3713
3714 release:
3715   freeAsmop (IC_LEFT (ic), NULL, ic);
3716   freeAsmop (IC_RIGHT (ic), NULL, ic);
3717   freeAsmop (IC_RESULT (ic), NULL, ic);
3718
3719 }
3720
3721 /*-----------------------------------------------------------------*/
3722 /* genMinusDec :- does subtraction with deccrement if possible     */
3723 /*-----------------------------------------------------------------*/
3724 static bool
3725 genMinusDec (iCode * ic)
3726 {
3727   unsigned int icount;
3728   unsigned int size = getDataSize (IC_RESULT (ic));
3729
3730   /* will try to generate an increment */
3731   /* if the right side is not a literal we cannot */
3732   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3733     return FALSE;
3734
3735   /* if the literal value of the right hand side
3736      is greater than 4 then it is not worth it */
3737   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
3738     return FALSE;
3739
3740   size = getDataSize (IC_RESULT (ic));
3741
3742   /* if decrement 16 bits in register */
3743   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3744       (size > 1) && isPair (AOP (IC_RESULT (ic))))
3745     {
3746       while (icount--)
3747         emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
3748       return TRUE;
3749     }
3750
3751   /* If result is a pair */
3752   if (isPair (AOP (IC_RESULT (ic))))
3753     {
3754       movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2);
3755       while (icount--)
3756         emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
3757       return TRUE;
3758     }
3759
3760   /* if increment 16 bits in register */
3761   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3762       (size == 2)
3763       )
3764     {
3765       fetchPair (_getTempPairId(), AOP (IC_RESULT (ic)));
3766
3767       while (icount--) {
3768         emit2 ("dec %s", _getTempPairName());
3769       }
3770
3771       commitPair (AOP (IC_RESULT (ic)), _getTempPairId());
3772
3773       return TRUE;
3774     }
3775
3776
3777   /* if the sizes are greater than 1 then we cannot */
3778   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3779       AOP_SIZE (IC_LEFT (ic)) > 1)
3780     return FALSE;
3781
3782   /* we can if the aops of the left & result match or if they are in
3783      registers and the registers are the same */
3784   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3785     {
3786       while (icount--)
3787         emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
3788       return TRUE;
3789     }
3790
3791   return FALSE;
3792 }
3793
3794 /*-----------------------------------------------------------------*/
3795 /* genMinus - generates code for subtraction                       */
3796 /*-----------------------------------------------------------------*/
3797 static void
3798 genMinus (iCode * ic)
3799 {
3800   int size, offset = 0;
3801   unsigned long lit = 0L;
3802
3803   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3804   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
3805   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3806
3807   /* special cases :- */
3808   /* if both left & right are in bit space */
3809   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3810       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3811     {
3812       wassertl (0, "Tried to subtract two bits");
3813       goto release;
3814     }
3815
3816   /* if I can do an decrement instead of subtract then GOOD for ME */
3817   if (genMinusDec (ic) == TRUE)
3818     goto release;
3819
3820   size = getDataSize (IC_RESULT (ic));
3821
3822   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3823     {
3824     }
3825   else
3826     {
3827       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3828       lit = -(long) lit;
3829     }
3830
3831   /* Same logic as genPlus */
3832   if (IS_GB)
3833     {
3834       if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
3835           AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
3836           AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
3837         {
3838           if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
3839                AOP_SIZE (IC_RIGHT (ic)) == 2) &&
3840               (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
3841                AOP_SIZE (IC_RIGHT (ic)) <= 2))
3842             {
3843               PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
3844               PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
3845
3846               if (left == PAIR_INVALID && right == PAIR_INVALID)
3847                 {
3848                   left = PAIR_DE;
3849                   right = PAIR_HL;
3850                 }
3851               else if (right == PAIR_INVALID)
3852                 right = PAIR_DE;
3853               else if (left == PAIR_INVALID)
3854                 left = PAIR_DE;
3855
3856               fetchPair (left, AOP (IC_LEFT (ic)));
3857               /* Order is important.  Right may be HL */
3858               fetchPair (right, AOP (IC_RIGHT (ic)));
3859
3860               emit2 ("ld a,%s", _pairs[left].l);
3861               emit2 ("sub a,%s", _pairs[right].l);
3862               emit2 ("ld e,a");
3863               emit2 ("ld a,%s", _pairs[left].h);
3864               emit2 ("sbc a,%s", _pairs[right].h);
3865
3866               if ( AOP_SIZE (IC_RESULT (ic)) > 1)
3867                 {
3868                   aopPut (AOP (IC_RESULT (ic)), "a", 1);
3869                 }
3870               aopPut (AOP (IC_RESULT (ic)), "e", 0);
3871               goto release;
3872             }
3873         }
3874       if (size == 4)
3875         {
3876           /* Be paranoid on the GB with 4 byte variables due to how C
3877              can be trashed by lda hl,n(sp).
3878           */
3879           _gbz80_emitAddSubLong (ic, FALSE);
3880           goto release;
3881         }
3882     }
3883
3884   setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
3885
3886   /* if literal, add a,#-lit, else normal subb */
3887   while (size--)
3888     {
3889       _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3890       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3891         {
3892           if (!offset)
3893             emit2 ("sub a,%s",
3894                       aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3895           else
3896             emit2 ("sbc a,%s",
3897                       aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3898         }
3899       else
3900         {
3901           /* first add without previous c */
3902           if (!offset)
3903             emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
3904           else
3905             emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3906         }
3907       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3908     }
3909
3910   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3911       AOP_SIZE (IC_LEFT (ic)) == 3 &&
3912       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3913     {
3914       wassertl (0, "Tried to subtract on a long pointer");
3915     }
3916
3917 release:
3918   freeAsmop (IC_LEFT (ic), NULL, ic);
3919   freeAsmop (IC_RIGHT (ic), NULL, ic);
3920   freeAsmop (IC_RESULT (ic), NULL, ic);
3921 }
3922
3923 /*-----------------------------------------------------------------*/
3924 /* genMult - generates code for multiplication                     */
3925 /*-----------------------------------------------------------------*/
3926 static void
3927 genMult (iCode * ic)
3928 {
3929   int val;
3930   int count, i;
3931   /* If true then the final operation should be a subtract */
3932   bool active = FALSE;
3933
3934   /* Shouldn't occur - all done through function calls */
3935   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3936   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
3937   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3938
3939   if (AOP_SIZE (IC_LEFT (ic)) > 2 ||
3940       AOP_SIZE (IC_RIGHT (ic)) > 2 ||
3941       AOP_SIZE (IC_RESULT (ic)) > 2)
3942     {
3943       wassertl (0, "Multiplication is handled through support function calls");
3944     }
3945
3946   /* Swap left and right such that right is a literal */
3947   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT))
3948     {
3949       operand *t = IC_RIGHT (ic);
3950       IC_RIGHT (ic) = IC_LEFT (ic);
3951       IC_LEFT (ic) = t;
3952     }
3953
3954   wassertl (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT, "Right must be a literal");
3955
3956   val = (int)floatFromVal ( AOP (IC_RIGHT (ic))->aopu.aop_lit);
3957   //  wassertl (val > 0, "Multiply must be positive");
3958   wassertl (val != 1, "Can't multiply by 1");
3959
3960   if (IS_Z80 && isPairInUseNotInRet (PAIR_DE, ic)) {
3961     _push (PAIR_DE);
3962     _G.stack.pushedDE = TRUE;
3963   }
3964
3965   if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
3966     {
3967       emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
3968       emit2 ("ld a,e");
3969       emit2 ("rlc a");
3970       emit2 ("sbc a,a");
3971       emit2 ("ld d,a");
3972     }
3973   else
3974     {
3975       fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
3976     }
3977
3978   i = val;
3979
3980   /* Fully unroled version of mul.s.  Not the most efficient.
3981    */
3982   for (count = 0; count < 16; count++)
3983     {
3984       if (count != 0 && active)
3985         {
3986           emit2 ("add hl,hl");
3987         }
3988       if (i & 0x8000U)
3989         {
3990           if (active == FALSE)
3991             {
3992               emit2 ("ld l,e");
3993               emit2 ("ld h,d");
3994             }
3995           else
3996             {
3997               emit2 ("add hl,de");
3998             }
3999           active = TRUE;
4000         }
4001       i <<= 1;
4002     }
4003
4004   spillCached();
4005
4006   if (IS_Z80 && _G.stack.pushedDE)
4007     {
4008       _pop (PAIR_DE);
4009       _G.stack.pushedDE = FALSE;
4010     }
4011
4012   commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
4013
4014   freeAsmop (IC_LEFT (ic), NULL, ic);
4015   freeAsmop (IC_RIGHT (ic), NULL, ic);
4016   freeAsmop (IC_RESULT (ic), NULL, ic);
4017 }
4018
4019 /*-----------------------------------------------------------------*/
4020 /* genDiv - generates code for division                            */
4021 /*-----------------------------------------------------------------*/
4022 static void
4023 genDiv (iCode * ic)
4024 {
4025   /* Shouldn't occur - all done through function calls */
4026   wassertl (0, "Division is handled through support function calls");
4027 }
4028
4029 /*-----------------------------------------------------------------*/
4030 /* genMod - generates code for division                            */
4031 /*-----------------------------------------------------------------*/
4032 static void
4033 genMod (iCode * ic)
4034 {
4035   /* Shouldn't occur - all done through function calls */
4036   wassert (0);
4037 }
4038
4039 /*-----------------------------------------------------------------*/
4040 /* genIfxJump :- will create a jump depending on the ifx           */
4041 /*-----------------------------------------------------------------*/
4042 static void
4043 genIfxJump (iCode * ic, char *jval)
4044 {
4045   symbol *jlbl;
4046   const char *inst;
4047
4048   /* if true label then we jump if condition
4049      supplied is true */
4050   if (IC_TRUE (ic))
4051     {
4052       jlbl = IC_TRUE (ic);
4053       if (!strcmp (jval, "a"))
4054         {
4055           inst = "nz";
4056         }
4057       else if (!strcmp (jval, "c"))
4058         {
4059           inst = "c";
4060         }
4061       else if (!strcmp (jval, "nc"))
4062         {
4063           inst = "nc";
4064         }
4065       else if (!strcmp (jval, "m"))
4066         {
4067           inst = "m";
4068         }
4069       else if (!strcmp (jval, "p"))
4070         {
4071           inst = "p";
4072         }
4073       else
4074         {
4075           /* The buffer contains the bit on A that we should test */
4076           inst = "nz";
4077         }
4078     }
4079   else
4080     {
4081       /* false label is present */
4082       jlbl = IC_FALSE (ic);
4083       if (!strcmp (jval, "a"))
4084         {
4085           inst = "z";
4086         }
4087       else if (!strcmp (jval, "c"))
4088         {
4089           inst = "nc";
4090         }
4091       else if (!strcmp (jval, "nc"))
4092         {
4093           inst = "c";
4094         }
4095       else if (!strcmp (jval, "m"))
4096         {
4097           inst = "p";
4098         }
4099       else if (!strcmp (jval, "p"))
4100         {
4101           inst = "m";
4102         }
4103       else
4104         {
4105           /* The buffer contains the bit on A that we should test */
4106           inst = "z";
4107         }
4108     }
4109   /* Z80 can do a conditional long jump */
4110   if (!strcmp (jval, "a"))
4111     {
4112       emit2 ("or a,a");
4113     }
4114   else if (!strcmp (jval, "c"))
4115     {
4116     }
4117   else if (!strcmp (jval, "nc"))
4118     {
4119     }
4120   else if (!strcmp (jval, "m"))
4121     {
4122     }
4123   else if (!strcmp (jval, "p"))
4124     {
4125     }
4126   else
4127     {
4128       emit2 ("bit %s,a", jval);
4129     }
4130   emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
4131
4132   /* mark the icode as generated */
4133   ic->generated = 1;
4134 }
4135
4136 #if DISABLED
4137 static const char *
4138 _getPairIdName (PAIR_ID id)
4139 {
4140   return _pairs[id].name;
4141 }
4142 #endif
4143
4144 #if OLD
4145       /* if unsigned char cmp with lit, just compare */
4146       if ((size == 1) &&
4147           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4148         {
4149           emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
4150           if (sign)
4151             {
4152               emit2 ("xor a,!immedbyte", 0x80);
4153               emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
4154             }
4155           else
4156             emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
4157         }
4158       else if (size == 4 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
4159         {
4160           // On the Gameboy we can't afford to adjust HL as it may trash the carry.
4161           // Pull left into DE and right into HL
4162           aopGet (AOP(left), LSB, FALSE);
4163           emit2 ("ld d,h");
4164           emit2 ("ld e,l");
4165           aopGet (AOP(right), LSB, FALSE);
4166
4167           while (size--)
4168             {
4169               if (size == 0 && sign)
4170                 {
4171                   // Highest byte when signed needs the bits flipped
4172                   // Save the flags
4173                   emit2 ("push af");
4174                   emit2 ("ld a,(de)");
4175                   emit2 ("xor !immedbyte", 0x80);
4176                   emit2 ("ld e,a");
4177                   emit2 ("ld a,(hl)");
4178                   emit2 ("xor !immedbyte", 0x80);
4179                   emit2 ("ld d,a");
4180                   emit2 ("pop af");
4181                   emit2 ("ld a,e");
4182                   emit2 ("%s a,d", offset == 0 ? "sub" : "sbc");
4183                 }
4184               else
4185                 {
4186                   emit2 ("ld a,(de)");
4187                   emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
4188                 }
4189               
4190               if (size != 0)
4191                 {
4192                   emit2 ("inc hl");
4193                   emit2 ("inc de");
4194                 }
4195               offset++;
4196             }
4197           spillPair (PAIR_HL);
4198         }
4199       else if (size == 4 && IS_Z80 && couldDestroyCarry(AOP(right)) && couldDestroyCarry(AOP(left)))
4200         {
4201           setupPair (PAIR_HL, AOP (left), 0);
4202           aopGet (AOP(right), LSB, FALSE);
4203
4204           while (size--)
4205             {
4206               if (size == 0 && sign)
4207                 {
4208                   // Highest byte when signed needs the bits flipped
4209                   // Save the flags
4210                   emit2 ("push af");
4211                   emit2 ("ld a,(hl)");
4212                   emit2 ("xor !immedbyte", 0x80);
4213                   emit2 ("ld l,a");
4214                   emit2 ("ld a,%d(iy)", offset);
4215                   emit2 ("xor !immedbyte", 0x80);
4216                   emit2 ("ld h,a");
4217                   emit2 ("pop af");
4218                   emit2 ("ld a,l");
4219                   emit2 ("%s a,h", offset == 0 ? "sub" : "sbc");
4220                 }
4221               else
4222                 {
4223                   emit2 ("ld a,(hl)");
4224                   emit2 ("%s a,%d(iy)", offset == 0 ? "sub" : "sbc", offset);
4225                 }
4226               
4227               if (size != 0)
4228                 {
4229                   emit2 ("inc hl");
4230                 }
4231               offset++;
4232             }
4233           spillPair (PAIR_HL);
4234           spillPair (PAIR_IY);
4235         }
4236       else
4237         {
4238           if (AOP_TYPE (right) == AOP_LIT)
4239             {
4240               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4241               /* optimize if(x < 0) or if(x >= 0) */
4242               if (lit == 0L)
4243                 {
4244                   if (!sign)
4245                     {
4246                       /* No sign so it's always false */
4247                       _clearCarry();
4248                     }
4249                   else
4250                     {
4251                       /* Just load in the top most bit */
4252                       _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
4253                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4254                         {
4255                           genIfxJump (ifx, "7");
4256                           return;
4257                         }
4258                       else
4259                         emit2 ("rlc a");
4260                     }
4261                   goto release;
4262                 }
4263             }
4264           
4265           if (sign)
4266             {
4267               /* First setup h and l contaning the top most bytes XORed */
4268               bool fDidXor = FALSE;
4269               if (AOP_TYPE (left) == AOP_LIT)
4270                 {
4271                   unsigned long lit = (unsigned long)
4272                   floatFromVal (AOP (left)->aopu.aop_lit);
4273                   emit2 ("ld %s,!immedbyte", _fTmp[0],
4274                          0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
4275                 }
4276               else
4277                 {
4278                   emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
4279                   emit2 ("xor a,!immedbyte", 0x80);
4280                   emit2 ("ld %s,a", _fTmp[0]);
4281                   fDidXor = TRUE;
4282                 }
4283               if (AOP_TYPE (right) == AOP_LIT)
4284                 {
4285                   unsigned long lit = (unsigned long)
4286                   floatFromVal (AOP (right)->aopu.aop_lit);
4287                   emit2 ("ld %s,!immedbyte", _fTmp[1],
4288                          0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
4289                 }
4290               else
4291                 {
4292                   emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
4293                   emit2 ("xor a,!immedbyte", 0x80);
4294                   emit2 ("ld %s,a", _fTmp[1]);
4295                   fDidXor = TRUE;
4296                 }
4297             }
4298           while (size--)
4299             {
4300               /* Do a long subtract */
4301               if (!sign || size)
4302                 {
4303                   _moveA (aopGet (AOP (left), offset, FALSE));
4304                 }
4305               if (sign && size == 0)
4306                 {
4307                   emit2 ("ld a,%s", _fTmp[0]);
4308                   emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", _fTmp[1]);
4309                 }
4310               else
4311                 {
4312                   /* Subtract through, propagating the carry */
4313                   emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
4314                   offset++;
4315                 }
4316             }
4317         }
4318     }
4319 #endif
4320
4321 /** Generic compare for > or <
4322  */
4323 static void
4324 genCmp (operand * left, operand * right,
4325         operand * result, iCode * ifx, int sign)
4326 {
4327   int size, offset = 0;
4328   unsigned long lit = 0L;
4329   bool swap_sense = FALSE;
4330
4331   /* if left & right are bit variables */
4332   if (AOP_TYPE (left) == AOP_CRY &&
4333       AOP_TYPE (right) == AOP_CRY)
4334     {
4335       /* Cant happen on the Z80 */
4336       wassertl (0, "Tried to compare two bits");
4337     }
4338   else
4339     {
4340       /* Do a long subtract of right from left. */
4341       size = max (AOP_SIZE (left), AOP_SIZE (right));
4342
4343       if (size > 1 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
4344         {
4345           // On the Gameboy we can't afford to adjust HL as it may trash the carry.
4346           // Pull left into DE and right into HL
4347           aopGet (AOP(left), LSB, FALSE);
4348           emit2 ("ld d,h");
4349           emit2 ("ld e,l");
4350           aopGet (AOP(right), LSB, FALSE);
4351
4352           while (size--)
4353             {
4354               emit2 ("ld a,(de)");
4355               emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
4356               
4357               if (size != 0)
4358                 {
4359                   emit2 ("inc hl");
4360                   emit2 ("inc de");
4361                 }
4362               offset++;
4363             }
4364           spillPair (PAIR_HL);
4365           goto release;
4366         }
4367
4368       if (AOP_TYPE (right) == AOP_LIT)
4369         {
4370           lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4371           /* optimize if(x < 0) or if(x >= 0) */
4372           if (lit == 0)
4373             {
4374               if (!sign)
4375                 {
4376                   /* No sign so it's always false */
4377                   _clearCarry();
4378                 }
4379               else
4380                 {
4381                   /* Just load in the top most bit */
4382                   _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
4383                   if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4384                     {
4385                       genIfxJump (ifx, "7");
4386                       return;
4387                     }
4388                   else
4389                     {
4390                       if (!sign) 
4391                         {
4392                           emit2 ("rlc a");
4393                         }
4394                       if (ifx)
4395                         {
4396                           genIfxJump (ifx, swap_sense ? "c" : "nc");
4397                           return;
4398                         }
4399                     }
4400                 }
4401               goto release;
4402             }
4403         }
4404
4405       while (size--)
4406         {
4407           _moveA (aopGet (AOP (left), offset, FALSE));
4408           /* Subtract through, propagating the carry */
4409           emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
4410           offset++;
4411         }
4412     }
4413
4414 release:
4415   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4416     {
4417       if (sign)
4418         {
4419           /* Shift the sign bit up into carry */
4420           emit2 ("rlca");
4421         }
4422       outBitCLong (result, swap_sense);
4423     }
4424   else
4425     {
4426       /* if the result is used in the next
4427          ifx conditional branch then generate
4428          code a little differently */
4429       if (ifx)
4430         {
4431           if (sign)
4432             {
4433               if (IS_GB)
4434                 {
4435                   emit2 ("rlca");
4436                   genIfxJump (ifx, swap_sense ? "nc" : "c");
4437                 }
4438               else
4439                 {
4440                   genIfxJump (ifx, swap_sense ? "p" : "m");
4441                 }
4442             }
4443           else
4444             {
4445               genIfxJump (ifx, swap_sense ? "nc" : "c");
4446             }
4447         }
4448       else
4449         {
4450           if (sign)
4451             {
4452               /* Shift the sign bit up into carry */
4453               emit2 ("rlca");
4454             }
4455           outBitCLong (result, swap_sense);
4456         }
4457       /* leave the result in acc */
4458     }
4459 }
4460
4461 /*-----------------------------------------------------------------*/
4462 /* genCmpGt :- greater than comparison                             */
4463 /*-----------------------------------------------------------------*/
4464 static void
4465 genCmpGt (iCode * ic, iCode * ifx)
4466 {
4467   operand *left, *right, *result;
4468   sym_link *letype, *retype;
4469   int sign;
4470
4471   left = IC_LEFT (ic);
4472   right = IC_RIGHT (ic);
4473   result = IC_RESULT (ic);
4474
4475   letype = getSpec (operandType (left));
4476   retype = getSpec (operandType (right));
4477   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4478   /* assign the amsops */
4479   aopOp (left, ic, FALSE, FALSE);
4480   aopOp (right, ic, FALSE, FALSE);
4481   aopOp (result, ic, TRUE, FALSE);
4482
4483   genCmp (right, left, result, ifx, sign);
4484
4485   freeAsmop (left, NULL, ic);
4486   freeAsmop (right, NULL, ic);
4487   freeAsmop (result, NULL, ic);
4488 }
4489
4490 /*-----------------------------------------------------------------*/
4491 /* genCmpLt - less than comparisons                                */
4492 /*-----------------------------------------------------------------*/
4493 static void
4494 genCmpLt (iCode * ic, iCode * ifx)
4495 {
4496   operand *left, *right, *result;
4497   sym_link *letype, *retype;
4498   int sign;
4499
4500   left = IC_LEFT (ic);
4501   right = IC_RIGHT (ic);
4502   result = IC_RESULT (ic);
4503
4504   letype = getSpec (operandType (left));
4505   retype = getSpec (operandType (right));
4506   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4507
4508   /* assign the amsops */
4509   aopOp (left, ic, FALSE, FALSE);
4510   aopOp (right, ic, FALSE, FALSE);
4511   aopOp (result, ic, TRUE, FALSE);
4512
4513   genCmp (left, right, result, ifx, sign);
4514
4515   freeAsmop (left, NULL, ic);
4516   freeAsmop (right, NULL, ic);
4517   freeAsmop (result, NULL, ic);
4518 }
4519
4520 /*-----------------------------------------------------------------*/
4521 /* gencjneshort - compare and jump if not equal                    */
4522 /*-----------------------------------------------------------------*/
4523 static void
4524 gencjneshort (operand * left, operand * right, symbol * lbl)
4525 {
4526   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4527   int offset = 0;
4528   unsigned long lit = 0L;
4529
4530   /* Swap the left and right if it makes the computation easier */
4531   if (AOP_TYPE (left) == AOP_LIT)
4532     {
4533       operand *t = right;
4534       right = left;
4535       left = t;
4536     }
4537
4538   if (AOP_TYPE (right) == AOP_LIT)
4539     {
4540       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4541     }
4542
4543   /* if the right side is a literal then anything goes */
4544   if (AOP_TYPE (right) == AOP_LIT &&
4545       AOP_TYPE (left) != AOP_DIR)
4546     {
4547       if (lit == 0)
4548         {
4549           emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
4550           if (size > 1)
4551             {
4552               while (--size)
4553                 {
4554                   emit2 ("or a,%s", aopGet (AOP (left), ++offset, FALSE));
4555                 }
4556             }
4557           else
4558             {
4559               emit2 ("or a,a");
4560             }
4561           emit2 ("jp nz,!tlabel", lbl->key + 100);
4562         }
4563       else
4564         {
4565           while (size--)
4566             {
4567               emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
4568               if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
4569                 emit2 ("or a,a");
4570               else
4571                 emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
4572               emit2 ("jp nz,!tlabel", lbl->key + 100);
4573               offset++;
4574             }
4575         }
4576     }
4577   /* if the right side is in a register or in direct space or
4578      if the left is a pointer register & right is not */
4579   else if (AOP_TYPE (right) == AOP_REG ||
4580            AOP_TYPE (right) == AOP_DIR ||
4581            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
4582     {
4583       while (size--)
4584         {
4585           _moveA (aopGet (AOP (left), offset, FALSE));
4586           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4587               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4588             /* PENDING */
4589             emit2 ("jp nz,!tlabel", lbl->key + 100);
4590           else
4591             {
4592               emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
4593               emit2 ("jp nz,!tlabel", lbl->key + 100);
4594             }
4595           offset++;
4596         }
4597     }
4598   else
4599     {
4600       /* right is a pointer reg need both a & b */
4601       /* PENDING: is this required? */
4602       while (size--)
4603         {
4604           _moveA (aopGet (AOP (right), offset, FALSE));
4605           emit2 ("cp %s", aopGet (AOP (left), offset, FALSE));
4606           emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
4607           offset++;
4608         }
4609     }
4610 }
4611
4612 /*-----------------------------------------------------------------*/
4613 /* gencjne - compare and jump if not equal                         */
4614 /*-----------------------------------------------------------------*/
4615 static void
4616 gencjne (operand * left, operand * right, symbol * lbl)
4617 {
4618   symbol *tlbl = newiTempLabel (NULL);
4619
4620   gencjneshort (left, right, lbl);
4621
4622   /* PENDING: ?? */
4623   emit2 ("ld a,!one");
4624   emit2 ("!shortjp !tlabel", tlbl->key + 100);
4625   emitLabel (lbl->key + 100);
4626   emit2 ("xor a,a");
4627   emitLabel (tlbl->key + 100);
4628 }
4629
4630 /*-----------------------------------------------------------------*/
4631 /* genCmpEq - generates code for equal to                          */
4632 /*-----------------------------------------------------------------*/
4633 static void
4634 genCmpEq (iCode * ic, iCode * ifx)
4635 {
4636   operand *left, *right, *result;
4637
4638   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4639   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4640   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4641
4642   emitDebug ("; genCmpEq: left %u, right %u, result %u", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
4643
4644   /* Swap operands if it makes the operation easier. ie if:
4645      1.  Left is a literal.
4646    */
4647   if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4648     {
4649       operand *t = IC_RIGHT (ic);
4650       IC_RIGHT (ic) = IC_LEFT (ic);
4651       IC_LEFT (ic) = t;
4652     }
4653
4654   if (ifx && !AOP_SIZE (result))
4655     {
4656       symbol *tlbl;
4657       /* if they are both bit variables */
4658       if (AOP_TYPE (left) == AOP_CRY &&
4659           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4660         {
4661           wassertl (0, "Tried to compare two bits");
4662         }
4663       else
4664         {
4665           tlbl = newiTempLabel (NULL);
4666           gencjneshort (left, right, tlbl);
4667           if (IC_TRUE (ifx))
4668             {
4669               emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
4670               emitLabel (tlbl->key + 100);
4671             }
4672           else
4673             {
4674               /* PENDING: do this better */
4675               symbol *lbl = newiTempLabel (NULL);
4676               emit2 ("!shortjp !tlabel", lbl->key + 100);
4677               emitLabel (tlbl->key + 100);
4678               emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
4679               emitLabel (lbl->key + 100);
4680             }
4681         }
4682       /* mark the icode as generated */
4683       ifx->generated = 1;
4684       goto release;
4685     }
4686
4687   /* if they are both bit variables */
4688   if (AOP_TYPE (left) == AOP_CRY &&
4689       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4690     {
4691       wassertl (0, "Tried to compare a bit to either a literal or another bit");
4692     }
4693   else
4694     {
4695       emitDebug(";4");
4696       
4697       gencjne (left, right, newiTempLabel (NULL));
4698       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4699         {
4700           wassert (0);
4701         }
4702       if (ifx)
4703         {
4704           emitDebug(";5");
4705           genIfxJump (ifx, "a");
4706           goto release;
4707         }
4708       /* if the result is used in an arithmetic operation
4709          then put the result in place */
4710       if (AOP_TYPE (result) != AOP_CRY)
4711         {
4712           emitDebug(";6");
4713           outAcc (result);
4714         }
4715       /* leave the result in acc */
4716     }
4717
4718 release:
4719   freeAsmop (left, NULL, ic);
4720   freeAsmop (right, NULL, ic);
4721   freeAsmop (result, NULL, ic);
4722 }
4723
4724 /*-----------------------------------------------------------------*/
4725 /* ifxForOp - returns the icode containing the ifx for operand     */
4726 /*-----------------------------------------------------------------*/
4727 static iCode *
4728 ifxForOp (operand * op, iCode * ic)
4729 {
4730   /* if true symbol then needs to be assigned */
4731   if (IS_TRUE_SYMOP (op))
4732     return NULL;
4733
4734   /* if this has register type condition and
4735      the next instruction is ifx with the same operand
4736      and live to of the operand is upto the ifx only then */
4737   if (ic->next &&
4738       ic->next->op == IFX &&
4739       IC_COND (ic->next)->key == op->key &&
4740       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4741     return ic->next;
4742
4743   return NULL;
4744 }
4745
4746 /*-----------------------------------------------------------------*/
4747 /* genAndOp - for && operation                                     */
4748 /*-----------------------------------------------------------------*/
4749 static void
4750 genAndOp (iCode * ic)
4751 {
4752   operand *left, *right, *result;
4753   symbol *tlbl;
4754
4755   /* note here that && operations that are in an if statement are
4756      taken away by backPatchLabels only those used in arthmetic
4757      operations remain */
4758   aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
4759   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
4760   aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
4761
4762   /* if both are bit variables */
4763   if (AOP_TYPE (left) == AOP_CRY &&
4764       AOP_TYPE (right) == AOP_CRY)
4765     {
4766       wassertl (0, "Tried to and two bits");
4767     }
4768   else
4769     {
4770       tlbl = newiTempLabel (NULL);
4771       _toBoolean (left);
4772       emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
4773       _toBoolean (right);
4774       emitLabel (tlbl->key + 100);
4775       outBitAcc (result);
4776     }
4777
4778   freeAsmop (left, NULL, ic);
4779   freeAsmop (right, NULL, ic);
4780   freeAsmop (result, NULL, ic);
4781 }
4782
4783 /*-----------------------------------------------------------------*/
4784 /* genOrOp - for || operation                                      */
4785 /*-----------------------------------------------------------------*/
4786 static void
4787 genOrOp (iCode * ic)
4788 {
4789   operand *left, *right, *result;
4790   symbol *tlbl;
4791
4792   /* note here that || operations that are in an
4793      if statement are taken away by backPatchLabels
4794      only those used in arthmetic operations remain */
4795   aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
4796   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
4797   aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
4798
4799   /* if both are bit variables */
4800   if (AOP_TYPE (left) == AOP_CRY &&
4801       AOP_TYPE (right) == AOP_CRY)
4802     {
4803       wassertl (0, "Tried to OR two bits");
4804     }
4805   else
4806     {
4807       tlbl = newiTempLabel (NULL);
4808       _toBoolean (left);
4809       emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4810       _toBoolean (right);
4811       emitLabel (tlbl->key + 100);
4812       outBitAcc (result);
4813     }
4814
4815   freeAsmop (left, NULL, ic);
4816   freeAsmop (right, NULL, ic);
4817   freeAsmop (result, NULL, ic);
4818 }
4819
4820 /*-----------------------------------------------------------------*/
4821 /* isLiteralBit - test if lit == 2^n                               */
4822 /*-----------------------------------------------------------------*/
4823 int
4824 isLiteralBit (unsigned long lit)
4825 {
4826   unsigned long pw[32] =
4827   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4828    0x100L, 0x200L, 0x400L, 0x800L,
4829    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4830    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4831    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4832    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4833    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4834   int idx;
4835
4836   for (idx = 0; idx < 32; idx++)
4837     if (lit == pw[idx])
4838       return idx + 1;
4839   return 0;
4840 }
4841
4842 /*-----------------------------------------------------------------*/
4843 /* jmpTrueOrFalse -                                                */
4844 /*-----------------------------------------------------------------*/
4845 static void
4846 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4847 {
4848   // ugly but optimized by peephole
4849   if (IC_TRUE (ic))
4850     {
4851       symbol *nlbl = newiTempLabel (NULL);
4852       emit2 ("jp !tlabel", nlbl->key + 100);
4853       emitLabel (tlbl->key + 100);
4854       emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
4855       emitLabel (nlbl->key + 100);
4856     }
4857   else
4858     {
4859       emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
4860       emitLabel (tlbl->key + 100);
4861     }
4862   ic->generated = 1;
4863 }
4864
4865 /*-----------------------------------------------------------------*/
4866 /* genAnd  - code for and                                          */
4867 /*-----------------------------------------------------------------*/
4868 static void
4869 genAnd (iCode * ic, iCode * ifx)
4870 {
4871   operand *left, *right, *result;
4872   int size, offset = 0;
4873   unsigned long lit = 0L;
4874   int bytelit = 0;
4875
4876   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4877   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4878   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4879
4880   /* if left is a literal & right is not then exchange them */
4881   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4882       AOP_NEEDSACC (left))
4883     {
4884       operand *tmp = right;
4885       right = left;
4886       left = tmp;
4887     }
4888
4889   /* if result = right then exchange them */
4890   if (sameRegs (AOP (result), AOP (right)))
4891     {
4892       operand *tmp = right;
4893       right = left;
4894       left = tmp;
4895     }
4896
4897   /* if right is bit then exchange them */
4898   if (AOP_TYPE (right) == AOP_CRY &&
4899       AOP_TYPE (left) != AOP_CRY)
4900     {
4901       operand *tmp = right;
4902       right = left;
4903       left = tmp;
4904     }
4905   if (AOP_TYPE (right) == AOP_LIT)
4906     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4907
4908   size = AOP_SIZE (result);
4909
4910   if (AOP_TYPE (left) == AOP_CRY)
4911     {
4912       wassertl (0, "Tried to perform an AND with a bit as an operand");
4913       goto release;
4914     }
4915
4916   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4917   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4918   if ((AOP_TYPE (right) == AOP_LIT) &&
4919       (AOP_TYPE (result) == AOP_CRY) &&
4920       (AOP_TYPE (left) != AOP_CRY))
4921     {
4922       symbol *tlbl = newiTempLabel (NULL);
4923       int sizel = AOP_SIZE (left);
4924       if (size)
4925         {
4926           /* PENDING: Test case for this. */
4927           emit2 ("scf");
4928         }
4929       while (sizel--)
4930         {
4931           if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4932             {
4933               _moveA (aopGet (AOP (left), offset, FALSE));
4934               if (bytelit != 0x0FFL)
4935                 {
4936                   emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
4937                 }
4938               else
4939                 {
4940                   /* For the flags */
4941                   emit2 ("or a,a");
4942                 }
4943               emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4944             }
4945               offset++;
4946         }
4947       // bit = left & literal
4948       if (size)
4949         {
4950           emit2 ("clr c");
4951           emit2 ("!tlabeldef", tlbl->key + 100);
4952         }
4953       // if(left & literal)
4954       else
4955         {
4956           if (ifx)
4957             {
4958               jmpTrueOrFalse (ifx, tlbl);
4959             }
4960           goto release;
4961         }
4962       outBitC (result);
4963       goto release;
4964     }
4965
4966   /* if left is same as result */
4967   if (sameRegs (AOP (result), AOP (left)))
4968     {
4969       for (; size--; offset++)
4970         {
4971           if (AOP_TYPE (right) == AOP_LIT)
4972             {
4973               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4974                 continue;
4975               else
4976                 {
4977                   if (bytelit == 0)
4978                     aopPut (AOP (result), "!zero", offset);
4979                   else
4980                     {
4981                       _moveA (aopGet (AOP (left), offset, FALSE));
4982                       emit2 ("and a,%s",
4983                                 aopGet (AOP (right), offset, FALSE));
4984                       aopPut (AOP (left), "a", offset);
4985                     }
4986                 }
4987
4988             }
4989           else
4990             {
4991               if (AOP_TYPE (left) == AOP_ACC)
4992                 {
4993                   wassertl (0, "Tried to perform an AND where the left operand is allocated into A");
4994                 }
4995               else
4996                 {
4997                   _moveA (aopGet (AOP (left), offset, FALSE));
4998                   emit2 ("and a,%s",
4999                             aopGet (AOP (right), offset, FALSE));
5000                   aopPut (AOP (left), "a", offset);
5001                 }
5002             }
5003         }
5004     }
5005   else
5006     {
5007       // left & result in different registers
5008       if (AOP_TYPE (result) == AOP_CRY)
5009         {
5010           wassertl (0, "Tried to AND where the result is in carry");
5011         }
5012       else
5013         {
5014           for (; (size--); offset++)
5015             {
5016               // normal case
5017               // result = left & right
5018               if (AOP_TYPE (right) == AOP_LIT)
5019                 {
5020                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5021                     {
5022                       aopPut (AOP (result),
5023                               aopGet (AOP (left), offset, FALSE),
5024                               offset);
5025                       continue;
5026                     }
5027                   else if (bytelit == 0)
5028                     {
5029                       aopPut (AOP (result), "!zero", offset);
5030                       continue;
5031                     }
5032                 }
5033               // faster than result <- left, anl result,right
5034               // and better if result is SFR
5035               if (AOP_TYPE (left) == AOP_ACC)
5036                 emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
5037               else
5038                 {
5039                   _moveA (aopGet (AOP (left), offset, FALSE));
5040                   emit2 ("and a,%s",
5041                             aopGet (AOP (right), offset, FALSE));
5042                 }
5043               aopPut (AOP (result), "a", offset);
5044             }
5045         }
5046
5047     }
5048
5049 release:
5050   freeAsmop (left, NULL, ic);
5051   freeAsmop (right, NULL, ic);
5052   freeAsmop (result, NULL, ic);
5053 }
5054
5055 /*-----------------------------------------------------------------*/
5056 /* genOr  - code for or                                            */
5057 /*-----------------------------------------------------------------*/
5058 static void
5059 genOr (iCode * ic, iCode * ifx)
5060 {
5061   operand *left, *right, *result;
5062   int size, offset = 0;
5063   unsigned long lit = 0L;
5064   int bytelit = 0;
5065
5066   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
5067   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
5068   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
5069
5070   /* if left is a literal & right is not then exchange them */
5071   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5072       AOP_NEEDSACC (left))
5073     {
5074       operand *tmp = right;
5075       right = left;
5076       left = tmp;
5077     }
5078
5079   /* if result = right then exchange them */
5080   if (sameRegs (AOP (result), AOP (right)))
5081     {
5082       operand *tmp = right;
5083       right = left;
5084       left = tmp;
5085     }
5086
5087   /* if right is bit then exchange them */
5088   if (AOP_TYPE (right) == AOP_CRY &&
5089       AOP_TYPE (left) != AOP_CRY)
5090     {
5091       operand *tmp = right;
5092       right = left;
5093       left = tmp;
5094     }
5095   if (AOP_TYPE (right) == AOP_LIT)
5096     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5097
5098   size = AOP_SIZE (result);
5099
5100   if (AOP_TYPE (left) == AOP_CRY)
5101     {
5102       wassertl (0, "Tried to OR where left is a bit");
5103       goto release;
5104     }
5105
5106   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5107   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5108   if ((AOP_TYPE (right) == AOP_LIT) &&
5109       (AOP_TYPE (result) == AOP_CRY) &&
5110       (AOP_TYPE (left) != AOP_CRY))
5111     {
5112       symbol *tlbl = newiTempLabel (NULL);
5113       int sizel = AOP_SIZE (left);
5114
5115       if (size)
5116         {
5117           wassertl (0, "Result is assigned to a bit");
5118         }
5119       /* PENDING: Modeled after the AND code which is inefficent. */
5120       while (sizel--)
5121         {
5122           bytelit = (lit >> (offset * 8)) & 0x0FFL;
5123
5124           _moveA (aopGet (AOP (left), offset, FALSE));
5125           /* OR with any literal is the same as OR with itself. */
5126           emit2 ("or a,a");
5127           emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5128
5129           offset++;
5130         }
5131       if (ifx)
5132         {
5133           jmpTrueOrFalse (ifx, tlbl);
5134         }
5135       goto release;
5136     }
5137
5138   /* if left is same as result */
5139   if (sameRegs (AOP (result), AOP (left)))
5140     {
5141       for (; size--; offset++)
5142         {
5143           if (AOP_TYPE (right) == AOP_LIT)
5144             {
5145               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5146                 continue;
5147               else
5148                 {
5149                   _moveA (aopGet (AOP (left), offset, FALSE));
5150                   emit2 ("or a,%s",
5151                             aopGet (AOP (right), offset, FALSE));
5152                   aopPut (AOP (result), "a", offset);
5153                 }
5154             }
5155           else
5156             {
5157               if (AOP_TYPE (left) == AOP_ACC)
5158                 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
5159               else
5160                 {
5161                   _moveA (aopGet (AOP (left), offset, FALSE));
5162                   emit2 ("or a,%s",
5163                             aopGet (AOP (right), offset, FALSE));
5164                   aopPut (AOP (result), "a", offset);
5165                 }
5166             }
5167         }
5168     }
5169   else
5170     {
5171       // left & result in different registers
5172       if (AOP_TYPE (result) == AOP_CRY)
5173         {
5174           wassertl (0, "Result of OR is in a bit");
5175         }
5176       else
5177         for (; (size--); offset++)
5178           {
5179             // normal case
5180             // result = left & right
5181             if (AOP_TYPE (right) == AOP_LIT)
5182               {
5183                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5184                   {
5185                     aopPut (AOP (result),
5186                             aopGet (AOP (left), offset, FALSE),
5187                             offset);
5188                     continue;
5189                   }
5190               }
5191             // faster than result <- left, anl result,right
5192             // and better if result is SFR
5193             if (AOP_TYPE (left) == AOP_ACC)
5194               emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
5195             else
5196               {
5197                 _moveA (aopGet (AOP (left), offset, FALSE));
5198                 emit2 ("or a,%s",
5199                           aopGet (AOP (right), offset, FALSE));
5200               }
5201             aopPut (AOP (result), "a", offset);
5202             /* PENDING: something weird is going on here.  Add exception. */
5203             if (AOP_TYPE (result) == AOP_ACC)
5204               break;
5205           }
5206     }
5207
5208 release:
5209   freeAsmop (left, NULL, ic);
5210   freeAsmop (right, NULL, ic);
5211   freeAsmop (result, NULL, ic);
5212 }
5213
5214 /*-----------------------------------------------------------------*/
5215 /* genXor - code for xclusive or                                   */
5216 /*-----------------------------------------------------------------*/
5217 static void
5218 genXor (iCode * ic, iCode * ifx)
5219 {
5220   operand *left, *right, *result;
5221   int size, offset = 0;
5222   unsigned long lit = 0L;
5223
5224   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
5225   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
5226   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
5227
5228   /* if left is a literal & right is not then exchange them */
5229   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5230       AOP_NEEDSACC (left))
5231     {
5232       operand *tmp = right;
5233       right = left;
5234       left = tmp;
5235     }
5236
5237   /* if result = right then exchange them */
5238   if (sameRegs (AOP (result), AOP (right)))
5239     {
5240       operand *tmp = right;
5241       right = left;
5242       left = tmp;
5243     }
5244
5245   /* if right is bit then exchange them */
5246   if (AOP_TYPE (right) == AOP_CRY &&
5247       AOP_TYPE (left) != AOP_CRY)
5248     {
5249       operand *tmp = right;
5250       right = left;
5251       left = tmp;
5252     }
5253   if (AOP_TYPE (right) == AOP_LIT)
5254     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5255
5256   size = AOP_SIZE (result);
5257
5258   if (AOP_TYPE (left) == AOP_CRY)
5259     {
5260       wassertl (0, "Tried to XOR a bit");
5261       goto release;
5262     }
5263
5264   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5265   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5266   if ((AOP_TYPE (right) == AOP_LIT) &&
5267       (AOP_TYPE (result) == AOP_CRY) &&
5268       (AOP_TYPE (left) != AOP_CRY))
5269     {
5270       symbol *tlbl = newiTempLabel (NULL);
5271       int sizel = AOP_SIZE (left);
5272
5273       if (size)
5274         {
5275           /* PENDING: Test case for this. */
5276           wassertl (0, "Tried to XOR left against a literal with the result going into a bit");
5277         }
5278       while (sizel--)
5279         {
5280           _moveA (aopGet (AOP (left), offset, FALSE));
5281           emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
5282           emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5283           offset++;
5284         }
5285       if (ifx)
5286         {
5287           jmpTrueOrFalse (ifx, tlbl);
5288         }
5289       else
5290         {
5291           wassertl (0, "Result of XOR was destined for a bit");
5292         }
5293       goto release;
5294     }
5295
5296   /* if left is same as result */
5297   if (sameRegs (AOP (result), AOP (left)))
5298     {
5299       for (; size--; offset++)
5300         {
5301           if (AOP_TYPE (right) == AOP_LIT)
5302             {
5303               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5304                 continue;
5305               else
5306                 {
5307                   _moveA (aopGet (AOP (right), offset, FALSE));
5308                   emit2 ("xor a,%s",
5309                             aopGet (AOP (left), offset, FALSE));
5310                   aopPut (AOP (result), "a", offset);
5311                 }
5312             }
5313           else
5314             {
5315               if (AOP_TYPE (left) == AOP_ACC)
5316                 {
5317                   emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
5318                 }
5319               else
5320                 {
5321                   _moveA (aopGet (AOP (right), offset, FALSE));
5322                   emit2 ("xor a,%s",
5323                             aopGet (AOP (left), offset, FALSE));
5324                   aopPut (AOP (result), "a", offset);
5325                 }
5326             }
5327         }
5328     }
5329   else
5330     {
5331       // left & result in different registers
5332       if (AOP_TYPE (result) == AOP_CRY)
5333         {
5334           wassertl (0, "Result of XOR is in a bit");
5335         }
5336       else
5337         for (; (size--); offset++)
5338           {
5339             // normal case
5340             // result = left & right
5341             if (AOP_TYPE (right) == AOP_LIT)
5342               {
5343                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5344                   {
5345                     aopPut (AOP (result),
5346                             aopGet (AOP (left), offset, FALSE),
5347                             offset);
5348                     continue;
5349                   }
5350               }
5351             // faster than result <- left, anl result,right
5352             // and better if result is SFR
5353             if (AOP_TYPE (left) == AOP_ACC) 
5354               {
5355                 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
5356               }
5357             else
5358               {
5359                 _moveA (aopGet (AOP (right), offset, FALSE));
5360                 emit2 ("xor a,%s",
5361                           aopGet (AOP (left), offset, FALSE));
5362               }
5363             aopPut (AOP (result), "a", offset);
5364           }
5365     }
5366
5367 release:
5368   freeAsmop (left, NULL, ic);
5369   freeAsmop (right, NULL, ic);
5370   freeAsmop (result, NULL, ic);
5371 }
5372
5373 /*-----------------------------------------------------------------*/
5374 /* genInline - write the inline code out                           */
5375 /*-----------------------------------------------------------------*/
5376 static void
5377 genInline (iCode * ic)
5378 {
5379   char *buffer, *bp, *bp1;
5380
5381   _G.lines.isInline += (!options.asmpeep);
5382
5383   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5384   strcpy (buffer, IC_INLINE (ic));
5385
5386   /* emit each line as a code */
5387   while (*bp)
5388     {
5389       if (*bp == '\n')
5390         {
5391           *bp++ = '\0';
5392           emit2 (bp1);
5393           bp1 = bp;
5394         }
5395       else
5396         {
5397           if (*bp == ':')
5398             {
5399               bp++;
5400               *bp = '\0';
5401               bp++;
5402               emit2 (bp1);
5403               bp1 = bp;
5404             }
5405           else
5406             bp++;
5407         }
5408     }
5409   if (bp1 != bp)
5410     emit2 (bp1);
5411   _G.lines.isInline -= (!options.asmpeep);
5412
5413 }
5414
5415 /*-----------------------------------------------------------------*/
5416 /* genRRC - rotate right with carry                                */
5417 /*-----------------------------------------------------------------*/
5418 static void
5419 genRRC (iCode * ic)
5420 {
5421   wassert (0);
5422 }
5423
5424 /*-----------------------------------------------------------------*/
5425 /* genRLC - generate code for rotate left with carry               */
5426 /*-----------------------------------------------------------------*/
5427 static void
5428 genRLC (iCode * ic)
5429 {
5430   wassert (0);
5431 }
5432
5433 /*-----------------------------------------------------------------*/
5434 /* genGetHbit - generates code get highest order bit               */
5435 /*-----------------------------------------------------------------*/
5436 static void
5437 genGetHbit (iCode * ic)
5438 {
5439   operand *left, *result;
5440   left = IC_LEFT (ic);
5441   result = IC_RESULT (ic);
5442
5443   aopOp (left, ic, FALSE, FALSE);
5444   aopOp (result, ic, FALSE, FALSE);
5445
5446   /* get the highest order byte into a */
5447   emit2("ld a,%s", aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
5448
5449   if (AOP_TYPE (result) == AOP_CRY)
5450     {
5451       emit2 ("rl a");
5452       outBitC (result);
5453     }
5454   else
5455     {
5456       emit2 ("rlc a");
5457       emit2 ("and a,!one");
5458       outAcc (result);
5459     }
5460
5461
5462   freeAsmop (left, NULL, ic);
5463   freeAsmop (result, NULL, ic);
5464 }
5465
5466 static void
5467 emitRsh2 (asmop *aop, int size, int is_signed)
5468 {
5469   int offset = 0;
5470
5471   while (size--)
5472     {
5473       const char *l = aopGet (aop, size, FALSE);
5474       if (offset == 0)
5475         {
5476           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
5477         }
5478       else
5479         {
5480           emit2 ("rr %s", l);
5481         }
5482       offset++;
5483     }
5484 }
5485
5486 /*-----------------------------------------------------------------*/
5487 /* shiftR2Left2Result - shift right two bytes from left to result  */
5488 /*-----------------------------------------------------------------*/
5489 static void
5490 shiftR2Left2Result (operand * left, int offl,
5491                     operand * result, int offr,
5492                     int shCount, int is_signed)
5493 {
5494   int size = 2;
5495   symbol *tlbl, *tlbl1;
5496
5497   movLeft2Result (left, offl, result, offr, 0);
5498   movLeft2Result (left, offl + 1, result, offr + 1, 0);
5499
5500   /*  if (AOP(result)->type == AOP_REG) { */
5501   
5502   tlbl = newiTempLabel (NULL);
5503   tlbl1 = newiTempLabel (NULL);
5504
5505   /* Left is already in result - so now do the shift */
5506   if (shCount <= 4)
5507     {
5508       while (shCount--)
5509         {
5510           emitRsh2 (AOP (result), size, is_signed);
5511         }
5512     }
5513   else
5514     {
5515       emit2 ("ld a,!immedbyte+1", shCount);
5516       emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5517       emitLabel (tlbl->key + 100);
5518
5519       emitRsh2 (AOP (result), size, is_signed);
5520
5521       emitLabel (tlbl1->key + 100);
5522       emit2 ("dec a");
5523       emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5524     }
5525 }
5526
5527 /*-----------------------------------------------------------------*/
5528 /* shiftL2Left2Result - shift left two bytes from left to result   */
5529 /*-----------------------------------------------------------------*/
5530 static void
5531 shiftL2Left2Result (operand * left, int offl,
5532                     operand * result, int offr, int shCount)
5533 {
5534   if (sameRegs (AOP (result), AOP (left)) &&
5535       ((offl + MSB16) == offr))
5536     {
5537       wassert (0);
5538     }
5539   else
5540     {
5541       /* Copy left into result */
5542       movLeft2Result (left, offl, result, offr, 0);
5543       movLeft2Result (left, offl + 1, result, offr + 1, 0);
5544     }
5545
5546   if (getPairId (AOP (result)) == PAIR_HL)
5547     {
5548       while (shCount--)
5549         {
5550           emit2 ("add hl,hl");
5551         }
5552     }
5553   else
5554     {
5555     int size = 2;
5556     int offset = 0;
5557     symbol *tlbl, *tlbl1;
5558     const char *l;
5559
5560     tlbl = newiTempLabel (NULL);
5561     tlbl1 = newiTempLabel (NULL);
5562
5563     if (AOP (result)->type == AOP_REG)
5564       {
5565         while (shCount--)
5566           {
5567             for (offset = 0; offset < size; offset++)
5568               {
5569                 l = aopGet (AOP (result), offset, FALSE);
5570             
5571                 if (offset == 0)
5572                   {
5573                     emit2 ("sla %s", l);
5574                   }
5575                 else
5576                   {
5577                     emit2 ("rl %s", l);
5578                   }
5579               }
5580           }
5581       }
5582     else
5583       {
5584         /* Left is already in result - so now do the shift */
5585         if (shCount > 1)
5586           {
5587             emit2 ("ld a,!immedbyte+1", shCount);
5588             emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5589             emitLabel (tlbl->key + 100);
5590           }
5591
5592         while (size--)
5593           {
5594             l = aopGet (AOP (result), offset, FALSE);
5595             
5596             if (offset == 0)
5597               {
5598                 emit2 ("sla %s", l);
5599               }
5600             else
5601               {
5602                 emit2 ("rl %s", l);
5603               }
5604             
5605             offset++;
5606           }
5607         if (shCount > 1)
5608           {
5609             emitLabel (tlbl1->key + 100);
5610             emit2 ("dec a");
5611             emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5612           }
5613       }
5614   }
5615 }
5616
5617 /*-----------------------------------------------------------------*/
5618 /* AccRol - rotate left accumulator by known count                 */
5619 /*-----------------------------------------------------------------*/
5620 static void
5621 AccRol (int shCount)
5622 {
5623   shCount &= 0x0007;            // shCount : 0..7
5624
5625 #if 0
5626   switch (shCount)
5627     {
5628     case 0:
5629       break;
5630     case 1:
5631       emit2 ("sla a");
5632       break;
5633     case 2:
5634       emit2 ("sla a");
5635       emit2 ("rl a");
5636       break;
5637     case 3:
5638       emit2 ("sla a");
5639       emit2 ("rl a");
5640       emit2 ("rl a");
5641       break;
5642     case 4:
5643       emit2 ("sla a");
5644       emit2 ("rl a");
5645       emit2 ("rl a");
5646       emit2 ("rl a");
5647       break;
5648     case 5:
5649       emit2 ("srl a");
5650       emit2 ("rr a");
5651       emit2 ("rr a");
5652       break;
5653     case 6:
5654       emit2 ("srl a");
5655       emit2 ("rr a");
5656       break;
5657     case 7:
5658       emit2 ("srl a");
5659       break;
5660     }
5661 #else
5662   switch (shCount)
5663     {
5664     case 0:
5665       break;
5666     case 1:
5667       emit2 ("rlca");
5668       break;
5669     case 2:
5670       emit2 ("rlca");
5671       emit2 ("rlca");
5672       break;
5673     case 3:
5674       emit2 ("rlca");
5675       emit2 ("rlca");
5676       emit2 ("rlca");
5677       break;
5678     case 4:
5679       emit2 ("rlca");
5680       emit2 ("rlca");
5681       emit2 ("rlca");
5682       emit2 ("rlca");
5683       break;
5684     case 5:
5685       emit2 ("rrca");
5686       emit2 ("rrca");
5687       emit2 ("rrca");
5688       break;
5689     case 6:
5690       emit2 ("rrca");
5691       emit2 ("rrca");
5692       break;
5693     case 7:
5694       emit2 ("rrca");
5695       break;
5696     }
5697 #endif
5698 }
5699
5700 /*-----------------------------------------------------------------*/
5701 /* AccLsh - left shift accumulator by known count                  */
5702 /*-----------------------------------------------------------------*/
5703 static void
5704 AccLsh (int shCount)
5705 {
5706   static const unsigned char SLMask[] =
5707     {
5708       0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
5709     };
5710
5711   if (shCount != 0)
5712     {
5713       if (shCount == 1)
5714         {
5715           emit2 ("add a,a");
5716         }
5717       else if (shCount == 2)
5718         {
5719           emit2 ("add a,a");
5720           emit2 ("add a,a");
5721         }
5722       else
5723         {
5724           /* rotate left accumulator */
5725           AccRol (shCount);
5726           /* and kill the lower order bits */
5727           emit2 ("and a,!immedbyte", SLMask[shCount]);
5728         }
5729     }
5730 }
5731
5732 /*-----------------------------------------------------------------*/
5733 /* shiftL1Left2Result - shift left one byte from left to result    */
5734 /*-----------------------------------------------------------------*/
5735 static void
5736 shiftL1Left2Result (operand * left, int offl,
5737                     operand * result, int offr, int shCount)
5738 {
5739   const char *l;
5740   l = aopGet (AOP (left), offl, FALSE);
5741   _moveA (l);
5742   /* shift left accumulator */
5743   AccLsh (shCount);
5744   aopPut (AOP (result), "a", offr);
5745 }
5746
5747
5748 /*-----------------------------------------------------------------*/
5749 /* genlshTwo - left shift two bytes by known amount != 0           */
5750 /*-----------------------------------------------------------------*/
5751 static void
5752 genlshTwo (operand * result, operand * left, int shCount)
5753 {
5754   int size = AOP_SIZE (result);
5755
5756   wassert (size == 2);
5757
5758   /* if shCount >= 8 */
5759   if (shCount >= 8)
5760     {
5761       shCount -= 8;
5762       if (size > 1)
5763         {
5764           if (shCount)
5765             {
5766               movLeft2Result (left, LSB, result, MSB16, 0);
5767               aopPut (AOP (result), "!zero", 0);
5768               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5769             }
5770           else
5771             {
5772               movLeft2Result (left, LSB, result, MSB16, 0);
5773               aopPut (AOP (result), "!zero", 0);
5774             }
5775         }
5776       else
5777         {
5778           aopPut (AOP (result), "!zero", LSB);
5779         }
5780     }
5781   /*  1 <= shCount <= 7 */
5782   else
5783     {
5784       if (size == 1)
5785         {
5786           wassert (0);
5787         }
5788       else
5789         {
5790           shiftL2Left2Result (left, LSB, result, LSB, shCount);
5791         }
5792     }
5793 }
5794
5795 /*-----------------------------------------------------------------*/
5796 /* genlshOne - left shift a one byte quantity by known count       */
5797 /*-----------------------------------------------------------------*/
5798 static void
5799 genlshOne (operand * result, operand * left, int shCount)
5800 {
5801   shiftL1Left2Result (left, LSB, result, LSB, shCount);
5802 }
5803
5804 /*-----------------------------------------------------------------*/
5805 /* genLeftShiftLiteral - left shifting by known count              */
5806 /*-----------------------------------------------------------------*/
5807 static void
5808 genLeftShiftLiteral (operand * left,
5809                      operand * right,
5810                      operand * result,
5811                      iCode * ic)
5812 {
5813   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5814   int size;
5815
5816   freeAsmop (right, NULL, ic);
5817
5818   aopOp (left, ic, FALSE, FALSE);
5819   aopOp (result, ic, FALSE, FALSE);
5820
5821   size = getSize (operandType (result));
5822
5823   /* I suppose that the left size >= result size */
5824   if (shCount == 0)
5825     {
5826       wassert (0);
5827     }
5828
5829   else if (shCount >= (size * 8)) 
5830     {
5831       while (size--)
5832         {
5833           aopPut (AOP (result), "!zero", size);
5834         }
5835     }
5836   else
5837     {
5838       switch (size)
5839         {
5840         case 1:
5841           genlshOne (result, left, shCount);
5842           break;
5843         case 2:
5844           genlshTwo (result, left, shCount);
5845           break;
5846         case 4:
5847           wassertl (0, "Shifting of longs is currently unsupported");
5848           break;
5849         default:
5850           wassert (0);
5851         }
5852     }
5853   freeAsmop (left, NULL, ic);
5854   freeAsmop (result, NULL, ic);
5855 }
5856
5857 /*-----------------------------------------------------------------*/
5858 /* genLeftShift - generates code for left shifting                 */
5859 /*-----------------------------------------------------------------*/
5860 static void
5861 genLeftShift (iCode * ic)
5862 {
5863   int size, offset;
5864   const char *l;
5865   symbol *tlbl, *tlbl1;
5866   operand *left, *right, *result;
5867
5868   right = IC_RIGHT (ic);
5869   left = IC_LEFT (ic);
5870   result = IC_RESULT (ic);
5871
5872   aopOp (right, ic, FALSE, FALSE);
5873
5874   /* if the shift count is known then do it
5875      as efficiently as possible */
5876   if (AOP_TYPE (right) == AOP_LIT)
5877     {
5878       genLeftShiftLiteral (left, right, result, ic);
5879       return;
5880     }
5881
5882   /* shift count is unknown then we have to form a loop get the loop
5883      count in B : Note: we take only the lower order byte since
5884      shifting more that 32 bits make no sense anyway, ( the largest
5885      size of an object can be only 32 bits ) */
5886   emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
5887   emit2 ("inc a");
5888   freeAsmop (right, NULL, ic);
5889   aopOp (left, ic, FALSE, FALSE);
5890   aopOp (result, ic, FALSE, FALSE);
5891
5892   /* now move the left to the result if they are not the
5893      same */
5894
5895   if (!sameRegs (AOP (left), AOP (result)))
5896     {
5897
5898       size = AOP_SIZE (result);
5899       offset = 0;
5900       while (size--)
5901         {
5902           l = aopGet (AOP (left), offset, FALSE);
5903           aopPut (AOP (result), l, offset);
5904           offset++;
5905         }
5906     }
5907
5908   tlbl = newiTempLabel (NULL);
5909   size = AOP_SIZE (result);
5910   offset = 0;
5911   tlbl1 = newiTempLabel (NULL);
5912
5913   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5914   emitLabel (tlbl->key + 100);
5915   l = aopGet (AOP (result), offset, FALSE);
5916
5917   while (size--)
5918     {
5919       l = aopGet (AOP (result), offset, FALSE);
5920
5921       if (offset == 0)
5922         {
5923           emit2 ("sla %s", l);
5924         }
5925       else
5926         {
5927           emit2 ("rl %s", l);
5928         }
5929       offset++;
5930     }
5931   emitLabel (tlbl1->key + 100);
5932   emit2 ("dec a");
5933   emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5934
5935   freeAsmop (left, NULL, ic);
5936   freeAsmop (result, NULL, ic);
5937 }
5938
5939 /*-----------------------------------------------------------------*/
5940 /* genrshOne - left shift two bytes by known amount != 0           */
5941 /*-----------------------------------------------------------------*/
5942 static void
5943 genrshOne (operand * result, operand * left, int shCount, int is_signed)
5944 {
5945   /* Errk */
5946   int size = AOP_SIZE (result);
5947   const char *l;
5948
5949   wassert (size == 1);
5950   wassert (shCount < 8);
5951
5952   l = aopGet (AOP (left), 0, FALSE);
5953
5954   if (AOP (result)->type == AOP_REG)
5955     {
5956       aopPut (AOP (result), l, 0);
5957       l = aopGet (AOP (result), 0, FALSE);
5958       while (shCount--)
5959         {
5960           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
5961         }
5962     }
5963   else
5964     {
5965       _moveA (l);
5966       while (shCount--)
5967         {
5968           emit2 ("%s a", is_signed ? "sra" : "srl");
5969         }
5970       aopPut (AOP (result), "a", 0);
5971     }
5972 }
5973
5974 /*-----------------------------------------------------------------*/
5975 /* AccRsh - right shift accumulator by known count                 */
5976 /*-----------------------------------------------------------------*/
5977 static void
5978 AccRsh (int shCount)
5979 {
5980   static const unsigned char SRMask[] =
5981     {
5982       0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
5983     };
5984
5985   if (shCount != 0)
5986     {
5987       /* rotate right accumulator */
5988       AccRol (8 - shCount);
5989       /* and kill the higher order bits */
5990       emit2 ("and a,!immedbyte", SRMask[shCount]);
5991     }
5992 }
5993
5994 /*-----------------------------------------------------------------*/
5995 /* shiftR1Left2Result - shift right one byte from left to result   */
5996 /*-----------------------------------------------------------------*/
5997 static void
5998 shiftR1Left2Result (operand * left, int offl,
5999                     operand * result, int offr,
6000                     int shCount, int sign)
6001 {
6002   _moveA (aopGet (AOP (left), offl, FALSE));
6003   if (sign)
6004     {
6005       while (shCount--)
6006         {
6007           emit2 ("%s a", sign ? "sra" : "srl");
6008         }
6009     }
6010   else
6011     {
6012       AccRsh (shCount);
6013     }
6014   aopPut (AOP (result), "a", offr);
6015 }
6016
6017 /*-----------------------------------------------------------------*/
6018 /* genrshTwo - right shift two bytes by known amount != 0          */
6019 /*-----------------------------------------------------------------*/
6020 static void
6021 genrshTwo (operand * result, operand * left,
6022            int shCount, int sign)
6023 {
6024   /* if shCount >= 8 */
6025   if (shCount >= 8)
6026     {
6027       shCount -= 8;
6028       if (shCount)
6029         {
6030           shiftR1Left2Result (left, MSB16, result, LSB,
6031                               shCount, sign);
6032         }
6033       else
6034         {
6035           movLeft2Result (left, MSB16, result, LSB, sign);
6036         }
6037       if (sign)
6038         {
6039           /* Sign extend the result */
6040           _moveA(aopGet (AOP (result), 0, FALSE));
6041           emit2 ("rlc a");
6042           emit2 ("sbc a,a");
6043
6044           aopPut (AOP (result), ACC_NAME, MSB16);
6045         }
6046       else
6047         {
6048           aopPut (AOP (result), "!zero", 1);
6049         }
6050     }
6051   /*  1 <= shCount <= 7 */
6052   else
6053     {
6054       shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6055     }
6056 }
6057
6058 /*-----------------------------------------------------------------*/
6059 /* genRightShiftLiteral - left shifting by known count              */
6060 /*-----------------------------------------------------------------*/
6061 static void
6062 genRightShiftLiteral (operand * left,
6063                       operand * right,
6064                       operand * result,
6065                       iCode * ic,
6066                       int sign)
6067 {
6068   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6069   int size;
6070
6071   freeAsmop (right, NULL, ic);
6072
6073   aopOp (left, ic, FALSE, FALSE);
6074   aopOp (result, ic, FALSE, FALSE);
6075
6076   size = getSize (operandType (result));
6077
6078   /* I suppose that the left size >= result size */
6079   if (shCount == 0)
6080     {
6081       wassert (0);
6082     }
6083
6084   else if (shCount >= (size * 8)) {
6085     const char *s;
6086     if (!SPEC_USIGN(getSpec(operandType(left)))) {
6087       _moveA(aopGet (AOP (left), 0, FALSE));
6088       emit2 ("rlc a");
6089       emit2 ("sbc a,a");
6090       s=ACC_NAME;
6091     } else {
6092       s="!zero";
6093     }
6094     while (size--)
6095       aopPut (AOP (result), s, size);
6096   }
6097   else
6098     {
6099       switch (size)
6100         {
6101         case 1:
6102           genrshOne (result, left, shCount, sign);
6103           break;
6104         case 2:
6105           genrshTwo (result, left, shCount, sign);
6106           break;
6107         case 4:
6108           wassertl (0, "Asked to shift right a long which should be a function call");
6109           break;
6110         default:
6111           wassertl (0, "Entered default case in right shift delegate");
6112         }
6113     }
6114   freeAsmop (left, NULL, ic);
6115   freeAsmop (result, NULL, ic);
6116 }
6117
6118 /*-----------------------------------------------------------------*/
6119 /* genRightShift - generate code for right shifting                */
6120 /*-----------------------------------------------------------------*/
6121 static void
6122 genRightShift (iCode * ic)
6123 {
6124   operand *right, *left, *result;
6125   sym_link *retype;
6126   int size, offset, first = 1;
6127   const char *l;
6128   bool is_signed;
6129
6130   symbol *tlbl, *tlbl1;
6131
6132   /* if signed then we do it the hard way preserve the
6133      sign bit moving it inwards */
6134   retype = getSpec (operandType (IC_RESULT (ic)));
6135
6136   is_signed = !SPEC_USIGN (retype);
6137
6138   /* signed & unsigned types are treated the same : i.e. the
6139      signed is NOT propagated inwards : quoting from the
6140      ANSI - standard : "for E1 >> E2, is equivalent to division
6141      by 2**E2 if unsigned or if it has a non-negative value,
6142      otherwise the result is implementation defined ", MY definition
6143      is that the sign does not get propagated */
6144
6145   right = IC_RIGHT (ic);
6146   left = IC_LEFT (ic);
6147   result = IC_RESULT (ic);
6148
6149   aopOp (right, ic, FALSE, FALSE);
6150
6151   /* if the shift count is known then do it
6152      as efficiently as possible */
6153   if (AOP_TYPE (right) == AOP_LIT)
6154     {
6155       genRightShiftLiteral (left, right, result, ic, is_signed);
6156       return;
6157     }
6158
6159   emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
6160   emit2 ("inc a");
6161   freeAsmop (right, NULL, ic);
6162
6163   aopOp (left, ic, FALSE, FALSE);
6164   aopOp (result, ic, FALSE, FALSE);
6165
6166   /* now move the left to the result if they are not the
6167      same */
6168   if (!sameRegs (AOP (left), AOP (result)))
6169     {
6170
6171       size = AOP_SIZE (result);
6172       offset = 0;
6173       while (size--)
6174         {
6175           l = aopGet (AOP (left), offset, FALSE);
6176           aopPut (AOP (result), l, offset);
6177           offset++;
6178         }
6179     }
6180
6181   tlbl = newiTempLabel (NULL);
6182   tlbl1 = newiTempLabel (NULL);
6183   size = AOP_SIZE (result);
6184   offset = size - 1;
6185
6186   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
6187   emitLabel (tlbl->key + 100);
6188   while (size--)
6189     {
6190       l = aopGet (AOP (result), offset--, FALSE);
6191       if (first)
6192         {
6193           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
6194           first = 0;
6195         }
6196       else
6197         {
6198           emit2 ("rr %s", l);
6199         }
6200     }
6201   emitLabel (tlbl1->key + 100);
6202   emit2 ("dec a");
6203   emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
6204
6205   freeAsmop (left, NULL, ic);
6206   freeAsmop (result, NULL, ic);
6207 }
6208
6209
6210 /*-----------------------------------------------------------------*/
6211 /* genUnpackBits - generates code for unpacking bits               */
6212 /*-----------------------------------------------------------------*/
6213 static void
6214 genUnpackBits (operand * result, int pair)
6215 {
6216   int offset = 0;       /* result byte offset */
6217   int rsize;            /* result size */
6218   int rlen = 0;         /* remaining bitfield length */
6219   sym_link *etype;      /* bitfield type information */
6220   int blen;             /* bitfield length */
6221   int bstr;             /* bitfield starting bit within byte */
6222
6223   emitDebug ("; genUnpackBits");
6224
6225   etype = getSpec (operandType (result));
6226   rsize = getSize (operandType (result));
6227   blen = SPEC_BLEN (etype);
6228   bstr = SPEC_BSTR (etype);
6229
6230   /* If the bitfield length is less than a byte */
6231   if (blen < 8)
6232     {
6233       emit2 ("ld a,!*pair", _pairs[pair].name);
6234       AccRsh (bstr);
6235       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - blen));
6236       aopPut (AOP (result), "a", offset++);
6237       goto finish;
6238     }
6239
6240   /* TODO: what if pair == PAIR_DE ? */
6241   if (getPairId (AOP (result)) == PAIR_HL)
6242     {
6243       wassertl (rsize == 2, "HL must be of size 2");
6244       emit2 ("ld a,!*hl");
6245       emit2 ("inc hl");
6246       emit2 ("ld h,!*hl");
6247       emit2 ("ld l,a");
6248       emit2 ("ld a,h");
6249       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (16 - blen));
6250       emit2 ("ld h,a");
6251       spillPair (PAIR_HL);
6252       return;
6253     }
6254
6255   /* Bit field did not fit in a byte. Copy all
6256      but the partial byte at the end.  */
6257   for (rlen=blen;rlen>=8;rlen-=8)
6258     {
6259       emit2 ("ld a,!*pair", _pairs[pair].name);
6260       aopPut (AOP (result), "a", offset++);
6261       if (rlen>8)
6262         {
6263           emit2 ("inc %s", _pairs[pair].name);
6264           _G.pairs[pair].offset++;
6265         }
6266     }
6267
6268   /* Handle the partial byte at the end */
6269   if (rlen)
6270     {
6271       emit2 ("ld a,!*pair", _pairs[pair].name);
6272       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - rlen));
6273       aopPut (AOP (result), "a", offset++);
6274     }
6275
6276 finish:
6277   if (offset < rsize)
6278     {
6279       rsize -= offset;
6280       while (rsize--)
6281         aopPut (AOP (result), "!zero", offset++);
6282     }
6283 }
6284
6285 /*-----------------------------------------------------------------*/
6286 /* genGenPointerGet -  get value from generic pointer space        */
6287 /*-----------------------------------------------------------------*/
6288 static void
6289 genGenPointerGet (operand * left,
6290                   operand * result, iCode * ic)
6291 {
6292   int size, offset;
6293   sym_link *retype = getSpec (operandType (result));
6294   int pair = PAIR_HL;
6295
6296   if (IS_GB)
6297     pair = PAIR_DE;
6298
6299   aopOp (left, ic, FALSE, FALSE);
6300   aopOp (result, ic, FALSE, FALSE);
6301
6302   size = AOP_SIZE (result);
6303
6304   if (isPair (AOP (left)) && size == 1 && !IS_BITVAR (retype))
6305     {
6306       /* Just do it */
6307       if (isPtrPair (AOP (left)))
6308         {
6309           tsprintf (buffer, sizeof(buffer), 
6310                     "!*pair", getPairName (AOP (left)));
6311           aopPut (AOP (result), buffer, 0);
6312         }
6313       else
6314         {
6315           emit2 ("ld a,!*pair", getPairName (AOP (left)));
6316           aopPut (AOP (result), "a", 0);
6317         }
6318       freeAsmop (left, NULL, ic);
6319       goto release;
6320     }
6321
6322   if (getPairId (AOP (left)) == PAIR_IY && !IS_BITVAR (retype))
6323     {
6324       /* Just do it */
6325       offset = 0;
6326       while (size--) 
6327         {
6328           char at[20];
6329           tsprintf (at, sizeof(at), "!*iyx", offset);
6330           aopPut (AOP (result), at, offset);
6331           offset++;
6332         }
6333  
6334       freeAsmop (left, NULL, ic);
6335       goto release;
6336     }
6337
6338   /* For now we always load into IY */
6339   /* if this is remateriazable */
6340   fetchPair (pair, AOP (left));
6341
6342   /* if bit then unpack */
6343   if (IS_BITVAR (retype))
6344     {
6345       genUnpackBits (result, pair);
6346       freeAsmop (left, NULL, ic);
6347       goto release;
6348       //wassert (0);
6349     }
6350   else if (getPairId (AOP (result)) == PAIR_HL)
6351     {
6352       wassertl (size == 2, "HL must be of size 2");
6353       emit2 ("ld a,!*hl");
6354       emit2 ("inc hl");
6355       emit2 ("ld h,!*hl");
6356       emit2 ("ld l,a");
6357       spillPair (PAIR_HL);
6358     }
6359   else if (getPairId (AOP (left)) == PAIR_HL && !isLastUse (ic, left))
6360     {
6361       size = AOP_SIZE (result);
6362       offset = 0;
6363
6364       while (size--)
6365         {
6366           /* PENDING: make this better */
6367           if (!IS_GB && AOP_TYPE (result) == AOP_REG)
6368             {
6369               aopPut (AOP (result), "!*hl", offset++);
6370             }
6371           else
6372             {
6373               emit2 ("ld a,!*pair", _pairs[pair].name);
6374               aopPut (AOP (result), "a", offset++);
6375             }
6376           if (size)
6377             {
6378               emit2 ("inc %s", _pairs[pair].name);
6379               _G.pairs[pair].offset++;
6380             }
6381         }
6382       /* Fixup HL back down */
6383       for (size = AOP_SIZE (result)-1; size; size--)
6384         {
6385           emit2 ("dec %s", _pairs[pair].name);
6386         }
6387     }
6388   else
6389     {
6390       size = AOP_SIZE (result);
6391       offset = 0;
6392
6393       while (size--)
6394         {
6395           /* PENDING: make this better */
6396           if (!IS_GB && 
6397               (AOP_TYPE (result) == AOP_REG || AOP_TYPE (result) == AOP_HLREG))
6398             {
6399               aopPut (AOP (result), "!*hl", offset++);
6400             }
6401           else
6402             {
6403               emit2 ("ld a,!*pair", _pairs[pair].name);
6404               aopPut (AOP (result), "a", offset++);
6405             }
6406           if (size)
6407             {
6408               emit2 ("inc %s", _pairs[pair].name);
6409               _G.pairs[pair].offset++;
6410             }
6411         }
6412     }
6413
6414   freeAsmop (left, NULL, ic);
6415
6416 release:
6417   freeAsmop (result, NULL, ic);
6418 }
6419
6420 /*-----------------------------------------------------------------*/
6421 /* genPointerGet - generate code for pointer get                   */
6422 /*-----------------------------------------------------------------*/
6423 static void
6424 genPointerGet (iCode * ic)
6425 {
6426   operand *left, *result;
6427   sym_link *type, *etype;
6428
6429   left = IC_LEFT (ic);
6430   result = IC_RESULT (ic);
6431
6432   /* depending on the type of pointer we need to
6433      move it to the correct pointer register */
6434   type = operandType (left);
6435   etype = getSpec (type);
6436
6437   genGenPointerGet (left, result, ic);
6438 }
6439
6440 bool
6441 isRegOrLit (asmop * aop)
6442 {
6443   if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD || aop->type == AOP_HLREG)
6444     return TRUE;
6445   return FALSE;
6446 }
6447
6448
6449 /*-----------------------------------------------------------------*/
6450 /* genPackBits - generates code for packed bit storage             */
6451 /*-----------------------------------------------------------------*/
6452 static void
6453 genPackBits (sym_link * etype,
6454              operand * right,
6455              int pair,
6456              iCode *ic)
6457 {
6458   int offset = 0;       /* source byte offset */
6459   int rlen = 0;         /* remaining bitfield length */
6460   int blen;             /* bitfield length */
6461   int bstr;             /* bitfield starting bit within byte */
6462   int litval;           /* source literal value (if AOP_LIT) */
6463   unsigned char mask;   /* bitmask within current byte */
6464   int extraPair;        /* a tempory register */
6465   bool needPopExtra=0;  /* need to restore original value of temp reg */
6466
6467   emitDebug (";     genPackBits","");
6468
6469   blen = SPEC_BLEN (etype);
6470   bstr = SPEC_BSTR (etype);
6471
6472   /* If the bitfield length is less than a byte */
6473   if (blen < 8)
6474     {
6475       mask = ((unsigned char) (0xFF << (blen + bstr)) |
6476               (unsigned char) (0xFF >> (8 - bstr)));
6477
6478       if (AOP_TYPE (right) == AOP_LIT)
6479         {
6480           /* Case with a bitfield length <8 and literal source
6481           */
6482           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6483           litval <<= bstr;
6484           litval &= (~mask) & 0xff;
6485           emit2 ("ld a,!*pair", _pairs[pair].name);
6486           if ((mask|litval)!=0xff)
6487             emit2 ("and a,!immedbyte", mask);
6488           if (litval)
6489             emit2 ("or a,!immedbyte", litval);
6490           emit2 ("ld !*pair,a", _pairs[pair].name);
6491           return;
6492         }
6493       else
6494         {
6495           /* Case with a bitfield length <8 and arbitrary source
6496           */
6497           _moveA (aopGet (AOP (right), 0, FALSE));
6498           /* shift and mask source value */
6499           AccLsh (bstr);
6500           emit2 ("and a,!immedbyte", (~mask) & 0xff);
6501
6502           extraPair = getFreePairId(ic);
6503           if (extraPair == PAIR_INVALID)
6504             {
6505               extraPair = PAIR_BC;
6506               if (getPairId (AOP (right)) != PAIR_BC
6507                   || !isLastUse (ic, right))
6508                 {
6509                   _push (extraPair);
6510                   needPopExtra = 1;
6511                 }
6512             }
6513           emit2 ("ld %s,a", _pairs[extraPair].l);
6514           emit2 ("ld a,!*pair", _pairs[pair].name);
6515
6516           emit2 ("and a,!immedbyte", mask);
6517           emit2 ("or a,%s", _pairs[extraPair].l);
6518           emit2 ("ld !*pair,a", _pairs[pair].name);
6519           if (needPopExtra)
6520             _pop (extraPair);
6521           return;
6522         }
6523     }
6524
6525   /* Bit length is greater than 7 bits. In this case, copy  */
6526   /* all except the partial byte at the end                 */
6527   for (rlen=blen;rlen>=8;rlen-=8)
6528     {
6529       emit2 ("ld a,%s", aopGet (AOP (right), offset++, FALSE) );
6530       emit2 ("ld !*pair,a", _pairs[pair].name);
6531       if (rlen>8)
6532         {
6533           emit2 ("inc %s", _pairs[pair].name);
6534           _G.pairs[pair].offset++;
6535         }
6536     }
6537
6538   /* If there was a partial byte at the end */
6539   if (rlen)
6540     {
6541       mask = (((unsigned char) -1 << rlen) & 0xff);
6542       
6543       if (AOP_TYPE (right) == AOP_LIT)
6544         {
6545           /* Case with partial byte and literal source
6546           */
6547           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6548           litval >>= (blen-rlen);
6549           litval &= (~mask) & 0xff;
6550           emit2 ("ld a,!*pair", _pairs[pair].name);
6551           if ((mask|litval)!=0xff)
6552             emit2 ("and a,!immedbyte", mask);
6553           if (litval)
6554             emit2 ("or a,!immedbyte", litval);
6555         }
6556       else
6557         {
6558           /* Case with partial byte and arbitrary source
6559           */
6560           _moveA (aopGet (AOP (right), offset++, FALSE));
6561           emit2 ("and a,!immedbyte", (~mask) & 0xff);
6562
6563           extraPair = getFreePairId(ic);
6564           if (extraPair == PAIR_INVALID)
6565             {
6566               extraPair = getPairId (AOP (right));
6567               if (!isLastUse (ic, right) || (extraPair == PAIR_INVALID))
6568                 extraPair = PAIR_BC;
6569
6570               if (getPairId (AOP (right)) != PAIR_BC
6571                   || !isLastUse (ic, right))
6572                 {
6573                   _push (extraPair);
6574                   needPopExtra = 1;
6575                 }
6576             }
6577           emit2 ("ld %s,a", _pairs[extraPair].l);
6578           emit2 ("ld a,!*pair", _pairs[pair].name);
6579
6580           emit2 ("and a,!immedbyte", mask);
6581           emit2 ("or a,%s", _pairs[extraPair].l);
6582           if (needPopExtra)
6583             _pop (extraPair);
6584
6585         }
6586       emit2 ("ld !*pair,a", _pairs[pair].name);
6587     }
6588 }
6589
6590
6591 /*-----------------------------------------------------------------*/
6592 /* genGenPointerSet - stores the value into a pointer location        */
6593 /*-----------------------------------------------------------------*/
6594 static void
6595 genGenPointerSet (operand * right,
6596                   operand * result, iCode * ic)
6597 {
6598   int size, offset;
6599   sym_link *retype = getSpec (operandType (right));
6600   sym_link *letype = getSpec (operandType (result));
6601   PAIR_ID pairId = PAIR_HL;
6602   bool isBitvar;
6603   
6604   aopOp (result, ic, FALSE, FALSE);
6605   aopOp (right, ic, FALSE, FALSE);
6606
6607   if (IS_GB)
6608     pairId = PAIR_DE;
6609
6610   size = AOP_SIZE (right);
6611
6612   isBitvar = IS_BITVAR(retype) || IS_BITVAR(letype);
6613   emitDebug("; isBitvar = %d", isBitvar);
6614
6615   /* Handle the exceptions first */
6616   if (isPair (AOP (result)) && size == 1 && !isBitvar)
6617     {
6618       /* Just do it */
6619       const char *l = aopGet (AOP (right), 0, FALSE);
6620       const char *pair = getPairName (AOP (result));
6621       if (canAssignToPtr (l) && isPtr (pair))
6622         {
6623           emit2 ("ld !*pair,%s", pair, l);
6624         }
6625       else
6626         {
6627           _moveA (l);
6628           emit2 ("ld !*pair,a", pair);
6629         }
6630       goto release;
6631     }
6632   
6633   if ( getPairId( AOP (result)) == PAIR_IY && !isBitvar)
6634     {
6635       /* Just do it */
6636       const char *l = aopGet (AOP (right), 0, FALSE);
6637
6638       offset = 0;
6639       while (size--) 
6640         {
6641           if (canAssignToPtr (l))
6642             {
6643               emit2 ("ld !*iyx,%s", offset, aopGet( AOP(right), offset, FALSE));
6644             }
6645           else
6646             {
6647               _moveA (aopGet (AOP (right), offset, FALSE));
6648               emit2 ("ld !*iyx,a", offset);
6649             }
6650           offset++;
6651         }
6652       goto release;
6653     }
6654   else if (getPairId (AOP (result)) == PAIR_HL && !isLastUse (ic, result)
6655            && !isBitvar)
6656     {
6657       offset = 0;
6658
6659       while (size--)
6660         {
6661           const char *l = aopGet (AOP (right), offset, FALSE);
6662           if (isRegOrLit (AOP (right)) && !IS_GB)
6663             {
6664               emit2 ("ld !*pair,%s", _pairs[PAIR_HL].name, l);
6665             }
6666           else
6667             {
6668               _moveA (l);
6669               emit2 ("ld !*pair,a", _pairs[PAIR_HL].name);
6670             }
6671           if (size)
6672             {
6673               emit2 ("inc %s", _pairs[PAIR_HL].name);
6674               _G.pairs[PAIR_HL].offset++;
6675             }
6676           offset++;
6677         }
6678
6679       /* Fixup HL back down */
6680       for (size = AOP_SIZE (right)-1; size; size--)
6681         {
6682           emit2 ("dec %s", _pairs[PAIR_HL].name);
6683         }
6684       goto release;
6685     }
6686
6687   /* if the operand is already in dptr
6688      then we do nothing else we move the value to dptr */
6689   if (AOP_TYPE (result) != AOP_STR)
6690     {
6691       fetchPair (pairId, AOP (result));
6692     }
6693   /* so hl know contains the address */
6694   freeAsmop (result, NULL, ic);
6695
6696   /* if bit then unpack */
6697   if (isBitvar)
6698     {
6699       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, pairId, ic);
6700       goto release;
6701       //wassert (0);
6702     }
6703   else
6704     {
6705       offset = 0;
6706
6707       while (size--)
6708         {
6709           const char *l = aopGet (AOP (right), offset, FALSE);
6710           if (isRegOrLit (AOP (right)) && !IS_GB)
6711             {
6712               emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
6713             }
6714           else
6715             {
6716               _moveA (l);
6717               emit2 ("ld !*pair,a", _pairs[pairId].name);
6718             }
6719           if (size)
6720             {
6721               emit2 ("inc %s", _pairs[pairId].name);
6722               _G.pairs[pairId].offset++;
6723             }
6724           offset++;
6725         }
6726     }
6727 release:
6728   freeAsmop (right, NULL, ic);
6729 }
6730
6731 /*-----------------------------------------------------------------*/
6732 /* genPointerSet - stores the value into a pointer location        */
6733 /*-----------------------------------------------------------------*/
6734 static void
6735 genPointerSet (iCode * ic)
6736 {
6737   operand *right, *result;
6738   sym_link *type, *etype;
6739
6740   right = IC_RIGHT (ic);
6741   result = IC_RESULT (ic);
6742
6743   /* depending on the type of pointer we need to
6744      move it to the correct pointer register */
6745   type = operandType (result);
6746   etype = getSpec (type);
6747
6748   genGenPointerSet (right, result, ic);
6749 }
6750
6751 /*-----------------------------------------------------------------*/
6752 /* genIfx - generate code for Ifx statement                        */
6753 /*-----------------------------------------------------------------*/
6754 static void
6755 genIfx (iCode * ic, iCode * popIc)
6756 {
6757   operand *cond = IC_COND (ic);
6758   int isbit = 0;
6759
6760   aopOp (cond, ic, FALSE, TRUE);
6761
6762   /* get the value into acc */
6763   if (AOP_TYPE (cond) != AOP_CRY)
6764     _toBoolean (cond);
6765   else
6766     isbit = 1;
6767   /* the result is now in the accumulator */
6768   freeAsmop (cond, NULL, ic);
6769
6770   /* if there was something to be popped then do it */
6771   if (popIc)
6772     genIpop (popIc);
6773
6774   /* if the condition is  a bit variable */
6775   if (isbit && IS_ITEMP (cond) &&
6776       SPIL_LOC (cond))
6777     genIfxJump (ic, SPIL_LOC (cond)->rname);
6778   else if (isbit && !IS_ITEMP (cond))
6779     genIfxJump (ic, OP_SYMBOL (cond)->rname);
6780   else
6781     genIfxJump (ic, "a");
6782
6783   ic->generated = 1;
6784 }
6785
6786 /*-----------------------------------------------------------------*/
6787 /* genAddrOf - generates code for address of                       */
6788 /*-----------------------------------------------------------------*/
6789 static void
6790 genAddrOf (iCode * ic)
6791 {
6792   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
6793
6794   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
6795
6796   /* if the operand is on the stack then we
6797      need to get the stack offset of this
6798      variable */
6799   if (IS_GB)
6800     {
6801       if (sym->onStack)
6802         {
6803           spillCached ();
6804           if (sym->stack <= 0)
6805             {
6806               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset);
6807             }
6808           else
6809             {
6810               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
6811             }
6812           commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
6813         }
6814       else
6815         {
6816           emit2 ("ld de,!hashedstr", sym->rname);
6817           commitPair (AOP (IC_RESULT (ic)), PAIR_DE);
6818         }
6819     }
6820   else
6821     {
6822       spillCached ();
6823       if (sym->onStack)
6824         {
6825           /* if it has an offset  then we need to compute it */
6826           if (sym->stack > 0)
6827             emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
6828           else
6829             emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset);
6830           emit2 ("add hl,sp");
6831         }
6832       else
6833         {
6834           emit2 ("ld hl,!hashedstr", sym->rname);
6835         }
6836       commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
6837     }
6838   freeAsmop (IC_RESULT (ic), NULL, ic);
6839 }
6840
6841 /*-----------------------------------------------------------------*/
6842 /* genAssign - generate code for assignment                        */
6843 /*-----------------------------------------------------------------*/
6844 static void
6845 genAssign (iCode * ic)
6846 {
6847   operand *result, *right;
6848   int size, offset;
6849   unsigned long lit = 0L;
6850
6851   result = IC_RESULT (ic);
6852   right = IC_RIGHT (ic);
6853
6854   /* Dont bother assigning if they are the same */
6855   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
6856     {
6857       emitDebug ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
6858       return;
6859     }
6860
6861   aopOp (right, ic, FALSE, FALSE);
6862   aopOp (result, ic, TRUE, FALSE);
6863
6864   /* if they are the same registers */
6865   if (sameRegs (AOP (right), AOP (result)))
6866     {
6867       emitDebug ("; (registers are the same)");
6868       goto release;
6869     }
6870
6871   /* if the result is a bit */
6872   if (AOP_TYPE (result) == AOP_CRY)
6873     {
6874       wassertl (0, "Tried to assign to a bit");
6875     }
6876
6877   /* general case */
6878   size = AOP_SIZE (result);
6879   offset = 0;
6880
6881   if (AOP_TYPE (right) == AOP_LIT)
6882     {
6883       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6884     }
6885
6886   if (isPair (AOP (result)))
6887     {
6888       fetchPairLong (getPairId (AOP (result)), AOP (right), ic, LSB);
6889     }
6890   else if ((size > 1) &&
6891            (AOP_TYPE (result) != AOP_REG) &&
6892            (AOP_TYPE (right) == AOP_LIT) &&
6893            !IS_FLOAT (operandType (right)) &&
6894            (lit < 256L))
6895     {
6896       bool fXored = FALSE;
6897       offset = 0;
6898       /* Work from the top down.
6899          Done this way so that we can use the cached copy of 0
6900          in A for a fast clear */
6901       while (size--)
6902         {
6903           if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
6904             {
6905               if (!fXored && size > 1)
6906                 {
6907                   emit2 ("xor a,a");
6908                   fXored = TRUE;
6909                 }
6910               if (fXored)
6911                 {
6912                   aopPut (AOP (result), "a", offset);
6913                 }
6914               else
6915                 {
6916                   aopPut (AOP (result), "!zero", offset);
6917                 }
6918             }
6919           else
6920             aopPut (AOP (result),
6921                     aopGet (AOP (right), offset, FALSE),
6922                     offset);
6923           offset++;
6924         }
6925     }
6926   else if (size == 2 && AOP_TYPE (right) == AOP_IY)
6927     {
6928       emit2 ("ld hl,(%s)", AOP (right)->aopu.aop_dir);
6929       aopPut (AOP (result), "l", LSB);
6930       aopPut (AOP (result), "h", MSB16);
6931     }
6932   else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
6933     {
6934       /* Special case.  Load into a and d, then load out. */
6935       _moveA (aopGet (AOP (right), 0, FALSE));
6936       emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
6937       aopPut (AOP (result), "a", 0);
6938       aopPut (AOP (result), "e", 1);
6939     }
6940   else if (size == 4 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
6941     {
6942       /* Special case - simple memcpy */
6943       aopGet (AOP (right), LSB, FALSE);
6944       emit2 ("ld d,h");
6945       emit2 ("ld e,l");
6946       aopGet (AOP (result), LSB, FALSE);
6947
6948       while (size--)
6949         {
6950           emit2 ("ld a,(de)");
6951           /* Peephole will optimise this. */
6952           emit2 ("ld (hl),a");
6953
6954           if (size != 0)
6955             {
6956               emit2 ("inc hl");
6957               emit2 ("inc de");
6958             }
6959         }
6960       spillPair (PAIR_HL);
6961     }
6962   else
6963     {
6964       while (size--)
6965         {
6966           /* PENDING: do this check better */
6967           if (IS_GB && requiresHL (AOP (right)) && requiresHL (AOP (result)))
6968             {
6969               _moveA (aopGet (AOP (right), offset, FALSE));
6970               aopPut (AOP (result), "a", offset);
6971             }
6972           else
6973             aopPut (AOP (result),
6974                     aopGet (AOP (right), offset, FALSE),
6975                     offset);
6976           offset++;
6977         }
6978     }
6979
6980 release:
6981   freeAsmop (right, NULL, ic);
6982   freeAsmop (result, NULL, ic);
6983 }
6984
6985 /*-----------------------------------------------------------------*/
6986 /* genJumpTab - genrates code for jump table                       */
6987 /*-----------------------------------------------------------------*/
6988 static void
6989 genJumpTab (iCode * ic)
6990 {
6991   symbol *jtab;
6992   const char *l;
6993
6994   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
6995   /* get the condition into accumulator */
6996   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
6997   if (!IS_GB)
6998     emit2 ("push de");
6999   emit2 ("ld e,%s", l);
7000   emit2 ("ld d,!zero");
7001   jtab = newiTempLabel (NULL);
7002   spillCached ();
7003   emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
7004   emit2 ("add hl,de");
7005   emit2 ("add hl,de");
7006   emit2 ("add hl,de");
7007   freeAsmop (IC_JTCOND (ic), NULL, ic);
7008   if (!IS_GB)
7009     emit2 ("pop de");
7010   emit2 ("jp !*hl");
7011   emitLabel (jtab->key + 100);
7012   /* now generate the jump labels */
7013   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7014        jtab = setNextItem (IC_JTLABELS (ic)))
7015     emit2 ("jp !tlabel", jtab->key + 100);
7016 }
7017
7018 /*-----------------------------------------------------------------*/
7019 /* genCast - gen code for casting                                  */
7020 /*-----------------------------------------------------------------*/
7021 static void
7022 genCast (iCode * ic)
7023 {
7024   operand *result = IC_RESULT (ic);
7025   sym_link *rtype = operandType (IC_RIGHT (ic));
7026   operand *right = IC_RIGHT (ic);
7027   int size, offset;
7028
7029   /* if they are equivalent then do nothing */
7030   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7031     return;
7032
7033   aopOp (right, ic, FALSE, FALSE);
7034   aopOp (result, ic, FALSE, FALSE);
7035
7036   /* if the result is a bit */
7037   if (AOP_TYPE (result) == AOP_CRY)
7038     {
7039       wassertl (0, "Tried to cast to a bit");
7040     }
7041
7042   /* if they are the same size : or less */
7043   if (AOP_SIZE (result) <= AOP_SIZE (right))
7044     {
7045
7046       /* if they are in the same place */
7047       if (sameRegs (AOP (right), AOP (result)))
7048         goto release;
7049
7050       /* if they in different places then copy */
7051       size = AOP_SIZE (result);
7052       offset = 0;
7053       while (size--)
7054         {
7055           aopPut (AOP (result),
7056                   aopGet (AOP (right), offset, FALSE),
7057                   offset);
7058           offset++;
7059         }
7060       goto release;
7061     }
7062
7063   /* So we now know that the size of destination is greater
7064      than the size of the source */
7065   /* we move to result for the size of source */
7066   size = AOP_SIZE (right);
7067   offset = 0;
7068   while (size--)
7069     {
7070       aopPut (AOP (result),
7071               aopGet (AOP (right), offset, FALSE),
7072               offset);
7073       offset++;
7074     }
7075
7076   /* now depending on the sign of the destination */
7077   size = AOP_SIZE (result) - AOP_SIZE (right);
7078   /* Unsigned or not an integral type - right fill with zeros */
7079   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7080     {
7081       while (size--)
7082         aopPut (AOP (result), "!zero", offset++);
7083     }
7084   else
7085     {
7086       /* we need to extend the sign :{ */
7087         const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
7088                         FALSE);
7089       _moveA (l);
7090       emit2 ("rla ");
7091       emit2 ("sbc a,a");
7092       while (size--)
7093         aopPut (AOP (result), "a", offset++);
7094     }
7095
7096 release:
7097   freeAsmop (right, NULL, ic);
7098   freeAsmop (result, NULL, ic);
7099 }
7100
7101 /*-----------------------------------------------------------------*/
7102 /* genReceive - generate code for a receive iCode                  */
7103 /*-----------------------------------------------------------------*/
7104 static void
7105 genReceive (iCode * ic)
7106 {
7107   if (isOperandInFarSpace (IC_RESULT (ic)) &&
7108       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
7109        IS_TRUE_SYMOP (IC_RESULT (ic))))
7110     {
7111       wassert (0);
7112     }
7113   else
7114     {
7115         // PENDING: HACK
7116         int size;
7117         int i;
7118
7119         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
7120         size = AOP_SIZE(IC_RESULT(ic));
7121
7122         for (i = 0; i < size; i++) {
7123             aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
7124         }
7125     }
7126
7127   freeAsmop (IC_RESULT (ic), NULL, ic);
7128 }
7129
7130 /*-----------------------------------------------------------------*/
7131 /* genDummyRead - generate code for dummy read of volatiles        */
7132 /*-----------------------------------------------------------------*/
7133 static void
7134 genDummyRead (iCode * ic)
7135 {
7136   operand *right;
7137   int size, offset;
7138
7139   right = IC_RIGHT (ic);
7140   aopOp (right, ic, FALSE, FALSE);
7141   
7142   /* general case */
7143   size = AOP_SIZE (right);
7144   offset = 0;
7145
7146   while (size--)
7147     {
7148       _moveA (aopGet (AOP (right), offset, FALSE));
7149       offset++;
7150     }
7151
7152   freeAsmop (right, NULL, ic);
7153 }
7154
7155 enum
7156   {
7157     /** Maximum number of bytes to emit per line. */
7158     DBEMIT_MAX_RUN = 8
7159   };
7160
7161 /** Context for the byte output chunker. */
7162 typedef struct
7163 {
7164   unsigned char buffer[DBEMIT_MAX_RUN];
7165   int pos;
7166 } DBEMITCTX;
7167
7168
7169 /** Flushes a byte chunker by writing out all in the buffer and
7170     reseting. 
7171 */
7172 static void
7173 _dbFlush(DBEMITCTX *self)
7174 {
7175   char line[256];
7176
7177   if (self->pos > 0)
7178     {
7179       int i;
7180       sprintf(line, ".db 0x%02X", self->buffer[0]);
7181
7182       for (i = 1; i < self->pos; i++)
7183         {
7184           sprintf(line + strlen(line), ", 0x%02X", self->buffer[i]);
7185         }
7186       emit2(line);
7187     }
7188   self->pos = 0;
7189 }
7190
7191 /** Write out another byte, buffering until a decent line is
7192     generated.
7193 */
7194 static void
7195 _dbEmit(DBEMITCTX *self, int c)
7196 {
7197   if (self->pos == DBEMIT_MAX_RUN)
7198     {
7199       _dbFlush(self);
7200     }
7201   self->buffer[self->pos++] = c;
7202 }
7203
7204 /** Context for a simple run length encoder. */
7205 typedef struct
7206 {
7207   unsigned last;
7208   unsigned char buffer[128];
7209   int pos;
7210   /** runLen may be equivalent to pos. */
7211   int runLen;
7212 } RLECTX;
7213
7214 enum
7215   {
7216     RLE_CHANGE_COST = 4,
7217     RLE_MAX_BLOCK = 127
7218   };
7219
7220 /** Flush the buffer of a run length encoder by writing out the run or
7221     data that it currently contains.
7222 */
7223 static void
7224 _rleCommit(RLECTX *self)
7225 {
7226   int i;
7227   if (self->pos != 0)
7228     {
7229       DBEMITCTX db;
7230       memset(&db, 0, sizeof(db));
7231           
7232       emit2(".db %u", self->pos);
7233       
7234       for (i = 0; i < self->pos; i++)
7235         {
7236           _dbEmit(&db, self->buffer[i]);
7237         }
7238       _dbFlush(&db);
7239     }
7240   /* Reset */
7241   self->pos = 0;
7242 }
7243
7244 /* Encoder design:
7245    Can get either a run or a block of random stuff.
7246    Only want to change state if a good run comes in or a run ends.
7247    Detecting run end is easy.
7248    Initial state?
7249
7250    Say initial state is in run, len zero, last zero.  Then if you get a
7251    few zeros then something else then a short run will be output.
7252    Seems OK.  While in run mode, keep counting.  While in random mode,
7253    keep a count of the run.  If run hits margin, output all up to run,
7254    restart, enter run mode.
7255 */
7256
7257 /** Add another byte into the run length encoder, flushing as
7258     required.  The run length encoder uses the Amiga IFF style, where
7259     a block is prefixed by its run length.  A positive length means
7260     the next n bytes pass straight through.  A negative length means
7261     that the next byte is repeated -n times.  A zero terminates the
7262     chunks.
7263 */
7264 static void
7265 _rleAppend(RLECTX *self, int c)
7266 {
7267   int i;
7268
7269   if (c != self->last)
7270     {
7271       /* The run has stopped.  See if it is worthwhile writing it out
7272          as a run.  Note that the random data comes in as runs of
7273          length one.
7274       */
7275       if (self->runLen > RLE_CHANGE_COST)
7276         {
7277           /* Yes, worthwhile. */
7278           /* Commit whatever was in the buffer. */
7279           _rleCommit(self);
7280           emit2("!db !immed-%u,!immedbyte", self->runLen, self->last);
7281         }
7282       else
7283         {
7284           /* Not worthwhile.  Append to the end of the random list. */
7285           for (i = 0; i < self->runLen; i++)
7286             {
7287               if (self->pos >= RLE_MAX_BLOCK)
7288                 {
7289                   /* Commit. */
7290                   _rleCommit(self);
7291                 }
7292               self->buffer[self->pos++] = self->last;
7293             }
7294         }
7295       self->runLen = 1;
7296       self->last = c;
7297     }
7298   else
7299     {
7300       if (self->runLen >= RLE_MAX_BLOCK)
7301         {
7302           /* Commit whatever was in the buffer. */
7303           _rleCommit(self);
7304
7305           emit2 ("!db !immed-%u,!immedbyte", self->runLen, self->last);
7306           self->runLen = 0;
7307         }
7308       self->runLen++;
7309     }
7310 }
7311
7312 static void
7313 _rleFlush(RLECTX *self)
7314 {
7315   _rleAppend(self, -1);
7316   _rleCommit(self);
7317   self->pos = 0;
7318   self->last = 0;
7319   self->runLen = 0;
7320 }
7321
7322 /** genArrayInit - Special code for initialising an array with constant
7323    data.
7324 */
7325 static void
7326 genArrayInit (iCode * ic)
7327 {
7328   literalList *iLoop;
7329   int         ix;
7330   int         elementSize = 0, eIndex, i;
7331   unsigned    val, lastVal;
7332   sym_link    *type;
7333   RLECTX      rle;
7334
7335   memset(&rle, 0, sizeof(rle));
7336
7337   aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
7338
7339   _saveRegsForCall(ic, 0);
7340
7341   fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
7342   emit2 ("call __initrleblock");
7343     
7344   type = operandType(IC_LEFT(ic));
7345     
7346   if (type && type->next)
7347     {
7348       elementSize = getSize(type->next);
7349     }
7350   else
7351     {
7352       wassertl (0, "Can't determine element size in genArrayInit.");
7353     }
7354
7355   iLoop = IC_ARRAYILIST(ic);
7356   lastVal = (unsigned)-1;
7357
7358   /* Feed all the bytes into the run length encoder which will handle
7359      the actual output.
7360      This works well for mixed char data, and for random int and long
7361      data.
7362   */
7363   while (iLoop)
7364     {
7365       ix = iLoop->count;
7366
7367       if (ix != 0)
7368         {
7369           for (i = 0; i < ix; i++)
7370             {
7371               for (eIndex = 0; eIndex < elementSize; eIndex++)
7372                 {
7373                   val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
7374                   _rleAppend(&rle, val);
7375                 }
7376             }
7377         }
7378         
7379       iLoop = iLoop->next;
7380     }
7381
7382   _rleFlush(&rle);
7383   /* Mark the end of the run. */
7384   emit2(".db 0");
7385
7386   _restoreRegsAfterCall();
7387
7388   spillCached ();
7389
7390   freeAsmop (IC_LEFT(ic), NULL, ic);
7391 }
7392
7393 static void
7394 _swap (PAIR_ID one, PAIR_ID two)
7395 {
7396   if ((one == PAIR_DE && two == PAIR_HL) || (one == PAIR_HL && two == PAIR_DE))
7397     {
7398       emit2 ("ex de,hl");
7399     }
7400   else
7401     {
7402       emit2 ("ld a,%s", _pairs[one].l);
7403       emit2 ("ld %s,%s", _pairs[one].l, _pairs[two].l);
7404       emit2 ("ld %s,a", _pairs[two].l);
7405       emit2 ("ld a,%s", _pairs[one].h);
7406       emit2 ("ld %s,%s", _pairs[one].h, _pairs[two].h);
7407       emit2 ("ld %s,a", _pairs[two].h);
7408     }
7409 }
7410
7411 /* The problem is that we may have all three pairs used and they may
7412    be needed in a different order.
7413
7414    Note: Have ex de,hl
7415
7416    Combinations:
7417      hl = hl            => unity, fine
7418      bc = bc
7419      de = de
7420
7421      hl = hl            hl = hl, swap de <=> bc
7422      bc = de
7423      de = bc
7424
7425      hl = bc            Worst case
7426      bc = de
7427      de = hl
7428      
7429      hl = bc            de = de, swap bc <=> hl
7430      bc = hl
7431      de = de
7432
7433      hl = de            Worst case
7434      bc = hl
7435      de = bc
7436
7437      hl = de            bc = bc, swap hl <=> de
7438      bc = bc
7439      de = hl
7440
7441    Break it down into:
7442     * Any pair = pair are done last
7443     * Any pair = iTemp are done last
7444     * Any swaps can be done any time
7445
7446    A worst case:
7447     push p1
7448     p1 = p2
7449     p2 = p3
7450     pop  p3
7451
7452    So how do we detect the cases?
7453    How about a 3x3 matrix?
7454         source
7455    dest x x x x
7456         x x x x
7457         x x x x (Fourth for iTemp/other)
7458
7459    First determin which mode to use by counting the number of unity and
7460    iTemp assigns.
7461      Three - any order
7462      Two - Assign the pair first, then the rest
7463      One - Swap the two, then the rest
7464      Zero - Worst case.
7465 */
7466 static void
7467 setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
7468 {
7469   PAIR_ID ids[NUM_PAIRS][NUM_PAIRS];
7470   PAIR_ID dest[3] = {
7471     PAIR_BC, PAIR_HL, PAIR_DE
7472   };
7473   int i, j, nunity = 0;
7474   memset (ids, PAIR_INVALID, sizeof (ids));
7475
7476   /* Sanity checks */
7477   wassert (nparams == 3);
7478
7479   /* First save everything that needs to be saved. */
7480   _saveRegsForCall (ic, 0);
7481
7482   /* Loading HL first means that DE is always fine. */
7483   for (i = 0; i < nparams; i++)
7484     {
7485       aopOp (pparams[i], ic, FALSE, FALSE);
7486       ids[dest[i]][getPairId (AOP (pparams[i]))] = TRUE;
7487     }
7488
7489   /* Count the number of unity or iTemp assigns. */
7490   for (i = 0; i < 3; i++) 
7491     {
7492       if (ids[dest[i]][dest[i]] == TRUE || ids[dest[i]][PAIR_INVALID] == TRUE)
7493         {
7494           nunity++;
7495         }
7496     }
7497
7498   if (nunity == 3)
7499     {
7500       /* Any order, fall through. */
7501     }
7502   else if (nunity == 2)
7503     {
7504       /* One is assigned.  Pull it out and assign. */
7505       for (i = 0; i < 3; i++)
7506         {
7507           for (j = 0; j < NUM_PAIRS; j++)
7508             {
7509               if (ids[dest[i]][j] == TRUE)
7510                 {
7511                   /* Found it.  See if it's the right one. */
7512                   if (j == PAIR_INVALID || j == dest[i])
7513                     {
7514                       /* Keep looking. */
7515                     }
7516                   else
7517                     {
7518                       fetchPair(dest[i], AOP (pparams[i]));
7519                       goto done;
7520                     }
7521                 }
7522             }
7523         }
7524     }
7525   else if (nunity == 1)
7526     {
7527       /* Find the pairs to swap. */
7528       for (i = 0; i < 3; i++)
7529         {
7530           for (j = 0; j < NUM_PAIRS; j++)
7531             {
7532               if (ids[dest[i]][j] == TRUE)
7533                 {
7534                   if (j == PAIR_INVALID || j == dest[i])
7535                     {
7536                       /* Keep looking. */
7537                     }
7538                   else
7539                     {
7540                       _swap (j, dest[i]);
7541                       goto done;
7542                     }
7543                 }
7544             }
7545         }
7546     }
7547   else
7548     {
7549       int next = getPairId (AOP (pparams[0]));
7550       emit2 ("push %s", _pairs[next].name);
7551
7552       if (next == dest[1])
7553         {
7554           fetchPair (dest[1], AOP (pparams[1]));
7555           fetchPair (dest[2], AOP (pparams[2]));
7556         }
7557       else
7558         {
7559           fetchPair (dest[2], AOP (pparams[2]));
7560           fetchPair (dest[1], AOP (pparams[1]));
7561         }
7562       emit2 ("pop %s", _pairs[dest[0]].name);
7563     }
7564  done:
7565   /* Finally pull out all of the iTemps */
7566   for (i = 0; i < 3; i++)
7567     {
7568       if (ids[dest[i]][PAIR_INVALID] == 1)
7569         {
7570           fetchPair (dest[i], AOP (pparams[i]));
7571         }
7572     }
7573 }
7574
7575 static void
7576 genBuiltInStrcpy (iCode *ic, int nParams, operand **pparams)
7577 {
7578   operand *from, *to;
7579   symbol *label;
7580   bool deInUse;
7581
7582   wassertl (nParams == 2, "Built-in strcpy must have two parameters");
7583   to = pparams[0];
7584   from = pparams[1];
7585
7586   deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
7587
7588   setupForBuiltin3 (ic, nParams, pparams);
7589
7590   label = newiTempLabel(NULL);
7591
7592   emitLabel (label->key);
7593   emit2 ("ld a,(hl)");
7594   emit2 ("ldi");
7595   emit2 ("or a");
7596   emit2 ("!shortjp nz,!tlabel ; 1", label->key);
7597
7598   freeAsmop (from, NULL, ic->next);
7599   freeAsmop (to, NULL, ic);
7600 }
7601
7602 static void
7603 genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams)
7604 {
7605   operand *from, *to, *count;
7606   bool deInUse;
7607
7608   wassertl (nParams == 3, "Built-in memcpy must have two parameters");
7609   to = pparams[2];
7610   from = pparams[1];
7611   count = pparams[0];
7612
7613   deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
7614
7615   setupForBuiltin3 (ic, nParams, pparams);
7616
7617   emit2 ("ldir");
7618
7619   freeAsmop (count, NULL, ic->next->next);
7620   freeAsmop (from, NULL, ic);
7621
7622   _restoreRegsAfterCall();
7623
7624   /* if we need assign a result value */
7625   if ((IS_ITEMP (IC_RESULT (ic)) &&
7626        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
7627         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
7628       IS_TRUE_SYMOP (IC_RESULT (ic)))
7629     {
7630       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
7631       movLeft2ResultLong (to, 0, IC_RESULT (ic), 0, 0, 2);
7632       freeAsmop (IC_RESULT (ic), NULL, ic);
7633     }
7634
7635   freeAsmop (to, NULL, ic->next);
7636 }
7637
7638 /*-----------------------------------------------------------------*/
7639 /* genBuiltIn - calls the appropriate function to  generating code */
7640 /* for a built in function                                         */
7641 /*-----------------------------------------------------------------*/
7642 static void genBuiltIn (iCode *ic)
7643 {
7644     operand *bi_parms[MAX_BUILTIN_ARGS];
7645     int nbi_parms;
7646     iCode *bi_iCode;
7647     symbol *bif;
7648
7649     /* get all the arguments for a built in function */
7650     bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
7651
7652     /* which function is it */
7653     bif = OP_SYMBOL(IC_LEFT(bi_iCode));
7654
7655     if (strcmp(bif->name,"__builtin_strcpy")==0) 
7656       {
7657         genBuiltInStrcpy(bi_iCode, nbi_parms, bi_parms);
7658       } 
7659     else if (strcmp(bif->name,"__builtin_memcpy")==0) 
7660       {
7661         genBuiltInMemcpy(bi_iCode, nbi_parms, bi_parms);
7662       } 
7663     else 
7664       {
7665         wassertl (0, "Unknown builtin function encountered");
7666       }
7667 }
7668
7669 /*-----------------------------------------------------------------*/
7670 /* genZ80Code - generate code for Z80 based controllers            */
7671 /*-----------------------------------------------------------------*/
7672 void
7673 genZ80Code (iCode * lic)
7674 {
7675   iCode *ic;
7676   int cln = 0;
7677
7678   /* Hack */
7679   if (IS_GB)
7680     {
7681       _fReturn = _gbz80_return;
7682       _fTmp = _gbz80_return;
7683     }
7684   else
7685     {
7686       _fReturn = _z80_return;
7687       _fTmp = _z80_return;
7688     }
7689
7690   _G.lines.head = _G.lines.current = NULL;
7691   
7692   /* if debug information required */
7693   if (options.debug && currFunc)
7694     {
7695       debugFile->writeFunction(currFunc);
7696       _G.lines.isDebug = 1;
7697       if (IS_STATIC (currFunc->etype))
7698         sprintf (buffer, "F%s$%s$0$0", moduleName, currFunc->name);
7699       else
7700         sprintf (buffer, "G$%s$0$0", currFunc->name);
7701       emit2 ("!labeldef", buffer);
7702       _G.lines.isDebug = 0;
7703     }
7704
7705   for (ic = lic; ic; ic = ic->next)
7706     {
7707       _G.current_iCode = ic;
7708
7709       if (ic->lineno && cln != ic->lineno)
7710         {
7711           if (options.debug)
7712             {
7713               _G.lines.isDebug = 1;
7714               sprintf (buffer, "C$%s$%d$%d$%d",
7715                         FileBaseName (ic->filename), ic->lineno,
7716                         ic->level, ic->block);
7717               emit2 ("%s !equ .", buffer);
7718               emit2 ("!global", buffer);
7719               _G.lines.isDebug = 0;
7720             }
7721           if (!options.noCcodeInAsm) {
7722             emit2 (";%s:%d: %s", ic->filename, ic->lineno,
7723                    printCLine(ic->filename, ic->lineno));
7724           }
7725           cln = ic->lineno;
7726         }
7727       if (options.iCodeInAsm) {
7728         emit2 (";ic:%d: %s", ic->key, printILine(ic));
7729       }
7730       /* if the result is marked as
7731          spilt and rematerializable or code for
7732          this has already been generated then
7733          do nothing */
7734       if (resultRemat (ic) || ic->generated)
7735         continue;
7736
7737       /* depending on the operation */
7738       switch (ic->op)
7739         {
7740         case '!':
7741           emitDebug ("; genNot");
7742           genNot (ic);
7743           break;
7744
7745         case '~':
7746           emitDebug ("; genCpl");
7747           genCpl (ic);
7748           break;
7749
7750         case UNARYMINUS:
7751           emitDebug ("; genUminus");
7752           genUminus (ic);
7753           break;
7754
7755         case IPUSH:
7756           emitDebug ("; genIpush");
7757           genIpush (ic);
7758           break;
7759
7760         case IPOP:
7761           /* IPOP happens only when trying to restore a
7762              spilt live range, if there is an ifx statement
7763              following this pop then the if statement might
7764              be using some of the registers being popped which
7765              would destory the contents of the register so
7766              we need to check for this condition and handle it */
7767           if (ic->next &&
7768               ic->next->op == IFX &&
7769               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7770             {
7771               emitDebug ("; genIfx");
7772               genIfx (ic->next, ic);
7773             }
7774           else
7775             {
7776               emitDebug ("; genIpop");
7777               genIpop (ic);
7778             }
7779           break;
7780
7781         case CALL:
7782           emitDebug ("; genCall");
7783           genCall (ic);
7784           break;
7785
7786         case PCALL:
7787           emitDebug ("; genPcall");
7788           genPcall (ic);
7789           break;
7790
7791         case FUNCTION:
7792           emitDebug ("; genFunction");
7793           genFunction (ic);
7794           break;
7795
7796         case ENDFUNCTION:
7797           emitDebug ("; genEndFunction");
7798           genEndFunction (ic);
7799           break;
7800
7801         case RETURN:
7802           emitDebug ("; genRet");
7803           genRet (ic);
7804           break;
7805
7806         case LABEL:
7807           emitDebug ("; genLabel");
7808           genLabel (ic);
7809           break;
7810
7811         case GOTO:
7812           emitDebug ("; genGoto");
7813           genGoto (ic);
7814           break;
7815
7816         case '+':
7817           emitDebug ("; genPlus");
7818           genPlus (ic);
7819           break;
7820
7821         case '-':
7822           emitDebug ("; genMinus");
7823           genMinus (ic);
7824           break;
7825
7826         case '*':
7827           emitDebug ("; genMult");
7828           genMult (ic);
7829           break;
7830
7831         case '/':
7832           emitDebug ("; genDiv");
7833           genDiv (ic);
7834           break;
7835
7836         case '%':
7837           emitDebug ("; genMod");
7838           genMod (ic);
7839           break;
7840
7841         case '>':
7842           emitDebug ("; genCmpGt");
7843           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7844           break;
7845
7846         case '<':
7847           emitDebug ("; genCmpLt");
7848           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7849           break;
7850
7851         case LE_OP:
7852         case GE_OP:
7853         case NE_OP:
7854
7855           /* note these two are xlated by algebraic equivalence
7856              during parsing SDCC.y */
7857           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7858                   "got '>=' or '<=' shouldn't have come here");
7859           break;
7860
7861         case EQ_OP:
7862           emitDebug ("; genCmpEq");
7863           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7864           break;
7865
7866         case AND_OP:
7867           emitDebug ("; genAndOp");
7868           genAndOp (ic);
7869           break;
7870
7871         case OR_OP:
7872           emitDebug ("; genOrOp");
7873           genOrOp (ic);
7874           break;
7875
7876         case '^':
7877           emitDebug ("; genXor");
7878           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7879           break;
7880
7881         case '|':
7882           emitDebug ("; genOr");
7883           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7884           break;
7885
7886         case BITWISEAND:
7887           emitDebug ("; genAnd");
7888           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7889           break;
7890
7891         case INLINEASM:
7892           emitDebug ("; genInline");
7893           genInline (ic);
7894           break;
7895
7896         case RRC:
7897           emitDebug ("; genRRC");
7898           genRRC (ic);
7899           break;
7900
7901         case RLC:
7902           emitDebug ("; genRLC");
7903           genRLC (ic);
7904           break;
7905
7906         case GETHBIT:
7907           emitDebug ("; genGetHBIT");
7908           genGetHbit (ic);
7909           break;
7910
7911         case LEFT_OP:
7912           emitDebug ("; genLeftShift");
7913           genLeftShift (ic);
7914           break;
7915
7916         case RIGHT_OP:
7917           emitDebug ("; genRightShift");
7918           genRightShift (ic);
7919           break;
7920
7921         case GET_VALUE_AT_ADDRESS:
7922           emitDebug ("; genPointerGet");
7923           genPointerGet (ic);
7924           break;
7925
7926         case '=':
7927
7928           if (POINTER_SET (ic))
7929             {
7930               emitDebug ("; genAssign (pointer)");
7931               genPointerSet (ic);
7932             }
7933           else
7934             {
7935               emitDebug ("; genAssign");
7936               genAssign (ic);
7937             }
7938           break;
7939
7940         case IFX:
7941           emitDebug ("; genIfx");
7942           genIfx (ic, NULL);
7943           break;
7944
7945         case ADDRESS_OF:
7946           emitDebug ("; genAddrOf");
7947           genAddrOf (ic);
7948           break;
7949
7950         case JUMPTABLE:
7951           emitDebug ("; genJumpTab");
7952           genJumpTab (ic);
7953           break;
7954
7955         case CAST:
7956           emitDebug ("; genCast");
7957           genCast (ic);
7958           break;
7959
7960         case RECEIVE:
7961           emitDebug ("; genReceive");
7962           genReceive (ic);
7963           break;
7964
7965         case SEND:
7966           if (ic->builtinSEND)
7967             {
7968               emitDebug ("; genBuiltIn");
7969               genBuiltIn(ic);
7970             }
7971           else
7972             {
7973               emitDebug ("; addSet");
7974               addSet (&_G.sendSet, ic);
7975             }
7976           break;
7977
7978         case ARRAYINIT:
7979           emitDebug ("; genArrayInit");
7980           genArrayInit(ic);
7981           break;
7982
7983         case DUMMY_READ_VOLATILE:
7984           emitDebug ("; genDummyRead");
7985           genDummyRead (ic);
7986           break;
7987
7988         default:
7989           ic = ic;
7990         }
7991     }
7992
7993
7994   /* now we are ready to call the
7995      peep hole optimizer */
7996   if (!options.nopeep)
7997     peepHole (&_G.lines.head);
7998
7999   /* This is unfortunate */
8000   /* now do the actual printing */
8001   {
8002     FILE *fp = codeOutFile;
8003     if (isInHome () && codeOutFile == code->oFile)
8004       codeOutFile = home->oFile;
8005     printLine (_G.lines.head, codeOutFile);
8006     if (_G.flushStatics)
8007       {
8008         flushStatics ();
8009         _G.flushStatics = 0;
8010       }
8011     codeOutFile = fp;
8012   }
8013
8014   freeTrace(&_G.lines.trace);
8015   freeTrace(&_G.trace.aops);
8016 }
8017
8018 /*
8019   Attic
8020 static int
8021 _isPairUsed (iCode * ic, PAIR_ID pairId)
8022 {
8023   int ret = 0;
8024   switch (pairId)
8025     {
8026     case PAIR_DE:
8027       if (bitVectBitValue (ic->rMask, D_IDX))
8028         ret++;
8029       if (bitVectBitValue (ic->rMask, E_IDX))
8030         ret++;
8031       break;
8032     default:
8033       wassert (0);
8034     }
8035   return ret;
8036 }
8037
8038 static char *
8039 fetchLitSpecial (asmop * aop, bool negate, bool xor)
8040 {
8041   unsigned long v;
8042   value *val = aop->aopu.aop_lit;
8043
8044   wassert (aop->type == AOP_LIT);
8045   wassert (!IS_FLOAT (val->type));
8046
8047   v = (unsigned long) floatFromVal (val);
8048
8049   if (xor)
8050     v ^= 0x8000;
8051   if (negate)
8052     v = 0-v;
8053   v &= 0xFFFF;
8054
8055   tsprintf (buffer, sizeof(buffer), "!immedword", v);
8056   return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
8057 }
8058
8059
8060 */