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