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