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