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