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