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