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