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