Made linking support base areas and extra libraries. Begin tidy up of gen.c
[fw/sdcc] / src / z80 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - Z80 specific code generator.
3
4   Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
5             ticks dhry  size
6   Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
7   Improved WORD push                    22784 144 19AE
8   With label1 on                        22694 144 197E
9   With label2 on                        22743 144 198A
10   With label3 on                        22776 144 1999
11   With label4 on                        22776 144 1999
12   With all 'label' on                   22661 144 196F
13   With loopInvariant on                 20919 156 19AB
14   With loopInduction on                 Breaks    198B
15   With all working on                   20796 158 196C
16   Slightly better genCmp(signed)        20597 159 195B
17   Better reg packing, first peephole    20038 163 1873
18   With assign packing                   19281 165 1849
19   5/3/00                                17741 185 17B6
20   With reg params for mul and div       16234 202 162D
21
22   Michael Hope <michaelh@earthling.net> 2000
23   Based on the mcs51 generator -
24       Sandeep Dutta . sandeep.dutta@usa.net (1998)
25    and -  Jean-Louis VERN.jlvern@writeme.com (1999)
26
27   This program is free software; you can redistribute it and/or modify it
28   under the terms of the GNU General Public License as published by the
29   Free Software Foundation; either version 2, or (at your option) any
30   later version.
31
32   This program is distributed in the hope that it will be useful,
33   but WITHOUT ANY WARRANTY; without even the implied warranty of
34   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35   GNU General Public License for more details.
36
37
38   You should have received a copy of the GNU General Public License
39   along with this program; if not, write to the Free Software
40   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41
42   In other words, you are welcome to use, share and improve this program.
43   You are forbidden to forbid anyone else to use, share and improve
44   what you give them.   Help stamp out software-hoarding!
45
46 -------------------------------------------------------------------------*/
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <ctype.h>
52
53 #ifdef HAVE_SYS_ISA_DEFS_H
54 #include <sys/isa_defs.h>
55 #endif
56
57 #include "z80.h"
58 #include "SDCCglobl.h"
59 #include "SDCCpeeph.h"
60 #include "gen.h"
61 #include "SDCCglue.h"
62 #include "newalloc.h"
63
64 /* this is the down and dirty file with all kinds of kludgy & hacky
65    stuff. This is what it is all about CODE GENERATION for a specific MCU.
66    Some of the routines may be reusable, will have to see */
67
68 /* Z80 calling convention description.
69    Parameters are passed right to left.  As the stack grows downwards,
70    the parameters are arranged in left to right in memory.
71    Parameters may be passed in the HL and DE registers with one
72    parameter per pair.
73    PENDING: What if the parameter is a long?
74    Everything is caller saves. i.e. the caller must save any registers
75    that it wants to preserve over the call.
76    The return value is returned in DEHL.  DE is normally used as a
77    working register pair.  Caller saves allows it to be used for a
78    return value.
79    va args functions do not use register parameters.  All arguments
80    are passed on the stack.
81    IX is used as an index register to the top of the local variable
82    area.  ix-0 is the top most local variable.
83 */
84 static char *_z80_return[] =
85 {"l", "h", "e", "d"};
86 static char *_gbz80_return[] =
87 {"e", "d", "l", "h"};
88 static char **_fReturn;
89 static char **_fTmp;
90
91 /* PENDING: messy */
92 static char zero[20];
93
94 short rbank = -1;
95 short inLine = 0;
96 short debugLine = 0;
97 short nregssaved = 0;
98 extern int ptrRegReq;
99 extern int nRegs;
100 extern FILE *codeOutFile;
101 set *sendSet = NULL;
102
103 typedef enum
104 {
105     PAIR_INVALID,
106     PAIR_AF,
107     PAIR_BC,
108     PAIR_DE,
109     PAIR_HL,
110     PAIR_IY,
111     PAIR_IX,
112     NUM_PAIRS
113 } PAIR_ID;
114
115 static struct
116 {
117     const char *name;
118     const char *l;
119     const char *h;
120 } _pairs[NUM_PAIRS] = {
121     {    "??", "?", "?" },
122     {    "af", "f", "a" },
123     {    "bc", "c", "b" },
124     {    "de", "e", "d" },
125     {    "hl", "l", "h" },
126     {    "iy", "iy.l?", "iy.h?" },
127     {    "ix", "ix.l?", "ix.h?" }
128 };
129
130 // PENDING
131 #define ACC_NAME        _pairs[PAIR_AF].h
132
133 #define RESULTONSTACK(x) \
134                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
135                          IC_RESULT(x)->aop->type == AOP_STK )
136
137 lineNode *lineHead = NULL;
138 lineNode *lineCurr = NULL;
139
140 static const unsigned char SLMask[] =
141 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
142 static const unsigned char SRMask[] =
143 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
144
145 #define LSB     0
146 #define MSB16   1
147 #define MSB24   2
148 #define MSB32   3
149
150 /* Stack frame:
151    IX+4   param0  LH
152    IX+2   ret LH
153    IX+0   ix  LH
154    IX-2   temp0 LH
155  */
156
157 static struct {
158     struct {
159         AOP_TYPE last_type;
160         const char *lit;
161         int offset;
162     }
163     pairs[NUM_PAIRS];
164     struct {
165         int last;
166         int pushed;
167         int param_offset;
168         int offset;
169         int pushed_bc;
170         int pushed_de;
171     } stack;
172     int frameId;
173     int receiveOffset;
174     bool flush_statics;
175     bool in_home;
176     const char *lastFunctionName;
177   }
178 _G;
179
180 static const char *aopGet (asmop * aop, int offset, bool bit16);
181
182 static void
183 _tidyUp (char *buf)
184 {
185   /* Clean up the line so that it is 'prettier' */
186   if (strchr (buf, ':'))
187     {
188       /* Is a label - cant do anything */
189       return;
190     }
191   /* Change the first (and probably only) ' ' to a tab so
192      everything lines up.
193    */
194   while (*buf)
195     {
196       if (*buf == ' ')
197         {
198           *buf = '\t';
199           return;
200         }
201       buf++;
202     }
203 }
204
205 static void
206 emit2 (const char *szFormat,...)
207 {
208   char buffer[256];
209   va_list ap;
210
211   va_start (ap, szFormat);
212
213   tvsprintf (buffer, szFormat, ap);
214
215   _tidyUp (buffer);
216   lineCurr = (lineCurr ?
217               connectLine (lineCurr, newLineNode (buffer)) :
218               (lineHead = newLineNode (buffer)));
219
220   lineCurr->isInline = inLine;
221   lineCurr->isDebug = debugLine;
222 }
223
224 /*-----------------------------------------------------------------*/
225 /* emitcode - writes the code into a file : for now it is simple    */
226 /*-----------------------------------------------------------------*/
227 void
228 emitcode (const char *inst, const char *fmt,...)
229 {
230   va_list ap;
231   char lb[INITIAL_INLINEASM];
232   char *lbp = lb;
233
234   va_start (ap, fmt);
235
236   if (*inst != '\0')
237     {
238       sprintf (lb, "%s\t", inst);
239       vsprintf (lb + (strlen (lb)), fmt, ap);
240     }
241   else
242     vsprintf (lb, fmt, ap);
243
244   while (isspace (*lbp))
245     lbp++;
246
247   if (lbp && *lbp)
248     lineCurr = (lineCurr ?
249                 connectLine (lineCurr, newLineNode (lb)) :
250                 (lineHead = newLineNode (lb)));
251   lineCurr->isInline = inLine;
252   lineCurr->isDebug = debugLine;
253   va_end (ap);
254 }
255
256 static void
257 _emitMove(const char *to, const char *from)
258 {
259     if (strcasecmp(to, from) != 0) {
260         emit2("ld %s,%s", to, from);
261     }
262     else {
263         // Optimise it out.
264         // Could leave this to the peephole, but sometimes the peephole is inhibited.
265     }
266 }
267
268 static void
269 _MoveA(const char *moveFrom)
270 {
271     // Let the peephole optimiser take care of redundent loads
272     _emitMove(ACC_NAME, moveFrom);
273 }
274
275 static void
276 _ClearCarry(void)
277 {
278     emit2("xor a,a");
279 }
280
281 const char *
282 getPairName (asmop * aop)
283 {
284   if (aop->type == AOP_REG)
285     {
286       switch (aop->aopu.aop_reg[0]->rIdx)
287         {
288         case C_IDX:
289           return "bc";
290           break;
291         case E_IDX:
292           return "de";
293           break;
294         case L_IDX:
295           return "hl";
296           break;
297         }
298     }
299   else if (aop->type == AOP_STR)
300     {
301       switch (*aop->aopu.aop_str[0])
302         {
303         case 'c':
304           return "bc";
305           break;
306         case 'e':
307           return "de";
308           break;
309         case 'l':
310           return "hl";
311           break;
312         }
313     }
314   wassert (0);
315   return NULL;
316 }
317
318 static PAIR_ID
319 getPairId (asmop * aop)
320 {
321   if (aop->size == 2)
322     {
323       if (aop->type == AOP_REG)
324         {
325           if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
326             {
327               return PAIR_BC;
328             }
329           if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
330             {
331               return PAIR_DE;
332             }
333           if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
334             {
335               return PAIR_HL;
336             }
337         }
338       if (aop->type == AOP_STR)
339         {
340           if (!strcmp (aop->aopu.aop_str[0], "c") && !strcmp (aop->aopu.aop_str[1], "b"))
341             {
342               return PAIR_BC;
343             }
344           if (!strcmp (aop->aopu.aop_str[0], "e") && !strcmp (aop->aopu.aop_str[1], "d"))
345             {
346               return PAIR_DE;
347             }
348           if (!strcmp (aop->aopu.aop_str[0], "l") && !strcmp (aop->aopu.aop_str[1], "h"))
349             {
350               return PAIR_HL;
351             }
352         }
353     }
354   return PAIR_INVALID;
355 }
356
357 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
358 bool
359 isPair (asmop * aop)
360 {
361   return (getPairId (aop) != PAIR_INVALID);
362 }
363
364 bool
365 isPtrPair (asmop * aop)
366 {
367   PAIR_ID pairId = getPairId (aop);
368   switch (pairId)
369     {
370     case PAIR_HL:
371     case PAIR_IY:
372     case PAIR_IX:
373       return TRUE;
374     default:
375       return FALSE;
376     }
377 }
378 /** Push a register pair onto the stack */
379 void
380 genPairPush (asmop * aop)
381 {
382   emitcode ("push", "%s", getPairName (aop));
383 }
384
385
386 /*-----------------------------------------------------------------*/
387 /* newAsmop - creates a new asmOp                                  */
388 /*-----------------------------------------------------------------*/
389 static asmop *
390 newAsmop (short type)
391 {
392   asmop *aop;
393
394   aop = Safe_calloc (1, sizeof (asmop));
395   aop->type = type;
396   return aop;
397 }
398
399 /*-----------------------------------------------------------------*/
400 /* aopForSym - for a true symbol                                   */
401 /*-----------------------------------------------------------------*/
402 static asmop *
403 aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
404 {
405   asmop *aop;
406   memmap *space;
407
408   wassert (ic);
409   wassert (sym);
410   wassert (sym->etype);
411
412   space = SPEC_OCLS (sym->etype);
413
414   /* if already has one */
415   if (sym->aop)
416     return sym->aop;
417
418   /* Assign depending on the storage class */
419   if (sym->onStack || sym->iaccess)
420     {
421       emitcode ("", "; AOP_STK for %s", sym->rname);
422       sym->aop = aop = newAsmop (AOP_STK);
423       aop->size = getSize (sym->type);
424       aop->aopu.aop_stk = sym->stack;
425       return aop;
426     }
427
428   /* special case for a function */
429   if (IS_FUNC (sym->type))
430     {
431       sym->aop = aop = newAsmop (AOP_IMMD);
432       aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
433       strcpy (aop->aopu.aop_immd, sym->rname);
434       aop->size = 2;
435       return aop;
436     }
437
438   if (IS_GB)
439     {
440       /* if it is in direct space */
441       if (IN_REGSP (space) && !requires_a)
442         {
443           sym->aop = aop = newAsmop (AOP_SFR);
444           aop->aopu.aop_dir = sym->rname;
445           aop->size = getSize (sym->type);
446           emitcode ("", "; AOP_SFR for %s", sym->rname);
447           return aop;
448         }
449     }
450
451   /* only remaining is far space */
452   /* in which case DPTR gets the address */
453   if (IS_GB)
454     {
455       emitcode ("", "; AOP_HL for %s", sym->rname);
456       sym->aop = aop = newAsmop (AOP_HL);
457     }
458   else
459     {
460       sym->aop = aop = newAsmop (AOP_IY);
461     }
462   aop->size = getSize (sym->type);
463   aop->aopu.aop_dir = sym->rname;
464
465   /* if it is in code space */
466   if (IN_CODESPACE (space))
467     aop->code = 1;
468
469   return aop;
470 }
471
472 /*-----------------------------------------------------------------*/
473 /* aopForRemat - rematerialzes an object                           */
474 /*-----------------------------------------------------------------*/
475 static asmop *
476 aopForRemat (symbol * sym)
477 {
478   char *s = buffer;
479   iCode *ic = sym->rematiCode;
480   asmop *aop = newAsmop (AOP_IMMD);
481
482   while (1)
483     {
484       /* if plus or minus print the right hand side */
485       if (ic->op == '+' || ic->op == '-')
486         {
487           /* PENDING: for re-target */
488           sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
489                    ic->op);
490           s += strlen (s);
491           ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
492           continue;
493         }
494       /* we reached the end */
495       sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
496       break;
497     }
498
499   aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
500   strcpy (aop->aopu.aop_immd, buffer);
501   return aop;
502 }
503
504 /*-----------------------------------------------------------------*/
505 /* regsInCommon - two operands have some registers in common       */
506 /*-----------------------------------------------------------------*/
507 bool
508 regsInCommon (operand * op1, operand * op2)
509 {
510   symbol *sym1, *sym2;
511   int i;
512
513   /* if they have registers in common */
514   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
515     return FALSE;
516
517   sym1 = OP_SYMBOL (op1);
518   sym2 = OP_SYMBOL (op2);
519
520   if (sym1->nRegs == 0 || sym2->nRegs == 0)
521     return FALSE;
522
523   for (i = 0; i < sym1->nRegs; i++)
524     {
525       int j;
526       if (!sym1->regs[i])
527         continue;
528
529       for (j = 0; j < sym2->nRegs; j++)
530         {
531           if (!sym2->regs[j])
532             continue;
533
534           if (sym2->regs[j] == sym1->regs[i])
535             return TRUE;
536         }
537     }
538
539   return FALSE;
540 }
541
542 /*-----------------------------------------------------------------*/
543 /* operandsEqu - equivalent                                        */
544 /*-----------------------------------------------------------------*/
545 bool
546 operandsEqu (operand * op1, operand * op2)
547 {
548   symbol *sym1, *sym2;
549
550   /* if they not symbols */
551   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
552     return FALSE;
553
554   sym1 = OP_SYMBOL (op1);
555   sym2 = OP_SYMBOL (op2);
556
557   /* if both are itemps & one is spilt
558      and the other is not then false */
559   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
560       sym1->isspilt != sym2->isspilt)
561     return FALSE;
562
563   /* if they are the same */
564   if (sym1 == sym2)
565     return 1;
566
567   if (strcmp (sym1->rname, sym2->rname) == 0)
568     return 2;
569
570
571   /* if left is a tmp & right is not */
572   if (IS_ITEMP (op1) &&
573       !IS_ITEMP (op2) &&
574       sym1->isspilt &&
575       (sym1->usl.spillLoc == sym2))
576     return 3;
577
578   if (IS_ITEMP (op2) &&
579       !IS_ITEMP (op1) &&
580       sym2->isspilt &&
581       sym1->level > 0 &&
582       (sym2->usl.spillLoc == sym1))
583     return 4;
584
585   return FALSE;
586 }
587
588 /*-----------------------------------------------------------------*/
589 /* sameRegs - two asmops have the same registers                   */
590 /*-----------------------------------------------------------------*/
591 bool
592 sameRegs (asmop * aop1, asmop * aop2)
593 {
594   int i;
595
596   if (aop1->type == AOP_SFR ||
597       aop2->type == AOP_SFR)
598     return FALSE;
599
600   if (aop1 == aop2)
601     return TRUE;
602
603   if (aop1->type != AOP_REG ||
604       aop2->type != AOP_REG)
605     return FALSE;
606
607   if (aop1->size != aop2->size)
608     return FALSE;
609
610   for (i = 0; i < aop1->size; i++)
611     if (aop1->aopu.aop_reg[i] !=
612         aop2->aopu.aop_reg[i])
613       return FALSE;
614
615   return TRUE;
616 }
617
618 /*-----------------------------------------------------------------*/
619 /* aopOp - allocates an asmop for an operand  :                    */
620 /*-----------------------------------------------------------------*/
621 static void
622 aopOp (operand * op, iCode * ic, bool result, bool requires_a)
623 {
624   asmop *aop;
625   symbol *sym;
626   int i;
627
628   if (!op)
629     return;
630
631   /* if this a literal */
632   if (IS_OP_LITERAL (op))
633     {
634       op->aop = aop = newAsmop (AOP_LIT);
635       aop->aopu.aop_lit = op->operand.valOperand;
636       aop->size = getSize (operandType (op));
637       return;
638     }
639
640   /* if already has a asmop then continue */
641   if (op->aop)
642     return;
643
644   /* if the underlying symbol has a aop */
645   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
646     {
647       op->aop = OP_SYMBOL (op)->aop;
648       return;
649     }
650
651   /* if this is a true symbol */
652   if (IS_TRUE_SYMOP (op))
653     {
654       op->aop = aopForSym (ic, OP_SYMBOL (op), result, requires_a);
655       return;
656     }
657
658   /* this is a temporary : this has
659      only four choices :
660      a) register
661      b) spillocation
662      c) rematerialize
663      d) conditional
664      e) can be a return use only */
665
666   sym = OP_SYMBOL (op);
667
668   /* if the type is a conditional */
669   if (sym->regType == REG_CND)
670     {
671       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
672       aop->size = 0;
673       return;
674     }
675
676   /* if it is spilt then two situations
677      a) is rematerialize
678      b) has a spill location */
679   if (sym->isspilt || sym->nRegs == 0)
680     {
681       /* rematerialize it NOW */
682       if (sym->remat)
683         {
684           sym->aop = op->aop = aop =
685             aopForRemat (sym);
686           aop->size = getSize (sym->type);
687           return;
688         }
689
690       if (sym->accuse)
691         {
692           int i;
693           if (sym->accuse == ACCUSE_A)
694             {
695               aop = op->aop = sym->aop = newAsmop (AOP_ACC);
696               aop->size = getSize (sym->type);
697               wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
698
699               aop->aopu.aop_str[i] = _pairs[PAIR_AF].h;
700             }
701           else if (sym->accuse == ACCUSE_HL)
702             {
703               wassert (!IS_GB);
704               aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
705               aop->size = getSize (sym->type);
706               wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL");
707               aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
708               aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
709             }
710           else 
711               {
712                   wassert (0);
713               }
714           return;
715         }
716
717       if (sym->ruonly)
718         {
719           int i;
720           aop = op->aop = sym->aop = newAsmop (AOP_STR);
721           aop->size = getSize (sym->type);
722           for (i = 0; i < 4; i++)
723             aop->aopu.aop_str[i] = _fReturn[i];
724           return;
725         }
726
727       /* else spill location  */
728       sym->aop = op->aop = aop =
729         aopForSym (ic, sym->usl.spillLoc, result, requires_a);
730       aop->size = getSize (sym->type);
731       return;
732     }
733
734   /* must be in a register */
735   sym->aop = op->aop = aop = newAsmop (AOP_REG);
736   aop->size = sym->nRegs;
737   for (i = 0; i < sym->nRegs; i++)
738     aop->aopu.aop_reg[i] = sym->regs[i];
739 }
740
741 /*-----------------------------------------------------------------*/
742 /* freeAsmop - free up the asmop given to an operand               */
743 /*----------------------------------------------------------------*/
744 static void
745 freeAsmop (operand * op, asmop * aaop, iCode * ic)
746 {
747   asmop *aop;
748
749   if (!op)
750     aop = aaop;
751   else
752     aop = op->aop;
753
754   if (!aop)
755     return;
756
757   if (aop->freed)
758     goto dealloc;
759
760   aop->freed = 1;
761
762 dealloc:
763   /* all other cases just dealloc */
764   if (op)
765     {
766       op->aop = NULL;
767       if (IS_SYMOP (op))
768         {
769           OP_SYMBOL (op)->aop = NULL;
770           /* if the symbol has a spill */
771           if (SPIL_LOC (op))
772             SPIL_LOC (op)->aop = NULL;
773         }
774     }
775 }
776
777 bool
778 isLitWord (asmop * aop)
779 {
780   /*    if (aop->size != 2)
781      return FALSE; */
782   switch (aop->type)
783     {
784     case AOP_IMMD:
785     case AOP_LIT:
786       return TRUE;
787     default:
788       return FALSE;
789     }
790 }
791
792 char *
793 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
794 {
795   char *s = buffer;
796   char *rs;
797
798 #if 0
799   if (aop->size != 2 && aop->type != AOP_HL)
800     return NULL;
801 #endif
802   /* depending on type */
803   switch (aop->type)
804     {
805     case AOP_HL:
806     case AOP_IY:
807     case AOP_IMMD:
808       /* PENDING: for re-target */
809       if (with_hash)
810         tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
811       else
812         tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
813       rs = Safe_calloc (1, strlen (s) + 1);
814       strcpy (rs, s);
815       return rs;
816     case AOP_LIT:
817       {
818         value *val = aop->aopu.aop_lit;
819         /* if it is a float then it gets tricky */
820         /* otherwise it is fairly simple */
821         if (!IS_FLOAT (val->type))
822           {
823             unsigned long v = (unsigned long) floatFromVal (val);
824
825             if (offset == 2)
826               v >>= 16;
827
828             if (with_hash)
829               tsprintf (buffer, "!immedword", v);
830             else
831               tsprintf (buffer, "!constword", v);
832             rs = Safe_calloc (1, strlen (buffer) + 1);
833             return strcpy (rs, buffer);
834           }
835         else
836           {
837             /* A float */
838             Z80_FLOAT f;
839             convertFloat (&f, floatFromVal (val));
840             if (with_hash)
841               tsprintf (buffer, "!immedword", f.w[offset / 2]);
842             else
843               tsprintf (buffer, "!constword", f.w[offset / 2]);
844             rs = Safe_calloc (1, strlen (buffer) + 1);
845             return strcpy (rs, buffer);
846           }
847       }
848     default:
849       return NULL;
850     }
851 }
852
853 char *
854 aopGetWord (asmop * aop, int offset)
855 {
856   return aopGetLitWordLong (aop, offset, TRUE);
857 }
858
859 bool
860 isPtr (const char *s)
861 {
862   if (!strcmp (s, "hl"))
863     return TRUE;
864   if (!strcmp (s, "ix"))
865     return TRUE;
866   if (!strcmp (s, "iy"))
867     return TRUE;
868   return FALSE;
869 }
870
871 static void
872 adjustPair (const char *pair, int *pold, int new)
873 {
874   wassert (pair);
875
876   while (*pold < new)
877     {
878       emitcode ("inc", "%s", pair);
879       (*pold)++;
880     }
881   while (*pold > new)
882     {
883       emitcode ("dec", "%s", pair);
884       (*pold)--;
885     }
886 }
887
888 static void
889 spillPair (PAIR_ID pairId)
890 {
891   _G.pairs[pairId].last_type = AOP_INVALID;
892   _G.pairs[pairId].lit = NULL;
893 }
894
895 static void
896 spillCached (void)
897 {
898   spillPair (PAIR_HL);
899   spillPair (PAIR_IY);
900 }
901
902 static bool
903 requiresHL (asmop * aop)
904 {
905   switch (aop->type)
906     {
907     case AOP_IY:
908     case AOP_HL:
909     case AOP_STK:
910       return TRUE;
911     default:
912       return FALSE;
913     }
914 }
915
916 static char *
917 fetchLitSpecial (asmop * aop, bool negate, bool xor)
918 {
919   unsigned long v;
920   value *val = aop->aopu.aop_lit;
921
922   wassert (aop->type == AOP_LIT);
923   wassert (!IS_FLOAT (val->type));
924
925   v = (unsigned long) floatFromVal (val);
926
927   if (xor)
928     v ^= 0x8000;
929   if (negate)
930     v = 0-v;
931   v &= 0xFFFF;
932
933   tsprintf (buffer, "!immedword", v);
934   return gc_strdup (buffer);
935 }
936
937 static void
938 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
939 {
940   const char *l;
941   const char *pair = _pairs[pairId].name;
942   l = aopGetLitWordLong (left, 0, FALSE);
943   wassert (l && pair);
944
945   if (isPtr (pair))
946     {
947       if (pairId == PAIR_HL || pairId == PAIR_IY)
948         {
949           if (_G.pairs[pairId].last_type == left->type)
950             {
951               if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
952                 {
953                   if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
954                     {
955                       adjustPair (pair, &_G.pairs[pairId].offset, offset);
956                       return;
957                     }
958                   if (pairId == PAIR_IY && abs (offset) < 127)
959                     {
960                       return;
961                     }
962                 }
963             }
964         }
965       _G.pairs[pairId].last_type = left->type;
966       _G.pairs[pairId].lit = gc_strdup (l);
967       _G.pairs[pairId].offset = offset;
968     }
969   if (IS_GB && pairId == PAIR_DE && 0)
970     {
971       if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
972         {
973           if (abs (_G.pairs[pairId].offset - offset) < 3)
974             {
975               adjustPair (pair, &_G.pairs[pairId].offset, offset);
976               return;
977             }
978         }
979       _G.pairs[pairId].last_type = left->type;
980       _G.pairs[pairId].lit = gc_strdup (l);
981       _G.pairs[pairId].offset = offset;
982     }
983   /* Both a lit on the right and a true symbol on the left */
984   if (offset)
985     emit2 ("ld %s,!hashedstr + %u", pair, l, offset);
986   else
987     emit2 ("ld %s,!hashedstr", pair, l);
988 }
989
990 static void
991 fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
992 {
993     /* if this is remateriazable */
994     if (isLitWord (aop)) {
995         fetchLitPair (pairId, aop, offset);
996     }
997     else {
998         /* we need to get it byte by byte */
999         if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
1000             aopGet (aop, offset, FALSE);
1001             switch (aop->size) {
1002             case 1:
1003                 emit2 ("ld l,!*hl");
1004                 emit2 ("ld h,!immedbyte", 0);
1005                             break;
1006             case 2:
1007                 emit2 ("!ldahli");
1008                 emit2 ("ld h,!*hl");
1009                 emit2 ("ld l,a");
1010                 break;
1011             default:
1012                 emit2 ("; WARNING: mlh woosed out.  This code is invalid.");
1013             }
1014         }
1015         else if (IS_Z80 && aop->type == AOP_IY) {
1016             /* Instead of fetching relative to IY, just grab directly
1017                from the address IY refers to */
1018             char *l = aopGetLitWordLong (aop, offset, FALSE);
1019             wassert (l);
1020             emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
1021
1022             if (aop->size < 2) {
1023                 emit2("ld %s,!zero", _pairs[pairId].h);
1024             }
1025         }
1026         else {
1027             emitcode ("ld", "%s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
1028             emitcode ("ld", "%s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
1029         }
1030         /* PENDING: check? */
1031         if (pairId == PAIR_HL)
1032             spillPair (PAIR_HL);
1033     }
1034 }
1035
1036 static void
1037 fetchPair (PAIR_ID pairId, asmop * aop)
1038 {
1039   fetchPairLong (pairId, aop, 0);
1040 }
1041
1042 static void
1043 fetchHL (asmop * aop)
1044 {
1045   fetchPair (PAIR_HL, aop);
1046 }
1047
1048 static void
1049 setupPair (PAIR_ID pairId, asmop * aop, int offset)
1050 {
1051   assert (pairId == PAIR_HL || pairId == PAIR_IY);
1052
1053   switch (aop->type)
1054     {
1055     case AOP_IY:
1056       fetchLitPair (pairId, aop, 0);
1057       break;
1058     case AOP_HL:
1059       fetchLitPair (pairId, aop, offset);
1060       _G.pairs[pairId].offset = offset;
1061       break;
1062     case AOP_STK:
1063       {
1064         /* Doesnt include _G.stack.pushed */
1065         int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
1066         if (aop->aopu.aop_stk > 0)
1067           {
1068             abso += _G.stack.param_offset;
1069           }
1070         assert (pairId == PAIR_HL);
1071         /* In some cases we can still inc or dec hl */
1072         if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
1073           {
1074             adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
1075           }
1076         else
1077           {
1078             emit2 ("!ldahlsp", abso + _G.stack.pushed);
1079           }
1080         _G.pairs[pairId].offset = abso;
1081         break;
1082       }
1083     default:
1084       wassert (0);
1085     }
1086   _G.pairs[pairId].last_type = aop->type;
1087 }
1088
1089 static void
1090 emitLabel (int key)
1091 {
1092   emit2 ("!tlabeldef", key);
1093   spillCached ();
1094 }
1095
1096 /*-----------------------------------------------------------------*/
1097 /* aopGet - for fetching value of the aop                          */
1098 /*-----------------------------------------------------------------*/
1099 static const char *
1100 aopGet (asmop * aop, int offset, bool bit16)
1101 {
1102   char *s = buffer;
1103   char *rs;
1104
1105   /* offset is greater than size then zero */
1106   /* PENDING: this seems a bit screwed in some pointer cases. */
1107   if (offset > (aop->size - 1) &&
1108       aop->type != AOP_LIT)
1109     return zero;
1110
1111   /* depending on type */
1112   switch (aop->type)
1113     {
1114     case AOP_IMMD:
1115       /* PENDING: re-target */
1116       if (bit16)
1117         tsprintf (s, "!immedwords", aop->aopu.aop_immd);
1118       else
1119         switch (offset)
1120           {
1121           case 2:
1122             tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
1123             break;
1124           case 1:
1125             tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
1126             break;
1127           case 0:
1128             tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
1129             break;
1130           default:
1131             wassert (0);
1132           }
1133       rs = Safe_calloc (1, strlen (s) + 1);
1134       strcpy (rs, s);
1135       return rs;
1136
1137     case AOP_DIR:
1138       wassert (IS_GB);
1139       emitcode ("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1140       sprintf (s, "a");
1141       rs = Safe_calloc (1, strlen (s) + 1);
1142       strcpy (rs, s);
1143       return rs;
1144
1145     case AOP_SFR:
1146       wassert (IS_GB);
1147       emitcode ("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1148       sprintf (s, "a");
1149       rs = Safe_calloc (1, strlen (s) + 1);
1150       strcpy (rs, s);
1151       return rs;
1152
1153     case AOP_REG:
1154       return aop->aopu.aop_reg[offset]->name;
1155
1156     case AOP_HL:
1157       wassert (IS_GB);
1158       setupPair (PAIR_HL, aop, offset);
1159       tsprintf (s, "!*hl");
1160       return gc_strdup (s);
1161
1162     case AOP_IY:
1163       wassert (IS_Z80);
1164       setupPair (PAIR_IY, aop, offset);
1165       tsprintf (s, "!*iyx", offset);
1166       rs = Safe_calloc (1, strlen (s) + 1);
1167       strcpy (rs, s);
1168       return rs;
1169
1170     case AOP_STK:
1171       if (IS_GB)
1172         {
1173           setupPair (PAIR_HL, aop, offset);
1174           tsprintf (s, "!*hl");
1175         }
1176       else
1177         {
1178           if (aop->aopu.aop_stk >= 0)
1179             offset += _G.stack.param_offset;
1180           tsprintf (s, "!*ixx ; x", aop->aopu.aop_stk + offset);
1181         }
1182       rs = Safe_calloc (1, strlen (s) + 1);
1183       strcpy (rs, s);
1184       return rs;
1185
1186     case AOP_CRY:
1187       wassert (0);
1188
1189     case AOP_ACC:
1190       if (!offset)
1191         {
1192           return "a";
1193         }
1194       return "!zero";
1195
1196     case AOP_HLREG:
1197       wassert (offset < 2);
1198       return aop->aopu.aop_str[offset];
1199
1200     case AOP_LIT:
1201       return aopLiteral (aop->aopu.aop_lit, offset);
1202
1203     case AOP_STR:
1204       aop->coff = offset;
1205       return aop->aopu.aop_str[offset];
1206     default:
1207       break;
1208     }
1209   wassertl (0, "aopget got unsupported aop->type");
1210   exit (0);
1211 }
1212
1213 bool
1214 isRegString (const char *s)
1215 {
1216   if (!strcmp (s, "b") ||
1217       !strcmp (s, "c") ||
1218       !strcmp (s, "d") ||
1219       !strcmp (s, "e") ||
1220       !strcmp (s, "a") ||
1221       !strcmp (s, "h") ||
1222       !strcmp (s, "l"))
1223     return TRUE;
1224   return FALSE;
1225 }
1226
1227 bool
1228 isConstant (const char *s)
1229 {
1230   /* This is a bit of a hack... */
1231   return (*s == '#' || *s == '$');
1232 }
1233
1234 bool
1235 canAssignToPtr (const char *s)
1236 {
1237   if (isRegString (s))
1238     return TRUE;
1239   if (isConstant (s))
1240     return TRUE;
1241   return FALSE;
1242 }
1243
1244 /*-----------------------------------------------------------------*/
1245 /* aopPut - puts a string for a aop                                */
1246 /*-----------------------------------------------------------------*/
1247 static void
1248 aopPut (asmop * aop, const char *s, int offset)
1249 {
1250   if (aop->size && offset > (aop->size - 1))
1251     {
1252       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1253               "aopPut got offset > aop->size");
1254       exit (0);
1255     }
1256
1257   /* will assign value to value */
1258   /* depending on where it is ofcourse */
1259   switch (aop->type)
1260     {
1261     case AOP_DIR:
1262       /* Direct.  Hmmm. */
1263       wassert (IS_GB);
1264       if (strcmp (s, "a"))
1265         emitcode ("ld", "a,%s", s);
1266       emitcode ("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
1267       break;
1268
1269     case AOP_SFR:
1270       wassert (IS_GB);
1271       if (strcmp (s, "a"))
1272         emitcode ("ld", "a,%s", s);
1273       emitcode ("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
1274       break;
1275
1276     case AOP_REG:
1277       if (!strcmp (s, "!*hl"))
1278         emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1279       else
1280         emit2 ("ld %s,%s",
1281                aop->aopu.aop_reg[offset]->name, s);
1282       break;
1283
1284     case AOP_IY:
1285       wassert (!IS_GB);
1286       setupPair (PAIR_IY, aop, offset);
1287       if (!canAssignToPtr (s))
1288         {
1289           emit2 ("ld a,%s", s);
1290           emit2 ("ld !*iyx,a", offset);
1291         }
1292       else
1293         emit2 ("ld !*iyx,%s", offset, s);
1294       break;
1295
1296     case AOP_HL:
1297       wassert (IS_GB);
1298       /* PENDING: for re-target */
1299       if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1300         {
1301           emit2 ("ld a,!*hl");
1302           s = "a";
1303         }
1304       setupPair (PAIR_HL, aop, offset);
1305
1306       emit2 ("ld !*hl,%s", s);
1307       break;
1308
1309     case AOP_STK:
1310       if (IS_GB)
1311         {
1312           /* PENDING: re-target */
1313           if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
1314             {
1315               emit2 ("ld a,!*hl");
1316               s = "a";
1317             }
1318           setupPair (PAIR_HL, aop, offset);
1319           if (!canAssignToPtr (s))
1320             {
1321               emit2 ("ld a,%s", s);
1322               emit2 ("ld !*hl,a");
1323             }
1324           else
1325             emit2 ("ld !*hl,%s", s);
1326         }
1327       else
1328         {
1329           if (aop->aopu.aop_stk >= 0)
1330             offset += _G.stack.param_offset;
1331           if (!canAssignToPtr (s))
1332             {
1333               emit2 ("ld a,%s", s);
1334               emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
1335             }
1336           else
1337             emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
1338         }
1339       break;
1340
1341     case AOP_CRY:
1342       /* if bit variable */
1343       if (!aop->aopu.aop_dir)
1344         {
1345           emit2 ("ld a,#0");
1346           emit2 ("rla");
1347         }
1348       else
1349         {
1350           /* In bit space but not in C - cant happen */
1351           wassert (0);
1352         }
1353       break;
1354
1355     case AOP_STR:
1356       aop->coff = offset;
1357       if (strcmp (aop->aopu.aop_str[offset], s))
1358         {
1359           emitcode ("ld", "%s,%s", aop->aopu.aop_str[offset], s);
1360         }
1361       break;
1362
1363     case AOP_ACC:
1364       aop->coff = offset;
1365       if (!offset && (strcmp (s, "acc") == 0))
1366         break;
1367       if (offset > 0)
1368         {
1369
1370           emitcode ("", "; Error aopPut AOP_ACC");
1371         }
1372       else
1373         {
1374           if (strcmp (aop->aopu.aop_str[offset], s))
1375             emitcode ("ld", "%s,%s", aop->aopu.aop_str[offset], s);
1376         }
1377       break;
1378
1379     case AOP_HLREG:
1380       wassert (offset < 2);
1381       emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
1382       break;
1383
1384     default:
1385       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1386               "aopPut got unsupported aop->type");
1387       exit (0);
1388     }
1389 }
1390
1391 #define AOP(op) op->aop
1392 #define AOP_TYPE(op) AOP(op)->type
1393 #define AOP_SIZE(op) AOP(op)->size
1394 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1395
1396 static void
1397 commitPair (asmop * aop, PAIR_ID id)
1398 {
1399   if (id == PAIR_HL && requiresHL (aop))
1400     {
1401       emit2 ("ld a,l");
1402       emit2 ("ld d,h");
1403       aopPut (aop, "a", 0);
1404       aopPut (aop, "d", 1);
1405     }
1406   else
1407     {
1408       aopPut (aop, _pairs[id].l, 0);
1409       aopPut (aop, _pairs[id].h, 1);
1410     }
1411 }
1412
1413 /*-----------------------------------------------------------------*/
1414 /* getDataSize - get the operand data size                         */
1415 /*-----------------------------------------------------------------*/
1416 int
1417 getDataSize (operand * op)
1418 {
1419   int size;
1420   size = AOP_SIZE (op);
1421   if (size == 3)
1422     {
1423       /* pointer */
1424       wassert (0);
1425     }
1426   return size;
1427 }
1428
1429 /*-----------------------------------------------------------------*/
1430 /* movLeft2Result - move byte from left to result                  */
1431 /*-----------------------------------------------------------------*/
1432 static void
1433 movLeft2Result (operand * left, int offl,
1434                 operand * result, int offr, int sign)
1435 {
1436     const char *l;
1437   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
1438     {
1439       l = aopGet (AOP (left), offl, FALSE);
1440
1441       if (!sign)
1442         {
1443           aopPut (AOP (result), l, offr);
1444         }
1445       else
1446         {
1447           wassert (0);
1448         }
1449     }
1450 }
1451
1452
1453 /** Put Acc into a register set
1454  */
1455 void
1456 outAcc (operand * result)
1457 {
1458   int size, offset;
1459   size = getDataSize (result);
1460   if (size)
1461     {
1462       aopPut (AOP (result), "a", 0);
1463       size--;
1464       offset = 1;
1465       /* unsigned or positive */
1466       while (size--)
1467         {
1468           aopPut (AOP (result), zero, offset++);
1469         }
1470     }
1471 }
1472
1473 /** Take the value in carry and put it into a register
1474  */
1475 void
1476 outBitCLong (operand * result, bool swap_sense)
1477 {
1478   /* if the result is bit */
1479   if (AOP_TYPE (result) == AOP_CRY)
1480     {
1481       emitcode ("", "; Note: outBitC form 1");
1482       aopPut (AOP (result), "blah", 0);
1483     }
1484   else
1485     {
1486       emit2 ("ld a,!zero");
1487       emit2 ("rla");
1488       if (swap_sense)
1489         emit2 ("xor a,!immedbyte", 1);
1490       outAcc (result);
1491     }
1492 }
1493
1494 void
1495 outBitC (operand * result)
1496 {
1497   outBitCLong (result, FALSE);
1498 }
1499
1500 /*-----------------------------------------------------------------*/
1501 /* toBoolean - emit code for orl a,operator(sizeop)                */
1502 /*-----------------------------------------------------------------*/
1503 void
1504 toBoolean (operand * oper)
1505 {
1506   int size = AOP_SIZE (oper);
1507   int offset = 0;
1508   if (size > 1)
1509     {
1510       emitcode ("ld", "a,%s", aopGet (AOP (oper), offset++, FALSE));
1511       size--;
1512       while (size--)
1513         emitcode ("or", "a,%s", aopGet (AOP (oper), offset++, FALSE));
1514     }
1515   else
1516     {
1517       if (AOP (oper)->type != AOP_ACC)
1518         {
1519           _ClearCarry();
1520           emitcode ("or", "a,%s", aopGet (AOP (oper), 0, FALSE));
1521         }
1522     }
1523 }
1524
1525 /*-----------------------------------------------------------------*/
1526 /* genNot - generate code for ! operation                          */
1527 /*-----------------------------------------------------------------*/
1528 static void
1529 genNot (iCode * ic)
1530 {
1531   sym_link *optype = operandType (IC_LEFT (ic));
1532
1533   /* assign asmOps to operand & result */
1534   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
1535   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1536
1537   /* if in bit space then a special case */
1538   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1539     {
1540       wassert (0);
1541     }
1542
1543   /* if type float then do float */
1544   if (IS_FLOAT (optype))
1545     {
1546       wassert (0);
1547     }
1548
1549   toBoolean (IC_LEFT (ic));
1550
1551   /* Not of A:
1552      If A == 0, !A = 1
1553      else A = 0
1554      So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1555   emit2 ("sub a,!one");
1556   outBitC (IC_RESULT (ic));
1557
1558   /* release the aops */
1559   freeAsmop (IC_LEFT (ic), NULL, ic);
1560   freeAsmop (IC_RESULT (ic), NULL, ic);
1561 }
1562
1563 /*-----------------------------------------------------------------*/
1564 /* genCpl - generate code for complement                           */
1565 /*-----------------------------------------------------------------*/
1566 static void
1567 genCpl (iCode * ic)
1568 {
1569   int offset = 0;
1570   int size;
1571
1572
1573   /* assign asmOps to operand & result */
1574   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1575   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1576
1577   /* if both are in bit space then
1578      a special case */
1579   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1580       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1581     {
1582       wassert (0);
1583     }
1584
1585   size = AOP_SIZE (IC_RESULT (ic));
1586   while (size--)
1587     {
1588       const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1589       _MoveA (l);
1590       emit2("cpl");
1591       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1592     }
1593
1594   /* release the aops */
1595   freeAsmop (IC_LEFT (ic), NULL, ic);
1596   freeAsmop (IC_RESULT (ic), NULL, ic);
1597 }
1598
1599 /*-----------------------------------------------------------------*/
1600 /* genUminus - unary minus code generation                         */
1601 /*-----------------------------------------------------------------*/
1602 static void
1603 genUminus (iCode * ic)
1604 {
1605   int offset, size;
1606   sym_link *optype, *rtype;
1607
1608   /* assign asmops */
1609   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1610   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
1611
1612   /* if both in bit space then special
1613      case */
1614   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1615       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1616     {
1617       wassert (0);
1618       goto release;
1619     }
1620
1621   optype = operandType (IC_LEFT (ic));
1622   rtype = operandType (IC_RESULT (ic));
1623
1624   /* if float then do float stuff */
1625   if (IS_FLOAT (optype))
1626     {
1627       wassert (0);
1628       goto release;
1629     }
1630
1631   /* otherwise subtract from zero */
1632   size = AOP_SIZE (IC_LEFT (ic));
1633   offset = 0;
1634   _ClearCarry();
1635   while (size--)
1636     {
1637       const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
1638       emit2 ("ld a,!zero");
1639       emit2 ("sbc a,%s", l);
1640       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1641     }
1642
1643   /* if any remaining bytes in the result */
1644   /* we just need to propagate the sign   */
1645   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1646     {
1647       emit2 ("rlc a");
1648       emit2 ("sbc a,a");
1649       while (size--)
1650         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1651     }
1652
1653 release:
1654   /* release the aops */
1655   freeAsmop (IC_LEFT (ic), NULL, ic);
1656   freeAsmop (IC_RESULT (ic), NULL, ic);
1657 }
1658
1659 static void
1660 _push (PAIR_ID pairId)
1661 {
1662   emit2 ("push %s", _pairs[pairId].name);
1663   _G.stack.pushed += 2;
1664 }
1665
1666 static void
1667 _pop (PAIR_ID pairId)
1668 {
1669   emit2 ("pop %s", _pairs[pairId].name);
1670   _G.stack.pushed -= 2;
1671 }
1672
1673
1674 /*-----------------------------------------------------------------*/
1675 /* assignResultValue -               */
1676 /*-----------------------------------------------------------------*/
1677 void
1678 assignResultValue (operand * oper)
1679 {
1680   int size = AOP_SIZE (oper);
1681   bool topInA = 0;
1682
1683   wassert (size <= 4);
1684   topInA = requiresHL (AOP (oper));
1685
1686 #if 0
1687   if (!IS_GB)
1688     wassert (size <= 2);
1689 #endif
1690   if (IS_GB && size == 4 && requiresHL (AOP (oper)))
1691     {
1692       /* We do it the hard way here. */
1693       _push (PAIR_HL);
1694       aopPut (AOP (oper), _fReturn[0], 0);
1695       aopPut (AOP (oper), _fReturn[1], 1);
1696       emitcode ("pop", "de");
1697       _G.stack.pushed -= 2;
1698       aopPut (AOP (oper), _fReturn[0], 2);
1699       aopPut (AOP (oper), _fReturn[1], 3);
1700     }
1701   else
1702     {
1703       while (size--)
1704         {
1705           aopPut (AOP (oper), _fReturn[size], size);
1706         }
1707     }
1708 }
1709
1710 /*-----------------------------------------------------------------*/
1711 /* genIpush - genrate code for pushing this gets a little complex  */
1712 /*-----------------------------------------------------------------*/
1713 static void
1714 genIpush (iCode * ic)
1715 {
1716   int size, offset = 0;
1717   const char *l;
1718
1719   /* if this is not a parm push : ie. it is spill push
1720      and spill push is always done on the local stack */
1721   if (!ic->parmPush)
1722     {
1723       /* and the item is spilt then do nothing */
1724       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1725         return;
1726
1727       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1728       size = AOP_SIZE (IC_LEFT (ic));
1729       /* push it on the stack */
1730       if (isPair (AOP (IC_LEFT (ic))))
1731         {
1732           emitcode ("push", getPairName (AOP (IC_LEFT (ic))));
1733           _G.stack.pushed += 2;
1734         }
1735       else
1736         {
1737           offset = size;
1738           while (size--)
1739             {
1740               /* Simple for now - load into A and PUSH AF */
1741               if (AOP (IC_LEFT (ic))->type == AOP_IY)
1742                 {
1743                   char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1744                   wassert (l);
1745                   emit2 ("ld a,(%s)", l);
1746                 }
1747               else
1748                 {
1749                   l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1750                   emit2 ("ld a,%s", l);
1751                 }
1752               emit2 ("push af");
1753               emit2 ("inc sp");
1754               _G.stack.pushed++;
1755             }
1756         }
1757       return;
1758     }
1759
1760   /* Hmmm... what about saving the currently used registers
1761      at this point? */
1762
1763   /* then do the push */
1764   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1765
1766   size = AOP_SIZE (IC_LEFT (ic));
1767
1768   if (isPair (AOP (IC_LEFT (ic))))
1769     {
1770       _G.stack.pushed += 2;
1771       emitcode ("push", "%s", getPairName (AOP (IC_LEFT (ic))));
1772     }
1773   else
1774     {
1775       if (size == 2)
1776         {
1777           fetchHL (AOP (IC_LEFT (ic)));
1778           emitcode ("push", "hl");
1779           spillPair (PAIR_HL);
1780           _G.stack.pushed += 2;
1781           goto release;
1782         }
1783       if (size == 4)
1784         {
1785           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
1786           emitcode ("push", "hl");
1787           spillPair (PAIR_HL);
1788           _G.stack.pushed += 2;
1789           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
1790           emitcode ("push", "hl");
1791           spillPair (PAIR_HL);
1792           _G.stack.pushed += 2;
1793           goto release;
1794         }
1795       offset = size;
1796       while (size--)
1797         {
1798           if (AOP (IC_LEFT (ic))->type == AOP_IY)
1799             {
1800               char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
1801               wassert (l);
1802               emit2 ("ld a,(%s)", l);
1803             }
1804           else
1805             {
1806               l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
1807               emit2 ("ld a,%s", l);
1808             }
1809           emitcode ("push", "af");
1810           emitcode ("inc", "sp");
1811           _G.stack.pushed++;
1812         }
1813     }
1814 release:
1815   freeAsmop (IC_LEFT (ic), NULL, ic);
1816 }
1817
1818 /*-----------------------------------------------------------------*/
1819 /* genIpop - recover the registers: can happen only for spilling   */
1820 /*-----------------------------------------------------------------*/
1821 static void
1822 genIpop (iCode * ic)
1823 {
1824   int size, offset;
1825
1826
1827   /* if the temp was not pushed then */
1828   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1829     return;
1830
1831   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1832   size = AOP_SIZE (IC_LEFT (ic));
1833   offset = (size - 1);
1834   if (isPair (AOP (IC_LEFT (ic))))
1835     {
1836       emitcode ("pop", getPairName (AOP (IC_LEFT (ic))));
1837     }
1838   else
1839     {
1840       while (size--)
1841         {
1842           emitcode ("dec", "sp");
1843           emitcode ("pop", "hl");
1844           spillPair (PAIR_HL);
1845           aopPut (AOP (IC_LEFT (ic)), "l", offset--);
1846         }
1847     }
1848
1849   freeAsmop (IC_LEFT (ic), NULL, ic);
1850 }
1851
1852 static int
1853 _isPairUsed (iCode * ic, PAIR_ID pairId)
1854 {
1855   int ret = 0;
1856   switch (pairId)
1857     {
1858     case PAIR_DE:
1859       if (bitVectBitValue (ic->rMask, D_IDX))
1860         ret++;
1861       if (bitVectBitValue (ic->rMask, E_IDX))
1862         ret++;
1863       break;
1864     default:
1865       wassert (0);
1866     }
1867   return ret;
1868 }
1869
1870 static int
1871 _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
1872 {
1873   int ret = 0;
1874   asmop *aop;
1875   symbol *sym = OP_SYMBOL (op);
1876
1877   if (sym->isspilt || sym->nRegs == 0)
1878     return 0;
1879
1880   aopOp (op, ic, FALSE, FALSE);
1881
1882   aop = AOP (op);
1883   if (aop->type == AOP_REG)
1884     {
1885       int i;
1886       for (i = 0; i < aop->size; i++)
1887         {
1888           if (pairId == PAIR_DE)
1889             {
1890               emit2 ("; name %s", aop->aopu.aop_reg[i]->name);
1891               if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
1892                 ret++;
1893               if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
1894                 ret++;
1895             }
1896           else
1897             {
1898               wassert (0);
1899             }
1900         }
1901     }
1902
1903   freeAsmop (IC_LEFT (ic), NULL, ic);
1904   return ret;
1905 }
1906
1907 /* This is quite unfortunate */
1908 static void
1909 setArea (int inHome)
1910 {
1911   /*
1912     static int lastArea = 0;
1913
1914      if (_G.in_home != inHome) {
1915      if (inHome) {
1916      const char *sz = port->mem.code_name;
1917      port->mem.code_name = "HOME";
1918      emit2("!area", CODE_NAME);
1919      port->mem.code_name = sz;
1920      }
1921      else
1922      emit2("!area", CODE_NAME); */
1923   _G.in_home = inHome;
1924   //    }
1925 }
1926
1927 static bool
1928 isInHome (void)
1929 {
1930   return _G.in_home;
1931 }
1932
1933 /** Emit the code for a call statement
1934  */
1935 static void
1936 emitCall (iCode * ic, bool ispcall)
1937 {
1938   int pushed_de = 0;
1939   sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
1940
1941   /* if caller saves & we have not saved then */
1942   if (!ic->regsSaved)
1943     {
1944       /* PENDING */
1945     }
1946
1947   /* if send set is not empty then assign */
1948   if (sendSet)
1949     {
1950       iCode *sic;
1951       int send = 0;
1952       int n = elementsInSet (sendSet);
1953       if (IS_Z80 && n == 2 && _isPairUsed (ic, PAIR_DE))
1954         {
1955           /* Only push de if it is used and if it's not used
1956              in the return value */
1957           /* Panic if partly used */
1958           if (_opUsesPair (IC_RESULT (ic), ic, PAIR_DE) == 1)
1959             {
1960               emit2 ("; Warning: de crossover");
1961             }
1962           else if (!_opUsesPair (IC_RESULT (ic), ic, PAIR_DE))
1963             {
1964               /* Store away de */
1965               _push (PAIR_DE);
1966               pushed_de = 1;
1967             }
1968         }
1969       /* PENDING: HACK */
1970       if (IS_Z80 && n == 2)
1971         {
1972           /* Want to load HL first, then DE as HL may = DE */
1973           sic = setFirstItem (sendSet);
1974           sic = setNextItem (sendSet);
1975           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
1976           fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
1977           send++;
1978           freeAsmop (IC_LEFT (sic), NULL, sic);
1979           sic = setFirstItem (sendSet);
1980           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
1981           fetchPair (PAIR_DE, AOP (IC_LEFT (sic)));
1982           send++;
1983           freeAsmop (IC_LEFT (sic), NULL, sic);
1984         }
1985       else
1986         {
1987           for (sic = setFirstItem (sendSet); sic;
1988                sic = setNextItem (sendSet))
1989             {
1990               int size;
1991               aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
1992               size = AOP_SIZE (IC_LEFT (sic));
1993               wassert (size <= 2);
1994               /* Always send in pairs */
1995               switch (send)
1996                 {
1997                 case 0:
1998                   if (IS_Z80 && n == 1)
1999                     fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
2000                   else
2001                     fetchPair (PAIR_DE, AOP (IC_LEFT (sic)));
2002                   break;
2003                 case 1:
2004                   fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
2005                   break;
2006                 default:
2007                   /* Send set too big */
2008                   wassert (0);
2009                 }
2010               send++;
2011               freeAsmop (IC_LEFT (sic), NULL, sic);
2012             }
2013         }
2014       sendSet = NULL;
2015       if (pushed_de)
2016         {
2017         }
2018     }
2019
2020   if (ispcall)
2021     {
2022       if (IS_BANKEDCALL (detype))
2023         {
2024           werror (W_INDIR_BANKED);
2025         }
2026       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2027
2028       if (isLitWord (AOP (IC_LEFT (ic))))
2029         {
2030           emitcode ("", "; Special case where the pCall is to a constant");
2031           
2032           emitcode ("call", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
2033         }
2034       else
2035         {
2036           symbol *rlbl = newiTempLabel (NULL);
2037           spillPair (PAIR_HL);
2038           emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
2039           emitcode ("push", "hl");
2040           _G.stack.pushed += 2;
2041
2042           fetchHL (AOP (IC_LEFT (ic)));
2043           emit2 ("jp !*hl");
2044           emit2 ("!tlabeldef", (rlbl->key + 100));
2045           _G.stack.pushed -= 2;
2046         }
2047       freeAsmop (IC_LEFT (ic), NULL, ic);
2048     }
2049   else
2050     {
2051       char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2052       OP_SYMBOL (IC_LEFT (ic))->rname :
2053       OP_SYMBOL (IC_LEFT (ic))->name;
2054       if (IS_BANKEDCALL (detype))
2055         {
2056           emit2 ("call banked_call");
2057           emit2 ("!dws", name);
2058           emit2 ("!dw !bankimmeds", name);
2059         }
2060       else
2061         {
2062           /* make the call */
2063           emit2 ("call %s", name);
2064         }
2065     }
2066   spillCached ();
2067
2068   /* if we need assign a result value */
2069   if ((IS_ITEMP (IC_RESULT (ic)) &&
2070        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2071         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2072       IS_TRUE_SYMOP (IC_RESULT (ic)))
2073     {
2074
2075       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2076
2077       assignResultValue (IC_RESULT (ic));
2078
2079       freeAsmop (IC_RESULT (ic), NULL, ic);
2080     }
2081
2082   /* adjust the stack for parameters if required */
2083   if (ic->parmBytes)
2084     {
2085       int i = ic->parmBytes;
2086       _G.stack.pushed -= i;
2087       if (IS_GB)
2088         {
2089           emit2 ("!ldaspsp", i);
2090         }
2091       else
2092         {
2093           spillCached ();
2094           if (i > 6)
2095             {
2096               emitcode ("ld", "hl,#%d", i);
2097               emitcode ("add", "hl,sp");
2098               emitcode ("ld", "sp,hl");
2099             }
2100           else
2101             {
2102               while (i > 1)
2103                 {
2104                   emitcode ("pop", "hl");
2105                   i -= 2;
2106                 }
2107               if (i)
2108                 emitcode ("inc", "sp");
2109             }
2110           spillCached ();
2111         }
2112     }
2113   if (pushed_de)
2114     _pop (PAIR_DE);
2115 }
2116
2117 /*-----------------------------------------------------------------*/
2118 /* genCall - generates a call statement                            */
2119 /*-----------------------------------------------------------------*/
2120 static void
2121 genCall (iCode * ic)
2122 {
2123   emitCall (ic, FALSE);
2124 }
2125
2126 /*-----------------------------------------------------------------*/
2127 /* genPcall - generates a call by pointer statement                */
2128 /*-----------------------------------------------------------------*/
2129 static void
2130 genPcall (iCode * ic)
2131 {
2132   emitCall (ic, TRUE);
2133 }
2134
2135 /*-----------------------------------------------------------------*/
2136 /* resultRemat - result  is rematerializable                       */
2137 /*-----------------------------------------------------------------*/
2138 static int
2139 resultRemat (iCode * ic)
2140 {
2141   if (SKIP_IC (ic) || ic->op == IFX)
2142     return 0;
2143
2144   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2145     {
2146       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2147       if (sym->remat && !POINTER_SET (ic))
2148         return 1;
2149     }
2150
2151   return 0;
2152 }
2153
2154 extern set *publics;
2155
2156 /*-----------------------------------------------------------------*/
2157 /* genFunction - generated code for function entry                 */
2158 /*-----------------------------------------------------------------*/
2159 static void
2160 genFunction (iCode * ic)
2161 {
2162   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2163   sym_link *fetype;
2164
2165   nregssaved = 0;
2166   // PENDING: HACK
2167   _G.receiveOffset = 0;
2168
2169   setArea (IS_NONBANKED (sym->etype));
2170
2171   /* PENDING: hack */
2172   if (!IS_STATIC (sym->etype))
2173     {
2174       addSetIfnotP (&publics, sym);
2175     }
2176
2177   _G.lastFunctionName = sym->rname;
2178
2179   /* create the function header */
2180   emit2 ("!functionheader", sym->name);
2181   /* PENDING: portability. */
2182   emit2 ("__%s_start:", sym->rname);
2183   emit2 ("!functionlabeldef", sym->rname);
2184
2185   fetype = getSpec (operandType (IC_LEFT (ic)));
2186
2187   /* if critical function then turn interrupts off */
2188   if (SPEC_CRTCL (fetype))
2189     emit2 ("!di");
2190
2191   /* if this is an interrupt service routine then
2192      save acc, b, dpl, dph  */
2193   if (IS_ISR (sym->etype))
2194     {
2195       emit2 ("!pusha");
2196     }
2197   /* PENDING: callee-save etc */
2198
2199   /* If BC or DE are used, then push */
2200   _G.stack.pushed_bc = 0;
2201   _G.stack.pushed_de = 0;
2202   _G.stack.param_offset = 0;
2203
2204   /* PENDING: BUG: We don't detect if DE or BC are used in a send set.
2205      For now assume the worst and always save.
2206   */
2207   _G.stack.pushed_bc = 1;
2208   _G.stack.pushed_de = 1;
2209
2210   if (sym->regsUsed)
2211     {
2212       int i;
2213       for (i = 0; i < sym->regsUsed->size; i++)
2214         {
2215           if (bitVectBitValue (sym->regsUsed, i))
2216             {
2217               switch (i)
2218                 {
2219                 case C_IDX:
2220                 case B_IDX:
2221                   _G.stack.pushed_bc = 1;
2222                   break;
2223                 case D_IDX:
2224                 case E_IDX:
2225                   if (IS_Z80)
2226                     _G.stack.pushed_de = 1;
2227                   break;
2228                 }
2229             }
2230         }
2231     }
2232
2233   if (_G.stack.pushed_bc)
2234       {
2235           emit2 ("push bc");
2236           _G.stack.param_offset += 2;
2237       }
2238   if (_G.stack.pushed_de)
2239       {
2240           emit2 ("push de");
2241           _G.stack.param_offset += 2;
2242       }
2243
2244   /* adjust the stack for the function */
2245   _G.stack.last = sym->stack;
2246
2247   if (sym->stack)
2248     emit2 ("!enterx", sym->stack);
2249   else
2250     emit2 ("!enter");
2251   _G.stack.offset = sym->stack;
2252 }
2253
2254 /*-----------------------------------------------------------------*/
2255 /* genEndFunction - generates epilogue for functions               */
2256 /*-----------------------------------------------------------------*/
2257 static void
2258 genEndFunction (iCode * ic)
2259 {
2260   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2261
2262   if (IS_ISR (sym->etype))
2263     {
2264       wassert (0);
2265     }
2266   else
2267     {
2268       if (SPEC_CRTCL (sym->etype))
2269         emit2 ("!ei");
2270
2271       /* PENDING: calleeSave */
2272
2273       /* if debug then send end of function */
2274       if (options.debug && currFunc)
2275         {
2276           debugLine = 1;
2277           emitcode ("", "C$%s$%d$%d$%d ==.",
2278                     FileBaseName (ic->filename), currFunc->lastLine,
2279                     ic->level, ic->block);
2280           if (IS_STATIC (currFunc->etype))
2281             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2282           else
2283             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2284           debugLine = 0;
2285         }
2286       if (_G.stack.offset)
2287         emit2 ("!leavex", _G.stack.offset);
2288       else
2289         emit2 ("!leave");
2290
2291       if (_G.stack.pushed_de)
2292         emit2 ("pop de");
2293       if (_G.stack.pushed_bc)
2294         emit2 ("pop bc");
2295       /* Both baned and non-banked just ret */
2296       emit2 ("ret");
2297
2298       /* PENDING: portability. */
2299       emit2 ("__%s_end:", sym->rname);
2300     }
2301   _G.flush_statics = 1;
2302   _G.stack.pushed = 0;
2303   _G.stack.offset = 0;
2304 }
2305
2306 /*-----------------------------------------------------------------*/
2307 /* genRet - generate code for return statement                     */
2308 /*-----------------------------------------------------------------*/
2309 static void
2310 genRet (iCode * ic)
2311 {
2312     const char *l;
2313   /* Errk.  This is a hack until I can figure out how
2314      to cause dehl to spill on a call */
2315   int size, offset = 0;
2316
2317   /* if we have no return value then
2318      just generate the "ret" */
2319   if (!IC_LEFT (ic))
2320     goto jumpret;
2321
2322   /* we have something to return then
2323      move the return value into place */
2324   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2325   size = AOP_SIZE (IC_LEFT (ic));
2326
2327   if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
2328     {
2329       if (IS_GB)
2330         {
2331           emitcode ("ld", "de,%s", l);
2332         }
2333       else
2334         {
2335           emitcode ("ld", "hl,%s", l);
2336         }
2337     }
2338   else
2339     {
2340       if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
2341         {
2342           fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2343           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
2344         }
2345       else
2346         {
2347           while (size--)
2348             {
2349               l = aopGet (AOP (IC_LEFT (ic)), offset,
2350                           FALSE);
2351               if (strcmp (_fReturn[offset], l))
2352                 emitcode ("ld", "%s,%s", _fReturn[offset++], l);
2353             }
2354         }
2355     }
2356   freeAsmop (IC_LEFT (ic), NULL, ic);
2357
2358 jumpret:
2359   /* generate a jump to the return label
2360      if the next is not the return statement */
2361   if (!(ic->next && ic->next->op == LABEL &&
2362         IC_LABEL (ic->next) == returnLabel))
2363
2364     emit2 ("jp !tlabel", returnLabel->key + 100);
2365 }
2366
2367 /*-----------------------------------------------------------------*/
2368 /* genLabel - generates a label                                    */
2369 /*-----------------------------------------------------------------*/
2370 static void
2371 genLabel (iCode * ic)
2372 {
2373   /* special case never generate */
2374   if (IC_LABEL (ic) == entryLabel)
2375     return;
2376
2377   emitLabel (IC_LABEL (ic)->key + 100);
2378 }
2379
2380 /*-----------------------------------------------------------------*/
2381 /* genGoto - generates a ljmp                                      */
2382 /*-----------------------------------------------------------------*/
2383 static void
2384 genGoto (iCode * ic)
2385 {
2386   emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
2387 }
2388
2389 /*-----------------------------------------------------------------*/
2390 /* genPlusIncr :- does addition with increment if possible         */
2391 /*-----------------------------------------------------------------*/
2392 static bool
2393 genPlusIncr (iCode * ic)
2394 {
2395   unsigned int icount;
2396   unsigned int size = getDataSize (IC_RESULT (ic));
2397   PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
2398
2399   /* will try to generate an increment */
2400   /* if the right side is not a literal
2401      we cannot */
2402   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2403     return FALSE;
2404
2405   emitcode ("", "; genPlusIncr");
2406
2407   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2408
2409   /* If result is a pair */
2410   if (resultId != PAIR_INVALID)
2411     {
2412       if (isLitWord (AOP (IC_LEFT (ic))))
2413         {
2414           fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
2415           return TRUE;
2416         }
2417       if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
2418         {
2419           fetchPair (resultId, AOP (IC_RIGHT (ic)));
2420           emitcode ("add", "hl,%s", getPairName (AOP (IC_LEFT (ic))));
2421           return TRUE;
2422         }
2423       if (icount > 5)
2424         return FALSE;
2425       /* Inc a pair */
2426       if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2427         {
2428           if (icount > 2)
2429             return FALSE;
2430           movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2431           movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2432         }
2433       while (icount--)
2434         {
2435           emitcode ("inc", "%s", getPairName (AOP (IC_RESULT (ic))));
2436         }
2437       return TRUE;
2438     }
2439
2440   /* if the literal value of the right hand side
2441      is greater than 4 then it is not worth it */
2442   if (icount > 4)
2443     return FALSE;
2444
2445   /* if increment 16 bits in register */
2446   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2447       size > 1 &&
2448       icount == 1
2449     )
2450     {
2451       int offset = 0;
2452       symbol *tlbl = NULL;
2453       tlbl = newiTempLabel (NULL);
2454       while (size--)
2455         {
2456           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
2457           if (size)
2458             {
2459               emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
2460             }
2461         }
2462       emitLabel (tlbl->key + 100);
2463       return TRUE;
2464     }
2465
2466   /* if the sizes are greater than 1 then we cannot */
2467   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2468       AOP_SIZE (IC_LEFT (ic)) > 1)
2469     return FALSE;
2470
2471   /* we can if the aops of the left & result match or
2472      if they are in registers and the registers are the
2473      same */
2474   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2475     {
2476       while (icount--)
2477         emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
2478       return TRUE;
2479     }
2480
2481   return FALSE;
2482 }
2483
2484 /*-----------------------------------------------------------------*/
2485 /* outBitAcc - output a bit in acc                                 */
2486 /*-----------------------------------------------------------------*/
2487 void
2488 outBitAcc (operand * result)
2489 {
2490   symbol *tlbl = newiTempLabel (NULL);
2491   /* if the result is a bit */
2492   if (AOP_TYPE (result) == AOP_CRY)
2493     {
2494       wassert (0);
2495     }
2496   else
2497     {
2498       emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
2499       emit2 ("ld a,!one");
2500       emitLabel (tlbl->key + 100);
2501       outAcc (result);
2502     }
2503 }
2504
2505 /*-----------------------------------------------------------------*/
2506 /* genPlus - generates code for addition                           */
2507 /*-----------------------------------------------------------------*/
2508 static void
2509 genPlus (iCode * ic)
2510 {
2511   int size, offset = 0;
2512
2513   /* special cases :- */
2514
2515   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2516   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2517   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2518
2519   /* Swap the left and right operands if:
2520
2521      if literal, literal on the right or
2522      if left requires ACC or right is already
2523      in ACC */
2524
2525   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2526       (AOP_NEEDSACC (IC_LEFT (ic))) ||
2527       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2528     {
2529       operand *t = IC_RIGHT (ic);
2530       IC_RIGHT (ic) = IC_LEFT (ic);
2531       IC_LEFT (ic) = t;
2532     }
2533
2534   /* if both left & right are in bit
2535      space */
2536   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2537       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2538     {
2539       /* Cant happen */
2540       wassert (0);
2541     }
2542
2543   /* if left in bit space & right literal */
2544   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2545       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2546     {
2547       /* Can happen I guess */
2548       wassert (0);
2549     }
2550
2551   /* if I can do an increment instead
2552      of add then GOOD for ME */
2553   if (genPlusIncr (ic) == TRUE)
2554     goto release;
2555
2556   emit2 ("; genPlusIncr failed");
2557
2558   size = getDataSize (IC_RESULT (ic));
2559
2560   /* Special case when left and right are constant */
2561   if (isPair (AOP (IC_RESULT (ic))))
2562     {
2563       char *left, *right;
2564
2565       left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
2566       right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
2567       if (left && right)
2568         {
2569           /* It's a pair */
2570           /* PENDING: fix */
2571           char buffer[100];
2572           sprintf (buffer, "#(%s + %s)", left, right);
2573           emitcode ("ld", "%s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
2574           goto release;
2575         }
2576     }
2577
2578   if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
2579     {
2580       /* Fetch into HL then do the add */
2581       spillPair (PAIR_HL);
2582       fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
2583       emitcode ("add", "hl,%s", getPairName (AOP (IC_RIGHT (ic))));
2584       goto release;
2585     }
2586
2587   /* Special case:
2588      ld hl,sp+n trashes C so we cant afford to do it during an
2589      add with stack based varibles.  Worst case is:
2590      ld  hl,sp+left
2591      ld  a,(hl)
2592      ld  hl,sp+right
2593      add (hl)
2594      ld  hl,sp+result
2595      ld  (hl),a
2596      ld  hl,sp+left+1
2597      ld  a,(hl)
2598      ld  hl,sp+right+1
2599      adc (hl)
2600      ld  hl,sp+result+1
2601      ld  (hl),a
2602      So you cant afford to load up hl if either left, right, or result
2603      is on the stack (*sigh*)  The alt is:
2604      ld  hl,sp+left
2605      ld  de,(hl)
2606      ld  hl,sp+right
2607      ld  hl,(hl)
2608      add hl,de
2609      ld  hl,sp+result
2610      ld  (hl),hl
2611      Combinations in here are:
2612      * If left or right are in bc then the loss is small - trap later
2613      * If the result is in bc then the loss is also small
2614    */
2615   if (IS_GB)
2616     {
2617       if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2618           AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2619           AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2620         {
2621           if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2622                AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2623               (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2624                AOP_SIZE (IC_RIGHT (ic)) <= 2))
2625             {
2626               if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
2627                 {
2628                   /* Swap left and right */
2629                   operand *t = IC_RIGHT (ic);
2630                   IC_RIGHT (ic) = IC_LEFT (ic);
2631                   IC_LEFT (ic) = t;
2632                 }
2633               if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
2634                 {
2635                   fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2636                   emit2 ("add hl,bc");
2637                 }
2638               else
2639                 {
2640                   fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
2641                   fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
2642                   emit2 ("add hl,de");
2643                 }
2644               commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
2645               goto release;
2646             }
2647           else if (size == 4)
2648             {
2649               emit2 ("; WARNING: This add is probably broken.\n");
2650             }
2651         }
2652     }
2653
2654   while (size--)
2655     {
2656       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2657         {
2658           _MoveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2659           if (offset == 0)
2660             emit2 ("add a,%s",
2661                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2662           else
2663             emit2 ("adc a,%s",
2664                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2665         }
2666       else
2667         {
2668           _MoveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2669           if (offset == 0)
2670             emit2 ("add a,%s",
2671                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2672           else
2673             emit2 ("adc a,%s",
2674                    aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2675         }
2676       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2677     }
2678
2679 release:
2680   freeAsmop (IC_LEFT (ic), NULL, ic);
2681   freeAsmop (IC_RIGHT (ic), NULL, ic);
2682   freeAsmop (IC_RESULT (ic), NULL, ic);
2683
2684 }
2685
2686 /*-----------------------------------------------------------------*/
2687 /* genMinusDec :- does subtraction with deccrement if possible     */
2688 /*-----------------------------------------------------------------*/
2689 static bool
2690 genMinusDec (iCode * ic)
2691 {
2692   unsigned int icount;
2693   unsigned int size = getDataSize (IC_RESULT (ic));
2694
2695   /* will try to generate an increment */
2696   /* if the right side is not a literal we cannot */
2697   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2698     return FALSE;
2699
2700   /* if the literal value of the right hand side
2701      is greater than 4 then it is not worth it */
2702   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
2703     return FALSE;
2704
2705   size = getDataSize (IC_RESULT (ic));
2706
2707 #if 0
2708   /* if increment 16 bits in register */
2709   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2710       (size > 1) &&
2711       (icount == 1))
2712     {
2713       symbol *tlbl = newiTempLabel (NULL);
2714       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
2715       emitcode ("jp", "np," LABEL_STR, tlbl->key + 100);
2716
2717       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE));
2718       if (size == 4)
2719         {
2720           wassert (0);
2721         }
2722       emitLabel (tlbl->key + 100);
2723       return TRUE;
2724     }
2725 #endif
2726
2727   /* if decrement 16 bits in register */
2728   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2729       (size > 1) && isPair (AOP (IC_RESULT (ic))))
2730     {
2731       while (icount--)
2732         emitcode ("dec", "%s", getPairName (AOP (IC_RESULT (ic))));
2733       return TRUE;
2734     }
2735
2736   /* If result is a pair */
2737   if (isPair (AOP (IC_RESULT (ic))))
2738     {
2739       movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
2740       movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
2741       while (icount--)
2742         emitcode ("dec", "%s", getPairName (AOP (IC_RESULT (ic))));
2743       return TRUE;
2744     }
2745
2746   /* if the sizes are greater than 1 then we cannot */
2747   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2748       AOP_SIZE (IC_LEFT (ic)) > 1)
2749     return FALSE;
2750
2751   /* we can if the aops of the left & result match or if they are in
2752      registers and the registers are the same */
2753   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2754     {
2755       while (icount--)
2756         emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
2757       return TRUE;
2758     }
2759
2760   return FALSE;
2761 }
2762
2763 /*-----------------------------------------------------------------*/
2764 /* genMinus - generates code for subtraction                       */
2765 /*-----------------------------------------------------------------*/
2766 static void
2767 genMinus (iCode * ic)
2768 {
2769   int size, offset = 0;
2770   unsigned long lit = 0L;
2771
2772   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2773   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
2774   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
2775
2776   /* special cases :- */
2777   /* if both left & right are in bit space */
2778   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2779       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2780     {
2781       wassert (0);
2782       goto release;
2783     }
2784
2785   /* if I can do an decrement instead of subtract then GOOD for ME */
2786   if (genMinusDec (ic) == TRUE)
2787     goto release;
2788
2789   size = getDataSize (IC_RESULT (ic));
2790
2791   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2792     {
2793     }
2794   else
2795     {
2796       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
2797       lit = -(long) lit;
2798     }
2799
2800   /* Same logic as genPlus */
2801   if (IS_GB)
2802     {
2803       if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
2804           AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
2805           AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
2806         {
2807           if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
2808                AOP_SIZE (IC_RIGHT (ic)) == 2) &&
2809               (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
2810                AOP_SIZE (IC_RIGHT (ic)) <= 2))
2811             {
2812               PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
2813               PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
2814
2815               if (left == PAIR_INVALID && right == PAIR_INVALID)
2816                 {
2817                   left = PAIR_DE;
2818                   right = PAIR_HL;
2819                 }
2820               else if (right == PAIR_INVALID)
2821                 right = PAIR_DE;
2822               else if (left == PAIR_INVALID)
2823                 left = PAIR_DE;
2824
2825               fetchPair (left, AOP (IC_LEFT (ic)));
2826               /* Order is important.  Right may be HL */
2827               fetchPair (right, AOP (IC_RIGHT (ic)));
2828
2829               emit2 ("ld a,%s", _pairs[left].l);
2830               emit2 ("sub a,%s", _pairs[right].l);
2831               emit2 ("ld e,a");
2832               emit2 ("ld a,%s", _pairs[left].h);
2833               emit2 ("sbc a,%s", _pairs[right].h);
2834
2835               aopPut (AOP (IC_RESULT (ic)), "a", 1);
2836               aopPut (AOP (IC_RESULT (ic)), "e", 0);
2837               goto release;
2838             }
2839           else if (size == 4)
2840             {
2841               emit2 ("; WARNING: This sub is probably broken.\n");
2842             }
2843         }
2844     }
2845
2846   /* if literal, add a,#-lit, else normal subb */
2847   while (size--)
2848     {
2849       _MoveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
2850       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2851         {
2852           if (!offset)
2853             emitcode ("sub", "a,%s",
2854                       aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2855           else
2856             emitcode ("sbc", "a,%s",
2857                       aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
2858         }
2859       else
2860         {
2861           /* first add without previous c */
2862           if (!offset)
2863             emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
2864           else
2865             emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
2866         }
2867       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2868     }
2869
2870   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2871       AOP_SIZE (IC_LEFT (ic)) == 3 &&
2872       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2873     wassert (0);
2874
2875 release:
2876   freeAsmop (IC_LEFT (ic), NULL, ic);
2877   freeAsmop (IC_RIGHT (ic), NULL, ic);
2878   freeAsmop (IC_RESULT (ic), NULL, ic);
2879 }
2880
2881 /*-----------------------------------------------------------------*/
2882 /* genMult - generates code for multiplication                     */
2883 /*-----------------------------------------------------------------*/
2884 static void
2885 genMult (iCode * ic)
2886 {
2887   /* Shouldn't occur - all done through function calls */
2888   wassert (0);
2889 }
2890
2891 /*-----------------------------------------------------------------*/
2892 /* genDiv - generates code for division                            */
2893 /*-----------------------------------------------------------------*/
2894 static void
2895 genDiv (iCode * ic)
2896 {
2897   /* Shouldn't occur - all done through function calls */
2898   wassert (0);
2899 }
2900
2901 /*-----------------------------------------------------------------*/
2902 /* genMod - generates code for division                            */
2903 /*-----------------------------------------------------------------*/
2904 static void
2905 genMod (iCode * ic)
2906 {
2907   /* Shouldn't occur - all done through function calls */
2908   wassert (0);
2909 }
2910
2911 /*-----------------------------------------------------------------*/
2912 /* genIfxJump :- will create a jump depending on the ifx           */
2913 /*-----------------------------------------------------------------*/
2914 static void
2915 genIfxJump (iCode * ic, char *jval)
2916 {
2917   symbol *jlbl;
2918   const char *inst;
2919
2920   /* if true label then we jump if condition
2921      supplied is true */
2922   if (IC_TRUE (ic))
2923     {
2924       jlbl = IC_TRUE (ic);
2925       if (!strcmp (jval, "a"))
2926         {
2927           inst = "nz";
2928         }
2929       else if (!strcmp (jval, "c"))
2930         {
2931           inst = "c";
2932         }
2933       else if (!strcmp (jval, "nc"))
2934         {
2935           inst = "nc";
2936         }
2937       else
2938         {
2939           /* The buffer contains the bit on A that we should test */
2940           inst = "nz";
2941         }
2942     }
2943   else
2944     {
2945       /* false label is present */
2946       jlbl = IC_FALSE (ic);
2947       if (!strcmp (jval, "a"))
2948         {
2949           inst = "z";
2950         }
2951       else if (!strcmp (jval, "c"))
2952         {
2953           inst = "nc";
2954         }
2955       else if (!strcmp (jval, "nc"))
2956         {
2957           inst = "c";
2958         }
2959       else
2960         {
2961           /* The buffer contains the bit on A that we should test */
2962           inst = "z";
2963         }
2964     }
2965   /* Z80 can do a conditional long jump */
2966   if (!strcmp (jval, "a"))
2967     {
2968       emitcode ("or", "a,a");
2969     }
2970   else if (!strcmp (jval, "c"))
2971     {
2972     }
2973   else if (!strcmp (jval, "nc"))
2974     {
2975     }
2976   else
2977     {
2978       emitcode ("bit", "%s,a", jval);
2979     }
2980   emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
2981
2982   /* mark the icode as generated */
2983   ic->generated = 1;
2984 }
2985
2986 static const char *
2987 _getPairIdName (PAIR_ID id)
2988 {
2989   return _pairs[id].name;
2990 }
2991
2992 /** Generic compare for > or <
2993  */
2994 static void
2995 genCmp (operand * left, operand * right,
2996         operand * result, iCode * ifx, int sign)
2997 {
2998   int size, offset = 0;
2999   unsigned long lit = 0L;
3000   bool swap_sense = FALSE;
3001
3002   /* if left & right are bit variables */
3003   if (AOP_TYPE (left) == AOP_CRY &&
3004       AOP_TYPE (right) == AOP_CRY)
3005     {
3006       /* Cant happen on the Z80 */
3007       wassert (0);
3008     }
3009   else
3010     {
3011       /* subtract right from left if at the
3012          end the carry flag is set then we know that
3013          left is greater than right */
3014       size = max (AOP_SIZE (left), AOP_SIZE (right));
3015
3016       /* if unsigned char cmp with lit, just compare */
3017       if ((size == 1) &&
3018           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3019         {
3020           emitcode ("ld", "a,%s", aopGet (AOP (left), offset, FALSE));
3021           if (sign)
3022             {
3023               emit2 ("xor a,!immedbyte", 0x80);
3024               emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
3025             }
3026           else
3027             emitcode ("cp", "%s", aopGet (AOP (right), offset, FALSE));
3028         }
3029       else
3030         {
3031           /* Special cases:
3032              On the GB:
3033              If the left or the right is a lit:
3034              Load -lit into HL, add to right via, check sense.
3035            */
3036           if (size == 2 && (AOP_TYPE (right) == AOP_LIT || AOP_TYPE (left) == AOP_LIT))
3037             {
3038               PAIR_ID id = PAIR_DE;
3039               asmop *lit = AOP (right);
3040               asmop *op = AOP (left);
3041               swap_sense = TRUE;
3042
3043               if (AOP_TYPE (left) == AOP_LIT)
3044                 {
3045                   swap_sense = FALSE;
3046                   lit = AOP (left);
3047                   op = AOP (right);
3048                 }
3049               if (sign)
3050                 {
3051                   emit2 ("ld e,%s", aopGet (op, 0, 0));
3052                   emit2 ("ld a,%s", aopGet (op, 1, 0));
3053                   emit2 ("xor a,!immedbyte", 0x80);
3054                   emit2 ("ld d,a");
3055                 }
3056               else
3057                 {
3058                   id = getPairId (op);
3059                   if (id == PAIR_INVALID)
3060                     {
3061                       fetchPair (PAIR_DE, op);
3062                       id = PAIR_DE;
3063                     }
3064                 }
3065               spillPair (PAIR_HL);
3066               emit2 ("ld hl,%s", fetchLitSpecial (lit, TRUE, sign));
3067               emit2 ("add hl,%s", _getPairIdName (id));
3068               goto release;
3069             }
3070           if (AOP_TYPE (right) == AOP_LIT)
3071             {
3072               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3073               /* optimize if(x < 0) or if(x >= 0) */
3074               if (lit == 0L)
3075                 {
3076                   if (!sign)
3077                     {
3078                       /* No sign so it's always false */
3079                       _ClearCarry();
3080                     }
3081                   else
3082                     {
3083                       /* Just load in the top most bit */
3084                       _MoveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
3085                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3086                         {
3087                           genIfxJump (ifx, "7");
3088                           return;
3089                         }
3090                       else
3091                         emitcode ("rlc", "a");
3092                     }
3093                   goto release;
3094                 }
3095             }
3096           if (sign)
3097             {
3098               /* First setup h and l contaning the top most bytes XORed */
3099               bool fDidXor = FALSE;
3100               if (AOP_TYPE (left) == AOP_LIT)
3101                 {
3102                   unsigned long lit = (unsigned long)
3103                   floatFromVal (AOP (left)->aopu.aop_lit);
3104                   emit2 ("ld %s,!immedbyte", _fTmp[0],
3105                          0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3106                 }
3107               else
3108                 {
3109                   emitcode ("ld", "a,%s", aopGet (AOP (left), size - 1, FALSE));
3110                   emit2 ("xor a,!immedbyte", 0x80);
3111                   emitcode ("ld", "%s,a", _fTmp[0]);
3112                   fDidXor = TRUE;
3113                 }
3114               if (AOP_TYPE (right) == AOP_LIT)
3115                 {
3116                   unsigned long lit = (unsigned long)
3117                   floatFromVal (AOP (right)->aopu.aop_lit);
3118                   emit2 ("ld %s,!immedbyte", _fTmp[1],
3119                          0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
3120                 }
3121               else
3122                 {
3123                   emitcode ("ld", "a,%s", aopGet (AOP (right), size - 1, FALSE));
3124                   emit2 ("xor a,!immedbyte", 0x80);
3125                   emitcode ("ld", "%s,a", _fTmp[1]);
3126                   fDidXor = TRUE;
3127                 }
3128               if (!fDidXor)
3129                 _ClearCarry();
3130             }
3131           else
3132             {
3133               _ClearCarry();
3134             }
3135           while (size--)
3136             {
3137               /* Do a long subtract */
3138               if (!sign || size)
3139                 {
3140                   _MoveA (aopGet (AOP (left), offset, FALSE));
3141                 }
3142               if (sign && size == 0)
3143                 {
3144                   emitcode ("ld", "a,%s", _fTmp[0]);
3145                   emitcode ("sbc", "a,%s", _fTmp[1]);
3146                 }
3147               else
3148                 {
3149                   /* Subtract through, propagating the carry */
3150                   emitcode ("sbc", "a,%s ; 2", aopGet (AOP (right), offset++, FALSE));
3151                 }
3152             }
3153         }
3154     }
3155
3156 release:
3157   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3158     {
3159       outBitCLong (result, swap_sense);
3160     }
3161   else
3162     {
3163       /* if the result is used in the next
3164          ifx conditional branch then generate
3165          code a little differently */
3166       if (ifx)
3167         genIfxJump (ifx, swap_sense ? "nc" : "c");
3168       else
3169         outBitCLong (result, swap_sense);
3170       /* leave the result in acc */
3171     }
3172 }
3173
3174 /*-----------------------------------------------------------------*/
3175 /* genCmpGt :- greater than comparison                             */
3176 /*-----------------------------------------------------------------*/
3177 static void
3178 genCmpGt (iCode * ic, iCode * ifx)
3179 {
3180   operand *left, *right, *result;
3181   sym_link *letype, *retype;
3182   int sign;
3183
3184   left = IC_LEFT (ic);
3185   right = IC_RIGHT (ic);
3186   result = IC_RESULT (ic);
3187
3188   letype = getSpec (operandType (left));
3189   retype = getSpec (operandType (right));
3190   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3191   /* assign the amsops */
3192   aopOp (left, ic, FALSE, FALSE);
3193   aopOp (right, ic, FALSE, FALSE);
3194   aopOp (result, ic, TRUE, FALSE);
3195
3196   genCmp (right, left, result, ifx, sign);
3197
3198   freeAsmop (left, NULL, ic);
3199   freeAsmop (right, NULL, ic);
3200   freeAsmop (result, NULL, ic);
3201 }
3202
3203 /*-----------------------------------------------------------------*/
3204 /* genCmpLt - less than comparisons                                */
3205 /*-----------------------------------------------------------------*/
3206 static void
3207 genCmpLt (iCode * ic, iCode * ifx)
3208 {
3209   operand *left, *right, *result;
3210   sym_link *letype, *retype;
3211   int sign;
3212
3213   left = IC_LEFT (ic);
3214   right = IC_RIGHT (ic);
3215   result = IC_RESULT (ic);
3216
3217   letype = getSpec (operandType (left));
3218   retype = getSpec (operandType (right));
3219   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3220
3221   /* assign the amsops */
3222   aopOp (left, ic, FALSE, FALSE);
3223   aopOp (right, ic, FALSE, FALSE);
3224   aopOp (result, ic, TRUE, FALSE);
3225
3226   genCmp (left, right, result, ifx, sign);
3227
3228   freeAsmop (left, NULL, ic);
3229   freeAsmop (right, NULL, ic);
3230   freeAsmop (result, NULL, ic);
3231 }
3232
3233 /*-----------------------------------------------------------------*/
3234 /* gencjneshort - compare and jump if not equal                    */
3235 /*-----------------------------------------------------------------*/
3236 static void
3237 gencjneshort (operand * left, operand * right, symbol * lbl)
3238 {
3239   int size = max (AOP_SIZE (left), AOP_SIZE (right));
3240   int offset = 0;
3241   unsigned long lit = 0L;
3242
3243   /* Swap the left and right if it makes the computation easier */
3244   if (AOP_TYPE (left) == AOP_LIT)
3245     {
3246       operand *t = right;
3247       right = left;
3248       left = t;
3249     }
3250
3251   if (AOP_TYPE (right) == AOP_LIT)
3252     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3253
3254   /* if the right side is a literal then anything goes */
3255   if (AOP_TYPE (right) == AOP_LIT &&
3256       AOP_TYPE (left) != AOP_DIR)
3257     {
3258       if (lit == 0)
3259         {
3260           emitcode ("ld", "a,%s", aopGet (AOP (left), offset, FALSE));
3261           if (size > 1)
3262             {
3263               size--;
3264               offset++;
3265               while (size--)
3266                 {
3267                   emitcode ("or", "a,%s", aopGet (AOP (left), offset, FALSE));
3268                 }
3269             }
3270           else
3271             {
3272               emitcode ("or", "a,a");
3273             }
3274           emit2 ("jp nz,!tlabel", lbl->key + 100);
3275         }
3276       else
3277         {
3278           while (size--)
3279             {
3280               emitcode ("ld", "a,%s ; 2", aopGet (AOP (left), offset, FALSE));
3281               if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
3282                 emitcode ("or", "a,a");
3283               else
3284                 emitcode ("cp", "a,%s", aopGet (AOP (right), offset, FALSE));
3285               emit2 ("jp nz,!tlabel", lbl->key + 100);
3286               offset++;
3287             }
3288         }
3289     }
3290   /* if the right side is in a register or in direct space or
3291      if the left is a pointer register & right is not */
3292   else if (AOP_TYPE (right) == AOP_REG ||
3293            AOP_TYPE (right) == AOP_DIR ||
3294            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
3295     {
3296       while (size--)
3297         {
3298           _MoveA (aopGet (AOP (left), offset, FALSE));
3299           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3300               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3301             /* PENDING */
3302             emit2 ("jp nz,!tlabel", lbl->key + 100);
3303           else
3304             {
3305               emitcode ("cp", "%s ; 4", aopGet (AOP (right), offset, FALSE));
3306               emit2 ("jp nz,!tlabel", lbl->key + 100);
3307             }
3308           offset++;
3309         }
3310     }
3311   else
3312     {
3313       /* right is a pointer reg need both a & b */
3314       /* PENDING: is this required? */
3315       while (size--)
3316         {
3317           _MoveA (aopGet (AOP (right), offset, FALSE));
3318           emitcode ("cp", "%s ; 5", aopGet (AOP (left), offset, FALSE));
3319           emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
3320           offset++;
3321         }
3322     }
3323 }
3324
3325 /*-----------------------------------------------------------------*/
3326 /* gencjne - compare and jump if not equal                         */
3327 /*-----------------------------------------------------------------*/
3328 static void
3329 gencjne (operand * left, operand * right, symbol * lbl)
3330 {
3331   symbol *tlbl = newiTempLabel (NULL);
3332
3333   gencjneshort (left, right, lbl);
3334
3335   /* PENDING: ?? */
3336   emit2 ("ld a,!one");
3337   emit2 ("!shortjp !tlabel", tlbl->key + 100);
3338   emitLabel (lbl->key + 100);
3339   emitcode ("xor", "a,a");
3340   emitLabel (tlbl->key + 100);
3341 }
3342
3343 /*-----------------------------------------------------------------*/
3344 /* genCmpEq - generates code for equal to                          */
3345 /*-----------------------------------------------------------------*/
3346 static void
3347 genCmpEq (iCode * ic, iCode * ifx)
3348 {
3349   operand *left, *right, *result;
3350
3351   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3352   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3353   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3354
3355   emit2("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
3356
3357   /* Swap operands if it makes the operation easier. ie if:
3358      1.  Left is a literal.
3359    */
3360   if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3361     {
3362       operand *t = IC_RIGHT (ic);
3363       IC_RIGHT (ic) = IC_LEFT (ic);
3364       IC_LEFT (ic) = t;
3365     }
3366
3367   if (ifx && !AOP_SIZE (result))
3368     {
3369       symbol *tlbl;
3370       /* if they are both bit variables */
3371       if (AOP_TYPE (left) == AOP_CRY &&
3372           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3373         {
3374           wassert (0);
3375         }
3376       else
3377         {
3378           tlbl = newiTempLabel (NULL);
3379           gencjneshort (left, right, tlbl);
3380           if (IC_TRUE (ifx))
3381             {
3382               emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
3383               emitLabel (tlbl->key + 100);
3384             }
3385           else
3386             {
3387               /* PENDING: do this better */
3388               symbol *lbl = newiTempLabel (NULL);
3389               emit2 ("!shortjp !tlabel", lbl->key + 100);
3390               emitLabel (tlbl->key + 100);
3391               emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
3392               emitLabel (lbl->key + 100);
3393             }
3394         }
3395       /* mark the icode as generated */
3396       ifx->generated = 1;
3397       goto release;
3398     }
3399
3400   /* if they are both bit variables */
3401   if (AOP_TYPE (left) == AOP_CRY &&
3402       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3403     {
3404       wassert (0);
3405     }
3406   else
3407     {
3408       gencjne (left, right, newiTempLabel (NULL));
3409       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3410         {
3411           wassert (0);
3412         }
3413       if (ifx)
3414         {
3415           genIfxJump (ifx, "a");
3416           goto release;
3417         }
3418       /* if the result is used in an arithmetic operation
3419          then put the result in place */
3420       if (AOP_TYPE (result) != AOP_CRY)
3421         {
3422           outAcc (result);
3423         }
3424       /* leave the result in acc */
3425     }
3426
3427 release:
3428   freeAsmop (left, NULL, ic);
3429   freeAsmop (right, NULL, ic);
3430   freeAsmop (result, NULL, ic);
3431 }
3432
3433 /*-----------------------------------------------------------------*/
3434 /* ifxForOp - returns the icode containing the ifx for operand     */
3435 /*-----------------------------------------------------------------*/
3436 static iCode *
3437 ifxForOp (operand * op, iCode * ic)
3438 {
3439   /* if true symbol then needs to be assigned */
3440   if (IS_TRUE_SYMOP (op))
3441     return NULL;
3442
3443   /* if this has register type condition and
3444      the next instruction is ifx with the same operand
3445      and live to of the operand is upto the ifx only then */
3446   if (ic->next &&
3447       ic->next->op == IFX &&
3448       IC_COND (ic->next)->key == op->key &&
3449       OP_SYMBOL (op)->liveTo <= ic->next->seq)
3450     return ic->next;
3451
3452   return NULL;
3453 }
3454
3455 /*-----------------------------------------------------------------*/
3456 /* genAndOp - for && operation                                     */
3457 /*-----------------------------------------------------------------*/
3458 static void
3459 genAndOp (iCode * ic)
3460 {
3461   operand *left, *right, *result;
3462   symbol *tlbl;
3463
3464   /* note here that && operations that are in an if statement are
3465      taken away by backPatchLabels only those used in arthmetic
3466      operations remain */
3467   aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3468   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3469   aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3470
3471   /* if both are bit variables */
3472   if (AOP_TYPE (left) == AOP_CRY &&
3473       AOP_TYPE (right) == AOP_CRY)
3474     {
3475       wassert (0);
3476     }
3477   else
3478     {
3479       tlbl = newiTempLabel (NULL);
3480       toBoolean (left);
3481       emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
3482       toBoolean (right);
3483       emitLabel (tlbl->key + 100);
3484       outBitAcc (result);
3485     }
3486
3487   freeAsmop (left, NULL, ic);
3488   freeAsmop (right, NULL, ic);
3489   freeAsmop (result, NULL, ic);
3490 }
3491
3492 /*-----------------------------------------------------------------*/
3493 /* genOrOp - for || operation                                      */
3494 /*-----------------------------------------------------------------*/
3495 static void
3496 genOrOp (iCode * ic)
3497 {
3498   operand *left, *right, *result;
3499   symbol *tlbl;
3500
3501   /* note here that || operations that are in an
3502      if statement are taken away by backPatchLabels
3503      only those used in arthmetic operations remain */
3504   aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
3505   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
3506   aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
3507
3508   /* if both are bit variables */
3509   if (AOP_TYPE (left) == AOP_CRY &&
3510       AOP_TYPE (right) == AOP_CRY)
3511     {
3512       wassert (0);
3513     }
3514   else
3515     {
3516       tlbl = newiTempLabel (NULL);
3517       toBoolean (left);
3518       emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3519       toBoolean (right);
3520       emitLabel (tlbl->key + 100);
3521       outBitAcc (result);
3522     }
3523
3524   freeAsmop (left, NULL, ic);
3525   freeAsmop (right, NULL, ic);
3526   freeAsmop (result, NULL, ic);
3527 }
3528
3529 /*-----------------------------------------------------------------*/
3530 /* isLiteralBit - test if lit == 2^n                               */
3531 /*-----------------------------------------------------------------*/
3532 int
3533 isLiteralBit (unsigned long lit)
3534 {
3535   unsigned long pw[32] =
3536   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
3537    0x100L, 0x200L, 0x400L, 0x800L,
3538    0x1000L, 0x2000L, 0x4000L, 0x8000L,
3539    0x10000L, 0x20000L, 0x40000L, 0x80000L,
3540    0x100000L, 0x200000L, 0x400000L, 0x800000L,
3541    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
3542    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
3543   int idx;
3544
3545   for (idx = 0; idx < 32; idx++)
3546     if (lit == pw[idx])
3547       return idx + 1;
3548   return 0;
3549 }
3550
3551 /*-----------------------------------------------------------------*/
3552 /* jmpTrueOrFalse -                                                */
3553 /*-----------------------------------------------------------------*/
3554 static void
3555 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
3556 {
3557   // ugly but optimized by peephole
3558   if (IC_TRUE (ic))
3559     {
3560       symbol *nlbl = newiTempLabel (NULL);
3561       emit2 ("jp !tlabel", nlbl->key + 100);
3562       emitLabel (tlbl->key + 100);
3563       emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
3564       emitLabel (nlbl->key + 100);
3565     }
3566   else
3567     {
3568       emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
3569       emitLabel (tlbl->key + 100);
3570     }
3571   ic->generated = 1;
3572 }
3573
3574 /*-----------------------------------------------------------------*/
3575 /* genAnd  - code for and                                          */
3576 /*-----------------------------------------------------------------*/
3577 static void
3578 genAnd (iCode * ic, iCode * ifx)
3579 {
3580   operand *left, *right, *result;
3581   int size, offset = 0;
3582   unsigned long lit = 0L;
3583   int bytelit = 0;
3584
3585   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3586   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3587   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3588
3589 #ifdef DEBUG_TYPE
3590   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
3591             AOP_TYPE (result),
3592             AOP_TYPE (left), AOP_TYPE (right));
3593   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
3594             AOP_SIZE (result),
3595             AOP_SIZE (left), AOP_SIZE (right));
3596 #endif
3597
3598   /* if left is a literal & right is not then exchange them */
3599   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3600       AOP_NEEDSACC (left))
3601     {
3602       operand *tmp = right;
3603       right = left;
3604       left = tmp;
3605     }
3606
3607   /* if result = right then exchange them */
3608   if (sameRegs (AOP (result), AOP (right)))
3609     {
3610       operand *tmp = right;
3611       right = left;
3612       left = tmp;
3613     }
3614
3615   /* if right is bit then exchange them */
3616   if (AOP_TYPE (right) == AOP_CRY &&
3617       AOP_TYPE (left) != AOP_CRY)
3618     {
3619       operand *tmp = right;
3620       right = left;
3621       left = tmp;
3622     }
3623   if (AOP_TYPE (right) == AOP_LIT)
3624     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3625
3626   size = AOP_SIZE (result);
3627
3628   if (AOP_TYPE (left) == AOP_CRY)
3629     {
3630       wassert (0);
3631       goto release;
3632     }
3633
3634   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
3635   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
3636   if ((AOP_TYPE (right) == AOP_LIT) &&
3637       (AOP_TYPE (result) == AOP_CRY) &&
3638       (AOP_TYPE (left) != AOP_CRY))
3639     {
3640       int posbit = isLiteralBit (lit);
3641       /* left &  2^n */
3642       if (posbit)
3643         {
3644           posbit--;
3645           _MoveA (aopGet (AOP (left), posbit >> 3, FALSE));
3646           // bit = left & 2^n
3647           if (size)
3648             {
3649               wassert (0);
3650               emitcode ("mov", "c,acc.%d", posbit & 0x07);
3651             }
3652           // if(left &  2^n)
3653           else
3654             {
3655               if (ifx)
3656                 {
3657                   sprintf (buffer, "%d", posbit & 0x07);
3658                   genIfxJump (ifx, buffer);
3659                 }
3660               else
3661                 {
3662                   wassert (0);
3663                 }
3664               goto release;
3665             }
3666         }
3667       else
3668         {
3669           symbol *tlbl = newiTempLabel (NULL);
3670           int sizel = AOP_SIZE (left);
3671           if (size)
3672             {
3673               wassert (0);
3674               emitcode ("setb", "c");
3675             }
3676           while (sizel--)
3677             {
3678               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
3679                 {
3680                   _MoveA (aopGet (AOP (left), offset, FALSE));
3681                   // byte ==  2^n ?
3682                   if ((posbit = isLiteralBit (bytelit)) != 0)
3683                     {
3684                       wassert (0);
3685                       emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
3686                     }
3687                   else
3688                     {
3689                       if (bytelit != 0x0FFL)
3690                         emitcode ("and", "a,%s",
3691                                   aopGet (AOP (right), offset, FALSE));
3692                       else
3693                         /* For the flags */
3694                         emit2 ("or a,a");
3695                       emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
3696                     }
3697                 }
3698               offset++;
3699             }
3700           // bit = left & literal
3701           if (size)
3702             {
3703               emitcode ("clr", "c");
3704               emit2 ("!tlabeldef", tlbl->key + 100);
3705             }
3706           // if(left & literal)
3707           else
3708             {
3709               if (ifx)
3710                 jmpTrueOrFalse (ifx, tlbl);
3711               goto release;
3712             }
3713         }
3714       outBitC (result);
3715       goto release;
3716     }
3717
3718   /* if left is same as result */
3719   if (sameRegs (AOP (result), AOP (left)))
3720     {
3721       for (; size--; offset++)
3722         {
3723           if (AOP_TYPE (right) == AOP_LIT)
3724             {
3725               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3726                 continue;
3727               else
3728                 {
3729                   if (bytelit == 0)
3730                     aopPut (AOP (result), zero, offset);
3731                   else
3732                     {
3733                       _MoveA (aopGet (AOP (left), offset, FALSE));
3734                       emitcode ("and", "a,%s",
3735                                 aopGet (AOP (right), offset, FALSE));
3736                       aopPut (AOP (left), "a", offset);
3737                     }
3738                 }
3739
3740             }
3741           else
3742             {
3743               if (AOP_TYPE (left) == AOP_ACC)
3744                 {
3745                   wassert (0);
3746                 }
3747               else
3748                 {
3749                   _MoveA (aopGet (AOP (left), offset, FALSE));
3750                   emitcode ("and", "a,%s",
3751                             aopGet (AOP (right), offset, FALSE));
3752                   aopPut (AOP (left), "a", offset);
3753                 }
3754             }
3755         }
3756     }
3757   else
3758     {
3759       // left & result in different registers
3760       if (AOP_TYPE (result) == AOP_CRY)
3761         {
3762           wassert (0);
3763         }
3764       else
3765         {
3766           for (; (size--); offset++)
3767             {
3768               // normal case
3769               // result = left & right
3770               if (AOP_TYPE (right) == AOP_LIT)
3771                 {
3772                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
3773                     {
3774                       aopPut (AOP (result),
3775                               aopGet (AOP (left), offset, FALSE),
3776                               offset);
3777                       continue;
3778                     }
3779                   else if (bytelit == 0)
3780                     {
3781                       aopPut (AOP (result), zero, offset);
3782                       continue;
3783                     }
3784                 }
3785               // faster than result <- left, anl result,right
3786               // and better if result is SFR
3787               if (AOP_TYPE (left) == AOP_ACC)
3788                 emitcode ("and", "a,%s", aopGet (AOP (right), offset, FALSE));
3789               else
3790                 {
3791                   _MoveA (aopGet (AOP (left), offset, FALSE));
3792                   emitcode ("and", "a,%s",
3793                             aopGet (AOP (right), offset, FALSE));
3794                 }
3795               aopPut (AOP (result), "a", offset);
3796             }
3797         }
3798
3799     }
3800
3801 release:
3802   freeAsmop (left, NULL, ic);
3803   freeAsmop (right, NULL, ic);
3804   freeAsmop (result, NULL, ic);
3805 }
3806
3807 /*-----------------------------------------------------------------*/
3808 /* genOr  - code for or                                            */
3809 /*-----------------------------------------------------------------*/
3810 static void
3811 genOr (iCode * ic, iCode * ifx)
3812 {
3813   operand *left, *right, *result;
3814   int size, offset = 0;
3815   unsigned long lit = 0L;
3816
3817   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3818   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3819   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3820
3821 #if 1
3822   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
3823             AOP_TYPE (result),
3824             AOP_TYPE (left), AOP_TYPE (right));
3825   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
3826             AOP_SIZE (result),
3827             AOP_SIZE (left), AOP_SIZE (right));
3828 #endif
3829
3830   /* if left is a literal & right is not then exchange them */
3831   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3832       AOP_NEEDSACC (left))
3833     {
3834       operand *tmp = right;
3835       right = left;
3836       left = tmp;
3837     }
3838
3839   /* if result = right then exchange them */
3840   if (sameRegs (AOP (result), AOP (right)))
3841     {
3842       operand *tmp = right;
3843       right = left;
3844       left = tmp;
3845     }
3846
3847   /* if right is bit then exchange them */
3848   if (AOP_TYPE (right) == AOP_CRY &&
3849       AOP_TYPE (left) != AOP_CRY)
3850     {
3851       operand *tmp = right;
3852       right = left;
3853       left = tmp;
3854     }
3855   if (AOP_TYPE (right) == AOP_LIT)
3856     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3857
3858   size = AOP_SIZE (result);
3859
3860   if (AOP_TYPE (left) == AOP_CRY)
3861     {
3862       wassert (0);
3863       goto release;
3864     }
3865
3866   if ((AOP_TYPE (right) == AOP_LIT) &&
3867       (AOP_TYPE (result) == AOP_CRY) &&
3868       (AOP_TYPE (left) != AOP_CRY))
3869     {
3870       wassert (0);
3871       goto release;
3872     }
3873
3874   /* if left is same as result */
3875   if (sameRegs (AOP (result), AOP (left)))
3876     {
3877       for (; size--; offset++)
3878         {
3879           if (AOP_TYPE (right) == AOP_LIT)
3880             {
3881               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
3882                 continue;
3883               else
3884                 {
3885                   _MoveA (aopGet (AOP (left), offset, FALSE));
3886                   emitcode ("or", "a,%s",
3887                             aopGet (AOP (right), offset, FALSE));
3888                   aopPut (AOP (result), "a", offset);
3889                 }
3890             }
3891           else
3892             {
3893               if (AOP_TYPE (left) == AOP_ACC)
3894                 emitcode ("or", "a,%s", aopGet (AOP (right), offset, FALSE));
3895               else
3896                 {
3897                   _MoveA (aopGet (AOP (left), offset, FALSE));
3898                   emitcode ("or", "a,%s",
3899                             aopGet (AOP (right), offset, FALSE));
3900                   aopPut (AOP (result), "a", offset);
3901                 }
3902             }
3903         }
3904     }
3905   else
3906     {
3907       // left & result in different registers
3908       if (AOP_TYPE (result) == AOP_CRY)
3909         {
3910           wassert (0);
3911         }
3912       else
3913         for (; (size--); offset++)
3914           {
3915             // normal case
3916             // result = left & right
3917             if (AOP_TYPE (right) == AOP_LIT)
3918               {
3919                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
3920                   {
3921                     aopPut (AOP (result),
3922                             aopGet (AOP (left), offset, FALSE),
3923                             offset);
3924                     continue;
3925                   }
3926               }
3927             // faster than result <- left, anl result,right
3928             // and better if result is SFR
3929             if (AOP_TYPE (left) == AOP_ACC)
3930               emitcode ("or", "a,%s", aopGet (AOP (right), offset, FALSE));
3931             else
3932               {
3933                 _MoveA (aopGet (AOP (left), offset, FALSE));
3934                 emitcode ("or", "a,%s",
3935                           aopGet (AOP (right), offset, FALSE));
3936               }
3937             aopPut (AOP (result), "a", offset);
3938             /* PENDING: something weird is going on here.  Add exception. */
3939             if (AOP_TYPE (result) == AOP_ACC)
3940               break;
3941           }
3942     }
3943
3944 release:
3945   freeAsmop (left, NULL, ic);
3946   freeAsmop (right, NULL, ic);
3947   freeAsmop (result, NULL, ic);
3948 }
3949
3950 /*-----------------------------------------------------------------*/
3951 /* genXor - code for xclusive or                                   */
3952 /*-----------------------------------------------------------------*/
3953 static void
3954 genXor (iCode * ic, iCode * ifx)
3955 {
3956   operand *left, *right, *result;
3957   int size, offset = 0;
3958   unsigned long lit = 0L;
3959
3960   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
3961   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
3962   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
3963
3964   /* if left is a literal & right is not then exchange them */
3965   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
3966       AOP_NEEDSACC (left))
3967     {
3968       operand *tmp = right;
3969       right = left;
3970       left = tmp;
3971     }
3972
3973   /* if result = right then exchange them */
3974   if (sameRegs (AOP (result), AOP (right)))
3975     {
3976       operand *tmp = right;
3977       right = left;
3978       left = tmp;
3979     }
3980
3981   /* if right is bit then exchange them */
3982   if (AOP_TYPE (right) == AOP_CRY &&
3983       AOP_TYPE (left) != AOP_CRY)
3984     {
3985       operand *tmp = right;
3986       right = left;
3987       left = tmp;
3988     }
3989   if (AOP_TYPE (right) == AOP_LIT)
3990     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3991
3992   size = AOP_SIZE (result);
3993
3994   if (AOP_TYPE (left) == AOP_CRY)
3995     {
3996       wassert (0);
3997       goto release;
3998     }
3999
4000   if ((AOP_TYPE (right) == AOP_LIT) &&
4001       (AOP_TYPE (result) == AOP_CRY) &&
4002       (AOP_TYPE (left) != AOP_CRY))
4003     {
4004       wassert (0);
4005       goto release;
4006     }
4007
4008   /* if left is same as result */
4009   if (sameRegs (AOP (result), AOP (left)))
4010     {
4011       for (; size--; offset++)
4012         {
4013           if (AOP_TYPE (right) == AOP_LIT)
4014             {
4015               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4016                 continue;
4017               else
4018                 {
4019                   _MoveA (aopGet (AOP (right), offset, FALSE));
4020                   emitcode ("xor", "a,%s",
4021                             aopGet (AOP (left), offset, FALSE));
4022                   aopPut (AOP (result), "a", 0);
4023                 }
4024             }
4025           else
4026             {
4027               if (AOP_TYPE (left) == AOP_ACC)
4028                 emitcode ("xor", "a,%s", aopGet (AOP (right), offset, FALSE));
4029               else
4030                 {
4031                   _MoveA (aopGet (AOP (right), offset, FALSE));
4032                   emitcode ("xor", "a,%s",
4033                             aopGet (AOP (left), offset, FALSE));
4034                   aopPut (AOP (result), "a", 0);
4035                 }
4036             }
4037         }
4038     }
4039   else
4040     {
4041       // left & result in different registers
4042       if (AOP_TYPE (result) == AOP_CRY)
4043         {
4044           wassert (0);
4045         }
4046       else
4047         for (; (size--); offset++)
4048           {
4049             // normal case
4050             // result = left & right
4051             if (AOP_TYPE (right) == AOP_LIT)
4052               {
4053                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4054                   {
4055                     aopPut (AOP (result),
4056                             aopGet (AOP (left), offset, FALSE),
4057                             offset);
4058                     continue;
4059                   }
4060               }
4061             // faster than result <- left, anl result,right
4062             // and better if result is SFR
4063             if (AOP_TYPE (left) == AOP_ACC)
4064               emitcode ("xor", "a,%s", aopGet (AOP (right), offset, FALSE));
4065             else
4066               {
4067                 _MoveA (aopGet (AOP (right), offset, FALSE));
4068                 emitcode ("xor", "a,%s",
4069                           aopGet (AOP (left), offset, FALSE));
4070                 aopPut (AOP (result), "a", 0);
4071               }
4072             aopPut (AOP (result), "a", offset);
4073           }
4074     }
4075
4076 release:
4077   freeAsmop (left, NULL, ic);
4078   freeAsmop (right, NULL, ic);
4079   freeAsmop (result, NULL, ic);
4080 }
4081
4082 /*-----------------------------------------------------------------*/
4083 /* genInline - write the inline code out                           */
4084 /*-----------------------------------------------------------------*/
4085 static void
4086 genInline (iCode * ic)
4087 {
4088   char *buffer, *bp, *bp1;
4089
4090   inLine += (!options.asmpeep);
4091
4092   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4093   strcpy (buffer, IC_INLINE (ic));
4094
4095   /* emit each line as a code */
4096   while (*bp)
4097     {
4098       if (*bp == '\n')
4099         {
4100           *bp++ = '\0';
4101           emitcode (bp1, "");
4102           bp1 = bp;
4103         }
4104       else
4105         {
4106           if (*bp == ':')
4107             {
4108               bp++;
4109               *bp = '\0';
4110               bp++;
4111               emitcode (bp1, "");
4112               bp1 = bp;
4113             }
4114           else
4115             bp++;
4116         }
4117     }
4118   if (bp1 != bp)
4119     emitcode (bp1, "");
4120   /*     emitcode("",buffer); */
4121   inLine -= (!options.asmpeep);
4122 }
4123
4124 /*-----------------------------------------------------------------*/
4125 /* genRRC - rotate right with carry                                */
4126 /*-----------------------------------------------------------------*/
4127 static void
4128 genRRC (iCode * ic)
4129 {
4130   wassert (0);
4131 }
4132
4133 /*-----------------------------------------------------------------*/
4134 /* genRLC - generate code for rotate left with carry               */
4135 /*-----------------------------------------------------------------*/
4136 static void
4137 genRLC (iCode * ic)
4138 {
4139   wassert (0);
4140 }
4141
4142 /*-----------------------------------------------------------------*/
4143 /* shiftR2Left2Result - shift right two bytes from left to result  */
4144 /*-----------------------------------------------------------------*/
4145 static void
4146 shiftR2Left2Result (operand * left, int offl,
4147                     operand * result, int offr,
4148                     int shCount, int sign)
4149 {
4150   movLeft2Result (left, offl, result, offr, 0);
4151   movLeft2Result (left, offl + 1, result, offr + 1, 0);
4152
4153   if (sign)
4154     {
4155       wassert (0);
4156     }
4157   else
4158     {
4159       /*  if (AOP(result)->type == AOP_REG) { */
4160       int size = 2;
4161       int offset = 0;
4162       symbol *tlbl, *tlbl1;
4163       const char *l;
4164
4165       tlbl = newiTempLabel (NULL);
4166       tlbl1 = newiTempLabel (NULL);
4167
4168       /* Left is already in result - so now do the shift */
4169       if (shCount > 1)
4170         {
4171           emit2 ("ld a,!immedbyte+1", shCount);
4172           emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4173           emitLabel (tlbl->key + 100);
4174         }
4175
4176       emitcode ("or", "a,a");
4177       offset = size;
4178       while (size--)
4179         {
4180           l = aopGet (AOP (result), --offset, FALSE);
4181           emitcode ("rr", "%s", l);
4182         }
4183       if (shCount > 1)
4184         {
4185           emitLabel (tlbl1->key + 100);
4186           emitcode ("dec", "a");
4187           emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4188         }
4189     }
4190 }
4191
4192 /*-----------------------------------------------------------------*/
4193 /* shiftL2Left2Result - shift left two bytes from left to result   */
4194 /*-----------------------------------------------------------------*/
4195 static void
4196 shiftL2Left2Result (operand * left, int offl,
4197                     operand * result, int offr, int shCount)
4198 {
4199   if (sameRegs (AOP (result), AOP (left)) &&
4200       ((offl + MSB16) == offr))
4201     {
4202       wassert (0);
4203     }
4204   else
4205     {
4206       /* Copy left into result */
4207       movLeft2Result (left, offl, result, offr, 0);
4208       movLeft2Result (left, offl + 1, result, offr + 1, 0);
4209     }
4210   /* PENDING: for now just see if it'll work. */
4211   /*if (AOP(result)->type == AOP_REG) { */
4212   {
4213     int size = 2;
4214     int offset = 0;
4215     symbol *tlbl, *tlbl1;
4216     const char *l;
4217
4218     tlbl = newiTempLabel (NULL);
4219     tlbl1 = newiTempLabel (NULL);
4220
4221     /* Left is already in result - so now do the shift */
4222     if (shCount > 1)
4223       {
4224         emit2 ("ld a,!immedbyte+1", shCount);
4225         emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4226         emitLabel (tlbl->key + 100);
4227       }
4228
4229     emitcode ("or", "a,a");
4230     while (size--)
4231       {
4232         l = aopGet (AOP (result), offset++, FALSE);
4233         emitcode ("rl", "%s", l);
4234       }
4235     if (shCount > 1)
4236       {
4237         emitLabel (tlbl1->key + 100);
4238         emitcode ("dec", "a");
4239         emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4240       }
4241   }
4242 }
4243
4244 /*-----------------------------------------------------------------*/
4245 /* AccRol - rotate left accumulator by known count                 */
4246 /*-----------------------------------------------------------------*/
4247 static void
4248 AccRol (int shCount)
4249 {
4250   shCount &= 0x0007;            // shCount : 0..7
4251
4252   switch (shCount)
4253     {
4254     case 0:
4255       break;
4256     case 1:
4257       emitcode ("rl", "a");
4258       break;
4259     case 2:
4260       emitcode ("rl", "a");
4261       emitcode ("rl", "a");
4262       break;
4263     case 3:
4264       emitcode ("rl", "a");
4265       emitcode ("rl", "a");
4266       emitcode ("rl", "a");
4267       break;
4268     case 4:
4269       emitcode ("rl", "a");
4270       emitcode ("rl", "a");
4271       emitcode ("rl", "a");
4272       emitcode ("rl", "a");
4273       break;
4274     case 5:
4275       emitcode ("rr", "a");
4276       emitcode ("rr", "a");
4277       emitcode ("rr", "a");
4278       break;
4279     case 6:
4280       emitcode ("rr", "a");
4281       emitcode ("rr", "a");
4282       break;
4283     case 7:
4284       emitcode ("rr", "a");
4285       break;
4286     }
4287 }
4288
4289 /*-----------------------------------------------------------------*/
4290 /* AccLsh - left shift accumulator by known count                  */
4291 /*-----------------------------------------------------------------*/
4292 static void
4293 AccLsh (int shCount)
4294 {
4295   if (shCount != 0)
4296     {
4297       if (shCount == 1)
4298         {
4299           emitcode ("add", "a,a");
4300         }
4301       else if (shCount == 2)
4302         {
4303           emitcode ("add", "a,a");
4304           emitcode ("add", "a,a");
4305         }
4306       else
4307         {
4308           /* rotate left accumulator */
4309           AccRol (shCount);
4310           /* and kill the lower order bits */
4311           emit2 ("and a,!immedbyte", SLMask[shCount]);
4312         }
4313     }
4314 }
4315
4316 /*-----------------------------------------------------------------*/
4317 /* shiftL1Left2Result - shift left one byte from left to result    */
4318 /*-----------------------------------------------------------------*/
4319 static void
4320 shiftL1Left2Result (operand * left, int offl,
4321                     operand * result, int offr, int shCount)
4322 {
4323   const char *l;
4324   l = aopGet (AOP (left), offl, FALSE);
4325   _MoveA (l);
4326   /* shift left accumulator */
4327   AccLsh (shCount);
4328   aopPut (AOP (result), "a", offr);
4329 }
4330
4331
4332 /*-----------------------------------------------------------------*/
4333 /* genlshTwo - left shift two bytes by known amount != 0           */
4334 /*-----------------------------------------------------------------*/
4335 static void
4336 genlshTwo (operand * result, operand * left, int shCount)
4337 {
4338   int size = AOP_SIZE (result);
4339
4340   wassert (size == 2);
4341
4342   /* if shCount >= 8 */
4343   if (shCount >= 8)
4344     {
4345       shCount -= 8;
4346       if (size > 1)
4347         {
4348           if (shCount)
4349             {
4350               movLeft2Result (left, LSB, result, MSB16, 0);
4351               aopPut (AOP (result), zero, 0);
4352               shiftL1Left2Result (left, MSB16, result, MSB16, shCount);
4353             }
4354           else
4355             {
4356               movLeft2Result (left, LSB, result, MSB16, 0);
4357               aopPut (AOP (result), zero, 0);
4358             }
4359         }
4360       else
4361         {
4362           aopPut (AOP (result), zero, LSB);
4363         }
4364     }
4365   /*  1 <= shCount <= 7 */
4366   else
4367     {
4368       if (size == 1)
4369         {
4370           wassert (0);
4371         }
4372       else
4373         {
4374           shiftL2Left2Result (left, LSB, result, LSB, shCount);
4375         }
4376     }
4377 }
4378
4379 /*-----------------------------------------------------------------*/
4380 /* genlshOne - left shift a one byte quantity by known count       */
4381 /*-----------------------------------------------------------------*/
4382 static void
4383 genlshOne (operand * result, operand * left, int shCount)
4384 {
4385   shiftL1Left2Result (left, LSB, result, LSB, shCount);
4386 }
4387
4388 /*-----------------------------------------------------------------*/
4389 /* genLeftShiftLiteral - left shifting by known count              */
4390 /*-----------------------------------------------------------------*/
4391 static void
4392 genLeftShiftLiteral (operand * left,
4393                      operand * right,
4394                      operand * result,
4395                      iCode * ic)
4396 {
4397   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4398   int size;
4399
4400   freeAsmop (right, NULL, ic);
4401
4402   aopOp (left, ic, FALSE, FALSE);
4403   aopOp (result, ic, FALSE, FALSE);
4404
4405   size = getSize (operandType (result));
4406
4407 #if VIEW_SIZE
4408   emitcode ("; shift left ", "result %d, left %d", size,
4409             AOP_SIZE (left));
4410 #endif
4411
4412   /* I suppose that the left size >= result size */
4413   if (shCount == 0)
4414     {
4415       wassert (0);
4416     }
4417
4418   else if (shCount >= (size * 8))
4419     while (size--)
4420       aopPut (AOP (result), zero, size);
4421   else
4422     {
4423       switch (size)
4424         {
4425         case 1:
4426           genlshOne (result, left, shCount);
4427           break;
4428         case 2:
4429           genlshTwo (result, left, shCount);
4430           break;
4431         case 4:
4432           wassert (0);
4433           break;
4434         default:
4435           wassert (0);
4436         }
4437     }
4438   freeAsmop (left, NULL, ic);
4439   freeAsmop (result, NULL, ic);
4440 }
4441
4442 /*-----------------------------------------------------------------*/
4443 /* genLeftShift - generates code for left shifting                 */
4444 /*-----------------------------------------------------------------*/
4445 static void
4446 genLeftShift (iCode * ic)
4447 {
4448   int size, offset;
4449   const char *l;
4450   symbol *tlbl, *tlbl1;
4451   operand *left, *right, *result;
4452
4453   right = IC_RIGHT (ic);
4454   left = IC_LEFT (ic);
4455   result = IC_RESULT (ic);
4456
4457   aopOp (right, ic, FALSE, FALSE);
4458
4459   /* if the shift count is known then do it
4460      as efficiently as possible */
4461   if (AOP_TYPE (right) == AOP_LIT)
4462     {
4463       genLeftShiftLiteral (left, right, result, ic);
4464       return;
4465     }
4466
4467   /* shift count is unknown then we have to form a loop get the loop
4468      count in B : Note: we take only the lower order byte since
4469      shifting more that 32 bits make no sense anyway, ( the largest
4470      size of an object can be only 32 bits ) */
4471   emitcode ("ld", "a,%s", aopGet (AOP (right), 0, FALSE));
4472   emitcode ("inc", "a");
4473   freeAsmop (right, NULL, ic);
4474   aopOp (left, ic, FALSE, FALSE);
4475   aopOp (result, ic, FALSE, FALSE);
4476
4477   /* now move the left to the result if they are not the
4478      same */
4479 #if 1
4480   if (!sameRegs (AOP (left), AOP (result)))
4481     {
4482
4483       size = AOP_SIZE (result);
4484       offset = 0;
4485       while (size--)
4486         {
4487           l = aopGet (AOP (left), offset, FALSE);
4488           aopPut (AOP (result), l, offset);
4489           offset++;
4490         }
4491     }
4492 #else
4493   size = AOP_SIZE (result);
4494   offset = 0;
4495   while (size--)
4496     {
4497       l = aopGet (AOP (left), offset, FALSE);
4498       aopPut (AOP (result), l, offset);
4499       offset++;
4500     }
4501 #endif
4502
4503
4504   tlbl = newiTempLabel (NULL);
4505   size = AOP_SIZE (result);
4506   offset = 0;
4507   tlbl1 = newiTempLabel (NULL);
4508
4509   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4510   emitLabel (tlbl->key + 100);
4511   l = aopGet (AOP (result), offset, FALSE);
4512   emitcode ("or", "a,a");
4513   while (size--)
4514     {
4515       l = aopGet (AOP (result), offset++, FALSE);
4516       emitcode ("rl", "%s", l);
4517     }
4518   emitLabel (tlbl1->key + 100);
4519   emitcode ("dec", "a");
4520   emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4521
4522   freeAsmop (left, NULL, ic);
4523   freeAsmop (result, NULL, ic);
4524 }
4525
4526 /*-----------------------------------------------------------------*/
4527 /* genrshOne - left shift two bytes by known amount != 0           */
4528 /*-----------------------------------------------------------------*/
4529 static void
4530 genrshOne (operand * result, operand * left, int shCount)
4531 {
4532   /* Errk */
4533   int size = AOP_SIZE (result);
4534   const char *l;
4535
4536   wassert (size == 1);
4537   wassert (shCount < 8);
4538
4539   l = aopGet (AOP (left), 0, FALSE);
4540   if (AOP (result)->type == AOP_REG)
4541     {
4542       aopPut (AOP (result), l, 0);
4543       l = aopGet (AOP (result), 0, FALSE);
4544       while (shCount--)
4545         emitcode ("srl", "%s", l);
4546     }
4547   else
4548     {
4549       _MoveA (l);
4550       while (shCount--)
4551         {
4552           emitcode ("srl", "a");
4553         }
4554       aopPut (AOP (result), "a", 0);
4555     }
4556 }
4557
4558 /*-----------------------------------------------------------------*/
4559 /* AccRsh - right shift accumulator by known count                 */
4560 /*-----------------------------------------------------------------*/
4561 static void
4562 AccRsh (int shCount)
4563 {
4564   if (shCount != 0)
4565     {
4566       /* rotate right accumulator */
4567       AccRol (8 - shCount);
4568       /* and kill the higher order bits */
4569       emit2 ("and a,!immedbyte", SRMask[shCount]);
4570     }
4571 }
4572
4573 /*-----------------------------------------------------------------*/
4574 /* shiftR1Left2Result - shift right one byte from left to result   */
4575 /*-----------------------------------------------------------------*/
4576 static void
4577 shiftR1Left2Result (operand * left, int offl,
4578                     operand * result, int offr,
4579                     int shCount, int sign)
4580 {
4581   _MoveA (aopGet (AOP (left), offl, FALSE));
4582   if (sign)
4583     {
4584       wassert (0);
4585     }
4586   else
4587     {
4588       AccRsh (shCount);
4589     }
4590   aopPut (AOP (result), "a", offr);
4591 }
4592
4593 /*-----------------------------------------------------------------*/
4594 /* genrshTwo - right shift two bytes by known amount != 0          */
4595 /*-----------------------------------------------------------------*/
4596 static void
4597 genrshTwo (operand * result, operand * left,
4598            int shCount, int sign)
4599 {
4600   /* if shCount >= 8 */
4601   if (shCount >= 8)
4602     {
4603       shCount -= 8;
4604       if (shCount)
4605         {
4606           shiftR1Left2Result (left, MSB16, result, LSB,
4607                               shCount, sign);
4608         }
4609       else
4610         {
4611           movLeft2Result (left, MSB16, result, LSB, sign);
4612         }
4613       aopPut (AOP (result), zero, 1);
4614     }
4615   /*  1 <= shCount <= 7 */
4616   else
4617     {
4618       shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
4619     }
4620 }
4621
4622 /*-----------------------------------------------------------------*/
4623 /* genRightShiftLiteral - left shifting by known count              */
4624 /*-----------------------------------------------------------------*/
4625 static void
4626 genRightShiftLiteral (operand * left,
4627                       operand * right,
4628                       operand * result,
4629                       iCode * ic)
4630 {
4631   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
4632   int size;
4633
4634   freeAsmop (right, NULL, ic);
4635
4636   aopOp (left, ic, FALSE, FALSE);
4637   aopOp (result, ic, FALSE, FALSE);
4638
4639   size = getSize (operandType (result));
4640
4641   emitcode ("; shift right ", "result %d, left %d", size,
4642             AOP_SIZE (left));
4643
4644   /* I suppose that the left size >= result size */
4645   if (shCount == 0)
4646     {
4647       wassert (0);
4648     }
4649
4650   else if (shCount >= (size * 8))
4651     while (size--)
4652       aopPut (AOP (result), zero, size);
4653   else
4654     {
4655       switch (size)
4656         {
4657         case 1:
4658           genrshOne (result, left, shCount);
4659           break;
4660         case 2:
4661           /* PENDING: sign support */
4662           genrshTwo (result, left, shCount, FALSE);
4663           break;
4664         case 4:
4665           wassert (0);
4666           break;
4667         default:
4668           wassert (0);
4669         }
4670     }
4671   freeAsmop (left, NULL, ic);
4672   freeAsmop (result, NULL, ic);
4673 }
4674
4675 /*-----------------------------------------------------------------*/
4676 /* genRightShift - generate code for right shifting                */
4677 /*-----------------------------------------------------------------*/
4678 static void
4679 genRightShift (iCode * ic)
4680 {
4681   operand *right, *left, *result;
4682   sym_link *retype;
4683   int size, offset, first = 1;
4684   const char *l;
4685   bool is_signed;
4686
4687   symbol *tlbl, *tlbl1;
4688
4689   /* if signed then we do it the hard way preserve the
4690      sign bit moving it inwards */
4691   retype = getSpec (operandType (IC_RESULT (ic)));
4692
4693   is_signed = !SPEC_USIGN (retype);
4694
4695   /* signed & unsigned types are treated the same : i.e. the
4696      signed is NOT propagated inwards : quoting from the
4697      ANSI - standard : "for E1 >> E2, is equivalent to division
4698      by 2**E2 if unsigned or if it has a non-negative value,
4699      otherwise the result is implementation defined ", MY definition
4700      is that the sign does not get propagated */
4701
4702   right = IC_RIGHT (ic);
4703   left = IC_LEFT (ic);
4704   result = IC_RESULT (ic);
4705
4706   aopOp (right, ic, FALSE, FALSE);
4707
4708   /* if the shift count is known then do it
4709      as efficiently as possible */
4710   if (AOP_TYPE (right) == AOP_LIT)
4711     {
4712       genRightShiftLiteral (left, right, result, ic);
4713       return;
4714     }
4715
4716   aopOp (left, ic, FALSE, FALSE);
4717   aopOp (result, ic, FALSE, FALSE);
4718
4719   /* now move the left to the result if they are not the
4720      same */
4721   if (!sameRegs (AOP (left), AOP (result)) &&
4722       AOP_SIZE (result) > 1)
4723     {
4724
4725       size = AOP_SIZE (result);
4726       offset = 0;
4727       while (size--)
4728         {
4729           l = aopGet (AOP (left), offset, FALSE);
4730           aopPut (AOP (result), l, offset);
4731           offset++;
4732         }
4733     }
4734
4735   emitcode ("ld", "a,%s", aopGet (AOP (right), 0, FALSE));
4736   emitcode ("inc", "a");
4737   freeAsmop (right, NULL, ic);
4738
4739   tlbl = newiTempLabel (NULL);
4740   tlbl1 = newiTempLabel (NULL);
4741   size = AOP_SIZE (result);
4742   offset = size - 1;
4743
4744   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
4745   emitLabel (tlbl->key + 100);
4746   while (size--)
4747     {
4748       l = aopGet (AOP (result), offset--, FALSE);
4749       if (first)
4750         {
4751           if (is_signed)
4752             emitcode ("sra", "%s", l);
4753           else
4754             emitcode ("srl", "%s", l);
4755           first = 0;
4756         }
4757       else
4758         emitcode ("rr", "%s", l);
4759     }
4760   emitLabel (tlbl1->key + 100);
4761   emitcode ("dec", "a");
4762   emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
4763
4764   freeAsmop (left, NULL, ic);
4765   freeAsmop (result, NULL, ic);
4766 }
4767
4768 /*-----------------------------------------------------------------*/
4769 /* genGenPointerGet -  get value from generic pointer space        */
4770 /*-----------------------------------------------------------------*/
4771 static void
4772 genGenPointerGet (operand * left,
4773                   operand * result, iCode * ic)
4774 {
4775   int size, offset;
4776   sym_link *retype = getSpec (operandType (result));
4777   int pair = PAIR_HL;
4778
4779   if (IS_GB)
4780     pair = PAIR_DE;
4781
4782   aopOp (left, ic, FALSE, FALSE);
4783   aopOp (result, ic, FALSE, FALSE);
4784
4785   if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
4786     {
4787       /* Just do it */
4788       if (isPtrPair (AOP (left)))
4789         {
4790           tsprintf (buffer, "!*pair", getPairName (AOP (left)));
4791           aopPut (AOP (result), buffer, 0);
4792         }
4793       else
4794         {
4795           emit2 ("ld a,!*pair", getPairName (AOP (left)));
4796           aopPut (AOP (result), "a", 0);
4797         }
4798       freeAsmop (left, NULL, ic);
4799       goto release;
4800     }
4801
4802   /* For now we always load into IY */
4803   /* if this is remateriazable */
4804   fetchPair (pair, AOP (left));
4805
4806   /* so iy now contains the address */
4807   freeAsmop (left, NULL, ic);
4808
4809   /* if bit then unpack */
4810   if (IS_BITVAR (retype))
4811     {
4812       wassert (0);
4813     }
4814   else
4815     {
4816       size = AOP_SIZE (result);
4817       offset = 0;
4818
4819       while (size--)
4820         {
4821           /* PENDING: make this better */
4822           if (!IS_GB && AOP (result)->type == AOP_REG)
4823             {
4824               aopPut (AOP (result), "!*hl", offset++);
4825             }
4826           else
4827             {
4828               emit2 ("ld a,!*pair", _pairs[pair].name);
4829               aopPut (AOP (result), "a", offset++);
4830             }
4831           if (size)
4832             {
4833               emit2 ("inc %s", _pairs[pair].name);
4834               _G.pairs[pair].offset++;
4835             }
4836         }
4837     }
4838
4839 release:
4840   freeAsmop (result, NULL, ic);
4841 }
4842
4843 /*-----------------------------------------------------------------*/
4844 /* genPointerGet - generate code for pointer get                   */
4845 /*-----------------------------------------------------------------*/
4846 static void
4847 genPointerGet (iCode * ic)
4848 {
4849   operand *left, *result;
4850   sym_link *type, *etype;
4851
4852   left = IC_LEFT (ic);
4853   result = IC_RESULT (ic);
4854
4855   /* depending on the type of pointer we need to
4856      move it to the correct pointer register */
4857   type = operandType (left);
4858   etype = getSpec (type);
4859
4860   genGenPointerGet (left, result, ic);
4861 }
4862
4863 bool
4864 isRegOrLit (asmop * aop)
4865 {
4866   if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
4867     return TRUE;
4868   return FALSE;
4869 }
4870
4871 /*-----------------------------------------------------------------*/
4872 /* genGenPointerSet - stores the value into a pointer location        */
4873 /*-----------------------------------------------------------------*/
4874 static void
4875 genGenPointerSet (operand * right,
4876                   operand * result, iCode * ic)
4877 {
4878   int size, offset;
4879   sym_link *retype = getSpec (operandType (right));
4880   PAIR_ID pairId = PAIR_HL;
4881
4882   aopOp (result, ic, FALSE, FALSE);
4883   aopOp (right, ic, FALSE, FALSE);
4884
4885   if (IS_GB)
4886     pairId = PAIR_DE;
4887
4888   /* Handle the exceptions first */
4889   if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
4890     {
4891       /* Just do it */
4892       const char *l = aopGet (AOP (right), 0, FALSE);
4893       const char *pair = getPairName (AOP (result));
4894       if (canAssignToPtr (l) && isPtr (pair))
4895         {
4896           emit2 ("ld !*pair,%s", pair, l);
4897         }
4898       else
4899         {
4900           _MoveA (l);
4901           emit2 ("ld !*pair,a", pair);
4902         }
4903       goto release;
4904     }
4905
4906   /* if the operand is already in dptr
4907      then we do nothing else we move the value to dptr */
4908   if (AOP_TYPE (result) != AOP_STR)
4909     {
4910       fetchPair (pairId, AOP (result));
4911     }
4912   /* so hl know contains the address */
4913   freeAsmop (result, NULL, ic);
4914
4915   /* if bit then unpack */
4916   if (IS_BITVAR (retype))
4917     {
4918       wassert (0);
4919     }
4920   else
4921     {
4922       size = AOP_SIZE (right);
4923       offset = 0;
4924
4925       while (size--)
4926         {
4927           const char *l = aopGet (AOP (right), offset, FALSE);
4928           if (isRegOrLit (AOP (right)) && !IS_GB)
4929             {
4930               emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
4931             }
4932           else
4933             {
4934               _MoveA (l);
4935               emit2 ("ld !*pair,a", _pairs[pairId].name);
4936             }
4937           if (size)
4938             {
4939               emitcode ("inc", _pairs[pairId].name);
4940               _G.pairs[pairId].offset++;
4941             }
4942           offset++;
4943         }
4944     }
4945 release:
4946   freeAsmop (right, NULL, ic);
4947 }
4948
4949 /*-----------------------------------------------------------------*/
4950 /* genPointerSet - stores the value into a pointer location        */
4951 /*-----------------------------------------------------------------*/
4952 static void
4953 genPointerSet (iCode * ic)
4954 {
4955   operand *right, *result;
4956   sym_link *type, *etype;
4957
4958   right = IC_RIGHT (ic);
4959   result = IC_RESULT (ic);
4960
4961   /* depending on the type of pointer we need to
4962      move it to the correct pointer register */
4963   type = operandType (result);
4964   etype = getSpec (type);
4965
4966   genGenPointerSet (right, result, ic);
4967 }
4968
4969 /*-----------------------------------------------------------------*/
4970 /* genIfx - generate code for Ifx statement                        */
4971 /*-----------------------------------------------------------------*/
4972 static void
4973 genIfx (iCode * ic, iCode * popIc)
4974 {
4975   operand *cond = IC_COND (ic);
4976   int isbit = 0;
4977
4978   aopOp (cond, ic, FALSE, TRUE);
4979
4980   /* get the value into acc */
4981   if (AOP_TYPE (cond) != AOP_CRY)
4982     toBoolean (cond);
4983   else
4984     isbit = 1;
4985   /* the result is now in the accumulator */
4986   freeAsmop (cond, NULL, ic);
4987
4988   /* if there was something to be popped then do it */
4989   if (popIc)
4990     genIpop (popIc);
4991
4992   /* if the condition is  a bit variable */
4993   if (isbit && IS_ITEMP (cond) &&
4994       SPIL_LOC (cond))
4995     genIfxJump (ic, SPIL_LOC (cond)->rname);
4996   else if (isbit && !IS_ITEMP (cond))
4997     genIfxJump (ic, OP_SYMBOL (cond)->rname);
4998   else
4999     genIfxJump (ic, "a");
5000
5001   ic->generated = 1;
5002 }
5003
5004 /*-----------------------------------------------------------------*/
5005 /* genAddrOf - generates code for address of                       */
5006 /*-----------------------------------------------------------------*/
5007 static void
5008 genAddrOf (iCode * ic)
5009 {
5010   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
5011
5012   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5013
5014   /* if the operand is on the stack then we
5015      need to get the stack offset of this
5016      variable */
5017   if (IS_GB)
5018     {
5019       if (sym->onStack)
5020         {
5021           spillCached ();
5022           if (sym->stack <= 0)
5023             {
5024               emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
5025             }
5026           else
5027             {
5028               emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
5029             }
5030           emitcode ("ld", "d,h");
5031           emitcode ("ld", "e,l");
5032         }
5033       else
5034         {
5035           emit2 ("ld de,!hashedstr", sym->rname);
5036         }
5037       aopPut (AOP (IC_RESULT (ic)), "e", 0);
5038       aopPut (AOP (IC_RESULT (ic)), "d", 1);
5039     }
5040   else
5041     {
5042       spillCached ();
5043       if (sym->onStack)
5044         {
5045           /* if it has an offset  then we need to compute it */
5046           if (sym->stack > 0)
5047             emitcode ("ld", "hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
5048           else
5049             emitcode ("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
5050           emitcode ("add", "hl,sp");
5051         }
5052       else
5053         {
5054           emitcode ("ld", "hl,#%s", sym->rname);
5055         }
5056       aopPut (AOP (IC_RESULT (ic)), "l", 0);
5057       aopPut (AOP (IC_RESULT (ic)), "h", 1);
5058     }
5059   freeAsmop (IC_RESULT (ic), NULL, ic);
5060 }
5061
5062 /*-----------------------------------------------------------------*/
5063 /* genAssign - generate code for assignment                        */
5064 /*-----------------------------------------------------------------*/
5065 static void
5066 genAssign (iCode * ic)
5067 {
5068   operand *result, *right;
5069   int size, offset;
5070   unsigned long lit = 0L;
5071
5072   result = IC_RESULT (ic);
5073   right = IC_RIGHT (ic);
5074
5075 #if 1
5076   /* Dont bother assigning if they are the same */
5077   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5078     {
5079       emitcode ("", "; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
5080       return;
5081     }
5082 #endif
5083
5084   aopOp (right, ic, FALSE, FALSE);
5085   aopOp (result, ic, TRUE, FALSE);
5086
5087   /* if they are the same registers */
5088   if (sameRegs (AOP (right), AOP (result)))
5089     {
5090       emitcode ("", "; (registers are the same)");
5091       goto release;
5092     }
5093
5094   /* if the result is a bit */
5095   if (AOP_TYPE (result) == AOP_CRY)
5096     {
5097       wassert (0);
5098     }
5099
5100   /* general case */
5101   size = AOP_SIZE (result);
5102   offset = 0;
5103
5104   if (AOP_TYPE (right) == AOP_LIT)
5105     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5106   if (isPair (AOP (result)))
5107     {
5108       fetchPair (getPairId (AOP (result)), AOP (right));
5109     }
5110   else if ((size > 1) &&
5111            (AOP_TYPE (result) != AOP_REG) &&
5112            (AOP_TYPE (right) == AOP_LIT) &&
5113            !IS_FLOAT (operandType (right)) &&
5114            (lit < 256L))
5115     {
5116       bool fXored = FALSE;
5117       offset = 0;
5118       /* Work from the top down.
5119          Done this way so that we can use the cached copy of 0
5120          in A for a fast clear */
5121       while (size--)
5122         {
5123           if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
5124             {
5125               if (!fXored && size > 1)
5126                 {
5127                   emitcode ("xor", "a,a");
5128                   fXored = TRUE;
5129                 }
5130               if (fXored)
5131                 {
5132                   aopPut (AOP (result), "a", offset);
5133                 }
5134               else
5135                 {
5136                   aopPut (AOP (result), zero, offset);
5137                 }
5138             }
5139           else
5140             aopPut (AOP (result),
5141                     aopGet (AOP (right), offset, FALSE),
5142                     offset);
5143           offset++;
5144         }
5145     }
5146   else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
5147     {
5148       /* Special case.  Load into a and d, then load out. */
5149       _MoveA (aopGet (AOP (right), 0, FALSE));
5150       emitcode ("ld", "e,%s", aopGet (AOP (right), 1, FALSE));
5151       aopPut (AOP (result), "a", 0);
5152       aopPut (AOP (result), "e", 1);
5153     }
5154   else
5155     {
5156       while (size--)
5157         {
5158           /* PENDING: do this check better */
5159           if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
5160             {
5161               _MoveA (aopGet (AOP (right), offset, FALSE));
5162               aopPut (AOP (result), "a", offset);
5163             }
5164           else
5165             aopPut (AOP (result),
5166                     aopGet (AOP (right), offset, FALSE),
5167                     offset);
5168           offset++;
5169         }
5170     }
5171
5172 release:
5173   freeAsmop (right, NULL, ic);
5174   freeAsmop (result, NULL, ic);
5175 }
5176
5177 /*-----------------------------------------------------------------*/
5178 /* genJumpTab - genrates code for jump table                       */
5179 /*-----------------------------------------------------------------*/
5180 static void
5181 genJumpTab (iCode * ic)
5182 {
5183   symbol *jtab;
5184   const char *l;
5185
5186   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
5187   /* get the condition into accumulator */
5188   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
5189   if (!IS_GB)
5190     emitcode ("push", "de");
5191   emitcode ("ld", "e,%s", l);
5192   emit2 ("ld d,!zero");
5193   jtab = newiTempLabel (NULL);
5194   spillCached ();
5195   emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
5196   emitcode ("add", "hl,de");
5197   emitcode ("add", "hl,de");
5198   emitcode ("add", "hl,de");
5199   freeAsmop (IC_JTCOND (ic), NULL, ic);
5200   if (!IS_GB)
5201     emitcode ("pop", "de");
5202   emit2 ("jp !*hl");
5203   emitLabel (jtab->key + 100);
5204   /* now generate the jump labels */
5205   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
5206        jtab = setNextItem (IC_JTLABELS (ic)))
5207     emit2 ("jp !tlabel", jtab->key + 100);
5208 }
5209
5210 /*-----------------------------------------------------------------*/
5211 /* genCast - gen code for casting                                  */
5212 /*-----------------------------------------------------------------*/
5213 static void
5214 genCast (iCode * ic)
5215 {
5216   operand *result = IC_RESULT (ic);
5217   sym_link *ctype = operandType (IC_LEFT (ic));
5218   operand *right = IC_RIGHT (ic);
5219   int size, offset;
5220
5221   /* if they are equivalent then do nothing */
5222   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
5223     return;
5224
5225   aopOp (right, ic, FALSE, FALSE);
5226   aopOp (result, ic, FALSE, FALSE);
5227
5228   /* if the result is a bit */
5229   if (AOP_TYPE (result) == AOP_CRY)
5230     {
5231       wassert (0);
5232     }
5233
5234   /* if they are the same size : or less */
5235   if (AOP_SIZE (result) <= AOP_SIZE (right))
5236     {
5237
5238       /* if they are in the same place */
5239       if (sameRegs (AOP (right), AOP (result)))
5240         goto release;
5241
5242       /* if they in different places then copy */
5243       size = AOP_SIZE (result);
5244       offset = 0;
5245       while (size--)
5246         {
5247           aopPut (AOP (result),
5248                   aopGet (AOP (right), offset, FALSE),
5249                   offset);
5250           offset++;
5251         }
5252       goto release;
5253     }
5254
5255   /* PENDING: should be OK. */
5256 #if 0
5257   /* if the result is of type pointer */
5258   if (IS_PTR (ctype))
5259     {
5260       wassert (0);
5261     }
5262 #endif
5263
5264   /* so we now know that the size of destination is greater
5265      than the size of the source */
5266   /* we move to result for the size of source */
5267   size = AOP_SIZE (right);
5268   offset = 0;
5269   while (size--)
5270     {
5271       aopPut (AOP (result),
5272               aopGet (AOP (right), offset, FALSE),
5273               offset);
5274       offset++;
5275     }
5276
5277   /* now depending on the sign of the destination */
5278   size = AOP_SIZE (result) - AOP_SIZE (right);
5279   /* Unsigned or not an integral type - right fill with zeros */
5280   if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
5281     {
5282       while (size--)
5283         aopPut (AOP (result), zero, offset++);
5284     }
5285   else
5286     {
5287       /* we need to extend the sign :{ */
5288         const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
5289                         FALSE);
5290       _MoveA (l);
5291       emitcode ("", "; genCast: sign extend untested.");
5292       emitcode ("rla", "");
5293       emitcode ("sbc", "a,a");
5294       while (size--)
5295         aopPut (AOP (result), "a", offset++);
5296     }
5297
5298 release:
5299   freeAsmop (right, NULL, ic);
5300   freeAsmop (result, NULL, ic);
5301 }
5302
5303 /*-----------------------------------------------------------------*/
5304 /* genReceive - generate code for a receive iCode                  */
5305 /*-----------------------------------------------------------------*/
5306 static void
5307 genReceive (iCode * ic)
5308 {
5309   if (isOperandInFarSpace (IC_RESULT (ic)) &&
5310       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
5311        IS_TRUE_SYMOP (IC_RESULT (ic))))
5312     {
5313       wassert (0);
5314     }
5315   else
5316     {
5317         // PENDING: HACK
5318         int size;
5319         int i;
5320
5321         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
5322         size = AOP_SIZE(IC_RESULT(ic));
5323
5324         for (i = 0; i < size; i++) {
5325             aopPut(AOP(IC_RESULT(ic)), _fReturn[_G.receiveOffset++], i);
5326         }
5327     }
5328
5329   freeAsmop (IC_RESULT (ic), NULL, ic);
5330 }
5331
5332 /*-----------------------------------------------------------------*/
5333 /* genZ80Code - generate code for Z80 based controllers            */
5334 /*-----------------------------------------------------------------*/
5335 void
5336 genZ80Code (iCode * lic)
5337 {
5338   iCode *ic;
5339   int cln = 0;
5340
5341   /* HACK */
5342   if (IS_GB)
5343     {
5344       _fReturn = _gbz80_return;
5345       _fTmp = _gbz80_return;
5346     }
5347   else
5348     {
5349       _fReturn = _z80_return;
5350       _fTmp = _z80_return;
5351     }
5352   tsprintf (zero, "!zero");
5353
5354   lineHead = lineCurr = NULL;
5355
5356   /* if debug information required */
5357   if (options.debug && currFunc)
5358     {
5359       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
5360       debugLine = 1;
5361       if (IS_STATIC (currFunc->etype))
5362         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
5363       else
5364         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
5365       debugLine = 0;
5366     }
5367
5368   for (ic = lic; ic; ic = ic->next)
5369     {
5370
5371       if (cln != ic->lineno)
5372         {
5373           if (options.debug)
5374             {
5375               debugLine = 1;
5376               emitcode ("", "C$%s$%d$%d$%d ==.",
5377                         FileBaseName (ic->filename), ic->lineno,
5378                         ic->level, ic->block);
5379               debugLine = 0;
5380             }
5381           emitcode (";", "%s %d", ic->filename, ic->lineno);
5382           cln = ic->lineno;
5383         }
5384       /* if the result is marked as
5385          spilt and rematerializable or code for
5386          this has already been generated then
5387          do nothing */
5388       if (resultRemat (ic) || ic->generated)
5389         continue;
5390
5391       /* depending on the operation */
5392       switch (ic->op)
5393         {
5394         case '!':
5395           emitcode ("", "; genNot");
5396           genNot (ic);
5397           break;
5398
5399         case '~':
5400           emitcode ("", "; genCpl");
5401           genCpl (ic);
5402           break;
5403
5404         case UNARYMINUS:
5405           emitcode ("", "; genUminus");
5406           genUminus (ic);
5407           break;
5408
5409         case IPUSH:
5410           emitcode ("", "; genIpush");
5411           genIpush (ic);
5412           break;
5413
5414         case IPOP:
5415           /* IPOP happens only when trying to restore a
5416              spilt live range, if there is an ifx statement
5417              following this pop then the if statement might
5418              be using some of the registers being popped which
5419              would destory the contents of the register so
5420              we need to check for this condition and handle it */
5421           if (ic->next &&
5422               ic->next->op == IFX &&
5423               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
5424             {
5425               emitcode ("", "; genIfx");
5426               genIfx (ic->next, ic);
5427             }
5428           else
5429             {
5430               emitcode ("", "; genIpop");
5431               genIpop (ic);
5432             }
5433           break;
5434
5435         case CALL:
5436           emitcode ("", "; genCall");
5437           genCall (ic);
5438           break;
5439
5440         case PCALL:
5441           emitcode ("", "; genPcall");
5442           genPcall (ic);
5443           break;
5444
5445         case FUNCTION:
5446           emitcode ("", "; genFunction");
5447           genFunction (ic);
5448           break;
5449
5450         case ENDFUNCTION:
5451           emitcode ("", "; genEndFunction");
5452           genEndFunction (ic);
5453           break;
5454
5455         case RETURN:
5456           emitcode ("", "; genRet");
5457           genRet (ic);
5458           break;
5459
5460         case LABEL:
5461           emitcode ("", "; genLabel");
5462           genLabel (ic);
5463           break;
5464
5465         case GOTO:
5466           emitcode ("", "; genGoto");
5467           genGoto (ic);
5468           break;
5469
5470         case '+':
5471           emitcode ("", "; genPlus");
5472           genPlus (ic);
5473           break;
5474
5475         case '-':
5476           emitcode ("", "; genMinus");
5477           genMinus (ic);
5478           break;
5479
5480         case '*':
5481           emitcode ("", "; genMult");
5482           genMult (ic);
5483           break;
5484
5485         case '/':
5486           emitcode ("", "; genDiv");
5487           genDiv (ic);
5488           break;
5489
5490         case '%':
5491           emitcode ("", "; genMod");
5492           genMod (ic);
5493           break;
5494
5495         case '>':
5496           emitcode ("", "; genCmpGt");
5497           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
5498           break;
5499
5500         case '<':
5501           emitcode ("", "; genCmpLt");
5502           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
5503           break;
5504
5505         case LE_OP:
5506         case GE_OP:
5507         case NE_OP:
5508
5509           /* note these two are xlated by algebraic equivalence
5510              during parsing SDCC.y */
5511           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5512                   "got '>=' or '<=' shouldn't have come here");
5513           break;
5514
5515         case EQ_OP:
5516           emitcode ("", "; genCmpEq");
5517           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
5518           break;
5519
5520         case AND_OP:
5521           emitcode ("", "; genAndOp");
5522           genAndOp (ic);
5523           break;
5524
5525         case OR_OP:
5526           emitcode ("", "; genOrOp");
5527           genOrOp (ic);
5528           break;
5529
5530         case '^':
5531           emitcode ("", "; genXor");
5532           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
5533           break;
5534
5535         case '|':
5536           emitcode ("", "; genOr");
5537           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
5538           break;
5539
5540         case BITWISEAND:
5541           emitcode ("", "; genAnd");
5542           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
5543           break;
5544
5545         case INLINEASM:
5546           emitcode ("", "; genInline");
5547           genInline (ic);
5548           break;
5549
5550         case RRC:
5551           emitcode ("", "; genRRC");
5552           genRRC (ic);
5553           break;
5554
5555         case RLC:
5556           emitcode ("", "; genRLC");
5557           genRLC (ic);
5558           break;
5559
5560         case GETHBIT:
5561           emitcode ("", "; genHBIT");
5562           wassert (0);
5563
5564         case LEFT_OP:
5565           emitcode ("", "; genLeftShift");
5566           genLeftShift (ic);
5567           break;
5568
5569         case RIGHT_OP:
5570           emitcode ("", "; genRightShift");
5571           genRightShift (ic);
5572           break;
5573
5574         case GET_VALUE_AT_ADDRESS:
5575           emitcode ("", "; genPointerGet");
5576           genPointerGet (ic);
5577           break;
5578
5579         case '=':
5580
5581           if (POINTER_SET (ic))
5582             {
5583               emitcode ("", "; genAssign (pointer)");
5584               genPointerSet (ic);
5585             }
5586           else
5587             {
5588               emitcode ("", "; genAssign");
5589               genAssign (ic);
5590             }
5591           break;
5592
5593         case IFX:
5594           emitcode ("", "; genIfx");
5595           genIfx (ic, NULL);
5596           break;
5597
5598         case ADDRESS_OF:
5599           emitcode ("", "; genAddrOf");
5600           genAddrOf (ic);
5601           break;
5602
5603         case JUMPTABLE:
5604           emitcode ("", "; genJumpTab");
5605           genJumpTab (ic);
5606           break;
5607
5608         case CAST:
5609           emitcode ("", "; genCast");
5610           genCast (ic);
5611           break;
5612
5613         case RECEIVE:
5614           emitcode ("", "; genReceive");
5615           genReceive (ic);
5616           break;
5617
5618         case SEND:
5619           emitcode ("", "; addSet");
5620           addSet (&sendSet, ic);
5621           break;
5622
5623         default:
5624           ic = ic;
5625           /*      piCode(ic,stdout); */
5626
5627         }
5628     }
5629
5630
5631   /* now we are ready to call the
5632      peep hole optimizer */
5633   if (!options.nopeep)
5634     peepHole (&lineHead);
5635
5636   /* This is unfortunate */
5637   /* now do the actual printing */
5638   {
5639     FILE *fp = codeOutFile;
5640     if (isInHome () && codeOutFile == code->oFile)
5641       codeOutFile = home->oFile;
5642     printLine (lineHead, codeOutFile);
5643     if (_G.flush_statics)
5644       {
5645         flushStatics ();
5646         _G.flush_statics = 0;
5647       }
5648     codeOutFile = fp;
5649   }
5650 }