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