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