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