fix genDjnz to handle data in far space
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for DS80C390
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31
32 #include <common.h>
33 #include "ralloc.h"
34 #include "gen.h"
35 #include "SDCCglobl.h"
36 #include "newalloc.h"
37
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
40 #else
41 #ifdef HAVE_ENDIAN_H
42 #include <endian.h>
43 #else
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
47 #endif
48 #endif
49 #endif
50
51 char *aopLiteral (value * val, int offset);
52
53 /* this is the down and dirty file with all kinds of
54    kludgy & hacky stuff. This is what it is all about
55    CODE GENERATION for a specific MCU . some of the
56    routines may be reusable, will have to see */
57
58 static char *zero = "#0x00";
59 static char *one = "#0x01";
60 static char *spname;
61
62 #define D(x) x
63
64 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
65 static char *fReturn[] =
66 {"dpl", "dph", "dpx", "b", "a"};
67 static char *accUse[] =
68 {"a", "b"};
69
70 static short rbank = -1;
71
72 static struct
73   {
74     short r0Pushed;
75     short r1Pushed;
76     short accInUse;
77     short inLine;
78     short debugLine;
79     short nRegsSaved;
80     set *sendSet;
81   }
82 _G;
83
84 static void saverbank (int, iCode *, bool);
85
86 #define RESULTONSTACK(x) \
87                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
88                          IC_RESULT(x)->aop->type == AOP_STK )
89
90 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
91 #define MOVA(x) { char *_mova_tmp = strdup(x); \
92                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
93                  { \
94                     emitcode("mov","a,%s",_mova_tmp); \
95                  } \
96                  free(_mova_tmp); \
97                 }
98 #define CLRC    emitcode("clr","c")
99 #define SETC    emitcode("setb","c")
100
101 // A scratch register which will be used to hold
102 // result bytes from operands in far space via DPTR2.
103 #define DP2_RESULT_REG  "ap"
104
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
107
108 static unsigned char SLMask[] =
109 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
110  0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] =
112 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113  0x07, 0x03, 0x01, 0x00};
114
115 #define LSB     0
116 #define MSB16   1
117 #define MSB24   2
118 #define MSB32   3
119
120 /*-----------------------------------------------------------------*/
121 /* emitcode - writes the code into a file : for now it is simple    */
122 /*-----------------------------------------------------------------*/
123 static void
124 emitcode (char *inst, char *fmt,...)
125 {
126   va_list ap;
127   char lb[MAX_INLINEASM];
128   char *lbp = lb;
129
130   va_start (ap, fmt);
131
132   if (inst && *inst)
133     {
134       if (fmt && *fmt)
135         sprintf (lb, "%s\t", inst);
136       else
137         sprintf (lb, "%s", inst);
138       vsprintf (lb + (strlen (lb)), fmt, ap);
139     }
140   else
141     vsprintf (lb, fmt, ap);
142
143   while (isspace (*lbp))
144     lbp++;
145
146   if (lbp && *lbp)
147     lineCurr = (lineCurr ?
148                 connectLine (lineCurr, newLineNode (lb)) :
149                 (lineHead = newLineNode (lb)));
150   lineCurr->isInline = _G.inLine;
151   lineCurr->isDebug = _G.debugLine;
152   va_end (ap);
153 }
154
155 /*-----------------------------------------------------------------*/
156 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
157 /*-----------------------------------------------------------------*/
158 static regs *
159 getFreePtr (iCode * ic, asmop ** aopp, bool result)
160 {
161   bool r0iu = FALSE, r1iu = FALSE;
162   bool r0ou = FALSE, r1ou = FALSE;
163
164   /* the logic: if r0 & r1 used in the instruction
165      then we are in trouble otherwise */
166
167   /* first check if r0 & r1 are used by this
168      instruction, in which case we are in trouble */
169   if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
170       (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
171     {
172       goto endOfWorld;
173     }
174
175   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
176   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
177
178   /* if no usage of r0 then return it */
179   if (!r0iu && !r0ou)
180     {
181       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
182       (*aopp)->type = AOP_R0;
183
184       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
185     }
186
187   /* if no usage of r1 then return it */
188   if (!r1iu && !r1ou)
189     {
190       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
191       (*aopp)->type = AOP_R1;
192
193       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
194     }
195
196   /* now we know they both have usage */
197   /* if r0 not used in this instruction */
198   if (!r0iu)
199     {
200       /* push it if not already pushed */
201       if (!_G.r0Pushed)
202         {
203           emitcode ("push", "%s",
204                     ds390_regWithIdx (R0_IDX)->dname);
205           _G.r0Pushed++;
206         }
207
208       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
209       (*aopp)->type = AOP_R0;
210
211       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
212     }
213
214   /* if r1 not used then */
215
216   if (!r1iu)
217     {
218       /* push it if not already pushed */
219       if (!_G.r1Pushed)
220         {
221           emitcode ("push", "%s",
222                     ds390_regWithIdx (R1_IDX)->dname);
223           _G.r1Pushed++;
224         }
225
226       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
227       (*aopp)->type = AOP_R1;
228       return ds390_regWithIdx (R1_IDX);
229     }
230
231 endOfWorld:
232   /* I said end of world but not quite end of world yet */
233   /* if this is a result then we can push it on the stack */
234   if (result)
235     {
236       (*aopp)->type = AOP_STK;
237       return NULL;
238     }
239
240   /* other wise this is true end of the world */
241   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
242           "getFreePtr should never reach here");
243   exit (1);
244 }
245
246 /*-----------------------------------------------------------------*/
247 /* newAsmop - creates a new asmOp                                  */
248 /*-----------------------------------------------------------------*/
249 static asmop *
250 newAsmop (short type)
251 {
252   asmop *aop;
253
254   aop = Safe_calloc (1, sizeof (asmop));
255   aop->type = type;
256   return aop;
257 }
258
259 static int _currentDPS;         /* Current processor DPS. */
260 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
261 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
262
263 /*-----------------------------------------------------------------*/
264 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
265 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
266 /* alternate DPTR (DPL1/DPH1/DPX1).          */
267 /*-----------------------------------------------------------------*/
268 static void
269 genSetDPTR (int n)
270 {
271
272   /* If we are doing lazy evaluation, simply note the desired
273    * change, but don't emit any code yet.
274    */
275   if (_lazyDPS)
276     {
277       _desiredDPS = n;
278       return;
279     }
280
281   if (!n)
282     {
283       emitcode ("mov", "dps, #0x00");
284     }
285   else
286     {
287       emitcode ("mov", "dps, #0x01");
288     }
289 }
290
291 /*-----------------------------------------------------------------*/
292 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
293 /*                   */
294 /* Any code that operates on DPTR (NB: not on the individual     */
295 /* components, like DPH) *must* call _flushLazyDPS() before using  */
296 /* DPTR within a lazy DPS evaluation block.        */
297 /*                   */
298 /* Note that aopPut and aopGet already contain the proper calls to */
299 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
300 /* DPS evaluation block.             */
301 /*                   */
302 /* Also, _flushLazyDPS must be called before any flow control      */
303 /* operations that could potentially branch out of the block.    */
304 /*                         */
305 /* Lazy DPS evaluation is simply an optimization (though an      */
306 /* important one), so if in doubt, leave it out.       */
307 /*-----------------------------------------------------------------*/
308 static void
309 _startLazyDPSEvaluation (void)
310 {
311   _currentDPS = 0;
312   _desiredDPS = 0;
313   _lazyDPS = 1;
314 }
315
316 /*-----------------------------------------------------------------*/
317 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
318 /* desired one. Call before using DPTR within a lazy DPS evaluation */
319 /* block.                */
320 /*-----------------------------------------------------------------*/
321 static void
322 _flushLazyDPS (void)
323 {
324   if (!_lazyDPS)
325     {
326       /* nothing to do. */
327       return;
328     }
329
330   if (_desiredDPS != _currentDPS)
331     {
332       if (_desiredDPS)
333         {
334           emitcode ("inc", "dps");
335         }
336       else
337         {
338           emitcode ("dec", "dps");
339         }
340       _currentDPS = _desiredDPS;
341     }
342 }
343
344 /*-----------------------------------------------------------------*/
345 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
346 /*                   */
347 /* Forces us back to the safe state (standard DPTR selected).    */
348 /*-----------------------------------------------------------------*/
349 static void
350 _endLazyDPSEvaluation (void)
351 {
352   if (_currentDPS)
353     {
354       genSetDPTR (0);
355       _flushLazyDPS ();
356     }
357   _lazyDPS = 0;
358   _currentDPS = 0;
359   _desiredDPS = 0;
360 }
361
362
363
364 /*-----------------------------------------------------------------*/
365 /* pointerCode - returns the code for a pointer type               */
366 /*-----------------------------------------------------------------*/
367 static int
368 pointerCode (sym_link * etype)
369 {
370
371   return PTR_TYPE (SPEC_OCLS (etype));
372
373 }
374
375 /*-----------------------------------------------------------------*/
376 /* aopForSym - for a true symbol                                   */
377 /*-----------------------------------------------------------------*/
378 static asmop *
379 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
380 {
381   asmop *aop;
382   memmap *space = SPEC_OCLS (sym->etype);
383
384   /* if already has one */
385   if (sym->aop)
386     return sym->aop;
387
388   /* assign depending on the storage class */
389   /* if it is on the stack or indirectly addressable */
390   /* space we need to assign either r0 or r1 to it   */
391   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
392     {
393       sym->aop = aop = newAsmop (0);
394       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
395       aop->size = getSize (sym->type);
396
397       /* now assign the address of the variable to
398          the pointer register */
399       if (aop->type != AOP_STK)
400         {
401
402           if (sym->onStack)
403             {
404               if (_G.accInUse)
405                 emitcode ("push", "acc");
406
407               emitcode ("mov", "a,_bp");
408               emitcode ("add", "a,#0x%02x",
409                         ((sym->stack < 0) ?
410                          ((char) (sym->stack - _G.nRegsSaved)) :
411                          ((char) sym->stack)) & 0xff);
412               emitcode ("mov", "%s,a",
413                         aop->aopu.aop_ptr->name);
414
415               if (_G.accInUse)
416                 emitcode ("pop", "acc");
417             }
418           else
419             emitcode ("mov", "%s,#%s",
420                       aop->aopu.aop_ptr->name,
421                       sym->rname);
422           aop->paged = space->paged;
423         }
424       else
425         aop->aopu.aop_stk = sym->stack;
426       return aop;
427     }
428
429   if (sym->onStack && options.stack10bit)
430     {
431       /* It's on the 10 bit stack, which is located in
432        * far data space.
433        */
434
435       if (_G.accInUse)
436         emitcode ("push", "acc");
437
438       emitcode ("mov", "a,_bp");
439       emitcode ("add", "a,#0x%02x",
440                 ((sym->stack < 0) ?
441                  ((char) (sym->stack - _G.nRegsSaved)) :
442                  ((char) sym->stack)) & 0xff);
443
444       if (useDP2)
445         {
446           /* genSetDPTR(1); */
447           emitcode ("mov", "dpx1,#0x40");
448           emitcode ("mov", "dph1,#0x00");
449           emitcode ("mov", "dpl1, a");
450           /* genSetDPTR(0); */
451         }
452       else
453         {
454           emitcode ("mov", "dpx,#0x40");
455           emitcode ("mov", "dph,#0x00");
456           emitcode ("mov", "dpl, a");
457         }
458
459       if (_G.accInUse)
460         emitcode ("pop", "acc");
461
462       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
463       aop->size = getSize (sym->type);
464       return aop;
465     }
466
467   /* if in bit space */
468   if (IN_BITSPACE (space))
469     {
470       sym->aop = aop = newAsmop (AOP_CRY);
471       aop->aopu.aop_dir = sym->rname;
472       aop->size = getSize (sym->type);
473       return aop;
474     }
475   /* if it is in direct space */
476   if (IN_DIRSPACE (space))
477     {
478       sym->aop = aop = newAsmop (AOP_DIR);
479       aop->aopu.aop_dir = sym->rname;
480       aop->size = getSize (sym->type);
481       return aop;
482     }
483
484   /* special case for a function */
485   if (IS_FUNC (sym->type))
486     {
487       sym->aop = aop = newAsmop (AOP_IMMD);
488       aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
489       strcpy (aop->aopu.aop_immd, sym->rname);
490       aop->size = FPTRSIZE;
491       return aop;
492     }
493
494   /* only remaining is far space */
495   /* in which case DPTR gets the address */
496   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
497   if (useDP2)
498     {
499       genSetDPTR (1);
500       _flushLazyDPS ();
501       emitcode ("mov", "dptr,#%s", sym->rname);
502       genSetDPTR (0);
503     }
504   else
505     {
506       emitcode ("mov", "dptr,#%s", sym->rname);
507     }
508   aop->size = getSize (sym->type);
509
510   /* if it is in code space */
511   if (IN_CODESPACE (space))
512     aop->code = 1;
513
514   return aop;
515 }
516
517 /*-----------------------------------------------------------------*/
518 /* aopForRemat - rematerialzes an object                           */
519 /*-----------------------------------------------------------------*/
520 static asmop *
521 aopForRemat (symbol * sym)
522 {
523   iCode *ic = sym->rematiCode;
524   asmop *aop = newAsmop (AOP_IMMD);
525
526   int val = 0;
527
528   for (;;)
529     {
530       if (ic->op == '+')
531         val += (int) operandLitValue (IC_RIGHT (ic));
532       else if (ic->op == '-')
533         val -= (int) operandLitValue (IC_RIGHT (ic));
534       else
535         break;
536
537       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
538     }
539
540   if (val)
541     sprintf (buffer, "(%s %c 0x%04x)",
542              OP_SYMBOL (IC_LEFT (ic))->rname,
543              val >= 0 ? '+' : '-',
544              abs (val) & 0xffff);
545   else
546     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
547
548   aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
549   strcpy (aop->aopu.aop_immd, buffer);
550   return aop;
551 }
552
553 /*-----------------------------------------------------------------*/
554 /* regsInCommon - two operands have some registers in common       */
555 /*-----------------------------------------------------------------*/
556 static bool
557 regsInCommon (operand * op1, operand * op2)
558 {
559   symbol *sym1, *sym2;
560   int i;
561
562   /* if they have registers in common */
563   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
564     return FALSE;
565
566   sym1 = OP_SYMBOL (op1);
567   sym2 = OP_SYMBOL (op2);
568
569   if (sym1->nRegs == 0 || sym2->nRegs == 0)
570     return FALSE;
571
572   for (i = 0; i < sym1->nRegs; i++)
573     {
574       int j;
575       if (!sym1->regs[i])
576         continue;
577
578       for (j = 0; j < sym2->nRegs; j++)
579         {
580           if (!sym2->regs[j])
581             continue;
582
583           if (sym2->regs[j] == sym1->regs[i])
584             return TRUE;
585         }
586     }
587
588   return FALSE;
589 }
590
591 /*-----------------------------------------------------------------*/
592 /* operandsEqu - equivalent                                        */
593 /*-----------------------------------------------------------------*/
594 static bool
595 operandsEqu (operand * op1, operand * op2)
596 {
597   symbol *sym1, *sym2;
598
599   /* if they not symbols */
600   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
601     return FALSE;
602
603   sym1 = OP_SYMBOL (op1);
604   sym2 = OP_SYMBOL (op2);
605
606   /* if both are itemps & one is spilt
607      and the other is not then false */
608   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
609       sym1->isspilt != sym2->isspilt)
610     return FALSE;
611
612   /* if they are the same */
613   if (sym1 == sym2)
614     return TRUE;
615
616   if (strcmp (sym1->rname, sym2->rname) == 0)
617     return TRUE;
618
619
620   /* if left is a tmp & right is not */
621   if (IS_ITEMP (op1) &&
622       !IS_ITEMP (op2) &&
623       sym1->isspilt &&
624       (sym1->usl.spillLoc == sym2))
625     return TRUE;
626
627   if (IS_ITEMP (op2) &&
628       !IS_ITEMP (op1) &&
629       sym2->isspilt &&
630       sym1->level > 0 &&
631       (sym2->usl.spillLoc == sym1))
632     return TRUE;
633
634   return FALSE;
635 }
636
637 /*-----------------------------------------------------------------*/
638 /* sameRegs - two asmops have the same registers                   */
639 /*-----------------------------------------------------------------*/
640 static bool
641 sameRegs (asmop * aop1, asmop * aop2)
642 {
643   int i;
644
645   if (aop1 == aop2)
646     {
647       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
648         {
649           return FALSE;
650         }
651       return TRUE;
652     }
653
654   if (aop1->type != AOP_REG ||
655       aop2->type != AOP_REG)
656     return FALSE;
657
658   if (aop1->size != aop2->size)
659     return FALSE;
660
661   for (i = 0; i < aop1->size; i++)
662     if (aop1->aopu.aop_reg[i] !=
663         aop2->aopu.aop_reg[i])
664       return FALSE;
665
666   return TRUE;
667 }
668
669 /*-----------------------------------------------------------------*/
670 /* aopOp - allocates an asmop for an operand  :                    */
671 /*-----------------------------------------------------------------*/
672 static void
673 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
674 {
675   asmop *aop;
676   symbol *sym;
677   int i;
678
679   if (!op)
680     return;
681
682   /* if this a literal */
683   if (IS_OP_LITERAL (op))
684     {
685       op->aop = aop = newAsmop (AOP_LIT);
686       aop->aopu.aop_lit = op->operand.valOperand;
687       aop->size = getSize (operandType (op));
688       return;
689     }
690
691   /* if already has a asmop then continue */
692   if (op->aop)
693     return;
694
695   /* if the underlying symbol has a aop */
696   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
697     {
698       op->aop = OP_SYMBOL (op)->aop;
699       return;
700     }
701
702   /* if this is a true symbol */
703   if (IS_TRUE_SYMOP (op))
704     {
705       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
706       return;
707     }
708
709   /* this is a temporary : this has
710      only four choices :
711      a) register
712      b) spillocation
713      c) rematerialize
714      d) conditional
715      e) can be a return use only */
716
717   sym = OP_SYMBOL (op);
718
719
720   /* if the type is a conditional */
721   if (sym->regType == REG_CND)
722     {
723       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
724       aop->size = 0;
725       return;
726     }
727
728   /* if it is spilt then two situations
729      a) is rematerialize
730      b) has a spill location */
731   if (sym->isspilt || sym->nRegs == 0)
732     {
733
734       /* rematerialize it NOW */
735       if (sym->remat)
736         {
737           sym->aop = op->aop = aop =
738             aopForRemat (sym);
739           aop->size = getSize (sym->type);
740           return;
741         }
742
743       if (sym->accuse)
744         {
745           int i;
746           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
747           aop->size = getSize (sym->type);
748           for (i = 0; i < 2; i++)
749             aop->aopu.aop_str[i] = accUse[i];
750           return;
751         }
752
753       if (sym->ruonly)
754         {
755           int i;
756
757           if (useDP2)
758             {
759               /* a AOP_STR uses DPTR, but DPTR is already in use;
760                * we're just hosed.
761                */
762               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
763             }
764
765           aop = op->aop = sym->aop = newAsmop (AOP_STR);
766           aop->size = getSize (sym->type);
767           for (i = 0; i < (int) fReturnSizeDS390; i++)
768             aop->aopu.aop_str[i] = fReturn[i];
769           return;
770         }
771
772       /* else spill location  */
773       sym->aop = op->aop = aop =
774         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
775       aop->size = getSize (sym->type);
776       return;
777     }
778
779   /* must be in a register */
780   sym->aop = op->aop = aop = newAsmop (AOP_REG);
781   aop->size = sym->nRegs;
782   for (i = 0; i < sym->nRegs; i++)
783     aop->aopu.aop_reg[i] = sym->regs[i];
784 }
785
786 /*-----------------------------------------------------------------*/
787 /* freeAsmop - free up the asmop given to an operand               */
788 /*----------------------------------------------------------------*/
789 static void
790 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
791 {
792   asmop *aop;
793
794   if (!op)
795     aop = aaop;
796   else
797     aop = op->aop;
798
799   if (!aop)
800     return;
801
802   if (aop->freed)
803     goto dealloc;
804
805   aop->freed = 1;
806
807   /* depending on the asmop type only three cases need work AOP_RO
808      , AOP_R1 && AOP_STK */
809   switch (aop->type)
810     {
811     case AOP_R0:
812       if (_G.r0Pushed)
813         {
814           if (pop)
815             {
816               emitcode ("pop", "ar0");
817               _G.r0Pushed--;
818             }
819         }
820       bitVectUnSetBit (ic->rUsed, R0_IDX);
821       break;
822
823     case AOP_R1:
824       if (_G.r1Pushed)
825         {
826           if (pop)
827             {
828               emitcode ("pop", "ar1");
829               _G.r1Pushed--;
830             }
831         }
832       bitVectUnSetBit (ic->rUsed, R1_IDX);
833       break;
834
835     case AOP_STK:
836       {
837         int sz = aop->size;
838         int stk = aop->aopu.aop_stk + aop->size;
839         bitVectUnSetBit (ic->rUsed, R0_IDX);
840         bitVectUnSetBit (ic->rUsed, R1_IDX);
841
842         getFreePtr (ic, &aop, FALSE);
843
844         if (options.stack10bit)
845           {
846             /* I'm not sure what to do here yet... */
847             /* #STUB */
848             fprintf (stderr,
849                      "*** Warning: probably generating bad code for "
850                      "10 bit stack mode.\n");
851           }
852
853         if (stk)
854           {
855             emitcode ("mov", "a,_bp");
856             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
857             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
858           }
859         else
860           {
861             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
862           }
863
864         while (sz--)
865           {
866             emitcode ("pop", "acc");
867             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
868             if (!sz)
869               break;
870             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
871           }
872         op->aop = aop;
873         freeAsmop (op, NULL, ic, TRUE);
874         if (_G.r0Pushed)
875           {
876             emitcode ("pop", "ar0");
877             _G.r0Pushed--;
878           }
879
880         if (_G.r1Pushed)
881           {
882             emitcode ("pop", "ar1");
883             _G.r1Pushed--;
884           }
885       }
886     }
887
888 dealloc:
889   /* all other cases just dealloc */
890   if (op)
891     {
892       op->aop = NULL;
893       if (IS_SYMOP (op))
894         {
895           OP_SYMBOL (op)->aop = NULL;
896           /* if the symbol has a spill */
897           if (SPIL_LOC (op))
898             SPIL_LOC (op)->aop = NULL;
899         }
900     }
901 }
902
903 /*------------------------------------------------------------------*/
904 /* aopGet - for fetching value of the aop                           */
905 /*                    */
906 /* Set canClobberACC if you are sure it is OK to clobber the value  */
907 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
908 /* just less efficient.               */
909 /*------------------------------------------------------------------*/
910
911 static char *
912 aopGet (asmop * aop,
913         int offset,
914         bool bit16,
915         bool dname,
916         bool canClobberACC)
917 {
918   char *s = buffer;
919   char *rs;
920
921   /* offset is greater than
922      size then zero */
923   if (offset > (aop->size - 1) &&
924       aop->type != AOP_LIT)
925     return zero;
926
927   /* depending on type */
928   switch (aop->type)
929     {
930
931     case AOP_R0:
932     case AOP_R1:
933       /* if we need to increment it */
934       while (offset > aop->coff)
935         {
936           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
937           aop->coff++;
938         }
939
940       while (offset < aop->coff)
941         {
942           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
943           aop->coff--;
944         }
945
946       aop->coff = offset;
947       if (aop->paged)
948         {
949           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
950           return (dname ? "acc" : "a");
951         }
952       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
953       rs = Safe_calloc (1, strlen (s) + 1);
954       strcpy (rs, s);
955       return rs;
956
957     case AOP_DPTR:
958     case AOP_DPTR2:
959
960       if (aop->type == AOP_DPTR2)
961         {
962           genSetDPTR (1);
963           if (!canClobberACC)
964             {
965               emitcode ("xch", "a, %s", DP2_RESULT_REG);
966             }
967         }
968
969       _flushLazyDPS ();
970
971       while (offset > aop->coff)
972         {
973           emitcode ("inc", "dptr");
974           aop->coff++;
975         }
976
977       while (offset < aop->coff)
978         {
979           emitcode ("lcall", "__decdptr");
980           aop->coff--;
981         }
982
983       aop->coff = offset;
984       if (aop->code)
985         {
986           emitcode ("clr", "a");
987           emitcode ("movc", "a,@a+dptr");
988         }
989       else
990         {
991           emitcode ("movx", "a,@dptr");
992         }
993
994       if (aop->type == AOP_DPTR2)
995         {
996           genSetDPTR (0);
997           if (!canClobberACC)
998             {
999               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1000               return DP2_RESULT_REG;
1001             }
1002         }
1003       return (dname ? "acc" : "a");
1004
1005     case AOP_IMMD:
1006       if (bit16)
1007         sprintf (s, "#%s", aop->aopu.aop_immd);
1008       else if (offset)
1009         sprintf (s, "#(%s >> %d)",
1010                  aop->aopu.aop_immd,
1011                  offset * 8);
1012       else
1013         sprintf (s, "#%s",
1014                  aop->aopu.aop_immd);
1015       rs = Safe_calloc (1, strlen (s) + 1);
1016       strcpy (rs, s);
1017       return rs;
1018
1019     case AOP_DIR:
1020       if (offset)
1021         sprintf (s, "(%s + %d)",
1022                  aop->aopu.aop_dir,
1023                  offset);
1024       else
1025         sprintf (s, "%s", aop->aopu.aop_dir);
1026       rs = Safe_calloc (1, strlen (s) + 1);
1027       strcpy (rs, s);
1028       return rs;
1029
1030     case AOP_REG:
1031       if (dname)
1032         return aop->aopu.aop_reg[offset]->dname;
1033       else
1034         return aop->aopu.aop_reg[offset]->name;
1035
1036     case AOP_CRY:
1037       emitcode ("clr", "a");
1038       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1039       emitcode ("rlc", "a");
1040       return (dname ? "acc" : "a");
1041
1042     case AOP_ACC:
1043       if (!offset && dname)
1044         return "acc";
1045       return aop->aopu.aop_str[offset];
1046
1047     case AOP_LIT:
1048       return aopLiteral (aop->aopu.aop_lit, offset);
1049
1050     case AOP_STR:
1051       aop->coff = offset;
1052       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1053           dname)
1054         return "acc";
1055
1056       return aop->aopu.aop_str[offset];
1057
1058     }
1059
1060   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1061           "aopget got unsupported aop->type");
1062   exit (1);
1063 }
1064 /*-----------------------------------------------------------------*/
1065 /* aopPut - puts a string for a aop                                */
1066 /*-----------------------------------------------------------------*/
1067 static void
1068 aopPut (asmop * aop, char *s, int offset)
1069 {
1070   char *d = buffer;
1071
1072   if (aop->size && offset > (aop->size - 1))
1073     {
1074       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1075               "aopPut got offset > aop->size");
1076       exit (1);
1077     }
1078
1079   /* will assign value to value */
1080   /* depending on where it is ofcourse */
1081   switch (aop->type)
1082     {
1083     case AOP_DIR:
1084       if (offset)
1085         sprintf (d, "(%s + %d)",
1086                  aop->aopu.aop_dir, offset);
1087       else
1088         sprintf (d, "%s", aop->aopu.aop_dir);
1089
1090       if (strcmp (d, s))
1091         emitcode ("mov", "%s,%s", d, s);
1092
1093       break;
1094
1095     case AOP_REG:
1096       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1097           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1098         {
1099           if (*s == '@' ||
1100               strcmp (s, "r0") == 0 ||
1101               strcmp (s, "r1") == 0 ||
1102               strcmp (s, "r2") == 0 ||
1103               strcmp (s, "r3") == 0 ||
1104               strcmp (s, "r4") == 0 ||
1105               strcmp (s, "r5") == 0 ||
1106               strcmp (s, "r6") == 0 ||
1107               strcmp (s, "r7") == 0)
1108             emitcode ("mov", "%s,%s",
1109                       aop->aopu.aop_reg[offset]->dname, s);
1110           else
1111             emitcode ("mov", "%s,%s",
1112                       aop->aopu.aop_reg[offset]->name, s);
1113         }
1114       break;
1115
1116     case AOP_DPTR:
1117     case AOP_DPTR2:
1118
1119       if (aop->type == AOP_DPTR2)
1120         {
1121           genSetDPTR (1);
1122         }
1123       _flushLazyDPS ();
1124
1125       if (aop->code)
1126         {
1127           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1128                   "aopPut writting to code space");
1129           exit (1);
1130         }
1131
1132       while (offset > aop->coff)
1133         {
1134           aop->coff++;
1135           emitcode ("inc", "dptr");
1136         }
1137
1138       while (offset < aop->coff)
1139         {
1140           aop->coff--;
1141           emitcode ("lcall", "__decdptr");
1142         }
1143
1144       aop->coff = offset;
1145
1146       /* if not in accumulater */
1147       MOVA (s);
1148
1149       emitcode ("movx", "@dptr,a");
1150
1151       if (aop->type == AOP_DPTR2)
1152         {
1153           genSetDPTR (0);
1154         }
1155       break;
1156
1157     case AOP_R0:
1158     case AOP_R1:
1159       while (offset > aop->coff)
1160         {
1161           aop->coff++;
1162           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1163         }
1164       while (offset < aop->coff)
1165         {
1166           aop->coff--;
1167           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1168         }
1169       aop->coff = offset;
1170
1171       if (aop->paged)
1172         {
1173           MOVA (s);
1174           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1175
1176         }
1177       else if (*s == '@')
1178         {
1179           MOVA (s);
1180           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1181         }
1182       else if (strcmp (s, "r0") == 0 ||
1183                strcmp (s, "r1") == 0 ||
1184                strcmp (s, "r2") == 0 ||
1185                strcmp (s, "r3") == 0 ||
1186                strcmp (s, "r4") == 0 ||
1187                strcmp (s, "r5") == 0 ||
1188                strcmp (s, "r6") == 0 ||
1189                strcmp (s, "r7") == 0)
1190         {
1191           char buffer[10];
1192           sprintf (buffer, "a%s", s);
1193           emitcode ("mov", "@%s,%s",
1194                     aop->aopu.aop_ptr->name, buffer);
1195         }
1196       else
1197         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1198
1199       break;
1200
1201     case AOP_STK:
1202       if (strcmp (s, "a") == 0)
1203         emitcode ("push", "acc");
1204       else
1205         emitcode ("push", "%s", s);
1206
1207       break;
1208
1209     case AOP_CRY:
1210       /* if bit variable */
1211       if (!aop->aopu.aop_dir)
1212         {
1213           emitcode ("clr", "a");
1214           emitcode ("rlc", "a");
1215         }
1216       else
1217         {
1218           if (s == zero)
1219             emitcode ("clr", "%s", aop->aopu.aop_dir);
1220           else if (s == one)
1221             emitcode ("setb", "%s", aop->aopu.aop_dir);
1222           else if (!strcmp (s, "c"))
1223             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1224           else
1225             {
1226               if (strcmp (s, "a"))
1227                 {
1228                   MOVA (s);
1229                 }
1230               {
1231                 symbol *lbl = newiTempLabel (NULL);
1232                 emitcode ("clr", "c");
1233                 emitcode ("jz", "%05d$", lbl->key + 100);
1234                 emitcode ("cpl", "c");
1235                 emitcode ("", "%05d$:", lbl->key + 100);
1236                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1237               }
1238             }
1239         }
1240       break;
1241
1242     case AOP_STR:
1243       aop->coff = offset;
1244       if (strcmp (aop->aopu.aop_str[offset], s))
1245         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1246       break;
1247
1248     case AOP_ACC:
1249       aop->coff = offset;
1250       if (!offset && (strcmp (s, "acc") == 0))
1251         break;
1252
1253       if (strcmp (aop->aopu.aop_str[offset], s))
1254         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1255       break;
1256
1257     default:
1258       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1259               "aopPut got unsupported aop->type");
1260       exit (1);
1261     }
1262
1263 }
1264
1265
1266 /*--------------------------------------------------------------------*/
1267 /* reAdjustPreg - points a register back to where it should (coff==0) */
1268 /*--------------------------------------------------------------------*/
1269 static void
1270 reAdjustPreg (asmop * aop)
1271 {
1272   if ((aop->coff==0) || (aop->size <= 1)) {
1273     return;
1274   }
1275
1276   switch (aop->type)
1277     {
1278     case AOP_R0:
1279     case AOP_R1:
1280       while (aop->coff--)
1281         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1282       break;
1283     case AOP_DPTR:
1284     case AOP_DPTR2:
1285       if (aop->type == AOP_DPTR2)
1286         {
1287           genSetDPTR (1);
1288           _flushLazyDPS ();
1289         }
1290       while (aop->coff--)
1291         {
1292           emitcode ("lcall", "__decdptr");
1293         }
1294
1295       if (aop->type == AOP_DPTR2)
1296         {
1297           genSetDPTR (0);
1298         }
1299       break;
1300
1301     }
1302   aop->coff=0;
1303 }
1304
1305 #define AOP(op) op->aop
1306 #define AOP_TYPE(op) AOP(op)->type
1307 #define AOP_SIZE(op) AOP(op)->size
1308 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1309                        AOP_TYPE(x) == AOP_R0))
1310
1311 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1312                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1313                          AOP(x)->paged))
1314
1315 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1316                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1317                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1318
1319 /* Workaround for DS80C390 bug: div ab may return bogus results
1320  * if A is accessed in instruction immediately before the div.
1321  *
1322  * Will be fixed in B4 rev of processor, Dallas claims.
1323  */
1324
1325 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1326     if (!AOP_NEEDSACC(RIGHT))         \
1327     {               \
1328       /* We can load A first, then B, since     \
1329        * B (the RIGHT operand) won't clobber A,   \
1330        * thus avoiding touching A right before the div. \
1331        */             \
1332       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1333       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1334       MOVA(L);            \
1335       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1336     }               \
1337     else              \
1338     {               \
1339       /* Just stuff in a nop after loading A. */    \
1340       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1341       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1342       MOVA(L);            \
1343       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1344     }
1345
1346 /*-----------------------------------------------------------------*/
1347 /* genNotFloat - generates not for float operations              */
1348 /*-----------------------------------------------------------------*/
1349 static void
1350 genNotFloat (operand * op, operand * res)
1351 {
1352   int size, offset;
1353   char *l;
1354   symbol *tlbl;
1355
1356   D (emitcode (";", "genNotFloat ");
1357     );
1358
1359   /* we will put 127 in the first byte of
1360      the result */
1361   aopPut (AOP (res), "#127", 0);
1362   size = AOP_SIZE (op) - 1;
1363   offset = 1;
1364
1365   _startLazyDPSEvaluation ();
1366   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1367   MOVA (l);
1368
1369   while (size--)
1370     {
1371       emitcode ("orl", "a,%s",
1372                 aopGet (op->aop,
1373                         offset++, FALSE, FALSE, FALSE));
1374     }
1375   _endLazyDPSEvaluation ();
1376
1377   tlbl = newiTempLabel (NULL);
1378   aopPut (res->aop, one, 1);
1379   emitcode ("jz", "%05d$", (tlbl->key + 100));
1380   aopPut (res->aop, zero, 1);
1381   emitcode ("", "%05d$:", (tlbl->key + 100));
1382
1383   size = res->aop->size - 2;
1384   offset = 2;
1385   /* put zeros in the rest */
1386   while (size--)
1387     aopPut (res->aop, zero, offset++);
1388 }
1389
1390 /*-----------------------------------------------------------------*/
1391 /* opIsGptr: returns non-zero if the passed operand is       */
1392 /* a generic pointer type.             */
1393 /*-----------------------------------------------------------------*/
1394 static int
1395 opIsGptr (operand * op)
1396 {
1397   sym_link *type = operandType (op);
1398
1399   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1400     {
1401       return 1;
1402     }
1403   return 0;
1404 }
1405
1406 /*-----------------------------------------------------------------*/
1407 /* getDataSize - get the operand data size                         */
1408 /*-----------------------------------------------------------------*/
1409 static int
1410 getDataSize (operand * op)
1411 {
1412   int size;
1413   size = AOP_SIZE (op);
1414   if (size == GPTRSIZE)
1415     {
1416       sym_link *type = operandType (op);
1417       if (IS_GENPTR (type))
1418         {
1419           /* generic pointer; arithmetic operations
1420            * should ignore the high byte (pointer type).
1421            */
1422           size--;
1423         }
1424     }
1425   return size;
1426 }
1427
1428 /*-----------------------------------------------------------------*/
1429 /* outAcc - output Acc                                             */
1430 /*-----------------------------------------------------------------*/
1431 static void
1432 outAcc (operand * result)
1433 {
1434   int size, offset;
1435   size = getDataSize (result);
1436   if (size)
1437     {
1438       aopPut (AOP (result), "a", 0);
1439       size--;
1440       offset = 1;
1441       /* unsigned or positive */
1442       while (size--)
1443         {
1444           aopPut (AOP (result), zero, offset++);
1445         }
1446     }
1447 }
1448
1449 /*-----------------------------------------------------------------*/
1450 /* outBitC - output a bit C                                        */
1451 /*-----------------------------------------------------------------*/
1452 static void
1453 outBitC (operand * result)
1454 {
1455   /* if the result is bit */
1456   if (AOP_TYPE (result) == AOP_CRY)
1457     {
1458       aopPut (AOP (result), "c", 0);
1459     }
1460   else
1461     {
1462       emitcode ("clr", "a");
1463       emitcode ("rlc", "a");
1464       outAcc (result);
1465     }
1466 }
1467
1468 /*-----------------------------------------------------------------*/
1469 /* toBoolean - emit code for orl a,operator(sizeop)                */
1470 /*-----------------------------------------------------------------*/
1471 static void
1472 toBoolean (operand * oper)
1473 {
1474   int size = AOP_SIZE (oper) - 1;
1475   int offset = 1;
1476
1477   /* The generic part of a generic pointer should
1478    * not participate in it's truth value.
1479    *
1480    * i.e. 0x10000000 is zero.
1481    */
1482   if (opIsGptr (oper))
1483     {
1484       D (emitcode (";", "toBoolean: generic ptr special case.");
1485         );
1486       size--;
1487     }
1488
1489   _startLazyDPSEvaluation ();
1490   if (AOP_NEEDSACC (oper))
1491     {
1492       emitcode ("push", "b");
1493       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1494     }
1495   else
1496     {
1497       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1498     }
1499   while (size--)
1500     {
1501       if (AOP_NEEDSACC (oper))
1502         {
1503           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1504         }
1505       else
1506         {
1507           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1508         }
1509     }
1510   _endLazyDPSEvaluation ();
1511
1512   if (AOP_NEEDSACC (oper))
1513     {
1514       emitcode ("mov", "a,b");
1515       emitcode ("pop", "b");
1516     }
1517 }
1518
1519
1520 /*-----------------------------------------------------------------*/
1521 /* genNot - generate code for ! operation                          */
1522 /*-----------------------------------------------------------------*/
1523 static void
1524 genNot (iCode * ic)
1525 {
1526   symbol *tlbl;
1527   sym_link *optype = operandType (IC_LEFT (ic));
1528
1529   D (emitcode (";", "genNot ");
1530     );
1531
1532   /* assign asmOps to operand & result */
1533   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1534   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1535
1536   /* if in bit space then a special case */
1537   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1538     {
1539       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1540       emitcode ("cpl", "c");
1541       outBitC (IC_RESULT (ic));
1542       goto release;
1543     }
1544
1545   /* if type float then do float */
1546   if (IS_FLOAT (optype))
1547     {
1548       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1549       goto release;
1550     }
1551
1552   toBoolean (IC_LEFT (ic));
1553
1554   tlbl = newiTempLabel (NULL);
1555   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1556   emitcode ("", "%05d$:", tlbl->key + 100);
1557   outBitC (IC_RESULT (ic));
1558
1559 release:
1560   /* release the aops */
1561   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1562   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1563 }
1564
1565
1566 /*-----------------------------------------------------------------*/
1567 /* genCpl - generate code for complement                           */
1568 /*-----------------------------------------------------------------*/
1569 static void
1570 genCpl (iCode * ic)
1571 {
1572   int offset = 0;
1573   int size;
1574
1575   D (emitcode (";", "genCpl ");
1576     );
1577
1578
1579   /* assign asmOps to operand & result */
1580   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1581   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1582
1583   /* if both are in bit space then
1584      a special case */
1585   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1586       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1587     {
1588
1589       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1590       emitcode ("cpl", "c");
1591       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1592       goto release;
1593     }
1594
1595   size = AOP_SIZE (IC_RESULT (ic));
1596   _startLazyDPSEvaluation ();
1597   while (size--)
1598     {
1599       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1600       MOVA (l);
1601       emitcode ("cpl", "a");
1602       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1603     }
1604   _endLazyDPSEvaluation ();
1605
1606
1607 release:
1608   /* release the aops */
1609   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1610   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1611 }
1612
1613 /*-----------------------------------------------------------------*/
1614 /* genUminusFloat - unary minus for floating points                */
1615 /*-----------------------------------------------------------------*/
1616 static void
1617 genUminusFloat (operand * op, operand * result)
1618 {
1619   int size, offset = 0;
1620   char *l;
1621   /* for this we just need to flip the
1622      first it then copy the rest in place */
1623   D (emitcode (";", "genUminusFloat");
1624     );
1625
1626   _startLazyDPSEvaluation ();
1627   size = AOP_SIZE (op) - 1;
1628   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1629   MOVA (l);
1630
1631   emitcode ("cpl", "acc.7");
1632   aopPut (AOP (result), "a", 3);
1633
1634   while (size--)
1635     {
1636       aopPut (AOP (result),
1637               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1638               offset);
1639       offset++;
1640     }
1641   _endLazyDPSEvaluation ();
1642 }
1643
1644 /*-----------------------------------------------------------------*/
1645 /* genUminus - unary minus code generation                         */
1646 /*-----------------------------------------------------------------*/
1647 static void
1648 genUminus (iCode * ic)
1649 {
1650   int offset, size;
1651   sym_link *optype, *rtype;
1652
1653   D (emitcode (";", "genUminus ");
1654     );
1655
1656
1657   /* assign asmops */
1658   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1659   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1660
1661   /* if both in bit space then special
1662      case */
1663   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1664       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1665     {
1666
1667       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1668       emitcode ("cpl", "c");
1669       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1670       goto release;
1671     }
1672
1673   optype = operandType (IC_LEFT (ic));
1674   rtype = operandType (IC_RESULT (ic));
1675
1676   /* if float then do float stuff */
1677   if (IS_FLOAT (optype))
1678     {
1679       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1680       goto release;
1681     }
1682
1683   /* otherwise subtract from zero */
1684   size = AOP_SIZE (IC_LEFT (ic));
1685   offset = 0;
1686   _startLazyDPSEvaluation ();
1687   while (size--)
1688     {
1689       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1690       if (!strcmp (l, "a"))
1691         {
1692           if (offset == 0)
1693             SETC;
1694           emitcode ("cpl", "a");
1695           emitcode ("addc", "a,#0");
1696         }
1697       else
1698         {
1699           if (offset == 0)
1700             CLRC;
1701           emitcode ("clr", "a");
1702           emitcode ("subb", "a,%s", l);
1703         }
1704       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1705     }
1706   _endLazyDPSEvaluation ();
1707
1708   /* if any remaining bytes in the result */
1709   /* we just need to propagate the sign   */
1710   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1711     {
1712       emitcode ("rlc", "a");
1713       emitcode ("subb", "a,acc");
1714       while (size--)
1715         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1716     }
1717
1718 release:
1719   /* release the aops */
1720   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1721   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1722 }
1723
1724 /*-----------------------------------------------------------------*/
1725 /* saveRegisters - will look for a call and save the registers     */
1726 /*-----------------------------------------------------------------*/
1727 static void
1728 saveRegisters (iCode * lic)
1729 {
1730   int i;
1731   iCode *ic;
1732   bitVect *rsave;
1733   sym_link *detype;
1734
1735   /* look for call */
1736   for (ic = lic; ic; ic = ic->next)
1737     if (ic->op == CALL || ic->op == PCALL)
1738       break;
1739
1740   if (!ic)
1741     {
1742       fprintf (stderr, "found parameter push with no function call\n");
1743       return;
1744     }
1745
1746   /* if the registers have been saved already then
1747      do nothing */
1748   if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1749     return;
1750
1751   /* find the registers in use at this time
1752      and push them away to safety */
1753   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1754                          ic->rUsed);
1755
1756   ic->regsSaved = 1;
1757   if (options.useXstack)
1758     {
1759       if (bitVectBitValue (rsave, R0_IDX))
1760         emitcode ("mov", "b,r0");
1761       emitcode ("mov", "r0,%s", spname);
1762       for (i = 0; i < ds390_nRegs; i++)
1763         {
1764           if (bitVectBitValue (rsave, i))
1765             {
1766               if (i == R0_IDX)
1767                 emitcode ("mov", "a,b");
1768               else
1769                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1770               emitcode ("movx", "@r0,a");
1771               emitcode ("inc", "r0");
1772             }
1773         }
1774       emitcode ("mov", "%s,r0", spname);
1775       if (bitVectBitValue (rsave, R0_IDX))
1776         emitcode ("mov", "r0,b");
1777     }
1778   else
1779     for (i = 0; i < ds390_nRegs; i++)
1780       {
1781         if (bitVectBitValue (rsave, i))
1782           emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1783       }
1784
1785   detype = getSpec (operandType (IC_LEFT (ic)));
1786   if (detype &&
1787       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1788       IS_ISR (currFunc->etype) &&
1789       !ic->bankSaved)
1790
1791     saverbank (SPEC_BANK (detype), ic, TRUE);
1792
1793 }
1794 /*-----------------------------------------------------------------*/
1795 /* unsaveRegisters - pop the pushed registers                      */
1796 /*-----------------------------------------------------------------*/
1797 static void
1798 unsaveRegisters (iCode * ic)
1799 {
1800   int i;
1801   bitVect *rsave;
1802   /* find the registers in use at this time
1803      and push them away to safety */
1804   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1805                          ic->rUsed);
1806
1807   if (options.useXstack)
1808     {
1809       emitcode ("mov", "r0,%s", spname);
1810       for (i = ds390_nRegs; i >= 0; i--)
1811         {
1812           if (bitVectBitValue (rsave, i))
1813             {
1814               emitcode ("dec", "r0");
1815               emitcode ("movx", "a,@r0");
1816               if (i == R0_IDX)
1817                 emitcode ("mov", "b,a");
1818               else
1819                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1820             }
1821
1822         }
1823       emitcode ("mov", "%s,r0", spname);
1824       if (bitVectBitValue (rsave, R0_IDX))
1825         emitcode ("mov", "r0,b");
1826     }
1827   else
1828     for (i = ds390_nRegs; i >= 0; i--)
1829       {
1830         if (bitVectBitValue (rsave, i))
1831           emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1832       }
1833
1834 }
1835
1836
1837 /*-----------------------------------------------------------------*/
1838 /* pushSide -                */
1839 /*-----------------------------------------------------------------*/
1840 static void
1841 pushSide (operand * oper, int size)
1842 {
1843   int offset = 0;
1844   _startLazyDPSEvaluation ();
1845   while (size--)
1846     {
1847       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1848       if (AOP_TYPE (oper) != AOP_REG &&
1849           AOP_TYPE (oper) != AOP_DIR &&
1850           strcmp (l, "a"))
1851         {
1852           emitcode ("mov", "a,%s", l);
1853           emitcode ("push", "acc");
1854         }
1855       else
1856         emitcode ("push", "%s", l);
1857     }
1858   _endLazyDPSEvaluation ();
1859 }
1860
1861 /*-----------------------------------------------------------------*/
1862 /* assignResultValue -               */
1863 /*-----------------------------------------------------------------*/
1864 static void
1865 assignResultValue (operand * oper)
1866 {
1867   int offset = 0;
1868   int size = AOP_SIZE (oper);
1869
1870   _startLazyDPSEvaluation ();
1871   while (size--)
1872     {
1873       aopPut (AOP (oper), fReturn[offset], offset);
1874       offset++;
1875     }
1876   _endLazyDPSEvaluation ();
1877 }
1878
1879
1880 /*-----------------------------------------------------------------*/
1881 /* genXpush - pushes onto the external stack                       */
1882 /*-----------------------------------------------------------------*/
1883 static void
1884 genXpush (iCode * ic)
1885 {
1886   asmop *aop = newAsmop (0);
1887   regs *r;
1888   int size, offset = 0;
1889
1890   D (emitcode (";", "genXpush ");
1891     );
1892
1893   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1894   r = getFreePtr (ic, &aop, FALSE);
1895
1896
1897   emitcode ("mov", "%s,_spx", r->name);
1898
1899   size = AOP_SIZE (IC_LEFT (ic));
1900   _startLazyDPSEvaluation ();
1901   while (size--)
1902     {
1903
1904       char *l = aopGet (AOP (IC_LEFT (ic)),
1905                         offset++, FALSE, FALSE, TRUE);
1906       MOVA (l);
1907       emitcode ("movx", "@%s,a", r->name);
1908       emitcode ("inc", "%s", r->name);
1909
1910     }
1911   _endLazyDPSEvaluation ();
1912
1913
1914   emitcode ("mov", "_spx,%s", r->name);
1915
1916   freeAsmop (NULL, aop, ic, TRUE);
1917   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1918 }
1919
1920 /*-----------------------------------------------------------------*/
1921 /* genIpush - genrate code for pushing this gets a little complex  */
1922 /*-----------------------------------------------------------------*/
1923 static void
1924 genIpush (iCode * ic)
1925 {
1926   int size, offset = 0;
1927   char *l;
1928
1929   D (emitcode (";", "genIpush ");
1930     );
1931
1932   /* if this is not a parm push : ie. it is spill push
1933      and spill push is always done on the local stack */
1934   if (!ic->parmPush)
1935     {
1936
1937       /* and the item is spilt then do nothing */
1938       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1939         return;
1940
1941       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1942       size = AOP_SIZE (IC_LEFT (ic));
1943       /* push it on the stack */
1944       _startLazyDPSEvaluation ();
1945       while (size--)
1946         {
1947           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1948           if (*l == '#')
1949             {
1950               MOVA (l);
1951               l = "acc";
1952             }
1953           emitcode ("push", "%s ;jwk genIpush: !parm", l);
1954         }
1955       _endLazyDPSEvaluation ();
1956       return;
1957     }
1958
1959   /* this is a paramter push: in this case we call
1960      the routine to find the call and save those
1961      registers that need to be saved */
1962   saveRegisters (ic);
1963
1964   /* if use external stack then call the external
1965      stack pushing routine */
1966   if (options.useXstack)
1967     {
1968       genXpush (ic);
1969       return;
1970     }
1971
1972   /* then do the push */
1973   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1974
1975   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1976   size = AOP_SIZE (IC_LEFT (ic));
1977
1978   _startLazyDPSEvaluation ();
1979   while (size--)
1980     {
1981       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1982       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1983           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1984           strcmp (l, "a"))
1985         {
1986           emitcode ("mov", "a,%s", l);
1987           emitcode ("push", "acc");
1988         }
1989       else
1990         emitcode ("push", "%s ;jwk genIpush", l);
1991     }
1992   _endLazyDPSEvaluation ();
1993
1994   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1995 }
1996
1997 /*-----------------------------------------------------------------*/
1998 /* genIpop - recover the registers: can happen only for spilling   */
1999 /*-----------------------------------------------------------------*/
2000 static void
2001 genIpop (iCode * ic)
2002 {
2003   int size, offset;
2004
2005   D (emitcode (";", "genIpop ");
2006     );
2007
2008
2009   /* if the temp was not pushed then */
2010   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2011     return;
2012
2013   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2014   size = AOP_SIZE (IC_LEFT (ic));
2015   offset = (size - 1);
2016   _startLazyDPSEvaluation ();
2017   while (size--)
2018     {
2019       emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2020                                      FALSE, TRUE, TRUE));
2021     }
2022   _endLazyDPSEvaluation ();
2023
2024   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2025 }
2026
2027 /*-----------------------------------------------------------------*/
2028 /* unsaverbank - restores the resgister bank from stack            */
2029 /*-----------------------------------------------------------------*/
2030 static void
2031 unsaverbank (int bank, iCode * ic, bool popPsw)
2032 {
2033   int i;
2034   asmop *aop;
2035   regs *r = NULL;
2036
2037   if (popPsw)
2038     {
2039       if (options.useXstack)
2040         {
2041           aop = newAsmop (0);
2042           r = getFreePtr (ic, &aop, FALSE);
2043
2044
2045           emitcode ("mov", "%s,_spx", r->name);
2046           emitcode ("movx", "a,@%s", r->name);
2047           emitcode ("mov", "psw,a");
2048           emitcode ("dec", "%s", r->name);
2049
2050         }
2051       else
2052         emitcode ("pop", "psw");
2053     }
2054
2055   for (i = (ds390_nRegs - 1); i >= 0; i--)
2056     {
2057       if (options.useXstack)
2058         {
2059           emitcode ("movx", "a,@%s", r->name);
2060           emitcode ("mov", "(%s+%d),a",
2061                     regs390[i].base, 8 * bank + regs390[i].offset);
2062           emitcode ("dec", "%s", r->name);
2063
2064         }
2065       else
2066         emitcode ("pop", "(%s+%d)",
2067                   regs390[i].base, 8 * bank + regs390[i].offset);
2068     }
2069
2070   if (options.useXstack)
2071     {
2072
2073       emitcode ("mov", "_spx,%s", r->name);
2074       freeAsmop (NULL, aop, ic, TRUE);
2075
2076     }
2077 }
2078
2079 /*-----------------------------------------------------------------*/
2080 /* saverbank - saves an entire register bank on the stack          */
2081 /*-----------------------------------------------------------------*/
2082 static void
2083 saverbank (int bank, iCode * ic, bool pushPsw)
2084 {
2085   int i;
2086   asmop *aop;
2087   regs *r = NULL;
2088
2089   if (options.useXstack)
2090     {
2091
2092       aop = newAsmop (0);
2093       r = getFreePtr (ic, &aop, FALSE);
2094       emitcode ("mov", "%s,_spx", r->name);
2095
2096     }
2097
2098   for (i = 0; i < ds390_nRegs; i++)
2099     {
2100       if (options.useXstack)
2101         {
2102           emitcode ("inc", "%s", r->name);
2103           emitcode ("mov", "a,(%s+%d)",
2104                     regs390[i].base, 8 * bank + regs390[i].offset);
2105           emitcode ("movx", "@%s,a", r->name);
2106         }
2107       else
2108         emitcode ("push", "(%s+%d)",
2109                   regs390[i].base, 8 * bank + regs390[i].offset);
2110     }
2111
2112   if (pushPsw)
2113     {
2114       if (options.useXstack)
2115         {
2116           emitcode ("mov", "a,psw");
2117           emitcode ("movx", "@%s,a", r->name);
2118           emitcode ("inc", "%s", r->name);
2119           emitcode ("mov", "_spx,%s", r->name);
2120           freeAsmop (NULL, aop, ic, TRUE);
2121
2122         }
2123       else
2124         emitcode ("push", "psw");
2125
2126       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2127     }
2128   ic->bankSaved = 1;
2129
2130 }
2131
2132 /*-----------------------------------------------------------------*/
2133 /* genCall - generates a call statement                            */
2134 /*-----------------------------------------------------------------*/
2135 static void
2136 genCall (iCode * ic)
2137 {
2138   sym_link *detype;
2139
2140   D (emitcode (";", "genCall ");
2141     );
2142
2143   /* if caller saves & we have not saved then */
2144   if (!ic->regsSaved)
2145     saveRegisters (ic);
2146
2147   /* if we are calling a function that is not using
2148      the same register bank then we need to save the
2149      destination registers on the stack */
2150   detype = getSpec (operandType (IC_LEFT (ic)));
2151   if (detype &&
2152       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2153       IS_ISR (currFunc->etype) &&
2154       !ic->bankSaved)
2155
2156     saverbank (SPEC_BANK (detype), ic, TRUE);
2157
2158   /* if send set is not empty the assign */
2159   if (_G.sendSet)
2160     {
2161       iCode *sic;
2162
2163       for (sic = setFirstItem (_G.sendSet); sic;
2164            sic = setNextItem (_G.sendSet))
2165         {
2166           int size, offset = 0;
2167
2168           aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2169           size = AOP_SIZE (IC_LEFT (sic));
2170
2171           _startLazyDPSEvaluation ();
2172           while (size--)
2173             {
2174               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2175                                 FALSE, FALSE, TRUE);
2176               if (strcmp (l, fReturn[offset])) {
2177                 genSetDPTR(0);
2178                 _flushLazyDPS();
2179                 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2180                           fReturn[offset],
2181                           l);
2182               }
2183               offset++;
2184             }
2185           _endLazyDPSEvaluation ();
2186           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2187         }
2188       _G.sendSet = NULL;
2189     }
2190   /* make the call */
2191   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2192                             OP_SYMBOL (IC_LEFT (ic))->rname :
2193                             OP_SYMBOL (IC_LEFT (ic))->name));
2194
2195   /* if we need assign a result value */
2196   if ((IS_ITEMP (IC_RESULT (ic)) &&
2197        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2198         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2199       IS_TRUE_SYMOP (IC_RESULT (ic)))
2200     {
2201       if (isOperandInFarSpace (IC_RESULT (ic))
2202           && getSize (operandType (IC_RESULT (ic))) <= 2)
2203         {
2204           int size = getSize (operandType (IC_RESULT (ic)));
2205
2206           /* Special case for 1 or 2 byte return in far space. */
2207           emitcode (";", "Kevin function call abuse #1");
2208
2209           MOVA (fReturn[0]);
2210           if (size > 1)
2211             {
2212               emitcode ("mov", "b,%s", fReturn[1]);
2213             }
2214
2215           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2216           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2217
2218           if (size > 1)
2219             {
2220               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2221             }
2222           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2223         }
2224       else
2225         {
2226           _G.accInUse++;
2227           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2228           _G.accInUse--;
2229
2230           assignResultValue (IC_RESULT (ic));
2231
2232           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2233         }
2234     }
2235
2236   /* adjust the stack for parameters if
2237      required */
2238   if (ic->parmBytes)
2239     {
2240       int i;
2241       if (ic->parmBytes > 3)
2242         {
2243           emitcode ("mov", "a,%s", spname);
2244           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2245           emitcode ("mov", "%s,a", spname);
2246         }
2247       else
2248         for (i = 0; i < ic->parmBytes; i++)
2249           emitcode ("dec", "%s", spname);
2250
2251     }
2252
2253   /* if register bank was saved then pop them */
2254   if (ic->bankSaved)
2255     unsaverbank (SPEC_BANK (detype), ic, TRUE);
2256
2257   /* if we hade saved some registers then unsave them */
2258   if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2259     unsaveRegisters (ic);
2260
2261
2262 }
2263
2264 /*-----------------------------------------------------------------*/
2265 /* genPcall - generates a call by pointer statement                */
2266 /*-----------------------------------------------------------------*/
2267 static void
2268 genPcall (iCode * ic)
2269 {
2270   sym_link *detype;
2271   symbol *rlbl = newiTempLabel (NULL);
2272
2273   D (emitcode (";", "genPcall ");
2274     );
2275
2276
2277   /* if caller saves & we have not saved then */
2278   if (!ic->regsSaved)
2279     saveRegisters (ic);
2280
2281   /* if we are calling a function that is not using
2282      the same register bank then we need to save the
2283      destination registers on the stack */
2284   detype = getSpec (operandType (IC_LEFT (ic)));
2285   if (detype &&
2286       IS_ISR (currFunc->etype) &&
2287       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2288     saverbank (SPEC_BANK (detype), ic, TRUE);
2289
2290
2291   /* push the return address on to the stack */
2292   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2293   emitcode ("push", "acc");
2294   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2295   emitcode ("push", "acc");
2296
2297   if (options.model == MODEL_FLAT24)
2298     {
2299       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2300       emitcode ("push", "acc");
2301     }
2302
2303   /* now push the calling address */
2304   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2305
2306   pushSide (IC_LEFT (ic), FPTRSIZE);
2307
2308   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2309
2310   /* if send set is not empty the assign */
2311   if (_G.sendSet)
2312     {
2313       iCode *sic;
2314
2315       for (sic = setFirstItem (_G.sendSet); sic;
2316            sic = setNextItem (_G.sendSet))
2317         {
2318           int size, offset = 0;
2319
2320           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2321           size = AOP_SIZE (IC_LEFT (sic));
2322           _startLazyDPSEvaluation ();
2323           while (size--)
2324             {
2325               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2326                                 FALSE, FALSE, TRUE);
2327               if (strcmp (l, fReturn[offset]))
2328                 {
2329                   emitcode ("mov", "%s,%s",
2330                             fReturn[offset],
2331                             l);
2332                 }
2333               offset++;
2334             }
2335           _endLazyDPSEvaluation ();
2336           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2337         }
2338       _G.sendSet = NULL;
2339     }
2340
2341   emitcode ("ret", "");
2342   emitcode ("", "%05d$:", (rlbl->key + 100));
2343
2344
2345   /* if we need assign a result value */
2346   if ((IS_ITEMP (IC_RESULT (ic)) &&
2347        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2348         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2349       IS_TRUE_SYMOP (IC_RESULT (ic)))
2350     {
2351
2352       _G.accInUse++;
2353       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2354       _G.accInUse--;
2355
2356       assignResultValue (IC_RESULT (ic));
2357
2358       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2359     }
2360
2361   /* adjust the stack for parameters if
2362      required */
2363   if (ic->parmBytes)
2364     {
2365       int i;
2366       if (ic->parmBytes > 3)
2367         {
2368           emitcode ("mov", "a,%s", spname);
2369           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2370           emitcode ("mov", "%s,a", spname);
2371         }
2372       else
2373         for (i = 0; i < ic->parmBytes; i++)
2374           emitcode ("dec", "%s", spname);
2375
2376     }
2377
2378   /* if register bank was saved then unsave them */
2379   if (detype &&
2380       (SPEC_BANK (currFunc->etype) !=
2381        SPEC_BANK (detype)))
2382     unsaverbank (SPEC_BANK (detype), ic, TRUE);
2383
2384   /* if we hade saved some registers then
2385      unsave them */
2386   if (ic->regsSaved)
2387     unsaveRegisters (ic);
2388
2389 }
2390
2391 /*-----------------------------------------------------------------*/
2392 /* resultRemat - result  is rematerializable                       */
2393 /*-----------------------------------------------------------------*/
2394 static int
2395 resultRemat (iCode * ic)
2396 {
2397   if (SKIP_IC (ic) || ic->op == IFX)
2398     return 0;
2399
2400   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2401     {
2402       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2403       if (sym->remat && !POINTER_SET (ic))
2404         return 1;
2405     }
2406
2407   return 0;
2408 }
2409
2410 #if defined(__BORLANDC__) || defined(_MSC_VER)
2411 #define STRCASECMP stricmp
2412 #else
2413 #define STRCASECMP strcasecmp
2414 #endif
2415
2416 /*-----------------------------------------------------------------*/
2417 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2418 /*-----------------------------------------------------------------*/
2419 static bool
2420 inExcludeList (char *s)
2421 {
2422   int i = 0;
2423
2424   if (options.excludeRegs[i] &&
2425       STRCASECMP (options.excludeRegs[i], "none") == 0)
2426     return FALSE;
2427
2428   for (i = 0; options.excludeRegs[i]; i++)
2429     {
2430       if (options.excludeRegs[i] &&
2431           STRCASECMP (s, options.excludeRegs[i]) == 0)
2432         return TRUE;
2433     }
2434   return FALSE;
2435 }
2436
2437 /*-----------------------------------------------------------------*/
2438 /* genFunction - generated code for function entry                 */
2439 /*-----------------------------------------------------------------*/
2440 static void
2441 genFunction (iCode * ic)
2442 {
2443   symbol *sym;
2444   sym_link *fetype;
2445
2446   D (emitcode (";", "genFunction ");
2447     );
2448
2449   _G.nRegsSaved = 0;
2450   /* create the function header */
2451   emitcode (";", "-----------------------------------------");
2452   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2453   emitcode (";", "-----------------------------------------");
2454
2455   emitcode ("", "%s:", sym->rname);
2456   fetype = getSpec (operandType (IC_LEFT (ic)));
2457
2458   /* if critical function then turn interrupts off */
2459   if (SPEC_CRTCL (fetype))
2460     emitcode ("clr", "ea");
2461
2462   /* here we need to generate the equates for the
2463      register bank if required */
2464   if (SPEC_BANK (fetype) != rbank)
2465     {
2466       int i;
2467
2468       rbank = SPEC_BANK (fetype);
2469       for (i = 0; i < ds390_nRegs; i++)
2470         {
2471           if (strcmp (regs390[i].base, "0") == 0)
2472             emitcode ("", "%s = 0x%02x",
2473                       regs390[i].dname,
2474                       8 * rbank + regs390[i].offset);
2475           else
2476             emitcode ("", "%s = %s + 0x%02x",
2477                       regs390[i].dname,
2478                       regs390[i].base,
2479                       8 * rbank + regs390[i].offset);
2480         }
2481     }
2482
2483   /* if this is an interrupt service routine then
2484      save acc, b, dpl, dph  */
2485   if (IS_ISR (sym->etype))
2486     {
2487
2488       if (!inExcludeList ("acc"))
2489         emitcode ("push", "acc");
2490       if (!inExcludeList ("b"))
2491         emitcode ("push", "b");
2492       if (!inExcludeList ("dpl"))
2493         emitcode ("push", "dpl");
2494       if (!inExcludeList ("dph"))
2495         emitcode ("push", "dph");
2496       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2497         {
2498           emitcode ("push", "dpx");
2499           /* Make sure we're using standard DPTR */
2500           emitcode ("push", "dps");
2501           emitcode ("mov", "dps, #0x00");
2502           if (options.stack10bit)
2503             {
2504               /* This ISR could conceivably use DPTR2. Better save it. */
2505               emitcode ("push", "dpl1");
2506               emitcode ("push", "dph1");
2507               emitcode ("push", "dpx1");
2508               emitcode ("push",  DP2_RESULT_REG);
2509             }
2510         }
2511       /* if this isr has no bank i.e. is going to
2512          run with bank 0 , then we need to save more
2513          registers :-) */
2514       if (!SPEC_BANK (sym->etype))
2515         {
2516
2517           /* if this function does not call any other
2518              function then we can be economical and
2519              save only those registers that are used */
2520           if (!sym->hasFcall)
2521             {
2522               int i;
2523
2524               /* if any registers used */
2525               if (sym->regsUsed)
2526                 {
2527                   /* save the registers used */
2528                   for (i = 0; i < sym->regsUsed->size; i++)
2529                     {
2530                       if (bitVectBitValue (sym->regsUsed, i) ||
2531                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2532                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2533                     }
2534                 }
2535
2536             }
2537           else
2538             {
2539               /* this function has  a function call cannot
2540                  determines register usage so we will have the
2541                  entire bank */
2542               saverbank (0, ic, FALSE);
2543             }
2544         }
2545     }
2546   else
2547     {
2548       /* if callee-save to be used for this function
2549          then save the registers being used in this function */
2550       if (sym->calleeSave)
2551         {
2552           int i;
2553
2554           /* if any registers used */
2555           if (sym->regsUsed)
2556             {
2557               /* save the registers used */
2558               for (i = 0; i < sym->regsUsed->size; i++)
2559                 {
2560                   if (bitVectBitValue (sym->regsUsed, i) ||
2561                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2562                     {
2563                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2564                       _G.nRegsSaved++;
2565                     }
2566                 }
2567             }
2568         }
2569     }
2570
2571   /* set the register bank to the desired value */
2572   if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2573     {
2574       emitcode ("push", "psw");
2575       emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2576     }
2577
2578   if (IS_RENT (sym->etype) || options.stackAuto)
2579     {
2580
2581       if (options.useXstack)
2582         {
2583           emitcode ("mov", "r0,%s", spname);
2584           emitcode ("mov", "a,_bp");
2585           emitcode ("movx", "@r0,a");
2586           emitcode ("inc", "%s", spname);
2587         }
2588       else
2589         {
2590           /* set up the stack */
2591           emitcode ("push", "_bp");     /* save the callers stack  */
2592         }
2593       emitcode ("mov", "_bp,%s", spname);
2594     }
2595
2596   /* adjust the stack for the function */
2597   if (sym->stack)
2598     {
2599
2600       int i = sym->stack;
2601       if (i > 256)
2602         werror (W_STACK_OVERFLOW, sym->name);
2603
2604       if (i > 3 && sym->recvSize < 4)
2605         {
2606
2607           emitcode ("mov", "a,sp");
2608           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2609           emitcode ("mov", "sp,a");
2610
2611         }
2612       else
2613         while (i--)
2614           emitcode ("inc", "sp");
2615     }
2616
2617   if (sym->xstack)
2618     {
2619
2620       emitcode ("mov", "a,_spx");
2621       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2622       emitcode ("mov", "_spx,a");
2623     }
2624
2625 }
2626
2627 /*-----------------------------------------------------------------*/
2628 /* genEndFunction - generates epilogue for functions               */
2629 /*-----------------------------------------------------------------*/
2630 static void
2631 genEndFunction (iCode * ic)
2632 {
2633   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2634
2635   D (emitcode (";", "genEndFunction ");
2636     );
2637
2638   if (IS_RENT (sym->etype) || options.stackAuto)
2639     {
2640       emitcode ("mov", "%s,_bp", spname);
2641     }
2642
2643   /* if use external stack but some variables were
2644      added to the local stack then decrement the
2645      local stack */
2646   if (options.useXstack && sym->stack)
2647     {
2648       emitcode ("mov", "a,sp");
2649       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2650       emitcode ("mov", "sp,a");
2651     }
2652
2653
2654   if ((IS_RENT (sym->etype) || options.stackAuto))
2655     {
2656       if (options.useXstack)
2657         {
2658           emitcode ("mov", "r0,%s", spname);
2659           emitcode ("movx", "a,@r0");
2660           emitcode ("mov", "_bp,a");
2661           emitcode ("dec", "%s", spname);
2662         }
2663       else
2664         {
2665           emitcode ("pop", "_bp");
2666         }
2667     }
2668
2669   /* restore the register bank  */
2670   if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2671     emitcode ("pop", "psw");
2672
2673   if (IS_ISR (sym->etype))
2674     {
2675
2676       /* now we need to restore the registers */
2677       /* if this isr has no bank i.e. is going to
2678          run with bank 0 , then we need to save more
2679          registers :-) */
2680       if (!SPEC_BANK (sym->etype))
2681         {
2682
2683           /* if this function does not call any other
2684              function then we can be economical and
2685              save only those registers that are used */
2686           if (!sym->hasFcall)
2687             {
2688               int i;
2689
2690               /* if any registers used */
2691               if (sym->regsUsed)
2692                 {
2693                   /* save the registers used */
2694                   for (i = sym->regsUsed->size; i >= 0; i--)
2695                     {
2696                       if (bitVectBitValue (sym->regsUsed, i) ||
2697                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2698                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2699                     }
2700                 }
2701
2702             }
2703           else
2704             {
2705               /* this function has  a function call cannot
2706                  determines register usage so we will have the
2707                  entire bank */
2708               unsaverbank (0, ic, FALSE);
2709             }
2710         }
2711
2712       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2713         {
2714           if (options.stack10bit)
2715             {
2716               emitcode ("pop", DP2_RESULT_REG);
2717               emitcode ("pop", "dpx1");
2718               emitcode ("pop", "dph1");
2719               emitcode ("pop", "dpl1");
2720             }
2721           emitcode ("pop", "dps");
2722           emitcode ("pop", "dpx");
2723         }
2724       if (!inExcludeList ("dph"))
2725         emitcode ("pop", "dph");
2726       if (!inExcludeList ("dpl"))
2727         emitcode ("pop", "dpl");
2728       if (!inExcludeList ("b"))
2729         emitcode ("pop", "b");
2730       if (!inExcludeList ("acc"))
2731         emitcode ("pop", "acc");
2732
2733       if (SPEC_CRTCL (sym->etype))
2734         emitcode ("setb", "ea");
2735
2736       /* if debug then send end of function */
2737 /*  if (options.debug && currFunc) { */
2738       if (currFunc)
2739         {
2740           _G.debugLine = 1;
2741           emitcode ("", "C$%s$%d$%d$%d ==.",
2742                     FileBaseName (ic->filename), currFunc->lastLine,
2743                     ic->level, ic->block);
2744           if (IS_STATIC (currFunc->etype))
2745             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2746           else
2747             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2748           _G.debugLine = 0;
2749         }
2750
2751       emitcode ("reti", "");
2752     }
2753   else
2754     {
2755       if (SPEC_CRTCL (sym->etype))
2756         emitcode ("setb", "ea");
2757
2758       if (sym->calleeSave)
2759         {
2760           int i;
2761
2762           /* if any registers used */
2763           if (sym->regsUsed)
2764             {
2765               /* save the registers used */
2766               for (i = sym->regsUsed->size; i >= 0; i--)
2767                 {
2768                   if (bitVectBitValue (sym->regsUsed, i) ||
2769                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2770                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2771                 }
2772             }
2773
2774         }
2775
2776       /* if debug then send end of function */
2777       if (currFunc)
2778         {
2779           _G.debugLine = 1;
2780           emitcode ("", "C$%s$%d$%d$%d ==.",
2781                     FileBaseName (ic->filename), currFunc->lastLine,
2782                     ic->level, ic->block);
2783           if (IS_STATIC (currFunc->etype))
2784             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2785           else
2786             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2787           _G.debugLine = 0;
2788         }
2789
2790       emitcode ("ret", "");
2791     }
2792
2793 }
2794
2795 /*-----------------------------------------------------------------*/
2796 /* genRet - generate code for return statement                     */
2797 /*-----------------------------------------------------------------*/
2798 static void
2799 genRet (iCode * ic)
2800 {
2801   int size, offset = 0, pushed = 0;
2802
2803   D (emitcode (";", "genRet ");
2804     );
2805
2806   /* if we have no return value then
2807      just generate the "ret" */
2808   if (!IC_LEFT (ic))
2809     goto jumpret;
2810
2811   /* we have something to return then
2812      move the return value into place */
2813   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2814   size = AOP_SIZE (IC_LEFT (ic));
2815
2816   _startLazyDPSEvaluation ();
2817   while (size--)
2818     {
2819       char *l;
2820       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2821         {
2822           l = aopGet (AOP (IC_LEFT (ic)), offset++,
2823                       FALSE, TRUE, FALSE);
2824           emitcode ("push", "%s", l);
2825           pushed++;
2826         }
2827       else
2828         {
2829           l = aopGet (AOP (IC_LEFT (ic)), offset,
2830                       FALSE, FALSE, FALSE);
2831           if (strcmp (fReturn[offset], l))
2832             emitcode ("mov", "%s,%s", fReturn[offset++], l);
2833         }
2834     }
2835   _endLazyDPSEvaluation ();
2836
2837   if (pushed)
2838     {
2839       while (pushed)
2840         {
2841           pushed--;
2842           if (strcmp (fReturn[pushed], "a"))
2843             emitcode ("pop", fReturn[pushed]);
2844           else
2845             emitcode ("pop", "acc");
2846         }
2847     }
2848   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2849
2850 jumpret:
2851   /* generate a jump to the return label
2852      if the next is not the return statement */
2853   if (!(ic->next && ic->next->op == LABEL &&
2854         IC_LABEL (ic->next) == returnLabel))
2855
2856     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2857
2858 }
2859
2860 /*-----------------------------------------------------------------*/
2861 /* genLabel - generates a label                                    */
2862 /*-----------------------------------------------------------------*/
2863 static void
2864 genLabel (iCode * ic)
2865 {
2866   /* special case never generate */
2867   if (IC_LABEL (ic) == entryLabel)
2868     return;
2869
2870   D (emitcode (";", "genLabel ");
2871     );
2872
2873   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2874 }
2875
2876 /*-----------------------------------------------------------------*/
2877 /* genGoto - generates a ljmp                                      */
2878 /*-----------------------------------------------------------------*/
2879 static void
2880 genGoto (iCode * ic)
2881 {
2882   D (emitcode (";", "genGoto ");
2883     );
2884   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2885 }
2886
2887 /*-----------------------------------------------------------------*/
2888 /* findLabelBackwards: walks back through the iCode chain looking  */
2889 /* for the given label. Returns number of iCode instructions     */
2890 /* between that label and given ic.          */
2891 /* Returns zero if label not found.          */
2892 /*-----------------------------------------------------------------*/
2893 static int
2894 findLabelBackwards (iCode * ic, int key)
2895 {
2896   int count = 0;
2897
2898   while (ic->prev)
2899     {
2900       ic = ic->prev;
2901       count++;
2902
2903       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2904         {
2905           /* printf("findLabelBackwards = %d\n", count); */
2906           return count;
2907         }
2908     }
2909
2910   return 0;
2911 }
2912
2913 /*-----------------------------------------------------------------*/
2914 /* genPlusIncr :- does addition with increment if possible         */
2915 /*-----------------------------------------------------------------*/
2916 static bool
2917 genPlusIncr (iCode * ic)
2918 {
2919   unsigned int icount;
2920   unsigned int size = getDataSize (IC_RESULT (ic));
2921
2922   /* will try to generate an increment */
2923   /* if the right side is not a literal
2924      we cannot */
2925   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2926     return FALSE;
2927
2928   /* if the literal value of the right hand side
2929      is greater than 4 then it is not worth it */
2930   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2931     return FALSE;
2932
2933   /* if increment 16 bits in register */
2934   if (
2935        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2936        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2937        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2938        (size > 1) &&
2939        (icount == 1))
2940     {
2941       symbol *tlbl;
2942       int emitTlbl;
2943       int labelRange;
2944
2945       /* If the next instruction is a goto and the goto target
2946        * is <= 5 instructions previous to this, we can generate
2947        * jumps straight to that target.
2948        */
2949       if (ic->next && ic->next->op == GOTO
2950           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2951           && labelRange <= 5)
2952         {
2953           emitcode (";", "tail increment optimized (range %d)", labelRange);
2954           tlbl = IC_LABEL (ic->next);
2955           emitTlbl = 0;
2956         }
2957       else
2958         {
2959           tlbl = newiTempLabel (NULL);
2960           emitTlbl = 1;
2961         }
2962       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2963       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2964           IS_AOP_PREG (IC_RESULT (ic)))
2965         emitcode ("cjne", "%s,#0x00,%05d$"
2966                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2967                   ,tlbl->key + 100);
2968       else
2969         {
2970           emitcode ("clr", "a");
2971           emitcode ("cjne", "a,%s,%05d$"
2972                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2973                     ,tlbl->key + 100);
2974         }
2975
2976       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2977       if (size > 2)
2978         {
2979           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2980               IS_AOP_PREG (IC_RESULT (ic)))
2981             emitcode ("cjne", "%s,#0x00,%05d$"
2982                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2983                       ,tlbl->key + 100);
2984           else
2985             emitcode ("cjne", "a,%s,%05d$"
2986                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2987                       ,tlbl->key + 100);
2988
2989           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
2990         }
2991       if (size > 3)
2992         {
2993           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2994               IS_AOP_PREG (IC_RESULT (ic)))
2995             emitcode ("cjne", "%s,#0x00,%05d$"
2996                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
2997                       ,tlbl->key + 100);
2998           else
2999             {
3000               emitcode ("cjne", "a,%s,%05d$"
3001                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3002                         ,tlbl->key + 100);
3003             }
3004           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3005         }
3006
3007       if (emitTlbl)
3008         {
3009           emitcode ("", "%05d$:", tlbl->key + 100);
3010         }
3011       return TRUE;
3012     }
3013
3014   /* if the sizes are greater than 1 then we cannot */
3015   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3016       AOP_SIZE (IC_LEFT (ic)) > 1)
3017     return FALSE;
3018
3019   /* we can if the aops of the left & result match or
3020      if they are in registers and the registers are the
3021      same */
3022   if (
3023        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3024        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3025        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3026     {
3027
3028       if (icount > 3)
3029         {
3030           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3031           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3032           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3033         }
3034       else
3035         {
3036
3037           _startLazyDPSEvaluation ();
3038           while (icount--)
3039             {
3040               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3041             }
3042           _endLazyDPSEvaluation ();
3043         }
3044
3045       return TRUE;
3046     }
3047
3048   return FALSE;
3049 }
3050
3051 /*-----------------------------------------------------------------*/
3052 /* outBitAcc - output a bit in acc                                 */
3053 /*-----------------------------------------------------------------*/
3054 static void
3055 outBitAcc (operand * result)
3056 {
3057   symbol *tlbl = newiTempLabel (NULL);
3058   /* if the result is a bit */
3059   if (AOP_TYPE (result) == AOP_CRY)
3060     {
3061       aopPut (AOP (result), "a", 0);
3062     }
3063   else
3064     {
3065       emitcode ("jz", "%05d$", tlbl->key + 100);
3066       emitcode ("mov", "a,%s", one);
3067       emitcode ("", "%05d$:", tlbl->key + 100);
3068       outAcc (result);
3069     }
3070 }
3071
3072 /*-----------------------------------------------------------------*/
3073 /* genPlusBits - generates code for addition of two bits           */
3074 /*-----------------------------------------------------------------*/
3075 static void
3076 genPlusBits (iCode * ic)
3077 {
3078   D (emitcode (";", "genPlusBits ");
3079     );
3080   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3081     {
3082       symbol *lbl = newiTempLabel (NULL);
3083       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3084       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3085       emitcode ("cpl", "c");
3086       emitcode ("", "%05d$:", (lbl->key + 100));
3087       outBitC (IC_RESULT (ic));
3088     }
3089   else
3090     {
3091       emitcode ("clr", "a");
3092       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3093       emitcode ("rlc", "a");
3094       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3095       emitcode ("addc", "a,#0x00");
3096       outAcc (IC_RESULT (ic));
3097     }
3098 }
3099
3100 static void
3101 adjustArithmeticResult (iCode * ic)
3102 {
3103   if (opIsGptr (IC_RESULT (ic)) &&
3104       opIsGptr (IC_LEFT (ic)) &&
3105       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3106     {
3107       aopPut (AOP (IC_RESULT (ic)),
3108               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3109               GPTRSIZE - 1);
3110     }
3111
3112   if (opIsGptr (IC_RESULT (ic)) &&
3113       opIsGptr (IC_RIGHT (ic)) &&
3114       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3115     {
3116       aopPut (AOP (IC_RESULT (ic)),
3117             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3118               GPTRSIZE - 1);
3119     }
3120
3121   if (opIsGptr (IC_RESULT (ic)) &&
3122       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3123       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3124       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3125       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3126     {
3127       char buffer[5];
3128       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3129       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3130     }
3131 }
3132
3133 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3134 // (because all three operands are in far space).
3135 #define AOP_OP_3(ic) \
3136     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3137     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3138     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3139               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3140     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3141         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3142     { \
3143         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3144         fprintf(stderr,                                  \
3145                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3146     }
3147
3148 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3149 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3150 // will be set TRUE. The caller must then handle the case specially, noting
3151 // that the IC_RESULT operand is not aopOp'd.
3152 #define AOP_OP_3_NOFATAL(ic, rc) \
3153     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3154     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3155     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3156         isOperandInFarSpace(IC_RESULT(ic))) \
3157     { \
3158        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3159        rc = TRUE; \
3160     }  \
3161     else \
3162     { \
3163        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3164                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3165        rc = FALSE; \
3166        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3167            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3168        { \
3169             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3170             fprintf(stderr,                                  \
3171                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3172        } \
3173     }
3174
3175 // aopOp the left & right operands of an ic.
3176 #define AOP_OP_2(ic) \
3177     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3178     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3179
3180 // convienience macro.
3181 #define AOP_SET_LOCALS(ic) \
3182     left = IC_LEFT(ic); \
3183     right = IC_RIGHT(ic); \
3184     result = IC_RESULT(ic);
3185
3186
3187 // Given an integer value of pushedSize bytes on the stack,
3188 // adjust it to be resultSize bytes, either by discarding
3189 // the most significant bytes or by zero-padding.
3190 //
3191 // On exit from this macro, pushedSize will have been adjusted to
3192 // equal resultSize, and ACC may be trashed.
3193 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3194       /* If the pushed data is bigger than the result,          \
3195        * simply discard unused bytes. Icky, but works.          \
3196        */                                                       \
3197       while (pushedSize > resultSize)                           \
3198       {                                                         \
3199           D (emitcode (";", "discarding unused result byte."););\
3200           emitcode ("pop", "acc");                              \
3201           pushedSize--;                                         \
3202       }                                                         \
3203       if (pushedSize < resultSize)                              \
3204       {                                                         \
3205           emitcode ("clr", "a");                                \
3206           /* Conversly, we haven't pushed enough here.          \
3207            * just zero-pad, and all is well.                    \
3208            */                                                   \
3209           while (pushedSize < resultSize)                       \
3210           {                                                     \
3211               emitcode("push", "acc");                          \
3212               pushedSize++;                                     \
3213           }                                                     \
3214       }                                                         \
3215       assert(pushedSize == resultSize);
3216
3217 /*-----------------------------------------------------------------*/
3218 /* genPlus - generates code for addition                           */
3219 /*-----------------------------------------------------------------*/
3220 static void
3221 genPlus (iCode * ic)
3222 {
3223   int size, offset = 0;
3224   bool pushResult = FALSE;
3225   int rSize;
3226
3227   D (emitcode (";", "genPlus "););
3228
3229   /* special cases :- */
3230
3231   AOP_OP_3_NOFATAL (ic, pushResult);
3232   if (pushResult)
3233     {
3234       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3235     }
3236
3237   if (!pushResult)
3238     {
3239       /* if literal, literal on the right or
3240          if left requires ACC or right is already
3241          in ACC */
3242       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3243        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3244           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3245         {
3246           operand *t = IC_RIGHT (ic);
3247           IC_RIGHT (ic) = IC_LEFT (ic);
3248           IC_LEFT (ic) = t;
3249           emitcode (";", "Swapped plus args.");
3250         }
3251
3252       /* if both left & right are in bit
3253          space */
3254       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3255           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3256         {
3257           genPlusBits (ic);
3258           goto release;
3259         }
3260
3261       /* if left in bit space & right literal */
3262       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3263           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3264         {
3265           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3266           /* if result in bit space */
3267           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3268             {
3269               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3270                 emitcode ("cpl", "c");
3271               outBitC (IC_RESULT (ic));
3272             }
3273           else
3274             {
3275               size = getDataSize (IC_RESULT (ic));
3276               _startLazyDPSEvaluation ();
3277               while (size--)
3278                 {
3279                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3280                   emitcode ("addc", "a,#00");
3281                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3282                 }
3283               _endLazyDPSEvaluation ();
3284             }
3285           goto release;
3286         }
3287
3288       /* if I can do an increment instead
3289          of add then GOOD for ME */
3290       if (genPlusIncr (ic) == TRUE)
3291         {
3292           emitcode (";", "did genPlusIncr");
3293           goto release;
3294         }
3295
3296     }
3297   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3298
3299   _startLazyDPSEvaluation ();
3300   while (size--)
3301     {
3302       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3303         {
3304           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3305           if (offset == 0)
3306             emitcode ("add", "a,%s",
3307                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3308           else
3309             emitcode ("addc", "a,%s",
3310                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3311         }
3312       else
3313         {
3314           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3315           if (offset == 0)
3316             emitcode ("add", "a,%s",
3317                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3318           else
3319             emitcode ("addc", "a,%s",
3320                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3321         }
3322       if (!pushResult)
3323         {
3324           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3325         }
3326       else
3327         {
3328           emitcode ("push", "acc");
3329         }
3330       offset++;
3331     }
3332   _endLazyDPSEvaluation ();
3333
3334   if (pushResult)
3335     {
3336       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3337
3338       size = getDataSize (IC_LEFT (ic));
3339       rSize = getDataSize (IC_RESULT (ic));
3340
3341       ADJUST_PUSHED_RESULT(size, rSize);
3342
3343       _startLazyDPSEvaluation ();
3344       while (size--)
3345         {
3346           emitcode ("pop", "acc");
3347           aopPut (AOP (IC_RESULT (ic)), "a", size);
3348         }
3349       _endLazyDPSEvaluation ();
3350     }
3351
3352   adjustArithmeticResult (ic);
3353
3354 release:
3355   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3356   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3357   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3358 }
3359
3360 /*-----------------------------------------------------------------*/
3361 /* genMinusDec :- does subtraction with deccrement if possible     */
3362 /*-----------------------------------------------------------------*/
3363 static bool
3364 genMinusDec (iCode * ic)
3365 {
3366   unsigned int icount;
3367   unsigned int size = getDataSize (IC_RESULT (ic));
3368
3369   /* will try to generate an increment */
3370   /* if the right side is not a literal
3371      we cannot */
3372   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3373     return FALSE;
3374
3375   /* if the literal value of the right hand side
3376      is greater than 4 then it is not worth it */
3377   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3378     return FALSE;
3379
3380   /* if decrement 16 bits in register */
3381   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3382       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3383       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3384       (size > 1) &&
3385       (icount == 1))
3386     {
3387       symbol *tlbl;
3388       int emitTlbl;
3389       int labelRange;
3390
3391       /* If the next instruction is a goto and the goto target
3392          * is <= 5 instructions previous to this, we can generate
3393          * jumps straight to that target.
3394        */
3395       if (ic->next && ic->next->op == GOTO
3396           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3397           && labelRange <= 5)
3398         {
3399           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3400           tlbl = IC_LABEL (ic->next);
3401           emitTlbl = 0;
3402         }
3403       else
3404         {
3405           tlbl = newiTempLabel (NULL);
3406           emitTlbl = 1;
3407         }
3408
3409       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3410       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3411           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3412           IS_AOP_PREG (IC_RESULT (ic)))
3413         emitcode ("cjne", "%s,#0xff,%05d$"
3414                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3415                   ,tlbl->key + 100);
3416       else
3417         {
3418           emitcode ("mov", "a,#0xff");
3419           emitcode ("cjne", "a,%s,%05d$"
3420                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3421                     ,tlbl->key + 100);
3422         }
3423       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3424       if (size > 2)
3425         {
3426           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3427               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3428               IS_AOP_PREG (IC_RESULT (ic)))
3429             emitcode ("cjne", "%s,#0xff,%05d$"
3430                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3431                       ,tlbl->key + 100);
3432           else
3433             {
3434               emitcode ("cjne", "a,%s,%05d$"
3435                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3436                         ,tlbl->key + 100);
3437             }
3438           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3439         }
3440       if (size > 3)
3441         {
3442           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3443               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3444               IS_AOP_PREG (IC_RESULT (ic)))
3445             emitcode ("cjne", "%s,#0xff,%05d$"
3446                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3447                       ,tlbl->key + 100);
3448           else
3449             {
3450               emitcode ("cjne", "a,%s,%05d$"
3451                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3452                         ,tlbl->key + 100);
3453             }
3454           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3455         }
3456       if (emitTlbl)
3457         {
3458           emitcode ("", "%05d$:", tlbl->key + 100);
3459         }
3460       return TRUE;
3461     }
3462
3463   /* if the sizes are greater than 1 then we cannot */
3464   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3465       AOP_SIZE (IC_LEFT (ic)) > 1)
3466     return FALSE;
3467
3468   /* we can if the aops of the left & result match or
3469      if they are in registers and the registers are the
3470      same */
3471   if (
3472        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3473        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3474        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3475     {
3476
3477       _startLazyDPSEvaluation ();
3478       while (icount--)
3479         {
3480           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3481         }
3482       _endLazyDPSEvaluation ();
3483
3484       return TRUE;
3485     }
3486
3487   return FALSE;
3488 }
3489
3490 /*-----------------------------------------------------------------*/
3491 /* addSign - complete with sign                                    */
3492 /*-----------------------------------------------------------------*/
3493 static void
3494 addSign (operand * result, int offset, int sign)
3495 {
3496   int size = (getDataSize (result) - offset);
3497   if (size > 0)
3498     {
3499       if (sign)
3500         {
3501           emitcode ("rlc", "a");
3502           emitcode ("subb", "a,acc");
3503           while (size--)
3504             aopPut (AOP (result), "a", offset++);
3505         }
3506       else
3507         while (size--)
3508           aopPut (AOP (result), zero, offset++);
3509     }
3510 }
3511
3512 /*-----------------------------------------------------------------*/
3513 /* genMinusBits - generates code for subtraction  of two bits      */
3514 /*-----------------------------------------------------------------*/
3515 static void
3516 genMinusBits (iCode * ic)
3517 {
3518   symbol *lbl = newiTempLabel (NULL);
3519
3520   D (emitcode (";", "genMinusBits ");
3521     );
3522
3523   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3524     {
3525       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3526       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3527       emitcode ("cpl", "c");
3528       emitcode ("", "%05d$:", (lbl->key + 100));
3529       outBitC (IC_RESULT (ic));
3530     }
3531   else
3532     {
3533       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3534       emitcode ("subb", "a,acc");
3535       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3536       emitcode ("inc", "a");
3537       emitcode ("", "%05d$:", (lbl->key + 100));
3538       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3539       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3540     }
3541 }
3542
3543 /*-----------------------------------------------------------------*/
3544 /* genMinus - generates code for subtraction                       */
3545 /*-----------------------------------------------------------------*/
3546 static void
3547 genMinus (iCode * ic)
3548 {
3549   int size, offset = 0;
3550   int rSize;
3551   unsigned long lit = 0L;
3552   bool pushResult = FALSE;
3553
3554   D (emitcode (";", "genMinus "););
3555
3556   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3557   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3558   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3559       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3560     {
3561       pushResult = TRUE;
3562     }
3563   else
3564     {
3565       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3566
3567       /* special cases :- */
3568       /* if both left & right are in bit space */
3569       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3570           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3571         {
3572           genMinusBits (ic);
3573           goto release;
3574         }
3575
3576       /* if I can do an decrement instead
3577          of subtract then GOOD for ME */
3578       if (genMinusDec (ic) == TRUE)
3579         goto release;
3580
3581     }
3582
3583   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3584
3585   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3586     {
3587       CLRC;
3588     }
3589   else
3590     {
3591       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3592       lit = -(long) lit;
3593     }
3594
3595
3596   /* if literal, add a,#-lit, else normal subb */
3597   _startLazyDPSEvaluation ();
3598   while (size--)
3599     {
3600       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3601       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3602         emitcode ("subb", "a,%s",
3603                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3604       else
3605         {
3606           /* first add without previous c */
3607           if (!offset)
3608             emitcode ("add", "a,#0x%02x",
3609                       (unsigned int) (lit & 0x0FFL));
3610           else
3611             emitcode ("addc", "a,#0x%02x",
3612                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3613         }
3614
3615       if (pushResult)
3616         {
3617           emitcode ("push", "acc");
3618         }
3619       else
3620         {
3621           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3622         }
3623       offset++;
3624     }
3625   _endLazyDPSEvaluation ();
3626
3627   if (pushResult)
3628     {
3629       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3630
3631       size = getDataSize (IC_LEFT (ic));
3632       rSize = getDataSize (IC_RESULT (ic));
3633
3634       ADJUST_PUSHED_RESULT(size, rSize);
3635
3636       _startLazyDPSEvaluation ();
3637       while (size--)
3638         {
3639           emitcode ("pop", "acc");
3640           aopPut (AOP (IC_RESULT (ic)), "a", size);
3641         }
3642       _endLazyDPSEvaluation ();
3643     }
3644
3645   adjustArithmeticResult (ic);
3646
3647 release:
3648   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3649   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3650   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3651 }
3652
3653
3654 /*-----------------------------------------------------------------*/
3655 /* genMultbits :- multiplication of bits                           */
3656 /*-----------------------------------------------------------------*/
3657 static void
3658 genMultbits (operand * left,
3659              operand * right,
3660              operand * result)
3661 {
3662   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3663   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3664   outBitC (result);
3665 }
3666
3667
3668 /*-----------------------------------------------------------------*/
3669 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3670 /*-----------------------------------------------------------------*/
3671 static void
3672 genMultOneByte (operand * left,
3673                 operand * right,
3674                 operand * result)
3675 {
3676   sym_link *opetype = operandType (result);
3677   symbol *lbl;
3678   int size=AOP_SIZE(result);
3679
3680   emitcode (";",__FUNCTION__);
3681   if (size<1 || size>2) {
3682     // this should never happen
3683       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3684                AOP_SIZE(result), __FUNCTION__, lineno);
3685       exit (1);
3686   }
3687
3688   /* (if two literals: the value is computed before) */
3689   /* if one literal, literal on the right */
3690   if (AOP_TYPE (left) == AOP_LIT)
3691     {
3692       operand *t = right;
3693       right = left;
3694       left = t;
3695       emitcode (";", "swapped left and right");
3696     }
3697
3698   if (SPEC_USIGN(opetype)
3699       // ignore the sign of left and right, what else can we do?
3700       || (SPEC_USIGN(operandType(left)) && 
3701           SPEC_USIGN(operandType(right)))) {
3702     // just an unsigned 8*8=8/16 multiply
3703     //emitcode (";","unsigned");
3704     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3705     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3706     emitcode ("mul", "ab");
3707     aopPut (AOP (result), "a", 0);
3708     if (size==2) {
3709       aopPut (AOP (result), "b", 1);
3710     }
3711     return;
3712   }
3713
3714   // we have to do a signed multiply
3715
3716   emitcode (";", "signed");
3717   emitcode ("clr", "F0"); // reset sign flag
3718   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3719   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3720
3721   lbl=newiTempLabel(NULL);
3722   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3723   // left side is negative, 8-bit two's complement, this fails for -128
3724   emitcode ("setb", "F0"); // set sign flag
3725   emitcode ("cpl", "a");
3726   emitcode ("inc", "a");
3727
3728   emitcode ("", "%05d$:", lbl->key+100);
3729   emitcode ("xch", "a,b");
3730
3731   /* if literal */
3732   if (AOP_TYPE(right)==AOP_LIT) {
3733     /* AND literal negative */
3734     if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3735       // two's complement for literal<0
3736       emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3737       emitcode ("cpl", "a");
3738       emitcode ("inc", "a");
3739     }
3740   } else {
3741     lbl=newiTempLabel(NULL);
3742     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3743     // right side is negative, 8-bit two's complement
3744     emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3745     emitcode ("cpl", "a");
3746     emitcode ("inc", "a");
3747     emitcode ("", "%05d$:", lbl->key+100);
3748   }
3749   emitcode ("mul", "ab");
3750     
3751   lbl=newiTempLabel(NULL);
3752   emitcode ("jnb", "F0,%05d$", lbl->key+100);
3753   // only ONE op was negative, we have to do a 8/16-bit two's complement
3754   emitcode ("cpl", "a"); // lsb
3755   if (size==1) {
3756     emitcode ("inc", "a");
3757   } else {
3758     emitcode ("add", "a,#1");
3759     emitcode ("xch", "a,b");
3760     emitcode ("cpl", "a"); // msb
3761     emitcode ("addc", "a,#0");
3762     emitcode ("xch", "a,b");
3763   }
3764
3765   emitcode ("", "%05d$:", lbl->key+100);
3766   aopPut (AOP (result), "a", 0);
3767   if (size==2) {
3768     aopPut (AOP (result), "b", 1);
3769   }
3770 }
3771
3772 /*-----------------------------------------------------------------*/
3773 /* genMult - generates code for multiplication                     */
3774 /*-----------------------------------------------------------------*/
3775 static void
3776 genMult (iCode * ic)
3777 {
3778   operand *left = IC_LEFT (ic);
3779   operand *right = IC_RIGHT (ic);
3780   operand *result = IC_RESULT (ic);
3781
3782   D (emitcode (";", "genMult "););
3783
3784   /* assign the amsops */
3785   AOP_OP_3 (ic);
3786
3787   /* special cases first */
3788   /* both are bits */
3789   if (AOP_TYPE (left) == AOP_CRY &&
3790       AOP_TYPE (right) == AOP_CRY)
3791     {
3792       genMultbits (left, right, result);
3793       goto release;
3794     }
3795
3796   /* if both are of size == 1 */
3797   if (AOP_SIZE (left) == 1 &&
3798       AOP_SIZE (right) == 1)
3799     {
3800       genMultOneByte (left, right, result);
3801       goto release;
3802     }
3803
3804   /* should have been converted to function call */
3805   assert (1);
3806
3807 release:
3808   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3809   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3810   freeAsmop (result, NULL, ic, TRUE);
3811 }
3812
3813 /*-----------------------------------------------------------------*/
3814 /* genDivbits :- division of bits                                  */
3815 /*-----------------------------------------------------------------*/
3816 static void
3817 genDivbits (operand * left,
3818             operand * right,
3819             operand * result)
3820 {
3821
3822   char *l;
3823
3824   /* the result must be bit */
3825   LOAD_AB_FOR_DIV (left, right, l);
3826   emitcode ("div", "ab");
3827   emitcode ("rrc", "a");
3828   aopPut (AOP (result), "c", 0);
3829 }
3830
3831 /*-----------------------------------------------------------------*/
3832 /* genDivOneByte : 8 bit division                                  */
3833 /*-----------------------------------------------------------------*/
3834 static void
3835 genDivOneByte (operand * left,
3836                operand * right,
3837                operand * result)
3838 {
3839   sym_link *opetype = operandType (result);
3840   char *l;
3841   symbol *lbl;
3842   int size, offset;
3843
3844   size = AOP_SIZE (result) - 1;
3845   offset = 1;
3846   /* signed or unsigned */
3847   if (SPEC_USIGN (opetype))
3848     {
3849       /* unsigned is easy */
3850       LOAD_AB_FOR_DIV (left, right, l);
3851       emitcode ("div", "ab");
3852       aopPut (AOP (result), "a", 0);
3853       while (size--)
3854         aopPut (AOP (result), zero, offset++);
3855       return;
3856     }
3857
3858   /* signed is a little bit more difficult */
3859
3860   /* save the signs of the operands */
3861   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3862   MOVA (l);
3863   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3864   emitcode ("push", "acc");     /* save it on the stack */
3865
3866   /* now sign adjust for both left & right */
3867   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3868   MOVA (l);
3869   lbl = newiTempLabel (NULL);
3870   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3871   emitcode ("cpl", "a");
3872   emitcode ("inc", "a");
3873   emitcode ("", "%05d$:", (lbl->key + 100));
3874   emitcode ("mov", "b,a");
3875
3876   /* sign adjust left side */
3877   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3878   MOVA (l);
3879
3880   lbl = newiTempLabel (NULL);
3881   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3882   emitcode ("cpl", "a");
3883   emitcode ("inc", "a");
3884   emitcode ("", "%05d$:", (lbl->key + 100));
3885
3886   /* now the division */
3887   emitcode ("nop", "; workaround for DS80C390 div bug.");
3888   emitcode ("div", "ab");
3889   /* we are interested in the lower order
3890      only */
3891   emitcode ("mov", "b,a");
3892   lbl = newiTempLabel (NULL);
3893   emitcode ("pop", "acc");
3894   /* if there was an over flow we don't
3895      adjust the sign of the result */
3896   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3897   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3898   CLRC;
3899   emitcode ("clr", "a");
3900   emitcode ("subb", "a,b");
3901   emitcode ("mov", "b,a");
3902   emitcode ("", "%05d$:", (lbl->key + 100));
3903
3904   /* now we are done */
3905   aopPut (AOP (result), "b", 0);
3906   if (size > 0)
3907     {
3908       emitcode ("mov", "c,b.7");
3909       emitcode ("subb", "a,acc");
3910     }
3911   while (size--)
3912     aopPut (AOP (result), "a", offset++);
3913
3914 }
3915
3916 /*-----------------------------------------------------------------*/
3917 /* genDiv - generates code for division                            */
3918 /*-----------------------------------------------------------------*/
3919 static void
3920 genDiv (iCode * ic)
3921 {
3922   operand *left = IC_LEFT (ic);
3923   operand *right = IC_RIGHT (ic);
3924   operand *result = IC_RESULT (ic);
3925
3926   D (emitcode (";", "genDiv ");
3927     );
3928
3929   /* assign the amsops */
3930   AOP_OP_3 (ic);
3931
3932   /* special cases first */
3933   /* both are bits */
3934   if (AOP_TYPE (left) == AOP_CRY &&
3935       AOP_TYPE (right) == AOP_CRY)
3936     {
3937       genDivbits (left, right, result);
3938       goto release;
3939     }
3940
3941   /* if both are of size == 1 */
3942   if (AOP_SIZE (left) == 1 &&
3943       AOP_SIZE (right) == 1)
3944     {
3945       genDivOneByte (left, right, result);
3946       goto release;
3947     }
3948
3949   /* should have been converted to function call */
3950   assert (1);
3951 release:
3952   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3953   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3954   freeAsmop (result, NULL, ic, TRUE);
3955 }
3956
3957 /*-----------------------------------------------------------------*/
3958 /* genModbits :- modulus of bits                                   */
3959 /*-----------------------------------------------------------------*/
3960 static void
3961 genModbits (operand * left,
3962             operand * right,
3963             operand * result)
3964 {
3965
3966   char *l;
3967
3968   /* the result must be bit */
3969   LOAD_AB_FOR_DIV (left, right, l);
3970   emitcode ("div", "ab");
3971   emitcode ("mov", "a,b");
3972   emitcode ("rrc", "a");
3973   aopPut (AOP (result), "c", 0);
3974 }
3975
3976 /*-----------------------------------------------------------------*/
3977 /* genModOneByte : 8 bit modulus                                   */
3978 /*-----------------------------------------------------------------*/
3979 static void
3980 genModOneByte (operand * left,
3981                operand * right,
3982                operand * result)
3983 {
3984   sym_link *opetype = operandType (result);
3985   char *l;
3986   symbol *lbl;
3987
3988   /* signed or unsigned */
3989   if (SPEC_USIGN (opetype))
3990     {
3991       /* unsigned is easy */
3992       LOAD_AB_FOR_DIV (left, right, l);
3993       emitcode ("div", "ab");
3994       aopPut (AOP (result), "b", 0);
3995       return;
3996     }
3997
3998   /* signed is a little bit more difficult */
3999
4000   /* save the signs of the operands */
4001   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4002   MOVA (l);
4003
4004   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4005   emitcode ("push", "acc");     /* save it on the stack */
4006
4007   /* now sign adjust for both left & right */
4008   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4009   MOVA (l);
4010
4011   lbl = newiTempLabel (NULL);
4012   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4013   emitcode ("cpl", "a");
4014   emitcode ("inc", "a");
4015   emitcode ("", "%05d$:", (lbl->key + 100));
4016   emitcode ("mov", "b,a");
4017
4018   /* sign adjust left side */
4019   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4020   MOVA (l);
4021
4022   lbl = newiTempLabel (NULL);
4023   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4024   emitcode ("cpl", "a");
4025   emitcode ("inc", "a");
4026   emitcode ("", "%05d$:", (lbl->key + 100));
4027
4028   /* now the multiplication */
4029   emitcode ("nop", "; workaround for DS80C390 div bug.");
4030   emitcode ("div", "ab");
4031   /* we are interested in the lower order
4032      only */
4033   lbl = newiTempLabel (NULL);
4034   emitcode ("pop", "acc");
4035   /* if there was an over flow we don't
4036      adjust the sign of the result */
4037   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4038   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4039   CLRC;
4040   emitcode ("clr", "a");
4041   emitcode ("subb", "a,b");
4042   emitcode ("mov", "b,a");
4043   emitcode ("", "%05d$:", (lbl->key + 100));
4044
4045   /* now we are done */
4046   aopPut (AOP (result), "b", 0);
4047
4048 }
4049
4050 /*-----------------------------------------------------------------*/
4051 /* genMod - generates code for division                            */
4052 /*-----------------------------------------------------------------*/
4053 static void
4054 genMod (iCode * ic)
4055 {
4056   operand *left = IC_LEFT (ic);
4057   operand *right = IC_RIGHT (ic);
4058   operand *result = IC_RESULT (ic);
4059
4060   D (emitcode (";", "genMod ");
4061     );
4062
4063   /* assign the amsops */
4064   AOP_OP_3 (ic);
4065
4066   /* special cases first */
4067   /* both are bits */
4068   if (AOP_TYPE (left) == AOP_CRY &&
4069       AOP_TYPE (right) == AOP_CRY)
4070     {
4071       genModbits (left, right, result);
4072       goto release;
4073     }
4074
4075   /* if both are of size == 1 */
4076   if (AOP_SIZE (left) == 1 &&
4077       AOP_SIZE (right) == 1)
4078     {
4079       genModOneByte (left, right, result);
4080       goto release;
4081     }
4082
4083   /* should have been converted to function call */
4084   assert (1);
4085
4086 release:
4087   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4088   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4089   freeAsmop (result, NULL, ic, TRUE);
4090 }
4091
4092 /*-----------------------------------------------------------------*/
4093 /* genIfxJump :- will create a jump depending on the ifx           */
4094 /*-----------------------------------------------------------------*/
4095 static void
4096 genIfxJump (iCode * ic, char *jval)
4097 {
4098   symbol *jlbl;
4099   symbol *tlbl = newiTempLabel (NULL);
4100   char *inst;
4101
4102   D (emitcode (";", "genIfxJump ");
4103     );
4104
4105   /* if true label then we jump if condition
4106      supplied is true */
4107   if (IC_TRUE (ic))
4108     {
4109       jlbl = IC_TRUE (ic);
4110       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4111                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4112     }
4113   else
4114     {
4115       /* false label is present */
4116       jlbl = IC_FALSE (ic);
4117       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4118                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4119     }
4120   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4121     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4122   else
4123     emitcode (inst, "%05d$", tlbl->key + 100);
4124   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4125   emitcode ("", "%05d$:", tlbl->key + 100);
4126
4127   /* mark the icode as generated */
4128   ic->generated = 1;
4129 }
4130
4131 /*-----------------------------------------------------------------*/
4132 /* genCmp :- greater or less than comparison                       */
4133 /*-----------------------------------------------------------------*/
4134 static void
4135 genCmp (operand * left, operand * right,
4136         iCode * ic, iCode * ifx, int sign)
4137 {
4138   int size, offset = 0;
4139   unsigned long lit = 0L;
4140   operand *result;
4141
4142   D (emitcode (";", "genCmp");
4143     );
4144
4145   result = IC_RESULT (ic);
4146
4147   /* if left & right are bit variables */
4148   if (AOP_TYPE (left) == AOP_CRY &&
4149       AOP_TYPE (right) == AOP_CRY)
4150     {
4151       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4152       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4153     }
4154   else
4155     {
4156       /* subtract right from left if at the
4157          end the carry flag is set then we know that
4158          left is greater than right */
4159       size = max (AOP_SIZE (left), AOP_SIZE (right));
4160
4161       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4162       if ((size == 1) && !sign &&
4163           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4164         {
4165           symbol *lbl = newiTempLabel (NULL);
4166           emitcode ("cjne", "%s,%s,%05d$",
4167                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4168                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4169                     lbl->key + 100);
4170           emitcode ("", "%05d$:", lbl->key + 100);
4171         }
4172       else
4173         {
4174           if (AOP_TYPE (right) == AOP_LIT)
4175             {
4176               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4177               /* optimize if(x < 0) or if(x >= 0) */
4178               if (lit == 0L)
4179                 {
4180                   if (!sign)
4181                     {
4182                       CLRC;
4183                     }
4184                   else
4185                     {
4186                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4187
4188                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4189                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4190
4191                       aopOp (result, ic, FALSE, FALSE);
4192
4193                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4194                         {
4195                           freeAsmop (result, NULL, ic, TRUE);
4196                           genIfxJump (ifx, "acc.7");
4197                           return;
4198                         }
4199                       else
4200                         {
4201                           emitcode ("rlc", "a");
4202                         }
4203                       goto release_freedLR;
4204                     }
4205                   goto release;
4206                 }
4207             }
4208           CLRC;
4209           while (size--)
4210             {
4211               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4212               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4213               emitcode (";", "genCmp #2");
4214               if (sign && (size == 0))
4215                 {
4216                   emitcode (";", "genCmp #3");
4217                   emitcode ("xrl", "a,#0x80");
4218                   if (AOP_TYPE (right) == AOP_LIT)
4219                     {
4220                       unsigned long lit = (unsigned long)
4221                       floatFromVal (AOP (right)->aopu.aop_lit);
4222                       emitcode (";", "genCmp #3.1");
4223                       emitcode ("subb", "a,#0x%02x",
4224                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4225                     }
4226                   else
4227                     {
4228                       emitcode (";", "genCmp #3.2");
4229                       if (AOP_NEEDSACC (right))
4230                         {
4231                           emitcode ("push", "acc");
4232                         }
4233                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4234                                                        FALSE, FALSE, FALSE));
4235                       emitcode ("xrl", "b,#0x80");
4236                       if (AOP_NEEDSACC (right))
4237                         {
4238                           emitcode ("pop", "acc");
4239                         }
4240                       emitcode ("subb", "a,b");
4241                     }
4242                 }
4243               else
4244                 {
4245                   const char *s;
4246
4247                   emitcode (";", "genCmp #4");
4248                   if (AOP_NEEDSACC (right))
4249                     {
4250                       /* Yuck!! */
4251                       emitcode (";", "genCmp #4.1");
4252                       emitcode ("xch", "a, b");
4253                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4254                       emitcode ("xch", "a, b");
4255                       s = "b";
4256                     }
4257                   else
4258                     {
4259                       emitcode (";", "genCmp #4.2");
4260                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4261                     }
4262
4263                   emitcode ("subb", "a,%s", s);
4264                 }
4265             }
4266         }
4267     }
4268
4269 release:
4270 /* Don't need the left & right operands any more; do need the result. */
4271   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4272   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4273
4274   aopOp (result, ic, FALSE, FALSE);
4275
4276 release_freedLR:
4277
4278   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4279     {
4280       outBitC (result);
4281     }
4282   else
4283     {
4284       /* if the result is used in the next
4285          ifx conditional branch then generate
4286          code a little differently */
4287       if (ifx)
4288         {
4289           genIfxJump (ifx, "c");
4290         }
4291       else
4292         {
4293           outBitC (result);
4294         }
4295       /* leave the result in acc */
4296     }
4297   freeAsmop (result, NULL, ic, TRUE);
4298 }
4299
4300 /*-----------------------------------------------------------------*/
4301 /* genCmpGt :- greater than comparison                             */
4302 /*-----------------------------------------------------------------*/
4303 static void
4304 genCmpGt (iCode * ic, iCode * ifx)
4305 {
4306   operand *left, *right;
4307   sym_link *letype, *retype;
4308   int sign;
4309
4310   D (emitcode (";", "genCmpGt ");
4311     );
4312
4313   left = IC_LEFT (ic);
4314   right = IC_RIGHT (ic);
4315
4316   letype = getSpec (operandType (left));
4317   retype = getSpec (operandType (right));
4318   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4319
4320   /* assign the left & right amsops */
4321   AOP_OP_2 (ic);
4322
4323   genCmp (right, left, ic, ifx, sign);
4324 }
4325
4326 /*-----------------------------------------------------------------*/
4327 /* genCmpLt - less than comparisons                                */
4328 /*-----------------------------------------------------------------*/
4329 static void
4330 genCmpLt (iCode * ic, iCode * ifx)
4331 {
4332   operand *left, *right;
4333   sym_link *letype, *retype;
4334   int sign;
4335
4336   D (emitcode (";", "genCmpLt "););
4337
4338   left = IC_LEFT (ic);
4339   right = IC_RIGHT (ic);
4340
4341   letype = getSpec (operandType (left));
4342   retype = getSpec (operandType (right));
4343   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4344
4345   /* assign the left & right amsops */
4346   AOP_OP_2 (ic);
4347
4348   genCmp (left, right, ic, ifx, sign);
4349 }
4350
4351 /*-----------------------------------------------------------------*/
4352 /* gencjneshort - compare and jump if not equal                    */
4353 /*-----------------------------------------------------------------*/
4354 static void
4355 gencjneshort (operand * left, operand * right, symbol * lbl)
4356 {
4357   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4358   int offset = 0;
4359   unsigned long lit = 0L;
4360
4361   D (emitcode (";", "gencjneshort");
4362     );
4363
4364   /* if the left side is a literal or
4365      if the right is in a pointer register and left
4366      is not */
4367   if ((AOP_TYPE (left) == AOP_LIT) ||
4368       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4369     {
4370       operand *t = right;
4371       right = left;
4372       left = t;
4373     }
4374
4375   if (AOP_TYPE (right) == AOP_LIT)
4376     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4377
4378   if (opIsGptr (left) || opIsGptr (right))
4379     {
4380       /* We are comparing a generic pointer to something.
4381        * Exclude the generic type byte from the comparison.
4382        */
4383       size--;
4384       D (emitcode (";", "cjneshort: generic ptr special case.");
4385         )
4386     }
4387
4388
4389   /* if the right side is a literal then anything goes */
4390   if (AOP_TYPE (right) == AOP_LIT &&
4391       AOP_TYPE (left) != AOP_DIR)
4392     {
4393       while (size--)
4394         {
4395           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4396           MOVA (l);
4397           emitcode ("cjne", "a,%s,%05d$",
4398                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4399                     lbl->key + 100);
4400           offset++;
4401         }
4402     }
4403
4404   /* if the right side is in a register or in direct space or
4405      if the left is a pointer register & right is not */
4406   else if (AOP_TYPE (right) == AOP_REG ||
4407            AOP_TYPE (right) == AOP_DIR ||
4408            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4409            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4410     {
4411       while (size--)
4412         {
4413           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4414           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4415               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4416             emitcode ("jnz", "%05d$", lbl->key + 100);
4417           else
4418             emitcode ("cjne", "a,%s,%05d$",
4419                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4420                       lbl->key + 100);
4421           offset++;
4422         }
4423     }
4424   else
4425     {
4426       /* right is a pointer reg need both a & b */
4427       while (size--)
4428         {
4429           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4430           if (strcmp (l, "b"))
4431             emitcode ("mov", "b,%s", l);
4432           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4433           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4434           offset++;
4435         }
4436     }
4437 }
4438
4439 /*-----------------------------------------------------------------*/
4440 /* gencjne - compare and jump if not equal                         */
4441 /*-----------------------------------------------------------------*/
4442 static void
4443 gencjne (operand * left, operand * right, symbol * lbl)
4444 {
4445   symbol *tlbl = newiTempLabel (NULL);
4446
4447   D (emitcode (";", "gencjne");
4448     );
4449
4450   gencjneshort (left, right, lbl);
4451
4452   emitcode ("mov", "a,%s", one);
4453   emitcode ("sjmp", "%05d$", tlbl->key + 100);
4454   emitcode ("", "%05d$:", lbl->key + 100);
4455   emitcode ("clr", "a");
4456   emitcode ("", "%05d$:", tlbl->key + 100);
4457 }
4458
4459 /*-----------------------------------------------------------------*/
4460 /* genCmpEq - generates code for equal to                          */
4461 /*-----------------------------------------------------------------*/
4462 static void
4463 genCmpEq (iCode * ic, iCode * ifx)
4464 {
4465   operand *left, *right, *result;
4466
4467   D (emitcode (";", "genCmpEq ");
4468     );
4469
4470   AOP_OP_2 (ic);
4471   AOP_SET_LOCALS (ic);
4472
4473   /* if literal, literal on the right or
4474      if the right is in a pointer register and left
4475      is not */
4476   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4477       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4478     {
4479       operand *t = IC_RIGHT (ic);
4480       IC_RIGHT (ic) = IC_LEFT (ic);
4481       IC_LEFT (ic) = t;
4482     }
4483
4484   if (ifx &&                    /* !AOP_SIZE(result) */
4485       OP_SYMBOL (result) &&
4486       OP_SYMBOL (result)->regType == REG_CND)
4487     {
4488       symbol *tlbl;
4489       /* if they are both bit variables */
4490       if (AOP_TYPE (left) == AOP_CRY &&
4491           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4492         {
4493           if (AOP_TYPE (right) == AOP_LIT)
4494             {
4495               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4496               if (lit == 0L)
4497                 {
4498                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4499                   emitcode ("cpl", "c");
4500                 }
4501               else if (lit == 1L)
4502                 {
4503                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4504                 }
4505               else
4506                 {
4507                   emitcode ("clr", "c");
4508                 }
4509               /* AOP_TYPE(right) == AOP_CRY */
4510             }
4511           else
4512             {
4513               symbol *lbl = newiTempLabel (NULL);
4514               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4515               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4516               emitcode ("cpl", "c");
4517               emitcode ("", "%05d$:", (lbl->key + 100));
4518             }
4519           /* if true label then we jump if condition
4520              supplied is true */
4521           tlbl = newiTempLabel (NULL);
4522           if (IC_TRUE (ifx))
4523             {
4524               emitcode ("jnc", "%05d$", tlbl->key + 100);
4525               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4526             }
4527           else
4528             {
4529               emitcode ("jc", "%05d$", tlbl->key + 100);
4530               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4531             }
4532           emitcode ("", "%05d$:", tlbl->key + 100);
4533         }
4534       else
4535         {
4536           tlbl = newiTempLabel (NULL);
4537           gencjneshort (left, right, tlbl);
4538           if (IC_TRUE (ifx))
4539             {
4540               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4541               emitcode ("", "%05d$:", tlbl->key + 100);
4542             }
4543           else
4544             {
4545               symbol *lbl = newiTempLabel (NULL);
4546               emitcode ("sjmp", "%05d$", lbl->key + 100);
4547               emitcode ("", "%05d$:", tlbl->key + 100);
4548               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4549               emitcode ("", "%05d$:", lbl->key + 100);
4550             }
4551         }
4552       /* mark the icode as generated */
4553       ifx->generated = 1;
4554
4555       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4556       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4557       return;
4558     }
4559
4560   /* if they are both bit variables */
4561   if (AOP_TYPE (left) == AOP_CRY &&
4562       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4563     {
4564       if (AOP_TYPE (right) == AOP_LIT)
4565         {
4566           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4567           if (lit == 0L)
4568             {
4569               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4570               emitcode ("cpl", "c");
4571             }
4572           else if (lit == 1L)
4573             {
4574               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4575             }
4576           else
4577             {
4578               emitcode ("clr", "c");
4579             }
4580           /* AOP_TYPE(right) == AOP_CRY */
4581         }
4582       else
4583         {
4584           symbol *lbl = newiTempLabel (NULL);
4585           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4586           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4587           emitcode ("cpl", "c");
4588           emitcode ("", "%05d$:", (lbl->key + 100));
4589         }
4590
4591       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4592       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4593
4594       aopOp (result, ic, TRUE, FALSE);
4595
4596       /* c = 1 if egal */
4597       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4598         {
4599           outBitC (result);
4600           goto release;
4601         }
4602       if (ifx)
4603         {
4604           genIfxJump (ifx, "c");
4605           goto release;
4606         }
4607       /* if the result is used in an arithmetic operation
4608          then put the result in place */
4609       outBitC (result);
4610     }
4611   else
4612     {
4613       gencjne (left, right, newiTempLabel (NULL));
4614
4615       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4616       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4617
4618       aopOp (result, ic, TRUE, FALSE);
4619
4620       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4621         {
4622           aopPut (AOP (result), "a", 0);
4623           goto release;
4624         }
4625       if (ifx)
4626         {
4627           genIfxJump (ifx, "a");
4628           goto release;
4629         }
4630       /* if the result is used in an arithmetic operation
4631          then put the result in place */
4632       if (AOP_TYPE (result) != AOP_CRY)
4633         outAcc (result);
4634       /* leave the result in acc */
4635     }
4636
4637 release:
4638   freeAsmop (result, NULL, ic, TRUE);
4639 }
4640
4641 /*-----------------------------------------------------------------*/
4642 /* ifxForOp - returns the icode containing the ifx for operand     */
4643 /*-----------------------------------------------------------------*/
4644 static iCode *
4645 ifxForOp (operand * op, iCode * ic)
4646 {
4647   /* if true symbol then needs to be assigned */
4648   if (IS_TRUE_SYMOP (op))
4649     return NULL;
4650
4651   /* if this has register type condition and
4652      the next instruction is ifx with the same operand
4653      and live to of the operand is upto the ifx only then */
4654   if (ic->next &&
4655       ic->next->op == IFX &&
4656       IC_COND (ic->next)->key == op->key &&
4657       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4658     return ic->next;
4659
4660   return NULL;
4661 }
4662 /*-----------------------------------------------------------------*/
4663 /* genAndOp - for && operation                                     */
4664 /*-----------------------------------------------------------------*/
4665 static void
4666 genAndOp (iCode * ic)
4667 {
4668   operand *left, *right, *result;
4669   symbol *tlbl;
4670
4671   D (emitcode (";", "genAndOp "););
4672
4673   /* note here that && operations that are in an
4674      if statement are taken away by backPatchLabels
4675      only those used in arthmetic operations remain */
4676   AOP_OP_2 (ic);
4677   AOP_SET_LOCALS (ic);
4678
4679   /* if both are bit variables */
4680   if (AOP_TYPE (left) == AOP_CRY &&
4681       AOP_TYPE (right) == AOP_CRY)
4682     {
4683       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4684       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4685       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4686       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4687   
4688       aopOp (result,ic,FALSE, FALSE);
4689       outBitC (result);
4690     }
4691   else
4692     {
4693       tlbl = newiTempLabel (NULL);
4694       toBoolean (left);
4695       emitcode ("jz", "%05d$", tlbl->key + 100);
4696       toBoolean (right);
4697       emitcode ("", "%05d$:", tlbl->key + 100);
4698       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4699       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4700   
4701       aopOp (result,ic,FALSE, FALSE);
4702       outBitAcc (result);
4703     }
4704     freeAsmop (result, NULL, ic, TRUE);
4705 }
4706
4707
4708 /*-----------------------------------------------------------------*/
4709 /* genOrOp - for || operation                                      */
4710 /*-----------------------------------------------------------------*/
4711 static void
4712 genOrOp (iCode * ic)
4713 {
4714   operand *left, *right, *result;
4715   symbol *tlbl;
4716
4717   D (emitcode (";", "genOrOp "););
4718
4719   /* note here that || operations that are in an
4720      if statement are taken away by backPatchLabels
4721      only those used in arthmetic operations remain */
4722   AOP_OP_2 (ic);
4723   AOP_SET_LOCALS (ic);
4724
4725   /* if both are bit variables */
4726   if (AOP_TYPE (left) == AOP_CRY &&
4727       AOP_TYPE (right) == AOP_CRY)
4728     {
4729       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4730       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4731       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4732       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4733   
4734       aopOp (result,ic,FALSE, FALSE);
4735       
4736       outBitC (result);
4737     }
4738   else
4739     {
4740       tlbl = newiTempLabel (NULL);
4741       toBoolean (left);
4742       emitcode ("jnz", "%05d$", tlbl->key + 100);
4743       toBoolean (right);
4744       emitcode ("", "%05d$:", tlbl->key + 100);
4745       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4746       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4747   
4748       aopOp (result,ic,FALSE, FALSE);
4749       
4750       outBitAcc (result);
4751     }
4752
4753   freeAsmop (result, NULL, ic, TRUE);
4754 }
4755
4756 /*-----------------------------------------------------------------*/
4757 /* isLiteralBit - test if lit == 2^n                               */
4758 /*-----------------------------------------------------------------*/
4759 static int
4760 isLiteralBit (unsigned long lit)
4761 {
4762   unsigned long pw[32] =
4763   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4764    0x100L, 0x200L, 0x400L, 0x800L,
4765    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4766    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4767    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4768    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4769    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4770   int idx;
4771
4772   for (idx = 0; idx < 32; idx++)
4773     if (lit == pw[idx])
4774       return idx + 1;
4775   return 0;
4776 }
4777
4778 /*-----------------------------------------------------------------*/
4779 /* continueIfTrue -                                                */
4780 /*-----------------------------------------------------------------*/
4781 static void
4782 continueIfTrue (iCode * ic)
4783 {
4784   if (IC_TRUE (ic))
4785     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4786   ic->generated = 1;
4787 }
4788
4789 /*-----------------------------------------------------------------*/
4790 /* jmpIfTrue -                                                     */
4791 /*-----------------------------------------------------------------*/
4792 static void
4793 jumpIfTrue (iCode * ic)
4794 {
4795   if (!IC_TRUE (ic))
4796     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4797   ic->generated = 1;
4798 }
4799
4800 /*-----------------------------------------------------------------*/
4801 /* jmpTrueOrFalse -                                                */
4802 /*-----------------------------------------------------------------*/
4803 static void
4804 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4805 {
4806   // ugly but optimized by peephole
4807   if (IC_TRUE (ic))
4808     {
4809       symbol *nlbl = newiTempLabel (NULL);
4810       emitcode ("sjmp", "%05d$", nlbl->key + 100);
4811       emitcode ("", "%05d$:", tlbl->key + 100);
4812       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4813       emitcode ("", "%05d$:", nlbl->key + 100);
4814     }
4815   else
4816     {
4817       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4818       emitcode ("", "%05d$:", tlbl->key + 100);
4819     }
4820   ic->generated = 1;
4821 }
4822
4823 // Generate code to perform a bit-wise logic operation
4824 // on two operands in far space (assumed to already have been 
4825 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4826 // in far space. This requires pushing the result on the stack
4827 // then popping it into the result.
4828 static void
4829 genFarFarLogicOp(iCode *ic, char *logicOp)
4830 {
4831       int size, resultSize, compSize;
4832       int offset = 0;
4833       
4834       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4835       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
4836                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4837       
4838       _startLazyDPSEvaluation();
4839       for (size = compSize; (size--); offset++)
4840       {
4841           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4842           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4843           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4844           
4845           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4846           emitcode ("push", "acc");
4847       }
4848       _endLazyDPSEvaluation();
4849      
4850       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4851       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4852       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4853      
4854       resultSize = AOP_SIZE(IC_RESULT(ic));
4855
4856       ADJUST_PUSHED_RESULT(compSize, resultSize);
4857
4858       _startLazyDPSEvaluation();
4859       while (compSize--)
4860       {
4861           emitcode ("pop", "acc");
4862           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4863       }
4864       _endLazyDPSEvaluation();
4865       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4866 }
4867
4868
4869 /*-----------------------------------------------------------------*/
4870 /* genAnd  - code for and                                          */
4871 /*-----------------------------------------------------------------*/
4872 static void
4873 genAnd (iCode * ic, iCode * ifx)
4874 {
4875   operand *left, *right, *result;
4876   int size, offset = 0;
4877   unsigned long lit = 0L;
4878   int bytelit = 0;
4879   char buffer[10];
4880   bool pushResult;
4881
4882   D (emitcode (";", "genAnd "););
4883
4884   AOP_OP_3_NOFATAL (ic, pushResult);
4885   AOP_SET_LOCALS (ic);
4886
4887   if (pushResult)
4888   {
4889       genFarFarLogicOp(ic, "anl");
4890       return;
4891   }  
4892
4893 #ifdef DEBUG_TYPE
4894   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4895             AOP_TYPE (result),
4896             AOP_TYPE (left), AOP_TYPE (right));
4897   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4898             AOP_SIZE (result),
4899             AOP_SIZE (left), AOP_SIZE (right));
4900 #endif
4901
4902   /* if left is a literal & right is not then exchange them */
4903   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4904       AOP_NEEDSACC (left))
4905     {
4906       operand *tmp = right;
4907       right = left;
4908       left = tmp;
4909     }
4910
4911   /* if result = right then exchange them */
4912   if (sameRegs (AOP (result), AOP (right)))
4913     {
4914       operand *tmp = right;
4915       right = left;
4916       left = tmp;
4917     }
4918
4919   /* if right is bit then exchange them */
4920   if (AOP_TYPE (right) == AOP_CRY &&
4921       AOP_TYPE (left) != AOP_CRY)
4922     {
4923       operand *tmp = right;
4924       right = left;
4925       left = tmp;
4926     }
4927   if (AOP_TYPE (right) == AOP_LIT)
4928     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4929
4930   size = AOP_SIZE (result);
4931
4932   // if(bit & yy)
4933   // result = bit & yy;
4934   if (AOP_TYPE (left) == AOP_CRY)
4935     {
4936       // c = bit & literal;
4937       if (AOP_TYPE (right) == AOP_LIT)
4938         {
4939           if (lit & 1)
4940             {
4941               if (size && sameRegs (AOP (result), AOP (left)))
4942                 // no change
4943                 goto release;
4944               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4945             }
4946           else
4947             {
4948               // bit(result) = 0;
4949               if (size && (AOP_TYPE (result) == AOP_CRY))
4950                 {
4951                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4952                   goto release;
4953                 }
4954               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4955                 {
4956                   jumpIfTrue (ifx);
4957                   goto release;
4958                 }
4959               emitcode ("clr", "c");
4960             }
4961         }
4962       else
4963         {
4964           if (AOP_TYPE (right) == AOP_CRY)
4965             {
4966               // c = bit & bit;
4967               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4968               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4969             }
4970           else
4971             {
4972               // c = bit & val;
4973               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4974               // c = lsb
4975               emitcode ("rrc", "a");
4976               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4977             }
4978         }
4979       // bit = c
4980       // val = c
4981       if (size)
4982         outBitC (result);
4983       // if(bit & ...)
4984       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4985         genIfxJump (ifx, "c");
4986       goto release;
4987     }
4988
4989   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4990   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4991   if ((AOP_TYPE (right) == AOP_LIT) &&
4992       (AOP_TYPE (result) == AOP_CRY) &&
4993       (AOP_TYPE (left) != AOP_CRY))
4994     {
4995       int posbit = isLiteralBit (lit);
4996       /* left &  2^n */
4997       if (posbit)
4998         {
4999           posbit--;
5000           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5001           // bit = left & 2^n
5002           if (size)
5003             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5004           // if(left &  2^n)
5005           else
5006             {
5007               if (ifx)
5008                 {
5009                   sprintf (buffer, "acc.%d", posbit & 0x07);
5010                   genIfxJump (ifx, buffer);
5011                 }
5012               goto release;
5013             }
5014         }
5015       else
5016         {
5017           symbol *tlbl = newiTempLabel (NULL);
5018           int sizel = AOP_SIZE (left);
5019           if (size)
5020             emitcode ("setb", "c");
5021           while (sizel--)
5022             {
5023               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5024                 {
5025                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5026                   // byte ==  2^n ?
5027                   if ((posbit = isLiteralBit (bytelit)) != 0)
5028                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5029                   else
5030                     {
5031                       if (bytelit != 0x0FFL)
5032                         emitcode ("anl", "a,%s",
5033                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5034                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5035                     }
5036                 }
5037               offset++;
5038             }
5039           // bit = left & literal
5040           if (size)
5041             {
5042               emitcode ("clr", "c");
5043               emitcode ("", "%05d$:", tlbl->key + 100);
5044             }
5045           // if(left & literal)
5046           else
5047             {
5048               if (ifx)
5049                 jmpTrueOrFalse (ifx, tlbl);
5050               goto release;
5051             }
5052         }
5053       outBitC (result);
5054       goto release;
5055     }
5056
5057   /* if left is same as result */
5058   if (sameRegs (AOP (result), AOP (left)))
5059     {
5060       for (; size--; offset++)
5061         {
5062           if (AOP_TYPE (right) == AOP_LIT)
5063             {
5064               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5065                 continue;
5066               else if (bytelit == 0)
5067                 aopPut (AOP (result), zero, offset);
5068               else if (IS_AOP_PREG (result))
5069                 {
5070                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5071                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5072                   aopPut (AOP (result), "a", offset);
5073                 }
5074               else
5075                 emitcode ("anl", "%s,%s",
5076                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5077                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5078             }
5079           else
5080             {
5081               if (AOP_TYPE (left) == AOP_ACC)
5082                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5083               else
5084                 {
5085                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5086                   if (IS_AOP_PREG (result))
5087                     {
5088                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5089                       aopPut (AOP (result), "a", offset);
5090
5091                     }
5092                   else
5093                     emitcode ("anl", "%s,a",
5094                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5095                 }
5096             }
5097         }
5098     }
5099   else
5100     {
5101       // left & result in different registers
5102       if (AOP_TYPE (result) == AOP_CRY)
5103         {
5104           // result = bit
5105           // if(size), result in bit
5106           // if(!size && ifx), conditional oper: if(left & right)
5107           symbol *tlbl = newiTempLabel (NULL);
5108           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5109           if (size)
5110             emitcode ("setb", "c");
5111           while (sizer--)
5112             {
5113               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5114               emitcode ("anl", "a,%s",
5115                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5116               emitcode ("jnz", "%05d$", tlbl->key + 100);
5117               offset++;
5118             }
5119           if (size)
5120             {
5121               CLRC;
5122               emitcode ("", "%05d$:", tlbl->key + 100);
5123               outBitC (result);
5124             }
5125           else if (ifx)
5126             jmpTrueOrFalse (ifx, tlbl);
5127         }
5128       else
5129         {
5130           for (; (size--); offset++)
5131             {
5132               // normal case
5133               // result = left & right
5134               if (AOP_TYPE (right) == AOP_LIT)
5135                 {
5136                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5137                     {
5138                       aopPut (AOP (result),
5139                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5140                               offset);
5141                       continue;
5142                     }
5143                   else if (bytelit == 0)
5144                     {
5145                       aopPut (AOP (result), zero, offset);
5146                       continue;
5147                     }
5148                   D (emitcode (";", "better literal AND.");
5149                     );
5150                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5151                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5152                                                     FALSE, FALSE, FALSE));
5153
5154                 }
5155               else
5156                 {
5157                   // faster than result <- left, anl result,right
5158                   // and better if result is SFR
5159                   if (AOP_TYPE (left) == AOP_ACC)
5160                     {
5161                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5162                                                        FALSE, FALSE, FALSE));
5163                     }
5164                   else
5165                     {
5166                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5167                       emitcode ("anl", "a,%s",
5168                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5169                     }
5170                 }
5171               aopPut (AOP (result), "a", offset);
5172             }
5173         }
5174     }
5175
5176 release:
5177   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5178   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5179   freeAsmop (result, NULL, ic, TRUE);
5180 }
5181
5182
5183 /*-----------------------------------------------------------------*/
5184 /* genOr  - code for or                                            */
5185 /*-----------------------------------------------------------------*/
5186 static void
5187 genOr (iCode * ic, iCode * ifx)
5188 {
5189   operand *left, *right, *result;
5190   int size, offset = 0;
5191   unsigned long lit = 0L;
5192   bool     pushResult;
5193
5194   D (emitcode (";", "genOr "););
5195
5196   AOP_OP_3_NOFATAL (ic, pushResult);
5197   AOP_SET_LOCALS (ic);
5198
5199   if (pushResult)
5200   {
5201       genFarFarLogicOp(ic, "orl");
5202       return;
5203   }
5204
5205
5206 #ifdef DEBUG_TYPE
5207   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5208             AOP_TYPE (result),
5209             AOP_TYPE (left), AOP_TYPE (right));
5210   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5211             AOP_SIZE (result),
5212             AOP_SIZE (left), AOP_SIZE (right));
5213 #endif
5214
5215   /* if left is a literal & right is not then exchange them */
5216   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5217       AOP_NEEDSACC (left))
5218     {
5219       operand *tmp = right;
5220       right = left;
5221       left = tmp;
5222     }
5223
5224   /* if result = right then exchange them */
5225   if (sameRegs (AOP (result), AOP (right)))
5226     {
5227       operand *tmp = right;
5228       right = left;
5229       left = tmp;
5230     }
5231
5232   /* if right is bit then exchange them */
5233   if (AOP_TYPE (right) == AOP_CRY &&
5234       AOP_TYPE (left) != AOP_CRY)
5235     {
5236       operand *tmp = right;
5237       right = left;
5238       left = tmp;
5239     }
5240   if (AOP_TYPE (right) == AOP_LIT)
5241     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5242
5243   size = AOP_SIZE (result);
5244
5245   // if(bit | yy)
5246   // xx = bit | yy;
5247   if (AOP_TYPE (left) == AOP_CRY)
5248     {
5249       if (AOP_TYPE (right) == AOP_LIT)
5250         {
5251           // c = bit & literal;
5252           if (lit)
5253             {
5254               // lit != 0 => result = 1
5255               if (AOP_TYPE (result) == AOP_CRY)
5256                 {
5257                   if (size)
5258                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5259                   else if (ifx)
5260                     continueIfTrue (ifx);
5261                   goto release;
5262                 }
5263               emitcode ("setb", "c");
5264             }
5265           else
5266             {
5267               // lit == 0 => result = left
5268               if (size && sameRegs (AOP (result), AOP (left)))
5269                 goto release;
5270               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5271             }
5272         }
5273       else
5274         {
5275           if (AOP_TYPE (right) == AOP_CRY)
5276             {
5277               // c = bit | bit;
5278               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5279               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5280             }
5281           else
5282             {
5283               // c = bit | val;
5284               symbol *tlbl = newiTempLabel (NULL);
5285               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5286                 emitcode ("setb", "c");
5287               emitcode ("jb", "%s,%05d$",
5288                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5289               toBoolean (right);
5290               emitcode ("jnz", "%05d$", tlbl->key + 100);
5291               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5292                 {
5293                   jmpTrueOrFalse (ifx, tlbl);
5294                   goto release;
5295                 }
5296               else
5297                 {
5298                   CLRC;
5299                   emitcode ("", "%05d$:", tlbl->key + 100);
5300                 }
5301             }
5302         }
5303       // bit = c
5304       // val = c
5305       if (size)
5306         outBitC (result);
5307       // if(bit | ...)
5308       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5309         genIfxJump (ifx, "c");
5310       goto release;
5311     }
5312
5313   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5314   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5315   if ((AOP_TYPE (right) == AOP_LIT) &&
5316       (AOP_TYPE (result) == AOP_CRY) &&
5317       (AOP_TYPE (left) != AOP_CRY))
5318     {
5319       if (lit)
5320         {
5321           // result = 1
5322           if (size)
5323             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5324           else
5325             continueIfTrue (ifx);
5326           goto release;
5327         }
5328       else
5329         {
5330           // lit = 0, result = boolean(left)
5331           if (size)
5332             emitcode ("setb", "c");
5333           toBoolean (right);
5334           if (size)
5335             {
5336               symbol *tlbl = newiTempLabel (NULL);
5337               emitcode ("jnz", "%05d$", tlbl->key + 100);
5338               CLRC;
5339               emitcode ("", "%05d$:", tlbl->key + 100);
5340             }
5341           else
5342             {
5343               genIfxJump (ifx, "a");
5344               goto release;
5345             }
5346         }
5347       outBitC (result);
5348       goto release;
5349     }
5350
5351   /* if left is same as result */
5352   if (sameRegs (AOP (result), AOP (left)))
5353     {
5354       for (; size--; offset++)
5355         {
5356           if (AOP_TYPE (right) == AOP_LIT)
5357             {
5358               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5359                 {
5360                   continue;
5361                 }
5362               else
5363                 {
5364                   if (IS_AOP_PREG (left))
5365                     {
5366                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5367                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5368                       aopPut (AOP (result), "a", offset);
5369                     }
5370                   else
5371                     {
5372                       emitcode ("orl", "%s,%s",
5373                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5374                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5375                     }
5376                 }
5377             }
5378           else
5379             {
5380               if (AOP_TYPE (left) == AOP_ACC)
5381                 {
5382                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5383                 }
5384               else
5385                 {
5386                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5387                   if (IS_AOP_PREG (left))
5388                     {
5389                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5390                       aopPut (AOP (result), "a", offset);
5391                     }
5392                   else
5393                     {
5394                       emitcode ("orl", "%s,a",
5395                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5396                     }
5397                 }
5398             }
5399         }
5400     }
5401   else
5402     {
5403       // left & result in different registers
5404       if (AOP_TYPE (result) == AOP_CRY)
5405         {
5406           // result = bit
5407           // if(size), result in bit
5408           // if(!size && ifx), conditional oper: if(left | right)
5409           symbol *tlbl = newiTempLabel (NULL);
5410           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5411           if (size)
5412             emitcode ("setb", "c");
5413           while (sizer--)
5414             {
5415               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5416               emitcode ("orl", "a,%s",
5417                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5418               emitcode ("jnz", "%05d$", tlbl->key + 100);
5419               offset++;
5420             }
5421           if (size)
5422             {
5423               CLRC;
5424               emitcode ("", "%05d$:", tlbl->key + 100);
5425               outBitC (result);
5426             }
5427           else if (ifx)
5428             jmpTrueOrFalse (ifx, tlbl);
5429         }
5430       else
5431         {
5432           for (; (size--); offset++)
5433             {
5434               // normal case
5435               // result = left & right
5436               if (AOP_TYPE (right) == AOP_LIT)
5437                 {
5438                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5439                     {
5440                       aopPut (AOP (result),
5441                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5442                               offset);
5443                       continue;
5444                     }
5445                   D (emitcode (";", "better literal OR.");
5446                     );
5447                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5448                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5449                                                     FALSE, FALSE, FALSE));
5450
5451                 }
5452               else
5453                 {
5454                   // faster than result <- left, anl result,right
5455                   // and better if result is SFR
5456                   if (AOP_TYPE (left) == AOP_ACC)
5457                     {
5458                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5459                                                        FALSE, FALSE, FALSE));
5460                     }
5461                   else
5462                     {
5463                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5464                       emitcode ("orl", "a,%s",
5465                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5466                     }
5467                 }
5468               aopPut (AOP (result), "a", offset);
5469             }
5470         }
5471     }
5472
5473 release:
5474   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5475   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5476   freeAsmop (result, NULL, ic, TRUE);
5477 }
5478
5479 /*-----------------------------------------------------------------*/
5480 /* genXor - code for xclusive or                                   */
5481 /*-----------------------------------------------------------------*/
5482 static void
5483 genXor (iCode * ic, iCode * ifx)
5484 {
5485   operand *left, *right, *result;
5486   int size, offset = 0;
5487   unsigned long lit = 0L;
5488   bool pushResult;
5489
5490   D (emitcode (";", "genXor "););
5491
5492   AOP_OP_3_NOFATAL (ic, pushResult);
5493   AOP_SET_LOCALS (ic);
5494
5495   if (pushResult)
5496   {
5497       genFarFarLogicOp(ic, "xrl");
5498       return;
5499   }  
5500
5501 #ifdef DEBUG_TYPE
5502   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5503             AOP_TYPE (result),
5504             AOP_TYPE (left), AOP_TYPE (right));
5505   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5506             AOP_SIZE (result),
5507             AOP_SIZE (left), AOP_SIZE (right));
5508 #endif
5509
5510   /* if left is a literal & right is not ||
5511      if left needs acc & right does not */
5512   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5513       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5514     {
5515       operand *tmp = right;
5516       right = left;
5517       left = tmp;
5518     }
5519
5520   /* if result = right then exchange them */
5521   if (sameRegs (AOP (result), AOP (right)))
5522     {
5523       operand *tmp = right;
5524       right = left;
5525       left = tmp;
5526     }
5527
5528   /* if right is bit then exchange them */
5529   if (AOP_TYPE (right) == AOP_CRY &&
5530       AOP_TYPE (left) != AOP_CRY)
5531     {
5532       operand *tmp = right;
5533       right = left;
5534       left = tmp;
5535     }
5536   if (AOP_TYPE (right) == AOP_LIT)
5537     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5538
5539   size = AOP_SIZE (result);
5540
5541   // if(bit ^ yy)
5542   // xx = bit ^ yy;
5543   if (AOP_TYPE (left) == AOP_CRY)
5544     {
5545       if (AOP_TYPE (right) == AOP_LIT)
5546         {
5547           // c = bit & literal;
5548           if (lit >> 1)
5549             {
5550               // lit>>1  != 0 => result = 1
5551               if (AOP_TYPE (result) == AOP_CRY)
5552                 {
5553                   if (size)
5554                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5555                   else if (ifx)
5556                     continueIfTrue (ifx);
5557                   goto release;
5558                 }
5559               emitcode ("setb", "c");
5560             }
5561           else
5562             {
5563               // lit == (0 or 1)
5564               if (lit == 0)
5565                 {
5566                   // lit == 0, result = left
5567                   if (size && sameRegs (AOP (result), AOP (left)))
5568                     goto release;
5569                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5570                 }
5571               else
5572                 {
5573                   // lit == 1, result = not(left)
5574                   if (size && sameRegs (AOP (result), AOP (left)))
5575                     {
5576                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5577                       goto release;
5578                     }
5579                   else
5580                     {
5581                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5582                       emitcode ("cpl", "c");
5583                     }
5584                 }
5585             }
5586
5587         }
5588       else
5589         {
5590           // right != literal
5591           symbol *tlbl = newiTempLabel (NULL);
5592           if (AOP_TYPE (right) == AOP_CRY)
5593             {
5594               // c = bit ^ bit;
5595               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5596             }
5597           else
5598             {
5599               int sizer = AOP_SIZE (right);
5600               // c = bit ^ val
5601               // if val>>1 != 0, result = 1
5602               emitcode ("setb", "c");
5603               while (sizer)
5604                 {
5605                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5606                   if (sizer == 1)
5607                     // test the msb of the lsb
5608                     emitcode ("anl", "a,#0xfe");
5609                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5610                   sizer--;
5611                 }
5612               // val = (0,1)
5613               emitcode ("rrc", "a");
5614             }
5615           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5616           emitcode ("cpl", "c");
5617           emitcode ("", "%05d$:", (tlbl->key + 100));
5618         }
5619       // bit = c
5620       // val = c
5621       if (size)
5622         outBitC (result);
5623       // if(bit | ...)
5624       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5625         genIfxJump (ifx, "c");
5626       goto release;
5627     }
5628
5629   if (sameRegs (AOP (result), AOP (left)))
5630     {
5631       /* if left is same as result */
5632       for (; size--; offset++)
5633         {
5634           if (AOP_TYPE (right) == AOP_LIT)
5635             {
5636               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5637                 continue;
5638               else if (IS_AOP_PREG (left))
5639                 {
5640                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5641                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5642                   aopPut (AOP (result), "a", offset);
5643                 }
5644               else
5645                 emitcode ("xrl", "%s,%s",
5646                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5647                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5648             }
5649           else
5650             {
5651               if (AOP_TYPE (left) == AOP_ACC)
5652                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5653               else
5654                 {
5655                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5656                   if (IS_AOP_PREG (left))
5657                     {
5658                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5659                       aopPut (AOP (result), "a", offset);
5660                     }
5661                   else
5662                     emitcode ("xrl", "%s,a",
5663                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5664                 }
5665             }
5666         }
5667     }
5668   else
5669     {
5670       // left & result in different registers
5671       if (AOP_TYPE (result) == AOP_CRY)
5672         {
5673           // result = bit
5674           // if(size), result in bit
5675           // if(!size && ifx), conditional oper: if(left ^ right)
5676           symbol *tlbl = newiTempLabel (NULL);
5677           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5678           if (size)
5679             emitcode ("setb", "c");
5680           while (sizer--)
5681             {
5682               if ((AOP_TYPE (right) == AOP_LIT) &&
5683                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5684                 {
5685                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5686                 }
5687               else
5688                 {
5689                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5690                   emitcode ("xrl", "a,%s",
5691                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5692                 }
5693               emitcode ("jnz", "%05d$", tlbl->key + 100);
5694               offset++;
5695             }
5696           if (size)
5697             {
5698               CLRC;
5699               emitcode ("", "%05d$:", tlbl->key + 100);
5700               outBitC (result);
5701             }
5702           else if (ifx)
5703             jmpTrueOrFalse (ifx, tlbl);
5704         }
5705       else
5706         for (; (size--); offset++)
5707           {
5708             // normal case
5709             // result = left & right
5710             if (AOP_TYPE (right) == AOP_LIT)
5711               {
5712                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5713                   {
5714                     aopPut (AOP (result),
5715                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5716                             offset);
5717                     continue;
5718                   }
5719                 D (emitcode (";", "better literal XOR.");
5720                   );
5721                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5722                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5723                                                   FALSE, FALSE, FALSE));
5724               }
5725             else
5726               {
5727                 // faster than result <- left, anl result,right
5728                 // and better if result is SFR
5729                 if (AOP_TYPE (left) == AOP_ACC)
5730                   {
5731                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5732                                                      FALSE, FALSE, FALSE));
5733                   }
5734                 else
5735                   {
5736                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5737                     emitcode ("xrl", "a,%s",
5738                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5739                   }
5740               }
5741             aopPut (AOP (result), "a", offset);
5742           }
5743     }
5744
5745 release:
5746   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5747   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5748   freeAsmop (result, NULL, ic, TRUE);
5749 }
5750
5751 /*-----------------------------------------------------------------*/
5752 /* genInline - write the inline code out                           */
5753 /*-----------------------------------------------------------------*/
5754 static void
5755 genInline (iCode * ic)
5756 {
5757   char buffer[MAX_INLINEASM];
5758   char *bp = buffer;
5759   char *bp1 = buffer;
5760
5761   D (emitcode (";", "genInline ");
5762     );
5763
5764   _G.inLine += (!options.asmpeep);
5765   strcpy (buffer, IC_INLINE (ic));
5766
5767   /* emit each line as a code */
5768   while (*bp)
5769     {
5770       if (*bp == '\n')
5771         {
5772           *bp++ = '\0';
5773           emitcode (bp1, "");
5774           bp1 = bp;
5775         }
5776       else
5777         {
5778           if (*bp == ':')
5779             {
5780               bp++;
5781               *bp = '\0';
5782               bp++;
5783               emitcode (bp1, "");
5784               bp1 = bp;
5785             }
5786           else
5787             bp++;
5788         }
5789     }
5790   if (bp1 != bp)
5791     emitcode (bp1, "");
5792   /*     emitcode("",buffer); */
5793   _G.inLine -= (!options.asmpeep);
5794 }
5795
5796 /*-----------------------------------------------------------------*/
5797 /* genRRC - rotate right with carry                                */
5798 /*-----------------------------------------------------------------*/
5799 static void
5800 genRRC (iCode * ic)
5801 {
5802   operand *left, *result;
5803   int size, offset = 0;
5804   char *l;
5805
5806   D (emitcode (";", "genRRC ");
5807     );
5808
5809   /* rotate right with carry */
5810   left = IC_LEFT (ic);
5811   result = IC_RESULT (ic);
5812   aopOp (left, ic, FALSE, FALSE);
5813   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5814
5815   /* move it to the result */
5816   size = AOP_SIZE (result);
5817   offset = size - 1;
5818   CLRC;
5819
5820   _startLazyDPSEvaluation ();
5821   while (size--)
5822     {
5823       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5824       MOVA (l);
5825       emitcode ("rrc", "a");
5826       if (AOP_SIZE (result) > 1)
5827         aopPut (AOP (result), "a", offset--);
5828     }
5829   _endLazyDPSEvaluation ();
5830
5831   /* now we need to put the carry into the
5832      highest order byte of the result */
5833   if (AOP_SIZE (result) > 1)
5834     {
5835       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5836       MOVA (l);
5837     }
5838   emitcode ("mov", "acc.7,c");
5839   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5840   freeAsmop (left, NULL, ic, TRUE);
5841   freeAsmop (result, NULL, ic, TRUE);
5842 }
5843
5844 /*-----------------------------------------------------------------*/
5845 /* genRLC - generate code for rotate left with carry               */
5846 /*-----------------------------------------------------------------*/
5847 static void
5848 genRLC (iCode * ic)
5849 {
5850   operand *left, *result;
5851   int size, offset = 0;
5852   char *l;
5853
5854   D (emitcode (";", "genRLC ");
5855     );
5856
5857   /* rotate right with carry */
5858   left = IC_LEFT (ic);
5859   result = IC_RESULT (ic);
5860   aopOp (left, ic, FALSE, FALSE);
5861   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5862
5863   /* move it to the result */
5864   size = AOP_SIZE (result);
5865   offset = 0;
5866   if (size--)
5867     {
5868       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5869       MOVA (l);
5870       emitcode ("add", "a,acc");
5871       if (AOP_SIZE (result) > 1)
5872         {
5873           aopPut (AOP (result), "a", offset++);
5874         }
5875
5876       _startLazyDPSEvaluation ();
5877       while (size--)
5878         {
5879           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5880           MOVA (l);
5881           emitcode ("rlc", "a");
5882           if (AOP_SIZE (result) > 1)
5883             aopPut (AOP (result), "a", offset++);
5884         }
5885       _endLazyDPSEvaluation ();
5886     }
5887   /* now we need to put the carry into the
5888      highest order byte of the result */
5889   if (AOP_SIZE (result) > 1)
5890     {
5891       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5892       MOVA (l);
5893     }
5894   emitcode ("mov", "acc.0,c");
5895   aopPut (AOP (result), "a", 0);
5896   freeAsmop (left, NULL, ic, TRUE);
5897   freeAsmop (result, NULL, ic, TRUE);
5898 }
5899
5900 /*-----------------------------------------------------------------*/
5901 /* genGetHbit - generates code get highest order bit               */
5902 /*-----------------------------------------------------------------*/
5903 static void
5904 genGetHbit (iCode * ic)
5905 {
5906   operand *left, *result;
5907   left = IC_LEFT (ic);
5908   result = IC_RESULT (ic);
5909   aopOp (left, ic, FALSE, FALSE);
5910   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5911
5912   D (emitcode (";", "genGetHbit ");
5913     );
5914
5915   /* get the highest order byte into a */
5916   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5917   if (AOP_TYPE (result) == AOP_CRY)
5918     {
5919       emitcode ("rlc", "a");
5920       outBitC (result);
5921     }
5922   else
5923     {
5924       emitcode ("rl", "a");
5925       emitcode ("anl", "a,#0x01");
5926       outAcc (result);
5927     }
5928
5929
5930   freeAsmop (left, NULL, ic, TRUE);
5931   freeAsmop (result, NULL, ic, TRUE);
5932 }
5933
5934 /*-----------------------------------------------------------------*/
5935 /* AccRol - rotate left accumulator by known count                 */
5936 /*-----------------------------------------------------------------*/
5937 static void
5938 AccRol (int shCount)
5939 {
5940   shCount &= 0x0007;            // shCount : 0..7
5941
5942   switch (shCount)
5943     {
5944     case 0:
5945       break;
5946     case 1:
5947       emitcode ("rl", "a");
5948       break;
5949     case 2:
5950       emitcode ("rl", "a");
5951       emitcode ("rl", "a");
5952       break;
5953     case 3:
5954       emitcode ("swap", "a");
5955       emitcode ("rr", "a");
5956       break;
5957     case 4:
5958       emitcode ("swap", "a");
5959       break;
5960     case 5:
5961       emitcode ("swap", "a");
5962       emitcode ("rl", "a");
5963       break;
5964     case 6:
5965       emitcode ("rr", "a");
5966       emitcode ("rr", "a");
5967       break;
5968     case 7:
5969       emitcode ("rr", "a");
5970       break;
5971     }
5972 }
5973
5974 /*-----------------------------------------------------------------*/
5975 /* AccLsh - left shift accumulator by known count                  */
5976 /*-----------------------------------------------------------------*/
5977 static void
5978 AccLsh (int shCount)
5979 {
5980   if (shCount != 0)
5981     {
5982       if (shCount == 1)
5983         emitcode ("add", "a,acc");
5984       else if (shCount == 2)
5985         {
5986           emitcode ("add", "a,acc");
5987           emitcode ("add", "a,acc");
5988         }
5989       else
5990         {
5991           /* rotate left accumulator */
5992           AccRol (shCount);
5993           /* and kill the lower order bits */
5994           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5995         }
5996     }
5997 }
5998
5999 /*-----------------------------------------------------------------*/
6000 /* AccRsh - right shift accumulator by known count                 */
6001 /*-----------------------------------------------------------------*/
6002 static void
6003 AccRsh (int shCount)
6004 {
6005   if (shCount != 0)
6006     {
6007       if (shCount == 1)
6008         {
6009           CLRC;
6010           emitcode ("rrc", "a");
6011         }
6012       else
6013         {
6014           /* rotate right accumulator */
6015           AccRol (8 - shCount);
6016           /* and kill the higher order bits */
6017           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6018         }
6019     }
6020 }
6021
6022 #if 0
6023 //REMOVE ME!!!
6024 /*-----------------------------------------------------------------*/
6025 /* AccSRsh - signed right shift accumulator by known count                 */
6026 /*-----------------------------------------------------------------*/
6027 static void
6028 AccSRsh (int shCount)
6029 {
6030   symbol *tlbl;
6031   if (shCount != 0)
6032     {
6033       if (shCount == 1)
6034         {
6035           emitcode ("mov", "c,acc.7");
6036           emitcode ("rrc", "a");
6037         }
6038       else if (shCount == 2)
6039         {
6040           emitcode ("mov", "c,acc.7");
6041           emitcode ("rrc", "a");
6042           emitcode ("mov", "c,acc.7");
6043           emitcode ("rrc", "a");
6044         }
6045       else
6046         {
6047           tlbl = newiTempLabel (NULL);
6048           /* rotate right accumulator */
6049           AccRol (8 - shCount);
6050           /* and kill the higher order bits */
6051           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6052           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6053           emitcode ("orl", "a,#0x%02x",
6054                     (unsigned char) ~SRMask[shCount]);
6055           emitcode ("", "%05d$:", tlbl->key + 100);
6056         }
6057     }
6058 }
6059 #endif
6060
6061 #if 0
6062 //REMOVE ME!!!
6063 /*-----------------------------------------------------------------*/
6064 /* shiftR1Left2Result - shift right one byte from left to result   */
6065 /*-----------------------------------------------------------------*/
6066 static void
6067 shiftR1Left2Result (operand * left, int offl,
6068                     operand * result, int offr,
6069                     int shCount, int sign)
6070 {
6071   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6072   /* shift right accumulator */
6073   if (sign)
6074     AccSRsh (shCount);
6075   else
6076     AccRsh (shCount);
6077   aopPut (AOP (result), "a", offr);
6078 }
6079 #endif
6080
6081 #if 0
6082 //REMOVE ME!!!
6083 /*-----------------------------------------------------------------*/
6084 /* shiftL1Left2Result - shift left one byte from left to result    */
6085 /*-----------------------------------------------------------------*/
6086 static void
6087 shiftL1Left2Result (operand * left, int offl,
6088                     operand * result, int offr, int shCount)
6089 {
6090   char *l;
6091   l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6092   MOVA (l);
6093   /* shift left accumulator */
6094   AccLsh (shCount);
6095   aopPut (AOP (result), "a", offr);
6096 }
6097 #endif
6098
6099 #if 0
6100 //REMOVE ME!!!
6101 /*-----------------------------------------------------------------*/
6102 /* movLeft2Result - move byte from left to result                  */
6103 /*-----------------------------------------------------------------*/
6104 static void
6105 movLeft2Result (operand * left, int offl,
6106                 operand * result, int offr, int sign)
6107 {
6108   char *l;
6109   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6110     {
6111       l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6112
6113       if (*l == '@' && (IS_AOP_PREG (result)))
6114         {
6115           emitcode ("mov", "a,%s", l);
6116           aopPut (AOP (result), "a", offr);
6117         }
6118       else
6119         {
6120           if (!sign)
6121             aopPut (AOP (result), l, offr);
6122           else
6123             {
6124               /* MSB sign in acc.7 ! */
6125               if (getDataSize (left) == offl + 1)
6126                 {
6127                   emitcode ("mov", "a,%s", l);
6128                   aopPut (AOP (result), "a", offr);
6129                 }
6130             }
6131         }
6132     }
6133 }
6134 #endif
6135
6136 #if 0
6137 //REMOVE ME!!!
6138 /*-----------------------------------------------------------------*/
6139 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6140 /*-----------------------------------------------------------------*/
6141 static void
6142 AccAXRrl1 (char *x)
6143 {
6144   emitcode ("rrc", "a");
6145   emitcode ("xch", "a,%s", x);
6146   emitcode ("rrc", "a");
6147   emitcode ("xch", "a,%s", x);
6148 }
6149 #endif
6150
6151 #if 0
6152 //REMOVE ME!!!
6153 /*-----------------------------------------------------------------*/
6154 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6155 /*-----------------------------------------------------------------*/
6156 static void
6157 AccAXLrl1 (char *x)
6158 {
6159   emitcode ("xch", "a,%s", x);
6160   emitcode ("rlc", "a");
6161   emitcode ("xch", "a,%s", x);
6162   emitcode ("rlc", "a");
6163 }
6164 #endif
6165
6166 #if 0
6167 //REMOVE ME!!!
6168 /*-----------------------------------------------------------------*/
6169 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6170 /*-----------------------------------------------------------------*/
6171 static void
6172 AccAXLsh1 (char *x)
6173 {
6174   emitcode ("xch", "a,%s", x);
6175   emitcode ("add", "a,acc");
6176   emitcode ("xch", "a,%s", x);
6177   emitcode ("rlc", "a");
6178 }
6179 #endif
6180
6181 #if 0
6182 //REMOVE ME!!!
6183 /*-----------------------------------------------------------------*/
6184 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6185 /*-----------------------------------------------------------------*/
6186 static void
6187 AccAXLsh (char *x, int shCount)
6188 {
6189   switch (shCount)
6190     {
6191     case 0:
6192       break;
6193     case 1:
6194       AccAXLsh1 (x);
6195       break;
6196     case 2:
6197       AccAXLsh1 (x);
6198       AccAXLsh1 (x);
6199       break;
6200     case 3:
6201     case 4:
6202     case 5:                     // AAAAABBB:CCCCCDDD
6203
6204       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6205
6206       emitcode ("anl", "a,#0x%02x",
6207                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6208
6209       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6210
6211       AccRol (shCount);         // DDDCCCCC:BBB00000
6212
6213       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6214
6215       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6216
6217       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6218
6219       emitcode ("anl", "a,#0x%02x",
6220                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6221
6222       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6223
6224       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6225
6226       break;
6227     case 6:                     // AAAAAABB:CCCCCCDD
6228       emitcode ("anl", "a,#0x%02x",
6229                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6230       emitcode ("mov", "c,acc.0");      // c = B
6231       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6232 #if 0
6233       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6234       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6235 #else
6236       emitcode("rrc","a"); 
6237       emitcode("xch","a,%s", x); 
6238       emitcode("rrc","a"); 
6239       emitcode("mov","c,acc.0"); //<< get correct bit 
6240       emitcode("xch","a,%s", x); 
6241
6242       emitcode("rrc","a"); 
6243       emitcode("xch","a,%s", x); 
6244       emitcode("rrc","a"); 
6245       emitcode("xch","a,%s", x); 
6246 #endif
6247       break;
6248     case 7:                     // a:x <<= 7
6249
6250       emitcode ("anl", "a,#0x%02x",
6251                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6252
6253       emitcode ("mov", "c,acc.0");      // c = B
6254
6255       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6256
6257       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6258
6259       break;
6260     default:
6261       break;
6262     }
6263 }
6264 #endif
6265
6266 #if 0
6267 //REMOVE ME!!!
6268 /*-----------------------------------------------------------------*/
6269 /* AccAXRsh - right shift a:x known count (0..7)                   */
6270 /*-----------------------------------------------------------------*/
6271 static void
6272 AccAXRsh (char *x, int shCount)
6273 {
6274   switch (shCount)
6275     {
6276     case 0:
6277       break;
6278     case 1:
6279       CLRC;
6280       AccAXRrl1 (x);            // 0->a:x
6281
6282       break;
6283     case 2:
6284       CLRC;
6285       AccAXRrl1 (x);            // 0->a:x
6286
6287       CLRC;
6288       AccAXRrl1 (x);            // 0->a:x
6289
6290       break;
6291     case 3:
6292     case 4:
6293     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6294
6295       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6296
6297       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6298
6299       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6300
6301       emitcode ("anl", "a,#0x%02x",
6302                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6303
6304       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6305
6306       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6307
6308       emitcode ("anl", "a,#0x%02x",
6309                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6310
6311       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6312
6313       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6314
6315       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6316
6317       break;
6318     case 6:                     // AABBBBBB:CCDDDDDD
6319
6320       emitcode ("mov", "c,acc.7");
6321       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6322
6323       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6324
6325       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6326
6327       emitcode ("anl", "a,#0x%02x",
6328                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6329
6330       break;
6331     case 7:                     // ABBBBBBB:CDDDDDDD
6332
6333       emitcode ("mov", "c,acc.7");      // c = A
6334
6335       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6336
6337       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6338
6339       emitcode ("anl", "a,#0x%02x",
6340                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6341
6342       break;
6343     default:
6344       break;
6345     }
6346 }
6347 #endif
6348
6349 #if 0
6350 //REMOVE ME!!!
6351 /*-----------------------------------------------------------------*/
6352 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6353 /*-----------------------------------------------------------------*/
6354 static void
6355 AccAXRshS (char *x, int shCount)
6356 {
6357   symbol *tlbl;
6358   switch (shCount)
6359     {
6360     case 0:
6361       break;
6362     case 1:
6363       emitcode ("mov", "c,acc.7");
6364       AccAXRrl1 (x);            // s->a:x
6365
6366       break;
6367     case 2:
6368       emitcode ("mov", "c,acc.7");
6369       AccAXRrl1 (x);            // s->a:x
6370
6371       emitcode ("mov", "c,acc.7");
6372       AccAXRrl1 (x);            // s->a:x
6373
6374       break;
6375     case 3:
6376     case 4:
6377     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6378
6379       tlbl = newiTempLabel (NULL);
6380       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6381
6382       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6383
6384       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6385
6386       emitcode ("anl", "a,#0x%02x",
6387                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6388
6389       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6390
6391       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6392
6393       emitcode ("anl", "a,#0x%02x",
6394                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6395
6396       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6397
6398       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6399
6400       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6401
6402       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6403       emitcode ("orl", "a,#0x%02x",
6404                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6405
6406       emitcode ("", "%05d$:", tlbl->key + 100);
6407       break;                    // SSSSAAAA:BBBCCCCC
6408
6409     case 6:                     // AABBBBBB:CCDDDDDD
6410
6411       tlbl = newiTempLabel (NULL);
6412       emitcode ("mov", "c,acc.7");
6413       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6414
6415       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6416
6417       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6418
6419       emitcode ("anl", "a,#0x%02x",
6420                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6421
6422       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6423       emitcode ("orl", "a,#0x%02x",
6424                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6425
6426       emitcode ("", "%05d$:", tlbl->key + 100);
6427       break;
6428     case 7:                     // ABBBBBBB:CDDDDDDD
6429
6430       tlbl = newiTempLabel (NULL);
6431       emitcode ("mov", "c,acc.7");      // c = A
6432
6433       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6434
6435       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6436
6437       emitcode ("anl", "a,#0x%02x",
6438                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6439
6440       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6441       emitcode ("orl", "a,#0x%02x",
6442                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6443
6444       emitcode ("", "%05d$:", tlbl->key + 100);
6445       break;
6446     default:
6447       break;
6448     }
6449 }
6450 #endif
6451
6452 #if 0
6453 //REMOVE ME!!!
6454 /*-----------------------------------------------------------------*/
6455 /* shiftL2Left2Result - shift left two bytes from left to result   */
6456 /*-----------------------------------------------------------------*/
6457 static void
6458 shiftL2Left2Result (operand * left, int offl,
6459                     operand * result, int offr, int shCount)
6460 {
6461   if (sameRegs (AOP (result), AOP (left)) &&
6462       ((offl + MSB16) == offr))
6463     {
6464       /* don't crash result[offr] */
6465       MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6466       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6467     }
6468   else
6469     {
6470       movLeft2Result (left, offl, result, offr, 0);
6471       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6472     }
6473   /* ax << shCount (x = lsb(result)) */
6474   AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6475   aopPut (AOP (result), "a", offr + MSB16);
6476 }
6477 #endif
6478
6479 #if 0
6480 //REMOVE ME!!!
6481 /*-----------------------------------------------------------------*/
6482 /* shiftR2Left2Result - shift right two bytes from left to result  */
6483 /*-----------------------------------------------------------------*/
6484 static void
6485 shiftR2Left2Result (operand * left, int offl,
6486                     operand * result, int offr,
6487                     int shCount, int sign)
6488 {
6489   if (sameRegs (AOP (result), AOP (left)) &&
6490       ((offl + MSB16) == offr))
6491     {
6492       /* don't crash result[offr] */
6493       MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6494       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6495     }
6496   else
6497     {
6498       movLeft2Result (left, offl, result, offr, 0);
6499       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6500     }
6501   /* a:x >> shCount (x = lsb(result)) */
6502   if (sign)
6503     AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6504   else
6505     AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6506   if (getDataSize (result) > 1)
6507     aopPut (AOP (result), "a", offr + MSB16);
6508 }
6509 #endif
6510
6511 #if 0
6512 //REMOVE ME!!!
6513 /*-----------------------------------------------------------------*/
6514 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6515 /*-----------------------------------------------------------------*/
6516 static void
6517 shiftLLeftOrResult (operand * left, int offl,
6518                     operand * result, int offr, int shCount)
6519 {
6520   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6521   /* shift left accumulator */
6522   AccLsh (shCount);
6523   /* or with result */
6524   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6525   /* back to result */
6526   aopPut (AOP (result), "a", offr);
6527 }
6528 #endif
6529
6530 #if 0
6531 //REMOVE ME!!!
6532 /*-----------------------------------------------------------------*/
6533 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6534 /*-----------------------------------------------------------------*/
6535 static void
6536 shiftRLeftOrResult (operand * left, int offl,
6537                     operand * result, int offr, int shCount)
6538 {
6539   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6540   /* shift right accumulator */
6541   AccRsh (shCount);
6542   /* or with result */
6543   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6544   /* back to result */
6545   aopPut (AOP (result), "a", offr);
6546 }
6547 #endif
6548
6549 #if 0
6550 //REMOVE ME!!!
6551 /*-----------------------------------------------------------------*/
6552 /* genlshOne - left shift a one byte quantity by known count       */
6553 /*-----------------------------------------------------------------*/
6554 static void
6555 genlshOne (operand * result, operand * left, int shCount)
6556 {
6557   D (emitcode (";", "genlshOne ");
6558     );
6559   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6560 }
6561 #endif
6562
6563 #if 0
6564 //REMOVE ME!!!
6565 /*-----------------------------------------------------------------*/
6566 /* genlshTwo - left shift two bytes by known amount != 0           */
6567 /*-----------------------------------------------------------------*/
6568 static void
6569 genlshTwo (operand * result, operand * left, int shCount)
6570 {
6571   int size;
6572
6573   D (emitcode (";", "genlshTwo ");
6574     );
6575
6576   size = getDataSize (result);
6577
6578   /* if shCount >= 8 */
6579   if (shCount >= 8)
6580     {
6581       shCount -= 8;
6582
6583       if (size > 1)
6584         {
6585           if (shCount)
6586             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6587           else
6588             movLeft2Result (left, LSB, result, MSB16, 0);
6589         }
6590       aopPut (AOP (result), zero, LSB);
6591     }
6592
6593   /*  1 <= shCount <= 7 */
6594   else
6595     {
6596       if (size == 1)
6597         shiftL1Left2Result (left, LSB, result, LSB, shCount);
6598       else
6599         shiftL2Left2Result (left, LSB, result, LSB, shCount);
6600     }
6601 }
6602 #endif
6603
6604 #if 0
6605 //REMOVE ME!!!
6606 /*-----------------------------------------------------------------*/
6607 /* shiftLLong - shift left one long from left to result            */
6608 /* offl = LSB or MSB16                                             */
6609 /*-----------------------------------------------------------------*/
6610 static void
6611 shiftLLong (operand * left, operand * result, int offr)
6612 {
6613   char *l;
6614   int size = AOP_SIZE (result);
6615
6616   if (size >= LSB + offr)
6617     {
6618       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6619       MOVA (l);
6620       emitcode ("add", "a,acc");
6621       if (sameRegs (AOP (left), AOP (result)) &&
6622           size >= MSB16 + offr && offr != LSB)
6623         emitcode ("xch", "a,%s",
6624                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6625       else
6626         aopPut (AOP (result), "a", LSB + offr);
6627     }
6628
6629   if (size >= MSB16 + offr)
6630     {
6631       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6632         {
6633           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6634           MOVA (l);
6635         }
6636       emitcode ("rlc", "a");
6637       if (sameRegs (AOP (left), AOP (result)) &&
6638           size >= MSB24 + offr && offr != LSB)
6639         emitcode ("xch", "a,%s",
6640                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6641       else
6642         aopPut (AOP (result), "a", MSB16 + offr);
6643     }
6644
6645   if (size >= MSB24 + offr)
6646     {
6647       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6648         {
6649           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6650           MOVA (l);
6651         }
6652       emitcode ("rlc", "a");
6653       if (sameRegs (AOP (left), AOP (result)) &&
6654           size >= MSB32 + offr && offr != LSB)
6655         emitcode ("xch", "a,%s",
6656                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6657       else
6658         aopPut (AOP (result), "a", MSB24 + offr);
6659     }
6660
6661   if (size > MSB32 + offr)
6662     {
6663       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6664         {
6665           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6666           MOVA (l);
6667         }
6668       emitcode ("rlc", "a");
6669       aopPut (AOP (result), "a", MSB32 + offr);
6670     }
6671   if (offr != LSB)
6672     aopPut (AOP (result), zero, LSB);
6673 }
6674 #endif
6675
6676 #if 0
6677 //REMOVE ME!!!
6678 /*-----------------------------------------------------------------*/
6679 /* genlshFour - shift four byte by a known amount != 0             */
6680 /*-----------------------------------------------------------------*/
6681 static void
6682 genlshFour (operand * result, operand * left, int shCount)
6683 {
6684   int size;
6685
6686   D (emitcode (";", "genlshFour ");
6687     );
6688
6689   size = AOP_SIZE (result);
6690
6691   /* if shifting more that 3 bytes */
6692   if (shCount >= 24)
6693     {
6694       shCount -= 24;
6695       if (shCount)
6696         /* lowest order of left goes to the highest
6697            order of the destination */
6698         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6699       else
6700         movLeft2Result (left, LSB, result, MSB32, 0);
6701       aopPut (AOP (result), zero, LSB);
6702       aopPut (AOP (result), zero, MSB16);
6703       aopPut (AOP (result), zero, MSB24);
6704       return;
6705     }
6706
6707   /* more than two bytes */
6708   else if (shCount >= 16)
6709     {
6710       /* lower order two bytes goes to higher order two bytes */
6711       shCount -= 16;
6712       /* if some more remaining */
6713       if (shCount)
6714         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6715       else
6716         {
6717           movLeft2Result (left, MSB16, result, MSB32, 0);
6718           movLeft2Result (left, LSB, result, MSB24, 0);
6719         }
6720       aopPut (AOP (result), zero, MSB16);
6721       aopPut (AOP (result), zero, LSB);
6722       return;
6723     }
6724
6725   /* if more than 1 byte */
6726   else if (shCount >= 8)
6727     {
6728       /* lower order three bytes goes to higher order  three bytes */
6729       shCount -= 8;
6730       if (size == 2)
6731         {
6732           if (shCount)
6733             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6734           else
6735             movLeft2Result (left, LSB, result, MSB16, 0);
6736         }
6737       else
6738         {                       /* size = 4 */
6739           if (shCount == 0)
6740             {
6741               movLeft2Result (left, MSB24, result, MSB32, 0);
6742               movLeft2Result (left, MSB16, result, MSB24, 0);
6743               movLeft2Result (left, LSB, result, MSB16, 0);
6744               aopPut (AOP (result), zero, LSB);
6745             }
6746           else if (shCount == 1)
6747             shiftLLong (left, result, MSB16);
6748           else
6749             {
6750               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6751               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6752               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6753               aopPut (AOP (result), zero, LSB);
6754             }
6755         }
6756     }
6757
6758   /* 1 <= shCount <= 7 */
6759   else if (shCount <= 2)
6760     {
6761       shiftLLong (left, result, LSB);
6762       if (shCount == 2)
6763         shiftLLong (result, result, LSB);
6764     }
6765   /* 3 <= shCount <= 7, optimize */
6766   else
6767     {
6768       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6769       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6770       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6771     }
6772 }
6773 #endif
6774
6775 #if 0
6776 //REMOVE ME!!!
6777 /*-----------------------------------------------------------------*/
6778 /* genLeftShiftLiteral - left shifting by known count              */
6779 /*-----------------------------------------------------------------*/
6780 static void
6781 genLeftShiftLiteral (operand * left,
6782                      operand * right,
6783                      operand * result,
6784                      iCode * ic)
6785 {
6786   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6787   int size;
6788
6789   D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6790     );
6791
6792   freeAsmop (right, NULL, ic, TRUE);
6793
6794   aopOp (left, ic, FALSE, FALSE);
6795   aopOp (result, ic, FALSE, TRUE);
6796
6797   size = getSize (operandType (result));
6798
6799 #if VIEW_SIZE
6800   emitcode ("; shift left ", "result %d, left %d", size,
6801             AOP_SIZE (left));
6802 #endif
6803
6804   /* I suppose that the left size >= result size */
6805   if (shCount == 0)
6806     {
6807       while (size--)
6808         {
6809           movLeft2Result (left, size, result, size, 0);
6810         }
6811     }
6812
6813   else if (shCount >= (size * 8))
6814     while (size--)
6815       aopPut (AOP (result), zero, size);
6816   else
6817     {
6818       switch (size)
6819         {
6820         case 1:
6821           genlshOne (result, left, shCount);
6822           break;
6823
6824         case 2:
6825         case 3:         /* bug: this is for generic pointers, I bet. */
6826           genlshTwo (result, left, shCount);
6827           break;
6828
6829         case 4:
6830           genlshFour (result, left, shCount);
6831           break;
6832         }
6833     }
6834   freeAsmop (left, NULL, ic, TRUE);
6835   freeAsmop (result, NULL, ic, TRUE);
6836 }
6837 #endif
6838
6839 /*-----------------------------------------------------------------*/
6840 /* genLeftShift - generates code for left shifting                 */
6841 /*-----------------------------------------------------------------*/
6842 static void
6843 genLeftShift (iCode * ic)
6844 {
6845   operand *left, *right, *result;
6846   int size, offset;
6847   char *l;
6848   symbol *tlbl, *tlbl1;
6849
6850   D (emitcode (";", "genLeftShift "););
6851
6852   right = IC_RIGHT (ic);
6853   left = IC_LEFT (ic);
6854   result = IC_RESULT (ic);
6855
6856   aopOp (right, ic, FALSE, FALSE);
6857
6858 #if 0
6859   /* if the shift count is known then do it
6860      as efficiently as possible */
6861   if (AOP_TYPE (right) == AOP_LIT)
6862     {
6863       genLeftShiftLiteral (left, right, result, ic);
6864       return;
6865     }
6866 #endif
6867
6868   /* shift count is unknown then we have to form
6869      a loop get the loop count in B : Note: we take
6870      only the lower order byte since shifting
6871      more that 32 bits make no sense anyway, ( the
6872      largest size of an object can be only 32 bits ) */
6873
6874   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6875   emitcode ("inc", "b");
6876   freeAsmop (right, NULL, ic, TRUE);
6877   aopOp (left, ic, FALSE, FALSE);
6878   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6879
6880   /* now move the left to the result if they are not the
6881      same */
6882   if (!sameRegs (AOP (left), AOP (result)) &&
6883       AOP_SIZE (result) > 1)
6884     {
6885
6886       size = AOP_SIZE (result);
6887       offset = 0;
6888       _startLazyDPSEvaluation ();
6889       while (size--)
6890         {
6891           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6892           if (*l == '@' && (IS_AOP_PREG (result)))
6893             {
6894
6895               emitcode ("mov", "a,%s", l);
6896               aopPut (AOP (result), "a", offset);
6897             }
6898           else
6899             aopPut (AOP (result), l, offset);
6900           offset++;
6901         }
6902       _endLazyDPSEvaluation ();
6903     }
6904
6905   tlbl = newiTempLabel (NULL);
6906   size = AOP_SIZE (result);
6907   offset = 0;
6908   tlbl1 = newiTempLabel (NULL);
6909
6910   /* if it is only one byte then */
6911   if (size == 1)
6912     {
6913       symbol *tlbl1 = newiTempLabel (NULL);
6914
6915       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6916       MOVA (l);
6917       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6918       emitcode ("", "%05d$:", tlbl->key + 100);
6919       emitcode ("add", "a,acc");
6920       emitcode ("", "%05d$:", tlbl1->key + 100);
6921       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6922       aopPut (AOP (result), "a", 0);
6923       goto release;
6924     }
6925
6926   reAdjustPreg (AOP (result));
6927
6928   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6929   emitcode ("", "%05d$:", tlbl->key + 100);
6930   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6931   MOVA (l);
6932   emitcode ("add", "a,acc");
6933   aopPut (AOP (result), "a", offset++);
6934   _startLazyDPSEvaluation ();
6935   while (--size)
6936     {
6937       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6938       MOVA (l);
6939       emitcode ("rlc", "a");
6940       aopPut (AOP (result), "a", offset++);
6941     }
6942   _endLazyDPSEvaluation ();
6943   reAdjustPreg (AOP (result));
6944
6945   emitcode ("", "%05d$:", tlbl1->key + 100);
6946   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6947 release:
6948   freeAsmop (left, NULL, ic, TRUE);
6949   freeAsmop (result, NULL, ic, TRUE);
6950 }
6951
6952 #if 0
6953 //REMOVE ME!!!
6954 /*-----------------------------------------------------------------*/
6955 /* genrshOne - right shift a one byte quantity by known count      */
6956 /*-----------------------------------------------------------------*/
6957 static void
6958 genrshOne (operand * result, operand * left,
6959            int shCount, int sign)
6960 {
6961   D (emitcode (";", "genrshOne");
6962     );
6963   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6964 }
6965 #endif
6966
6967 #if 0
6968 //REMOVE ME!!!
6969 /*-----------------------------------------------------------------*/
6970 /* genrshTwo - right shift two bytes by known amount != 0          */
6971 /*-----------------------------------------------------------------*/
6972 static void
6973 genrshTwo (operand * result, operand * left,
6974            int shCount, int sign)
6975 {
6976   D (emitcode (";", "genrshTwo");
6977     );
6978
6979   /* if shCount >= 8 */
6980   if (shCount >= 8)
6981     {
6982       shCount -= 8;
6983       if (shCount)
6984         shiftR1Left2Result (left, MSB16, result, LSB,
6985                             shCount, sign);
6986       else
6987         movLeft2Result (left, MSB16, result, LSB, sign);
6988       addSign (result, MSB16, sign);
6989     }
6990
6991   /*  1 <= shCount <= 7 */
6992   else
6993     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6994 }
6995 #endif
6996
6997 #if 0
6998 //REMOVE ME!!!
6999 /*-----------------------------------------------------------------*/
7000 /* shiftRLong - shift right one long from left to result           */
7001 /* offl = LSB or MSB16                                             */
7002 /*-----------------------------------------------------------------*/
7003 static void
7004 shiftRLong (operand * left, int offl,
7005             operand * result, int sign)
7006 {
7007   if (!sign)
7008     emitcode ("clr", "c");
7009   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7010   if (sign)
7011     emitcode ("mov", "c,acc.7");
7012   emitcode ("rrc", "a");
7013   aopPut (AOP (result), "a", MSB32 - offl);
7014   if (offl == MSB16)
7015     /* add sign of "a" */
7016     addSign (result, MSB32, sign);
7017
7018   MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7019   emitcode ("rrc", "a");
7020   aopPut (AOP (result), "a", MSB24 - offl);
7021
7022   MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7023   emitcode ("rrc", "a");
7024   aopPut (AOP (result), "a", MSB16 - offl);
7025
7026   if (offl == LSB)
7027     {
7028       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7029       emitcode ("rrc", "a");
7030       aopPut (AOP (result), "a", LSB);
7031     }
7032 }
7033 #endif
7034
7035 #if 0
7036 //REMOVE ME!!!
7037 /*-----------------------------------------------------------------*/
7038 /* genrshFour - shift four byte by a known amount != 0             */
7039 /*-----------------------------------------------------------------*/
7040 static void
7041 genrshFour (operand * result, operand * left,
7042             int shCount, int sign)
7043 {
7044   D (emitcode (";", "genrshFour");
7045     );
7046
7047   /* if shifting more that 3 bytes */
7048   if (shCount >= 24)
7049     {
7050       shCount -= 24;
7051       if (shCount)
7052         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7053       else
7054         movLeft2Result (left, MSB32, result, LSB, sign);
7055       addSign (result, MSB16, sign);
7056     }
7057   else if (shCount >= 16)
7058     {
7059       shCount -= 16;
7060       if (shCount)
7061         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7062       else
7063         {
7064           movLeft2Result (left, MSB24, result, LSB, 0);
7065           movLeft2Result (left, MSB32, result, MSB16, sign);
7066         }
7067       addSign (result, MSB24, sign);
7068     }
7069   else if (shCount >= 8)
7070     {
7071       shCount -= 8;
7072       if (shCount == 1)
7073         shiftRLong (left, MSB16, result, sign);
7074       else if (shCount == 0)
7075         {
7076           movLeft2Result (left, MSB16, result, LSB, 0);
7077           movLeft2Result (left, MSB24, result, MSB16, 0);
7078           movLeft2Result (left, MSB32, result, MSB24, sign);
7079           addSign (result, MSB32, sign);
7080         }
7081       else
7082         {
7083           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7084           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7085           /* the last shift is signed */
7086           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7087           addSign (result, MSB32, sign);
7088         }
7089     }
7090   else
7091     {                           /* 1 <= shCount <= 7 */
7092       if (shCount <= 2)
7093         {
7094           shiftRLong (left, LSB, result, sign);
7095           if (shCount == 2)
7096             shiftRLong (result, LSB, result, sign);
7097         }
7098       else
7099         {
7100           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7101           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7102           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7103         }
7104     }
7105 }
7106 #endif
7107
7108 #if 0
7109 //REMOVE ME!!!
7110 /*-----------------------------------------------------------------*/
7111 /* genRightShiftLiteral - right shifting by known count            */
7112 /*-----------------------------------------------------------------*/
7113 static void
7114 genRightShiftLiteral (operand * left,
7115                       operand * right,
7116                       operand * result,
7117                       iCode * ic,
7118                       int sign)
7119 {
7120   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7121   int size;
7122
7123   D (emitcode (";", "genRightShiftLiteral");
7124     );
7125
7126   freeAsmop (right, NULL, ic, TRUE);
7127
7128   aopOp (left, ic, FALSE, FALSE);
7129   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7130
7131 #if VIEW_SIZE
7132   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7133             AOP_SIZE (left));
7134 #endif
7135
7136   size = getDataSize (left);
7137   /* test the LEFT size !!! */
7138
7139   /* I suppose that the left size >= result size */
7140   if (shCount == 0)
7141     {
7142       size = getDataSize (result);
7143       while (size--)
7144         movLeft2Result (left, size, result, size, 0);
7145     }
7146
7147   else if (shCount >= (size * 8))
7148     {
7149       if (sign)
7150         /* get sign in acc.7 */
7151         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7152       addSign (result, LSB, sign);
7153     }
7154   else
7155     {
7156       switch (size)
7157         {
7158         case 1:
7159           genrshOne (result, left, shCount, sign);
7160           break;
7161
7162         case 2:
7163           genrshTwo (result, left, shCount, sign);
7164           break;
7165
7166         case 4:
7167           genrshFour (result, left, shCount, sign);
7168           break;
7169         default:
7170           break;
7171         }
7172
7173       freeAsmop (left, NULL, ic, TRUE);
7174       freeAsmop (result, NULL, ic, TRUE);
7175     }
7176 }
7177 #endif
7178
7179 /*-----------------------------------------------------------------*/
7180 /* genSignedRightShift - right shift of signed number              */
7181 /*-----------------------------------------------------------------*/
7182 static void
7183 genSignedRightShift (iCode * ic)
7184 {
7185   operand *right, *left, *result;
7186   int size, offset;
7187   char *l;
7188   symbol *tlbl, *tlbl1;
7189
7190   D (emitcode (";", "genSignedRightShift ");
7191     );
7192
7193   /* we do it the hard way put the shift count in b
7194      and loop thru preserving the sign */
7195
7196   right = IC_RIGHT (ic);
7197   left = IC_LEFT (ic);
7198   result = IC_RESULT (ic);
7199
7200   aopOp (right, ic, FALSE, FALSE);
7201
7202 #if 0
7203   if (AOP_TYPE (right) == AOP_LIT)
7204     {
7205       genRightShiftLiteral (left, right, result, ic, 1);
7206       return;
7207     }
7208 #endif
7209   /* shift count is unknown then we have to form
7210      a loop get the loop count in B : Note: we take
7211      only the lower order byte since shifting
7212      more that 32 bits make no sense anyway, ( the
7213      largest size of an object can be only 32 bits ) */
7214
7215   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7216   emitcode ("inc", "b");
7217   freeAsmop (right, NULL, ic, TRUE);
7218   aopOp (left, ic, FALSE, FALSE);
7219   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7220
7221   /* now move the left to the result if they are not the
7222      same */
7223   if (!sameRegs (AOP (left), AOP (result)) &&
7224       AOP_SIZE (result) > 1)
7225     {
7226
7227       size = AOP_SIZE (result);
7228       offset = 0;
7229       _startLazyDPSEvaluation ();
7230       while (size--)
7231         {
7232           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7233           if (*l == '@' && IS_AOP_PREG (result))
7234             {
7235
7236               emitcode ("mov", "a,%s", l);
7237               aopPut (AOP (result), "a", offset);
7238             }
7239           else
7240             aopPut (AOP (result), l, offset);
7241           offset++;
7242         }
7243       _endLazyDPSEvaluation ();
7244     }
7245
7246   /* mov the highest order bit to OVR */
7247   tlbl = newiTempLabel (NULL);
7248   tlbl1 = newiTempLabel (NULL);
7249
7250   size = AOP_SIZE (result);
7251   offset = size - 1;
7252   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7253   emitcode ("rlc", "a");
7254   emitcode ("mov", "ov,c");
7255   /* if it is only one byte then */
7256   if (size == 1)
7257     {
7258       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7259       MOVA (l);
7260       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7261       emitcode ("", "%05d$:", tlbl->key + 100);
7262       emitcode ("mov", "c,ov");
7263       emitcode ("rrc", "a");
7264       emitcode ("", "%05d$:", tlbl1->key + 100);
7265       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7266       aopPut (AOP (result), "a", 0);
7267       goto release;
7268     }
7269
7270   reAdjustPreg (AOP (result));
7271   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7272   emitcode ("", "%05d$:", tlbl->key + 100);
7273   emitcode ("mov", "c,ov");
7274   _startLazyDPSEvaluation ();
7275   while (size--)
7276     {
7277       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7278       MOVA (l);
7279       emitcode ("rrc", "a");
7280       aopPut (AOP (result), "a", offset--);
7281     }
7282   _endLazyDPSEvaluation ();
7283   reAdjustPreg (AOP (result));
7284   emitcode ("", "%05d$:", tlbl1->key + 100);
7285   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7286
7287 release:
7288   freeAsmop (left, NULL, ic, TRUE);
7289   freeAsmop (result, NULL, ic, TRUE);
7290 }
7291
7292 /*-----------------------------------------------------------------*/
7293 /* genRightShift - generate code for right shifting                */
7294 /*-----------------------------------------------------------------*/
7295 static void
7296 genRightShift (iCode * ic)
7297 {
7298   operand *right, *left, *result;
7299   sym_link *retype;
7300   int size, offset;
7301   char *l;
7302   symbol *tlbl, *tlbl1;
7303
7304   D (emitcode (";", "genRightShift ");
7305     );
7306
7307   /* if signed then we do it the hard way preserve the
7308      sign bit moving it inwards */
7309   retype = getSpec (operandType (IC_RESULT (ic)));
7310
7311   if (!SPEC_USIGN (retype))
7312     {
7313       genSignedRightShift (ic);
7314       return;
7315     }
7316
7317   /* signed & unsigned types are treated the same : i.e. the
7318      signed is NOT propagated inwards : quoting from the
7319      ANSI - standard : "for E1 >> E2, is equivalent to division
7320      by 2**E2 if unsigned or if it has a non-negative value,
7321      otherwise the result is implementation defined ", MY definition
7322      is that the sign does not get propagated */
7323
7324   right = IC_RIGHT (ic);
7325   left = IC_LEFT (ic);
7326   result = IC_RESULT (ic);
7327
7328   aopOp (right, ic, FALSE, FALSE);
7329
7330 #if 0
7331   /* if the shift count is known then do it
7332      as efficiently as possible */
7333   if (AOP_TYPE (right) == AOP_LIT)
7334     {
7335       genRightShiftLiteral (left, right, result, ic, 0);
7336       return;
7337     }
7338 #endif
7339
7340   /* shift count is unknown then we have to form
7341      a loop get the loop count in B : Note: we take
7342      only the lower order byte since shifting
7343      more that 32 bits make no sense anyway, ( the
7344      largest size of an object can be only 32 bits ) */
7345
7346   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7347   emitcode ("inc", "b");
7348   freeAsmop (right, NULL, ic, TRUE);
7349   aopOp (left, ic, FALSE, FALSE);
7350   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7351
7352   /* now move the left to the result if they are not the
7353      same */
7354   if (!sameRegs (AOP (left), AOP (result)) &&
7355       AOP_SIZE (result) > 1)
7356     {
7357
7358       size = AOP_SIZE (result);
7359       offset = 0;
7360       _startLazyDPSEvaluation ();
7361       while (size--)
7362         {
7363           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7364           if (*l == '@' && IS_AOP_PREG (result))
7365             {
7366
7367               emitcode ("mov", "a,%s", l);
7368               aopPut (AOP (result), "a", offset);
7369             }
7370           else
7371             aopPut (AOP (result), l, offset);
7372           offset++;
7373         }
7374       _endLazyDPSEvaluation ();
7375     }
7376
7377   tlbl = newiTempLabel (NULL);
7378   tlbl1 = newiTempLabel (NULL);
7379   size = AOP_SIZE (result);
7380   offset = size - 1;
7381
7382   /* if it is only one byte then */
7383   if (size == 1)
7384     {
7385       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7386       MOVA (l);
7387       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7388       emitcode ("", "%05d$:", tlbl->key + 100);
7389       CLRC;
7390       emitcode ("rrc", "a");
7391       emitcode ("", "%05d$:", tlbl1->key + 100);
7392       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7393       aopPut (AOP (result), "a", 0);
7394       goto release;
7395     }
7396
7397   reAdjustPreg (AOP (result));
7398   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7399   emitcode ("", "%05d$:", tlbl->key + 100);
7400   CLRC;
7401   _startLazyDPSEvaluation ();
7402   while (size--)
7403     {
7404       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7405       MOVA (l);
7406       emitcode ("rrc", "a");
7407       aopPut (AOP (result), "a", offset--);
7408     }
7409   _endLazyDPSEvaluation ();
7410   reAdjustPreg (AOP (result));
7411
7412   emitcode ("", "%05d$:", tlbl1->key + 100);
7413   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7414
7415 release:
7416   freeAsmop (left, NULL, ic, TRUE);
7417   freeAsmop (result, NULL, ic, TRUE);
7418 }
7419
7420 /*-----------------------------------------------------------------*/
7421 /* genUnpackBits - generates code for unpacking bits               */
7422 /*-----------------------------------------------------------------*/
7423 static void
7424 genUnpackBits (operand * result, char *rname, int ptype)
7425 {
7426   int shCnt;
7427   int rlen = 0;
7428   sym_link *etype;
7429   int offset = 0;
7430
7431   D (emitcode (";", "genUnpackBits ");
7432     );
7433
7434   etype = getSpec (operandType (result));
7435
7436   /* read the first byte  */
7437   switch (ptype)
7438     {
7439
7440     case POINTER:
7441     case IPOINTER:
7442       emitcode ("mov", "a,@%s", rname);
7443       break;
7444
7445     case PPOINTER:
7446       emitcode ("movx", "a,@%s", rname);
7447       break;
7448
7449     case FPOINTER:
7450       emitcode ("movx", "a,@dptr");
7451       break;
7452
7453     case CPOINTER:
7454       emitcode ("clr", "a");
7455       emitcode ("movc", "a", "@a+dptr");
7456       break;
7457
7458     case GPOINTER:
7459       emitcode ("lcall", "__gptrget");
7460       break;
7461     }
7462
7463   /* if we have bitdisplacement then it fits   */
7464   /* into this byte completely or if length is */
7465   /* less than a byte                          */
7466   if ((shCnt = SPEC_BSTR (etype)) ||
7467       (SPEC_BLEN (etype) <= 8))
7468     {
7469
7470       /* shift right acc */
7471       AccRsh (shCnt);
7472
7473       emitcode ("anl", "a,#0x%02x",
7474                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7475       aopPut (AOP (result), "a", offset);
7476       return;
7477     }
7478
7479   /* bit field did not fit in a byte  */
7480   rlen = SPEC_BLEN (etype) - 8;
7481   aopPut (AOP (result), "a", offset++);
7482
7483   while (1)
7484     {
7485
7486       switch (ptype)
7487         {
7488         case POINTER:
7489         case IPOINTER:
7490           emitcode ("inc", "%s", rname);
7491           emitcode ("mov", "a,@%s", rname);
7492           break;
7493
7494         case PPOINTER:
7495           emitcode ("inc", "%s", rname);
7496           emitcode ("movx", "a,@%s", rname);
7497           break;
7498
7499         case FPOINTER:
7500           emitcode ("inc", "dptr");
7501           emitcode ("movx", "a,@dptr");
7502           break;
7503
7504         case CPOINTER:
7505           emitcode ("clr", "a");
7506           emitcode ("inc", "dptr");
7507           emitcode ("movc", "a", "@a+dptr");
7508           break;
7509
7510         case GPOINTER:
7511           emitcode ("inc", "dptr");
7512           emitcode ("lcall", "__gptrget");
7513           break;
7514         }
7515
7516       rlen -= 8;
7517       /* if we are done */
7518       if (rlen < 8)
7519         break;
7520
7521       aopPut (AOP (result), "a", offset++);
7522
7523     }
7524
7525   if (rlen)
7526     {
7527       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7528       aopPut (AOP (result), "a", offset);
7529     }
7530
7531   return;
7532 }
7533
7534
7535 /*-----------------------------------------------------------------*/
7536 /* genDataPointerGet - generates code when ptr offset is known     */
7537 /*-----------------------------------------------------------------*/
7538 static void
7539 genDataPointerGet (operand * left,
7540                    operand * result,
7541                    iCode * ic)
7542 {
7543   char *l;
7544   char buffer[256];
7545   int size, offset = 0;
7546   aopOp (result, ic, TRUE, FALSE);
7547
7548   /* get the string representation of the name */
7549   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7550   size = AOP_SIZE (result);
7551   _startLazyDPSEvaluation ();
7552   while (size--)
7553     {
7554       if (offset)
7555         sprintf (buffer, "(%s + %d)", l + 1, offset);
7556       else
7557         sprintf (buffer, "%s", l + 1);
7558       aopPut (AOP (result), buffer, offset++);
7559     }
7560   _endLazyDPSEvaluation ();
7561
7562   freeAsmop (left, NULL, ic, TRUE);
7563   freeAsmop (result, NULL, ic, TRUE);
7564 }
7565
7566 /*-----------------------------------------------------------------*/
7567 /* genNearPointerGet - emitcode for near pointer fetch             */
7568 /*-----------------------------------------------------------------*/
7569 static void
7570 genNearPointerGet (operand * left,
7571                    operand * result,
7572                    iCode * ic)
7573 {
7574   asmop *aop = NULL;
7575   regs *preg = NULL;
7576   char *rname;
7577   sym_link *rtype, *retype, *letype;
7578   sym_link *ltype = operandType (left);
7579   char buffer[80];
7580
7581   rtype = operandType (result);
7582   retype = getSpec (rtype);
7583   letype = getSpec (ltype);
7584
7585   aopOp (left, ic, FALSE, FALSE);
7586
7587   /* if left is rematerialisable and
7588      result is not bit variable type and
7589      the left is pointer to data space i.e
7590      lower 128 bytes of space */
7591   if (AOP_TYPE (left) == AOP_IMMD &&
7592       !IS_BITVAR (retype) &&
7593       !IS_BITVAR (letype) &&
7594       DCL_TYPE (ltype) == POINTER)
7595     {
7596       genDataPointerGet (left, result, ic);
7597       return;
7598     }
7599
7600   /* if the value is already in a pointer register
7601      then don't need anything more */
7602   if (!AOP_INPREG (AOP (left)))
7603     {
7604       /* otherwise get a free pointer register */
7605       aop = newAsmop (0);
7606       preg = getFreePtr (ic, &aop, FALSE);
7607       emitcode ("mov", "%s,%s",
7608                 preg->name,
7609                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7610       rname = preg->name;
7611     }
7612   else
7613     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7614
7615   freeAsmop (left, NULL, ic, TRUE);
7616   aopOp (result, ic, FALSE, FALSE);
7617
7618   /* if bitfield then unpack the bits */
7619   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7620     genUnpackBits (result, rname, POINTER);
7621   else
7622     {
7623       /* we have can just get the values */
7624       int size = AOP_SIZE (result);
7625       int offset = 0;
7626
7627       while (size--)
7628         {
7629           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7630             {
7631
7632               emitcode ("mov", "a,@%s", rname);
7633               aopPut (AOP (result), "a", offset);
7634             }
7635           else
7636             {
7637               sprintf (buffer, "@%s", rname);
7638               aopPut (AOP (result), buffer, offset);
7639             }
7640           offset++;
7641           if (size)
7642             emitcode ("inc", "%s", rname);
7643         }
7644     }
7645
7646   /* now some housekeeping stuff */
7647   if (aop)
7648     {
7649       /* we had to allocate for this iCode */
7650       freeAsmop (NULL, aop, ic, TRUE);
7651     }
7652   else
7653     {
7654       /* we did not allocate which means left
7655          already in a pointer register, then
7656          if size > 0 && this could be used again
7657          we have to point it back to where it
7658          belongs */
7659       if (AOP_SIZE (result) > 1 &&
7660           !OP_SYMBOL (left)->remat &&
7661           (OP_SYMBOL (left)->liveTo > ic->seq ||
7662            ic->depth))
7663         {
7664           int size = AOP_SIZE (result) - 1;
7665           while (size--)
7666             emitcode ("dec", "%s", rname);
7667         }
7668     }
7669
7670   /* done */
7671   freeAsmop (result, NULL, ic, TRUE);
7672
7673 }
7674
7675 /*-----------------------------------------------------------------*/
7676 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7677 /*-----------------------------------------------------------------*/
7678 static void
7679 genPagedPointerGet (operand * left,
7680                     operand * result,
7681                     iCode * ic)
7682 {
7683   asmop *aop = NULL;
7684   regs *preg = NULL;
7685   char *rname;
7686   sym_link *rtype, *retype, *letype;
7687
7688   rtype = operandType (result);
7689   retype = getSpec (rtype);
7690   letype = getSpec (operandType (left));
7691   aopOp (left, ic, FALSE, FALSE);
7692
7693   /* if the value is already in a pointer register
7694      then don't need anything more */
7695   if (!AOP_INPREG (AOP (left)))
7696     {
7697       /* otherwise get a free pointer register */
7698       aop = newAsmop (0);
7699       preg = getFreePtr (ic, &aop, FALSE);
7700       emitcode ("mov", "%s,%s",
7701                 preg->name,
7702                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7703       rname = preg->name;
7704     }
7705   else
7706     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7707
7708   freeAsmop (left, NULL, ic, TRUE);
7709   aopOp (result, ic, FALSE, FALSE);
7710
7711   /* if bitfield then unpack the bits */
7712   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7713     genUnpackBits (result, rname, PPOINTER);
7714   else
7715     {
7716       /* we have can just get the values */
7717       int size = AOP_SIZE (result);
7718       int offset = 0;
7719
7720       while (size--)
7721         {
7722
7723           emitcode ("movx", "a,@%s", rname);
7724           aopPut (AOP (result), "a", offset);
7725
7726           offset++;
7727
7728           if (size)
7729             emitcode ("inc", "%s", rname);
7730         }
7731     }
7732
7733   /* now some housekeeping stuff */
7734   if (aop)
7735     {
7736       /* we had to allocate for this iCode */
7737       freeAsmop (NULL, aop, ic, TRUE);
7738     }
7739   else
7740     {
7741       /* we did not allocate which means left
7742          already in a pointer register, then
7743          if size > 0 && this could be used again
7744          we have to point it back to where it
7745          belongs */
7746       if (AOP_SIZE (result) > 1 &&
7747           !OP_SYMBOL (left)->remat &&
7748           (OP_SYMBOL (left)->liveTo > ic->seq ||
7749            ic->depth))
7750         {
7751           int size = AOP_SIZE (result) - 1;
7752           while (size--)
7753             emitcode ("dec", "%s", rname);
7754         }
7755     }
7756
7757   /* done */
7758   freeAsmop (result, NULL, ic, TRUE);
7759
7760
7761 }
7762
7763 /*-----------------------------------------------------------------*/
7764 /* genFarPointerGet - gget value from far space                    */
7765 /*-----------------------------------------------------------------*/
7766 static void
7767 genFarPointerGet (operand * left,
7768                   operand * result, iCode * ic)
7769 {
7770   int size, offset;
7771   sym_link *retype = getSpec (operandType (result));
7772   sym_link *letype = getSpec (operandType (left));
7773   D (emitcode (";", "genFarPointerGet");
7774     );
7775
7776   aopOp (left, ic, FALSE, FALSE);
7777
7778   /* if the operand is already in dptr
7779      then we do nothing else we move the value to dptr */
7780   if (AOP_TYPE (left) != AOP_STR)
7781     {
7782       /* if this is remateriazable */
7783       if (AOP_TYPE (left) == AOP_IMMD)
7784         {
7785           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7786         }
7787       else
7788         {
7789           /* we need to get it byte by byte */
7790           _startLazyDPSEvaluation ();
7791           if (AOP_TYPE (left) != AOP_DPTR)
7792             {
7793               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7794               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7795               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7796             }
7797           else
7798             {
7799               /* We need to generate a load to DPTR indirect through DPTR. */
7800               D (emitcode (";", "genFarPointerGet -- indirection special case.");
7801                 );
7802               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7803               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7804               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7805               emitcode ("pop", "dph");
7806               emitcode ("pop", "dpl");
7807             }
7808           _endLazyDPSEvaluation ();
7809         }
7810     }
7811   /* so dptr know contains the address */
7812   freeAsmop (left, NULL, ic, TRUE);
7813   aopOp (result, ic, FALSE, TRUE);
7814
7815   /* if bit then unpack */
7816   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7817     genUnpackBits (result, "dptr", FPOINTER);
7818   else
7819     {
7820       size = AOP_SIZE (result);
7821       offset = 0;
7822
7823       _startLazyDPSEvaluation ();
7824       while (size--)
7825         {
7826
7827           genSetDPTR (0);
7828           _flushLazyDPS ();
7829
7830           emitcode ("movx", "a,@dptr");
7831           if (size)
7832             emitcode ("inc", "dptr");
7833
7834           aopPut (AOP (result), "a", offset++);
7835         }
7836       _endLazyDPSEvaluation ();
7837     }
7838
7839   freeAsmop (result, NULL, ic, TRUE);
7840 }
7841
7842 /*-----------------------------------------------------------------*/
7843 /* emitcodePointerGet - gget value from code space                  */
7844 /*-----------------------------------------------------------------*/
7845 static void
7846 emitcodePointerGet (operand * left,
7847                     operand * result, iCode * ic)
7848 {
7849   int size, offset;
7850   sym_link *retype = getSpec (operandType (result));
7851
7852   aopOp (left, ic, FALSE, FALSE);
7853
7854   /* if the operand is already in dptr
7855      then we do nothing else we move the value to dptr */
7856   if (AOP_TYPE (left) != AOP_STR)
7857     {
7858       /* if this is remateriazable */
7859       if (AOP_TYPE (left) == AOP_IMMD)
7860         {
7861           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7862         }
7863       else
7864         {                       /* we need to get it byte by byte */
7865           _startLazyDPSEvaluation ();
7866           if (AOP_TYPE (left) != AOP_DPTR)
7867             {
7868               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7869               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7870               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7871             }
7872           else
7873             {
7874               /* We need to generate a load to DPTR indirect through DPTR. */
7875               D (emitcode (";", "gencodePointerGet -- indirection special case.");
7876                 );
7877               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7878               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7879               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7880               emitcode ("pop", "dph");
7881               emitcode ("pop", "dpl");
7882             }
7883           _endLazyDPSEvaluation ();
7884         }
7885     }
7886   /* so dptr know contains the address */
7887   freeAsmop (left, NULL, ic, TRUE);
7888   aopOp (result, ic, FALSE, TRUE);
7889
7890   /* if bit then unpack */
7891   if (IS_BITVAR (retype))
7892     genUnpackBits (result, "dptr", CPOINTER);
7893   else
7894     {
7895       size = AOP_SIZE (result);
7896       offset = 0;
7897
7898       _startLazyDPSEvaluation ();
7899       while (size--)
7900         {
7901           genSetDPTR (0);
7902           _flushLazyDPS ();
7903
7904           emitcode ("clr", "a");
7905           emitcode ("movc", "a,@a+dptr");
7906           if (size)
7907             emitcode ("inc", "dptr");
7908           aopPut (AOP (result), "a", offset++);
7909         }
7910       _endLazyDPSEvaluation ();
7911     }
7912
7913   freeAsmop (result, NULL, ic, TRUE);
7914 }
7915
7916 /*-----------------------------------------------------------------*/
7917 /* genGenPointerGet - gget value from generic pointer space        */
7918 /*-----------------------------------------------------------------*/
7919 static void
7920 genGenPointerGet (operand * left,
7921                   operand * result, iCode * ic)
7922 {
7923   int size, offset;
7924   sym_link *retype = getSpec (operandType (result));
7925   sym_link *letype = getSpec (operandType (left));
7926
7927   D (emitcode (";", "genGenPointerGet "); );
7928
7929   aopOp (left, ic, FALSE, TRUE);
7930
7931   /* if the operand is already in dptr
7932      then we do nothing else we move the value to dptr */
7933   if (AOP_TYPE (left) != AOP_STR)
7934     {
7935       /* if this is remateriazable */
7936       if (AOP_TYPE (left) == AOP_IMMD)
7937         {
7938           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7939           emitcode ("mov", "b,#%d", pointerCode (retype));
7940         }
7941       else
7942         {                       /* we need to get it byte by byte */
7943           _startLazyDPSEvaluation ();
7944           if (AOP(left)->type==AOP_DPTR2) {
7945             char *l;
7946             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7947             genSetDPTR(0);
7948             _flushLazyDPS();
7949             emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7950             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7951             genSetDPTR(0);
7952             _flushLazyDPS();
7953             emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7954             l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7955             genSetDPTR(0);
7956             _flushLazyDPS();
7957             emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7958             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7959           } else {
7960             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7961             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7962             emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7963             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7964           }
7965           _endLazyDPSEvaluation ();
7966         }
7967     }
7968   /* so dptr know contains the address */
7969   freeAsmop (left, NULL, ic, TRUE);
7970   aopOp (result, ic, FALSE, TRUE);
7971
7972   /* if bit then unpack */
7973   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7974     genUnpackBits (result, "dptr", GPOINTER);
7975   else
7976     {
7977       size = AOP_SIZE (result);
7978       offset = 0;
7979
7980       while (size--)
7981         {
7982           emitcode ("lcall", "__gptrget");
7983           aopPut (AOP (result), "a", offset++);
7984           if (size)
7985             emitcode ("inc", "dptr");
7986         }
7987     }
7988
7989   freeAsmop (result, NULL, ic, TRUE);
7990 }
7991
7992 /*-----------------------------------------------------------------*/
7993 /* genPointerGet - generate code for pointer get                   */
7994 /*-----------------------------------------------------------------*/
7995 static void
7996 genPointerGet (iCode * ic)
7997 {
7998   operand *left, *result;
7999   sym_link *type, *etype;
8000   int p_type;
8001
8002   D (emitcode (";", "genPointerGet ");
8003     );
8004
8005   left = IC_LEFT (ic);
8006   result = IC_RESULT (ic);
8007
8008   /* depending on the type of pointer we need to
8009      move it to the correct pointer register */
8010   type = operandType (left);
8011   etype = getSpec (type);
8012   /* if left is of type of pointer then it is simple */
8013   if (IS_PTR (type) && !IS_FUNC (type->next))
8014     p_type = DCL_TYPE (type);
8015   else
8016     {
8017       /* we have to go by the storage class */
8018       p_type = PTR_TYPE (SPEC_OCLS (etype));
8019     }
8020
8021   /* now that we have the pointer type we assign
8022      the pointer values */
8023   switch (p_type)
8024     {
8025
8026     case POINTER:
8027     case IPOINTER:
8028       genNearPointerGet (left, result, ic);
8029       break;
8030
8031     case PPOINTER:
8032       genPagedPointerGet (left, result, ic);
8033       break;
8034
8035     case FPOINTER:
8036       genFarPointerGet (left, result, ic);
8037       break;
8038
8039     case CPOINTER:
8040       emitcodePointerGet (left, result, ic);
8041       break;
8042
8043     case GPOINTER:
8044       genGenPointerGet (left, result, ic);
8045       break;
8046     }
8047
8048 }
8049
8050 /*-----------------------------------------------------------------*/
8051 /* genPackBits - generates code for packed bit storage             */
8052 /*-----------------------------------------------------------------*/
8053 static void
8054 genPackBits (sym_link * etype,
8055              operand * right,
8056              char *rname, int p_type)
8057 {
8058   int shCount = 0;
8059   int offset = 0;
8060   int rLen = 0;
8061   int blen, bstr;
8062   char *l;
8063
8064   blen = SPEC_BLEN (etype);
8065   bstr = SPEC_BSTR (etype);
8066
8067   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8068   MOVA (l);
8069
8070   /* if the bit lenth is less than or    */
8071   /* it exactly fits a byte then         */
8072   if (SPEC_BLEN (etype) <= 8)
8073     {
8074       shCount = SPEC_BSTR (etype);
8075
8076       /* shift left acc */
8077       AccLsh (shCount);
8078
8079       if (SPEC_BLEN (etype) < 8)
8080         {                       /* if smaller than a byte */
8081
8082
8083           switch (p_type)
8084             {
8085             case POINTER:
8086               emitcode ("mov", "b,a");
8087               emitcode ("mov", "a,@%s", rname);
8088               break;
8089
8090             case FPOINTER:
8091               emitcode ("mov", "b,a");
8092               emitcode ("movx", "a,@dptr");
8093               break;
8094
8095             case GPOINTER:
8096               emitcode ("push", "b");
8097               emitcode ("push", "acc");
8098               emitcode ("lcall", "__gptrget");
8099               emitcode ("pop", "b");
8100               break;
8101             }
8102
8103           emitcode ("anl", "a,#0x%02x", (unsigned char)
8104                     ((unsigned char) (0xFF << (blen + bstr)) |
8105                      (unsigned char) (0xFF >> (8 - bstr))));
8106           emitcode ("orl", "a,b");
8107           if (p_type == GPOINTER)
8108             emitcode ("pop", "b");
8109         }
8110     }
8111
8112   switch (p_type)
8113     {
8114     case POINTER:
8115       emitcode ("mov", "@%s,a", rname);
8116       break;
8117
8118     case FPOINTER:
8119       emitcode ("movx", "@dptr,a");
8120       break;
8121
8122     case GPOINTER:
8123       emitcode ("lcall", "__gptrput");
8124       break;
8125     }
8126
8127   /* if we r done */
8128   if (SPEC_BLEN (etype) <= 8)
8129     return;
8130
8131   emitcode ("inc", "%s", rname);
8132   rLen = SPEC_BLEN (etype);
8133
8134   /* now generate for lengths greater than one byte */
8135   while (1)
8136     {
8137
8138       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8139
8140       rLen -= 8;
8141       if (rLen < 8)
8142         break;
8143
8144       switch (p_type)
8145         {
8146         case POINTER:
8147           if (*l == '@')
8148             {
8149               MOVA (l);
8150               emitcode ("mov", "@%s,a", rname);
8151             }
8152           else
8153             emitcode ("mov", "@%s,%s", rname, l);
8154           break;
8155
8156         case FPOINTER:
8157           MOVA (l);
8158           emitcode ("movx", "@dptr,a");
8159           break;
8160
8161         case GPOINTER:
8162           MOVA (l);
8163           emitcode ("lcall", "__gptrput");
8164           break;
8165         }
8166       emitcode ("inc", "%s", rname);
8167     }
8168
8169   MOVA (l);
8170
8171   /* last last was not complete */
8172   if (rLen)
8173     {
8174       /* save the byte & read byte */
8175       switch (p_type)
8176         {
8177         case POINTER:
8178           emitcode ("mov", "b,a");
8179           emitcode ("mov", "a,@%s", rname);
8180           break;
8181
8182         case FPOINTER:
8183           emitcode ("mov", "b,a");
8184           emitcode ("movx", "a,@dptr");
8185           break;
8186
8187         case GPOINTER:
8188           emitcode ("push", "b");
8189           emitcode ("push", "acc");
8190           emitcode ("lcall", "__gptrget");
8191           emitcode ("pop", "b");
8192           break;
8193         }
8194
8195       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8196       emitcode ("orl", "a,b");
8197     }
8198
8199   if (p_type == GPOINTER)
8200     emitcode ("pop", "b");
8201
8202   switch (p_type)
8203     {
8204
8205     case POINTER:
8206       emitcode ("mov", "@%s,a", rname);
8207       break;
8208
8209     case FPOINTER:
8210       emitcode ("movx", "@dptr,a");
8211       break;
8212
8213     case GPOINTER:
8214       emitcode ("lcall", "__gptrput");
8215       break;
8216     }
8217 }
8218 /*-----------------------------------------------------------------*/
8219 /* genDataPointerSet - remat pointer to data space                 */
8220 /*-----------------------------------------------------------------*/
8221 static void
8222 genDataPointerSet (operand * right,
8223                    operand * result,
8224                    iCode * ic)
8225 {
8226   int size, offset = 0;
8227   char *l, buffer[256];
8228
8229   aopOp (right, ic, FALSE, FALSE);
8230
8231   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8232   size = AOP_SIZE (right);
8233   while (size--)
8234     {
8235       if (offset)
8236         sprintf (buffer, "(%s + %d)", l + 1, offset);
8237       else
8238         sprintf (buffer, "%s", l + 1);
8239       emitcode ("mov", "%s,%s", buffer,
8240                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8241     }
8242
8243   freeAsmop (right, NULL, ic, TRUE);
8244   freeAsmop (result, NULL, ic, TRUE);
8245 }
8246
8247 /*-----------------------------------------------------------------*/
8248 /* genNearPointerSet - emitcode for near pointer put                */
8249 /*-----------------------------------------------------------------*/
8250 static void
8251 genNearPointerSet (operand * right,
8252                    operand * result,
8253                    iCode * ic)
8254 {
8255   asmop *aop = NULL;
8256   regs *preg = NULL;
8257   char *rname, *l;
8258   sym_link *retype, *letype;
8259   sym_link *ptype = operandType (result);
8260
8261   retype = getSpec (operandType (right));
8262   letype = getSpec (ptype);
8263
8264   aopOp (result, ic, FALSE, FALSE);
8265
8266   /* if the result is rematerializable &
8267      in data space & not a bit variable */
8268   if (AOP_TYPE (result) == AOP_IMMD &&
8269       DCL_TYPE (ptype) == POINTER &&
8270       !IS_BITVAR (retype) &&
8271       !IS_BITVAR (letype))
8272     {
8273       genDataPointerSet (right, result, ic);
8274       return;
8275     }
8276
8277   /* if the value is already in a pointer register
8278      then don't need anything more */
8279   if (!AOP_INPREG (AOP (result)))
8280     {
8281       /* otherwise get a free pointer register */
8282       aop = newAsmop (0);
8283       preg = getFreePtr (ic, &aop, FALSE);
8284       emitcode ("mov", "%s,%s",
8285                 preg->name,
8286                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8287       rname = preg->name;
8288     }
8289   else
8290     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8291
8292   freeAsmop (result, NULL, ic, TRUE);
8293   aopOp (right, ic, FALSE, FALSE);
8294
8295   /* if bitfield then unpack the bits */
8296   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8297     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8298   else
8299     {
8300       /* we have can just get the values */
8301       int size = AOP_SIZE (right);
8302       int offset = 0;
8303
8304       while (size--)
8305         {
8306           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8307           if (*l == '@')
8308             {
8309               MOVA (l);
8310               emitcode ("mov", "@%s,a", rname);
8311             }
8312           else
8313             emitcode ("mov", "@%s,%s", rname, l);
8314           if (size)
8315             emitcode ("inc", "%s", rname);
8316           offset++;
8317         }
8318     }
8319
8320   /* now some housekeeping stuff */
8321   if (aop)
8322     {
8323       /* we had to allocate for this iCode */
8324       freeAsmop (NULL, aop, ic, TRUE);
8325     }
8326   else
8327     {
8328       /* we did not allocate which means left
8329          already in a pointer register, then
8330          if size > 0 && this could be used again
8331          we have to point it back to where it
8332          belongs */
8333       if (AOP_SIZE (right) > 1 &&
8334           !OP_SYMBOL (result)->remat &&
8335           (OP_SYMBOL (result)->liveTo > ic->seq ||
8336            ic->depth))
8337         {
8338           int size = AOP_SIZE (right) - 1;
8339           while (size--)
8340             emitcode ("dec", "%s", rname);
8341         }
8342     }
8343
8344   /* done */
8345   freeAsmop (right, NULL, ic, TRUE);
8346
8347
8348 }
8349
8350 /*-----------------------------------------------------------------*/
8351 /* genPagedPointerSet - emitcode for Paged pointer put             */
8352 /*-----------------------------------------------------------------*/
8353 static void
8354 genPagedPointerSet (operand * right,
8355                     operand * result,
8356                     iCode * ic)
8357 {
8358   asmop *aop = NULL;
8359   regs *preg = NULL;
8360   char *rname, *l;
8361   sym_link *retype, *letype;
8362
8363   retype = getSpec (operandType (right));
8364   letype = getSpec (operandType (result));
8365
8366   aopOp (result, ic, FALSE, FALSE);
8367
8368   /* if the value is already in a pointer register
8369      then don't need anything more */
8370   if (!AOP_INPREG (AOP (result)))
8371     {
8372       /* otherwise get a free pointer register */
8373       aop = newAsmop (0);
8374       preg = getFreePtr (ic, &aop, FALSE);
8375       emitcode ("mov", "%s,%s",
8376                 preg->name,
8377                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8378       rname = preg->name;
8379     }
8380   else
8381     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8382
8383   freeAsmop (result, NULL, ic, TRUE);
8384   aopOp (right, ic, FALSE, FALSE);
8385
8386   /* if bitfield then unpack the bits */
8387   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8388     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8389   else
8390     {
8391       /* we have can just get the values */
8392       int size = AOP_SIZE (right);
8393       int offset = 0;
8394
8395       while (size--)
8396         {
8397           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8398
8399           MOVA (l);
8400           emitcode ("movx", "@%s,a", rname);
8401
8402           if (size)
8403             emitcode ("inc", "%s", rname);
8404
8405           offset++;
8406         }
8407     }
8408
8409   /* now some housekeeping stuff */
8410   if (aop)
8411     {
8412       /* we had to allocate for this iCode */
8413       freeAsmop (NULL, aop, ic, TRUE);
8414     }
8415   else
8416     {
8417       /* we did not allocate which means left
8418          already in a pointer register, then
8419          if size > 0 && this could be used again
8420          we have to point it back to where it
8421          belongs */
8422       if (AOP_SIZE (right) > 1 &&
8423           !OP_SYMBOL (result)->remat &&
8424           (OP_SYMBOL (result)->liveTo > ic->seq ||
8425            ic->depth))
8426         {
8427           int size = AOP_SIZE (right) - 1;
8428           while (size--)
8429             emitcode ("dec", "%s", rname);
8430         }
8431     }
8432
8433   /* done */
8434   freeAsmop (right, NULL, ic, TRUE);
8435
8436
8437 }
8438
8439 /*-----------------------------------------------------------------*/
8440 /* genFarPointerSet - set value from far space                     */
8441 /*-----------------------------------------------------------------*/
8442 static void
8443 genFarPointerSet (operand * right,
8444                   operand * result, iCode * ic)
8445 {
8446   int size, offset;
8447   sym_link *retype = getSpec (operandType (right));
8448   sym_link *letype = getSpec (operandType (result));
8449
8450   aopOp (result, ic, FALSE, FALSE);
8451
8452   /* if the operand is already in dptr
8453      then we do nothing else we move the value to dptr */
8454   if (AOP_TYPE (result) != AOP_STR)
8455     {
8456       /* if this is remateriazable */
8457       if (AOP_TYPE (result) == AOP_IMMD)
8458         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8459       else
8460         {
8461           /* we need to get it byte by byte */
8462           _startLazyDPSEvaluation ();
8463           if (AOP_TYPE (result) != AOP_DPTR)
8464             {
8465               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8466               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8467               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8468             }
8469           else
8470             {
8471               /* We need to generate a load to DPTR indirect through DPTR. */
8472               D (emitcode (";", "genFarPointerSet -- indirection special case.");
8473                 );
8474               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8475               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8476               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8477               emitcode ("pop", "dph");
8478               emitcode ("pop", "dpl");
8479             }
8480           _endLazyDPSEvaluation ();
8481         }
8482     }
8483   /* so dptr know contains the address */
8484   freeAsmop (result, NULL, ic, TRUE);
8485   aopOp (right, ic, FALSE, TRUE);
8486
8487   /* if bit then unpack */
8488   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8489     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8490   else
8491     {
8492       size = AOP_SIZE (right);
8493       offset = 0;
8494
8495       _startLazyDPSEvaluation ();
8496       while (size--)
8497         {
8498           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8499           MOVA (l);
8500
8501           genSetDPTR (0);
8502           _flushLazyDPS ();
8503
8504           emitcode ("movx", "@dptr,a");
8505           if (size)
8506             emitcode ("inc", "dptr");
8507         }
8508       _endLazyDPSEvaluation ();
8509     }
8510
8511   freeAsmop (right, NULL, ic, TRUE);
8512 }
8513
8514 /*-----------------------------------------------------------------*/
8515 /* genGenPointerSet - set value from generic pointer space         */
8516 /*-----------------------------------------------------------------*/
8517 static void
8518 genGenPointerSet (operand * right,
8519                   operand * result, iCode * ic)
8520 {
8521   int size, offset;
8522   sym_link *retype = getSpec (operandType (right));
8523   sym_link *letype = getSpec (operandType (result));
8524
8525   aopOp (result, ic, FALSE, TRUE);
8526
8527   /* if the operand is already in dptr
8528      then we do nothing else we move the value to dptr */
8529   if (AOP_TYPE (result) != AOP_STR)
8530     {
8531       _startLazyDPSEvaluation ();
8532       /* if this is remateriazable */
8533       if (AOP_TYPE (result) == AOP_IMMD)
8534         {
8535           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8536           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8537         }
8538       else
8539         {                       /* we need to get it byte by byte */
8540           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8541           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8542           emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8543           emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8544         }
8545       _endLazyDPSEvaluation ();
8546     }
8547   /* so dptr know contains the address */
8548   freeAsmop (result, NULL, ic, TRUE);
8549   aopOp (right, ic, FALSE, TRUE);
8550
8551   /* if bit then unpack */
8552   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8553     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8554   else
8555     {
8556       size = AOP_SIZE (right);
8557       offset = 0;
8558
8559       _startLazyDPSEvaluation ();
8560       while (size--)
8561         {
8562           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8563           MOVA (l);
8564
8565           genSetDPTR (0);
8566           _flushLazyDPS ();
8567
8568           emitcode ("lcall", "__gptrput");
8569           if (size)
8570             emitcode ("inc", "dptr");
8571         }
8572       _endLazyDPSEvaluation ();
8573     }
8574
8575   freeAsmop (right, NULL, ic, TRUE);
8576 }
8577
8578 /*-----------------------------------------------------------------*/
8579 /* genPointerSet - stores the value into a pointer location        */
8580 /*-----------------------------------------------------------------*/
8581 static void
8582 genPointerSet (iCode * ic)
8583 {
8584   operand *right, *result;
8585   sym_link *type, *etype;
8586   int p_type;
8587
8588   D (emitcode (";", "genPointerSet ");
8589     );
8590
8591   right = IC_RIGHT (ic);
8592   result = IC_RESULT (ic);
8593
8594   /* depending on the type of pointer we need to
8595      move it to the correct pointer register */
8596   type = operandType (result);
8597   etype = getSpec (type);
8598   /* if left is of type of pointer then it is simple */
8599   if (IS_PTR (type) && !IS_FUNC (type->next))
8600     {
8601       p_type = DCL_TYPE (type);
8602     }
8603   else
8604     {
8605       /* we have to go by the storage class */
8606       p_type = PTR_TYPE (SPEC_OCLS (etype));
8607     }
8608
8609   /* now that we have the pointer type we assign
8610      the pointer values */
8611   switch (p_type)
8612     {
8613
8614     case POINTER:
8615     case IPOINTER:
8616       genNearPointerSet (right, result, ic);
8617       break;
8618
8619     case PPOINTER:
8620       genPagedPointerSet (right, result, ic);
8621       break;
8622
8623     case FPOINTER:
8624       genFarPointerSet (right, result, ic);
8625       break;
8626
8627     case GPOINTER:
8628       genGenPointerSet (right, result, ic);
8629       break;
8630     }
8631
8632 }
8633
8634 /*-----------------------------------------------------------------*/
8635 /* genIfx - generate code for Ifx statement                        */
8636 /*-----------------------------------------------------------------*/
8637 static void
8638 genIfx (iCode * ic, iCode * popIc)
8639 {
8640   operand *cond = IC_COND (ic);
8641   int isbit = 0;
8642
8643   D (emitcode (";", "genIfx ");
8644     );
8645
8646   aopOp (cond, ic, FALSE, FALSE);
8647
8648   /* get the value into acc */
8649   if (AOP_TYPE (cond) != AOP_CRY)
8650     toBoolean (cond);
8651   else
8652     isbit = 1;
8653   /* the result is now in the accumulator */
8654   freeAsmop (cond, NULL, ic, TRUE);
8655
8656   /* if there was something to be popped then do it */
8657   if (popIc)
8658     genIpop (popIc);
8659
8660   /* if the condition is  a bit variable */
8661   if (isbit && IS_ITEMP (cond) &&
8662       SPIL_LOC (cond))
8663     genIfxJump (ic, SPIL_LOC (cond)->rname);
8664   else if (isbit && !IS_ITEMP (cond))
8665     genIfxJump (ic, OP_SYMBOL (cond)->rname);
8666   else
8667     genIfxJump (ic, "a");
8668
8669   ic->generated = 1;
8670 }
8671
8672 /*-----------------------------------------------------------------*/
8673 /* genAddrOf - generates code for address of                       */
8674 /*-----------------------------------------------------------------*/
8675 static void
8676 genAddrOf (iCode * ic)
8677 {
8678   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8679   int size, offset;
8680
8681   D (emitcode (";", "genAddrOf ");
8682     );
8683
8684   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8685
8686   /* if the operand is on the stack then we
8687      need to get the stack offset of this
8688      variable */
8689   if (sym->onStack)
8690     {
8691       /* if it has an offset then we need to compute
8692          it */
8693       if (sym->stack)
8694         {
8695           emitcode ("mov", "a,_bp");
8696           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8697           aopPut (AOP (IC_RESULT (ic)), "a", 0);
8698         }
8699       else
8700         {
8701           /* we can just move _bp */
8702           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8703         }
8704       /* fill the result with zero */
8705       size = AOP_SIZE (IC_RESULT (ic)) - 1;
8706
8707
8708       if (options.stack10bit && size < (FPTRSIZE - 1))
8709         {
8710           fprintf (stderr,
8711                    "*** warning: pointer to stack var truncated.\n");
8712         }
8713
8714       offset = 1;
8715       while (size--)
8716         {
8717           /* Yuck! */
8718           if (options.stack10bit && offset == 2)
8719             {
8720               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8721             }
8722           else
8723             {
8724               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8725             }
8726         }
8727
8728       goto release;
8729     }
8730
8731   /* object not on stack then we need the name */
8732   size = AOP_SIZE (IC_RESULT (ic));
8733   offset = 0;
8734
8735   while (size--)
8736     {
8737       char s[SDCC_NAME_MAX];
8738       if (offset)
8739         sprintf (s, "#(%s >> %d)",
8740                  sym->rname,
8741                  offset * 8);
8742       else
8743         sprintf (s, "#%s", sym->rname);
8744       aopPut (AOP (IC_RESULT (ic)), s, offset++);
8745     }
8746
8747 release:
8748   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8749
8750 }
8751
8752 /*-----------------------------------------------------------------*/
8753 /* genFarFarAssign - assignment when both are in far space         */
8754 /*-----------------------------------------------------------------*/
8755 static void
8756 genFarFarAssign (operand * result, operand * right, iCode * ic)
8757 {
8758   int size = AOP_SIZE (right);
8759   int offset = 0;
8760   char *l;
8761
8762   if (size > 1)
8763     {
8764       /* This is a net loss for size == 1, but a big gain
8765        * otherwise.
8766        */
8767       D (emitcode (";", "genFarFarAssign (improved)");
8768         );
8769
8770       aopOp (result, ic, TRUE, TRUE);
8771
8772       _startLazyDPSEvaluation ();
8773       while (size--)
8774         {
8775           aopPut (AOP (result),
8776                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8777           offset++;
8778         }
8779       _endLazyDPSEvaluation ();
8780       freeAsmop (result, NULL, ic, FALSE);
8781       freeAsmop (right, NULL, ic, FALSE);
8782     }
8783   else
8784     {
8785       D (emitcode (";", "genFarFarAssign ");
8786         );
8787
8788       /* first push the right side on to the stack */
8789       _startLazyDPSEvaluation ();
8790       while (size--)
8791         {
8792           l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8793           MOVA (l);
8794           emitcode ("push", "acc");
8795         }
8796
8797       freeAsmop (right, NULL, ic, FALSE);
8798       /* now assign DPTR to result */
8799       aopOp (result, ic, FALSE, FALSE);
8800       size = AOP_SIZE (result);
8801       while (size--)
8802         {
8803           emitcode ("pop", "acc");
8804           aopPut (AOP (result), "a", --offset);
8805         }
8806       freeAsmop (result, NULL, ic, FALSE);
8807       _endLazyDPSEvaluation ();
8808     }
8809 }
8810
8811 /*-----------------------------------------------------------------*/
8812 /* genAssign - generate code for assignment                        */
8813 /*-----------------------------------------------------------------*/
8814 static void
8815 genAssign (iCode * ic)
8816 {
8817   operand *result, *right;
8818   int size, offset;
8819   unsigned long lit = 0L;
8820
8821   D (emitcode (";", "genAssign ");
8822     );
8823
8824   result = IC_RESULT (ic);
8825   right = IC_RIGHT (ic);
8826
8827   /* if they are the same */
8828   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8829     return;
8830
8831   aopOp (right, ic, FALSE, FALSE);
8832
8833   emitcode (";", "genAssign: resultIsFar = %s",
8834             isOperandInFarSpace (result) ?
8835             "TRUE" : "FALSE");
8836
8837   /* special case both in far space */
8838   if ((AOP_TYPE (right) == AOP_DPTR ||
8839        AOP_TYPE (right) == AOP_DPTR2) &&
8840   /* IS_TRUE_SYMOP(result)       && */
8841       isOperandInFarSpace (result))
8842     {
8843       genFarFarAssign (result, right, ic);
8844       return;
8845     }
8846
8847   aopOp (result, ic, TRUE, FALSE);
8848
8849   /* if they are the same registers */
8850   if (sameRegs (AOP (right), AOP (result)))
8851     goto release;
8852
8853   /* if the result is a bit */
8854   if (AOP_TYPE (result) == AOP_CRY)
8855     {
8856
8857       /* if the right size is a literal then
8858          we know what the value is */
8859       if (AOP_TYPE (right) == AOP_LIT)
8860         {
8861           if (((int) operandLitValue (right)))
8862             aopPut (AOP (result), one, 0);
8863           else
8864             aopPut (AOP (result), zero, 0);
8865           goto release;
8866         }
8867
8868       /* the right is also a bit variable */
8869       if (AOP_TYPE (right) == AOP_CRY)
8870         {
8871           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8872           aopPut (AOP (result), "c", 0);
8873           goto release;
8874         }
8875
8876       /* we need to or */
8877       toBoolean (right);
8878       aopPut (AOP (result), "a", 0);
8879       goto release;
8880     }
8881
8882   /* bit variables done */
8883   /* general case */
8884   size = AOP_SIZE (result);
8885   offset = 0;
8886   if (AOP_TYPE (right) == AOP_LIT)
8887     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8888
8889   if ((size > 1) &&
8890       (AOP_TYPE (result) != AOP_REG) &&
8891       (AOP_TYPE (right) == AOP_LIT) &&
8892       !IS_FLOAT (operandType (right)))
8893     {
8894       D (emitcode (";", "Kevin's better literal load code");
8895         );
8896       _startLazyDPSEvaluation ();
8897       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8898         {
8899           aopPut (AOP (result),
8900                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8901                   offset);
8902           offset++;
8903           size--;
8904         }
8905       /* And now fill the rest with zeros. */
8906       if (size)
8907         {
8908           emitcode ("clr", "a");
8909         }
8910       while (size--)
8911         {
8912           aopPut (AOP (result), "a", offset++);
8913         }
8914       _endLazyDPSEvaluation ();
8915     }
8916   else
8917     {
8918       _startLazyDPSEvaluation ();
8919       while (size--)
8920         {
8921           aopPut (AOP (result),
8922                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8923                   offset);
8924           offset++;
8925         }
8926       _endLazyDPSEvaluation ();
8927     }
8928
8929 release:
8930   freeAsmop (right, NULL, ic, FALSE);
8931   freeAsmop (result, NULL, ic, TRUE);
8932 }
8933
8934 /*-----------------------------------------------------------------*/
8935 /* genJumpTab - generates code for jump table                      */
8936 /*-----------------------------------------------------------------*/
8937 static void
8938 genJumpTab (iCode * ic)
8939 {
8940   symbol *jtab;
8941   char *l;
8942
8943   D (emitcode (";", "genJumpTab ");
8944     );
8945
8946   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8947   /* get the condition into accumulator */
8948   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8949   MOVA (l);
8950   /* multiply by four! */
8951   emitcode ("add", "a,acc");
8952   emitcode ("add", "a,acc");
8953   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8954
8955   jtab = newiTempLabel (NULL);
8956   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8957   emitcode ("jmp", "@a+dptr");
8958   emitcode ("", "%05d$:", jtab->key + 100);
8959   /* now generate the jump labels */
8960   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8961        jtab = setNextItem (IC_JTLABELS (ic)))
8962     emitcode ("ljmp", "%05d$", jtab->key + 100);
8963
8964 }
8965
8966 /*-----------------------------------------------------------------*/
8967 /* genCast - gen code for casting                                  */
8968 /*-----------------------------------------------------------------*/
8969 static void
8970 genCast (iCode * ic)
8971 {
8972   operand *result = IC_RESULT (ic);
8973   sym_link *ctype = operandType (IC_LEFT (ic));
8974   sym_link *rtype = operandType (IC_RIGHT (ic));
8975   operand *right = IC_RIGHT (ic);
8976   int size, offset;
8977
8978   D (emitcode (";", "genCast ");
8979     );
8980
8981   /* if they are equivalent then do nothing */
8982   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8983     return;
8984
8985   aopOp (right, ic, FALSE, FALSE);
8986   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8987
8988   /* if the result is a bit */
8989   if (AOP_TYPE (result) == AOP_CRY)
8990     {
8991       /* if the right size is a literal then
8992          we know what the value is */
8993       if (AOP_TYPE (right) == AOP_LIT)
8994         {
8995           if (((int) operandLitValue (right)))
8996             aopPut (AOP (result), one, 0);
8997           else
8998             aopPut (AOP (result), zero, 0);
8999
9000           goto release;
9001         }
9002
9003       /* the right is also a bit variable */
9004       if (AOP_TYPE (right) == AOP_CRY)
9005         {
9006           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9007           aopPut (AOP (result), "c", 0);
9008           goto release;
9009         }
9010
9011       /* we need to or */
9012       toBoolean (right);
9013       aopPut (AOP (result), "a", 0);
9014       goto release;
9015     }
9016
9017   /* if they are the same size : or less */
9018   if (AOP_SIZE (result) <= AOP_SIZE (right))
9019     {
9020
9021       /* if they are in the same place */
9022       if (sameRegs (AOP (right), AOP (result)))
9023         goto release;
9024
9025       /* if they in different places then copy */
9026       size = AOP_SIZE (result);
9027       offset = 0;
9028       _startLazyDPSEvaluation ();
9029       while (size--)
9030         {
9031           aopPut (AOP (result),
9032                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9033                   offset);
9034           offset++;
9035         }
9036       _endLazyDPSEvaluation ();
9037       goto release;
9038     }
9039
9040
9041   /* if the result is of type pointer */
9042   if (IS_PTR (ctype))
9043     {
9044
9045       int p_type;
9046       sym_link *type = operandType (right);
9047
9048       /* pointer to generic pointer */
9049       if (IS_GENPTR (ctype))
9050         {
9051           char *l = zero;
9052
9053           if (IS_PTR (type))
9054             {
9055               p_type = DCL_TYPE (type);
9056             }
9057           else
9058             {
9059 #if OLD_CAST_BEHAVIOR
9060               /* KV: we are converting a non-pointer type to
9061                * a generic pointer. This (ifdef'd out) code
9062                * says that the resulting generic pointer
9063                * should have the same class as the storage
9064                * location of the non-pointer variable.
9065                *
9066                * For example, converting an int (which happens
9067                * to be stored in DATA space) to a pointer results
9068                * in a DATA generic pointer; if the original int
9069                * in XDATA space, so will be the resulting pointer.
9070                *
9071                * I don't like that behavior, and thus this change:
9072                * all such conversions will be forced to XDATA and
9073                * throw a warning. If you want some non-XDATA
9074                * type, or you want to suppress the warning, you
9075                * must go through an intermediate cast, like so:
9076                *
9077                * char _generic *gp = (char _xdata *)(intVar);
9078                */
9079               sym_link *etype = getSpec (type);
9080
9081               /* we have to go by the storage class */
9082               if (SPEC_OCLS (etype) != generic)
9083                 {
9084                   p_type = PTR_TYPE (SPEC_OCLS (etype));
9085                 }
9086               else
9087 #endif
9088                 {
9089                   /* Converting unknown class (i.e. register variable)
9090                    * to generic pointer. This is not good, but
9091                    * we'll make a guess (and throw a warning).
9092                    */
9093                   p_type = FPOINTER;
9094                   werror (W_INT_TO_GEN_PTR_CAST);
9095                 }
9096             }
9097
9098           /* the first two bytes are known */
9099           size = GPTRSIZE - 1;
9100           offset = 0;
9101           _startLazyDPSEvaluation ();
9102           while (size--)
9103             {
9104               aopPut (AOP (result),
9105                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9106                       offset);
9107               offset++;
9108             }
9109           _endLazyDPSEvaluation ();
9110
9111           /* the last byte depending on type */
9112           switch (p_type)
9113             {
9114             case IPOINTER:
9115             case POINTER:
9116               l = zero;
9117               break;
9118             case FPOINTER:
9119               l = one;
9120               break;
9121             case CPOINTER:
9122               l = "#0x02";
9123               break;
9124             case PPOINTER:
9125               l = "#0x03";
9126               break;
9127
9128             default:
9129               /* this should never happen */
9130               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9131                       "got unknown pointer type");
9132               exit (1);
9133             }
9134           aopPut (AOP (result), l, GPTRSIZE - 1);
9135           goto release;
9136         }
9137
9138       /* just copy the pointers */
9139       size = AOP_SIZE (result);
9140       offset = 0;
9141       _startLazyDPSEvaluation ();
9142       while (size--)
9143         {
9144           aopPut (AOP (result),
9145                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9146                   offset);
9147           offset++;
9148         }
9149       _endLazyDPSEvaluation ();
9150       goto release;
9151     }
9152
9153   /* so we now know that the size of destination is greater
9154      than the size of the source */
9155   /* we move to result for the size of source */
9156   size = AOP_SIZE (right);
9157   offset = 0;
9158   _startLazyDPSEvaluation ();
9159   while (size--)
9160     {
9161       aopPut (AOP (result),
9162               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9163               offset);
9164       offset++;
9165     }
9166   _endLazyDPSEvaluation ();
9167
9168   /* now depending on the sign of the source && destination */
9169   size = AOP_SIZE (result) - AOP_SIZE (right);
9170   /* if unsigned or not an integral type */
9171   /* also, if the source is a bit, we don't need to sign extend, because
9172    * it can't possibly have set the sign bit.
9173    */
9174   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9175     {
9176       while (size--)
9177         {
9178           aopPut (AOP (result), zero, offset++);
9179         }
9180     }
9181   else
9182     {
9183       /* we need to extend the sign :{ */
9184       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9185                         FALSE, FALSE, TRUE);
9186       MOVA (l);
9187       emitcode ("rlc", "a");
9188       emitcode ("subb", "a,acc");
9189       while (size--)
9190         aopPut (AOP (result), "a", offset++);
9191     }
9192
9193   /* we are done hurray !!!! */
9194
9195 release:
9196   freeAsmop (right, NULL, ic, TRUE);
9197   freeAsmop (result, NULL, ic, TRUE);
9198
9199 }
9200
9201 /*-----------------------------------------------------------------*/
9202 /* genDjnz - generate decrement & jump if not zero instrucion      */
9203 /*-----------------------------------------------------------------*/
9204 static int
9205 genDjnz (iCode * ic, iCode * ifx)
9206 {
9207   symbol *lbl, *lbl1;
9208   if (!ifx)
9209     return 0;
9210
9211   /* if the if condition has a false label
9212      then we cannot save */
9213   if (IC_FALSE (ifx))
9214     return 0;
9215
9216   /* if the minus is not of the form
9217      a = a - 1 */
9218   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9219       !IS_OP_LITERAL (IC_RIGHT (ic)))
9220     return 0;
9221
9222   if (operandLitValue (IC_RIGHT (ic)) != 1)
9223     return 0;
9224
9225   /* if the size of this greater than one then no
9226      saving */
9227   if (getSize (operandType (IC_RESULT (ic))) > 1)
9228     return 0;
9229
9230   /* otherwise we can save BIG */
9231   D(emitcode(";", "genDjnz"););
9232
9233   lbl = newiTempLabel (NULL);
9234   lbl1 = newiTempLabel (NULL);
9235
9236   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9237
9238   if (AOP_NEEDSACC(IC_RESULT(ic)))
9239   {
9240       /* If the result is accessed indirectly via
9241        * the accumulator, we must explicitly write
9242        * it back after the decrement.
9243        */
9244       emitcode ("dec", "%s",
9245                  aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, FALSE));
9246       aopPut(AOP(IC_RESULT(ic)), "acc", 0);
9247       emitcode ("jnz", "%05d$", lbl->key + 100);
9248   }
9249   else if (IS_AOP_PREG (IC_RESULT (ic)))
9250     {
9251       emitcode ("dec", "%s",
9252                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9253       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9254       emitcode ("jnz", "%05d$", lbl->key + 100);
9255     }
9256   else
9257     {
9258       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9259                 lbl->key + 100);
9260     }
9261   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9262   emitcode ("", "%05d$:", lbl->key + 100);
9263   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9264   emitcode ("", "%05d$:", lbl1->key + 100);
9265
9266   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9267   ifx->generated = 1;
9268   return 1;
9269 }
9270
9271 /*-----------------------------------------------------------------*/
9272 /* genReceive - generate code for a receive iCode                  */
9273 /*-----------------------------------------------------------------*/
9274 static void
9275 genReceive (iCode * ic)
9276 {
9277
9278   D (emitcode (";", "genReceive ");
9279     );
9280
9281   if (isOperandInFarSpace (IC_RESULT (ic)) &&
9282       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9283        IS_TRUE_SYMOP (IC_RESULT (ic))))
9284     {
9285       int size = getSize (operandType (IC_RESULT (ic)));
9286       int offset = fReturnSizeDS390 - size;
9287       while (size--)
9288         {
9289           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9290                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9291           offset++;
9292         }
9293       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9294       size = AOP_SIZE (IC_RESULT (ic));
9295       offset = 0;
9296       while (size--)
9297         {
9298           emitcode ("pop", "acc");
9299           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9300         }
9301
9302     }
9303   else
9304     {
9305       _G.accInUse++;
9306       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9307       _G.accInUse--;
9308       assignResultValue (IC_RESULT (ic));
9309     }
9310
9311   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9312 }
9313
9314 /*-----------------------------------------------------------------*/
9315 /* gen390Code - generate code for Dallas 390 based controllers     */
9316 /*-----------------------------------------------------------------*/
9317 void
9318 gen390Code (iCode * lic)
9319 {
9320   iCode *ic;
9321   int cln = 0;
9322
9323   lineHead = lineCurr = NULL;
9324
9325 #if 0
9326   //REMOVE ME!!!
9327   /* print the allocation information */
9328   if (allocInfo)
9329     printAllocInfo (currFunc, codeOutFile);
9330 #endif
9331   /* if debug information required */
9332   if (options.debug && currFunc)
9333     {
9334       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9335       _G.debugLine = 1;
9336       if (IS_STATIC (currFunc->etype))
9337         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9338       else
9339         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9340       _G.debugLine = 0;
9341     }
9342   /* stack pointer name */
9343   if (options.useXstack)
9344     spname = "_spx";
9345   else
9346     spname = "sp";
9347
9348
9349   for (ic = lic; ic; ic = ic->next)
9350     {
9351
9352       if (cln != ic->lineno)
9353         {
9354           if (options.debug)
9355             {
9356               _G.debugLine = 1;
9357               emitcode ("", "C$%s$%d$%d$%d ==.",
9358                         FileBaseName (ic->filename), ic->lineno,
9359                         ic->level, ic->block);
9360               _G.debugLine = 0;
9361             }
9362           emitcode (";", "%s %d", ic->filename, ic->lineno);
9363           cln = ic->lineno;
9364         }
9365       /* if the result is marked as
9366          spilt and rematerializable or code for
9367          this has already been generated then
9368          do nothing */
9369       if (resultRemat (ic) || ic->generated)
9370         continue;
9371
9372       /* depending on the operation */
9373       switch (ic->op)
9374         {
9375         case '!':
9376           genNot (ic);
9377           break;
9378
9379         case '~':
9380           genCpl (ic);
9381           break;
9382
9383         case UNARYMINUS:
9384           genUminus (ic);
9385           break;
9386
9387         case IPUSH:
9388           genIpush (ic);
9389           break;
9390
9391         case IPOP:
9392           /* IPOP happens only when trying to restore a
9393              spilt live range, if there is an ifx statement
9394              following this pop then the if statement might
9395              be using some of the registers being popped which
9396              would destory the contents of the register so
9397              we need to check for this condition and handle it */
9398           if (ic->next &&
9399               ic->next->op == IFX &&
9400               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9401             genIfx (ic->next, ic);
9402           else
9403             genIpop (ic);
9404           break;
9405
9406         case CALL:
9407           genCall (ic);
9408           break;
9409
9410         case PCALL:
9411           genPcall (ic);
9412           break;
9413
9414         case FUNCTION:
9415           genFunction (ic);
9416           break;
9417
9418         case ENDFUNCTION:
9419           genEndFunction (ic);
9420           break;
9421
9422         case RETURN:
9423           genRet (ic);
9424           break;
9425
9426         case LABEL:
9427           genLabel (ic);
9428           break;
9429
9430         case GOTO:
9431           genGoto (ic);
9432           break;
9433
9434         case '+':
9435           genPlus (ic);
9436           break;
9437
9438         case '-':
9439           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9440             genMinus (ic);
9441           break;
9442
9443         case '*':
9444           genMult (ic);
9445           break;
9446
9447         case '/':
9448           genDiv (ic);
9449           break;
9450
9451         case '%':
9452           genMod (ic);
9453           break;
9454
9455         case '>':
9456           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9457           break;
9458
9459         case '<':
9460           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9461           break;
9462
9463         case LE_OP:
9464         case GE_OP:
9465         case NE_OP:
9466
9467           /* note these two are xlated by algebraic equivalence
9468              during parsing SDCC.y */
9469           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9470                   "got '>=' or '<=' shouldn't have come here");
9471           break;
9472
9473         case EQ_OP:
9474           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9475           break;
9476
9477         case AND_OP:
9478           genAndOp (ic);
9479           break;
9480
9481         case OR_OP:
9482           genOrOp (ic);
9483           break;
9484
9485         case '^':
9486           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9487           break;
9488
9489         case '|':
9490           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9491           break;
9492
9493         case BITWISEAND:
9494           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9495           break;
9496
9497         case INLINEASM:
9498           genInline (ic);
9499           break;
9500
9501         case RRC:
9502           genRRC (ic);
9503           break;
9504
9505         case RLC:
9506           genRLC (ic);
9507           break;
9508
9509         case GETHBIT:
9510           genGetHbit (ic);
9511           break;
9512
9513         case LEFT_OP:
9514           genLeftShift (ic);
9515           break;
9516
9517         case RIGHT_OP:
9518           genRightShift (ic);
9519           break;
9520
9521         case GET_VALUE_AT_ADDRESS:
9522           genPointerGet (ic);
9523           break;
9524
9525         case '=':
9526           if (POINTER_SET (ic))
9527             genPointerSet (ic);
9528           else
9529             genAssign (ic);
9530           break;
9531
9532         case IFX:
9533           genIfx (ic, NULL);
9534           break;
9535
9536         case ADDRESS_OF:
9537           genAddrOf (ic);
9538           break;
9539
9540         case JUMPTABLE:
9541           genJumpTab (ic);
9542           break;
9543
9544         case CAST:
9545           genCast (ic);
9546           break;
9547
9548         case RECEIVE:
9549           genReceive (ic);
9550           break;
9551
9552         case SEND:
9553           addSet (&_G.sendSet, ic);
9554           break;
9555
9556         default:
9557           ic = ic;
9558         }
9559     }
9560
9561
9562   /* now we are ready to call the
9563      peep hole optimizer */
9564   if (!options.nopeep)
9565     peepHole (&lineHead);
9566
9567   /* now do the actual printing */
9568   printLine (lineHead, codeOutFile);
9569   return;
9570 }