* src/z80/gen.c (genFunction, genEndFunction): fixed bug 1160666,
[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   unsigned 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)
1893                 emit2( "push bc" );
1894
1895               if (strlen(s) != 1
1896                   || (s[0] != 'a' && s[0] != 'd' && s[0] != 'e'
1897                       && s[0] != 'h' && s[0] != 'l'))
1898                 {
1899                   emit2( "ld a,%s", s );
1900                   s = "a";
1901                 }
1902
1903               emit2( "ld bc,#%s", aop->aopu.aop_dir );
1904               emit2( "out (c),%s", s );
1905
1906               if( aop->bcInUse )
1907                 emit2( "pop bc"    );
1908               else
1909                 spillPair (PAIR_BC);
1910             }
1911           else if( z80_opts.port_mode == 180 )
1912             { /* z180 in0/out0 mode */
1913               emit2( "ld a,%s", s );
1914               emit2( "out0 (%s),a", aop->aopu.aop_dir );
1915             }
1916           else
1917             { /* 8 bit mode */
1918               emit2( "ld a,%s", s );
1919               emit2( "out (%s),a", aop->aopu.aop_dir );
1920             }
1921         }
1922       break;
1923
1924     case AOP_REG:
1925       if (!strcmp (s, "!*hl"))
1926         emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1927       else
1928         emit2 ("ld %s,%s",
1929                aop->aopu.aop_reg[offset]->name, s);
1930       spillPairReg(aop->aopu.aop_reg[offset]->name);
1931       break;
1932
1933     case AOP_IY:
1934       wassert (!IS_GB);
1935       if (!canAssignToPtr (s))
1936         {
1937           emit2 ("ld a,%s", s);
1938           setupPair (PAIR_IY, aop, offset);
1939           emit2 ("ld !*iyx,a", offset);
1940         }
1941       else
1942         {
1943           setupPair (PAIR_IY, aop, offset);
1944           emit2 ("ld !*iyx,%s", offset, s);
1945         }
1946       break;
1947
1948     case AOP_HL:
1949       wassert (IS_GB);
1950       /* PENDING: for re-target */
1951       if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1952         {
1953           emit2 ("ld a,!*hl");
1954           s = "a";
1955         }
1956       setupPair (PAIR_HL, aop, offset);
1957
1958       emit2 ("ld !*hl,%s", s);
1959       break;
1960
1961     case AOP_EXSTK:
1962       wassert (!IS_GB);
1963       if (!canAssignToPtr (s))
1964         {
1965           emit2 ("ld a,%s", s);
1966           setupPair (PAIR_IY, aop, offset);
1967           emit2 ("ld !*iyx,a", offset);
1968         }
1969       else
1970         {
1971           setupPair (PAIR_IY, aop, offset);
1972           emit2 ("ld !*iyx,%s", offset, s);
1973         }
1974       break;
1975
1976     case AOP_STK:
1977       if (IS_GB)
1978         {
1979           /* PENDING: re-target */
1980           if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1981             {
1982               emit2 ("ld a,!*hl");
1983               s = "a";
1984             }
1985           setupPair (PAIR_HL, aop, offset);
1986           if (!canAssignToPtr (s))
1987             {
1988               emit2 ("ld a,%s", s);
1989               emit2 ("ld !*hl,a");
1990             }
1991           else
1992             emit2 ("ld !*hl,%s", s);
1993         }
1994       else
1995         {
1996           if (aop->aopu.aop_stk >= 0)
1997             offset += _G.stack.param_offset;
1998           if (!canAssignToPtr (s))
1999             {
2000               emit2 ("ld a,%s", s);
2001               emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
2002             }
2003           else
2004             {
2005               emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
2006             }
2007         }
2008       break;
2009
2010     case AOP_CRY:
2011       /* if bit variable */
2012       if (!aop->aopu.aop_dir)
2013         {
2014           emit2 ("ld a,!zero");
2015           emit2 ("rla");
2016         }
2017       else
2018         {
2019           /* In bit space but not in C - cant happen */
2020           wassertl (0, "Tried to write into a bit variable");
2021         }
2022       break;
2023
2024     case AOP_STR:
2025       aop->coff = offset;
2026       if (strcmp (aop->aopu.aop_str[offset], s))
2027         {
2028           emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
2029         }
2030       spillPairReg(aop->aopu.aop_str[offset]);
2031       break;
2032
2033     case AOP_ACC:
2034       aop->coff = offset;
2035       if (!offset && (strcmp (s, "acc") == 0))
2036         break;
2037       if (offset > 0)
2038         {
2039           wassertl (0, "Tried to access past the end of A");
2040         }
2041       else
2042         {
2043           if (strcmp (aop->aopu.aop_str[offset], s))
2044             {
2045               emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
2046               spillPairReg(aop->aopu.aop_str[offset]);
2047             }
2048         }
2049       break;
2050
2051     case AOP_HLREG:
2052       wassert (offset < 2);
2053       emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
2054       spillPairReg(aop->aopu.aop_str[offset]);
2055       break;
2056
2057     case AOP_PAIRPTR:
2058       setupPair (aop->aopu.aop_pairId, aop, offset);
2059       if (aop->aopu.aop_pairId==PAIR_IX)
2060         emit2 ("ld !*ixx,%s", 0, s);
2061       else if (aop->aopu.aop_pairId==PAIR_IY)
2062         emit2 ("ld !*ixy,%s", 0, s);
2063       else
2064         emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
2065       break;
2066
2067     default:
2068       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2069               "aopPut got unsupported aop->type");
2070       exit (0);
2071     }
2072 }
2073
2074 #define AOP(op) op->aop
2075 #define AOP_TYPE(op) AOP(op)->type
2076 #define AOP_SIZE(op) AOP(op)->size
2077 #define AOP_NEEDSACC(x) (AOP(x) && ((AOP_TYPE(x) == AOP_CRY) || (AOP_TYPE(x) == AOP_SFR)))
2078
2079 static void
2080 commitPair (asmop * aop, PAIR_ID id)
2081 {
2082   /* PENDING: Verify this. */
2083   if (id == PAIR_HL && requiresHL (aop) && IS_GB)
2084     {
2085       emit2 ("ld a,l");
2086       emit2 ("ld d,h");
2087       aopPut (aop, "a", 0);
2088       aopPut (aop, "d", 1);
2089     }
2090   else
2091     {
2092       /* Special cases */
2093       if (id == PAIR_HL && aop->type == AOP_IY && aop->size == 2)
2094         {
2095           char *l = aopGetLitWordLong (aop, 0, FALSE);
2096           wassert (l);
2097
2098           emit2 ("ld (%s),%s", l, _pairs[id].name);
2099         }
2100       else
2101         {
2102           aopPut (aop, _pairs[id].l, 0);
2103           aopPut (aop, _pairs[id].h, 1);
2104         }
2105     }
2106 }
2107
2108 /*-----------------------------------------------------------------*/
2109 /* getDataSize - get the operand data size                         */
2110 /*-----------------------------------------------------------------*/
2111 int
2112 getDataSize (operand * op)
2113 {
2114   int size;
2115   size = AOP_SIZE (op);
2116   if (size == 3)
2117     {
2118       /* pointer */
2119       wassertl (0, "Somehow got a three byte data pointer");
2120     }
2121   return size;
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* movLeft2Result - move byte from left to result                  */
2126 /*-----------------------------------------------------------------*/
2127 static void
2128 movLeft2Result (operand * left, int offl,
2129                 operand * result, int offr, int sign)
2130 {
2131   const char *l;
2132
2133   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
2134     {
2135       l = aopGet (AOP (left), offl, FALSE);
2136
2137       if (!sign)
2138         {
2139           aopPut (AOP (result), l, offr);
2140         }
2141       else
2142         {
2143           if (getDataSize (left) == offl + 1)
2144             {
2145               emit2 ("ld a,%s", l);
2146               aopPut (AOP (result), "a", offr);
2147             }
2148         }
2149     }
2150 }
2151
2152 static void
2153 movLeft2ResultLong (operand * left, int offl,
2154                 operand * result, int offr, int sign,
2155                 int size)
2156 {
2157   if (size == 1)
2158     {
2159       movLeft2Result (left, offl, result, offr, sign);
2160     }
2161   else
2162     {
2163       wassertl (offl == 0 && offr == 0, "Only implemented for zero offset");
2164       wassertl (size == 2, "Only implemented for two bytes or one");
2165
2166       if ( IS_GB && requiresHL ( AOP (left)) && getPairId ( AOP (result)) == PAIR_HL)
2167         {
2168           emit2 ("ld a,%s", aopGet (AOP (left), LSB, FALSE));
2169           emit2 ("ld h,%s", aopGet (AOP (left), MSB16, FALSE));
2170           emit2 ("ld l,a");
2171           spillPair (PAIR_HL);
2172         }
2173       else if ( getPairId ( AOP (result)) == PAIR_IY)
2174         {
2175           PAIR_ID id = getPairId (AOP (left));
2176           if (id != PAIR_INVALID)
2177             {
2178               emit2("push %s", _pairs[id].name);
2179               emit2("pop iy");
2180             }
2181           else
2182             {
2183               /* PENDING */
2184               emitDebug("Error");
2185             }
2186         }
2187       else
2188         {
2189           movLeft2Result (left, offl, result, offr, sign);
2190           movLeft2Result (left, offl+1, result, offr+1, sign);
2191         }
2192     }
2193 }
2194
2195 /** Put Acc into a register set
2196  */
2197 void
2198 outAcc (operand * result)
2199 {
2200   int size, offset;
2201   size = getDataSize (result);
2202   if (size)
2203     {
2204       aopPut (AOP (result), "a", 0);
2205       size--;
2206       offset = 1;
2207       /* unsigned or positive */
2208       while (size--)
2209         {
2210           aopPut (AOP (result), "!zero", offset++);
2211         }
2212     }
2213 }
2214
2215 /** Take the value in carry and put it into a register
2216  */
2217 void
2218 outBitCLong (operand * result, bool swap_sense)
2219 {
2220   /* if the result is bit */
2221   if (AOP_TYPE (result) == AOP_CRY)
2222     {
2223       wassertl (0, "Tried to write carry to a bit");
2224     }
2225   else
2226     {
2227       emit2 ("ld a,!zero");
2228       emit2 ("rla");
2229       if (swap_sense)
2230         emit2 ("xor a,!immedbyte", 1);
2231       outAcc (result);
2232     }
2233 }
2234
2235 void
2236 outBitC (operand * result)
2237 {
2238   outBitCLong (result, FALSE);
2239 }
2240
2241 /*-----------------------------------------------------------------*/
2242 /* toBoolean - emit code for orl a,operator(sizeop)                */
2243 /*-----------------------------------------------------------------*/
2244 void
2245 _toBoolean (operand * oper)
2246 {
2247   int size = AOP_SIZE (oper);
2248   int offset = 0;
2249   if (size > 1)
2250     {
2251       emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE));
2252       size--;
2253       while (size--)
2254         emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
2255     }
2256   else
2257     {
2258       if (AOP (oper)->type != AOP_ACC)
2259         {
2260           _clearCarry();
2261           emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
2262         }
2263     }
2264 }
2265
2266
2267 /*-----------------------------------------------------------------*/
2268 /* genNot - generate code for ! operation                          */
2269 /*-----------------------------------------------------------------*/
2270 static void
2271 genNot (iCode * ic)
2272 {
2273
2274   /* assign asmOps to operand & result */
2275   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2276   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2277
2278   /* if in bit space then a special case */
2279   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2280     {
2281       wassertl (0, "Tried to negate a bit");
2282     }
2283
2284   _toBoolean (IC_LEFT (ic));
2285
2286   /* Not of A:
2287      If A == 0, !A = 1
2288      else A = 0
2289      So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
2290   emit2 ("sub a,!one");
2291   outBitC (IC_RESULT (ic));
2292
2293   /* release the aops */
2294   freeAsmop (IC_LEFT (ic), NULL, ic);
2295   freeAsmop (IC_RESULT (ic), NULL, ic);
2296 }
2297
2298 /*-----------------------------------------------------------------*/
2299 /* genCpl - generate code for complement                           */
2300 /*-----------------------------------------------------------------*/
2301 static void
2302 genCpl (iCode * ic)
2303 {
2304   int offset = 0;
2305   int size;
2306
2307
2308   /* assign asmOps to operand & result */
2309   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2310   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2311
2312   /* if both are in bit space then
2313      a special case */
2314   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2315       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2316     {
2317       wassertl (0, "Left and the result are in bit space");
2318     }
2319
2320   size = AOP_SIZE (IC_RESULT (ic));
2321   while (size--)
2322     {
2323       const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
2324       _moveA (l);
2325       emit2("cpl");
2326       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2327     }
2328
2329   /* release the aops */
2330   freeAsmop (IC_LEFT (ic), NULL, ic);
2331   freeAsmop (IC_RESULT (ic), NULL, ic);
2332 }
2333
2334 static void
2335 _gbz80_emitAddSubLongLong (iCode *ic, asmop *left, asmop *right, bool isAdd)
2336 {
2337   /* Logic:
2338        ld de,right.lw
2339        setup hl to left
2340        de = hl - de
2341        push flags
2342        store de into result
2343        pop flags
2344        ld de,right.hw
2345        setup hl
2346        de = hl -de
2347        store de into result
2348   */
2349   const char *first = isAdd ? "add" : "sub";
2350   const char *later = isAdd ? "adc" : "sbc";
2351
2352   wassertl (IS_GB, "Code is only relevent to the gbz80");
2353   wassertl (AOP( IC_RESULT (ic))->size == 4, "Only works for four bytes");
2354
2355   fetchPair (PAIR_DE, left);
2356
2357   emit2 ("ld a,e");
2358   emit2 ("%s a,%s", first, aopGet( right, LSB, FALSE));
2359   emit2 ("ld e,a");
2360   emit2 ("ld a,d");
2361   emit2 ("%s a,%s", later, aopGet( right, MSB16, FALSE));
2362
2363   _push (PAIR_AF);
2364   aopPut ( AOP (IC_RESULT (ic)), "a", MSB16);
2365   aopPut ( AOP (IC_RESULT (ic)), "e", LSB);
2366
2367   fetchPairLong (PAIR_DE, left, NULL, MSB24);
2368   aopGet (right, MSB24, FALSE);
2369
2370   _pop (PAIR_AF);
2371   emit2 ("ld a,e");
2372   emit2 ("%s a,%s", later, aopGet( right, MSB24, FALSE));
2373   emit2 ("ld e,a");
2374   emit2 ("ld a,d");
2375   emit2 ("%s a,%s", later, aopGet( right, MSB32, FALSE));
2376
2377   aopPut ( AOP (IC_RESULT (ic)), "a", MSB32);
2378   aopPut ( AOP (IC_RESULT (ic)), "e", MSB24);
2379 }
2380
2381 static void
2382 _gbz80_emitAddSubLong (iCode *ic, bool isAdd)
2383 {
2384   _gbz80_emitAddSubLongLong (ic, AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)), isAdd);
2385 }
2386
2387 /*-----------------------------------------------------------------*/
2388 /* genUminusFloat - unary minus for floating points                */
2389 /*-----------------------------------------------------------------*/
2390 static void
2391 genUminusFloat (operand * op, operand * result)
2392 {
2393   int size, offset = 0;
2394
2395   emitDebug("; genUminusFloat");
2396
2397   /* for this we just need to flip the
2398      first bit then copy the rest in place */
2399   size = AOP_SIZE (op) - 1;
2400
2401   _moveA(aopGet (AOP (op), MSB32, FALSE));
2402
2403   emit2("xor a,!immedbyte", 0x80);
2404   aopPut (AOP (result), "a", MSB32);
2405
2406   while (size--)
2407     {
2408       aopPut (AOP (result), aopGet (AOP (op), offset, FALSE), offset);
2409       offset++;
2410     }
2411 }
2412
2413 /*-----------------------------------------------------------------*/
2414 /* genUminus - unary minus code generation                         */
2415 /*-----------------------------------------------------------------*/
2416 static void
2417 genUminus (iCode * ic)
2418 {
2419   int offset, size;
2420   sym_link *optype, *rtype;
2421
2422   /* assign asmops */
2423   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2424   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2425
2426   /* if both in bit space then special
2427      case */
2428   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2429       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2430     {
2431       wassertl (0, "Left and right are in bit space");
2432       goto release;
2433     }
2434
2435   optype = operandType (IC_LEFT (ic));
2436   rtype = operandType (IC_RESULT (ic));
2437
2438   /* if float then do float stuff */
2439   if (IS_FLOAT (optype))
2440     {
2441       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2442       goto release;
2443     }
2444
2445   /* otherwise subtract from zero */
2446   size = AOP_SIZE (IC_LEFT (ic));
2447
2448   if (AOP_SIZE (IC_RESULT (ic)) == 4 && IS_GB)
2449     {
2450       /* Create a new asmop with value zero */
2451       asmop *azero = newAsmop (AOP_SIMPLELIT);
2452       azero->aopu.aop_simplelit = 0;
2453       azero->size = size;
2454       _gbz80_emitAddSubLongLong (ic, azero, AOP (IC_LEFT (ic)), FALSE);
2455       goto release;
2456     }
2457
2458   offset = 0;
2459   _clearCarry();
2460   while (size--)
2461     {
2462       const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
2463       emit2 ("ld a,!zero");
2464       emit2 ("sbc a,%s", l);
2465       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2466     }
2467
2468   /* if any remaining bytes in the result */
2469   /* we just need to propagate the sign   */
2470   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2471     {
2472       emit2 ("rlc a");
2473       emit2 ("sbc a,a");
2474       while (size--)
2475         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2476     }
2477
2478 release:
2479   /* release the aops */
2480   freeAsmop (IC_LEFT (ic), NULL, ic);
2481   freeAsmop (IC_RESULT (ic), NULL, ic);
2482 }
2483
2484 /*-----------------------------------------------------------------*/
2485 /* assignResultValue -               */
2486 /*-----------------------------------------------------------------*/
2487 void
2488 assignResultValue (operand * oper)
2489 {
2490   int size = AOP_SIZE (oper);
2491   bool topInA = 0;
2492
2493   wassertl (size <= 4, "Got a result that is bigger than four bytes");
2494   topInA = requiresHL (AOP (oper));
2495
2496   if (IS_GB && size == 4 && requiresHL (AOP (oper)))
2497     {
2498       /* We do it the hard way here. */
2499       _push (PAIR_HL);
2500       aopPut (AOP (oper), _fReturn[0], 0);
2501       aopPut (AOP (oper), _fReturn[1], 1);
2502       _pop (PAIR_DE);
2503       aopPut (AOP (oper), _fReturn[0], 2);
2504       aopPut (AOP (oper), _fReturn[1], 3);
2505     }
2506   else
2507     {
2508       while (size--)
2509         {
2510           aopPut (AOP (oper), _fReturn[size], size);
2511         }
2512     }
2513 }
2514
2515 /** Simple restore that doesn't take into account what is used in the
2516     return.
2517 */
2518 static void
2519 _restoreRegsAfterCall(void)
2520 {
2521   if (_G.stack.pushedDE)
2522     {
2523       _pop ( PAIR_DE);
2524       _G.stack.pushedDE = FALSE;
2525     }
2526   if (_G.stack.pushedBC)
2527     {
2528       _pop ( PAIR_BC);
2529       _G.stack.pushedBC = FALSE;
2530     }
2531   _G.saves.saved = FALSE;
2532 }
2533
2534 static void
2535 _saveRegsForCall(iCode *ic, int sendSetSize)
2536 {
2537   /* Rules:
2538       o Stack parameters are pushed before this function enters
2539       o DE and BC may be used in this function.
2540       o HL and DE may be used to return the result.
2541       o HL and DE may be used to send variables.
2542       o DE and BC may be used to store the result value.
2543       o HL may be used in computing the sent value of DE
2544       o The iPushes for other parameters occur before any addSets
2545
2546      Logic: (to be run inside the first iPush or if none, before sending)
2547       o Compute if DE and/or BC are in use over the call
2548       o Compute if DE is used in the send set
2549       o Compute if DE and/or BC are used to hold the result value
2550       o If (DE is used, or in the send set) and is not used in the result, push.
2551       o If BC is used and is not in the result, push
2552       o
2553       o If DE is used in the send set, fetch
2554       o If HL is used in the send set, fetch
2555       o Call
2556       o ...
2557   */
2558   if (_G.saves.saved == FALSE) {
2559     bool deInUse, bcInUse;
2560     bool deSending;
2561     bool bcInRet = FALSE, deInRet = FALSE;
2562     bitVect *rInUse;
2563
2564     rInUse = bitVectCplAnd (bitVectCopy (ic->rMask),
2565                             z80_rUmaskForOp (IC_RESULT(ic)));
2566
2567     deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
2568     bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
2569
2570     deSending = (sendSetSize > 1);
2571
2572     emitDebug ("; _saveRegsForCall: sendSetSize: %u deInUse: %u bcInUse: %u deSending: %u", sendSetSize, deInUse, bcInUse, deSending);
2573
2574     if (bcInUse && bcInRet == FALSE) {
2575       _push(PAIR_BC);
2576       _G.stack.pushedBC = TRUE;
2577     }
2578     if (deInUse && deInRet == FALSE) {
2579       _push(PAIR_DE);
2580       _G.stack.pushedDE = TRUE;
2581     }
2582
2583     _G.saves.saved = TRUE;
2584   }
2585   else {
2586     /* Already saved. */
2587   }
2588 }
2589
2590 /*-----------------------------------------------------------------*/
2591 /* genIpush - genrate code for pushing this gets a little complex  */
2592 /*-----------------------------------------------------------------*/
2593 static void
2594 genIpush (iCode * ic)
2595 {
2596   int size, offset = 0;
2597   const char *l;
2598
2599   /* if this is not a parm push : ie. it is spill push
2600      and spill push is always done on the local stack */
2601   if (!ic->parmPush)
2602     {
2603       wassertl(0, "Encountered an unsupported spill push.");
2604       return;
2605     }
2606
2607   if (_G.saves.saved == FALSE) {
2608     /* Caller saves, and this is the first iPush. */
2609     /* Scan ahead until we find the function that we are pushing parameters to.
2610        Count the number of addSets on the way to figure out what registers
2611        are used in the send set.
2612     */
2613     int nAddSets = 0;
2614     iCode *walk = ic->next;
2615
2616     while (walk) {
2617       if (walk->op == SEND) {
2618         nAddSets++;
2619       }
2620       else if (walk->op == CALL || walk->op == PCALL) {
2621         /* Found it. */
2622         break;
2623       }
2624       else {
2625         /* Keep looking. */
2626       }
2627       walk = walk->next;
2628     }
2629     _saveRegsForCall(walk, nAddSets);
2630   }
2631   else {
2632     /* Already saved by another iPush. */
2633   }
2634
2635   /* then do the push */
2636   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2637
2638   size = AOP_SIZE (IC_LEFT (ic));
2639
2640   if (isPair (AOP (IC_LEFT (ic))) && size == 2)
2641     {
2642       _G.stack.pushed += 2;
2643       emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
2644     }
2645   else
2646     {
2647       if (size == 2)
2648         {
2649           fetchHL (AOP (IC_LEFT (ic)));
2650           emit2 ("push hl");
2651           spillPair (PAIR_HL);
2652           _G.stack.pushed += 2;
2653           goto release;
2654         }
2655       if (size == 4)
2656         {
2657           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
2658           emit2 ("push hl");
2659           spillPair (PAIR_HL);
2660           _G.stack.pushed += 2;
2661           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0);
2662           emit2 ("push hl");
2663           spillPair (PAIR_HL);
2664           _G.stack.pushed += 2;
2665           goto release;
2666         }
2667       offset = size;
2668       while (size--)
2669         {
2670           if (AOP (IC_LEFT (ic))->type == AOP_IY)
2671             {
2672               char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
2673               wassert (l);
2674               emit2 ("ld a,(%s)", l);
2675             }
2676           else
2677             {
2678               l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
2679               emit2 ("ld a,%s", l);
2680             }
2681           emit2 ("push af");
2682           emit2 ("inc sp");
2683           _G.stack.pushed++;
2684         }
2685     }
2686 release:
2687   freeAsmop (IC_LEFT (ic), NULL, ic);
2688 }
2689
2690 /*-----------------------------------------------------------------*/
2691 /* genIpop - recover the registers: can happen only for spilling   */
2692 /*-----------------------------------------------------------------*/
2693 static void
2694 genIpop (iCode * ic)
2695 {
2696   int size, offset;
2697
2698
2699   /* if the temp was not pushed then */
2700   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2701     return;
2702
2703   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2704   size = AOP_SIZE (IC_LEFT (ic));
2705   offset = (size - 1);
2706   if (isPair (AOP (IC_LEFT (ic))))
2707     {
2708       emit2 ("pop %s", getPairName (AOP (IC_LEFT (ic))));
2709     }
2710   else
2711     {
2712       while (size--)
2713         {
2714           emit2 ("dec sp");
2715           emit2 ("pop hl");
2716           spillPair (PAIR_HL);
2717           aopPut (AOP (IC_LEFT (ic)), "l", offset--);
2718         }
2719     }
2720
2721   freeAsmop (IC_LEFT (ic), NULL, ic);
2722 }
2723
2724 /* This is quite unfortunate */
2725 static void
2726 setArea (int inHome)
2727 {
2728   /*
2729     static int lastArea = 0;
2730
2731      if (_G.in_home != inHome) {
2732      if (inHome) {
2733      const char *sz = port->mem.code_name;
2734      port->mem.code_name = "HOME";
2735      emit2("!area", CODE_NAME);
2736      port->mem.code_name = sz;
2737      }
2738      else
2739      emit2("!area", CODE_NAME); */
2740   _G.in_home = inHome;
2741   //    }
2742 }
2743
2744 static bool
2745 isInHome (void)
2746 {
2747   return _G.in_home;
2748 }
2749
2750 static int
2751 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
2752 {
2753   int ret = 0;
2754   asmop *aop;
2755   symbol *sym = OP_SYMBOL (op);
2756
2757   if (sym->isspilt || sym->nRegs == 0)
2758     return 0;
2759
2760   aopOp (op, ic, FALSE, FALSE);
2761
2762   aop = AOP (op);
2763   if (aop->type == AOP_REG)
2764     {
2765       int i;
2766       for (i = 0; i < aop->size; i++)
2767         {
2768           if (pairId == PAIR_DE)
2769             {
2770               emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
2771               if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
2772                 ret++;
2773               if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
2774                 ret++;
2775             }
2776           else if (pairId == PAIR_BC)
2777             {
2778               emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
2779               if (!strcmp (aop->aopu.aop_reg[i]->name, "c"))
2780                 ret++;
2781               if (!strcmp (aop->aopu.aop_reg[i]->name, "b"))
2782                 ret++;
2783             }
2784           else
2785             {
2786               wassert (0);
2787             }
2788         }
2789     }
2790
2791   freeAsmop (IC_LEFT (ic), NULL, ic);
2792   return ret;
2793 }
2794
2795 /** Emit the code for a call statement
2796  */
2797 static void
2798 emitCall (iCode * ic, bool ispcall)
2799 {
2800   bool bInRet, cInRet, dInRet, eInRet;
2801   sym_link *dtype = operandType (IC_LEFT (ic));
2802
2803   /* if caller saves & we have not saved then */
2804   if (!ic->regsSaved)
2805     {
2806       /* PENDING */
2807     }
2808
2809   _saveRegsForCall(ic, _G.sendSet ? elementsInSet(_G.sendSet) : 0);
2810
2811   /* if send set is not empty then assign */
2812   if (_G.sendSet)
2813     {
2814       iCode *sic;
2815       int send = 0;
2816       int nSend = elementsInSet(_G.sendSet);
2817       bool swapped = FALSE;
2818
2819       int _z80_sendOrder[] = {
2820         PAIR_BC, PAIR_DE
2821       };
2822
2823       if (nSend > 1) {
2824         /* Check if the parameters are swapped.  If so route through hl instead. */
2825         wassertl (nSend == 2, "Pedantic check.  Code only checks for the two send items case.");
2826
2827         sic = setFirstItem(_G.sendSet);
2828         sic = setNextItem(_G.sendSet);
2829
2830         if (_opUsesPair (IC_LEFT(sic), sic, _z80_sendOrder[0])) {
2831           /* The second send value is loaded from one the one that holds the first
2832              send, i.e. it is overwritten. */
2833           /* Cache the first in HL, and load the second from HL instead. */
2834           emit2 ("ld h,%s", _pairs[_z80_sendOrder[0]].h);
2835           emit2 ("ld l,%s", _pairs[_z80_sendOrder[0]].l);
2836
2837           swapped = TRUE;
2838         }
2839       }
2840
2841       for (sic = setFirstItem (_G.sendSet); sic;
2842            sic = setNextItem (_G.sendSet))
2843         {
2844           int size;
2845           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2846
2847           size = AOP_SIZE (IC_LEFT (sic));
2848           wassertl (size <= 2, "Tried to send a parameter that is bigger than two bytes");
2849           wassertl (_z80_sendOrder[send] != PAIR_INVALID, "Tried to send more parameters than we have registers for");
2850
2851           // PENDING: Mild hack
2852           if (swapped == TRUE && send == 1) {
2853             if (size > 1) {
2854               emit2 ("ld %s,h", _pairs[_z80_sendOrder[send]].h);
2855             }
2856             else {
2857               emit2 ("ld %s,!zero", _pairs[_z80_sendOrder[send]].h);
2858             }
2859             emit2 ("ld %s,l", _pairs[_z80_sendOrder[send]].l);
2860           }
2861           else {
2862             fetchPair(_z80_sendOrder[send], AOP (IC_LEFT (sic)));
2863           }
2864
2865           send++;
2866           freeAsmop (IC_LEFT (sic), NULL, sic);
2867         }
2868       _G.sendSet = NULL;
2869     }
2870
2871   if (ispcall)
2872     {
2873       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2874         {
2875           werror (W_INDIR_BANKED);
2876         }
2877       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2878
2879       if (isLitWord (AOP (IC_LEFT (ic))))
2880         {
2881           emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2882         }
2883       else
2884         {
2885           symbol *rlbl = newiTempLabel (NULL);
2886           spillPair (PAIR_HL);
2887           emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2888           emit2 ("push hl");
2889           _G.stack.pushed += 2;
2890
2891           fetchHL (AOP (IC_LEFT (ic)));
2892           emit2 ("jp !*hl");
2893           emit2 ("!tlabeldef", (rlbl->key + 100));
2894           _G.stack.pushed -= 2;
2895         }
2896       freeAsmop (IC_LEFT (ic), NULL, ic);
2897     }
2898   else
2899     {
2900       char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2901       OP_SYMBOL (IC_LEFT (ic))->rname :
2902       OP_SYMBOL (IC_LEFT (ic))->name;
2903       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2904         {
2905           emit2 ("call banked_call");
2906           emit2 ("!dws", name);
2907           emit2 ("!dw !bankimmeds", name);
2908         }
2909       else
2910         {
2911           /* make the call */
2912           emit2 ("call %s", name);
2913         }
2914     }
2915   spillCached ();
2916
2917   /* Mark the registers as restored. */
2918   _G.saves.saved = FALSE;
2919
2920   /* if we need assign a result value */
2921   if ((IS_ITEMP (IC_RESULT (ic)) &&
2922        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2923         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2924       IS_TRUE_SYMOP (IC_RESULT (ic)))
2925     {
2926
2927       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2928
2929       assignResultValue (IC_RESULT (ic));
2930
2931       freeAsmop (IC_RESULT (ic), NULL, ic);
2932     }
2933
2934   /* adjust the stack for parameters if required */
2935   if (ic->parmBytes)
2936     {
2937       int i = ic->parmBytes;
2938
2939       _G.stack.pushed -= i;
2940       if (IS_GB)
2941         {
2942           emit2 ("!ldaspsp", i);
2943         }
2944       else
2945         {
2946           spillCached ();
2947           if (i > 8)
2948             {
2949               emit2 ("ld iy,!immedword", i);
2950               emit2 ("add iy,sp");
2951               emit2 ("ld sp,iy");
2952             }
2953           else
2954             {
2955               while (i > 1)
2956                 {
2957                   emit2 ("pop af");
2958                   i -= 2;
2959                 }
2960               if (i)
2961                 {
2962                   emit2 ("inc sp");
2963                 }
2964             }
2965         }
2966     }
2967
2968   spillCached ();
2969   if (IC_RESULT (ic))
2970     {
2971       bitVect *result = z80_rUmaskForOp (IC_RESULT (ic));
2972       bInRet = bitVectBitValue(result, B_IDX);
2973       cInRet = bitVectBitValue(result, C_IDX);
2974       dInRet = bitVectBitValue(result, D_IDX);
2975       eInRet = bitVectBitValue(result, E_IDX);
2976     }
2977   else
2978     {
2979       bInRet = FALSE;
2980       cInRet = FALSE;
2981       dInRet = FALSE;
2982       eInRet = FALSE;
2983     }
2984
2985   if (_G.stack.pushedDE)
2986     {
2987       if (dInRet && eInRet)
2988         {
2989           wassertl (0, "Shouldn't push DE if it's wiped out by the return");
2990         }
2991       else if (dInRet)
2992         {
2993           /* Only restore E */
2994           emit2 ("ld a,d");
2995           _pop (PAIR_DE);
2996           emit2 ("ld d,a");
2997         }
2998       else if (eInRet)
2999         {
3000           /* Only restore D */
3001           _pop (PAIR_AF);
3002           emit2 ("ld d,a");
3003         }
3004       else
3005         {
3006           _pop (PAIR_DE);
3007         }
3008       _G.stack.pushedDE = FALSE;
3009     }
3010
3011   if (_G.stack.pushedBC)
3012     {
3013       if (bInRet && cInRet)
3014         {
3015           wassertl (0, "Shouldn't push BC if it's wiped out by the return");
3016         }
3017       else if (bInRet)
3018         {
3019           /* Only restore C */
3020           emit2 ("ld a,b");
3021           _pop (PAIR_BC);
3022           emit2 ("ld b,a");
3023         }
3024       else if (cInRet)
3025         {
3026           /* Only restore B */
3027           _pop (PAIR_AF);
3028           emit2 ("ld b,a");
3029         }
3030       else
3031         {
3032           _pop (PAIR_BC);
3033         }
3034       _G.stack.pushedBC = FALSE;
3035     }
3036 }
3037
3038 /*-----------------------------------------------------------------*/
3039 /* genCall - generates a call statement                            */
3040 /*-----------------------------------------------------------------*/
3041 static void
3042 genCall (iCode * ic)
3043 {
3044   emitCall (ic, FALSE);
3045 }
3046
3047 /*-----------------------------------------------------------------*/
3048 /* genPcall - generates a call by pointer statement                */
3049 /*-----------------------------------------------------------------*/
3050 static void
3051 genPcall (iCode * ic)
3052 {
3053   emitCall (ic, TRUE);
3054 }
3055
3056 /*-----------------------------------------------------------------*/
3057 /* resultRemat - result  is rematerializable                       */
3058 /*-----------------------------------------------------------------*/
3059 static int
3060 resultRemat (iCode * ic)
3061 {
3062   if (SKIP_IC (ic) || ic->op == IFX)
3063     return 0;
3064
3065   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3066     {
3067       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3068       if (sym->remat && !POINTER_SET (ic))
3069         return 1;
3070     }
3071
3072   return 0;
3073 }
3074
3075 extern set *publics;
3076
3077 /*-----------------------------------------------------------------*/
3078 /* genFunction - generated code for function entry                 */
3079 /*-----------------------------------------------------------------*/
3080 static void
3081 genFunction (iCode * ic)
3082 {
3083   bool stackParm;
3084
3085   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3086   sym_link *ftype;
3087
3088   bool bcInUse = FALSE;
3089   bool deInUse = FALSE;
3090
3091   setArea (IFFUNC_NONBANKED (sym->type));
3092
3093   /* PENDING: Reset the receive offset as it
3094      doesn't seem to get reset anywhere else.
3095   */
3096   _G.receiveOffset = 0;
3097
3098   /* Record the last function name for debugging. */
3099   _G.lastFunctionName = sym->rname;
3100
3101   /* Create the function header */
3102   emit2 ("!functionheader", sym->name);
3103   if (!IS_STATIC(sym->etype))
3104     {
3105       sprintf (buffer, "%s_start", sym->rname);
3106       emit2 ("!labeldef", buffer);
3107     }
3108   emit2 ("!functionlabeldef", sym->rname);
3109
3110   ftype = operandType (IC_LEFT (ic));
3111
3112   if (IFFUNC_ISNAKED(ftype))
3113     {
3114       emitDebug("; naked function: no prologue.");
3115       return;
3116     }
3117
3118   /* if this is an interrupt service routine
3119      then save all potentially used registers. */
3120   if (IFFUNC_ISISR (sym->type))
3121     {
3122       /* If critical function then turn interrupts off */
3123       /* except when no interrupt number is given then it implies the NMI handler */
3124       if (IFFUNC_ISCRITICAL (sym->type) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC))
3125         {
3126           emit2 ("!di");
3127         }
3128
3129       emit2 ("!pusha");
3130     }
3131   else
3132     {
3133       /* This is a non-ISR function.
3134          If critical function then turn interrupts off */
3135       if (IFFUNC_ISCRITICAL (sym->type))
3136         {
3137           if (IS_GB)
3138             {
3139               emit2 ("!di");
3140             }
3141           else
3142             {
3143               //get interrupt enable flag IFF2 into P/O
3144               emit2 ("ld a,i");
3145               emit2 ("!di");
3146               //save P/O flag
3147               emit2 ("push af");
3148             }
3149         }
3150     }
3151
3152   if (options.profile)
3153     {
3154       emit2 ("!profileenter");
3155     }
3156
3157   /* PENDING: callee-save etc */
3158
3159   _G.stack.param_offset = 0;
3160
3161   if (z80_opts.calleeSavesBC)
3162     {
3163       bcInUse = TRUE;
3164     }
3165
3166   /* Detect which registers are used. */
3167   if (IFFUNC_CALLEESAVES(sym->type) && sym->regsUsed)
3168     {
3169       int i;
3170       for (i = 0; i < sym->regsUsed->size; i++)
3171         {
3172           if (bitVectBitValue (sym->regsUsed, i))
3173             {
3174               switch (i)
3175                 {
3176                 case C_IDX:
3177                 case B_IDX:
3178                   bcInUse = TRUE;
3179                   break;
3180                 case D_IDX:
3181                 case E_IDX:
3182                   if (IS_Z80) {
3183                     deInUse = TRUE;
3184                   }
3185                   else {
3186                     /* Other systems use DE as a temporary. */
3187                   }
3188                   break;
3189                 }
3190             }
3191         }
3192     }
3193
3194   if (bcInUse)
3195     {
3196       emit2 ("push bc");
3197       _G.stack.param_offset += 2;
3198     }
3199
3200   _G.calleeSaves.pushedBC = bcInUse;
3201
3202   if (deInUse)
3203     {
3204       emit2 ("push de");
3205       _G.stack.param_offset += 2;
3206     }
3207
3208   _G.calleeSaves.pushedDE = deInUse;
3209
3210   /* adjust the stack for the function */
3211   _G.stack.last = sym->stack;
3212
3213   stackParm = FALSE;
3214   for (sym = setFirstItem (istack->syms); sym;
3215        sym = setNextItem (istack->syms))
3216     {
3217       if (sym->_isparm && !IS_REGPARM (sym->etype))
3218         {
3219           stackParm = TRUE;
3220           break;
3221         }
3222     }
3223   sym = OP_SYMBOL (IC_LEFT (ic));
3224
3225   _G.omitFramePtr = options.ommitFramePtr;
3226   if (IS_Z80 && !stackParm && !sym->stack)
3227     {
3228       /* When the conflicts between AOP_EXSTK && AOP_HLREG are fixed, */
3229       /* the above !sym->stack condition can be removed. -- EEP       */
3230       if (sym->stack)
3231         emit2 ("!ldaspsp", -sym->stack);
3232       _G.omitFramePtr = TRUE;
3233     }
3234   else if (sym->stack && IS_GB && sym->stack > -INT8MIN)
3235     emit2 ("!enterxl", sym->stack);
3236   else if (sym->stack)
3237     emit2 ("!enterx", sym->stack);
3238   else
3239     emit2 ("!enter");
3240
3241   _G.stack.offset = sym->stack;
3242 }
3243
3244 /*-----------------------------------------------------------------*/
3245 /* genEndFunction - generates epilogue for functions               */
3246 /*-----------------------------------------------------------------*/
3247 static void
3248 genEndFunction (iCode * ic)
3249 {
3250   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3251
3252   if (IFFUNC_ISNAKED(sym->type))
3253   {
3254       emitDebug("; naked function: no epilogue.");
3255       return;
3256   }
3257
3258   /* PENDING: calleeSave */
3259   if (IS_Z80 && _G.omitFramePtr)
3260     {
3261       if (_G.stack.offset)
3262         emit2 ("!ldaspsp", _G.stack.offset);
3263     }
3264   else if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX)
3265     {
3266       emit2 ("!leavexl", _G.stack.offset);
3267     }
3268   else if (_G.stack.offset)
3269     {
3270       emit2 ("!leavex", _G.stack.offset);
3271     }
3272   else
3273     {
3274       emit2 ("!leave");
3275     }
3276
3277   if (_G.calleeSaves.pushedDE)
3278     {
3279       emit2 ("pop de");
3280       _G.calleeSaves.pushedDE = FALSE;
3281     }
3282
3283   if (_G.calleeSaves.pushedBC)
3284     {
3285       emit2 ("pop bc");
3286       _G.calleeSaves.pushedBC = FALSE;
3287     }
3288
3289   if (options.profile)
3290     {
3291       emit2 ("!profileexit");
3292     }
3293
3294   /* if this is an interrupt service routine
3295      then save all potentially used registers. */
3296   if (IFFUNC_ISISR (sym->type))
3297     {
3298       emit2 ("!popa");
3299
3300       /* If critical function then turn interrupts back on */
3301       /* except when no interrupt number is given then it implies the NMI handler */
3302       if (IFFUNC_ISCRITICAL (sym->type) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC))
3303         {
3304           emit2 ("!ei");
3305         }
3306     }
3307   else
3308     {
3309       /* This is a non-ISR function.
3310          If critical function then turn interrupts back on */
3311       if (IFFUNC_ISCRITICAL (sym->type))
3312         {
3313           if (IS_GB)
3314             {
3315               emit2 ("!ei");
3316             }
3317           else
3318             {
3319               symbol *tlbl = newiTempLabel (NULL);
3320               //restore P/O flag
3321               emit2 ("pop af");
3322               //parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==>
3323               //don't enable interrupts as they were off before
3324               emit2 ("jp po,!tlabel", tlbl->key + 100);
3325               emit2 ("!ei");
3326               emit2 ("!tlabeldef", (tlbl->key + 100));
3327             }
3328         }
3329     }
3330
3331   if (options.debug && currFunc)
3332     {
3333       debugFile->writeEndFunction (currFunc, ic, 1);
3334     }
3335
3336   if (IFFUNC_ISISR (sym->type))
3337     {
3338       /* "critical interrupt" is used to imply NMI handler */
3339       if (IS_Z80 && IFFUNC_ISCRITICAL (sym->type) && FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3340         emit2 ("retn");
3341       else
3342         emit2 ("reti");
3343     }
3344   else
3345     {
3346       /* Both banked and non-banked just ret */
3347       emit2 ("ret");
3348     }
3349
3350   if (!IS_STATIC(sym->etype))
3351     {
3352       sprintf (buffer, "%s_end", sym->rname);
3353       emit2 ("!labeldef", buffer);
3354     }
3355
3356   _G.flushStatics = 1;
3357   _G.stack.pushed = 0;
3358   _G.stack.offset = 0;
3359 }
3360
3361 /*-----------------------------------------------------------------*/
3362 /* genRet - generate code for return statement                     */
3363 /*-----------------------------------------------------------------*/
3364 static void
3365 genRet (iCode * ic)
3366 {
3367     const char *l;
3368   /* Errk.  This is a hack until I can figure out how
3369      to cause dehl to spill on a call */
3370   int size, offset = 0;
3371
3372   /* if we have no return value then
3373      just generate the "ret" */
3374   if (!IC_LEFT (ic))
3375     goto jumpret;
3376
3377   /* we have something to return then
3378      move the return value into place */
3379   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3380   size = AOP_SIZE (IC_LEFT (ic));
3381
3382   aopDump("IC_LEFT", AOP(IC_LEFT(ic)));
3383
3384   #if 0
3385   if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
3386     {
3387       if (IS_GB)
3388         {
3389           emit2 ("ld de,%s", l);
3390         }
3391       else
3392         {
3393           emit2 ("ld hl,%s", l);
3394         }
3395     }
3396   #endif
3397   if (size==2)
3398     {
3399       fetchPair(IS_GB ? PAIR_DE : PAIR_HL, AOP (IC_LEFT (ic)));
3400     }
3401   else
3402     {
3403       if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
3404         {
3405           fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
3406           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
3407         }
3408       else
3409         {
3410           while (size--)
3411             {
3412               l = aopGet (AOP (IC_LEFT (ic)), offset,
3413                           FALSE);
3414               if (strcmp (_fReturn[offset], l))
3415                 emit2 ("ld %s,%s", _fReturn[offset], l);
3416               offset++;
3417             }
3418         }
3419     }
3420   freeAsmop (IC_LEFT (ic), NULL, ic);
3421
3422 jumpret:
3423   /* generate a jump to the return label
3424      if the next is not the return statement */
3425   if (!(ic->next && ic->next->op == LABEL &&
3426         IC_LABEL (ic->next) == returnLabel))
3427
3428     emit2 ("jp !tlabel", returnLabel->key + 100);
3429 }
3430
3431 /*-----------------------------------------------------------------*/
3432 /* genLabel - generates a label                                    */
3433 /*-----------------------------------------------------------------*/
3434 static void
3435 genLabel (iCode * ic)
3436 {
3437   /* special case never generate */
3438   if (IC_LABEL (ic) == entryLabel)
3439     return;
3440
3441   emitLabel (IC_LABEL (ic)->key + 100);
3442 }
3443
3444 /*-----------------------------------------------------------------*/
3445 /* genGoto - generates a ljmp                                      */
3446 /*-----------------------------------------------------------------*/
3447 static void
3448 genGoto (iCode * ic)
3449 {
3450   emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
3451 }
3452
3453 /*-----------------------------------------------------------------*/
3454 /* genPlusIncr :- does addition with increment if possible         */
3455 /*-----------------------------------------------------------------*/
3456 static bool
3457 genPlusIncr (iCode * ic)
3458 {
3459   unsigned int icount;
3460   unsigned int size = getDataSize (IC_RESULT (ic));
3461   PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
3462
3463   /* will try to generate an increment */
3464   /* if the right side is not a literal
3465      we cannot */
3466   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3467     return FALSE;
3468
3469   emitDebug ("; genPlusIncr");
3470
3471   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3472
3473   /* If result is a pair */
3474   if (resultId != PAIR_INVALID)
3475     {
3476       if (isLitWord (AOP (IC_LEFT (ic))))
3477         {
3478           fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
3479           return TRUE;
3480         }
3481       if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
3482         {
3483           if (getPairId (AOP (IC_LEFT (ic))) == PAIR_HL)
3484             {
3485               PAIR_ID freep = getFreePairId (ic);
3486               if (freep != PAIR_INVALID)
3487                 {
3488                   fetchPair (freep, AOP (IC_RIGHT (ic)));
3489                   emit2 ("add hl,%s", _pairs[freep].name);
3490                   return TRUE;
3491                 }
3492             }
3493           else
3494             {
3495               fetchPair (resultId, AOP (IC_RIGHT (ic)));
3496               emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
3497               return TRUE;
3498             }
3499         }
3500       if (icount > 5)
3501         return FALSE;
3502       /* Inc a pair */
3503       if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3504         {
3505           if (icount > 2)
3506             return FALSE;
3507           movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2);
3508         }
3509       while (icount--)
3510         {
3511           emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
3512         }
3513       return TRUE;
3514     }
3515
3516   if (IS_Z80 && isLitWord (AOP (IC_LEFT (ic))) && size == 2)
3517     {
3518       fetchLitPair (PAIR_HL, AOP (IC_LEFT (ic)), icount);
3519       commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
3520       return TRUE;
3521     }
3522
3523   /* if the literal value of the right hand side
3524      is greater than 4 then it is not worth it */
3525   if (icount > 4)
3526     return FALSE;
3527
3528   /* if increment 16 bits in register */
3529   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3530       size > 1 &&
3531       icount == 1
3532     )
3533     {
3534       int offset = 0;
3535       symbol *tlbl = NULL;
3536       tlbl = newiTempLabel (NULL);
3537       while (size--)
3538         {
3539           emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
3540           if (size)
3541             {
3542               emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3543             }
3544         }
3545       emitLabel (tlbl->key + 100);
3546       return TRUE;
3547     }
3548
3549   /* if the sizes are greater than 1 then we cannot */
3550   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3551       AOP_SIZE (IC_LEFT (ic)) > 1)
3552     return FALSE;
3553
3554   /* If the result is in a register then we can load then increment.
3555    */
3556   if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG)
3557     {
3558       aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), LSB, FALSE), LSB);
3559       while (icount--)
3560         {
3561           emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
3562         }
3563       return TRUE;
3564     }
3565
3566   /* we can if the aops of the left & result match or
3567      if they are in registers and the registers are the
3568      same */
3569   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3570     {
3571       while (icount--)
3572         {
3573           emit2 ("inc %s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
3574         }
3575       return TRUE;
3576     }
3577
3578   return FALSE;
3579 }
3580
3581 /*-----------------------------------------------------------------*/
3582 /* outBitAcc - output a bit in acc                                 */
3583 /*-----------------------------------------------------------------*/
3584 void
3585 outBitAcc (operand * result)
3586 {
3587   symbol *tlbl = newiTempLabel (NULL);
3588   /* if the result is a bit */
3589   if (AOP_TYPE (result) == AOP_CRY)
3590     {
3591       wassertl (0, "Tried to write A into a bit");
3592     }
3593   else
3594     {
3595       emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
3596       emit2 ("ld a,!one");
3597       emitLabel (tlbl->key + 100);
3598       outAcc (result);
3599     }
3600 }
3601
3602 bool
3603 couldDestroyCarry (asmop *aop)
3604 {
3605   if (aop)
3606     {
3607       if (aop->type == AOP_EXSTK || aop->type == AOP_IY)
3608         {
3609           return TRUE;
3610         }
3611     }
3612   return FALSE;
3613 }
3614
3615 static void
3616 shiftIntoPair (int idx, asmop *aop)
3617 {
3618   PAIR_ID id = PAIR_INVALID;
3619
3620   wassertl (IS_Z80, "Only implemented for the Z80");
3621   //  wassertl (aop->type == AOP_EXSTK, "Only implemented for EXSTK");
3622
3623   switch (idx)
3624     {
3625     case 0:
3626       id = PAIR_HL;
3627       break;
3628     case 1:
3629       id = PAIR_DE;
3630       _push (PAIR_DE);
3631       break;
3632     default:
3633       wassertl (0, "Internal error - hit default case");
3634     }
3635
3636   emitDebug ("; Shift into pair idx %u", idx);
3637
3638   if (id == PAIR_HL)
3639     {
3640       setupPair (PAIR_HL, aop, 0);
3641     }
3642   else
3643     {
3644       setupPair (PAIR_IY, aop, 0);
3645       emit2 ("push iy");
3646       emit2 ("pop %s", _pairs[id].name);
3647     }
3648
3649   aop->type = AOP_PAIRPTR;
3650   aop->aopu.aop_pairId = id;
3651   _G.pairs[id].offset = 0;
3652   _G.pairs[id].last_type = aop->type;
3653 }
3654
3655 static void
3656 setupToPreserveCarry (asmop *result, asmop *left, asmop *right)
3657 {
3658   wassert (left && right);
3659
3660   if (IS_Z80)
3661     {
3662       if (couldDestroyCarry (right) && couldDestroyCarry (result))
3663         {
3664           shiftIntoPair (0, right);
3665           /* check result again, in case right == result */
3666           if (couldDestroyCarry (result))
3667             shiftIntoPair (1, result);
3668         }
3669       else if (couldDestroyCarry (right))
3670         {
3671           if (getPairId (result) == PAIR_HL)
3672             _G.preserveCarry = TRUE;
3673           else
3674             shiftIntoPair (0, right);
3675         }
3676       else if (couldDestroyCarry (result))
3677         {
3678           shiftIntoPair (0, result);
3679         }
3680       else
3681         {
3682           /* Fine */
3683         }
3684     }
3685 }
3686
3687 /*-----------------------------------------------------------------*/
3688 /* genPlus - generates code for addition                           */
3689 /*-----------------------------------------------------------------*/
3690 static void
3691 genPlus (iCode * ic)
3692 {
3693   int size, offset = 0;
3694
3695   /* special cases :- */
3696
3697   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3698   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
3699   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3700
3701   /* Swap the left and right operands if:
3702
3703      if literal, literal on the right or
3704      if left requires ACC or right is already
3705      in ACC */
3706
3707   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3708       (AOP_NEEDSACC (IC_RIGHT (ic))) ||
3709       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3710     {
3711       operand *t = IC_RIGHT (ic);
3712       IC_RIGHT (ic) = IC_LEFT (ic);
3713       IC_LEFT (ic) = t;
3714     }
3715
3716   /* if both left & right are in bit
3717      space */
3718   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3719       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3720     {
3721       /* Cant happen */
3722       wassertl (0, "Tried to add two bits");
3723     }
3724
3725   /* if left in bit space & right literal */
3726   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3727       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3728     {
3729       /* Can happen I guess */
3730       wassertl (0, "Tried to add a bit to a literal");
3731     }
3732
3733   /* if I can do an increment instead
3734      of add then GOOD for ME */
3735   if (genPlusIncr (ic) == TRUE)
3736     goto release;
3737
3738   emitDebug ("; Can't optimise plus by inc, falling back to the normal way");
3739
3740   size = getDataSize (IC_RESULT (ic));
3741
3742   /* Special case when left and right are constant */
3743   if (isPair (AOP (IC_RESULT (ic))))
3744     {
3745       char *left, *right;
3746       left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
3747       right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
3748
3749       if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT && AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT &&
3750           left && right)
3751         {
3752           /* It's a pair */
3753           /* PENDING: fix */
3754           char buffer[100];
3755           sprintf (buffer, "#(%s + %s)", left, right);
3756           emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
3757           goto release;
3758         }
3759     }
3760
3761   if ((isPair (AOP (IC_RIGHT (ic))) || isPair (AOP (IC_LEFT (ic)))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
3762     {
3763       /* Fetch into HL then do the add */
3764       PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
3765       PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
3766
3767       spillPair (PAIR_HL);
3768
3769       if (left == PAIR_HL && right != PAIR_INVALID)
3770         {
3771           emit2 ("add hl,%s", _pairs[right].name);
3772           goto release;
3773         }
3774       else if (right == PAIR_HL && left != PAIR_INVALID)
3775         {
3776           emit2 ("add hl,%s", _pairs[left].name);
3777           goto release;
3778         }
3779       else if (right != PAIR_INVALID && right != PAIR_HL)
3780         {
3781           fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
3782           emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
3783           goto release;
3784         }
3785       else if (left != PAIR_INVALID && left != PAIR_HL)
3786         {
3787           fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3788           emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
3789           goto release;
3790         }
3791       else
3792         {
3793           /* Can't do it */
3794         }
3795     }
3796
3797   if (isPair (AOP (IC_RIGHT (ic))) && AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD && getPairId (AOP (IC_RIGHT (ic))) != PAIR_HL)
3798     {
3799       fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
3800       emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
3801       spillCached();
3802       commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
3803       goto release;
3804     }
3805
3806   /* Special case:
3807      ld hl,sp+n trashes C so we cant afford to do it during an
3808      add with stack based varibles.  Worst case is:
3809      ld  hl,sp+left
3810      ld  a,(hl)
3811      ld  hl,sp+right
3812      add (hl)
3813      ld  hl,sp+result
3814      ld  (hl),a
3815      ld  hl,sp+left+1
3816      ld  a,(hl)
3817      ld  hl,sp+right+1
3818      adc (hl)
3819      ld  hl,sp+result+1
3820      ld  (hl),a
3821      So you cant afford to load up hl if either left, right, or result
3822      is on the stack (*sigh*)  The alt is:
3823      ld  hl,sp+left
3824      ld  de,(hl)
3825      ld  hl,sp+right
3826      ld  hl,(hl)
3827      add hl,de
3828      ld  hl,sp+result
3829      ld  (hl),hl
3830      Combinations in here are:
3831      * If left or right are in bc then the loss is small - trap later
3832      * If the result is in bc then the loss is also small
3833    */
3834   if (IS_GB)
3835     {
3836       if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
3837           AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
3838           AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
3839         {
3840           if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
3841                AOP_SIZE (IC_RIGHT (ic)) == 2) &&
3842               (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
3843                AOP_SIZE (IC_RIGHT (ic)) <= 2))
3844             {
3845               if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
3846                 {
3847                   /* Swap left and right */
3848                   operand *t = IC_RIGHT (ic);
3849                   IC_RIGHT (ic) = IC_LEFT (ic);
3850                   IC_LEFT (ic) = t;
3851                 }
3852               if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
3853                 {
3854                   fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3855                   emit2 ("add hl,bc");
3856                 }
3857               else
3858                 {
3859                   fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
3860                   fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
3861                   emit2 ("add hl,de");
3862                 }
3863               commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
3864               goto release;
3865             }
3866         }
3867       if (size == 4)
3868         {
3869           /* Be paranoid on the GB with 4 byte variables due to how C
3870              can be trashed by lda hl,n(sp).
3871           */
3872           _gbz80_emitAddSubLong (ic, TRUE);
3873           goto release;
3874         }
3875     }
3876
3877   setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
3878
3879   while (size--)
3880     {
3881       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3882         {
3883           _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3884           if (offset == 0)
3885             emit2 ("add a,%s",
3886                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3887           else
3888             emit2 ("adc a,%s",
3889                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3890         }
3891       else
3892         {
3893           _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
3894           if (offset == 0)
3895             emit2 ("add a,%s",
3896                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3897           else
3898             emit2 ("adc a,%s",
3899                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
3900         }
3901       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3902     }
3903
3904 release:
3905   _G.preserveCarry = FALSE;
3906   freeAsmop (IC_LEFT (ic), NULL, ic);
3907   freeAsmop (IC_RIGHT (ic), NULL, ic);
3908   freeAsmop (IC_RESULT (ic), NULL, ic);
3909
3910 }
3911
3912 /*-----------------------------------------------------------------*/
3913 /* genMinusDec :- does subtraction with deccrement if possible     */
3914 /*-----------------------------------------------------------------*/
3915 static bool
3916 genMinusDec (iCode * ic)
3917 {
3918   unsigned int icount;
3919   unsigned int size = getDataSize (IC_RESULT (ic));
3920
3921   /* will try to generate an increment */
3922   /* if the right side is not a literal we cannot */
3923   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3924     return FALSE;
3925
3926   /* if the literal value of the right hand side
3927      is greater than 4 then it is not worth it */
3928   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
3929     return FALSE;
3930
3931   size = getDataSize (IC_RESULT (ic));
3932
3933   /* if decrement 16 bits in register */
3934   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3935       (size > 1) && isPair (AOP (IC_RESULT (ic))))
3936     {
3937       while (icount--)
3938         emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
3939       return TRUE;
3940     }
3941
3942   /* If result is a pair */
3943   if (isPair (AOP (IC_RESULT (ic))))
3944     {
3945       movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2);
3946       while (icount--)
3947         emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
3948       return TRUE;
3949     }
3950
3951   /* if increment 16 bits in register */
3952   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3953       (size == 2)
3954       )
3955     {
3956       fetchPair (_getTempPairId(), AOP (IC_RESULT (ic)));
3957
3958       while (icount--) {
3959         emit2 ("dec %s", _getTempPairName());
3960       }
3961
3962       commitPair (AOP (IC_RESULT (ic)), _getTempPairId());
3963
3964       return TRUE;
3965     }
3966
3967
3968   /* if the sizes are greater than 1 then we cannot */
3969   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3970       AOP_SIZE (IC_LEFT (ic)) > 1)
3971     return FALSE;
3972
3973   /* we can if the aops of the left & result match or if they are in
3974      registers and the registers are the same */
3975   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3976     {
3977       while (icount--)
3978         emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
3979       return TRUE;
3980     }
3981
3982   return FALSE;
3983 }
3984
3985 /*-----------------------------------------------------------------*/
3986 /* genMinus - generates code for subtraction                       */
3987 /*-----------------------------------------------------------------*/
3988 static void
3989 genMinus (iCode * ic)
3990 {
3991   int size, offset = 0;
3992   unsigned long lit = 0L;
3993
3994   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3995   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
3996   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3997
3998   /* special cases :- */
3999   /* if both left & right are in bit space */
4000   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4001       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4002     {
4003       wassertl (0, "Tried to subtract two bits");
4004       goto release;
4005     }
4006
4007   /* if I can do an decrement instead of subtract then GOOD for ME */
4008   if (genMinusDec (ic) == TRUE)
4009     goto release;
4010
4011   size = getDataSize (IC_RESULT (ic));
4012
4013   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4014     {
4015     }
4016   else
4017     {
4018       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4019       lit = -(long) lit;
4020     }
4021
4022   /* Same logic as genPlus */
4023   if (IS_GB)
4024     {
4025       if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
4026           AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
4027           AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
4028         {
4029           if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
4030                AOP_SIZE (IC_RIGHT (ic)) == 2) &&
4031               (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
4032                AOP_SIZE (IC_RIGHT (ic)) <= 2))
4033             {
4034               PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
4035               PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
4036
4037               if (left == PAIR_INVALID && right == PAIR_INVALID)
4038                 {
4039                   left = PAIR_DE;
4040                   right = PAIR_HL;
4041                 }
4042               else if (right == PAIR_INVALID)
4043                 right = PAIR_DE;
4044               else if (left == PAIR_INVALID)
4045                 left = PAIR_DE;
4046
4047               fetchPair (left, AOP (IC_LEFT (ic)));
4048               /* Order is important.  Right may be HL */
4049               fetchPair (right, AOP (IC_RIGHT (ic)));
4050
4051               emit2 ("ld a,%s", _pairs[left].l);
4052               emit2 ("sub a,%s", _pairs[right].l);
4053               emit2 ("ld e,a");
4054               emit2 ("ld a,%s", _pairs[left].h);
4055               emit2 ("sbc a,%s", _pairs[right].h);
4056
4057               if ( AOP_SIZE (IC_RESULT (ic)) > 1)
4058                 {
4059                   aopPut (AOP (IC_RESULT (ic)), "a", 1);
4060                 }
4061               aopPut (AOP (IC_RESULT (ic)), "e", 0);
4062               goto release;
4063             }
4064         }
4065       if (size == 4)
4066         {
4067           /* Be paranoid on the GB with 4 byte variables due to how C
4068              can be trashed by lda hl,n(sp).
4069           */
4070           _gbz80_emitAddSubLong (ic, FALSE);
4071           goto release;
4072         }
4073     }
4074
4075   setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
4076
4077   /* if literal, add a,#-lit, else normal subb */
4078   while (size--)
4079     {
4080       _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
4081       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4082         {
4083           if (!offset)
4084             emit2 ("sub a,%s",
4085                       aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
4086           else
4087             emit2 ("sbc a,%s",
4088                       aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
4089         }
4090       else
4091         {
4092           /* first add without previous c */
4093           if (!offset)
4094             emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
4095           else
4096             emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4097         }
4098       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4099     }
4100
4101   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4102       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4103       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4104     {
4105       wassertl (0, "Tried to subtract on a long pointer");
4106     }
4107
4108 release:
4109   _G.preserveCarry = FALSE;
4110   freeAsmop (IC_LEFT (ic), NULL, ic);
4111   freeAsmop (IC_RIGHT (ic), NULL, ic);
4112   freeAsmop (IC_RESULT (ic), NULL, ic);
4113 }
4114
4115 /*-----------------------------------------------------------------*/
4116 /* genMult - generates code for multiplication                     */
4117 /*-----------------------------------------------------------------*/
4118 static void
4119 genMult (iCode * ic)
4120 {
4121   int val;
4122   int count, i;
4123   /* If true then the final operation should be a subtract */
4124   bool active = FALSE;
4125   bool byteResult;
4126
4127   /* Shouldn't occur - all done through function calls */
4128   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4129   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
4130   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4131
4132   byteResult =  (AOP_SIZE (IC_RESULT (ic)) == 1);
4133
4134   if (AOP_SIZE (IC_LEFT (ic)) > 2 ||
4135       AOP_SIZE (IC_RIGHT (ic)) > 2 ||
4136       AOP_SIZE (IC_RESULT (ic)) > 2)
4137     {
4138       wassertl (0, "Multiplication is handled through support function calls");
4139     }
4140
4141   /* Swap left and right such that right is a literal */
4142   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT))
4143     {
4144       operand *t = IC_RIGHT (ic);
4145       IC_RIGHT (ic) = IC_LEFT (ic);
4146       IC_LEFT (ic) = t;
4147     }
4148
4149   wassertl (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT, "Right must be a literal");
4150
4151   val = (int)floatFromVal ( AOP (IC_RIGHT (ic))->aopu.aop_lit);
4152   //  wassertl (val > 0, "Multiply must be positive");
4153   wassertl (val != 1, "Can't multiply by 1");
4154
4155   if (IS_Z80 && isPairInUseNotInRet (PAIR_DE, ic)) {
4156     _push (PAIR_DE);
4157     _G.stack.pushedDE = TRUE;
4158   }
4159
4160   if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
4161     {
4162       emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
4163       if (!byteResult)
4164         {
4165           emit2 ("ld a,e");
4166           emit2 ("rlc a");
4167           emit2 ("sbc a,a");
4168           emit2 ("ld d,a");
4169         }
4170     }
4171   else
4172     {
4173       fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
4174     }
4175
4176   i = val;
4177
4178   /* Fully unroled version of mul.s.  Not the most efficient.
4179    */
4180   for (count = 0; count < 16; count++)
4181     {
4182       if (count != 0 && active)
4183         {
4184           emit2 ("add hl,hl");
4185         }
4186       if (i & 0x8000U)
4187         {
4188           if (active == FALSE)
4189             {
4190               emit2 ("ld l,e");
4191               if (!byteResult)
4192                 emit2 ("ld h,d");
4193             }
4194           else
4195             {
4196               emit2 ("add hl,de");
4197             }
4198           active = TRUE;
4199         }
4200       i <<= 1;
4201     }
4202
4203   spillCached();
4204
4205   if (IS_Z80 && _G.stack.pushedDE)
4206     {
4207       _pop (PAIR_DE);
4208       _G.stack.pushedDE = FALSE;
4209     }
4210
4211   if (byteResult)
4212     aopPut (AOP (IC_RESULT (ic)), _pairs[PAIR_HL].l, 0);
4213   else
4214     commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
4215
4216   freeAsmop (IC_LEFT (ic), NULL, ic);
4217   freeAsmop (IC_RIGHT (ic), NULL, ic);
4218   freeAsmop (IC_RESULT (ic), NULL, ic);
4219 }
4220
4221 /*-----------------------------------------------------------------*/
4222 /* genDiv - generates code for division                            */
4223 /*-----------------------------------------------------------------*/
4224 static void
4225 genDiv (iCode * ic)
4226 {
4227   /* Shouldn't occur - all done through function calls */
4228   wassertl (0, "Division is handled through support function calls");
4229 }
4230
4231 /*-----------------------------------------------------------------*/
4232 /* genMod - generates code for division                            */
4233 /*-----------------------------------------------------------------*/
4234 static void
4235 genMod (iCode * ic)
4236 {
4237   /* Shouldn't occur - all done through function calls */
4238   wassert (0);
4239 }
4240
4241 /*-----------------------------------------------------------------*/
4242 /* genIfxJump :- will create a jump depending on the ifx           */
4243 /*-----------------------------------------------------------------*/
4244 static void
4245 genIfxJump (iCode * ic, char *jval)
4246 {
4247   symbol *jlbl;
4248   const char *inst;
4249
4250   /* if true label then we jump if condition
4251      supplied is true */
4252   if (IC_TRUE (ic))
4253     {
4254       jlbl = IC_TRUE (ic);
4255       if (!strcmp (jval, "a"))
4256         {
4257           inst = "nz";
4258         }
4259       else if (!strcmp (jval, "c"))
4260         {
4261           inst = "c";
4262         }
4263       else if (!strcmp (jval, "nc"))
4264         {
4265           inst = "nc";
4266         }
4267       else if (!strcmp (jval, "m"))
4268         {
4269           inst = "m";
4270         }
4271       else if (!strcmp (jval, "p"))
4272         {
4273           inst = "p";
4274         }
4275       else
4276         {
4277           /* The buffer contains the bit on A that we should test */
4278           inst = "nz";
4279         }
4280     }
4281   else
4282     {
4283       /* false label is present */
4284       jlbl = IC_FALSE (ic);
4285       if (!strcmp (jval, "a"))
4286         {
4287           inst = "z";
4288         }
4289       else if (!strcmp (jval, "c"))
4290         {
4291           inst = "nc";
4292         }
4293       else if (!strcmp (jval, "nc"))
4294         {
4295           inst = "c";
4296         }
4297       else if (!strcmp (jval, "m"))
4298         {
4299           inst = "p";
4300         }
4301       else if (!strcmp (jval, "p"))
4302         {
4303           inst = "m";
4304         }
4305       else
4306         {
4307           /* The buffer contains the bit on A that we should test */
4308           inst = "z";
4309         }
4310     }
4311   /* Z80 can do a conditional long jump */
4312   if (!strcmp (jval, "a"))
4313     {
4314       emit2 ("or a,a");
4315     }
4316   else if (!strcmp (jval, "c"))
4317     {
4318     }
4319   else if (!strcmp (jval, "nc"))
4320     {
4321     }
4322   else if (!strcmp (jval, "m"))
4323     {
4324     }
4325   else if (!strcmp (jval, "p"))
4326     {
4327     }
4328   else
4329     {
4330       emit2 ("bit %s,a", jval);
4331     }
4332   emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
4333
4334   /* mark the icode as generated */
4335   ic->generated = 1;
4336 }
4337
4338 #if DISABLED
4339 static const char *
4340 _getPairIdName (PAIR_ID id)
4341 {
4342   return _pairs[id].name;
4343 }
4344 #endif
4345
4346 #if OLD
4347       /* if unsigned char cmp with lit, just compare */
4348       if ((size == 1) &&
4349           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4350         {
4351           emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
4352           if (sign)
4353             {
4354               emit2 ("xor a,!immedbyte", 0x80);
4355               emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
4356             }
4357           else
4358             emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
4359         }
4360       else if (size == 4 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
4361         {
4362           // On the Gameboy we can't afford to adjust HL as it may trash the carry.
4363           // Pull left into DE and right into HL
4364           aopGet (AOP(left), LSB, FALSE);
4365           emit2 ("ld d,h");
4366           emit2 ("ld e,l");
4367           aopGet (AOP(right), LSB, FALSE);
4368
4369           while (size--)
4370             {
4371               if (size == 0 && sign)
4372                 {
4373                   // Highest byte when signed needs the bits flipped
4374                   // Save the flags
4375                   emit2 ("push af");
4376                   emit2 ("ld a,(de)");
4377                   emit2 ("xor !immedbyte", 0x80);
4378                   emit2 ("ld e,a");
4379                   emit2 ("ld a,(hl)");
4380                   emit2 ("xor !immedbyte", 0x80);
4381                   emit2 ("ld d,a");
4382                   emit2 ("pop af");
4383                   emit2 ("ld a,e");
4384                   emit2 ("%s a,d", offset == 0 ? "sub" : "sbc");
4385                 }
4386               else
4387                 {
4388                   emit2 ("ld a,(de)");
4389                   emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
4390                 }
4391
4392               if (size != 0)
4393                 {
4394                   emit2 ("inc hl");
4395                   emit2 ("inc de");
4396                 }
4397               offset++;
4398             }
4399           spillPair (PAIR_HL);
4400         }
4401       else if (size == 4 && IS_Z80 && couldDestroyCarry(AOP(right)) && couldDestroyCarry(AOP(left)))
4402         {
4403           setupPair (PAIR_HL, AOP (left), 0);
4404           aopGet (AOP(right), LSB, FALSE);
4405
4406           while (size--)
4407             {
4408               if (size == 0 && sign)
4409                 {
4410                   // Highest byte when signed needs the bits flipped
4411                   // Save the flags
4412                   emit2 ("push af");
4413                   emit2 ("ld a,(hl)");
4414                   emit2 ("xor !immedbyte", 0x80);
4415                   emit2 ("ld l,a");
4416                   emit2 ("ld a,%d(iy)", offset);
4417                   emit2 ("xor !immedbyte", 0x80);
4418                   emit2 ("ld h,a");
4419                   emit2 ("pop af");
4420                   emit2 ("ld a,l");
4421                   emit2 ("%s a,h", offset == 0 ? "sub" : "sbc");
4422                 }
4423               else
4424                 {
4425                   emit2 ("ld a,(hl)");
4426                   emit2 ("%s a,%d(iy)", offset == 0 ? "sub" : "sbc", offset);
4427                 }
4428
4429               if (size != 0)
4430                 {
4431                   emit2 ("inc hl");
4432                 }
4433               offset++;
4434             }
4435           spillPair (PAIR_HL);
4436           spillPair (PAIR_IY);
4437         }
4438       else
4439         {
4440           if (AOP_TYPE (right) == AOP_LIT)
4441             {
4442               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4443               /* optimize if(x < 0) or if(x >= 0) */
4444               if (lit == 0L)
4445                 {
4446                   if (!sign)
4447                     {
4448                       /* No sign so it's always false */
4449                       _clearCarry();
4450                     }
4451                   else
4452                     {
4453                       /* Just load in the top most bit */
4454                       _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
4455                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4456                         {
4457                           genIfxJump (ifx, "7");
4458                           return;
4459                         }
4460                       else
4461                         emit2 ("rlc a");
4462                     }
4463                   goto release;
4464                 }
4465             }
4466
4467           if (sign)
4468             {
4469               /* First setup h and l contaning the top most bytes XORed */
4470               bool fDidXor = FALSE;
4471               if (AOP_TYPE (left) == AOP_LIT)
4472                 {
4473                   unsigned long lit = (unsigned long)
4474                   floatFromVal (AOP (left)->aopu.aop_lit);
4475                   emit2 ("ld %s,!immedbyte", _fTmp[0],
4476                          0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
4477                 }
4478               else
4479                 {
4480                   emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
4481                   emit2 ("xor a,!immedbyte", 0x80);
4482                   emit2 ("ld %s,a", _fTmp[0]);
4483                   fDidXor = TRUE;
4484                 }
4485               if (AOP_TYPE (right) == AOP_LIT)
4486                 {
4487                   unsigned long lit = (unsigned long)
4488                   floatFromVal (AOP (right)->aopu.aop_lit);
4489                   emit2 ("ld %s,!immedbyte", _fTmp[1],
4490                          0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
4491                 }
4492               else
4493                 {
4494                   emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
4495                   emit2 ("xor a,!immedbyte", 0x80);
4496                   emit2 ("ld %s,a", _fTmp[1]);
4497                   fDidXor = TRUE;
4498                 }
4499             }
4500           while (size--)
4501             {
4502               /* Do a long subtract */
4503               if (!sign || size)
4504                 {
4505                   _moveA (aopGet (AOP (left), offset, FALSE));
4506                 }
4507               if (sign && size == 0)
4508                 {
4509                   emit2 ("ld a,%s", _fTmp[0]);
4510                   emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", _fTmp[1]);
4511                 }
4512               else
4513                 {
4514                   /* Subtract through, propagating the carry */
4515                   emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
4516                   offset++;
4517                 }
4518             }
4519         }
4520     }
4521 #endif
4522
4523 /** Generic compare for > or <
4524  */
4525 static void
4526 genCmp (operand * left, operand * right,
4527         operand * result, iCode * ifx, int sign)
4528 {
4529   int size, offset = 0;
4530   unsigned long lit = 0L;
4531   bool swap_sense = FALSE;
4532
4533   /* if left & right are bit variables */
4534   if (AOP_TYPE (left) == AOP_CRY &&
4535       AOP_TYPE (right) == AOP_CRY)
4536     {
4537       /* Cant happen on the Z80 */
4538       wassertl (0, "Tried to compare two bits");
4539     }
4540   else
4541     {
4542       /* Do a long subtract of right from left. */
4543       size = max (AOP_SIZE (left), AOP_SIZE (right));
4544
4545       if (size > 1 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
4546         {
4547           // On the Gameboy we can't afford to adjust HL as it may trash the carry.
4548           // Pull left into DE and right into HL
4549           aopGet (AOP(left), LSB, FALSE);
4550           emit2 ("ld d,h");
4551           emit2 ("ld e,l");
4552           aopGet (AOP(right), LSB, FALSE);
4553
4554           while (size--)
4555             {
4556               emit2 ("ld a,(de)");
4557               emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
4558
4559               if (size != 0)
4560                 {
4561                   emit2 ("inc hl");
4562                   emit2 ("inc de");
4563                 }
4564               offset++;
4565             }
4566           spillPair (PAIR_HL);
4567           goto release;
4568         }
4569
4570       if (AOP_TYPE (right) == AOP_LIT)
4571         {
4572           lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4573           /* optimize if(x < 0) or if(x >= 0) */
4574           if (lit == 0)
4575             {
4576               if (!sign)
4577                 {
4578                   /* No sign so it's always false */
4579                   _clearCarry();
4580                 }
4581               else
4582                 {
4583                   /* Just load in the top most bit */
4584                   _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
4585                   if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4586                     {
4587                       genIfxJump (ifx, "7");
4588                       return;
4589                     }
4590                   else
4591                     {
4592                       if (!sign)
4593                         {
4594                           emit2 ("rlc a");
4595                         }
4596                       if (ifx)
4597                         {
4598                           genIfxJump (ifx, swap_sense ? "c" : "nc");
4599                           return;
4600                         }
4601                     }
4602                 }
4603               goto release;
4604             }
4605         }
4606
4607       while (size--)
4608         {
4609           _moveA (aopGet (AOP (left), offset, FALSE));
4610           /* Subtract through, propagating the carry */
4611           emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
4612           offset++;
4613         }
4614     }
4615
4616 release:
4617   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4618     {
4619       if (sign)
4620         {
4621           /* Shift the sign bit up into carry */
4622           emit2 ("rlca");
4623         }
4624       outBitCLong (result, swap_sense);
4625     }
4626   else
4627     {
4628       /* if the result is used in the next
4629          ifx conditional branch then generate
4630          code a little differently */
4631       if (ifx)
4632         {
4633           if (sign)
4634             {
4635               if (IS_GB)
4636                 {
4637                   emit2 ("rlca");
4638                   genIfxJump (ifx, swap_sense ? "nc" : "c");
4639                 }
4640               else
4641                 {
4642                   genIfxJump (ifx, swap_sense ? "p" : "m");
4643                 }
4644             }
4645           else
4646             {
4647               genIfxJump (ifx, swap_sense ? "nc" : "c");
4648             }
4649         }
4650       else
4651         {
4652           if (sign)
4653             {
4654               /* Shift the sign bit up into carry */
4655               emit2 ("rlca");
4656             }
4657           outBitCLong (result, swap_sense);
4658         }
4659       /* leave the result in acc */
4660     }
4661 }
4662
4663 /*-----------------------------------------------------------------*/
4664 /* genCmpGt :- greater than comparison                             */
4665 /*-----------------------------------------------------------------*/
4666 static void
4667 genCmpGt (iCode * ic, iCode * ifx)
4668 {
4669   operand *left, *right, *result;
4670   sym_link *letype, *retype;
4671   int sign;
4672
4673   left = IC_LEFT (ic);
4674   right = IC_RIGHT (ic);
4675   result = IC_RESULT (ic);
4676
4677   letype = getSpec (operandType (left));
4678   retype = getSpec (operandType (right));
4679   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4680   /* assign the amsops */
4681   aopOp (left, ic, FALSE, FALSE);
4682   aopOp (right, ic, FALSE, FALSE);
4683   aopOp (result, ic, TRUE, FALSE);
4684
4685   genCmp (right, left, result, ifx, sign);
4686
4687   freeAsmop (left, NULL, ic);
4688   freeAsmop (right, NULL, ic);
4689   freeAsmop (result, NULL, ic);
4690 }
4691
4692 /*-----------------------------------------------------------------*/
4693 /* genCmpLt - less than comparisons                                */
4694 /*-----------------------------------------------------------------*/
4695 static void
4696 genCmpLt (iCode * ic, iCode * ifx)
4697 {
4698   operand *left, *right, *result;
4699   sym_link *letype, *retype;
4700   int sign;
4701
4702   left = IC_LEFT (ic);
4703   right = IC_RIGHT (ic);
4704   result = IC_RESULT (ic);
4705
4706   letype = getSpec (operandType (left));
4707   retype = getSpec (operandType (right));
4708   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4709
4710   /* assign the amsops */
4711   aopOp (left, ic, FALSE, FALSE);
4712   aopOp (right, ic, FALSE, FALSE);
4713   aopOp (result, ic, TRUE, FALSE);
4714
4715   genCmp (left, right, result, ifx, sign);
4716
4717   freeAsmop (left, NULL, ic);
4718   freeAsmop (right, NULL, ic);
4719   freeAsmop (result, NULL, ic);
4720 }
4721
4722 /*-----------------------------------------------------------------*/
4723 /* gencjneshort - compare and jump if not equal                    */
4724 /*-----------------------------------------------------------------*/
4725 static void
4726 gencjneshort (operand * left, operand * right, symbol * lbl)
4727 {
4728   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4729   int offset = 0;
4730   unsigned long lit = 0L;
4731
4732   /* Swap the left and right if it makes the computation easier */
4733   if (AOP_TYPE (left) == AOP_LIT)
4734     {
4735       operand *t = right;
4736       right = left;
4737       left = t;
4738     }
4739
4740   if (AOP_TYPE (right) == AOP_LIT)
4741     {
4742       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4743     }
4744
4745   /* if the right side is a literal then anything goes */
4746   if (AOP_TYPE (right) == AOP_LIT &&
4747       AOP_TYPE (left) != AOP_DIR)
4748     {
4749       if (lit == 0)
4750         {
4751           emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
4752           if (size > 1)
4753             {
4754               while (--size)
4755                 {
4756                   emit2 ("or a,%s", aopGet (AOP (left), ++offset, FALSE));
4757                 }
4758             }
4759           else
4760             {
4761               emit2 ("or a,a");
4762             }
4763           emit2 ("jp nz,!tlabel", lbl->key + 100);
4764         }
4765       else
4766         {
4767           while (size--)
4768             {
4769               emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
4770               if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
4771                 emit2 ("or a,a");
4772               else
4773                 emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
4774               emit2 ("jp nz,!tlabel", lbl->key + 100);
4775               offset++;
4776             }
4777         }
4778     }
4779   /* if the right side is in a register or in direct space or
4780      if the left is a pointer register & right is not */
4781   else if (AOP_TYPE (right) == AOP_REG ||
4782            AOP_TYPE (right) == AOP_DIR ||
4783            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
4784     {
4785       while (size--)
4786         {
4787           _moveA (aopGet (AOP (left), offset, FALSE));
4788           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4789               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4790             /* PENDING */
4791             emit2 ("jp nz,!tlabel", lbl->key + 100);
4792           else
4793             {
4794               emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
4795               emit2 ("jp nz,!tlabel", lbl->key + 100);
4796             }
4797           offset++;
4798         }
4799     }
4800   else
4801     {
4802       /* right is a pointer reg need both a & b */
4803       /* PENDING: is this required? */
4804       while (size--)
4805         {
4806           _moveA (aopGet (AOP (right), offset, FALSE));
4807           emit2 ("cp %s", aopGet (AOP (left), offset, FALSE));
4808           emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
4809           offset++;
4810         }
4811     }
4812 }
4813
4814 /*-----------------------------------------------------------------*/
4815 /* gencjne - compare and jump if not equal                         */
4816 /*-----------------------------------------------------------------*/
4817 static void
4818 gencjne (operand * left, operand * right, symbol * lbl)
4819 {
4820   symbol *tlbl = newiTempLabel (NULL);
4821
4822   gencjneshort (left, right, lbl);
4823
4824   /* PENDING: ?? */
4825   emit2 ("ld a,!one");
4826   emit2 ("!shortjp !tlabel", tlbl->key + 100);
4827   emitLabel (lbl->key + 100);
4828   emit2 ("xor a,a");
4829   emitLabel (tlbl->key + 100);
4830 }
4831
4832 /*-----------------------------------------------------------------*/
4833 /* genCmpEq - generates code for equal to                          */
4834 /*-----------------------------------------------------------------*/
4835 static void
4836 genCmpEq (iCode * ic, iCode * ifx)
4837 {
4838   operand *left, *right, *result;
4839
4840   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4841   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4842   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4843
4844   emitDebug ("; genCmpEq: left %u, right %u, result %u", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
4845
4846   /* Swap operands if it makes the operation easier. ie if:
4847      1.  Left is a literal.
4848    */
4849   if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4850     {
4851       operand *t = IC_RIGHT (ic);
4852       IC_RIGHT (ic) = IC_LEFT (ic);
4853       IC_LEFT (ic) = t;
4854     }
4855
4856   if (ifx && !AOP_SIZE (result))
4857     {
4858       symbol *tlbl;
4859       /* if they are both bit variables */
4860       if (AOP_TYPE (left) == AOP_CRY &&
4861           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4862         {
4863           wassertl (0, "Tried to compare two bits");
4864         }
4865       else
4866         {
4867           tlbl = newiTempLabel (NULL);
4868           gencjneshort (left, right, tlbl);
4869           if (IC_TRUE (ifx))
4870             {
4871               emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
4872               emitLabel (tlbl->key + 100);
4873             }
4874           else
4875             {
4876               /* PENDING: do this better */
4877               symbol *lbl = newiTempLabel (NULL);
4878               emit2 ("!shortjp !tlabel", lbl->key + 100);
4879               emitLabel (tlbl->key + 100);
4880               emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
4881               emitLabel (lbl->key + 100);
4882             }
4883         }
4884       /* mark the icode as generated */
4885       ifx->generated = 1;
4886       goto release;
4887     }
4888
4889   /* if they are both bit variables */
4890   if (AOP_TYPE (left) == AOP_CRY &&
4891       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4892     {
4893       wassertl (0, "Tried to compare a bit to either a literal or another bit");
4894     }
4895   else
4896     {
4897       emitDebug(";4");
4898
4899       gencjne (left, right, newiTempLabel (NULL));
4900       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4901         {
4902           wassert (0);
4903         }
4904       if (ifx)
4905         {
4906           emitDebug(";5");
4907           genIfxJump (ifx, "a");
4908           goto release;
4909         }
4910       /* if the result is used in an arithmetic operation
4911          then put the result in place */
4912       if (AOP_TYPE (result) != AOP_CRY)
4913         {
4914           emitDebug(";6");
4915           outAcc (result);
4916         }
4917       /* leave the result in acc */
4918     }
4919
4920 release:
4921   freeAsmop (left, NULL, ic);
4922   freeAsmop (right, NULL, ic);
4923   freeAsmop (result, NULL, ic);
4924 }
4925
4926 /*-----------------------------------------------------------------*/
4927 /* ifxForOp - returns the icode containing the ifx for operand     */
4928 /*-----------------------------------------------------------------*/
4929 static iCode *
4930 ifxForOp (operand * op, iCode * ic)
4931 {
4932   /* if true symbol then needs to be assigned */
4933   if (IS_TRUE_SYMOP (op))
4934     return NULL;
4935
4936   /* if this has register type condition and
4937      the next instruction is ifx with the same operand
4938      and live to of the operand is upto the ifx only then */
4939   if (ic->next &&
4940       ic->next->op == IFX &&
4941       IC_COND (ic->next)->key == op->key &&
4942       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4943     return ic->next;
4944
4945   return NULL;
4946 }
4947
4948 /*-----------------------------------------------------------------*/
4949 /* genAndOp - for && operation                                     */
4950 /*-----------------------------------------------------------------*/
4951 static void
4952 genAndOp (iCode * ic)
4953 {
4954   operand *left, *right, *result;
4955   symbol *tlbl;
4956
4957   /* note here that && operations that are in an if statement are
4958      taken away by backPatchLabels only those used in arthmetic
4959      operations remain */
4960   aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
4961   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
4962   aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
4963
4964   /* if both are bit variables */
4965   if (AOP_TYPE (left) == AOP_CRY &&
4966       AOP_TYPE (right) == AOP_CRY)
4967     {
4968       wassertl (0, "Tried to and two bits");
4969     }
4970   else
4971     {
4972       tlbl = newiTempLabel (NULL);
4973       _toBoolean (left);
4974       emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
4975       _toBoolean (right);
4976       emitLabel (tlbl->key + 100);
4977       outBitAcc (result);
4978     }
4979
4980   freeAsmop (left, NULL, ic);
4981   freeAsmop (right, NULL, ic);
4982   freeAsmop (result, NULL, ic);
4983 }
4984
4985 /*-----------------------------------------------------------------*/
4986 /* genOrOp - for || operation                                      */
4987 /*-----------------------------------------------------------------*/
4988 static void
4989 genOrOp (iCode * ic)
4990 {
4991   operand *left, *right, *result;
4992   symbol *tlbl;
4993
4994   /* note here that || operations that are in an
4995      if statement are taken away by backPatchLabels
4996      only those used in arthmetic operations remain */
4997   aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
4998   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
4999   aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
5000
5001   /* if both are bit variables */
5002   if (AOP_TYPE (left) == AOP_CRY &&
5003       AOP_TYPE (right) == AOP_CRY)
5004     {
5005       wassertl (0, "Tried to OR two bits");
5006     }
5007   else
5008     {
5009       tlbl = newiTempLabel (NULL);
5010       _toBoolean (left);
5011       emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5012       _toBoolean (right);
5013       emitLabel (tlbl->key + 100);
5014       outBitAcc (result);
5015     }
5016
5017   freeAsmop (left, NULL, ic);
5018   freeAsmop (right, NULL, ic);
5019   freeAsmop (result, NULL, ic);
5020 }
5021
5022 /*-----------------------------------------------------------------*/
5023 /* isLiteralBit - test if lit == 2^n                               */
5024 /*-----------------------------------------------------------------*/
5025 int
5026 isLiteralBit (unsigned long lit)
5027 {
5028   unsigned long pw[32] =
5029   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5030    0x100L, 0x200L, 0x400L, 0x800L,
5031    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5032    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5033    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5034    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5035    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5036   int idx;
5037
5038   for (idx = 0; idx < 32; idx++)
5039     if (lit == pw[idx])
5040       return idx + 1;
5041   return 0;
5042 }
5043
5044 /*-----------------------------------------------------------------*/
5045 /* jmpTrueOrFalse -                                                */
5046 /*-----------------------------------------------------------------*/
5047 static void
5048 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5049 {
5050   // ugly but optimized by peephole
5051   if (IC_TRUE (ic))
5052     {
5053       symbol *nlbl = newiTempLabel (NULL);
5054       emit2 ("jp !tlabel", nlbl->key + 100);
5055       emitLabel (tlbl->key + 100);
5056       emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
5057       emitLabel (nlbl->key + 100);
5058     }
5059   else
5060     {
5061       emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
5062       emitLabel (tlbl->key + 100);
5063     }
5064   ic->generated = 1;
5065 }
5066
5067 /*-----------------------------------------------------------------*/
5068 /* genAnd  - code for and                                          */
5069 /*-----------------------------------------------------------------*/
5070 static void
5071 genAnd (iCode * ic, iCode * ifx)
5072 {
5073   operand *left, *right, *result;
5074   int size, offset = 0;
5075   unsigned long lit = 0L;
5076   int bytelit = 0;
5077
5078   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
5079   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
5080   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
5081
5082   /* if left is a literal & right is not then exchange them */
5083   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5084       (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
5085     {
5086       operand *tmp = right;
5087       right = left;
5088       left = tmp;
5089     }
5090
5091   /* if result = right then exchange them */
5092   if (sameRegs (AOP (result), AOP (right)))
5093     {
5094       operand *tmp = right;
5095       right = left;
5096       left = tmp;
5097     }
5098
5099   /* if right is bit then exchange them */
5100   if (AOP_TYPE (right) == AOP_CRY &&
5101       AOP_TYPE (left) != AOP_CRY)
5102     {
5103       operand *tmp = right;
5104       right = left;
5105       left = tmp;
5106     }
5107   if (AOP_TYPE (right) == AOP_LIT)
5108     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5109
5110   size = AOP_SIZE (result);
5111
5112   if (AOP_TYPE (left) == AOP_CRY)
5113     {
5114       wassertl (0, "Tried to perform an AND with a bit as an operand");
5115       goto release;
5116     }
5117
5118   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5119   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5120   if ((AOP_TYPE (right) == AOP_LIT) &&
5121       (AOP_TYPE (result) == AOP_CRY) &&
5122       (AOP_TYPE (left) != AOP_CRY))
5123     {
5124       symbol *tlbl = newiTempLabel (NULL);
5125       int sizel = AOP_SIZE (left);
5126       if (size)
5127         {
5128           /* PENDING: Test case for this. */
5129           emit2 ("scf");
5130         }
5131       while (sizel--)
5132         {
5133           if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5134             {
5135               _moveA (aopGet (AOP (left), offset, FALSE));
5136               if (bytelit != 0x0FFL)
5137                 {
5138                   emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
5139                 }
5140               else
5141                 {
5142                   /* For the flags */
5143                   emit2 ("or a,a");
5144                 }
5145               emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5146             }
5147               offset++;
5148         }
5149       // bit = left & literal
5150       if (size)
5151         {
5152           emit2 ("clr c");
5153           emit2 ("!tlabeldef", tlbl->key + 100);
5154         }
5155       // if(left & literal)
5156       else
5157         {
5158           if (ifx)
5159             {
5160               jmpTrueOrFalse (ifx, tlbl);
5161             }
5162           goto release;
5163         }
5164       outBitC (result);
5165       goto release;
5166     }
5167
5168   /* if left is same as result */
5169   if (sameRegs (AOP (result), AOP (left)))
5170     {
5171       for (; size--; offset++)
5172         {
5173           if (AOP_TYPE (right) == AOP_LIT)
5174             {
5175               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5176                 continue;
5177               else
5178                 {
5179                   if (bytelit == 0)
5180                     aopPut (AOP (result), "!zero", offset);
5181                   else
5182                     {
5183                       _moveA (aopGet (AOP (left), offset, FALSE));
5184                       emit2 ("and a,%s",
5185                                 aopGet (AOP (right), offset, FALSE));
5186                       aopPut (AOP (left), "a", offset);
5187                     }
5188                 }
5189
5190             }
5191           else
5192             {
5193               if (AOP_TYPE (left) == AOP_ACC)
5194                 {
5195                   wassertl (0, "Tried to perform an AND where the left operand is allocated into A");
5196                 }
5197               else
5198                 {
5199                   _moveA (aopGet (AOP (left), offset, FALSE));
5200                   emit2 ("and a,%s",
5201                             aopGet (AOP (right), offset, FALSE));
5202                   aopPut (AOP (left), "a", offset);
5203                 }
5204             }
5205         }
5206     }
5207   else
5208     {
5209       // left & result in different registers
5210       if (AOP_TYPE (result) == AOP_CRY)
5211         {
5212           wassertl (0, "Tried to AND where the result is in carry");
5213         }
5214       else
5215         {
5216           for (; (size--); offset++)
5217             {
5218               // normal case
5219               // result = left & right
5220               if (AOP_TYPE (right) == AOP_LIT)
5221                 {
5222                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5223                     {
5224                       aopPut (AOP (result),
5225                               aopGet (AOP (left), offset, FALSE),
5226                               offset);
5227                       continue;
5228                     }
5229                   else if (bytelit == 0)
5230                     {
5231                       aopPut (AOP (result), "!zero", offset);
5232                       continue;
5233                     }
5234                 }
5235               // faster than result <- left, anl result,right
5236               // and better if result is SFR
5237               if (AOP_TYPE (left) == AOP_ACC)
5238                 emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
5239               else
5240                 {
5241                   _moveA (aopGet (AOP (left), offset, FALSE));
5242                   emit2 ("and a,%s",
5243                             aopGet (AOP (right), offset, FALSE));
5244                 }
5245               aopPut (AOP (result), "a", offset);
5246             }
5247         }
5248
5249     }
5250
5251 release:
5252   freeAsmop (left, NULL, ic);
5253   freeAsmop (right, NULL, ic);
5254   freeAsmop (result, NULL, ic);
5255 }
5256
5257 /*-----------------------------------------------------------------*/
5258 /* genOr  - code for or                                            */
5259 /*-----------------------------------------------------------------*/
5260 static void
5261 genOr (iCode * ic, iCode * ifx)
5262 {
5263   operand *left, *right, *result;
5264   int size, offset = 0;
5265   unsigned long lit = 0L;
5266   int bytelit = 0;
5267
5268   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
5269   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
5270   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
5271
5272   /* if left is a literal & right is not then exchange them */
5273   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5274       (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
5275     {
5276       operand *tmp = right;
5277       right = left;
5278       left = tmp;
5279     }
5280
5281   /* if result = right then exchange them */
5282   if (sameRegs (AOP (result), AOP (right)))
5283     {
5284       operand *tmp = right;
5285       right = left;
5286       left = tmp;
5287     }
5288
5289   /* if right is bit then exchange them */
5290   if (AOP_TYPE (right) == AOP_CRY &&
5291       AOP_TYPE (left) != AOP_CRY)
5292     {
5293       operand *tmp = right;
5294       right = left;
5295       left = tmp;
5296     }
5297   if (AOP_TYPE (right) == AOP_LIT)
5298     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5299
5300   size = AOP_SIZE (result);
5301
5302   if (AOP_TYPE (left) == AOP_CRY)
5303     {
5304       wassertl (0, "Tried to OR where left is a bit");
5305       goto release;
5306     }
5307
5308   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5309   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5310   if ((AOP_TYPE (right) == AOP_LIT) &&
5311       (AOP_TYPE (result) == AOP_CRY) &&
5312       (AOP_TYPE (left) != AOP_CRY))
5313     {
5314       symbol *tlbl = newiTempLabel (NULL);
5315       int sizel = AOP_SIZE (left);
5316
5317       if (size)
5318         {
5319           wassertl (0, "Result is assigned to a bit");
5320         }
5321       /* PENDING: Modeled after the AND code which is inefficient. */
5322       while (sizel--)
5323         {
5324           bytelit = (lit >> (offset * 8)) & 0x0FFL;
5325
5326           _moveA (aopGet (AOP (left), offset, FALSE));
5327           /* OR with any literal is the same as OR with itself. */
5328           emit2 ("or a,a");
5329           emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5330
5331           offset++;
5332         }
5333       if (ifx)
5334         {
5335           jmpTrueOrFalse (ifx, tlbl);
5336         }
5337       goto release;
5338     }
5339
5340   /* if left is same as result */
5341   if (sameRegs (AOP (result), AOP (left)))
5342     {
5343       for (; size--; offset++)
5344         {
5345           if (AOP_TYPE (right) == AOP_LIT)
5346             {
5347               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5348                 continue;
5349               else
5350                 {
5351                   _moveA (aopGet (AOP (left), offset, FALSE));
5352                   emit2 ("or a,%s",
5353                             aopGet (AOP (right), offset, FALSE));
5354                   aopPut (AOP (result), "a", offset);
5355                 }
5356             }
5357           else
5358             {
5359               if (AOP_TYPE (left) == AOP_ACC)
5360                 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
5361               else
5362                 {
5363                   _moveA (aopGet (AOP (left), offset, FALSE));
5364                   emit2 ("or a,%s",
5365                             aopGet (AOP (right), offset, FALSE));
5366                   aopPut (AOP (result), "a", offset);
5367                 }
5368             }
5369         }
5370     }
5371   else
5372     {
5373       // left & result in different registers
5374       if (AOP_TYPE (result) == AOP_CRY)
5375         {
5376           wassertl (0, "Result of OR is in a bit");
5377         }
5378       else
5379         for (; (size--); offset++)
5380           {
5381             // normal case
5382             // result = left & right
5383             if (AOP_TYPE (right) == AOP_LIT)
5384               {
5385                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5386                   {
5387                     aopPut (AOP (result),
5388                             aopGet (AOP (left), offset, FALSE),
5389                             offset);
5390                     continue;
5391                   }
5392               }
5393             // faster than result <- left, anl result,right
5394             // and better if result is SFR
5395             if (AOP_TYPE (left) == AOP_ACC)
5396               emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
5397             else
5398               {
5399                 _moveA (aopGet (AOP (left), offset, FALSE));
5400                 emit2 ("or a,%s",
5401                           aopGet (AOP (right), offset, FALSE));
5402               }
5403             aopPut (AOP (result), "a", offset);
5404             /* PENDING: something weird is going on here.  Add exception. */
5405             if (AOP_TYPE (result) == AOP_ACC)
5406               break;
5407           }
5408     }
5409
5410 release:
5411   freeAsmop (left, NULL, ic);
5412   freeAsmop (right, NULL, ic);
5413   freeAsmop (result, NULL, ic);
5414 }
5415
5416 /*-----------------------------------------------------------------*/
5417 /* genXor - code for xclusive or                                   */
5418 /*-----------------------------------------------------------------*/
5419 static void
5420 genXor (iCode * ic, iCode * ifx)
5421 {
5422   operand *left, *right, *result;
5423   int size, offset = 0;
5424   unsigned long lit = 0L;
5425
5426   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
5427   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
5428   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
5429
5430   /* if left is a literal & right is not then exchange them */
5431   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5432       (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
5433     {
5434       operand *tmp = right;
5435       right = left;
5436       left = tmp;
5437     }
5438
5439   /* if result = right then exchange them */
5440   if (sameRegs (AOP (result), AOP (right)))
5441     {
5442       operand *tmp = right;
5443       right = left;
5444       left = tmp;
5445     }
5446
5447   /* if right is bit then exchange them */
5448   if (AOP_TYPE (right) == AOP_CRY &&
5449       AOP_TYPE (left) != AOP_CRY)
5450     {
5451       operand *tmp = right;
5452       right = left;
5453       left = tmp;
5454     }
5455   if (AOP_TYPE (right) == AOP_LIT)
5456     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5457
5458   size = AOP_SIZE (result);
5459
5460   if (AOP_TYPE (left) == AOP_CRY)
5461     {
5462       wassertl (0, "Tried to XOR a bit");
5463       goto release;
5464     }
5465
5466   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5467   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5468   if ((AOP_TYPE (right) == AOP_LIT) &&
5469       (AOP_TYPE (result) == AOP_CRY) &&
5470       (AOP_TYPE (left) != AOP_CRY))
5471     {
5472       symbol *tlbl = newiTempLabel (NULL);
5473       int sizel = AOP_SIZE (left);
5474
5475       if (size)
5476         {
5477           /* PENDING: Test case for this. */
5478           wassertl (0, "Tried to XOR left against a literal with the result going into a bit");
5479         }
5480       while (sizel--)
5481         {
5482           _moveA (aopGet (AOP (left), offset, FALSE));
5483           emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
5484           emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5485           offset++;
5486         }
5487       if (ifx)
5488         {
5489           jmpTrueOrFalse (ifx, tlbl);
5490         }
5491       else
5492         {
5493           wassertl (0, "Result of XOR was destined for a bit");
5494         }
5495       goto release;
5496     }
5497
5498   /* if left is same as result */
5499   if (sameRegs (AOP (result), AOP (left)))
5500     {
5501       for (; size--; offset++)
5502         {
5503           if (AOP_TYPE (right) == AOP_LIT)
5504             {
5505               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5506                 continue;
5507               else
5508                 {
5509                   _moveA (aopGet (AOP (left), offset, FALSE));
5510                   emit2 ("xor a,%s",
5511                             aopGet (AOP (right), offset, FALSE));
5512                   aopPut (AOP (result), "a", offset);
5513                 }
5514             }
5515           else
5516             {
5517               if (AOP_TYPE (left) == AOP_ACC)
5518                 {
5519                   emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
5520                 }
5521               else
5522                 {
5523                   _moveA (aopGet (AOP (left), offset, FALSE));
5524                   emit2 ("xor a,%s",
5525                             aopGet (AOP (right), offset, FALSE));
5526                   aopPut (AOP (result), "a", offset);
5527                 }
5528             }
5529         }
5530     }
5531   else
5532     {
5533       // left & result in different registers
5534       if (AOP_TYPE (result) == AOP_CRY)
5535         {
5536           wassertl (0, "Result of XOR is in a bit");
5537         }
5538       else
5539         for (; (size--); offset++)
5540           {
5541             // normal case
5542             // result = left & right
5543             if (AOP_TYPE (right) == AOP_LIT)
5544               {
5545                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5546                   {
5547                     aopPut (AOP (result),
5548                             aopGet (AOP (left), offset, FALSE),
5549                             offset);
5550                     continue;
5551                   }
5552               }
5553             // faster than result <- left, anl result,right
5554             // and better if result is SFR
5555             if (AOP_TYPE (left) == AOP_ACC)
5556               {
5557                 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
5558               }
5559             else
5560               {
5561                 _moveA (aopGet (AOP (left), offset, FALSE));
5562                 emit2 ("xor a,%s",
5563                           aopGet (AOP (right), offset, FALSE));
5564               }
5565             aopPut (AOP (result), "a", offset);
5566           }
5567     }
5568
5569 release:
5570   freeAsmop (left, NULL, ic);
5571   freeAsmop (right, NULL, ic);
5572   freeAsmop (result, NULL, ic);
5573 }
5574
5575 /*-----------------------------------------------------------------*/
5576 /* genInline - write the inline code out                           */
5577 /*-----------------------------------------------------------------*/
5578 static void
5579 genInline (iCode * ic)
5580 {
5581   char *buffer, *bp, *bp1;
5582
5583   _G.lines.isInline += (!options.asmpeep);
5584
5585   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5586   strcpy (buffer, IC_INLINE (ic));
5587
5588   /* emit each line as a code */
5589   while (*bp)
5590     {
5591       if (*bp == '\n')
5592         {
5593           *bp++ = '\0';
5594           emit2 (bp1);
5595           bp1 = bp;
5596         }
5597       else
5598         {
5599           if (*bp == ':')
5600             {
5601               bp++;
5602               *bp = '\0';
5603               bp++;
5604               emit2 (bp1);
5605               bp1 = bp;
5606             }
5607           else
5608             bp++;
5609         }
5610     }
5611   if (bp1 != bp)
5612     emit2 (bp1);
5613   _G.lines.isInline -= (!options.asmpeep);
5614
5615 }
5616
5617 /*-----------------------------------------------------------------*/
5618 /* genRRC - rotate right with carry                                */
5619 /*-----------------------------------------------------------------*/
5620 static void
5621 genRRC (iCode * ic)
5622 {
5623   wassert (0);
5624 }
5625
5626 /*-----------------------------------------------------------------*/
5627 /* genRLC - generate code for rotate left with carry               */
5628 /*-----------------------------------------------------------------*/
5629 static void
5630 genRLC (iCode * ic)
5631 {
5632   wassert (0);
5633 }
5634
5635 /*-----------------------------------------------------------------*/
5636 /* genGetHbit - generates code get highest order bit               */
5637 /*-----------------------------------------------------------------*/
5638 static void
5639 genGetHbit (iCode * ic)
5640 {
5641   operand *left, *result;
5642   left = IC_LEFT (ic);
5643   result = IC_RESULT (ic);
5644
5645   aopOp (left, ic, FALSE, FALSE);
5646   aopOp (result, ic, FALSE, FALSE);
5647
5648   /* get the highest order byte into a */
5649   emit2("ld a,%s", aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
5650
5651   if (AOP_TYPE (result) == AOP_CRY)
5652     {
5653       emit2 ("rl a");
5654       outBitC (result);
5655     }
5656   else
5657     {
5658       emit2 ("rlc a");
5659       emit2 ("and a,!one");
5660       outAcc (result);
5661     }
5662
5663
5664   freeAsmop (left, NULL, ic);
5665   freeAsmop (result, NULL, ic);
5666 }
5667
5668 static void
5669 emitRsh2 (asmop *aop, int size, int is_signed)
5670 {
5671   int offset = 0;
5672
5673   while (size--)
5674     {
5675       const char *l = aopGet (aop, size, FALSE);
5676       if (offset == 0)
5677         {
5678           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
5679         }
5680       else
5681         {
5682           emit2 ("rr %s", l);
5683         }
5684       offset++;
5685     }
5686 }
5687
5688 /*-----------------------------------------------------------------*/
5689 /* shiftR2Left2Result - shift right two bytes from left to result  */
5690 /*-----------------------------------------------------------------*/
5691 static void
5692 shiftR2Left2Result (operand * left, int offl,
5693                     operand * result, int offr,
5694                     int shCount, int is_signed)
5695 {
5696   int size = 2;
5697   symbol *tlbl, *tlbl1;
5698
5699   movLeft2Result (left, offl, result, offr, 0);
5700   movLeft2Result (left, offl + 1, result, offr + 1, 0);
5701
5702   /*  if (AOP(result)->type == AOP_REG) { */
5703
5704   tlbl = newiTempLabel (NULL);
5705   tlbl1 = newiTempLabel (NULL);
5706
5707   /* Left is already in result - so now do the shift */
5708   if (shCount <= 4)
5709     {
5710       while (shCount--)
5711         {
5712           emitRsh2 (AOP (result), size, is_signed);
5713         }
5714     }
5715   else
5716     {
5717       emit2 ("ld a,!immedbyte+1", shCount);
5718       emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5719       emitLabel (tlbl->key + 100);
5720
5721       emitRsh2 (AOP (result), size, is_signed);
5722
5723       emitLabel (tlbl1->key + 100);
5724       emit2 ("dec a");
5725       emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5726     }
5727 }
5728
5729 /*-----------------------------------------------------------------*/
5730 /* shiftL2Left2Result - shift left two bytes from left to result   */
5731 /*-----------------------------------------------------------------*/
5732 static void
5733 shiftL2Left2Result (operand * left, int offl,
5734                     operand * result, int offr, int shCount)
5735 {
5736   if (sameRegs (AOP (result), AOP (left)) &&
5737       ((offl + MSB16) == offr))
5738     {
5739       wassert (0);
5740     }
5741   else
5742     {
5743       /* Copy left into result */
5744       movLeft2Result (left, offl, result, offr, 0);
5745       movLeft2Result (left, offl + 1, result, offr + 1, 0);
5746     }
5747
5748   if (getPairId (AOP (result)) == PAIR_HL)
5749     {
5750       while (shCount--)
5751         {
5752           emit2 ("add hl,hl");
5753         }
5754     }
5755   else
5756     {
5757     int size = 2;
5758     int offset = 0;
5759     symbol *tlbl, *tlbl1;
5760     const char *l;
5761
5762     tlbl = newiTempLabel (NULL);
5763     tlbl1 = newiTempLabel (NULL);
5764
5765     if (AOP (result)->type == AOP_REG)
5766       {
5767         while (shCount--)
5768           {
5769             for (offset = 0; offset < size; offset++)
5770               {
5771                 l = aopGet (AOP (result), offset, FALSE);
5772
5773                 if (offset == 0)
5774                   {
5775                     emit2 ("sla %s", l);
5776                   }
5777                 else
5778                   {
5779                     emit2 ("rl %s", l);
5780                   }
5781               }
5782           }
5783       }
5784     else
5785       {
5786         /* Left is already in result - so now do the shift */
5787         if (shCount > 1)
5788           {
5789             emit2 ("ld a,!immedbyte+1", shCount);
5790             emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5791             emitLabel (tlbl->key + 100);
5792           }
5793
5794         while (size--)
5795           {
5796             l = aopGet (AOP (result), offset, FALSE);
5797
5798             if (offset == 0)
5799               {
5800                 emit2 ("sla %s", l);
5801               }
5802             else
5803               {
5804                 emit2 ("rl %s", l);
5805               }
5806
5807             offset++;
5808           }
5809         if (shCount > 1)
5810           {
5811             emitLabel (tlbl1->key + 100);
5812             emit2 ("dec a");
5813             emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5814           }
5815       }
5816   }
5817 }
5818
5819 /*-----------------------------------------------------------------*/
5820 /* AccRol - rotate left accumulator by known count                 */
5821 /*-----------------------------------------------------------------*/
5822 static void
5823 AccRol (int shCount)
5824 {
5825   shCount &= 0x0007;            // shCount : 0..7
5826
5827 #if 0
5828   switch (shCount)
5829     {
5830     case 0:
5831       break;
5832     case 1:
5833       emit2 ("sla a");
5834       break;
5835     case 2:
5836       emit2 ("sla a");
5837       emit2 ("rl a");
5838       break;
5839     case 3:
5840       emit2 ("sla a");
5841       emit2 ("rl a");
5842       emit2 ("rl a");
5843       break;
5844     case 4:
5845       emit2 ("sla a");
5846       emit2 ("rl a");
5847       emit2 ("rl a");
5848       emit2 ("rl a");
5849       break;
5850     case 5:
5851       emit2 ("srl a");
5852       emit2 ("rr a");
5853       emit2 ("rr a");
5854       break;
5855     case 6:
5856       emit2 ("srl a");
5857       emit2 ("rr a");
5858       break;
5859     case 7:
5860       emit2 ("srl a");
5861       break;
5862     }
5863 #else
5864   switch (shCount)
5865     {
5866     case 0:
5867       break;
5868     case 1:
5869       emit2 ("rlca");
5870       break;
5871     case 2:
5872       emit2 ("rlca");
5873       emit2 ("rlca");
5874       break;
5875     case 3:
5876       emit2 ("rlca");
5877       emit2 ("rlca");
5878       emit2 ("rlca");
5879       break;
5880     case 4:
5881       emit2 ("rlca");
5882       emit2 ("rlca");
5883       emit2 ("rlca");
5884       emit2 ("rlca");
5885       break;
5886     case 5:
5887       emit2 ("rrca");
5888       emit2 ("rrca");
5889       emit2 ("rrca");
5890       break;
5891     case 6:
5892       emit2 ("rrca");
5893       emit2 ("rrca");
5894       break;
5895     case 7:
5896       emit2 ("rrca");
5897       break;
5898     }
5899 #endif
5900 }
5901
5902 /*-----------------------------------------------------------------*/
5903 /* AccLsh - left shift accumulator by known count                  */
5904 /*-----------------------------------------------------------------*/
5905 static void
5906 AccLsh (int shCount)
5907 {
5908   static const unsigned char SLMask[] =
5909     {
5910       0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
5911     };
5912
5913   if (shCount != 0)
5914     {
5915       if (shCount == 1)
5916         {
5917           emit2 ("add a,a");
5918         }
5919       else if (shCount == 2)
5920         {
5921           emit2 ("add a,a");
5922           emit2 ("add a,a");
5923         }
5924       else
5925         {
5926           /* rotate left accumulator */
5927           AccRol (shCount);
5928           /* and kill the lower order bits */
5929           emit2 ("and a,!immedbyte", SLMask[shCount]);
5930         }
5931     }
5932 }
5933
5934 /*-----------------------------------------------------------------*/
5935 /* shiftL1Left2Result - shift left one byte from left to result    */
5936 /*-----------------------------------------------------------------*/
5937 static void
5938 shiftL1Left2Result (operand * left, int offl,
5939                     operand * result, int offr, int shCount)
5940 {
5941   const char *l;
5942   l = aopGet (AOP (left), offl, FALSE);
5943   _moveA (l);
5944   /* shift left accumulator */
5945   AccLsh (shCount);
5946   aopPut (AOP (result), "a", offr);
5947 }
5948
5949
5950 /*-----------------------------------------------------------------*/
5951 /* genlshTwo - left shift two bytes by known amount != 0           */
5952 /*-----------------------------------------------------------------*/
5953 static void
5954 genlshTwo (operand * result, operand * left, int shCount)
5955 {
5956   int size = AOP_SIZE (result);
5957
5958   wassert (size == 2);
5959
5960   /* if shCount >= 8 */
5961   if (shCount >= 8)
5962     {
5963       shCount -= 8;
5964       if (size > 1)
5965         {
5966           if (shCount)
5967             {
5968               movLeft2Result (left, LSB, result, MSB16, 0);
5969               aopPut (AOP (result), "!zero", 0);
5970               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5971             }
5972           else
5973             {
5974               movLeft2Result (left, LSB, result, MSB16, 0);
5975               aopPut (AOP (result), "!zero", 0);
5976             }
5977         }
5978       else
5979         {
5980           aopPut (AOP (result), "!zero", LSB);
5981         }
5982     }
5983   /*  1 <= shCount <= 7 */
5984   else
5985     {
5986       if (size == 1)
5987         {
5988           wassert (0);
5989         }
5990       else
5991         {
5992           shiftL2Left2Result (left, LSB, result, LSB, shCount);
5993         }
5994     }
5995 }
5996
5997 /*-----------------------------------------------------------------*/
5998 /* genlshOne - left shift a one byte quantity by known count       */
5999 /*-----------------------------------------------------------------*/
6000 static void
6001 genlshOne (operand * result, operand * left, int shCount)
6002 {
6003   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6004 }
6005
6006 /*-----------------------------------------------------------------*/
6007 /* genLeftShiftLiteral - left shifting by known count              */
6008 /*-----------------------------------------------------------------*/
6009 static void
6010 genLeftShiftLiteral (operand * left,
6011                      operand * right,
6012                      operand * result,
6013                      iCode * ic)
6014 {
6015   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6016   int size;
6017
6018   freeAsmop (right, NULL, ic);
6019
6020   aopOp (left, ic, FALSE, FALSE);
6021   aopOp (result, ic, FALSE, FALSE);
6022
6023   size = getSize (operandType (result));
6024
6025   /* I suppose that the left size >= result size */
6026   if (shCount == 0)
6027     {
6028       wassert (0);
6029     }
6030
6031   else if (shCount >= (size * 8))
6032     {
6033       while (size--)
6034         {
6035           aopPut (AOP (result), "!zero", size);
6036         }
6037     }
6038   else
6039     {
6040       switch (size)
6041         {
6042         case 1:
6043           genlshOne (result, left, shCount);
6044           break;
6045         case 2:
6046           genlshTwo (result, left, shCount);
6047           break;
6048         case 4:
6049           wassertl (0, "Shifting of longs is currently unsupported");
6050           break;
6051         default:
6052           wassert (0);
6053         }
6054     }
6055   freeAsmop (left, NULL, ic);
6056   freeAsmop (result, NULL, ic);
6057 }
6058
6059 /*-----------------------------------------------------------------*/
6060 /* genLeftShift - generates code for left shifting                 */
6061 /*-----------------------------------------------------------------*/
6062 static void
6063 genLeftShift (iCode * ic)
6064 {
6065   int size, offset;
6066   const char *l;
6067   symbol *tlbl, *tlbl1;
6068   operand *left, *right, *result;
6069
6070   right = IC_RIGHT (ic);
6071   left = IC_LEFT (ic);
6072   result = IC_RESULT (ic);
6073
6074   aopOp (right, ic, FALSE, FALSE);
6075
6076   /* if the shift count is known then do it
6077      as efficiently as possible */
6078   if (AOP_TYPE (right) == AOP_LIT)
6079     {
6080       genLeftShiftLiteral (left, right, result, ic);
6081       return;
6082     }
6083
6084   /* shift count is unknown then we have to form a loop get the loop
6085      count in B : Note: we take only the lower order byte since
6086      shifting more that 32 bits make no sense anyway, ( the largest
6087      size of an object can be only 32 bits ) */
6088   emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
6089   emit2 ("inc a");
6090   freeAsmop (right, NULL, ic);
6091   aopOp (left, ic, FALSE, FALSE);
6092   aopOp (result, ic, FALSE, FALSE);
6093
6094   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6095      _push (PAIR_AF);
6096
6097   /* now move the left to the result if they are not the
6098      same */
6099
6100   if (!sameRegs (AOP (left), AOP (result)))
6101     {
6102
6103       size = AOP_SIZE (result);
6104       offset = 0;
6105       while (size--)
6106         {
6107           l = aopGet (AOP (left), offset, FALSE);
6108           aopPut (AOP (result), l, offset);
6109           offset++;
6110         }
6111     }
6112
6113   tlbl = newiTempLabel (NULL);
6114   size = AOP_SIZE (result);
6115   offset = 0;
6116   tlbl1 = newiTempLabel (NULL);
6117
6118   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6119      _pop (PAIR_AF);
6120
6121   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
6122   emitLabel (tlbl->key + 100);
6123   l = aopGet (AOP (result), offset, FALSE);
6124
6125   while (size--)
6126     {
6127       l = aopGet (AOP (result), offset, FALSE);
6128
6129       if (offset == 0)
6130         {
6131           emit2 ("sla %s", l);
6132         }
6133       else
6134         {
6135           emit2 ("rl %s", l);
6136         }
6137       offset++;
6138     }
6139   emitLabel (tlbl1->key + 100);
6140   emit2 ("dec a");
6141   emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
6142
6143   freeAsmop (left, NULL, ic);
6144   freeAsmop (result, NULL, ic);
6145 }
6146
6147 /*-----------------------------------------------------------------*/
6148 /* genrshOne - left shift two bytes by known amount != 0           */
6149 /*-----------------------------------------------------------------*/
6150 static void
6151 genrshOne (operand * result, operand * left, int shCount, int is_signed)
6152 {
6153   /* Errk */
6154   int size = AOP_SIZE (result);
6155   const char *l;
6156
6157   wassert (size == 1);
6158   wassert (shCount < 8);
6159
6160   l = aopGet (AOP (left), 0, FALSE);
6161
6162   if (AOP (result)->type == AOP_REG)
6163     {
6164       aopPut (AOP (result), l, 0);
6165       l = aopGet (AOP (result), 0, FALSE);
6166       while (shCount--)
6167         {
6168           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
6169         }
6170     }
6171   else
6172     {
6173       _moveA (l);
6174       while (shCount--)
6175         {
6176           emit2 ("%s a", is_signed ? "sra" : "srl");
6177         }
6178       aopPut (AOP (result), "a", 0);
6179     }
6180 }
6181
6182 /*-----------------------------------------------------------------*/
6183 /* AccRsh - right shift accumulator by known count                 */
6184 /*-----------------------------------------------------------------*/
6185 static void
6186 AccRsh (int shCount)
6187 {
6188   static const unsigned char SRMask[] =
6189     {
6190       0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
6191     };
6192
6193   if (shCount != 0)
6194     {
6195       /* rotate right accumulator */
6196       AccRol (8 - shCount);
6197       /* and kill the higher order bits */
6198       emit2 ("and a,!immedbyte", SRMask[shCount]);
6199     }
6200 }
6201
6202 /*-----------------------------------------------------------------*/
6203 /* shiftR1Left2Result - shift right one byte from left to result   */
6204 /*-----------------------------------------------------------------*/
6205 static void
6206 shiftR1Left2Result (operand * left, int offl,
6207                     operand * result, int offr,
6208                     int shCount, int sign)
6209 {
6210   _moveA (aopGet (AOP (left), offl, FALSE));
6211   if (sign)
6212     {
6213       while (shCount--)
6214         {
6215           emit2 ("%s a", sign ? "sra" : "srl");
6216         }
6217     }
6218   else
6219     {
6220       AccRsh (shCount);
6221     }
6222   aopPut (AOP (result), "a", offr);
6223 }
6224
6225 /*-----------------------------------------------------------------*/
6226 /* genrshTwo - right shift two bytes by known amount != 0          */
6227 /*-----------------------------------------------------------------*/
6228 static void
6229 genrshTwo (operand * result, operand * left,
6230            int shCount, int sign)
6231 {
6232   /* if shCount >= 8 */
6233   if (shCount >= 8)
6234     {
6235       shCount -= 8;
6236       if (shCount)
6237         {
6238           shiftR1Left2Result (left, MSB16, result, LSB,
6239                               shCount, sign);
6240         }
6241       else
6242         {
6243           movLeft2Result (left, MSB16, result, LSB, sign);
6244         }
6245       if (sign)
6246         {
6247           /* Sign extend the result */
6248           _moveA(aopGet (AOP (result), 0, FALSE));
6249           emit2 ("rlc a");
6250           emit2 ("sbc a,a");
6251
6252           aopPut (AOP (result), ACC_NAME, MSB16);
6253         }
6254       else
6255         {
6256           aopPut (AOP (result), "!zero", 1);
6257         }
6258     }
6259   /*  1 <= shCount <= 7 */
6260   else
6261     {
6262       shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6263     }
6264 }
6265
6266 /*-----------------------------------------------------------------*/
6267 /* genRightShiftLiteral - left shifting by known count              */
6268 /*-----------------------------------------------------------------*/
6269 static void
6270 genRightShiftLiteral (operand * left,
6271                       operand * right,
6272                       operand * result,
6273                       iCode * ic,
6274                       int sign)
6275 {
6276   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6277   int size;
6278
6279   freeAsmop (right, NULL, ic);
6280
6281   aopOp (left, ic, FALSE, FALSE);
6282   aopOp (result, ic, FALSE, FALSE);
6283
6284   size = getSize (operandType (result));
6285
6286   /* I suppose that the left size >= result size */
6287   if (shCount == 0)
6288     {
6289       wassert (0);
6290     }
6291
6292   else if (shCount >= (size * 8)) {
6293     const char *s;
6294     if (!SPEC_USIGN(getSpec(operandType(left)))) {
6295       _moveA(aopGet (AOP (left), 0, FALSE));
6296       emit2 ("rlc a");
6297       emit2 ("sbc a,a");
6298       s=ACC_NAME;
6299     } else {
6300       s="!zero";
6301     }
6302     while (size--)
6303       aopPut (AOP (result), s, size);
6304   }
6305   else
6306     {
6307       switch (size)
6308         {
6309         case 1:
6310           genrshOne (result, left, shCount, sign);
6311           break;
6312         case 2:
6313           genrshTwo (result, left, shCount, sign);
6314           break;
6315         case 4:
6316           wassertl (0, "Asked to shift right a long which should be a function call");
6317           break;
6318         default:
6319           wassertl (0, "Entered default case in right shift delegate");
6320         }
6321     }
6322   freeAsmop (left, NULL, ic);
6323   freeAsmop (result, NULL, ic);
6324 }
6325
6326 /*-----------------------------------------------------------------*/
6327 /* genRightShift - generate code for right shifting                */
6328 /*-----------------------------------------------------------------*/
6329 static void
6330 genRightShift (iCode * ic)
6331 {
6332   operand *right, *left, *result;
6333   sym_link *retype;
6334   int size, offset, first = 1;
6335   const char *l;
6336   bool is_signed;
6337
6338   symbol *tlbl, *tlbl1;
6339
6340   /* if signed then we do it the hard way preserve the
6341      sign bit moving it inwards */
6342   retype = getSpec (operandType (IC_RESULT (ic)));
6343
6344   is_signed = !SPEC_USIGN (retype);
6345
6346   /* signed & unsigned types are treated the same : i.e. the
6347      signed is NOT propagated inwards : quoting from the
6348      ANSI - standard : "for E1 >> E2, is equivalent to division
6349      by 2**E2 if unsigned or if it has a non-negative value,
6350      otherwise the result is implementation defined ", MY definition
6351      is that the sign does not get propagated */
6352
6353   right = IC_RIGHT (ic);
6354   left = IC_LEFT (ic);
6355   result = IC_RESULT (ic);
6356
6357   aopOp (right, ic, FALSE, FALSE);
6358
6359   /* if the shift count is known then do it
6360      as efficiently as possible */
6361   if (AOP_TYPE (right) == AOP_LIT)
6362     {
6363       genRightShiftLiteral (left, right, result, ic, is_signed);
6364       return;
6365     }
6366
6367   emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
6368   emit2 ("inc a");
6369   freeAsmop (right, NULL, ic);
6370
6371   aopOp (left, ic, FALSE, FALSE);
6372   aopOp (result, ic, FALSE, FALSE);
6373
6374   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6375      _push (PAIR_AF);
6376
6377   /* now move the left to the result if they are not the
6378      same */
6379   if (!sameRegs (AOP (left), AOP (result)))
6380     {
6381
6382       size = AOP_SIZE (result);
6383       offset = 0;
6384       while (size--)
6385         {
6386           l = aopGet (AOP (left), offset, FALSE);
6387           aopPut (AOP (result), l, offset);
6388           offset++;
6389         }
6390     }
6391
6392   tlbl = newiTempLabel (NULL);
6393   tlbl1 = newiTempLabel (NULL);
6394   size = AOP_SIZE (result);
6395   offset = size - 1;
6396
6397   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6398      _pop (PAIR_AF);
6399
6400   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
6401   emitLabel (tlbl->key + 100);
6402   while (size--)
6403     {
6404       l = aopGet (AOP (result), offset--, FALSE);
6405       if (first)
6406         {
6407           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
6408           first = 0;
6409         }
6410       else
6411         {
6412           emit2 ("rr %s", l);
6413         }
6414     }
6415   emitLabel (tlbl1->key + 100);
6416   emit2 ("dec a");
6417   emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
6418
6419   freeAsmop (left, NULL, ic);
6420   freeAsmop (result, NULL, ic);
6421 }
6422
6423
6424 /*-----------------------------------------------------------------*/
6425 /* genUnpackBits - generates code for unpacking bits               */
6426 /*-----------------------------------------------------------------*/
6427 static void
6428 genUnpackBits (operand * result, int pair)
6429 {
6430   int offset = 0;       /* result byte offset */
6431   int rsize;            /* result size */
6432   int rlen = 0;         /* remaining bitfield length */
6433   sym_link *etype;      /* bitfield type information */
6434   int blen;             /* bitfield length */
6435   int bstr;             /* bitfield starting bit within byte */
6436
6437   emitDebug ("; genUnpackBits");
6438
6439   etype = getSpec (operandType (result));
6440   rsize = getSize (operandType (result));
6441   blen = SPEC_BLEN (etype);
6442   bstr = SPEC_BSTR (etype);
6443
6444   /* If the bitfield length is less than a byte */
6445   if (blen < 8)
6446     {
6447       emit2 ("ld a,!*pair", _pairs[pair].name);
6448       AccRol (8 - bstr);
6449       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - blen));
6450       if (!SPEC_USIGN (etype))
6451         {
6452           /* signed bitfield */
6453           symbol *tlbl = newiTempLabel (NULL);
6454
6455           emit2 ("bit %d,a", blen - 1);
6456           emit2 ("jp z,!tlabel", tlbl->key + 100);
6457           emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
6458           emitLabel (tlbl->key + 100);
6459         }
6460       aopPut (AOP (result), "a", offset++);
6461       goto finish;
6462     }
6463
6464   /* TODO: what if pair == PAIR_DE ? */
6465   if (getPairId (AOP (result)) == PAIR_HL)
6466     {
6467       wassertl (rsize == 2, "HL must be of size 2");
6468       emit2 ("ld a,!*hl");
6469       emit2 ("inc hl");
6470       emit2 ("ld h,!*hl");
6471       emit2 ("ld l,a");
6472       emit2 ("ld a,h");
6473       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (16 - blen));
6474       if (!SPEC_USIGN (etype))
6475         {
6476           /* signed bitfield */
6477           symbol *tlbl = newiTempLabel (NULL);
6478
6479           emit2 ("bit %d,a", blen - 1);
6480           emit2 ("jp z,!tlabel", tlbl->key + 100);
6481           emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
6482           emitLabel (tlbl->key + 100);
6483         }
6484       emit2 ("ld h,a");
6485       spillPair (PAIR_HL);
6486       return;
6487     }
6488
6489   /* Bit field did not fit in a byte. Copy all
6490      but the partial byte at the end.  */
6491   for (rlen=blen;rlen>=8;rlen-=8)
6492     {
6493       emit2 ("ld a,!*pair", _pairs[pair].name);
6494       aopPut (AOP (result), "a", offset++);
6495       if (rlen>8)
6496         {
6497           emit2 ("inc %s", _pairs[pair].name);
6498           _G.pairs[pair].offset++;
6499         }
6500     }
6501
6502   /* Handle the partial byte at the end */
6503   if (rlen)
6504     {
6505       emit2 ("ld a,!*pair", _pairs[pair].name);
6506       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - rlen));
6507       if (!SPEC_USIGN (etype))
6508         {
6509           /* signed bitfield */
6510           symbol *tlbl = newiTempLabel (NULL);
6511
6512           emit2 ("bit %d,a", rlen - 1);
6513           emit2 ("jp z,!tlabel", tlbl->key + 100);
6514           emit2 ("or a,!immedbyte", (unsigned char) (0xff << rlen));
6515           emitLabel (tlbl->key + 100);
6516         }
6517       aopPut (AOP (result), "a", offset++);
6518     }
6519
6520 finish:
6521   if (offset < rsize)
6522     {
6523       char *source;
6524
6525       if (SPEC_USIGN (etype))
6526         source = "!zero";
6527       else
6528         {
6529           /* signed bitfield: sign extension with 0x00 or 0xff */
6530           emit2 ("rla");
6531           emit2 ("sbc a,a");
6532
6533           source = "a";
6534         }
6535       rsize -= offset;
6536       while (rsize--)
6537         aopPut (AOP (result), source, offset++);
6538     }
6539 }
6540
6541 /*-----------------------------------------------------------------*/
6542 /* genGenPointerGet -  get value from generic pointer space        */
6543 /*-----------------------------------------------------------------*/
6544 static void
6545 genGenPointerGet (operand * left,
6546                   operand * result, iCode * ic)
6547 {
6548   int size, offset;
6549   sym_link *retype = getSpec (operandType (result));
6550   int pair = PAIR_HL;
6551
6552   if (IS_GB)
6553     pair = PAIR_DE;
6554
6555   aopOp (left, ic, FALSE, FALSE);
6556   aopOp (result, ic, FALSE, FALSE);
6557
6558   size = AOP_SIZE (result);
6559
6560   if (isPair (AOP (left)) && size == 1 && !IS_BITVAR (retype))
6561     {
6562       /* Just do it */
6563       if (isPtrPair (AOP (left)))
6564         {
6565           tsprintf (buffer, sizeof(buffer),
6566                     "!*pair", getPairName (AOP (left)));
6567           aopPut (AOP (result), buffer, 0);
6568         }
6569       else
6570         {
6571           emit2 ("ld a,!*pair", getPairName (AOP (left)));
6572           aopPut (AOP (result), "a", 0);
6573         }
6574       freeAsmop (left, NULL, ic);
6575       goto release;
6576     }
6577
6578   if (getPairId (AOP (left)) == PAIR_IY && !IS_BITVAR (retype))
6579     {
6580       /* Just do it */
6581       offset = 0;
6582       while (size--)
6583         {
6584           char at[20];
6585           tsprintf (at, sizeof(at), "!*iyx", offset);
6586           aopPut (AOP (result), at, offset);
6587           offset++;
6588         }
6589
6590       freeAsmop (left, NULL, ic);
6591       goto release;
6592     }
6593
6594   /* For now we always load into IY */
6595   /* if this is remateriazable */
6596   fetchPair (pair, AOP (left));
6597
6598   /* if bit then unpack */
6599   if (IS_BITVAR (retype))
6600     {
6601       genUnpackBits (result, pair);
6602       freeAsmop (left, NULL, ic);
6603       goto release;
6604       //wassert (0);
6605     }
6606   else if (getPairId (AOP (result)) == PAIR_HL)
6607     {
6608       wassertl (size == 2, "HL must be of size 2");
6609       emit2 ("ld a,!*hl");
6610       emit2 ("inc hl");
6611       emit2 ("ld h,!*hl");
6612       emit2 ("ld l,a");
6613       spillPair (PAIR_HL);
6614     }
6615   else if (getPairId (AOP (left)) == PAIR_HL && !isLastUse (ic, left))
6616     {
6617       size = AOP_SIZE (result);
6618       offset = 0;
6619
6620       while (size--)
6621         {
6622           /* PENDING: make this better */
6623           if (!IS_GB && AOP_TYPE (result) == AOP_REG)
6624             {
6625               aopPut (AOP (result), "!*hl", offset++);
6626             }
6627           else
6628             {
6629               emit2 ("ld a,!*pair", _pairs[pair].name);
6630               aopPut (AOP (result), "a", offset++);
6631             }
6632           if (size)
6633             {
6634               emit2 ("inc %s", _pairs[pair].name);
6635               _G.pairs[pair].offset++;
6636             }
6637         }
6638       /* Fixup HL back down */
6639       for (size = AOP_SIZE (result)-1; size; size--)
6640         {
6641           emit2 ("dec %s", _pairs[pair].name);
6642         }
6643     }
6644   else
6645     {
6646       size = AOP_SIZE (result);
6647       offset = 0;
6648
6649       while (size--)
6650         {
6651           /* PENDING: make this better */
6652           if (!IS_GB &&
6653               (AOP_TYPE (result) == AOP_REG || AOP_TYPE (result) == AOP_HLREG))
6654             {
6655               aopPut (AOP (result), "!*hl", offset++);
6656             }
6657           else
6658             {
6659               emit2 ("ld a,!*pair", _pairs[pair].name);
6660               aopPut (AOP (result), "a", offset++);
6661             }
6662           if (size)
6663             {
6664               emit2 ("inc %s", _pairs[pair].name);
6665               _G.pairs[pair].offset++;
6666             }
6667         }
6668     }
6669
6670   freeAsmop (left, NULL, ic);
6671
6672 release:
6673   freeAsmop (result, NULL, ic);
6674 }
6675
6676 /*-----------------------------------------------------------------*/
6677 /* genPointerGet - generate code for pointer get                   */
6678 /*-----------------------------------------------------------------*/
6679 static void
6680 genPointerGet (iCode * ic)
6681 {
6682   operand *left, *result;
6683   sym_link *type, *etype;
6684
6685   left = IC_LEFT (ic);
6686   result = IC_RESULT (ic);
6687
6688   /* depending on the type of pointer we need to
6689      move it to the correct pointer register */
6690   type = operandType (left);
6691   etype = getSpec (type);
6692
6693   genGenPointerGet (left, result, ic);
6694 }
6695
6696 bool
6697 isRegOrLit (asmop * aop)
6698 {
6699   if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD || aop->type == AOP_HLREG)
6700     return TRUE;
6701   return FALSE;
6702 }
6703
6704
6705 /*-----------------------------------------------------------------*/
6706 /* genPackBits - generates code for packed bit storage             */
6707 /*-----------------------------------------------------------------*/
6708 static void
6709 genPackBits (sym_link * etype,
6710              operand * right,
6711              int pair,
6712              iCode *ic)
6713 {
6714   int offset = 0;       /* source byte offset */
6715   int rlen = 0;         /* remaining bitfield length */
6716   int blen;             /* bitfield length */
6717   int bstr;             /* bitfield starting bit within byte */
6718   int litval;           /* source literal value (if AOP_LIT) */
6719   unsigned char mask;   /* bitmask within current byte */
6720   int extraPair;        /* a tempory register */
6721   bool needPopExtra=0;  /* need to restore original value of temp reg */
6722
6723   emitDebug (";     genPackBits","");
6724
6725   blen = SPEC_BLEN (etype);
6726   bstr = SPEC_BSTR (etype);
6727
6728   /* If the bitfield length is less than a byte */
6729   if (blen < 8)
6730     {
6731       mask = ((unsigned char) (0xFF << (blen + bstr)) |
6732               (unsigned char) (0xFF >> (8 - bstr)));
6733
6734       if (AOP_TYPE (right) == AOP_LIT)
6735         {
6736           /* Case with a bitfield length <8 and literal source
6737           */
6738           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6739           litval <<= bstr;
6740           litval &= (~mask) & 0xff;
6741           emit2 ("ld a,!*pair", _pairs[pair].name);
6742           if ((mask|litval)!=0xff)
6743             emit2 ("and a,!immedbyte", mask);
6744           if (litval)
6745             emit2 ("or a,!immedbyte", litval);
6746           emit2 ("ld !*pair,a", _pairs[pair].name);
6747           return;
6748         }
6749       else
6750         {
6751           /* Case with a bitfield length <8 and arbitrary source
6752           */
6753           _moveA (aopGet (AOP (right), 0, FALSE));
6754           /* shift and mask source value */
6755           AccLsh (bstr);
6756           emit2 ("and a,!immedbyte", (~mask) & 0xff);
6757
6758           extraPair = getFreePairId(ic);
6759           if (extraPair == PAIR_INVALID)
6760             {
6761               extraPair = PAIR_BC;
6762               if (getPairId (AOP (right)) != PAIR_BC
6763                   || !isLastUse (ic, right))
6764                 {
6765                   _push (extraPair);
6766                   needPopExtra = 1;
6767                 }
6768             }
6769           emit2 ("ld %s,a", _pairs[extraPair].l);
6770           emit2 ("ld a,!*pair", _pairs[pair].name);
6771
6772           emit2 ("and a,!immedbyte", mask);
6773           emit2 ("or a,%s", _pairs[extraPair].l);
6774           emit2 ("ld !*pair,a", _pairs[pair].name);
6775           if (needPopExtra)
6776             _pop (extraPair);
6777           return;
6778         }
6779     }
6780
6781   /* Bit length is greater than 7 bits. In this case, copy  */
6782   /* all except the partial byte at the end                 */
6783   for (rlen=blen;rlen>=8;rlen-=8)
6784     {
6785       emit2 ("ld a,%s", aopGet (AOP (right), offset++, FALSE) );
6786       emit2 ("ld !*pair,a", _pairs[pair].name);
6787       if (rlen>8)
6788         {
6789           emit2 ("inc %s", _pairs[pair].name);
6790           _G.pairs[pair].offset++;
6791         }
6792     }
6793
6794   /* If there was a partial byte at the end */
6795   if (rlen)
6796     {
6797       mask = (((unsigned char) -1 << rlen) & 0xff);
6798
6799       if (AOP_TYPE (right) == AOP_LIT)
6800         {
6801           /* Case with partial byte and literal source
6802           */
6803           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6804           litval >>= (blen-rlen);
6805           litval &= (~mask) & 0xff;
6806           emit2 ("ld a,!*pair", _pairs[pair].name);
6807           if ((mask|litval)!=0xff)
6808             emit2 ("and a,!immedbyte", mask);
6809           if (litval)
6810             emit2 ("or a,!immedbyte", litval);
6811         }
6812       else
6813         {
6814           /* Case with partial byte and arbitrary source
6815           */
6816           _moveA (aopGet (AOP (right), offset++, FALSE));
6817           emit2 ("and a,!immedbyte", (~mask) & 0xff);
6818
6819           extraPair = getFreePairId(ic);
6820           if (extraPair == PAIR_INVALID)
6821             {
6822               extraPair = getPairId (AOP (right));
6823               if (!isLastUse (ic, right) || (extraPair == PAIR_INVALID))
6824                 extraPair = PAIR_BC;
6825
6826               if (getPairId (AOP (right)) != PAIR_BC
6827                   || !isLastUse (ic, right))
6828                 {
6829                   _push (extraPair);
6830                   needPopExtra = 1;
6831                 }
6832             }
6833           emit2 ("ld %s,a", _pairs[extraPair].l);
6834           emit2 ("ld a,!*pair", _pairs[pair].name);
6835
6836           emit2 ("and a,!immedbyte", mask);
6837           emit2 ("or a,%s", _pairs[extraPair].l);
6838           if (needPopExtra)
6839             _pop (extraPair);
6840
6841         }
6842       emit2 ("ld !*pair,a", _pairs[pair].name);
6843     }
6844 }
6845
6846
6847 /*-----------------------------------------------------------------*/
6848 /* genGenPointerSet - stores the value into a pointer location        */
6849 /*-----------------------------------------------------------------*/
6850 static void
6851 genGenPointerSet (operand * right,
6852                   operand * result, iCode * ic)
6853 {
6854   int size, offset;
6855   sym_link *retype = getSpec (operandType (right));
6856   sym_link *letype = getSpec (operandType (result));
6857   PAIR_ID pairId = PAIR_HL;
6858   bool isBitvar;
6859
6860   aopOp (result, ic, FALSE, FALSE);
6861   aopOp (right, ic, FALSE, FALSE);
6862
6863   if (IS_GB)
6864     pairId = PAIR_DE;
6865
6866   size = AOP_SIZE (right);
6867
6868   isBitvar = IS_BITVAR(retype) || IS_BITVAR(letype);
6869   emitDebug("; isBitvar = %d", isBitvar);
6870
6871   /* Handle the exceptions first */
6872   if (isPair (AOP (result)) && size == 1 && !isBitvar)
6873     {
6874       /* Just do it */
6875       const char *l = aopGet (AOP (right), 0, FALSE);
6876       const char *pair = getPairName (AOP (result));
6877       if (canAssignToPtr (l) && isPtr (pair))
6878         {
6879           emit2 ("ld !*pair,%s", pair, l);
6880         }
6881       else
6882         {
6883           _moveA (l);
6884           emit2 ("ld !*pair,a", pair);
6885         }
6886       goto release;
6887     }
6888
6889   if ( getPairId( AOP (result)) == PAIR_IY && !isBitvar)
6890     {
6891       /* Just do it */
6892       const char *l = aopGet (AOP (right), 0, FALSE);
6893
6894       offset = 0;
6895       while (size--)
6896         {
6897           if (canAssignToPtr (l))
6898             {
6899               emit2 ("ld !*iyx,%s", offset, aopGet( AOP(right), offset, FALSE));
6900             }
6901           else
6902             {
6903               _moveA (aopGet (AOP (right), offset, FALSE));
6904               emit2 ("ld !*iyx,a", offset);
6905             }
6906           offset++;
6907         }
6908       goto release;
6909     }
6910   else if (getPairId (AOP (result)) == PAIR_HL && !isLastUse (ic, result)
6911            && !isBitvar)
6912     {
6913       offset = 0;
6914
6915       while (size--)
6916         {
6917           const char *l = aopGet (AOP (right), offset, FALSE);
6918           if (isRegOrLit (AOP (right)) && !IS_GB)
6919             {
6920               emit2 ("ld !*pair,%s", _pairs[PAIR_HL].name, l);
6921             }
6922           else
6923             {
6924               _moveA (l);
6925               emit2 ("ld !*pair,a", _pairs[PAIR_HL].name);
6926             }
6927           if (size)
6928             {
6929               emit2 ("inc %s", _pairs[PAIR_HL].name);
6930               _G.pairs[PAIR_HL].offset++;
6931             }
6932           offset++;
6933         }
6934
6935       /* Fixup HL back down */
6936       for (size = AOP_SIZE (right)-1; size; size--)
6937         {
6938           emit2 ("dec %s", _pairs[PAIR_HL].name);
6939         }
6940       goto release;
6941     }
6942
6943   /* if the operand is already in dptr
6944      then we do nothing else we move the value to dptr */
6945   if (AOP_TYPE (result) != AOP_STR)
6946     {
6947       fetchPair (pairId, AOP (result));
6948     }
6949   /* so hl now contains the address */
6950   freeAsmop (result, NULL, ic);
6951
6952   /* if bit then unpack */
6953   if (isBitvar)
6954     {
6955       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, pairId, ic);
6956       goto release;
6957       //wassert (0);
6958     }
6959   else
6960     {
6961       offset = 0;
6962
6963       while (size--)
6964         {
6965           const char *l = aopGet (AOP (right), offset, FALSE);
6966           if (isRegOrLit (AOP (right)) && !IS_GB)
6967             {
6968               emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
6969             }
6970           else
6971             {
6972               _moveA (l);
6973               emit2 ("ld !*pair,a", _pairs[pairId].name);
6974             }
6975           if (size)
6976             {
6977               emit2 ("inc %s", _pairs[pairId].name);
6978               _G.pairs[pairId].offset++;
6979             }
6980           offset++;
6981         }
6982     }
6983 release:
6984   freeAsmop (right, NULL, ic);
6985 }
6986
6987 /*-----------------------------------------------------------------*/
6988 /* genPointerSet - stores the value into a pointer location        */
6989 /*-----------------------------------------------------------------*/
6990 static void
6991 genPointerSet (iCode * ic)
6992 {
6993   operand *right, *result;
6994   sym_link *type, *etype;
6995
6996   right = IC_RIGHT (ic);
6997   result = IC_RESULT (ic);
6998
6999   /* depending on the type of pointer we need to
7000      move it to the correct pointer register */
7001   type = operandType (result);
7002   etype = getSpec (type);
7003
7004   genGenPointerSet (right, result, ic);
7005 }
7006
7007 /*-----------------------------------------------------------------*/
7008 /* genIfx - generate code for Ifx statement                        */
7009 /*-----------------------------------------------------------------*/
7010 static void
7011 genIfx (iCode * ic, iCode * popIc)
7012 {
7013   operand *cond = IC_COND (ic);
7014   int isbit = 0;
7015
7016   aopOp (cond, ic, FALSE, TRUE);
7017
7018   /* get the value into acc */
7019   if (AOP_TYPE (cond) != AOP_CRY)
7020     _toBoolean (cond);
7021   else
7022     isbit = 1;
7023   /* the result is now in the accumulator */
7024   freeAsmop (cond, NULL, ic);
7025
7026   /* if there was something to be popped then do it */
7027   if (popIc)
7028     genIpop (popIc);
7029
7030   /* if the condition is  a bit variable */
7031   if (isbit && IS_ITEMP (cond) &&
7032       SPIL_LOC (cond))
7033     genIfxJump (ic, SPIL_LOC (cond)->rname);
7034   else if (isbit && !IS_ITEMP (cond))
7035     genIfxJump (ic, OP_SYMBOL (cond)->rname);
7036   else
7037     genIfxJump (ic, "a");
7038
7039   ic->generated = 1;
7040 }
7041
7042 /*-----------------------------------------------------------------*/
7043 /* genAddrOf - generates code for address of                       */
7044 /*-----------------------------------------------------------------*/
7045 static void
7046 genAddrOf (iCode * ic)
7047 {
7048   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7049
7050   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
7051
7052   /* if the operand is on the stack then we
7053      need to get the stack offset of this
7054      variable */
7055   if (IS_GB)
7056     {
7057       if (sym->onStack)
7058         {
7059           spillCached ();
7060           if (sym->stack <= 0)
7061             {
7062               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset);
7063             }
7064           else
7065             {
7066               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
7067             }
7068           commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
7069         }
7070       else
7071         {
7072           emit2 ("ld de,!hashedstr", sym->rname);
7073           commitPair (AOP (IC_RESULT (ic)), PAIR_DE);
7074         }
7075     }
7076   else
7077     {
7078       spillCached ();
7079       if (sym->onStack)
7080         {
7081           /* if it has an offset  then we need to compute it */
7082           if (sym->stack > 0)
7083             emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
7084           else
7085             emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset);
7086           emit2 ("add hl,sp");
7087         }
7088       else
7089         {
7090           emit2 ("ld hl,!hashedstr", sym->rname);
7091         }
7092       commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
7093     }
7094   freeAsmop (IC_RESULT (ic), NULL, ic);
7095 }
7096
7097 /*-----------------------------------------------------------------*/
7098 /* genAssign - generate code for assignment                        */
7099 /*-----------------------------------------------------------------*/
7100 static void
7101 genAssign (iCode * ic)
7102 {
7103   operand *result, *right;
7104   int size, offset;
7105   unsigned long lit = 0L;
7106
7107   result = IC_RESULT (ic);
7108   right = IC_RIGHT (ic);
7109
7110   /* Dont bother assigning if they are the same */
7111   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7112     {
7113       emitDebug ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
7114       return;
7115     }
7116
7117   aopOp (right, ic, FALSE, FALSE);
7118   aopOp (result, ic, TRUE, FALSE);
7119
7120   /* if they are the same registers */
7121   if (sameRegs (AOP (right), AOP (result)))
7122     {
7123       emitDebug ("; (registers are the same)");
7124       goto release;
7125     }
7126
7127   /* if the result is a bit */
7128   if (AOP_TYPE (result) == AOP_CRY)
7129     {
7130       wassertl (0, "Tried to assign to a bit");
7131     }
7132
7133   /* general case */
7134   size = AOP_SIZE (result);
7135   offset = 0;
7136
7137   if (AOP_TYPE (right) == AOP_LIT)
7138     {
7139       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7140     }
7141
7142   if (isPair (AOP (result)))
7143     {
7144       fetchPairLong (getPairId (AOP (result)), AOP (right), ic, LSB);
7145     }
7146   else if ((size > 1) &&
7147            (AOP_TYPE (result) != AOP_REG) &&
7148            (AOP_TYPE (right) == AOP_LIT) &&
7149            !IS_FLOAT (operandType (right)) &&
7150            (lit < 256L))
7151     {
7152       bool fXored = FALSE;
7153       offset = 0;
7154       /* Work from the top down.
7155          Done this way so that we can use the cached copy of 0
7156          in A for a fast clear */
7157       while (size--)
7158         {
7159           if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
7160             {
7161               if (!fXored && size > 1)
7162                 {
7163                   emit2 ("xor a,a");
7164                   fXored = TRUE;
7165                 }
7166               if (fXored)
7167                 {
7168                   aopPut (AOP (result), "a", offset);
7169                 }
7170               else
7171                 {
7172                   aopPut (AOP (result), "!zero", offset);
7173                 }
7174             }
7175           else
7176             aopPut (AOP (result),
7177                     aopGet (AOP (right), offset, FALSE),
7178                     offset);
7179           offset++;
7180         }
7181     }
7182   else if (size == 2 && AOP_TYPE (right) == AOP_IY)
7183     {
7184       emit2 ("ld hl,(%s)", AOP (right)->aopu.aop_dir);
7185       aopPut (AOP (result), "l", LSB);
7186       aopPut (AOP (result), "h", MSB16);
7187     }
7188   else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
7189     {
7190       /* Special case.  Load into a and d, then load out. */
7191       _moveA (aopGet (AOP (right), 0, FALSE));
7192       emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
7193       aopPut (AOP (result), "a", 0);
7194       aopPut (AOP (result), "e", 1);
7195     }
7196   else if (size == 4 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
7197     {
7198       /* Special case - simple memcpy */
7199       aopGet (AOP (right), LSB, FALSE);
7200       emit2 ("ld d,h");
7201       emit2 ("ld e,l");
7202       aopGet (AOP (result), LSB, FALSE);
7203
7204       while (size--)
7205         {
7206           emit2 ("ld a,(de)");
7207           /* Peephole will optimise this. */
7208           emit2 ("ld (hl),a");
7209
7210           if (size != 0)
7211             {
7212               emit2 ("inc hl");
7213               emit2 ("inc de");
7214             }
7215         }
7216       spillPair (PAIR_HL);
7217     }
7218   else
7219     {
7220       while (size--)
7221         {
7222           /* PENDING: do this check better */
7223           if (IS_GB && requiresHL (AOP (right)) && requiresHL (AOP (result)))
7224             {
7225               _moveA (aopGet (AOP (right), offset, FALSE));
7226               aopPut (AOP (result), "a", offset);
7227             }
7228           else
7229             aopPut (AOP (result),
7230                     aopGet (AOP (right), offset, FALSE),
7231                     offset);
7232           offset++;
7233         }
7234     }
7235
7236 release:
7237   freeAsmop (right, NULL, ic);
7238   freeAsmop (result, NULL, ic);
7239 }
7240
7241 /*-----------------------------------------------------------------*/
7242 /* genJumpTab - genrates code for jump table                       */
7243 /*-----------------------------------------------------------------*/
7244 static void
7245 genJumpTab (iCode * ic)
7246 {
7247   symbol *jtab;
7248   const char *l;
7249
7250   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
7251   /* get the condition into accumulator */
7252   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
7253   if (!IS_GB)
7254     emit2 ("push de");
7255   emit2 ("ld e,%s", l);
7256   emit2 ("ld d,!zero");
7257   jtab = newiTempLabel (NULL);
7258   spillCached ();
7259   emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
7260   emit2 ("add hl,de");
7261   emit2 ("add hl,de");
7262   emit2 ("add hl,de");
7263   freeAsmop (IC_JTCOND (ic), NULL, ic);
7264   if (!IS_GB)
7265     emit2 ("pop de");
7266   emit2 ("jp !*hl");
7267   emitLabel (jtab->key + 100);
7268   /* now generate the jump labels */
7269   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7270        jtab = setNextItem (IC_JTLABELS (ic)))
7271     emit2 ("jp !tlabel", jtab->key + 100);
7272 }
7273
7274 /*-----------------------------------------------------------------*/
7275 /* genCast - gen code for casting                                  */
7276 /*-----------------------------------------------------------------*/
7277 static void
7278 genCast (iCode * ic)
7279 {
7280   operand *result = IC_RESULT (ic);
7281   sym_link *rtype = operandType (IC_RIGHT (ic));
7282   operand *right = IC_RIGHT (ic);
7283   int size, offset;
7284
7285   /* if they are equivalent then do nothing */
7286   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7287     return;
7288
7289   aopOp (right, ic, FALSE, FALSE);
7290   aopOp (result, ic, FALSE, FALSE);
7291
7292   /* if the result is a bit */
7293   if (AOP_TYPE (result) == AOP_CRY)
7294     {
7295       wassertl (0, "Tried to cast to a bit");
7296     }
7297
7298   /* if they are the same size : or less */
7299   if (AOP_SIZE (result) <= AOP_SIZE (right))
7300     {
7301
7302       /* if they are in the same place */
7303       if (sameRegs (AOP (right), AOP (result)))
7304         goto release;
7305
7306       /* if they in different places then copy */
7307       size = AOP_SIZE (result);
7308       offset = 0;
7309       while (size--)
7310         {
7311           aopPut (AOP (result),
7312                   aopGet (AOP (right), offset, FALSE),
7313                   offset);
7314           offset++;
7315         }
7316       goto release;
7317     }
7318
7319   /* So we now know that the size of destination is greater
7320      than the size of the source */
7321   /* we move to result for the size of source */
7322   size = AOP_SIZE (right);
7323   offset = 0;
7324   while (size--)
7325     {
7326       aopPut (AOP (result),
7327               aopGet (AOP (right), offset, FALSE),
7328               offset);
7329       offset++;
7330     }
7331
7332   /* now depending on the sign of the destination */
7333   size = AOP_SIZE (result) - AOP_SIZE (right);
7334   /* Unsigned or not an integral type - right fill with zeros */
7335   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7336     {
7337       while (size--)
7338         aopPut (AOP (result), "!zero", offset++);
7339     }
7340   else
7341     {
7342       /* we need to extend the sign :{ */
7343         const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
7344                         FALSE);
7345       _moveA (l);
7346       emit2 ("rla ");
7347       emit2 ("sbc a,a");
7348       while (size--)
7349         aopPut (AOP (result), "a", offset++);
7350     }
7351
7352 release:
7353   freeAsmop (right, NULL, ic);
7354   freeAsmop (result, NULL, ic);
7355 }
7356
7357 /*-----------------------------------------------------------------*/
7358 /* genReceive - generate code for a receive iCode                  */
7359 /*-----------------------------------------------------------------*/
7360 static void
7361 genReceive (iCode * ic)
7362 {
7363   if (isOperandInFarSpace (IC_RESULT (ic)) &&
7364       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
7365        IS_TRUE_SYMOP (IC_RESULT (ic))))
7366     {
7367       wassert (0);
7368     }
7369   else
7370     {
7371         // PENDING: HACK
7372         int size;
7373         int i;
7374
7375         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
7376         size = AOP_SIZE(IC_RESULT(ic));
7377
7378         for (i = 0; i < size; i++) {
7379             aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
7380         }
7381     }
7382
7383   freeAsmop (IC_RESULT (ic), NULL, ic);
7384 }
7385
7386 /*-----------------------------------------------------------------*/
7387 /* genDummyRead - generate code for dummy read of volatiles        */
7388 /*-----------------------------------------------------------------*/
7389 static void
7390 genDummyRead (iCode * ic)
7391 {
7392   operand *op;
7393   int size, offset;
7394
7395   op = IC_RIGHT (ic);
7396   if (op && IS_SYMOP (op))
7397     {
7398       aopOp (op, ic, FALSE, FALSE);
7399
7400       /* general case */
7401       size = AOP_SIZE (op);
7402       offset = 0;
7403
7404       while (size--)
7405         {
7406           _moveA (aopGet (AOP (op), offset, FALSE));
7407           offset++;
7408         }
7409
7410       freeAsmop (op, NULL, ic);
7411     }
7412
7413   op = IC_LEFT (ic);
7414   if (op && IS_SYMOP (op))
7415     {
7416       aopOp (op, ic, FALSE, FALSE);
7417
7418       /* general case */
7419       size = AOP_SIZE (op);
7420       offset = 0;
7421
7422       while (size--)
7423         {
7424           _moveA (aopGet (AOP (op), offset, FALSE));
7425           offset++;
7426         }
7427
7428       freeAsmop (op, NULL, ic);
7429     }
7430 }
7431
7432 /*-----------------------------------------------------------------*/
7433 /* genCritical - generate code for start of a critical sequence    */
7434 /*-----------------------------------------------------------------*/
7435 static void
7436 genCritical (iCode *ic)
7437 {
7438   symbol *tlbl = newiTempLabel (NULL);
7439
7440   if (IS_GB)
7441     {
7442       emit2 ("!di");
7443     }
7444   else if (IC_RESULT (ic))
7445     {
7446       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
7447       aopPut (AOP (IC_RESULT (ic)), "!zero", 0);
7448       //get interrupt enable flag IFF2 into P/O
7449       emit2 ("ld a,i");
7450       //disable interrupt
7451       emit2 ("!di");
7452       //parity odd <==> P/O=0 <==> interrupt enable flag IFF2=0
7453       emit2 ("jp po,!tlabel", tlbl->key + 100);
7454       aopPut (AOP (IC_RESULT (ic)), "!one", 0);
7455       emit2 ("!tlabeldef", (tlbl->key + 100));
7456       freeAsmop (IC_RESULT (ic), NULL, ic);
7457     }
7458   else
7459     {
7460       //get interrupt enable flag IFF2 into P/O
7461       emit2 ("ld a,i");
7462       //disable interrupt
7463       emit2 ("!di");
7464       //save P/O flag
7465       emit2 ("push af");
7466     }
7467 }
7468
7469 /*-----------------------------------------------------------------*/
7470 /* genEndCritical - generate code for end of a critical sequence   */
7471 /*-----------------------------------------------------------------*/
7472 static void
7473 genEndCritical (iCode *ic)
7474 {
7475   symbol *tlbl = newiTempLabel (NULL);
7476
7477   if (IS_GB)
7478     {
7479       emit2 ("!ei");
7480     }
7481   else if (IC_RIGHT (ic))
7482     {
7483       aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
7484       _toBoolean (IC_RIGHT (ic));
7485       //don't enable interrupts if they were off before
7486       emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
7487       emit2 ("!ei");
7488       emitLabel (tlbl->key + 100);
7489       freeAsmop (IC_RIGHT (ic), NULL, ic);
7490     }
7491   else
7492     {
7493       //restore P/O flag
7494       emit2 ("pop af");
7495       //parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==>
7496       //don't enable interrupts as they were off before
7497       emit2 ("jp po,!tlabel", tlbl->key + 100);
7498       emit2 ("!ei");
7499       emit2 ("!tlabeldef", (tlbl->key + 100));
7500     }
7501 }
7502
7503 enum
7504   {
7505     /** Maximum number of bytes to emit per line. */
7506     DBEMIT_MAX_RUN = 8
7507   };
7508
7509 /** Context for the byte output chunker. */
7510 typedef struct
7511 {
7512   unsigned char buffer[DBEMIT_MAX_RUN];
7513   int pos;
7514 } DBEMITCTX;
7515
7516
7517 /** Flushes a byte chunker by writing out all in the buffer and
7518     reseting.
7519 */
7520 static void
7521 _dbFlush(DBEMITCTX *self)
7522 {
7523   char line[256];
7524
7525   if (self->pos > 0)
7526     {
7527       int i;
7528       sprintf(line, ".db 0x%02X", self->buffer[0]);
7529
7530       for (i = 1; i < self->pos; i++)
7531         {
7532           sprintf(line + strlen(line), ", 0x%02X", self->buffer[i]);
7533         }
7534       emit2(line);
7535     }
7536   self->pos = 0;
7537 }
7538
7539 /** Write out another byte, buffering until a decent line is
7540     generated.
7541 */
7542 static void
7543 _dbEmit(DBEMITCTX *self, int c)
7544 {
7545   if (self->pos == DBEMIT_MAX_RUN)
7546     {
7547       _dbFlush(self);
7548     }
7549   self->buffer[self->pos++] = c;
7550 }
7551
7552 /** Context for a simple run length encoder. */
7553 typedef struct
7554 {
7555   unsigned last;
7556   unsigned char buffer[128];
7557   int pos;
7558   /** runLen may be equivalent to pos. */
7559   int runLen;
7560 } RLECTX;
7561
7562 enum
7563   {
7564     RLE_CHANGE_COST = 4,
7565     RLE_MAX_BLOCK = 127
7566   };
7567
7568 /** Flush the buffer of a run length encoder by writing out the run or
7569     data that it currently contains.
7570 */
7571 static void
7572 _rleCommit(RLECTX *self)
7573 {
7574   int i;
7575   if (self->pos != 0)
7576     {
7577       DBEMITCTX db;
7578       memset(&db, 0, sizeof(db));
7579
7580       emit2(".db %u", self->pos);
7581
7582       for (i = 0; i < self->pos; i++)
7583         {
7584           _dbEmit(&db, self->buffer[i]);
7585         }
7586       _dbFlush(&db);
7587     }
7588   /* Reset */
7589   self->pos = 0;
7590 }
7591
7592 /* Encoder design:
7593    Can get either a run or a block of random stuff.
7594    Only want to change state if a good run comes in or a run ends.
7595    Detecting run end is easy.
7596    Initial state?
7597
7598    Say initial state is in run, len zero, last zero.  Then if you get a
7599    few zeros then something else then a short run will be output.
7600    Seems OK.  While in run mode, keep counting.  While in random mode,
7601    keep a count of the run.  If run hits margin, output all up to run,
7602    restart, enter run mode.
7603 */
7604
7605 /** Add another byte into the run length encoder, flushing as
7606     required.  The run length encoder uses the Amiga IFF style, where
7607     a block is prefixed by its run length.  A positive length means
7608     the next n bytes pass straight through.  A negative length means
7609     that the next byte is repeated -n times.  A zero terminates the
7610     chunks.
7611 */
7612 static void
7613 _rleAppend(RLECTX *self, unsigned c)
7614 {
7615   int i;
7616
7617   if (c != self->last)
7618     {
7619       /* The run has stopped.  See if it is worthwhile writing it out
7620          as a run.  Note that the random data comes in as runs of
7621          length one.
7622       */
7623       if (self->runLen > RLE_CHANGE_COST)
7624         {
7625           /* Yes, worthwhile. */
7626           /* Commit whatever was in the buffer. */
7627           _rleCommit(self);
7628           emit2("!db !immed-%u,!immedbyte", self->runLen, self->last);
7629         }
7630       else
7631         {
7632           /* Not worthwhile.  Append to the end of the random list. */
7633           for (i = 0; i < self->runLen; i++)
7634             {
7635               if (self->pos >= RLE_MAX_BLOCK)
7636                 {
7637                   /* Commit. */
7638                   _rleCommit(self);
7639                 }
7640               self->buffer[self->pos++] = self->last;
7641             }
7642         }
7643       self->runLen = 1;
7644       self->last = c;
7645     }
7646   else
7647     {
7648       if (self->runLen >= RLE_MAX_BLOCK)
7649         {
7650           /* Commit whatever was in the buffer. */
7651           _rleCommit(self);
7652
7653           emit2 ("!db !immed-%u,!immedbyte", self->runLen, self->last);
7654           self->runLen = 0;
7655         }
7656       self->runLen++;
7657     }
7658 }
7659
7660 static void
7661 _rleFlush(RLECTX *self)
7662 {
7663   _rleAppend(self, -1);
7664   _rleCommit(self);
7665   self->pos = 0;
7666   self->last = 0;
7667   self->runLen = 0;
7668 }
7669
7670 /** genArrayInit - Special code for initialising an array with constant
7671    data.
7672 */
7673 static void
7674 genArrayInit (iCode * ic)
7675 {
7676   literalList *iLoop;
7677   int         ix;
7678   int         elementSize = 0, eIndex, i;
7679   unsigned    val, lastVal;
7680   sym_link    *type;
7681   RLECTX      rle;
7682
7683   memset(&rle, 0, sizeof(rle));
7684
7685   aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
7686
7687   _saveRegsForCall(ic, 0);
7688
7689   fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
7690   emit2 ("call __initrleblock");
7691
7692   type = operandType(IC_LEFT(ic));
7693
7694   if (type && type->next)
7695     {
7696       if (IS_SPEC(type->next) || IS_PTR(type->next))
7697         {
7698           elementSize = getSize(type->next);
7699         }
7700       else if (IS_ARRAY(type->next) && type->next->next)
7701         {
7702           elementSize = getSize(type->next->next);
7703         }
7704       else
7705         {
7706           printTypeChainRaw (type, NULL);
7707           wassertl (0, "Can't determine element size in genArrayInit.");
7708         }
7709     }
7710   else
7711     {
7712       wassertl (0, "Can't determine element size in genArrayInit.");
7713     }
7714
7715   wassertl ((elementSize > 0) && (elementSize <= 4), "Illegal element size in genArrayInit.");
7716
7717   iLoop = IC_ARRAYILIST(ic);
7718   lastVal = (unsigned)-1;
7719
7720   /* Feed all the bytes into the run length encoder which will handle
7721      the actual output.
7722      This works well for mixed char data, and for random int and long
7723      data.
7724   */
7725   while (iLoop)
7726     {
7727       ix = iLoop->count;
7728
7729       for (i = 0; i < ix; i++)
7730         {
7731           for (eIndex = 0; eIndex < elementSize; eIndex++)
7732             {
7733               val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
7734               _rleAppend(&rle, val);
7735             }
7736         }
7737
7738       iLoop = iLoop->next;
7739     }
7740
7741   _rleFlush(&rle);
7742   /* Mark the end of the run. */
7743   emit2(".db 0");
7744
7745   _restoreRegsAfterCall();
7746
7747   spillCached ();
7748
7749   freeAsmop (IC_LEFT(ic), NULL, ic);
7750 }
7751
7752 static void
7753 _swap (PAIR_ID one, PAIR_ID two)
7754 {
7755   if ((one == PAIR_DE && two == PAIR_HL) || (one == PAIR_HL && two == PAIR_DE))
7756     {
7757       emit2 ("ex de,hl");
7758     }
7759   else
7760     {
7761       emit2 ("ld a,%s", _pairs[one].l);
7762       emit2 ("ld %s,%s", _pairs[one].l, _pairs[two].l);
7763       emit2 ("ld %s,a", _pairs[two].l);
7764       emit2 ("ld a,%s", _pairs[one].h);
7765       emit2 ("ld %s,%s", _pairs[one].h, _pairs[two].h);
7766       emit2 ("ld %s,a", _pairs[two].h);
7767     }
7768 }
7769
7770 /* The problem is that we may have all three pairs used and they may
7771    be needed in a different order.
7772
7773    Note: Have ex de,hl
7774
7775    Combinations:
7776      hl = hl            => unity, fine
7777      bc = bc
7778      de = de
7779
7780      hl = hl            hl = hl, swap de <=> bc
7781      bc = de
7782      de = bc
7783
7784      hl = bc            Worst case
7785      bc = de
7786      de = hl
7787
7788      hl = bc            de = de, swap bc <=> hl
7789      bc = hl
7790      de = de
7791
7792      hl = de            Worst case
7793      bc = hl
7794      de = bc
7795
7796      hl = de            bc = bc, swap hl <=> de
7797      bc = bc
7798      de = hl
7799
7800    Break it down into:
7801     * Any pair = pair are done last
7802     * Any pair = iTemp are done last
7803     * Any swaps can be done any time
7804
7805    A worst case:
7806     push p1
7807     p1 = p2
7808     p2 = p3
7809     pop  p3
7810
7811    So how do we detect the cases?
7812    How about a 3x3 matrix?
7813         source
7814    dest x x x x
7815         x x x x
7816         x x x x (Fourth for iTemp/other)
7817
7818    First determin which mode to use by counting the number of unity and
7819    iTemp assigns.
7820      Three - any order
7821      Two - Assign the pair first, then the rest
7822      One - Swap the two, then the rest
7823      Zero - Worst case.
7824 */
7825 static void
7826 setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
7827 {
7828   PAIR_ID ids[NUM_PAIRS][NUM_PAIRS];
7829   PAIR_ID dest[3] = {
7830     PAIR_BC, PAIR_HL, PAIR_DE
7831   };
7832   int i, j, nunity = 0;
7833   memset (ids, PAIR_INVALID, sizeof (ids));
7834
7835   /* Sanity checks */
7836   wassert (nparams == 3);
7837
7838   /* First save everything that needs to be saved. */
7839   _saveRegsForCall (ic, 0);
7840
7841   /* Loading HL first means that DE is always fine. */
7842   for (i = 0; i < nparams; i++)
7843     {
7844       aopOp (pparams[i], ic, FALSE, FALSE);
7845       ids[dest[i]][getPairId (AOP (pparams[i]))] = TRUE;
7846     }
7847
7848   /* Count the number of unity or iTemp assigns. */
7849   for (i = 0; i < 3; i++)
7850     {
7851       if (ids[dest[i]][dest[i]] == TRUE || ids[dest[i]][PAIR_INVALID] == TRUE)
7852         {
7853           nunity++;
7854         }
7855     }
7856
7857   if (nunity == 3)
7858     {
7859       /* Any order, fall through. */
7860     }
7861   else if (nunity == 2)
7862     {
7863       /* One is assigned.  Pull it out and assign. */
7864       for (i = 0; i < 3; i++)
7865         {
7866           for (j = 0; j < NUM_PAIRS; j++)
7867             {
7868               if (ids[dest[i]][j] == TRUE)
7869                 {
7870                   /* Found it.  See if it's the right one. */
7871                   if (j == PAIR_INVALID || j == dest[i])
7872                     {
7873                       /* Keep looking. */
7874                     }
7875                   else
7876                     {
7877                       fetchPair(dest[i], AOP (pparams[i]));
7878                       goto done;
7879                     }
7880                 }
7881             }
7882         }
7883     }
7884   else if (nunity == 1)
7885     {
7886       /* Find the pairs to swap. */
7887       for (i = 0; i < 3; i++)
7888         {
7889           for (j = 0; j < NUM_PAIRS; j++)
7890             {
7891               if (ids[dest[i]][j] == TRUE)
7892                 {
7893                   if (j == PAIR_INVALID || j == dest[i])
7894                     {
7895                       /* Keep looking. */
7896                     }
7897                   else
7898                     {
7899                       _swap (j, dest[i]);
7900                       goto done;
7901                     }
7902                 }
7903             }
7904         }
7905     }
7906   else
7907     {
7908       int next = getPairId (AOP (pparams[0]));
7909       emit2 ("push %s", _pairs[next].name);
7910
7911       if (next == dest[1])
7912         {
7913           fetchPair (dest[1], AOP (pparams[1]));
7914           fetchPair (dest[2], AOP (pparams[2]));
7915         }
7916       else
7917         {
7918           fetchPair (dest[2], AOP (pparams[2]));
7919           fetchPair (dest[1], AOP (pparams[1]));
7920         }
7921       emit2 ("pop %s", _pairs[dest[0]].name);
7922     }
7923  done:
7924   /* Finally pull out all of the iTemps */
7925   for (i = 0; i < 3; i++)
7926     {
7927       if (ids[dest[i]][PAIR_INVALID] == 1)
7928         {
7929           fetchPair (dest[i], AOP (pparams[i]));
7930         }
7931     }
7932 }
7933
7934 static void
7935 genBuiltInStrcpy (iCode *ic, int nParams, operand **pparams)
7936 {
7937   operand *from, *to;
7938   symbol *label;
7939   bool deInUse;
7940
7941   wassertl (nParams == 2, "Built-in strcpy must have two parameters");
7942   to = pparams[0];
7943   from = pparams[1];
7944
7945   deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
7946
7947   setupForBuiltin3 (ic, nParams, pparams);
7948
7949   label = newiTempLabel(NULL);
7950
7951   emitLabel (label->key);
7952   emit2 ("ld a,(hl)");
7953   emit2 ("ldi");
7954   emit2 ("or a");
7955   emit2 ("!shortjp nz,!tlabel ; 1", label->key);
7956
7957   freeAsmop (from, NULL, ic->next);
7958   freeAsmop (to, NULL, ic);
7959 }
7960
7961 static void
7962 genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams)
7963 {
7964   operand *from, *to, *count;
7965   bool deInUse;
7966
7967   wassertl (nParams == 3, "Built-in memcpy must have two parameters");
7968   to = pparams[2];
7969   from = pparams[1];
7970   count = pparams[0];
7971
7972   deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
7973
7974   setupForBuiltin3 (ic, nParams, pparams);
7975
7976   emit2 ("ldir");
7977
7978   freeAsmop (count, NULL, ic->next->next);
7979   freeAsmop (from, NULL, ic);
7980
7981   _restoreRegsAfterCall();
7982
7983   /* if we need assign a result value */
7984   if ((IS_ITEMP (IC_RESULT (ic)) &&
7985        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
7986         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
7987       IS_TRUE_SYMOP (IC_RESULT (ic)))
7988     {
7989       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
7990       movLeft2ResultLong (to, 0, IC_RESULT (ic), 0, 0, 2);
7991       freeAsmop (IC_RESULT (ic), NULL, ic);
7992     }
7993
7994   freeAsmop (to, NULL, ic->next);
7995 }
7996
7997 /*-----------------------------------------------------------------*/
7998 /* genBuiltIn - calls the appropriate function to  generating code */
7999 /* for a built in function                                         */
8000 /*-----------------------------------------------------------------*/
8001 static void genBuiltIn (iCode *ic)
8002 {
8003     operand *bi_parms[MAX_BUILTIN_ARGS];
8004     int nbi_parms;
8005     iCode *bi_iCode;
8006     symbol *bif;
8007
8008     /* get all the arguments for a built in function */
8009     bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
8010
8011     /* which function is it */
8012     bif = OP_SYMBOL(IC_LEFT(bi_iCode));
8013
8014     if (strcmp(bif->name,"__builtin_strcpy")==0)
8015       {
8016         genBuiltInStrcpy(bi_iCode, nbi_parms, bi_parms);
8017       }
8018     else if (strcmp(bif->name,"__builtin_memcpy")==0)
8019       {
8020         genBuiltInMemcpy(bi_iCode, nbi_parms, bi_parms);
8021       }
8022     else
8023       {
8024         wassertl (0, "Unknown builtin function encountered");
8025       }
8026 }
8027
8028 /*-----------------------------------------------------------------*/
8029 /* genZ80Code - generate code for Z80 based controllers            */
8030 /*-----------------------------------------------------------------*/
8031 void
8032 genZ80Code (iCode * lic)
8033 {
8034   iCode *ic;
8035   int cln = 0;
8036
8037   /* Hack */
8038   if (IS_GB)
8039     {
8040       _fReturn = _gbz80_return;
8041       _fTmp = _gbz80_return;
8042     }
8043   else
8044     {
8045       _fReturn = _z80_return;
8046       _fTmp = _z80_return;
8047     }
8048
8049   _G.lines.head = _G.lines.current = NULL;
8050
8051   /* if debug information required */
8052   if (options.debug && currFunc)
8053     {
8054       debugFile->writeFunction (currFunc, lic);
8055     }
8056
8057   for (ic = lic; ic; ic = ic->next)
8058     {
8059       _G.current_iCode = ic;
8060
8061       if (ic->lineno && cln != ic->lineno)
8062         {
8063           if (options.debug)
8064             {
8065               debugFile->writeCLine (ic);
8066             }
8067           if (!options.noCcodeInAsm)
8068             {
8069               emit2 (";%s:%d: %s", ic->filename, ic->lineno,
8070                      printCLine(ic->filename, ic->lineno));
8071             }
8072           cln = ic->lineno;
8073         }
8074       if (options.iCodeInAsm)
8075         {
8076           emit2 (";ic:%d: %s", ic->key, printILine(ic));
8077         }
8078       /* if the result is marked as
8079          spilt and rematerializable or code for
8080          this has already been generated then
8081          do nothing */
8082       if (resultRemat (ic) || ic->generated)
8083         continue;
8084
8085       /* depending on the operation */
8086       switch (ic->op)
8087         {
8088         case '!':
8089           emitDebug ("; genNot");
8090           genNot (ic);
8091           break;
8092
8093         case '~':
8094           emitDebug ("; genCpl");
8095           genCpl (ic);
8096           break;
8097
8098         case UNARYMINUS:
8099           emitDebug ("; genUminus");
8100           genUminus (ic);
8101           break;
8102
8103         case IPUSH:
8104           emitDebug ("; genIpush");
8105           genIpush (ic);
8106           break;
8107
8108         case IPOP:
8109           /* IPOP happens only when trying to restore a
8110              spilt live range, if there is an ifx statement
8111              following this pop then the if statement might
8112              be using some of the registers being popped which
8113              would destory the contents of the register so
8114              we need to check for this condition and handle it */
8115           if (ic->next &&
8116               ic->next->op == IFX &&
8117               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8118             {
8119               emitDebug ("; genIfx");
8120               genIfx (ic->next, ic);
8121             }
8122           else
8123             {
8124               emitDebug ("; genIpop");
8125               genIpop (ic);
8126             }
8127           break;
8128
8129         case CALL:
8130           emitDebug ("; genCall");
8131           genCall (ic);
8132           break;
8133
8134         case PCALL:
8135           emitDebug ("; genPcall");
8136           genPcall (ic);
8137           break;
8138
8139         case FUNCTION:
8140           emitDebug ("; genFunction");
8141           genFunction (ic);
8142           break;
8143
8144         case ENDFUNCTION:
8145           emitDebug ("; genEndFunction");
8146           genEndFunction (ic);
8147           break;
8148
8149         case RETURN:
8150           emitDebug ("; genRet");
8151           genRet (ic);
8152           break;
8153
8154         case LABEL:
8155           emitDebug ("; genLabel");
8156           genLabel (ic);
8157           break;
8158
8159         case GOTO:
8160           emitDebug ("; genGoto");
8161           genGoto (ic);
8162           break;
8163
8164         case '+':
8165           emitDebug ("; genPlus");
8166           genPlus (ic);
8167           break;
8168
8169         case '-':
8170           emitDebug ("; genMinus");
8171           genMinus (ic);
8172           break;
8173
8174         case '*':
8175           emitDebug ("; genMult");
8176           genMult (ic);
8177           break;
8178
8179         case '/':
8180           emitDebug ("; genDiv");
8181           genDiv (ic);
8182           break;
8183
8184         case '%':
8185           emitDebug ("; genMod");
8186           genMod (ic);
8187           break;
8188
8189         case '>':
8190           emitDebug ("; genCmpGt");
8191           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8192           break;
8193
8194         case '<':
8195           emitDebug ("; genCmpLt");
8196           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8197           break;
8198
8199         case LE_OP:
8200         case GE_OP:
8201         case NE_OP:
8202
8203           /* note these two are xlated by algebraic equivalence
8204              during parsing SDCC.y */
8205           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8206                   "got '>=' or '<=' shouldn't have come here");
8207           break;
8208
8209         case EQ_OP:
8210           emitDebug ("; genCmpEq");
8211           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8212           break;
8213
8214         case AND_OP:
8215           emitDebug ("; genAndOp");
8216           genAndOp (ic);
8217           break;
8218
8219         case OR_OP:
8220           emitDebug ("; genOrOp");
8221           genOrOp (ic);
8222           break;
8223
8224         case '^':
8225           emitDebug ("; genXor");
8226           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8227           break;
8228
8229         case '|':
8230           emitDebug ("; genOr");
8231           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8232           break;
8233
8234         case BITWISEAND:
8235           emitDebug ("; genAnd");
8236           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8237           break;
8238
8239         case INLINEASM:
8240           emitDebug ("; genInline");
8241           genInline (ic);
8242           break;
8243
8244         case RRC:
8245           emitDebug ("; genRRC");
8246           genRRC (ic);
8247           break;
8248
8249         case RLC:
8250           emitDebug ("; genRLC");
8251           genRLC (ic);
8252           break;
8253
8254         case GETHBIT:
8255           emitDebug ("; genGetHBIT");
8256           genGetHbit (ic);
8257           break;
8258
8259         case LEFT_OP:
8260           emitDebug ("; genLeftShift");
8261           genLeftShift (ic);
8262           break;
8263
8264         case RIGHT_OP:
8265           emitDebug ("; genRightShift");
8266           genRightShift (ic);
8267           break;
8268
8269         case GET_VALUE_AT_ADDRESS:
8270           emitDebug ("; genPointerGet");
8271           genPointerGet (ic);
8272           break;
8273
8274         case '=':
8275
8276           if (POINTER_SET (ic))
8277             {
8278               emitDebug ("; genAssign (pointer)");
8279               genPointerSet (ic);
8280             }
8281           else
8282             {
8283               emitDebug ("; genAssign");
8284               genAssign (ic);
8285             }
8286           break;
8287
8288         case IFX:
8289           emitDebug ("; genIfx");
8290           genIfx (ic, NULL);
8291           break;
8292
8293         case ADDRESS_OF:
8294           emitDebug ("; genAddrOf");
8295           genAddrOf (ic);
8296           break;
8297
8298         case JUMPTABLE:
8299           emitDebug ("; genJumpTab");
8300           genJumpTab (ic);
8301           break;
8302
8303         case CAST:
8304           emitDebug ("; genCast");
8305           genCast (ic);
8306           break;
8307
8308         case RECEIVE:
8309           emitDebug ("; genReceive");
8310           genReceive (ic);
8311           break;
8312
8313         case SEND:
8314           if (ic->builtinSEND)
8315             {
8316               emitDebug ("; genBuiltIn");
8317               genBuiltIn(ic);
8318             }
8319           else
8320             {
8321               emitDebug ("; addSet");
8322               addSet (&_G.sendSet, ic);
8323             }
8324           break;
8325
8326         case ARRAYINIT:
8327           emitDebug ("; genArrayInit");
8328           genArrayInit(ic);
8329           break;
8330
8331         case DUMMY_READ_VOLATILE:
8332           emitDebug ("; genDummyRead");
8333           genDummyRead (ic);
8334           break;
8335
8336         case CRITICAL:
8337           emitDebug ("; genCritical");
8338           genCritical (ic);
8339           break;
8340
8341         case ENDCRITICAL:
8342           emitDebug ("; genEndCritical");
8343           genEndCritical (ic);
8344           break;
8345
8346         default:
8347           ic = ic;
8348         }
8349     }
8350
8351
8352   /* now we are ready to call the
8353      peep hole optimizer */
8354   if (!options.nopeep)
8355     peepHole (&_G.lines.head);
8356
8357   /* This is unfortunate */
8358   /* now do the actual printing */
8359   {
8360     FILE *fp = codeOutFile;
8361     if (isInHome () && codeOutFile == code->oFile)
8362       codeOutFile = home->oFile;
8363     printLine (_G.lines.head, codeOutFile);
8364     if (_G.flushStatics)
8365       {
8366         flushStatics ();
8367         _G.flushStatics = 0;
8368       }
8369     codeOutFile = fp;
8370   }
8371
8372   freeTrace(&_G.lines.trace);
8373   freeTrace(&_G.trace.aops);
8374 }
8375
8376 /*
8377   Attic
8378 static int
8379 _isPairUsed (iCode * ic, PAIR_ID pairId)
8380 {
8381   int ret = 0;
8382   switch (pairId)
8383     {
8384     case PAIR_DE:
8385       if (bitVectBitValue (ic->rMask, D_IDX))
8386         ret++;
8387       if (bitVectBitValue (ic->rMask, E_IDX))
8388         ret++;
8389       break;
8390     default:
8391       wassert (0);
8392     }
8393   return ret;
8394 }
8395
8396 static char *
8397 fetchLitSpecial (asmop * aop, bool negate, bool xor)
8398 {
8399   unsigned long v;
8400   value *val = aop->aopu.aop_lit;
8401
8402   wassert (aop->type == AOP_LIT);
8403   wassert (!IS_FLOAT (val->type));
8404
8405   v = (unsigned long) floatFromVal (val);
8406
8407   if (xor)
8408     v ^= 0x8000;
8409   if (negate)
8410     v = 0-v;
8411   v &= 0xFFFF;
8412
8413   tsprintf (buffer, sizeof(buffer), "!immedword", v);
8414   return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
8415 }
8416
8417
8418 */