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