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