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