e218d9b0a280808669268326217e1266863bf0a4
[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               emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
4783               if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
4784                 emit2 ("or a,a");
4785               else
4786                 emit2 ("cp 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             /* PENDING */
4804             emit2 ("jp nz,!tlabel", lbl->key + 100);
4805           else
4806             {
4807               emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
4808               emit2 ("jp nz,!tlabel", lbl->key + 100);
4809             }
4810           offset++;
4811         }
4812     }
4813   else
4814     {
4815       /* right is a pointer reg need both a & b */
4816       /* PENDING: is this required? */
4817       while (size--)
4818         {
4819           _moveA (aopGet (AOP (right), offset, FALSE));
4820           emit2 ("cp %s", aopGet (AOP (left), offset, FALSE));
4821           emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
4822           offset++;
4823         }
4824     }
4825 }
4826
4827 /*-----------------------------------------------------------------*/
4828 /* gencjne - compare and jump if not equal                         */
4829 /*-----------------------------------------------------------------*/
4830 static void
4831 gencjne (operand * left, operand * right, symbol * lbl)
4832 {
4833   symbol *tlbl = newiTempLabel (NULL);
4834
4835   gencjneshort (left, right, lbl);
4836
4837   /* PENDING: ?? */
4838   emit2 ("ld a,!one");
4839   emit2 ("!shortjp !tlabel", tlbl->key + 100);
4840   emitLabel (lbl->key + 100);
4841   emit2 ("xor a,a");
4842   emitLabel (tlbl->key + 100);
4843 }
4844
4845 /*-----------------------------------------------------------------*/
4846 /* genCmpEq - generates code for equal to                          */
4847 /*-----------------------------------------------------------------*/
4848 static void
4849 genCmpEq (iCode * ic, iCode * ifx)
4850 {
4851   operand *left, *right, *result;
4852
4853   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
4854   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
4855   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
4856
4857   emitDebug ("; genCmpEq: left %u, right %u, result %u", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
4858
4859   /* Swap operands if it makes the operation easier. ie if:
4860      1.  Left is a literal.
4861    */
4862   if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4863     {
4864       operand *t = IC_RIGHT (ic);
4865       IC_RIGHT (ic) = IC_LEFT (ic);
4866       IC_LEFT (ic) = t;
4867     }
4868
4869   if (ifx && !AOP_SIZE (result))
4870     {
4871       symbol *tlbl;
4872       /* if they are both bit variables */
4873       if (AOP_TYPE (left) == AOP_CRY &&
4874           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4875         {
4876           wassertl (0, "Tried to compare two bits");
4877         }
4878       else
4879         {
4880           tlbl = newiTempLabel (NULL);
4881           gencjneshort (left, right, tlbl);
4882           if (IC_TRUE (ifx))
4883             {
4884               emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
4885               emitLabel (tlbl->key + 100);
4886             }
4887           else
4888             {
4889               /* PENDING: do this better */
4890               symbol *lbl = newiTempLabel (NULL);
4891               emit2 ("!shortjp !tlabel", lbl->key + 100);
4892               emitLabel (tlbl->key + 100);
4893               emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
4894               emitLabel (lbl->key + 100);
4895             }
4896         }
4897       /* mark the icode as generated */
4898       ifx->generated = 1;
4899       goto release;
4900     }
4901
4902   /* if they are both bit variables */
4903   if (AOP_TYPE (left) == AOP_CRY &&
4904       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4905     {
4906       wassertl (0, "Tried to compare a bit to either a literal or another bit");
4907     }
4908   else
4909     {
4910       emitDebug(";4");
4911
4912       gencjne (left, right, newiTempLabel (NULL));
4913       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4914         {
4915           wassert (0);
4916         }
4917       if (ifx)
4918         {
4919           emitDebug(";5");
4920           genIfxJump (ifx, "a");
4921           goto release;
4922         }
4923       /* if the result is used in an arithmetic operation
4924          then put the result in place */
4925       if (AOP_TYPE (result) != AOP_CRY)
4926         {
4927           emitDebug(";6");
4928           outAcc (result);
4929         }
4930       /* leave the result in acc */
4931     }
4932
4933 release:
4934   freeAsmop (left, NULL, ic);
4935   freeAsmop (right, NULL, ic);
4936   freeAsmop (result, NULL, ic);
4937 }
4938
4939 /*-----------------------------------------------------------------*/
4940 /* ifxForOp - returns the icode containing the ifx for operand     */
4941 /*-----------------------------------------------------------------*/
4942 static iCode *
4943 ifxForOp (operand * op, iCode * ic)
4944 {
4945   /* if true symbol then needs to be assigned */
4946   if (IS_TRUE_SYMOP (op))
4947     return NULL;
4948
4949   /* if this has register type condition and
4950      the next instruction is ifx with the same operand
4951      and live to of the operand is upto the ifx only then */
4952   if (ic->next &&
4953       ic->next->op == IFX &&
4954       IC_COND (ic->next)->key == op->key &&
4955       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4956     return ic->next;
4957
4958   return NULL;
4959 }
4960
4961 /*-----------------------------------------------------------------*/
4962 /* genAndOp - for && operation                                     */
4963 /*-----------------------------------------------------------------*/
4964 static void
4965 genAndOp (iCode * ic)
4966 {
4967   operand *left, *right, *result;
4968   symbol *tlbl;
4969
4970   /* note here that && operations that are in an if statement are
4971      taken away by backPatchLabels only those used in arthmetic
4972      operations remain */
4973   aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
4974   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
4975   aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
4976
4977   /* if both are bit variables */
4978   if (AOP_TYPE (left) == AOP_CRY &&
4979       AOP_TYPE (right) == AOP_CRY)
4980     {
4981       wassertl (0, "Tried to and two bits");
4982     }
4983   else
4984     {
4985       tlbl = newiTempLabel (NULL);
4986       _toBoolean (left);
4987       emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
4988       _toBoolean (right);
4989       emitLabel (tlbl->key + 100);
4990       outBitAcc (result);
4991     }
4992
4993   freeAsmop (left, NULL, ic);
4994   freeAsmop (right, NULL, ic);
4995   freeAsmop (result, NULL, ic);
4996 }
4997
4998 /*-----------------------------------------------------------------*/
4999 /* genOrOp - for || operation                                      */
5000 /*-----------------------------------------------------------------*/
5001 static void
5002 genOrOp (iCode * ic)
5003 {
5004   operand *left, *right, *result;
5005   symbol *tlbl;
5006
5007   /* note here that || operations that are in an
5008      if statement are taken away by backPatchLabels
5009      only those used in arthmetic operations remain */
5010   aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
5011   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
5012   aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
5013
5014   /* if both are bit variables */
5015   if (AOP_TYPE (left) == AOP_CRY &&
5016       AOP_TYPE (right) == AOP_CRY)
5017     {
5018       wassertl (0, "Tried to OR two bits");
5019     }
5020   else
5021     {
5022       tlbl = newiTempLabel (NULL);
5023       _toBoolean (left);
5024       emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5025       _toBoolean (right);
5026       emitLabel (tlbl->key + 100);
5027       outBitAcc (result);
5028     }
5029
5030   freeAsmop (left, NULL, ic);
5031   freeAsmop (right, NULL, ic);
5032   freeAsmop (result, NULL, ic);
5033 }
5034
5035 /*-----------------------------------------------------------------*/
5036 /* isLiteralBit - test if lit == 2^n                               */
5037 /*-----------------------------------------------------------------*/
5038 int
5039 isLiteralBit (unsigned long lit)
5040 {
5041   unsigned long pw[32] =
5042   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5043    0x100L, 0x200L, 0x400L, 0x800L,
5044    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5045    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5046    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5047    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5048    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5049   int idx;
5050
5051   for (idx = 0; idx < 32; idx++)
5052     if (lit == pw[idx])
5053       return idx + 1;
5054   return 0;
5055 }
5056
5057 /*-----------------------------------------------------------------*/
5058 /* jmpTrueOrFalse -                                                */
5059 /*-----------------------------------------------------------------*/
5060 static void
5061 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5062 {
5063   // ugly but optimized by peephole
5064   if (IC_TRUE (ic))
5065     {
5066       symbol *nlbl = newiTempLabel (NULL);
5067       emit2 ("jp !tlabel", nlbl->key + 100);
5068       emitLabel (tlbl->key + 100);
5069       emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
5070       emitLabel (nlbl->key + 100);
5071     }
5072   else
5073     {
5074       emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
5075       emitLabel (tlbl->key + 100);
5076     }
5077   ic->generated = 1;
5078 }
5079
5080 /*-----------------------------------------------------------------*/
5081 /* genAnd  - code for and                                          */
5082 /*-----------------------------------------------------------------*/
5083 static void
5084 genAnd (iCode * ic, iCode * ifx)
5085 {
5086   operand *left, *right, *result;
5087   int size, offset = 0;
5088   unsigned long lit = 0L;
5089   int bytelit = 0;
5090
5091   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
5092   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
5093   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
5094
5095   /* if left is a literal & right is not then exchange them */
5096   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5097       (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
5098     {
5099       operand *tmp = right;
5100       right = left;
5101       left = tmp;
5102     }
5103
5104   /* if result = right then exchange them */
5105   if (sameRegs (AOP (result), AOP (right)))
5106     {
5107       operand *tmp = right;
5108       right = left;
5109       left = tmp;
5110     }
5111
5112   /* if right is bit then exchange them */
5113   if (AOP_TYPE (right) == AOP_CRY &&
5114       AOP_TYPE (left) != AOP_CRY)
5115     {
5116       operand *tmp = right;
5117       right = left;
5118       left = tmp;
5119     }
5120   if (AOP_TYPE (right) == AOP_LIT)
5121     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5122
5123   size = AOP_SIZE (result);
5124
5125   if (AOP_TYPE (left) == AOP_CRY)
5126     {
5127       wassertl (0, "Tried to perform an AND with a bit as an operand");
5128       goto release;
5129     }
5130
5131   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5132   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5133   if ((AOP_TYPE (right) == AOP_LIT) &&
5134       (AOP_TYPE (result) == AOP_CRY) &&
5135       (AOP_TYPE (left) != AOP_CRY))
5136     {
5137       symbol *tlbl = newiTempLabel (NULL);
5138       int sizel = AOP_SIZE (left);
5139       if (size)
5140         {
5141           /* PENDING: Test case for this. */
5142           emit2 ("scf");
5143         }
5144       while (sizel--)
5145         {
5146           if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5147             {
5148               _moveA (aopGet (AOP (left), offset, FALSE));
5149               if (bytelit != 0x0FFL)
5150                 {
5151                   emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
5152                 }
5153               else
5154                 {
5155                   /* For the flags */
5156                   emit2 ("or a,a");
5157                 }
5158               emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5159             }
5160               offset++;
5161         }
5162       // bit = left & literal
5163       if (size)
5164         {
5165           emit2 ("clr c");
5166           emit2 ("!tlabeldef", tlbl->key + 100);
5167         }
5168       // if(left & literal)
5169       else
5170         {
5171           if (ifx)
5172             {
5173               jmpTrueOrFalse (ifx, tlbl);
5174             }
5175           goto release;
5176         }
5177       outBitC (result);
5178       goto release;
5179     }
5180
5181   /* if left is same as result */
5182   if (sameRegs (AOP (result), AOP (left)))
5183     {
5184       for (; size--; offset++)
5185         {
5186           if (AOP_TYPE (right) == AOP_LIT)
5187             {
5188               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5189                 continue;
5190               else
5191                 {
5192                   if (bytelit == 0)
5193                     aopPut (AOP (result), "!zero", offset);
5194                   else
5195                     {
5196                       _moveA (aopGet (AOP (left), offset, FALSE));
5197                       emit2 ("and a,%s",
5198                                 aopGet (AOP (right), offset, FALSE));
5199                       aopPut (AOP (left), "a", offset);
5200                     }
5201                 }
5202
5203             }
5204           else
5205             {
5206               if (AOP_TYPE (left) == AOP_ACC)
5207                 {
5208                   wassertl (0, "Tried to perform an AND where the left operand is allocated into A");
5209                 }
5210               else
5211                 {
5212                   _moveA (aopGet (AOP (left), offset, FALSE));
5213                   emit2 ("and a,%s",
5214                             aopGet (AOP (right), offset, FALSE));
5215                   aopPut (AOP (left), "a", offset);
5216                 }
5217             }
5218         }
5219     }
5220   else
5221     {
5222       // left & result in different registers
5223       if (AOP_TYPE (result) == AOP_CRY)
5224         {
5225           wassertl (0, "Tried to AND where the result is in carry");
5226         }
5227       else
5228         {
5229           for (; (size--); offset++)
5230             {
5231               // normal case
5232               // result = left & right
5233               if (AOP_TYPE (right) == AOP_LIT)
5234                 {
5235                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5236                     {
5237                       aopPut (AOP (result),
5238                               aopGet (AOP (left), offset, FALSE),
5239                               offset);
5240                       continue;
5241                     }
5242                   else if (bytelit == 0)
5243                     {
5244                       aopPut (AOP (result), "!zero", offset);
5245                       continue;
5246                     }
5247                 }
5248               // faster than result <- left, anl result,right
5249               // and better if result is SFR
5250               if (AOP_TYPE (left) == AOP_ACC)
5251                 emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
5252               else
5253                 {
5254                   _moveA (aopGet (AOP (left), offset, FALSE));
5255                   emit2 ("and a,%s",
5256                             aopGet (AOP (right), offset, FALSE));
5257                 }
5258               aopPut (AOP (result), "a", offset);
5259             }
5260         }
5261
5262     }
5263
5264 release:
5265   freeAsmop (left, NULL, ic);
5266   freeAsmop (right, NULL, ic);
5267   freeAsmop (result, NULL, ic);
5268 }
5269
5270 /*-----------------------------------------------------------------*/
5271 /* genOr  - code for or                                            */
5272 /*-----------------------------------------------------------------*/
5273 static void
5274 genOr (iCode * ic, iCode * ifx)
5275 {
5276   operand *left, *right, *result;
5277   int size, offset = 0;
5278   unsigned long lit = 0L;
5279   int bytelit = 0;
5280
5281   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
5282   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
5283   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
5284
5285   /* if left is a literal & right is not then exchange them */
5286   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5287       (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
5288     {
5289       operand *tmp = right;
5290       right = left;
5291       left = tmp;
5292     }
5293
5294   /* if result = right then exchange them */
5295   if (sameRegs (AOP (result), AOP (right)))
5296     {
5297       operand *tmp = right;
5298       right = left;
5299       left = tmp;
5300     }
5301
5302   /* if right is bit then exchange them */
5303   if (AOP_TYPE (right) == AOP_CRY &&
5304       AOP_TYPE (left) != AOP_CRY)
5305     {
5306       operand *tmp = right;
5307       right = left;
5308       left = tmp;
5309     }
5310   if (AOP_TYPE (right) == AOP_LIT)
5311     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5312
5313   size = AOP_SIZE (result);
5314
5315   if (AOP_TYPE (left) == AOP_CRY)
5316     {
5317       wassertl (0, "Tried to OR where left is a bit");
5318       goto release;
5319     }
5320
5321   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5322   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5323   if ((AOP_TYPE (right) == AOP_LIT) &&
5324       (AOP_TYPE (result) == AOP_CRY) &&
5325       (AOP_TYPE (left) != AOP_CRY))
5326     {
5327       symbol *tlbl = newiTempLabel (NULL);
5328       int sizel = AOP_SIZE (left);
5329
5330       if (size)
5331         {
5332           wassertl (0, "Result is assigned to a bit");
5333         }
5334       /* PENDING: Modeled after the AND code which is inefficient. */
5335       while (sizel--)
5336         {
5337           bytelit = (lit >> (offset * 8)) & 0x0FFL;
5338
5339           _moveA (aopGet (AOP (left), offset, FALSE));
5340           /* OR with any literal is the same as OR with itself. */
5341           emit2 ("or a,a");
5342           emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5343
5344           offset++;
5345         }
5346       if (ifx)
5347         {
5348           jmpTrueOrFalse (ifx, tlbl);
5349         }
5350       goto release;
5351     }
5352
5353   /* if left is same as result */
5354   if (sameRegs (AOP (result), AOP (left)))
5355     {
5356       for (; size--; offset++)
5357         {
5358           if (AOP_TYPE (right) == AOP_LIT)
5359             {
5360               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5361                 continue;
5362               else
5363                 {
5364                   _moveA (aopGet (AOP (left), offset, FALSE));
5365                   emit2 ("or a,%s",
5366                             aopGet (AOP (right), offset, FALSE));
5367                   aopPut (AOP (result), "a", offset);
5368                 }
5369             }
5370           else
5371             {
5372               if (AOP_TYPE (left) == AOP_ACC)
5373                 emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
5374               else
5375                 {
5376                   _moveA (aopGet (AOP (left), offset, FALSE));
5377                   emit2 ("or a,%s",
5378                             aopGet (AOP (right), offset, FALSE));
5379                   aopPut (AOP (result), "a", offset);
5380                 }
5381             }
5382         }
5383     }
5384   else
5385     {
5386       // left & result in different registers
5387       if (AOP_TYPE (result) == AOP_CRY)
5388         {
5389           wassertl (0, "Result of OR is in a bit");
5390         }
5391       else
5392         for (; (size--); offset++)
5393           {
5394             // normal case
5395             // result = left & right
5396             if (AOP_TYPE (right) == AOP_LIT)
5397               {
5398                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5399                   {
5400                     aopPut (AOP (result),
5401                             aopGet (AOP (left), offset, FALSE),
5402                             offset);
5403                     continue;
5404                   }
5405               }
5406             // faster than result <- left, anl result,right
5407             // and better if result is SFR
5408             if (AOP_TYPE (left) == AOP_ACC)
5409               emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
5410             else
5411               {
5412                 _moveA (aopGet (AOP (left), offset, FALSE));
5413                 emit2 ("or a,%s",
5414                           aopGet (AOP (right), offset, FALSE));
5415               }
5416             aopPut (AOP (result), "a", offset);
5417             /* PENDING: something weird is going on here.  Add exception. */
5418             if (AOP_TYPE (result) == AOP_ACC)
5419               break;
5420           }
5421     }
5422
5423 release:
5424   freeAsmop (left, NULL, ic);
5425   freeAsmop (right, NULL, ic);
5426   freeAsmop (result, NULL, ic);
5427 }
5428
5429 /*-----------------------------------------------------------------*/
5430 /* genXor - code for xclusive or                                   */
5431 /*-----------------------------------------------------------------*/
5432 static void
5433 genXor (iCode * ic, iCode * ifx)
5434 {
5435   operand *left, *right, *result;
5436   int size, offset = 0;
5437   unsigned long lit = 0L;
5438
5439   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
5440   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
5441   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
5442
5443   /* if left is a literal & right is not then exchange them */
5444   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5445       (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
5446     {
5447       operand *tmp = right;
5448       right = left;
5449       left = tmp;
5450     }
5451
5452   /* if result = right then exchange them */
5453   if (sameRegs (AOP (result), AOP (right)))
5454     {
5455       operand *tmp = right;
5456       right = left;
5457       left = tmp;
5458     }
5459
5460   /* if right is bit then exchange them */
5461   if (AOP_TYPE (right) == AOP_CRY &&
5462       AOP_TYPE (left) != AOP_CRY)
5463     {
5464       operand *tmp = right;
5465       right = left;
5466       left = tmp;
5467     }
5468   if (AOP_TYPE (right) == AOP_LIT)
5469     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5470
5471   size = AOP_SIZE (result);
5472
5473   if (AOP_TYPE (left) == AOP_CRY)
5474     {
5475       wassertl (0, "Tried to XOR a bit");
5476       goto release;
5477     }
5478
5479   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5480   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5481   if ((AOP_TYPE (right) == AOP_LIT) &&
5482       (AOP_TYPE (result) == AOP_CRY) &&
5483       (AOP_TYPE (left) != AOP_CRY))
5484     {
5485       symbol *tlbl = newiTempLabel (NULL);
5486       int sizel = AOP_SIZE (left);
5487
5488       if (size)
5489         {
5490           /* PENDING: Test case for this. */
5491           wassertl (0, "Tried to XOR left against a literal with the result going into a bit");
5492         }
5493       while (sizel--)
5494         {
5495           _moveA (aopGet (AOP (left), offset, FALSE));
5496           emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
5497           emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5498           offset++;
5499         }
5500       if (ifx)
5501         {
5502           jmpTrueOrFalse (ifx, tlbl);
5503         }
5504       else
5505         {
5506           wassertl (0, "Result of XOR was destined for a bit");
5507         }
5508       goto release;
5509     }
5510
5511   /* if left is same as result */
5512   if (sameRegs (AOP (result), AOP (left)))
5513     {
5514       for (; size--; offset++)
5515         {
5516           if (AOP_TYPE (right) == AOP_LIT)
5517             {
5518               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5519                 continue;
5520               else
5521                 {
5522                   _moveA (aopGet (AOP (left), offset, FALSE));
5523                   emit2 ("xor a,%s",
5524                             aopGet (AOP (right), offset, FALSE));
5525                   aopPut (AOP (result), "a", offset);
5526                 }
5527             }
5528           else
5529             {
5530               if (AOP_TYPE (left) == AOP_ACC)
5531                 {
5532                   emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
5533                 }
5534               else
5535                 {
5536                   _moveA (aopGet (AOP (left), offset, FALSE));
5537                   emit2 ("xor a,%s",
5538                             aopGet (AOP (right), offset, FALSE));
5539                   aopPut (AOP (result), "a", offset);
5540                 }
5541             }
5542         }
5543     }
5544   else
5545     {
5546       // left & result in different registers
5547       if (AOP_TYPE (result) == AOP_CRY)
5548         {
5549           wassertl (0, "Result of XOR is in a bit");
5550         }
5551       else
5552         for (; (size--); offset++)
5553           {
5554             // normal case
5555             // result = left & right
5556             if (AOP_TYPE (right) == AOP_LIT)
5557               {
5558                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5559                   {
5560                     aopPut (AOP (result),
5561                             aopGet (AOP (left), offset, FALSE),
5562                             offset);
5563                     continue;
5564                   }
5565               }
5566             // faster than result <- left, anl result,right
5567             // and better if result is SFR
5568             if (AOP_TYPE (left) == AOP_ACC)
5569               {
5570                 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
5571               }
5572             else
5573               {
5574                 _moveA (aopGet (AOP (left), offset, FALSE));
5575                 emit2 ("xor a,%s",
5576                           aopGet (AOP (right), offset, FALSE));
5577               }
5578             aopPut (AOP (result), "a", offset);
5579           }
5580     }
5581
5582 release:
5583   freeAsmop (left, NULL, ic);
5584   freeAsmop (right, NULL, ic);
5585   freeAsmop (result, NULL, ic);
5586 }
5587
5588 /*-----------------------------------------------------------------*/
5589 /* genInline - write the inline code out                           */
5590 /*-----------------------------------------------------------------*/
5591 static void
5592 genInline (iCode * ic)
5593 {
5594   char *buffer, *bp, *bp1;
5595
5596   _G.lines.isInline += (!options.asmpeep);
5597
5598   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5599   strcpy (buffer, IC_INLINE (ic));
5600
5601   /* emit each line as a code */
5602   while (*bp)
5603     {
5604       if (*bp == '\n')
5605         {
5606           *bp++ = '\0';
5607           emit2 (bp1);
5608           bp1 = bp;
5609         }
5610       else
5611         {
5612           if (*bp == ':')
5613             {
5614               bp++;
5615               *bp = '\0';
5616               bp++;
5617               emit2 (bp1);
5618               bp1 = bp;
5619             }
5620           else
5621             bp++;
5622         }
5623     }
5624   if (bp1 != bp)
5625     emit2 (bp1);
5626   _G.lines.isInline -= (!options.asmpeep);
5627
5628 }
5629
5630 /*-----------------------------------------------------------------*/
5631 /* genRRC - rotate right with carry                                */
5632 /*-----------------------------------------------------------------*/
5633 static void
5634 genRRC (iCode * ic)
5635 {
5636   wassert (0);
5637 }
5638
5639 /*-----------------------------------------------------------------*/
5640 /* genRLC - generate code for rotate left with carry               */
5641 /*-----------------------------------------------------------------*/
5642 static void
5643 genRLC (iCode * ic)
5644 {
5645   wassert (0);
5646 }
5647
5648 /*-----------------------------------------------------------------*/
5649 /* genGetHbit - generates code get highest order bit               */
5650 /*-----------------------------------------------------------------*/
5651 static void
5652 genGetHbit (iCode * ic)
5653 {
5654   operand *left, *result;
5655   left = IC_LEFT (ic);
5656   result = IC_RESULT (ic);
5657
5658   aopOp (left, ic, FALSE, FALSE);
5659   aopOp (result, ic, FALSE, FALSE);
5660
5661   /* get the highest order byte into a */
5662   emit2("ld a,%s", aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
5663
5664   if (AOP_TYPE (result) == AOP_CRY)
5665     {
5666       emit2 ("rl a");
5667       outBitC (result);
5668     }
5669   else
5670     {
5671       emit2 ("rlc a");
5672       emit2 ("and a,!one");
5673       outAcc (result);
5674     }
5675
5676
5677   freeAsmop (left, NULL, ic);
5678   freeAsmop (result, NULL, ic);
5679 }
5680
5681 static void
5682 emitRsh2 (asmop *aop, int size, int is_signed)
5683 {
5684   int offset = 0;
5685
5686   while (size--)
5687     {
5688       const char *l = aopGet (aop, size, FALSE);
5689       if (offset == 0)
5690         {
5691           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
5692         }
5693       else
5694         {
5695           emit2 ("rr %s", l);
5696         }
5697       offset++;
5698     }
5699 }
5700
5701 /*-----------------------------------------------------------------*/
5702 /* shiftR2Left2Result - shift right two bytes from left to result  */
5703 /*-----------------------------------------------------------------*/
5704 static void
5705 shiftR2Left2Result (operand * left, int offl,
5706                     operand * result, int offr,
5707                     int shCount, int is_signed)
5708 {
5709   int size = 2;
5710   symbol *tlbl, *tlbl1;
5711
5712   movLeft2Result (left, offl, result, offr, 0);
5713   movLeft2Result (left, offl + 1, result, offr + 1, 0);
5714
5715   if (shCount == 0)
5716     return;
5717
5718   /*  if (AOP(result)->type == AOP_REG) { */
5719
5720   tlbl = newiTempLabel (NULL);
5721   tlbl1 = newiTempLabel (NULL);
5722
5723   /* Left is already in result - so now do the shift */
5724   if (shCount <= 4)
5725     {
5726       while (shCount--)
5727         {
5728           emitRsh2 (AOP (result), size, is_signed);
5729         }
5730     }
5731   else
5732     {
5733       emit2 ("ld a,!immedbyte+1", shCount);
5734       emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5735       emitLabel (tlbl->key + 100);
5736
5737       emitRsh2 (AOP (result), size, is_signed);
5738
5739       emitLabel (tlbl1->key + 100);
5740       emit2 ("dec a");
5741       emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5742     }
5743 }
5744
5745 /*-----------------------------------------------------------------*/
5746 /* shiftL2Left2Result - shift left two bytes from left to result   */
5747 /*-----------------------------------------------------------------*/
5748 static void
5749 shiftL2Left2Result (operand * left, int offl,
5750                     operand * result, int offr, int shCount)
5751 {
5752   if (sameRegs (AOP (result), AOP (left)) &&
5753       ((offl + MSB16) == offr))
5754     {
5755       wassert (0);
5756     }
5757   else
5758     {
5759       /* Copy left into result */
5760       movLeft2Result (left, offl, result, offr, 0);
5761       movLeft2Result (left, offl + 1, result, offr + 1, 0);
5762     }
5763
5764   if (shCount == 0)
5765     return;
5766
5767   if (getPairId (AOP (result)) == PAIR_HL)
5768     {
5769       while (shCount--)
5770         {
5771           emit2 ("add hl,hl");
5772         }
5773     }
5774   else
5775     {
5776     int size = 2;
5777     int offset = 0;
5778     symbol *tlbl, *tlbl1;
5779     const char *l;
5780
5781     tlbl = newiTempLabel (NULL);
5782     tlbl1 = newiTempLabel (NULL);
5783
5784     if (AOP (result)->type == AOP_REG)
5785       {
5786         while (shCount--)
5787           {
5788             for (offset = 0; offset < size; offset++)
5789               {
5790                 l = aopGet (AOP (result), offset, FALSE);
5791
5792                 if (offset == 0)
5793                   {
5794                     emit2 ("sla %s", l);
5795                   }
5796                 else
5797                   {
5798                     emit2 ("rl %s", l);
5799                   }
5800               }
5801           }
5802       }
5803     else
5804       {
5805         /* Left is already in result - so now do the shift */
5806         if (shCount > 1)
5807           {
5808             emit2 ("ld a,!immedbyte+1", shCount);
5809             emit2 ("!shortjp !tlabel", tlbl1->key + 100);
5810             emitLabel (tlbl->key + 100);
5811           }
5812
5813         while (size--)
5814           {
5815             l = aopGet (AOP (result), offset, FALSE);
5816
5817             if (offset == 0)
5818               {
5819                 emit2 ("sla %s", l);
5820               }
5821             else
5822               {
5823                 emit2 ("rl %s", l);
5824               }
5825
5826             offset++;
5827           }
5828         if (shCount > 1)
5829           {
5830             emitLabel (tlbl1->key + 100);
5831             emit2 ("dec a");
5832             emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
5833           }
5834       }
5835   }
5836 }
5837
5838 /*-----------------------------------------------------------------*/
5839 /* AccRol - rotate left accumulator by known count                 */
5840 /*-----------------------------------------------------------------*/
5841 static void
5842 AccRol (int shCount)
5843 {
5844   shCount &= 0x0007;            // shCount : 0..7
5845
5846 #if 0
5847   switch (shCount)
5848     {
5849     case 0:
5850       break;
5851     case 1:
5852       emit2 ("sla a");
5853       break;
5854     case 2:
5855       emit2 ("sla a");
5856       emit2 ("rl a");
5857       break;
5858     case 3:
5859       emit2 ("sla a");
5860       emit2 ("rl a");
5861       emit2 ("rl a");
5862       break;
5863     case 4:
5864       emit2 ("sla a");
5865       emit2 ("rl a");
5866       emit2 ("rl a");
5867       emit2 ("rl a");
5868       break;
5869     case 5:
5870       emit2 ("srl a");
5871       emit2 ("rr a");
5872       emit2 ("rr a");
5873       break;
5874     case 6:
5875       emit2 ("srl a");
5876       emit2 ("rr a");
5877       break;
5878     case 7:
5879       emit2 ("srl a");
5880       break;
5881     }
5882 #else
5883   switch (shCount)
5884     {
5885     case 0:
5886       break;
5887     case 1:
5888       emit2 ("rlca");
5889       break;
5890     case 2:
5891       emit2 ("rlca");
5892       emit2 ("rlca");
5893       break;
5894     case 3:
5895       emit2 ("rlca");
5896       emit2 ("rlca");
5897       emit2 ("rlca");
5898       break;
5899     case 4:
5900       emit2 ("rlca");
5901       emit2 ("rlca");
5902       emit2 ("rlca");
5903       emit2 ("rlca");
5904       break;
5905     case 5:
5906       emit2 ("rrca");
5907       emit2 ("rrca");
5908       emit2 ("rrca");
5909       break;
5910     case 6:
5911       emit2 ("rrca");
5912       emit2 ("rrca");
5913       break;
5914     case 7:
5915       emit2 ("rrca");
5916       break;
5917     }
5918 #endif
5919 }
5920
5921 /*-----------------------------------------------------------------*/
5922 /* AccLsh - left shift accumulator by known count                  */
5923 /*-----------------------------------------------------------------*/
5924 static void
5925 AccLsh (int shCount)
5926 {
5927   static const unsigned char SLMask[] =
5928     {
5929       0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
5930     };
5931
5932   if (shCount != 0)
5933     {
5934       if (shCount == 1)
5935         {
5936           emit2 ("add a,a");
5937         }
5938       else if (shCount == 2)
5939         {
5940           emit2 ("add a,a");
5941           emit2 ("add a,a");
5942         }
5943       else
5944         {
5945           /* rotate left accumulator */
5946           AccRol (shCount);
5947           /* and kill the lower order bits */
5948           emit2 ("and a,!immedbyte", SLMask[shCount]);
5949         }
5950     }
5951 }
5952
5953 /*-----------------------------------------------------------------*/
5954 /* shiftL1Left2Result - shift left one byte from left to result    */
5955 /*-----------------------------------------------------------------*/
5956 static void
5957 shiftL1Left2Result (operand * left, int offl,
5958                     operand * result, int offr, int shCount)
5959 {
5960   const char *l;
5961   l = aopGet (AOP (left), offl, FALSE);
5962   _moveA (l);
5963   /* shift left accumulator */
5964   AccLsh (shCount);
5965   aopPut (AOP (result), "a", offr);
5966 }
5967
5968
5969 /*-----------------------------------------------------------------*/
5970 /* genlshTwo - left shift two bytes by known amount                */
5971 /*-----------------------------------------------------------------*/
5972 static void
5973 genlshTwo (operand * result, operand * left, int shCount)
5974 {
5975   int size = AOP_SIZE (result);
5976
5977   wassert (size == 2);
5978
5979   /* if shCount >= 8 */
5980   if (shCount >= 8)
5981     {
5982       shCount -= 8;
5983       if (size > 1)
5984         {
5985           if (shCount)
5986             {
5987               movLeft2Result (left, LSB, result, MSB16, 0);
5988               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5989               aopPut (AOP (result), "!zero", LSB);
5990             }
5991           else
5992             {
5993               movLeft2Result (left, LSB, result, MSB16, 0);
5994               aopPut (AOP (result), "!zero", 0);
5995             }
5996         }
5997       else
5998         {
5999           aopPut (AOP (result), "!zero", LSB);
6000         }
6001     }
6002   /*  0 <= shCount <= 7 */
6003   else
6004     {
6005       if (size == 1)
6006         {
6007           wassert (0);
6008         }
6009       else
6010         {
6011           shiftL2Left2Result (left, LSB, result, LSB, shCount);
6012         }
6013     }
6014 }
6015
6016 /*-----------------------------------------------------------------*/
6017 /* genlshOne - left shift a one byte quantity by known count       */
6018 /*-----------------------------------------------------------------*/
6019 static void
6020 genlshOne (operand * result, operand * left, int shCount)
6021 {
6022   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6023 }
6024
6025 /*-----------------------------------------------------------------*/
6026 /* genLeftShiftLiteral - left shifting by known count              */
6027 /*-----------------------------------------------------------------*/
6028 static void
6029 genLeftShiftLiteral (operand * left,
6030                      operand * right,
6031                      operand * result,
6032                      iCode * ic)
6033 {
6034   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6035   int size;
6036
6037   freeAsmop (right, NULL, ic);
6038
6039   aopOp (left, ic, FALSE, FALSE);
6040   aopOp (result, ic, FALSE, FALSE);
6041
6042   size = getSize (operandType (result));
6043
6044   /* I suppose that the left size >= result size */
6045
6046   if (shCount >= (size * 8))
6047     {
6048       while (size--)
6049         {
6050           aopPut (AOP (result), "!zero", size);
6051         }
6052     }
6053   else
6054     {
6055       switch (size)
6056         {
6057         case 1:
6058           genlshOne (result, left, shCount);
6059           break;
6060         case 2:
6061           genlshTwo (result, left, shCount);
6062           break;
6063         case 4:
6064           wassertl (0, "Shifting of longs is currently unsupported");
6065           break;
6066         default:
6067           wassert (0);
6068         }
6069     }
6070   freeAsmop (left, NULL, ic);
6071   freeAsmop (result, NULL, ic);
6072 }
6073
6074 /*-----------------------------------------------------------------*/
6075 /* genLeftShift - generates code for left shifting                 */
6076 /*-----------------------------------------------------------------*/
6077 static void
6078 genLeftShift (iCode * ic)
6079 {
6080   int size, offset;
6081   const char *l;
6082   symbol *tlbl, *tlbl1;
6083   operand *left, *right, *result;
6084
6085   right = IC_RIGHT (ic);
6086   left = IC_LEFT (ic);
6087   result = IC_RESULT (ic);
6088
6089   aopOp (right, ic, FALSE, FALSE);
6090
6091   /* if the shift count is known then do it
6092      as efficiently as possible */
6093   if (AOP_TYPE (right) == AOP_LIT)
6094     {
6095       genLeftShiftLiteral (left, right, result, ic);
6096       return;
6097     }
6098
6099   /* shift count is unknown then we have to form a loop get the loop
6100      count in B : Note: we take only the lower order byte since
6101      shifting more that 32 bits make no sense anyway, ( the largest
6102      size of an object can be only 32 bits ) */
6103   emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
6104   emit2 ("inc a");
6105   freeAsmop (right, NULL, ic);
6106   aopOp (left, ic, FALSE, FALSE);
6107   aopOp (result, ic, FALSE, FALSE);
6108
6109   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6110      _push (PAIR_AF);
6111
6112   /* now move the left to the result if they are not the
6113      same */
6114
6115   if (!sameRegs (AOP (left), AOP (result)))
6116     {
6117
6118       size = AOP_SIZE (result);
6119       offset = 0;
6120       while (size--)
6121         {
6122           l = aopGet (AOP (left), offset, FALSE);
6123           aopPut (AOP (result), l, offset);
6124           offset++;
6125         }
6126     }
6127
6128   tlbl = newiTempLabel (NULL);
6129   size = AOP_SIZE (result);
6130   offset = 0;
6131   tlbl1 = newiTempLabel (NULL);
6132
6133   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6134      _pop (PAIR_AF);
6135
6136   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
6137   emitLabel (tlbl->key + 100);
6138   l = aopGet (AOP (result), offset, FALSE);
6139
6140   while (size--)
6141     {
6142       l = aopGet (AOP (result), offset, FALSE);
6143
6144       if (offset == 0)
6145         {
6146           emit2 ("sla %s", l);
6147         }
6148       else
6149         {
6150           emit2 ("rl %s", l);
6151         }
6152       offset++;
6153     }
6154   emitLabel (tlbl1->key + 100);
6155   emit2 ("dec a");
6156   emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
6157
6158   freeAsmop (left, NULL, ic);
6159   freeAsmop (result, NULL, ic);
6160 }
6161
6162 /*-----------------------------------------------------------------*/
6163 /* genrshOne - left shift two bytes by known amount != 0           */
6164 /*-----------------------------------------------------------------*/
6165 static void
6166 genrshOne (operand * result, operand * left, int shCount, int is_signed)
6167 {
6168   /* Errk */
6169   int size = AOP_SIZE (result);
6170   const char *l;
6171
6172   wassert (size == 1);
6173   wassert (shCount < 8);
6174
6175   l = aopGet (AOP (left), 0, FALSE);
6176
6177   if (AOP (result)->type == AOP_REG)
6178     {
6179       aopPut (AOP (result), l, 0);
6180       l = aopGet (AOP (result), 0, FALSE);
6181       while (shCount--)
6182         {
6183           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
6184         }
6185     }
6186   else
6187     {
6188       _moveA (l);
6189       while (shCount--)
6190         {
6191           emit2 ("%s a", is_signed ? "sra" : "srl");
6192         }
6193       aopPut (AOP (result), "a", 0);
6194     }
6195 }
6196
6197 /*-----------------------------------------------------------------*/
6198 /* AccRsh - right shift accumulator by known count                 */
6199 /*-----------------------------------------------------------------*/
6200 static void
6201 AccRsh (int shCount)
6202 {
6203   static const unsigned char SRMask[] =
6204     {
6205       0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
6206     };
6207
6208   if (shCount != 0)
6209     {
6210       /* rotate right accumulator */
6211       AccRol (8 - shCount);
6212       /* and kill the higher order bits */
6213       emit2 ("and a,!immedbyte", SRMask[shCount]);
6214     }
6215 }
6216
6217 /*-----------------------------------------------------------------*/
6218 /* shiftR1Left2Result - shift right one byte from left to result   */
6219 /*-----------------------------------------------------------------*/
6220 static void
6221 shiftR1Left2Result (operand * left, int offl,
6222                     operand * result, int offr,
6223                     int shCount, int sign)
6224 {
6225   _moveA (aopGet (AOP (left), offl, FALSE));
6226   if (sign)
6227     {
6228       while (shCount--)
6229         {
6230           emit2 ("%s a", sign ? "sra" : "srl");
6231         }
6232     }
6233   else
6234     {
6235       AccRsh (shCount);
6236     }
6237   aopPut (AOP (result), "a", offr);
6238 }
6239
6240 /*-----------------------------------------------------------------*/
6241 /* genrshTwo - right shift two bytes by known amount               */
6242 /*-----------------------------------------------------------------*/
6243 static void
6244 genrshTwo (operand * result, operand * left,
6245            int shCount, int sign)
6246 {
6247   /* if shCount >= 8 */
6248   if (shCount >= 8)
6249     {
6250       shCount -= 8;
6251       if (shCount)
6252         {
6253           shiftR1Left2Result (left, MSB16, result, LSB,
6254                               shCount, sign);
6255         }
6256       else
6257         {
6258           movLeft2Result (left, MSB16, result, LSB, sign);
6259         }
6260       if (sign)
6261         {
6262           /* Sign extend the result */
6263           _moveA(aopGet (AOP (result), 0, FALSE));
6264           emit2 ("rlc a");
6265           emit2 ("sbc a,a");
6266
6267           aopPut (AOP (result), ACC_NAME, MSB16);
6268         }
6269       else
6270         {
6271           aopPut (AOP (result), "!zero", 1);
6272         }
6273     }
6274   /*  0 <= shCount <= 7 */
6275   else
6276     {
6277       shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6278     }
6279 }
6280
6281 /*-----------------------------------------------------------------*/
6282 /* genRightShiftLiteral - left shifting by known count              */
6283 /*-----------------------------------------------------------------*/
6284 static void
6285 genRightShiftLiteral (operand * left,
6286                       operand * right,
6287                       operand * result,
6288                       iCode * ic,
6289                       int sign)
6290 {
6291   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6292   int size;
6293
6294   freeAsmop (right, NULL, ic);
6295
6296   aopOp (left, ic, FALSE, FALSE);
6297   aopOp (result, ic, FALSE, FALSE);
6298
6299   size = getSize (operandType (result));
6300
6301   /* I suppose that the left size >= result size */
6302
6303   if (shCount >= (size * 8)) {
6304     const char *s;
6305     if (!SPEC_USIGN(getSpec(operandType(left)))) {
6306       _moveA(aopGet (AOP (left), 0, FALSE));
6307       emit2 ("rlc a");
6308       emit2 ("sbc a,a");
6309       s=ACC_NAME;
6310     } else {
6311       s="!zero";
6312     }
6313     while (size--)
6314       aopPut (AOP (result), s, size);
6315   }
6316   else
6317     {
6318       switch (size)
6319         {
6320         case 1:
6321           genrshOne (result, left, shCount, sign);
6322           break;
6323         case 2:
6324           genrshTwo (result, left, shCount, sign);
6325           break;
6326         case 4:
6327           wassertl (0, "Asked to shift right a long which should be a function call");
6328           break;
6329         default:
6330           wassertl (0, "Entered default case in right shift delegate");
6331         }
6332     }
6333   freeAsmop (left, NULL, ic);
6334   freeAsmop (result, NULL, ic);
6335 }
6336
6337 /*-----------------------------------------------------------------*/
6338 /* genRightShift - generate code for right shifting                */
6339 /*-----------------------------------------------------------------*/
6340 static void
6341 genRightShift (iCode * ic)
6342 {
6343   operand *right, *left, *result;
6344   sym_link *retype;
6345   int size, offset, first = 1;
6346   const char *l;
6347   bool is_signed;
6348
6349   symbol *tlbl, *tlbl1;
6350
6351   /* if signed then we do it the hard way preserve the
6352      sign bit moving it inwards */
6353   retype = getSpec (operandType (IC_RESULT (ic)));
6354
6355   is_signed = !SPEC_USIGN (retype);
6356
6357   /* signed & unsigned types are treated the same : i.e. the
6358      signed is NOT propagated inwards : quoting from the
6359      ANSI - standard : "for E1 >> E2, is equivalent to division
6360      by 2**E2 if unsigned or if it has a non-negative value,
6361      otherwise the result is implementation defined ", MY definition
6362      is that the sign does not get propagated */
6363
6364   right = IC_RIGHT (ic);
6365   left = IC_LEFT (ic);
6366   result = IC_RESULT (ic);
6367
6368   aopOp (right, ic, FALSE, FALSE);
6369
6370   /* if the shift count is known then do it
6371      as efficiently as possible */
6372   if (AOP_TYPE (right) == AOP_LIT)
6373     {
6374       genRightShiftLiteral (left, right, result, ic, is_signed);
6375       return;
6376     }
6377
6378   emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
6379   emit2 ("inc a");
6380   freeAsmop (right, NULL, ic);
6381
6382   aopOp (left, ic, FALSE, FALSE);
6383   aopOp (result, ic, FALSE, FALSE);
6384
6385   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6386      _push (PAIR_AF);
6387
6388   /* now move the left to the result if they are not the
6389      same */
6390   if (!sameRegs (AOP (left), AOP (result)))
6391     {
6392
6393       size = AOP_SIZE (result);
6394       offset = 0;
6395       while (size--)
6396         {
6397           l = aopGet (AOP (left), offset, FALSE);
6398           aopPut (AOP (result), l, offset);
6399           offset++;
6400         }
6401     }
6402
6403   tlbl = newiTempLabel (NULL);
6404   tlbl1 = newiTempLabel (NULL);
6405   size = AOP_SIZE (result);
6406   offset = size - 1;
6407
6408   if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
6409      _pop (PAIR_AF);
6410
6411   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
6412   emitLabel (tlbl->key + 100);
6413   while (size--)
6414     {
6415       l = aopGet (AOP (result), offset--, FALSE);
6416       if (first)
6417         {
6418           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
6419           first = 0;
6420         }
6421       else
6422         {
6423           emit2 ("rr %s", l);
6424         }
6425     }
6426   emitLabel (tlbl1->key + 100);
6427   emit2 ("dec a");
6428   emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
6429
6430   freeAsmop (left, NULL, ic);
6431   freeAsmop (result, NULL, ic);
6432 }
6433
6434
6435 /*-----------------------------------------------------------------*/
6436 /* genUnpackBits - generates code for unpacking bits               */
6437 /*-----------------------------------------------------------------*/
6438 static void
6439 genUnpackBits (operand * result, int pair)
6440 {
6441   int offset = 0;       /* result byte offset */
6442   int rsize;            /* result size */
6443   int rlen = 0;         /* remaining bitfield length */
6444   sym_link *etype;      /* bitfield type information */
6445   int blen;             /* bitfield length */
6446   int bstr;             /* bitfield starting bit within byte */
6447
6448   emitDebug ("; genUnpackBits");
6449
6450   etype = getSpec (operandType (result));
6451   rsize = getSize (operandType (result));
6452   blen = SPEC_BLEN (etype);
6453   bstr = SPEC_BSTR (etype);
6454
6455   /* If the bitfield length is less than a byte */
6456   if (blen < 8)
6457     {
6458       emit2 ("ld a,!*pair", _pairs[pair].name);
6459       AccRol (8 - bstr);
6460       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - blen));
6461       if (!SPEC_USIGN (etype))
6462         {
6463           /* signed bitfield */
6464           symbol *tlbl = newiTempLabel (NULL);
6465
6466           emit2 ("bit %d,a", blen - 1);
6467           emit2 ("jp z,!tlabel", tlbl->key + 100);
6468           emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
6469           emitLabel (tlbl->key + 100);
6470         }
6471       aopPut (AOP (result), "a", offset++);
6472       goto finish;
6473     }
6474
6475   /* TODO: what if pair == PAIR_DE ? */
6476   if (getPairId (AOP (result)) == PAIR_HL)
6477     {
6478       wassertl (rsize == 2, "HL must be of size 2");
6479       emit2 ("ld a,!*hl");
6480       emit2 ("inc hl");
6481       emit2 ("ld h,!*hl");
6482       emit2 ("ld l,a");
6483       emit2 ("ld a,h");
6484       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (16 - blen));
6485       if (!SPEC_USIGN (etype))
6486         {
6487           /* signed bitfield */
6488           symbol *tlbl = newiTempLabel (NULL);
6489
6490           emit2 ("bit %d,a", blen - 1);
6491           emit2 ("jp z,!tlabel", tlbl->key + 100);
6492           emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
6493           emitLabel (tlbl->key + 100);
6494         }
6495       emit2 ("ld h,a");
6496       spillPair (PAIR_HL);
6497       return;
6498     }
6499
6500   /* Bit field did not fit in a byte. Copy all
6501      but the partial byte at the end.  */
6502   for (rlen=blen;rlen>=8;rlen-=8)
6503     {
6504       emit2 ("ld a,!*pair", _pairs[pair].name);
6505       aopPut (AOP (result), "a", offset++);
6506       if (rlen>8)
6507         {
6508           emit2 ("inc %s", _pairs[pair].name);
6509           _G.pairs[pair].offset++;
6510         }
6511     }
6512
6513   /* Handle the partial byte at the end */
6514   if (rlen)
6515     {
6516       emit2 ("ld a,!*pair", _pairs[pair].name);
6517       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - rlen));
6518       if (!SPEC_USIGN (etype))
6519         {
6520           /* signed bitfield */
6521           symbol *tlbl = newiTempLabel (NULL);
6522
6523           emit2 ("bit %d,a", rlen - 1);
6524           emit2 ("jp z,!tlabel", tlbl->key + 100);
6525           emit2 ("or a,!immedbyte", (unsigned char) (0xff << rlen));
6526           emitLabel (tlbl->key + 100);
6527         }
6528       aopPut (AOP (result), "a", offset++);
6529     }
6530
6531 finish:
6532   if (offset < rsize)
6533     {
6534       char *source;
6535
6536       if (SPEC_USIGN (etype))
6537         source = "!zero";
6538       else
6539         {
6540           /* signed bitfield: sign extension with 0x00 or 0xff */
6541           emit2 ("rla");
6542           emit2 ("sbc a,a");
6543
6544           source = "a";
6545         }
6546       rsize -= offset;
6547       while (rsize--)
6548         aopPut (AOP (result), source, offset++);
6549     }
6550 }
6551
6552 /*-----------------------------------------------------------------*/
6553 /* genGenPointerGet -  get value from generic pointer space        */
6554 /*-----------------------------------------------------------------*/
6555 static void
6556 genGenPointerGet (operand * left,
6557                   operand * result, iCode * ic)
6558 {
6559   int size, offset;
6560   sym_link *retype = getSpec (operandType (result));
6561   int pair = PAIR_HL;
6562
6563   if (IS_GB)
6564     pair = PAIR_DE;
6565
6566   aopOp (left, ic, FALSE, FALSE);
6567   aopOp (result, ic, FALSE, FALSE);
6568
6569   size = AOP_SIZE (result);
6570
6571   if (isPair (AOP (left)) && size == 1 && !IS_BITVAR (retype))
6572     {
6573       /* Just do it */
6574       if (isPtrPair (AOP (left)))
6575         {
6576           tsprintf (buffer, sizeof(buffer),
6577                     "!*pair", getPairName (AOP (left)));
6578           aopPut (AOP (result), buffer, 0);
6579         }
6580       else
6581         {
6582           emit2 ("ld a,!*pair", getPairName (AOP (left)));
6583           aopPut (AOP (result), "a", 0);
6584         }
6585       freeAsmop (left, NULL, ic);
6586       goto release;
6587     }
6588
6589   if (getPairId (AOP (left)) == PAIR_IY && !IS_BITVAR (retype))
6590     {
6591       /* Just do it */
6592       offset = 0;
6593       while (size--)
6594         {
6595           char at[20];
6596           tsprintf (at, sizeof(at), "!*iyx", offset);
6597           aopPut (AOP (result), at, offset);
6598           offset++;
6599         }
6600
6601       freeAsmop (left, NULL, ic);
6602       goto release;
6603     }
6604
6605   /* For now we always load into IY */
6606   /* if this is remateriazable */
6607   fetchPair (pair, AOP (left));
6608
6609   /* if bit then unpack */
6610   if (IS_BITVAR (retype))
6611     {
6612       genUnpackBits (result, pair);
6613       freeAsmop (left, NULL, ic);
6614       goto release;
6615       //wassert (0);
6616     }
6617   else if (getPairId (AOP (result)) == PAIR_HL)
6618     {
6619       wassertl (size == 2, "HL must be of size 2");
6620       emit2 ("ld a,!*hl");
6621       emit2 ("inc hl");
6622       emit2 ("ld h,!*hl");
6623       emit2 ("ld l,a");
6624       spillPair (PAIR_HL);
6625     }
6626   else if (getPairId (AOP (left)) == PAIR_HL && !isLastUse (ic, left))
6627     {
6628       size = AOP_SIZE (result);
6629       offset = 0;
6630
6631       while (size--)
6632         {
6633           /* PENDING: make this better */
6634           if (!IS_GB && AOP_TYPE (result) == AOP_REG)
6635             {
6636               aopPut (AOP (result), "!*hl", offset++);
6637             }
6638           else
6639             {
6640               emit2 ("ld a,!*pair", _pairs[pair].name);
6641               aopPut (AOP (result), "a", offset++);
6642             }
6643           if (size)
6644             {
6645               emit2 ("inc %s", _pairs[pair].name);
6646               _G.pairs[pair].offset++;
6647             }
6648         }
6649       /* Fixup HL back down */
6650       for (size = AOP_SIZE (result)-1; size; size--)
6651         {
6652           emit2 ("dec %s", _pairs[pair].name);
6653         }
6654     }
6655   else
6656     {
6657       size = AOP_SIZE (result);
6658       offset = 0;
6659
6660       while (size--)
6661         {
6662           /* PENDING: make this better */
6663           if (!IS_GB &&
6664               (AOP_TYPE (result) == AOP_REG || AOP_TYPE (result) == AOP_HLREG))
6665             {
6666               aopPut (AOP (result), "!*hl", offset++);
6667             }
6668           else
6669             {
6670               emit2 ("ld a,!*pair", _pairs[pair].name);
6671               aopPut (AOP (result), "a", offset++);
6672             }
6673           if (size)
6674             {
6675               emit2 ("inc %s", _pairs[pair].name);
6676               _G.pairs[pair].offset++;
6677             }
6678         }
6679     }
6680
6681   freeAsmop (left, NULL, ic);
6682
6683 release:
6684   freeAsmop (result, NULL, ic);
6685 }
6686
6687 /*-----------------------------------------------------------------*/
6688 /* genPointerGet - generate code for pointer get                   */
6689 /*-----------------------------------------------------------------*/
6690 static void
6691 genPointerGet (iCode * ic)
6692 {
6693   operand *left, *result;
6694   sym_link *type, *etype;
6695
6696   left = IC_LEFT (ic);
6697   result = IC_RESULT (ic);
6698
6699   /* depending on the type of pointer we need to
6700      move it to the correct pointer register */
6701   type = operandType (left);
6702   etype = getSpec (type);
6703
6704   genGenPointerGet (left, result, ic);
6705 }
6706
6707 bool
6708 isRegOrLit (asmop * aop)
6709 {
6710   if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD || aop->type == AOP_HLREG)
6711     return TRUE;
6712   return FALSE;
6713 }
6714
6715
6716 /*-----------------------------------------------------------------*/
6717 /* genPackBits - generates code for packed bit storage             */
6718 /*-----------------------------------------------------------------*/
6719 static void
6720 genPackBits (sym_link * etype,
6721              operand * right,
6722              int pair,
6723              iCode *ic)
6724 {
6725   int offset = 0;       /* source byte offset */
6726   int rlen = 0;         /* remaining bitfield length */
6727   int blen;             /* bitfield length */
6728   int bstr;             /* bitfield starting bit within byte */
6729   int litval;           /* source literal value (if AOP_LIT) */
6730   unsigned char mask;   /* bitmask within current byte */
6731   int extraPair;        /* a tempory register */
6732   bool needPopExtra=0;  /* need to restore original value of temp reg */
6733
6734   emitDebug (";     genPackBits","");
6735
6736   blen = SPEC_BLEN (etype);
6737   bstr = SPEC_BSTR (etype);
6738
6739   /* If the bitfield length is less than a byte */
6740   if (blen < 8)
6741     {
6742       mask = ((unsigned char) (0xFF << (blen + bstr)) |
6743               (unsigned char) (0xFF >> (8 - bstr)));
6744
6745       if (AOP_TYPE (right) == AOP_LIT)
6746         {
6747           /* Case with a bitfield length <8 and literal source
6748           */
6749           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6750           litval <<= bstr;
6751           litval &= (~mask) & 0xff;
6752           emit2 ("ld a,!*pair", _pairs[pair].name);
6753           if ((mask|litval)!=0xff)
6754             emit2 ("and a,!immedbyte", mask);
6755           if (litval)
6756             emit2 ("or a,!immedbyte", litval);
6757           emit2 ("ld !*pair,a", _pairs[pair].name);
6758           return;
6759         }
6760       else
6761         {
6762           /* Case with a bitfield length <8 and arbitrary source
6763           */
6764           _moveA (aopGet (AOP (right), 0, FALSE));
6765           /* shift and mask source value */
6766           AccLsh (bstr);
6767           emit2 ("and a,!immedbyte", (~mask) & 0xff);
6768
6769           extraPair = getFreePairId(ic);
6770           if (extraPair == PAIR_INVALID)
6771             {
6772               extraPair = PAIR_BC;
6773               if (getPairId (AOP (right)) != PAIR_BC
6774                   || !isLastUse (ic, right))
6775                 {
6776                   _push (extraPair);
6777                   needPopExtra = 1;
6778                 }
6779             }
6780           emit2 ("ld %s,a", _pairs[extraPair].l);
6781           emit2 ("ld a,!*pair", _pairs[pair].name);
6782
6783           emit2 ("and a,!immedbyte", mask);
6784           emit2 ("or a,%s", _pairs[extraPair].l);
6785           emit2 ("ld !*pair,a", _pairs[pair].name);
6786           if (needPopExtra)
6787             _pop (extraPair);
6788           return;
6789         }
6790     }
6791
6792   /* Bit length is greater than 7 bits. In this case, copy  */
6793   /* all except the partial byte at the end                 */
6794   for (rlen=blen;rlen>=8;rlen-=8)
6795     {
6796       emit2 ("ld a,%s", aopGet (AOP (right), offset++, FALSE) );
6797       emit2 ("ld !*pair,a", _pairs[pair].name);
6798       if (rlen>8)
6799         {
6800           emit2 ("inc %s", _pairs[pair].name);
6801           _G.pairs[pair].offset++;
6802         }
6803     }
6804
6805   /* If there was a partial byte at the end */
6806   if (rlen)
6807     {
6808       mask = (((unsigned char) -1 << rlen) & 0xff);
6809
6810       if (AOP_TYPE (right) == AOP_LIT)
6811         {
6812           /* Case with partial byte and literal source
6813           */
6814           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6815           litval >>= (blen-rlen);
6816           litval &= (~mask) & 0xff;
6817           emit2 ("ld a,!*pair", _pairs[pair].name);
6818           if ((mask|litval)!=0xff)
6819             emit2 ("and a,!immedbyte", mask);
6820           if (litval)
6821             emit2 ("or a,!immedbyte", litval);
6822         }
6823       else
6824         {
6825           /* Case with partial byte and arbitrary source
6826           */
6827           _moveA (aopGet (AOP (right), offset++, FALSE));
6828           emit2 ("and a,!immedbyte", (~mask) & 0xff);
6829
6830           extraPair = getFreePairId(ic);
6831           if (extraPair == PAIR_INVALID)
6832             {
6833               extraPair = getPairId (AOP (right));
6834               if (!isLastUse (ic, right) || (extraPair == PAIR_INVALID))
6835                 extraPair = PAIR_BC;
6836
6837               if (getPairId (AOP (right)) != PAIR_BC
6838                   || !isLastUse (ic, right))
6839                 {
6840                   _push (extraPair);
6841                   needPopExtra = 1;
6842                 }
6843             }
6844           emit2 ("ld %s,a", _pairs[extraPair].l);
6845           emit2 ("ld a,!*pair", _pairs[pair].name);
6846
6847           emit2 ("and a,!immedbyte", mask);
6848           emit2 ("or a,%s", _pairs[extraPair].l);
6849           if (needPopExtra)
6850             _pop (extraPair);
6851
6852         }
6853       emit2 ("ld !*pair,a", _pairs[pair].name);
6854     }
6855 }
6856
6857
6858 /*-----------------------------------------------------------------*/
6859 /* genGenPointerSet - stores the value into a pointer location        */
6860 /*-----------------------------------------------------------------*/
6861 static void
6862 genGenPointerSet (operand * right,
6863                   operand * result, iCode * ic)
6864 {
6865   int size, offset;
6866   sym_link *retype = getSpec (operandType (right));
6867   sym_link *letype = getSpec (operandType (result));
6868   PAIR_ID pairId = PAIR_HL;
6869   bool isBitvar;
6870
6871   aopOp (result, ic, FALSE, FALSE);
6872   aopOp (right, ic, FALSE, FALSE);
6873
6874   if (IS_GB)
6875     pairId = PAIR_DE;
6876
6877   size = AOP_SIZE (right);
6878
6879   isBitvar = IS_BITVAR(retype) || IS_BITVAR(letype);
6880   emitDebug("; isBitvar = %d", isBitvar);
6881
6882   /* Handle the exceptions first */
6883   if (isPair (AOP (result)) && size == 1 && !isBitvar)
6884     {
6885       /* Just do it */
6886       const char *l = aopGet (AOP (right), 0, FALSE);
6887       const char *pair = getPairName (AOP (result));
6888       if (canAssignToPtr (l) && isPtr (pair))
6889         {
6890           emit2 ("ld !*pair,%s", pair, l);
6891         }
6892       else
6893         {
6894           _moveA (l);
6895           emit2 ("ld !*pair,a", pair);
6896         }
6897       goto release;
6898     }
6899
6900   if ( getPairId( AOP (result)) == PAIR_IY && !isBitvar)
6901     {
6902       /* Just do it */
6903       const char *l = aopGet (AOP (right), 0, FALSE);
6904
6905       offset = 0;
6906       while (size--)
6907         {
6908           if (canAssignToPtr (l))
6909             {
6910               emit2 ("ld !*iyx,%s", offset, aopGet( AOP(right), offset, FALSE));
6911             }
6912           else
6913             {
6914               _moveA (aopGet (AOP (right), offset, FALSE));
6915               emit2 ("ld !*iyx,a", offset);
6916             }
6917           offset++;
6918         }
6919       goto release;
6920     }
6921   else if (getPairId (AOP (result)) == PAIR_HL && !isLastUse (ic, result)
6922            && !isBitvar)
6923     {
6924       offset = 0;
6925
6926       while (size--)
6927         {
6928           const char *l = aopGet (AOP (right), offset, FALSE);
6929           if (isRegOrLit (AOP (right)) && !IS_GB)
6930             {
6931               emit2 ("ld !*pair,%s", _pairs[PAIR_HL].name, l);
6932             }
6933           else
6934             {
6935               _moveA (l);
6936               emit2 ("ld !*pair,a", _pairs[PAIR_HL].name);
6937             }
6938           if (size)
6939             {
6940               emit2 ("inc %s", _pairs[PAIR_HL].name);
6941               _G.pairs[PAIR_HL].offset++;
6942             }
6943           offset++;
6944         }
6945
6946       /* Fixup HL back down */
6947       for (size = AOP_SIZE (right)-1; size; size--)
6948         {
6949           emit2 ("dec %s", _pairs[PAIR_HL].name);
6950         }
6951       goto release;
6952     }
6953
6954   /* if the operand is already in dptr
6955      then we do nothing else we move the value to dptr */
6956   if (AOP_TYPE (result) != AOP_STR)
6957     {
6958       fetchPair (pairId, AOP (result));
6959     }
6960   /* so hl now contains the address */
6961   freeAsmop (result, NULL, ic);
6962
6963   /* if bit then unpack */
6964   if (isBitvar)
6965     {
6966       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, pairId, ic);
6967       goto release;
6968       //wassert (0);
6969     }
6970   else
6971     {
6972       offset = 0;
6973
6974       while (size--)
6975         {
6976           const char *l = aopGet (AOP (right), offset, FALSE);
6977           if (isRegOrLit (AOP (right)) && !IS_GB)
6978             {
6979               emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
6980             }
6981           else
6982             {
6983               _moveA (l);
6984               emit2 ("ld !*pair,a", _pairs[pairId].name);
6985             }
6986           if (size)
6987             {
6988               emit2 ("inc %s", _pairs[pairId].name);
6989               _G.pairs[pairId].offset++;
6990             }
6991           offset++;
6992         }
6993     }
6994 release:
6995   freeAsmop (right, NULL, ic);
6996 }
6997
6998 /*-----------------------------------------------------------------*/
6999 /* genPointerSet - stores the value into a pointer location        */
7000 /*-----------------------------------------------------------------*/
7001 static void
7002 genPointerSet (iCode * ic)
7003 {
7004   operand *right, *result;
7005   sym_link *type, *etype;
7006
7007   right = IC_RIGHT (ic);
7008   result = IC_RESULT (ic);
7009
7010   /* depending on the type of pointer we need to
7011      move it to the correct pointer register */
7012   type = operandType (result);
7013   etype = getSpec (type);
7014
7015   genGenPointerSet (right, result, ic);
7016 }
7017
7018 /*-----------------------------------------------------------------*/
7019 /* genIfx - generate code for Ifx statement                        */
7020 /*-----------------------------------------------------------------*/
7021 static void
7022 genIfx (iCode * ic, iCode * popIc)
7023 {
7024   operand *cond = IC_COND (ic);
7025   int isbit = 0;
7026
7027   aopOp (cond, ic, FALSE, TRUE);
7028
7029   /* get the value into acc */
7030   if (AOP_TYPE (cond) != AOP_CRY)
7031     _toBoolean (cond);
7032   else
7033     isbit = 1;
7034   /* the result is now in the accumulator */
7035   freeAsmop (cond, NULL, ic);
7036
7037   /* if there was something to be popped then do it */
7038   if (popIc)
7039     genIpop (popIc);
7040
7041   /* if the condition is  a bit variable */
7042   if (isbit && IS_ITEMP (cond) &&
7043       SPIL_LOC (cond))
7044     genIfxJump (ic, SPIL_LOC (cond)->rname);
7045   else if (isbit && !IS_ITEMP (cond))
7046     genIfxJump (ic, OP_SYMBOL (cond)->rname);
7047   else
7048     genIfxJump (ic, "a");
7049
7050   ic->generated = 1;
7051 }
7052
7053 /*-----------------------------------------------------------------*/
7054 /* genAddrOf - generates code for address of                       */
7055 /*-----------------------------------------------------------------*/
7056 static void
7057 genAddrOf (iCode * ic)
7058 {
7059   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7060
7061   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
7062
7063   /* if the operand is on the stack then we
7064      need to get the stack offset of this
7065      variable */
7066   if (IS_GB)
7067     {
7068       if (sym->onStack)
7069         {
7070           spillCached ();
7071           if (sym->stack <= 0)
7072             {
7073               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset);
7074             }
7075           else
7076             {
7077               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
7078             }
7079           commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
7080         }
7081       else
7082         {
7083           emit2 ("ld de,!hashedstr", sym->rname);
7084           commitPair (AOP (IC_RESULT (ic)), PAIR_DE);
7085         }
7086     }
7087   else
7088     {
7089       spillCached ();
7090       if (sym->onStack)
7091         {
7092           /* if it has an offset  then we need to compute it */
7093           if (sym->stack > 0)
7094             emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
7095           else
7096             emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset);
7097           emit2 ("add hl,sp");
7098         }
7099       else
7100         {
7101           emit2 ("ld hl,!hashedstr", sym->rname);
7102         }
7103       commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
7104     }
7105   freeAsmop (IC_RESULT (ic), NULL, ic);
7106 }
7107
7108 /*-----------------------------------------------------------------*/
7109 /* genAssign - generate code for assignment                        */
7110 /*-----------------------------------------------------------------*/
7111 static void
7112 genAssign (iCode * ic)
7113 {
7114   operand *result, *right;
7115   int size, offset;
7116   unsigned long lit = 0L;
7117
7118   result = IC_RESULT (ic);
7119   right = IC_RIGHT (ic);
7120
7121   /* Dont bother assigning if they are the same */
7122   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7123     {
7124       emitDebug ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
7125       return;
7126     }
7127
7128   aopOp (right, ic, FALSE, FALSE);
7129   aopOp (result, ic, TRUE, FALSE);
7130
7131   /* if they are the same registers */
7132   if (sameRegs (AOP (right), AOP (result)))
7133     {
7134       emitDebug ("; (registers are the same)");
7135       goto release;
7136     }
7137
7138   /* if the result is a bit */
7139   if (AOP_TYPE (result) == AOP_CRY)
7140     {
7141       wassertl (0, "Tried to assign to a bit");
7142     }
7143
7144   /* general case */
7145   size = AOP_SIZE (result);
7146   offset = 0;
7147
7148   if (AOP_TYPE (right) == AOP_LIT)
7149     {
7150       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7151     }
7152
7153   if (isPair (AOP (result)))
7154     {
7155       fetchPairLong (getPairId (AOP (result)), AOP (right), ic, LSB);
7156     }
7157   else if ((size > 1) &&
7158            (AOP_TYPE (result) != AOP_REG) &&
7159            (AOP_TYPE (right) == AOP_LIT) &&
7160            !IS_FLOAT (operandType (right)) &&
7161            (lit < 256L))
7162     {
7163       bool fXored = FALSE;
7164       offset = 0;
7165       /* Work from the top down.
7166          Done this way so that we can use the cached copy of 0
7167          in A for a fast clear */
7168       while (size--)
7169         {
7170           if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
7171             {
7172               if (!fXored && size > 1)
7173                 {
7174                   emit2 ("xor a,a");
7175                   fXored = TRUE;
7176                 }
7177               if (fXored)
7178                 {
7179                   aopPut (AOP (result), "a", offset);
7180                 }
7181               else
7182                 {
7183                   aopPut (AOP (result), "!zero", offset);
7184                 }
7185             }
7186           else
7187             aopPut (AOP (result),
7188                     aopGet (AOP (right), offset, FALSE),
7189                     offset);
7190           offset++;
7191         }
7192     }
7193   else if (size == 2 && AOP_TYPE (right) == AOP_IY)
7194     {
7195       emit2 ("ld hl,(%s)", AOP (right)->aopu.aop_dir);
7196       aopPut (AOP (result), "l", LSB);
7197       aopPut (AOP (result), "h", MSB16);
7198     }
7199   else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
7200     {
7201       /* Special case.  Load into a and d, then load out. */
7202       _moveA (aopGet (AOP (right), 0, FALSE));
7203       emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
7204       aopPut (AOP (result), "a", 0);
7205       aopPut (AOP (result), "e", 1);
7206     }
7207   else if (size == 4 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
7208     {
7209       /* Special case - simple memcpy */
7210       aopGet (AOP (right), LSB, FALSE);
7211       emit2 ("ld d,h");
7212       emit2 ("ld e,l");
7213       aopGet (AOP (result), LSB, FALSE);
7214
7215       while (size--)
7216         {
7217           emit2 ("ld a,(de)");
7218           /* Peephole will optimise this. */
7219           emit2 ("ld (hl),a");
7220
7221           if (size != 0)
7222             {
7223               emit2 ("inc hl");
7224               emit2 ("inc de");
7225             }
7226         }
7227       spillPair (PAIR_HL);
7228     }
7229   else
7230     {
7231       while (size--)
7232         {
7233           /* PENDING: do this check better */
7234           if (IS_GB && requiresHL (AOP (right)) && requiresHL (AOP (result)))
7235             {
7236               _moveA (aopGet (AOP (right), offset, FALSE));
7237               aopPut (AOP (result), "a", offset);
7238             }
7239           else
7240             aopPut (AOP (result),
7241                     aopGet (AOP (right), offset, FALSE),
7242                     offset);
7243           offset++;
7244         }
7245     }
7246
7247 release:
7248   freeAsmop (right, NULL, ic);
7249   freeAsmop (result, NULL, ic);
7250 }
7251
7252 /*-----------------------------------------------------------------*/
7253 /* genJumpTab - genrates code for jump table                       */
7254 /*-----------------------------------------------------------------*/
7255 static void
7256 genJumpTab (iCode * ic)
7257 {
7258   symbol *jtab;
7259   const char *l;
7260
7261   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
7262   /* get the condition into accumulator */
7263   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
7264   if (!IS_GB)
7265     emit2 ("push de");
7266   emit2 ("ld e,%s", l);
7267   emit2 ("ld d,!zero");
7268   jtab = newiTempLabel (NULL);
7269   spillCached ();
7270   emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
7271   emit2 ("add hl,de");
7272   emit2 ("add hl,de");
7273   emit2 ("add hl,de");
7274   freeAsmop (IC_JTCOND (ic), NULL, ic);
7275   if (!IS_GB)
7276     emit2 ("pop de");
7277   emit2 ("jp !*hl");
7278   emitLabel (jtab->key + 100);
7279   /* now generate the jump labels */
7280   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7281        jtab = setNextItem (IC_JTLABELS (ic)))
7282     emit2 ("jp !tlabel", jtab->key + 100);
7283 }
7284
7285 /*-----------------------------------------------------------------*/
7286 /* genCast - gen code for casting                                  */
7287 /*-----------------------------------------------------------------*/
7288 static void
7289 genCast (iCode * ic)
7290 {
7291   operand *result = IC_RESULT (ic);
7292   sym_link *rtype = operandType (IC_RIGHT (ic));
7293   operand *right = IC_RIGHT (ic);
7294   int size, offset;
7295
7296   /* if they are equivalent then do nothing */
7297   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7298     return;
7299
7300   aopOp (right, ic, FALSE, FALSE);
7301   aopOp (result, ic, FALSE, FALSE);
7302
7303   /* if the result is a bit */
7304   if (AOP_TYPE (result) == AOP_CRY)
7305     {
7306       wassertl (0, "Tried to cast to a bit");
7307     }
7308
7309   /* if they are the same size : or less */
7310   if (AOP_SIZE (result) <= AOP_SIZE (right))
7311     {
7312
7313       /* if they are in the same place */
7314       if (sameRegs (AOP (right), AOP (result)))
7315         goto release;
7316
7317       /* if they in different places then copy */
7318       size = AOP_SIZE (result);
7319       offset = 0;
7320       while (size--)
7321         {
7322           aopPut (AOP (result),
7323                   aopGet (AOP (right), offset, FALSE),
7324                   offset);
7325           offset++;
7326         }
7327       goto release;
7328     }
7329
7330   /* So we now know that the size of destination is greater
7331      than the size of the source */
7332   /* we move to result for the size of source */
7333   size = AOP_SIZE (right);
7334   offset = 0;
7335   while (size--)
7336     {
7337       aopPut (AOP (result),
7338               aopGet (AOP (right), offset, FALSE),
7339               offset);
7340       offset++;
7341     }
7342
7343   /* now depending on the sign of the destination */
7344   size = AOP_SIZE (result) - AOP_SIZE (right);
7345   /* Unsigned or not an integral type - right fill with zeros */
7346   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7347     {
7348       while (size--)
7349         aopPut (AOP (result), "!zero", offset++);
7350     }
7351   else
7352     {
7353       /* we need to extend the sign :{ */
7354         const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
7355                         FALSE);
7356       _moveA (l);
7357       emit2 ("rla ");
7358       emit2 ("sbc a,a");
7359       while (size--)
7360         aopPut (AOP (result), "a", offset++);
7361     }
7362
7363 release:
7364   freeAsmop (right, NULL, ic);
7365   freeAsmop (result, NULL, ic);
7366 }
7367
7368 /*-----------------------------------------------------------------*/
7369 /* genReceive - generate code for a receive iCode                  */
7370 /*-----------------------------------------------------------------*/
7371 static void
7372 genReceive (iCode * ic)
7373 {
7374   if (isOperandInFarSpace (IC_RESULT (ic)) &&
7375       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
7376        IS_TRUE_SYMOP (IC_RESULT (ic))))
7377     {
7378       wassert (0);
7379     }
7380   else
7381     {
7382         // PENDING: HACK
7383         int size;
7384         int i;
7385
7386         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
7387         size = AOP_SIZE(IC_RESULT(ic));
7388
7389         for (i = 0; i < size; i++) {
7390             aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
7391         }
7392     }
7393
7394   freeAsmop (IC_RESULT (ic), NULL, ic);
7395 }
7396
7397 /*-----------------------------------------------------------------*/
7398 /* genDummyRead - generate code for dummy read of volatiles        */
7399 /*-----------------------------------------------------------------*/
7400 static void
7401 genDummyRead (iCode * ic)
7402 {
7403   operand *op;
7404   int size, offset;
7405
7406   op = IC_RIGHT (ic);
7407   if (op && IS_SYMOP (op))
7408     {
7409       aopOp (op, ic, FALSE, FALSE);
7410
7411       /* general case */
7412       size = AOP_SIZE (op);
7413       offset = 0;
7414
7415       while (size--)
7416         {
7417           _moveA (aopGet (AOP (op), offset, FALSE));
7418           offset++;
7419         }
7420
7421       freeAsmop (op, NULL, ic);
7422     }
7423
7424   op = IC_LEFT (ic);
7425   if (op && IS_SYMOP (op))
7426     {
7427       aopOp (op, ic, FALSE, FALSE);
7428
7429       /* general case */
7430       size = AOP_SIZE (op);
7431       offset = 0;
7432
7433       while (size--)
7434         {
7435           _moveA (aopGet (AOP (op), offset, FALSE));
7436           offset++;
7437         }
7438
7439       freeAsmop (op, NULL, ic);
7440     }
7441 }
7442
7443 /*-----------------------------------------------------------------*/
7444 /* genCritical - generate code for start of a critical sequence    */
7445 /*-----------------------------------------------------------------*/
7446 static void
7447 genCritical (iCode *ic)
7448 {
7449   symbol *tlbl = newiTempLabel (NULL);
7450
7451   if (IS_GB)
7452     {
7453       emit2 ("!di");
7454     }
7455   else if (IC_RESULT (ic))
7456     {
7457       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
7458       aopPut (AOP (IC_RESULT (ic)), "!zero", 0);
7459       //get interrupt enable flag IFF2 into P/O
7460       emit2 ("ld a,i");
7461       //disable interrupt
7462       emit2 ("!di");
7463       //parity odd <==> P/O=0 <==> interrupt enable flag IFF2=0
7464       emit2 ("jp po,!tlabel", tlbl->key + 100);
7465       aopPut (AOP (IC_RESULT (ic)), "!one", 0);
7466       emit2 ("!tlabeldef", (tlbl->key + 100));
7467       freeAsmop (IC_RESULT (ic), NULL, ic);
7468     }
7469   else
7470     {
7471       //get interrupt enable flag IFF2 into P/O
7472       emit2 ("ld a,i");
7473       //disable interrupt
7474       emit2 ("!di");
7475       //save P/O flag
7476       emit2 ("push af");
7477     }
7478 }
7479
7480 /*-----------------------------------------------------------------*/
7481 /* genEndCritical - generate code for end of a critical sequence   */
7482 /*-----------------------------------------------------------------*/
7483 static void
7484 genEndCritical (iCode *ic)
7485 {
7486   symbol *tlbl = newiTempLabel (NULL);
7487
7488   if (IS_GB)
7489     {
7490       emit2 ("!ei");
7491     }
7492   else if (IC_RIGHT (ic))
7493     {
7494       aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
7495       _toBoolean (IC_RIGHT (ic));
7496       //don't enable interrupts if they were off before
7497       emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
7498       emit2 ("!ei");
7499       emitLabel (tlbl->key + 100);
7500       freeAsmop (IC_RIGHT (ic), NULL, ic);
7501     }
7502   else
7503     {
7504       //restore P/O flag
7505       emit2 ("pop af");
7506       //parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==>
7507       //don't enable interrupts as they were off before
7508       emit2 ("jp po,!tlabel", tlbl->key + 100);
7509       emit2 ("!ei");
7510       emit2 ("!tlabeldef", (tlbl->key + 100));
7511     }
7512 }
7513
7514 enum
7515   {
7516     /** Maximum number of bytes to emit per line. */
7517     DBEMIT_MAX_RUN = 8
7518   };
7519
7520 /** Context for the byte output chunker. */
7521 typedef struct
7522 {
7523   unsigned char buffer[DBEMIT_MAX_RUN];
7524   int pos;
7525 } DBEMITCTX;
7526
7527
7528 /** Flushes a byte chunker by writing out all in the buffer and
7529     reseting.
7530 */
7531 static void
7532 _dbFlush(DBEMITCTX *self)
7533 {
7534   char line[256];
7535
7536   if (self->pos > 0)
7537     {
7538       int i;
7539       sprintf(line, ".db 0x%02X", self->buffer[0]);
7540
7541       for (i = 1; i < self->pos; i++)
7542         {
7543           sprintf(line + strlen(line), ", 0x%02X", self->buffer[i]);
7544         }
7545       emit2(line);
7546     }
7547   self->pos = 0;
7548 }
7549
7550 /** Write out another byte, buffering until a decent line is
7551     generated.
7552 */
7553 static void
7554 _dbEmit(DBEMITCTX *self, int c)
7555 {
7556   if (self->pos == DBEMIT_MAX_RUN)
7557     {
7558       _dbFlush(self);
7559     }
7560   self->buffer[self->pos++] = c;
7561 }
7562
7563 /** Context for a simple run length encoder. */
7564 typedef struct
7565 {
7566   unsigned last;
7567   unsigned char buffer[128];
7568   int pos;
7569   /** runLen may be equivalent to pos. */
7570   int runLen;
7571 } RLECTX;
7572
7573 enum
7574   {
7575     RLE_CHANGE_COST = 4,
7576     RLE_MAX_BLOCK = 127
7577   };
7578
7579 /** Flush the buffer of a run length encoder by writing out the run or
7580     data that it currently contains.
7581 */
7582 static void
7583 _rleCommit(RLECTX *self)
7584 {
7585   int i;
7586   if (self->pos != 0)
7587     {
7588       DBEMITCTX db;
7589       memset(&db, 0, sizeof(db));
7590
7591       emit2(".db %u", self->pos);
7592
7593       for (i = 0; i < self->pos; i++)
7594         {
7595           _dbEmit(&db, self->buffer[i]);
7596         }
7597       _dbFlush(&db);
7598     }
7599   /* Reset */
7600   self->pos = 0;
7601 }
7602
7603 /* Encoder design:
7604    Can get either a run or a block of random stuff.
7605    Only want to change state if a good run comes in or a run ends.
7606    Detecting run end is easy.
7607    Initial state?
7608
7609    Say initial state is in run, len zero, last zero.  Then if you get a
7610    few zeros then something else then a short run will be output.
7611    Seems OK.  While in run mode, keep counting.  While in random mode,
7612    keep a count of the run.  If run hits margin, output all up to run,
7613    restart, enter run mode.
7614 */
7615
7616 /** Add another byte into the run length encoder, flushing as
7617     required.  The run length encoder uses the Amiga IFF style, where
7618     a block is prefixed by its run length.  A positive length means
7619     the next n bytes pass straight through.  A negative length means
7620     that the next byte is repeated -n times.  A zero terminates the
7621     chunks.
7622 */
7623 static void
7624 _rleAppend(RLECTX *self, unsigned c)
7625 {
7626   int i;
7627
7628   if (c != self->last)
7629     {
7630       /* The run has stopped.  See if it is worthwhile writing it out
7631          as a run.  Note that the random data comes in as runs of
7632          length one.
7633       */
7634       if (self->runLen > RLE_CHANGE_COST)
7635         {
7636           /* Yes, worthwhile. */
7637           /* Commit whatever was in the buffer. */
7638           _rleCommit(self);
7639           emit2("!db !immed-%u,!immedbyte", self->runLen, self->last);
7640         }
7641       else
7642         {
7643           /* Not worthwhile.  Append to the end of the random list. */
7644           for (i = 0; i < self->runLen; i++)
7645             {
7646               if (self->pos >= RLE_MAX_BLOCK)
7647                 {
7648                   /* Commit. */
7649                   _rleCommit(self);
7650                 }
7651               self->buffer[self->pos++] = self->last;
7652             }
7653         }
7654       self->runLen = 1;
7655       self->last = c;
7656     }
7657   else
7658     {
7659       if (self->runLen >= RLE_MAX_BLOCK)
7660         {
7661           /* Commit whatever was in the buffer. */
7662           _rleCommit(self);
7663
7664           emit2 ("!db !immed-%u,!immedbyte", self->runLen, self->last);
7665           self->runLen = 0;
7666         }
7667       self->runLen++;
7668     }
7669 }
7670
7671 static void
7672 _rleFlush(RLECTX *self)
7673 {
7674   _rleAppend(self, -1);
7675   _rleCommit(self);
7676   self->pos = 0;
7677   self->last = 0;
7678   self->runLen = 0;
7679 }
7680
7681 /** genArrayInit - Special code for initialising an array with constant
7682    data.
7683 */
7684 static void
7685 genArrayInit (iCode * ic)
7686 {
7687   literalList *iLoop;
7688   int         ix;
7689   int         elementSize = 0, eIndex, i;
7690   unsigned    val, lastVal;
7691   sym_link    *type;
7692   RLECTX      rle;
7693
7694   memset(&rle, 0, sizeof(rle));
7695
7696   aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
7697
7698   _saveRegsForCall(ic, 0);
7699
7700   fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
7701   emit2 ("call __initrleblock");
7702
7703   type = operandType(IC_LEFT(ic));
7704
7705   if (type && type->next)
7706     {
7707       if (IS_SPEC(type->next) || IS_PTR(type->next))
7708         {
7709           elementSize = getSize(type->next);
7710         }
7711       else if (IS_ARRAY(type->next) && type->next->next)
7712         {
7713           elementSize = getSize(type->next->next);
7714         }
7715       else
7716         {
7717           printTypeChainRaw (type, NULL);
7718           wassertl (0, "Can't determine element size in genArrayInit.");
7719         }
7720     }
7721   else
7722     {
7723       wassertl (0, "Can't determine element size in genArrayInit.");
7724     }
7725
7726   wassertl ((elementSize > 0) && (elementSize <= 4), "Illegal element size in genArrayInit.");
7727
7728   iLoop = IC_ARRAYILIST(ic);
7729   lastVal = (unsigned)-1;
7730
7731   /* Feed all the bytes into the run length encoder which will handle
7732      the actual output.
7733      This works well for mixed char data, and for random int and long
7734      data.
7735   */
7736   while (iLoop)
7737     {
7738       ix = iLoop->count;
7739
7740       for (i = 0; i < ix; i++)
7741         {
7742           for (eIndex = 0; eIndex < elementSize; eIndex++)
7743             {
7744               val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
7745               _rleAppend(&rle, val);
7746             }
7747         }
7748
7749       iLoop = iLoop->next;
7750     }
7751
7752   _rleFlush(&rle);
7753   /* Mark the end of the run. */
7754   emit2(".db 0");
7755
7756   _restoreRegsAfterCall();
7757
7758   spillCached ();
7759
7760   freeAsmop (IC_LEFT(ic), NULL, ic);
7761 }
7762
7763 static void
7764 _swap (PAIR_ID one, PAIR_ID two)
7765 {
7766   if ((one == PAIR_DE && two == PAIR_HL) || (one == PAIR_HL && two == PAIR_DE))
7767     {
7768       emit2 ("ex de,hl");
7769     }
7770   else
7771     {
7772       emit2 ("ld a,%s", _pairs[one].l);
7773       emit2 ("ld %s,%s", _pairs[one].l, _pairs[two].l);
7774       emit2 ("ld %s,a", _pairs[two].l);
7775       emit2 ("ld a,%s", _pairs[one].h);
7776       emit2 ("ld %s,%s", _pairs[one].h, _pairs[two].h);
7777       emit2 ("ld %s,a", _pairs[two].h);
7778     }
7779 }
7780
7781 /* The problem is that we may have all three pairs used and they may
7782    be needed in a different order.
7783
7784    Note: Have ex de,hl
7785
7786    Combinations:
7787      hl = hl            => unity, fine
7788      bc = bc
7789      de = de
7790
7791      hl = hl            hl = hl, swap de <=> bc
7792      bc = de
7793      de = bc
7794
7795      hl = bc            Worst case
7796      bc = de
7797      de = hl
7798
7799      hl = bc            de = de, swap bc <=> hl
7800      bc = hl
7801      de = de
7802
7803      hl = de            Worst case
7804      bc = hl
7805      de = bc
7806
7807      hl = de            bc = bc, swap hl <=> de
7808      bc = bc
7809      de = hl
7810
7811    Break it down into:
7812     * Any pair = pair are done last
7813     * Any pair = iTemp are done last
7814     * Any swaps can be done any time
7815
7816    A worst case:
7817     push p1
7818     p1 = p2
7819     p2 = p3
7820     pop  p3
7821
7822    So how do we detect the cases?
7823    How about a 3x3 matrix?
7824         source
7825    dest x x x x
7826         x x x x
7827         x x x x (Fourth for iTemp/other)
7828
7829    First determin which mode to use by counting the number of unity and
7830    iTemp assigns.
7831      Three - any order
7832      Two - Assign the pair first, then the rest
7833      One - Swap the two, then the rest
7834      Zero - Worst case.
7835 */
7836 static void
7837 setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
7838 {
7839   PAIR_ID ids[NUM_PAIRS][NUM_PAIRS];
7840   PAIR_ID dest[3] = {
7841     PAIR_BC, PAIR_HL, PAIR_DE
7842   };
7843   int i, j, nunity = 0;
7844   memset (ids, PAIR_INVALID, sizeof (ids));
7845
7846   /* Sanity checks */
7847   wassert (nparams == 3);
7848
7849   /* First save everything that needs to be saved. */
7850   _saveRegsForCall (ic, 0);
7851
7852   /* Loading HL first means that DE is always fine. */
7853   for (i = 0; i < nparams; i++)
7854     {
7855       aopOp (pparams[i], ic, FALSE, FALSE);
7856       ids[dest[i]][getPairId (AOP (pparams[i]))] = TRUE;
7857     }
7858
7859   /* Count the number of unity or iTemp assigns. */
7860   for (i = 0; i < 3; i++)
7861     {
7862       if (ids[dest[i]][dest[i]] == TRUE || ids[dest[i]][PAIR_INVALID] == TRUE)
7863         {
7864           nunity++;
7865         }
7866     }
7867
7868   if (nunity == 3)
7869     {
7870       /* Any order, fall through. */
7871     }
7872   else if (nunity == 2)
7873     {
7874       /* One is assigned.  Pull it out and assign. */
7875       for (i = 0; i < 3; i++)
7876         {
7877           for (j = 0; j < NUM_PAIRS; j++)
7878             {
7879               if (ids[dest[i]][j] == TRUE)
7880                 {
7881                   /* Found it.  See if it's the right one. */
7882                   if (j == PAIR_INVALID || j == dest[i])
7883                     {
7884                       /* Keep looking. */
7885                     }
7886                   else
7887                     {
7888                       fetchPair(dest[i], AOP (pparams[i]));
7889                       goto done;
7890                     }
7891                 }
7892             }
7893         }
7894     }
7895   else if (nunity == 1)
7896     {
7897       /* Find the pairs to swap. */
7898       for (i = 0; i < 3; i++)
7899         {
7900           for (j = 0; j < NUM_PAIRS; j++)
7901             {
7902               if (ids[dest[i]][j] == TRUE)
7903                 {
7904                   if (j == PAIR_INVALID || j == dest[i])
7905                     {
7906                       /* Keep looking. */
7907                     }
7908                   else
7909                     {
7910                       _swap (j, dest[i]);
7911                       goto done;
7912                     }
7913                 }
7914             }
7915         }
7916     }
7917   else
7918     {
7919       int next = getPairId (AOP (pparams[0]));
7920       emit2 ("push %s", _pairs[next].name);
7921
7922       if (next == dest[1])
7923         {
7924           fetchPair (dest[1], AOP (pparams[1]));
7925           fetchPair (dest[2], AOP (pparams[2]));
7926         }
7927       else
7928         {
7929           fetchPair (dest[2], AOP (pparams[2]));
7930           fetchPair (dest[1], AOP (pparams[1]));
7931         }
7932       emit2 ("pop %s", _pairs[dest[0]].name);
7933     }
7934  done:
7935   /* Finally pull out all of the iTemps */
7936   for (i = 0; i < 3; i++)
7937     {
7938       if (ids[dest[i]][PAIR_INVALID] == 1)
7939         {
7940           fetchPair (dest[i], AOP (pparams[i]));
7941         }
7942     }
7943 }
7944
7945 static void
7946 genBuiltInStrcpy (iCode *ic, int nParams, operand **pparams)
7947 {
7948   operand *from, *to;
7949   symbol *label;
7950   bool deInUse;
7951
7952   wassertl (nParams == 2, "Built-in strcpy must have two parameters");
7953   to = pparams[0];
7954   from = pparams[1];
7955
7956   deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
7957
7958   setupForBuiltin3 (ic, nParams, pparams);
7959
7960   label = newiTempLabel(NULL);
7961
7962   emitLabel (label->key);
7963   emit2 ("ld a,(hl)");
7964   emit2 ("ldi");
7965   emit2 ("or a");
7966   emit2 ("!shortjp nz,!tlabel ; 1", label->key);
7967
7968   freeAsmop (from, NULL, ic->next);
7969   freeAsmop (to, NULL, ic);
7970 }
7971
7972 static void
7973 genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams)
7974 {
7975   operand *from, *to, *count;
7976   bool deInUse;
7977
7978   wassertl (nParams == 3, "Built-in memcpy must have two parameters");
7979   to = pparams[2];
7980   from = pparams[1];
7981   count = pparams[0];
7982
7983   deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
7984
7985   setupForBuiltin3 (ic, nParams, pparams);
7986
7987   emit2 ("ldir");
7988
7989   freeAsmop (count, NULL, ic->next->next);
7990   freeAsmop (from, NULL, ic);
7991
7992   _restoreRegsAfterCall();
7993
7994   /* if we need assign a result value */
7995   if ((IS_ITEMP (IC_RESULT (ic)) &&
7996        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
7997         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
7998       IS_TRUE_SYMOP (IC_RESULT (ic)))
7999     {
8000       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8001       movLeft2ResultLong (to, 0, IC_RESULT (ic), 0, 0, 2);
8002       freeAsmop (IC_RESULT (ic), NULL, ic);
8003     }
8004
8005   freeAsmop (to, NULL, ic->next);
8006 }
8007
8008 /*-----------------------------------------------------------------*/
8009 /* genBuiltIn - calls the appropriate function to  generating code */
8010 /* for a built in function                                         */
8011 /*-----------------------------------------------------------------*/
8012 static void genBuiltIn (iCode *ic)
8013 {
8014     operand *bi_parms[MAX_BUILTIN_ARGS];
8015     int nbi_parms;
8016     iCode *bi_iCode;
8017     symbol *bif;
8018
8019     /* get all the arguments for a built in function */
8020     bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
8021
8022     /* which function is it */
8023     bif = OP_SYMBOL(IC_LEFT(bi_iCode));
8024
8025     if (strcmp(bif->name,"__builtin_strcpy")==0)
8026       {
8027         genBuiltInStrcpy(bi_iCode, nbi_parms, bi_parms);
8028       }
8029     else if (strcmp(bif->name,"__builtin_memcpy")==0)
8030       {
8031         genBuiltInMemcpy(bi_iCode, nbi_parms, bi_parms);
8032       }
8033     else
8034       {
8035         wassertl (0, "Unknown builtin function encountered");
8036       }
8037 }
8038
8039 /*-----------------------------------------------------------------*/
8040 /* genZ80Code - generate code for Z80 based controllers            */
8041 /*-----------------------------------------------------------------*/
8042 void
8043 genZ80Code (iCode * lic)
8044 {
8045   iCode *ic;
8046   int cln = 0;
8047
8048   /* Hack */
8049   if (IS_GB)
8050     {
8051       _fReturn = _gbz80_return;
8052       _fTmp = _gbz80_return;
8053     }
8054   else
8055     {
8056       _fReturn = _z80_return;
8057       _fTmp = _z80_return;
8058     }
8059
8060   _G.lines.head = _G.lines.current = NULL;
8061
8062   /* if debug information required */
8063   if (options.debug && currFunc)
8064     {
8065       debugFile->writeFunction (currFunc, lic);
8066     }
8067
8068   for (ic = lic; ic; ic = ic->next)
8069     {
8070       _G.current_iCode = ic;
8071
8072       if (ic->lineno && cln != ic->lineno)
8073         {
8074           if (options.debug)
8075             {
8076               debugFile->writeCLine (ic);
8077             }
8078           if (!options.noCcodeInAsm)
8079             {
8080               emit2 (";%s:%d: %s", ic->filename, ic->lineno,
8081                      printCLine(ic->filename, ic->lineno));
8082             }
8083           cln = ic->lineno;
8084         }
8085       if (options.iCodeInAsm)
8086         {
8087           emit2 (";ic:%d: %s", ic->key, printILine(ic));
8088         }
8089       /* if the result is marked as
8090          spilt and rematerializable or code for
8091          this has already been generated then
8092          do nothing */
8093       if (resultRemat (ic) || ic->generated)
8094         continue;
8095
8096       /* depending on the operation */
8097       switch (ic->op)
8098         {
8099         case '!':
8100           emitDebug ("; genNot");
8101           genNot (ic);
8102           break;
8103
8104         case '~':
8105           emitDebug ("; genCpl");
8106           genCpl (ic);
8107           break;
8108
8109         case UNARYMINUS:
8110           emitDebug ("; genUminus");
8111           genUminus (ic);
8112           break;
8113
8114         case IPUSH:
8115           emitDebug ("; genIpush");
8116           genIpush (ic);
8117           break;
8118
8119         case IPOP:
8120           /* IPOP happens only when trying to restore a
8121              spilt live range, if there is an ifx statement
8122              following this pop then the if statement might
8123              be using some of the registers being popped which
8124              would destory the contents of the register so
8125              we need to check for this condition and handle it */
8126           if (ic->next &&
8127               ic->next->op == IFX &&
8128               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8129             {
8130               emitDebug ("; genIfx");
8131               genIfx (ic->next, ic);
8132             }
8133           else
8134             {
8135               emitDebug ("; genIpop");
8136               genIpop (ic);
8137             }
8138           break;
8139
8140         case CALL:
8141           emitDebug ("; genCall");
8142           genCall (ic);
8143           break;
8144
8145         case PCALL:
8146           emitDebug ("; genPcall");
8147           genPcall (ic);
8148           break;
8149
8150         case FUNCTION:
8151           emitDebug ("; genFunction");
8152           genFunction (ic);
8153           break;
8154
8155         case ENDFUNCTION:
8156           emitDebug ("; genEndFunction");
8157           genEndFunction (ic);
8158           break;
8159
8160         case RETURN:
8161           emitDebug ("; genRet");
8162           genRet (ic);
8163           break;
8164
8165         case LABEL:
8166           emitDebug ("; genLabel");
8167           genLabel (ic);
8168           break;
8169
8170         case GOTO:
8171           emitDebug ("; genGoto");
8172           genGoto (ic);
8173           break;
8174
8175         case '+':
8176           emitDebug ("; genPlus");
8177           genPlus (ic);
8178           break;
8179
8180         case '-':
8181           emitDebug ("; genMinus");
8182           genMinus (ic);
8183           break;
8184
8185         case '*':
8186           emitDebug ("; genMult");
8187           genMult (ic);
8188           break;
8189
8190         case '/':
8191           emitDebug ("; genDiv");
8192           genDiv (ic);
8193           break;
8194
8195         case '%':
8196           emitDebug ("; genMod");
8197           genMod (ic);
8198           break;
8199
8200         case '>':
8201           emitDebug ("; genCmpGt");
8202           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8203           break;
8204
8205         case '<':
8206           emitDebug ("; genCmpLt");
8207           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8208           break;
8209
8210         case LE_OP:
8211         case GE_OP:
8212         case NE_OP:
8213
8214           /* note these two are xlated by algebraic equivalence
8215              during parsing SDCC.y */
8216           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8217                   "got '>=' or '<=' shouldn't have come here");
8218           break;
8219
8220         case EQ_OP:
8221           emitDebug ("; genCmpEq");
8222           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8223           break;
8224
8225         case AND_OP:
8226           emitDebug ("; genAndOp");
8227           genAndOp (ic);
8228           break;
8229
8230         case OR_OP:
8231           emitDebug ("; genOrOp");
8232           genOrOp (ic);
8233           break;
8234
8235         case '^':
8236           emitDebug ("; genXor");
8237           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8238           break;
8239
8240         case '|':
8241           emitDebug ("; genOr");
8242           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8243           break;
8244
8245         case BITWISEAND:
8246           emitDebug ("; genAnd");
8247           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8248           break;
8249
8250         case INLINEASM:
8251           emitDebug ("; genInline");
8252           genInline (ic);
8253           break;
8254
8255         case RRC:
8256           emitDebug ("; genRRC");
8257           genRRC (ic);
8258           break;
8259
8260         case RLC:
8261           emitDebug ("; genRLC");
8262           genRLC (ic);
8263           break;
8264
8265         case GETHBIT:
8266           emitDebug ("; genGetHBIT");
8267           genGetHbit (ic);
8268           break;
8269
8270         case LEFT_OP:
8271           emitDebug ("; genLeftShift");
8272           genLeftShift (ic);
8273           break;
8274
8275         case RIGHT_OP:
8276           emitDebug ("; genRightShift");
8277           genRightShift (ic);
8278           break;
8279
8280         case GET_VALUE_AT_ADDRESS:
8281           emitDebug ("; genPointerGet");
8282           genPointerGet (ic);
8283           break;
8284
8285         case '=':
8286
8287           if (POINTER_SET (ic))
8288             {
8289               emitDebug ("; genAssign (pointer)");
8290               genPointerSet (ic);
8291             }
8292           else
8293             {
8294               emitDebug ("; genAssign");
8295               genAssign (ic);
8296             }
8297           break;
8298
8299         case IFX:
8300           emitDebug ("; genIfx");
8301           genIfx (ic, NULL);
8302           break;
8303
8304         case ADDRESS_OF:
8305           emitDebug ("; genAddrOf");
8306           genAddrOf (ic);
8307           break;
8308
8309         case JUMPTABLE:
8310           emitDebug ("; genJumpTab");
8311           genJumpTab (ic);
8312           break;
8313
8314         case CAST:
8315           emitDebug ("; genCast");
8316           genCast (ic);
8317           break;
8318
8319         case RECEIVE:
8320           emitDebug ("; genReceive");
8321           genReceive (ic);
8322           break;
8323
8324         case SEND:
8325           if (ic->builtinSEND)
8326             {
8327               emitDebug ("; genBuiltIn");
8328               genBuiltIn(ic);
8329             }
8330           else
8331             {
8332               emitDebug ("; addSet");
8333               addSet (&_G.sendSet, ic);
8334             }
8335           break;
8336
8337         case ARRAYINIT:
8338           emitDebug ("; genArrayInit");
8339           genArrayInit(ic);
8340           break;
8341
8342         case DUMMY_READ_VOLATILE:
8343           emitDebug ("; genDummyRead");
8344           genDummyRead (ic);
8345           break;
8346
8347         case CRITICAL:
8348           emitDebug ("; genCritical");
8349           genCritical (ic);
8350           break;
8351
8352         case ENDCRITICAL:
8353           emitDebug ("; genEndCritical");
8354           genEndCritical (ic);
8355           break;
8356
8357         default:
8358           ic = ic;
8359         }
8360     }
8361
8362
8363   /* now we are ready to call the
8364      peep hole optimizer */
8365   if (!options.nopeep)
8366     peepHole (&_G.lines.head);
8367
8368   /* This is unfortunate */
8369   /* now do the actual printing */
8370   {
8371     FILE *fp = codeOutFile;
8372     if (isInHome () && codeOutFile == code->oFile)
8373       codeOutFile = home->oFile;
8374     printLine (_G.lines.head, codeOutFile);
8375     if (_G.flushStatics)
8376       {
8377         flushStatics ();
8378         _G.flushStatics = 0;
8379       }
8380     codeOutFile = fp;
8381   }
8382
8383   freeTrace(&_G.lines.trace);
8384   freeTrace(&_G.trace.aops);
8385 }
8386
8387 /*
8388   Attic
8389 static int
8390 _isPairUsed (iCode * ic, PAIR_ID pairId)
8391 {
8392   int ret = 0;
8393   switch (pairId)
8394     {
8395     case PAIR_DE:
8396       if (bitVectBitValue (ic->rMask, D_IDX))
8397         ret++;
8398       if (bitVectBitValue (ic->rMask, E_IDX))
8399         ret++;
8400       break;
8401     default:
8402       wassert (0);
8403     }
8404   return ret;
8405 }
8406
8407 static char *
8408 fetchLitSpecial (asmop * aop, bool negate, bool xor)
8409 {
8410   unsigned long v;
8411   value *val = aop->aopu.aop_lit;
8412
8413   wassert (aop->type == AOP_LIT);
8414   wassert (!IS_FLOAT (val->type));
8415
8416   v = (unsigned long) floatFromVal (val);
8417
8418   if (xor)
8419     v ^= 0x8000;
8420   if (negate)
8421     v = 0-v;
8422   v &= 0xFFFF;
8423
8424   tsprintf (buffer, sizeof(buffer), "!immedword", v);
8425   return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
8426 }
8427
8428
8429 */