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