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