Let's adjust instead of a boldy decrement
[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
6158       emitcode ("anl", "a,#0x%02x",
6159                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6160
6161       emitcode ("mov", "c,acc.0");      // c = B
6162
6163       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6164
6165       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6166
6167       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6168
6169       break;
6170     case 7:                     // a:x <<= 7
6171
6172       emitcode ("anl", "a,#0x%02x",
6173                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6174
6175       emitcode ("mov", "c,acc.0");      // c = B
6176
6177       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6178
6179       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6180
6181       break;
6182     default:
6183       break;
6184     }
6185 }
6186 #endif
6187
6188 #if 0
6189 //REMOVE ME!!!
6190 /*-----------------------------------------------------------------*/
6191 /* AccAXRsh - right shift a:x known count (0..7)                   */
6192 /*-----------------------------------------------------------------*/
6193 static void
6194 AccAXRsh (char *x, int shCount)
6195 {
6196   switch (shCount)
6197     {
6198     case 0:
6199       break;
6200     case 1:
6201       CLRC;
6202       AccAXRrl1 (x);            // 0->a:x
6203
6204       break;
6205     case 2:
6206       CLRC;
6207       AccAXRrl1 (x);            // 0->a:x
6208
6209       CLRC;
6210       AccAXRrl1 (x);            // 0->a:x
6211
6212       break;
6213     case 3:
6214     case 4:
6215     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6216
6217       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6218
6219       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6220
6221       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6222
6223       emitcode ("anl", "a,#0x%02x",
6224                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6225
6226       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6227
6228       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6229
6230       emitcode ("anl", "a,#0x%02x",
6231                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6232
6233       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6234
6235       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6236
6237       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6238
6239       break;
6240     case 6:                     // AABBBBBB:CCDDDDDD
6241
6242       emitcode ("mov", "c,acc.7");
6243       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6244
6245       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6246
6247       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6248
6249       emitcode ("anl", "a,#0x%02x",
6250                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6251
6252       break;
6253     case 7:                     // ABBBBBBB:CDDDDDDD
6254
6255       emitcode ("mov", "c,acc.7");      // c = A
6256
6257       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6258
6259       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6260
6261       emitcode ("anl", "a,#0x%02x",
6262                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6263
6264       break;
6265     default:
6266       break;
6267     }
6268 }
6269 #endif
6270
6271 #if 0
6272 //REMOVE ME!!!
6273 /*-----------------------------------------------------------------*/
6274 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6275 /*-----------------------------------------------------------------*/
6276 static void
6277 AccAXRshS (char *x, int shCount)
6278 {
6279   symbol *tlbl;
6280   switch (shCount)
6281     {
6282     case 0:
6283       break;
6284     case 1:
6285       emitcode ("mov", "c,acc.7");
6286       AccAXRrl1 (x);            // s->a:x
6287
6288       break;
6289     case 2:
6290       emitcode ("mov", "c,acc.7");
6291       AccAXRrl1 (x);            // s->a:x
6292
6293       emitcode ("mov", "c,acc.7");
6294       AccAXRrl1 (x);            // s->a:x
6295
6296       break;
6297     case 3:
6298     case 4:
6299     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6300
6301       tlbl = newiTempLabel (NULL);
6302       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6303
6304       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6305
6306       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6307
6308       emitcode ("anl", "a,#0x%02x",
6309                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6310
6311       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6312
6313       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6314
6315       emitcode ("anl", "a,#0x%02x",
6316                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6317
6318       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6319
6320       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6321
6322       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6323
6324       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6325       emitcode ("orl", "a,#0x%02x",
6326                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6327
6328       emitcode ("", "%05d$:", tlbl->key + 100);
6329       break;                    // SSSSAAAA:BBBCCCCC
6330
6331     case 6:                     // AABBBBBB:CCDDDDDD
6332
6333       tlbl = newiTempLabel (NULL);
6334       emitcode ("mov", "c,acc.7");
6335       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6336
6337       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6338
6339       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6340
6341       emitcode ("anl", "a,#0x%02x",
6342                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6343
6344       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6345       emitcode ("orl", "a,#0x%02x",
6346                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6347
6348       emitcode ("", "%05d$:", tlbl->key + 100);
6349       break;
6350     case 7:                     // ABBBBBBB:CDDDDDDD
6351
6352       tlbl = newiTempLabel (NULL);
6353       emitcode ("mov", "c,acc.7");      // c = A
6354
6355       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6356
6357       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6358
6359       emitcode ("anl", "a,#0x%02x",
6360                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6361
6362       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6363       emitcode ("orl", "a,#0x%02x",
6364                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6365
6366       emitcode ("", "%05d$:", tlbl->key + 100);
6367       break;
6368     default:
6369       break;
6370     }
6371 }
6372 #endif
6373
6374 #if 0
6375 //REMOVE ME!!!
6376 /*-----------------------------------------------------------------*/
6377 /* shiftL2Left2Result - shift left two bytes from left to result   */
6378 /*-----------------------------------------------------------------*/
6379 static void
6380 shiftL2Left2Result (operand * left, int offl,
6381                     operand * result, int offr, int shCount)
6382 {
6383   if (sameRegs (AOP (result), AOP (left)) &&
6384       ((offl + MSB16) == offr))
6385     {
6386       /* don't crash result[offr] */
6387       MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6388       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6389     }
6390   else
6391     {
6392       movLeft2Result (left, offl, result, offr, 0);
6393       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6394     }
6395   /* ax << shCount (x = lsb(result)) */
6396   AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6397   aopPut (AOP (result), "a", offr + MSB16);
6398 }
6399 #endif
6400
6401 #if 0
6402 //REMOVE ME!!!
6403 /*-----------------------------------------------------------------*/
6404 /* shiftR2Left2Result - shift right two bytes from left to result  */
6405 /*-----------------------------------------------------------------*/
6406 static void
6407 shiftR2Left2Result (operand * left, int offl,
6408                     operand * result, int offr,
6409                     int shCount, int sign)
6410 {
6411   if (sameRegs (AOP (result), AOP (left)) &&
6412       ((offl + MSB16) == offr))
6413     {
6414       /* don't crash result[offr] */
6415       MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6416       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6417     }
6418   else
6419     {
6420       movLeft2Result (left, offl, result, offr, 0);
6421       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6422     }
6423   /* a:x >> shCount (x = lsb(result)) */
6424   if (sign)
6425     AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6426   else
6427     AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6428   if (getDataSize (result) > 1)
6429     aopPut (AOP (result), "a", offr + MSB16);
6430 }
6431 #endif
6432
6433 #if 0
6434 //REMOVE ME!!!
6435 /*-----------------------------------------------------------------*/
6436 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6437 /*-----------------------------------------------------------------*/
6438 static void
6439 shiftLLeftOrResult (operand * left, int offl,
6440                     operand * result, int offr, int shCount)
6441 {
6442   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6443   /* shift left accumulator */
6444   AccLsh (shCount);
6445   /* or with result */
6446   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6447   /* back to result */
6448   aopPut (AOP (result), "a", offr);
6449 }
6450 #endif
6451
6452 #if 0
6453 //REMOVE ME!!!
6454 /*-----------------------------------------------------------------*/
6455 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6456 /*-----------------------------------------------------------------*/
6457 static void
6458 shiftRLeftOrResult (operand * left, int offl,
6459                     operand * result, int offr, int shCount)
6460 {
6461   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6462   /* shift right accumulator */
6463   AccRsh (shCount);
6464   /* or with result */
6465   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6466   /* back to result */
6467   aopPut (AOP (result), "a", offr);
6468 }
6469 #endif
6470
6471 #if 0
6472 //REMOVE ME!!!
6473 /*-----------------------------------------------------------------*/
6474 /* genlshOne - left shift a one byte quantity by known count       */
6475 /*-----------------------------------------------------------------*/
6476 static void
6477 genlshOne (operand * result, operand * left, int shCount)
6478 {
6479   D (emitcode (";", "genlshOne ");
6480     );
6481   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6482 }
6483 #endif
6484
6485 #if 0
6486 //REMOVE ME!!!
6487 /*-----------------------------------------------------------------*/
6488 /* genlshTwo - left shift two bytes by known amount != 0           */
6489 /*-----------------------------------------------------------------*/
6490 static void
6491 genlshTwo (operand * result, operand * left, int shCount)
6492 {
6493   int size;
6494
6495   D (emitcode (";", "genlshTwo ");
6496     );
6497
6498   size = getDataSize (result);
6499
6500   /* if shCount >= 8 */
6501   if (shCount >= 8)
6502     {
6503       shCount -= 8;
6504
6505       if (size > 1)
6506         {
6507           if (shCount)
6508             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6509           else
6510             movLeft2Result (left, LSB, result, MSB16, 0);
6511         }
6512       aopPut (AOP (result), zero, LSB);
6513     }
6514
6515   /*  1 <= shCount <= 7 */
6516   else
6517     {
6518       if (size == 1)
6519         shiftL1Left2Result (left, LSB, result, LSB, shCount);
6520       else
6521         shiftL2Left2Result (left, LSB, result, LSB, shCount);
6522     }
6523 }
6524 #endif
6525
6526 #if 0
6527 //REMOVE ME!!!
6528 /*-----------------------------------------------------------------*/
6529 /* shiftLLong - shift left one long from left to result            */
6530 /* offl = LSB or MSB16                                             */
6531 /*-----------------------------------------------------------------*/
6532 static void
6533 shiftLLong (operand * left, operand * result, int offr)
6534 {
6535   char *l;
6536   int size = AOP_SIZE (result);
6537
6538   if (size >= LSB + offr)
6539     {
6540       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6541       MOVA (l);
6542       emitcode ("add", "a,acc");
6543       if (sameRegs (AOP (left), AOP (result)) &&
6544           size >= MSB16 + offr && offr != LSB)
6545         emitcode ("xch", "a,%s",
6546                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6547       else
6548         aopPut (AOP (result), "a", LSB + offr);
6549     }
6550
6551   if (size >= MSB16 + offr)
6552     {
6553       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6554         {
6555           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6556           MOVA (l);
6557         }
6558       emitcode ("rlc", "a");
6559       if (sameRegs (AOP (left), AOP (result)) &&
6560           size >= MSB24 + offr && offr != LSB)
6561         emitcode ("xch", "a,%s",
6562                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6563       else
6564         aopPut (AOP (result), "a", MSB16 + offr);
6565     }
6566
6567   if (size >= MSB24 + offr)
6568     {
6569       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6570         {
6571           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6572           MOVA (l);
6573         }
6574       emitcode ("rlc", "a");
6575       if (sameRegs (AOP (left), AOP (result)) &&
6576           size >= MSB32 + offr && offr != LSB)
6577         emitcode ("xch", "a,%s",
6578                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6579       else
6580         aopPut (AOP (result), "a", MSB24 + offr);
6581     }
6582
6583   if (size > MSB32 + offr)
6584     {
6585       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6586         {
6587           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6588           MOVA (l);
6589         }
6590       emitcode ("rlc", "a");
6591       aopPut (AOP (result), "a", MSB32 + offr);
6592     }
6593   if (offr != LSB)
6594     aopPut (AOP (result), zero, LSB);
6595 }
6596 #endif
6597
6598 #if 0
6599 //REMOVE ME!!!
6600 /*-----------------------------------------------------------------*/
6601 /* genlshFour - shift four byte by a known amount != 0             */
6602 /*-----------------------------------------------------------------*/
6603 static void
6604 genlshFour (operand * result, operand * left, int shCount)
6605 {
6606   int size;
6607
6608   D (emitcode (";", "genlshFour ");
6609     );
6610
6611   size = AOP_SIZE (result);
6612
6613   /* if shifting more that 3 bytes */
6614   if (shCount >= 24)
6615     {
6616       shCount -= 24;
6617       if (shCount)
6618         /* lowest order of left goes to the highest
6619            order of the destination */
6620         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6621       else
6622         movLeft2Result (left, LSB, result, MSB32, 0);
6623       aopPut (AOP (result), zero, LSB);
6624       aopPut (AOP (result), zero, MSB16);
6625       aopPut (AOP (result), zero, MSB32);
6626       return;
6627     }
6628
6629   /* more than two bytes */
6630   else if (shCount >= 16)
6631     {
6632       /* lower order two bytes goes to higher order two bytes */
6633       shCount -= 16;
6634       /* if some more remaining */
6635       if (shCount)
6636         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6637       else
6638         {
6639           movLeft2Result (left, MSB16, result, MSB32, 0);
6640           movLeft2Result (left, LSB, result, MSB24, 0);
6641         }
6642       aopPut (AOP (result), zero, MSB16);
6643       aopPut (AOP (result), zero, LSB);
6644       return;
6645     }
6646
6647   /* if more than 1 byte */
6648   else if (shCount >= 8)
6649     {
6650       /* lower order three bytes goes to higher order  three bytes */
6651       shCount -= 8;
6652       if (size == 2)
6653         {
6654           if (shCount)
6655             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6656           else
6657             movLeft2Result (left, LSB, result, MSB16, 0);
6658         }
6659       else
6660         {                       /* size = 4 */
6661           if (shCount == 0)
6662             {
6663               movLeft2Result (left, MSB24, result, MSB32, 0);
6664               movLeft2Result (left, MSB16, result, MSB24, 0);
6665               movLeft2Result (left, LSB, result, MSB16, 0);
6666               aopPut (AOP (result), zero, LSB);
6667             }
6668           else if (shCount == 1)
6669             shiftLLong (left, result, MSB16);
6670           else
6671             {
6672               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6673               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6674               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6675               aopPut (AOP (result), zero, LSB);
6676             }
6677         }
6678     }
6679
6680   /* 1 <= shCount <= 7 */
6681   else if (shCount <= 2)
6682     {
6683       shiftLLong (left, result, LSB);
6684       if (shCount == 2)
6685         shiftLLong (result, result, LSB);
6686     }
6687   /* 3 <= shCount <= 7, optimize */
6688   else
6689     {
6690       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6691       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6692       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6693     }
6694 }
6695 #endif
6696
6697 #if 0
6698 //REMOVE ME!!!
6699 /*-----------------------------------------------------------------*/
6700 /* genLeftShiftLiteral - left shifting by known count              */
6701 /*-----------------------------------------------------------------*/
6702 static void
6703 genLeftShiftLiteral (operand * left,
6704                      operand * right,
6705                      operand * result,
6706                      iCode * ic)
6707 {
6708   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6709   int size;
6710
6711   D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6712     );
6713
6714   freeAsmop (right, NULL, ic, TRUE);
6715
6716   aopOp (left, ic, FALSE, FALSE);
6717   aopOp (result, ic, FALSE, TRUE);
6718
6719   size = getSize (operandType (result));
6720
6721 #if VIEW_SIZE
6722   emitcode ("; shift left ", "result %d, left %d", size,
6723             AOP_SIZE (left));
6724 #endif
6725
6726   /* I suppose that the left size >= result size */
6727   if (shCount == 0)
6728     {
6729       while (size--)
6730         {
6731           movLeft2Result (left, size, result, size, 0);
6732         }
6733     }
6734
6735   else if (shCount >= (size * 8))
6736     while (size--)
6737       aopPut (AOP (result), zero, size);
6738   else
6739     {
6740       switch (size)
6741         {
6742         case 1:
6743           genlshOne (result, left, shCount);
6744           break;
6745
6746         case 2:
6747         case 3:         /* bug: this is for generic pointers, I bet. */
6748           genlshTwo (result, left, shCount);
6749           break;
6750
6751         case 4:
6752           genlshFour (result, left, shCount);
6753           break;
6754         }
6755     }
6756   freeAsmop (left, NULL, ic, TRUE);
6757   freeAsmop (result, NULL, ic, TRUE);
6758 }
6759 #endif
6760
6761 /*-----------------------------------------------------------------*/
6762 /* genLeftShift - generates code for left shifting                 */
6763 /*-----------------------------------------------------------------*/
6764 static void
6765 genLeftShift (iCode * ic)
6766 {
6767   operand *left, *right, *result;
6768   int size, offset;
6769   char *l;
6770   symbol *tlbl, *tlbl1;
6771
6772   D (emitcode (";", "genLeftShift ");
6773     );
6774
6775   right = IC_RIGHT (ic);
6776   left = IC_LEFT (ic);
6777   result = IC_RESULT (ic);
6778
6779   aopOp (right, ic, FALSE, FALSE);
6780
6781 #if 0
6782   /* if the shift count is known then do it
6783      as efficiently as possible */
6784   if (AOP_TYPE (right) == AOP_LIT)
6785     {
6786       genLeftShiftLiteral (left, right, result, ic);
6787       return;
6788     }
6789 #endif
6790
6791   /* shift count is unknown then we have to form
6792      a loop get the loop count in B : Note: we take
6793      only the lower order byte since shifting
6794      more that 32 bits make no sense anyway, ( the
6795      largest size of an object can be only 32 bits ) */
6796
6797   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6798   emitcode ("inc", "b");
6799   freeAsmop (right, NULL, ic, TRUE);
6800   aopOp (left, ic, FALSE, FALSE);
6801   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6802
6803   /* now move the left to the result if they are not the
6804      same */
6805   if (!sameRegs (AOP (left), AOP (result)) &&
6806       AOP_SIZE (result) > 1)
6807     {
6808
6809       size = AOP_SIZE (result);
6810       offset = 0;
6811       _startLazyDPSEvaluation ();
6812       while (size--)
6813         {
6814           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6815           if (*l == '@' && (IS_AOP_PREG (result)))
6816             {
6817
6818               emitcode ("mov", "a,%s", l);
6819               aopPut (AOP (result), "a", offset);
6820             }
6821           else
6822             aopPut (AOP (result), l, offset);
6823           offset++;
6824         }
6825       _endLazyDPSEvaluation ();
6826     }
6827
6828   tlbl = newiTempLabel (NULL);
6829   size = AOP_SIZE (result);
6830   offset = 0;
6831   tlbl1 = newiTempLabel (NULL);
6832
6833   /* if it is only one byte then */
6834   if (size == 1)
6835     {
6836       symbol *tlbl1 = newiTempLabel (NULL);
6837
6838       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6839       MOVA (l);
6840       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6841       emitcode ("", "%05d$:", tlbl->key + 100);
6842       emitcode ("add", "a,acc");
6843       emitcode ("", "%05d$:", tlbl1->key + 100);
6844       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6845       aopPut (AOP (result), "a", 0);
6846       goto release;
6847     }
6848
6849   reAdjustPreg (AOP (result));
6850
6851   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6852   emitcode ("", "%05d$:", tlbl->key + 100);
6853   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6854   MOVA (l);
6855   emitcode ("add", "a,acc");
6856   aopPut (AOP (result), "a", offset++);
6857   _startLazyDPSEvaluation ();
6858   while (--size)
6859     {
6860       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6861       MOVA (l);
6862       emitcode ("rlc", "a");
6863       aopPut (AOP (result), "a", offset++);
6864     }
6865   _endLazyDPSEvaluation ();
6866   reAdjustPreg (AOP (result));
6867
6868   emitcode ("", "%05d$:", tlbl1->key + 100);
6869   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6870 release:
6871   freeAsmop (left, NULL, ic, TRUE);
6872   freeAsmop (result, NULL, ic, TRUE);
6873 }
6874
6875 #if 0
6876 //REMOVE ME!!!
6877 /*-----------------------------------------------------------------*/
6878 /* genrshOne - right shift a one byte quantity by known count      */
6879 /*-----------------------------------------------------------------*/
6880 static void
6881 genrshOne (operand * result, operand * left,
6882            int shCount, int sign)
6883 {
6884   D (emitcode (";", "genrshOne");
6885     );
6886   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6887 }
6888 #endif
6889
6890 #if 0
6891 //REMOVE ME!!!
6892 /*-----------------------------------------------------------------*/
6893 /* genrshTwo - right shift two bytes by known amount != 0          */
6894 /*-----------------------------------------------------------------*/
6895 static void
6896 genrshTwo (operand * result, operand * left,
6897            int shCount, int sign)
6898 {
6899   D (emitcode (";", "genrshTwo");
6900     );
6901
6902   /* if shCount >= 8 */
6903   if (shCount >= 8)
6904     {
6905       shCount -= 8;
6906       if (shCount)
6907         shiftR1Left2Result (left, MSB16, result, LSB,
6908                             shCount, sign);
6909       else
6910         movLeft2Result (left, MSB16, result, LSB, sign);
6911       addSign (result, MSB16, sign);
6912     }
6913
6914   /*  1 <= shCount <= 7 */
6915   else
6916     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6917 }
6918 #endif
6919
6920 #if 0
6921 //REMOVE ME!!!
6922 /*-----------------------------------------------------------------*/
6923 /* shiftRLong - shift right one long from left to result           */
6924 /* offl = LSB or MSB16                                             */
6925 /*-----------------------------------------------------------------*/
6926 static void
6927 shiftRLong (operand * left, int offl,
6928             operand * result, int sign)
6929 {
6930   if (!sign)
6931     emitcode ("clr", "c");
6932   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
6933   if (sign)
6934     emitcode ("mov", "c,acc.7");
6935   emitcode ("rrc", "a");
6936   aopPut (AOP (result), "a", MSB32 - offl);
6937   if (offl == MSB16)
6938     /* add sign of "a" */
6939     addSign (result, MSB32, sign);
6940
6941   MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
6942   emitcode ("rrc", "a");
6943   aopPut (AOP (result), "a", MSB24 - offl);
6944
6945   MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
6946   emitcode ("rrc", "a");
6947   aopPut (AOP (result), "a", MSB16 - offl);
6948
6949   if (offl == LSB)
6950     {
6951       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
6952       emitcode ("rrc", "a");
6953       aopPut (AOP (result), "a", LSB);
6954     }
6955 }
6956 #endif
6957
6958 #if 0
6959 //REMOVE ME!!!
6960 /*-----------------------------------------------------------------*/
6961 /* genrshFour - shift four byte by a known amount != 0             */
6962 /*-----------------------------------------------------------------*/
6963 static void
6964 genrshFour (operand * result, operand * left,
6965             int shCount, int sign)
6966 {
6967   D (emitcode (";", "genrshFour");
6968     );
6969
6970   /* if shifting more that 3 bytes */
6971   if (shCount >= 24)
6972     {
6973       shCount -= 24;
6974       if (shCount)
6975         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6976       else
6977         movLeft2Result (left, MSB32, result, LSB, sign);
6978       addSign (result, MSB16, sign);
6979     }
6980   else if (shCount >= 16)
6981     {
6982       shCount -= 16;
6983       if (shCount)
6984         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6985       else
6986         {
6987           movLeft2Result (left, MSB24, result, LSB, 0);
6988           movLeft2Result (left, MSB32, result, MSB16, sign);
6989         }
6990       addSign (result, MSB24, sign);
6991     }
6992   else if (shCount >= 8)
6993     {
6994       shCount -= 8;
6995       if (shCount == 1)
6996         shiftRLong (left, MSB16, result, sign);
6997       else if (shCount == 0)
6998         {
6999           movLeft2Result (left, MSB16, result, LSB, 0);
7000           movLeft2Result (left, MSB24, result, MSB16, 0);
7001           movLeft2Result (left, MSB32, result, MSB24, sign);
7002           addSign (result, MSB32, sign);
7003         }
7004       else
7005         {
7006           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7007           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7008           /* the last shift is signed */
7009           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7010           addSign (result, MSB32, sign);
7011         }
7012     }
7013   else
7014     {                           /* 1 <= shCount <= 7 */
7015       if (shCount <= 2)
7016         {
7017           shiftRLong (left, LSB, result, sign);
7018           if (shCount == 2)
7019             shiftRLong (result, LSB, result, sign);
7020         }
7021       else
7022         {
7023           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7024           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7025           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7026         }
7027     }
7028 }
7029 #endif
7030
7031 #if 0
7032 //REMOVE ME!!!
7033 /*-----------------------------------------------------------------*/
7034 /* genRightShiftLiteral - right shifting by known count            */
7035 /*-----------------------------------------------------------------*/
7036 static void
7037 genRightShiftLiteral (operand * left,
7038                       operand * right,
7039                       operand * result,
7040                       iCode * ic,
7041                       int sign)
7042 {
7043   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7044   int size;
7045
7046   D (emitcode (";", "genRightShiftLiteral");
7047     );
7048
7049   freeAsmop (right, NULL, ic, TRUE);
7050
7051   aopOp (left, ic, FALSE, FALSE);
7052   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7053
7054 #if VIEW_SIZE
7055   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7056             AOP_SIZE (left));
7057 #endif
7058
7059   size = getDataSize (left);
7060   /* test the LEFT size !!! */
7061
7062   /* I suppose that the left size >= result size */
7063   if (shCount == 0)
7064     {
7065       size = getDataSize (result);
7066       while (size--)
7067         movLeft2Result (left, size, result, size, 0);
7068     }
7069
7070   else if (shCount >= (size * 8))
7071     {
7072       if (sign)
7073         /* get sign in acc.7 */
7074         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7075       addSign (result, LSB, sign);
7076     }
7077   else
7078     {
7079       switch (size)
7080         {
7081         case 1:
7082           genrshOne (result, left, shCount, sign);
7083           break;
7084
7085         case 2:
7086           genrshTwo (result, left, shCount, sign);
7087           break;
7088
7089         case 4:
7090           genrshFour (result, left, shCount, sign);
7091           break;
7092         default:
7093           break;
7094         }
7095
7096       freeAsmop (left, NULL, ic, TRUE);
7097       freeAsmop (result, NULL, ic, TRUE);
7098     }
7099 }
7100 #endif
7101
7102 /*-----------------------------------------------------------------*/
7103 /* genSignedRightShift - right shift of signed number              */
7104 /*-----------------------------------------------------------------*/
7105 static void
7106 genSignedRightShift (iCode * ic)
7107 {
7108   operand *right, *left, *result;
7109   int size, offset;
7110   char *l;
7111   symbol *tlbl, *tlbl1;
7112
7113   D (emitcode (";", "genSignedRightShift ");
7114     );
7115
7116   /* we do it the hard way put the shift count in b
7117      and loop thru preserving the sign */
7118
7119   right = IC_RIGHT (ic);
7120   left = IC_LEFT (ic);
7121   result = IC_RESULT (ic);
7122
7123   aopOp (right, ic, FALSE, FALSE);
7124
7125 #if 0
7126   if (AOP_TYPE (right) == AOP_LIT)
7127     {
7128       genRightShiftLiteral (left, right, result, ic, 1);
7129       return;
7130     }
7131 #endif
7132   /* shift count is unknown then we have to form
7133      a loop get the loop count in B : Note: we take
7134      only the lower order byte since shifting
7135      more that 32 bits make no sense anyway, ( the
7136      largest size of an object can be only 32 bits ) */
7137
7138   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7139   emitcode ("inc", "b");
7140   freeAsmop (right, NULL, ic, TRUE);
7141   aopOp (left, ic, FALSE, FALSE);
7142   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7143
7144   /* now move the left to the result if they are not the
7145      same */
7146   if (!sameRegs (AOP (left), AOP (result)) &&
7147       AOP_SIZE (result) > 1)
7148     {
7149
7150       size = AOP_SIZE (result);
7151       offset = 0;
7152       _startLazyDPSEvaluation ();
7153       while (size--)
7154         {
7155           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7156           if (*l == '@' && IS_AOP_PREG (result))
7157             {
7158
7159               emitcode ("mov", "a,%s", l);
7160               aopPut (AOP (result), "a", offset);
7161             }
7162           else
7163             aopPut (AOP (result), l, offset);
7164           offset++;
7165         }
7166       _endLazyDPSEvaluation ();
7167     }
7168
7169   /* mov the highest order bit to OVR */
7170   tlbl = newiTempLabel (NULL);
7171   tlbl1 = newiTempLabel (NULL);
7172
7173   size = AOP_SIZE (result);
7174   offset = size - 1;
7175   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7176   emitcode ("rlc", "a");
7177   emitcode ("mov", "ov,c");
7178   /* if it is only one byte then */
7179   if (size == 1)
7180     {
7181       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7182       MOVA (l);
7183       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7184       emitcode ("", "%05d$:", tlbl->key + 100);
7185       emitcode ("mov", "c,ov");
7186       emitcode ("rrc", "a");
7187       emitcode ("", "%05d$:", tlbl1->key + 100);
7188       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7189       aopPut (AOP (result), "a", 0);
7190       goto release;
7191     }
7192
7193   reAdjustPreg (AOP (result));
7194   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7195   emitcode ("", "%05d$:", tlbl->key + 100);
7196   emitcode ("mov", "c,ov");
7197   _startLazyDPSEvaluation ();
7198   while (size--)
7199     {
7200       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7201       MOVA (l);
7202       emitcode ("rrc", "a");
7203       aopPut (AOP (result), "a", offset--);
7204     }
7205   _endLazyDPSEvaluation ();
7206   reAdjustPreg (AOP (result));
7207   emitcode ("", "%05d$:", tlbl1->key + 100);
7208   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7209
7210 release:
7211   freeAsmop (left, NULL, ic, TRUE);
7212   freeAsmop (result, NULL, ic, TRUE);
7213 }
7214
7215 /*-----------------------------------------------------------------*/
7216 /* genRightShift - generate code for right shifting                */
7217 /*-----------------------------------------------------------------*/
7218 static void
7219 genRightShift (iCode * ic)
7220 {
7221   operand *right, *left, *result;
7222   sym_link *retype;
7223   int size, offset;
7224   char *l;
7225   symbol *tlbl, *tlbl1;
7226
7227   D (emitcode (";", "genRightShift ");
7228     );
7229
7230   /* if signed then we do it the hard way preserve the
7231      sign bit moving it inwards */
7232   retype = getSpec (operandType (IC_RESULT (ic)));
7233
7234   if (!SPEC_USIGN (retype))
7235     {
7236       genSignedRightShift (ic);
7237       return;
7238     }
7239
7240   /* signed & unsigned types are treated the same : i.e. the
7241      signed is NOT propagated inwards : quoting from the
7242      ANSI - standard : "for E1 >> E2, is equivalent to division
7243      by 2**E2 if unsigned or if it has a non-negative value,
7244      otherwise the result is implementation defined ", MY definition
7245      is that the sign does not get propagated */
7246
7247   right = IC_RIGHT (ic);
7248   left = IC_LEFT (ic);
7249   result = IC_RESULT (ic);
7250
7251   aopOp (right, ic, FALSE, FALSE);
7252
7253 #if 0
7254   /* if the shift count is known then do it
7255      as efficiently as possible */
7256   if (AOP_TYPE (right) == AOP_LIT)
7257     {
7258       genRightShiftLiteral (left, right, result, ic, 0);
7259       return;
7260     }
7261 #endif
7262
7263   /* shift count is unknown then we have to form
7264      a loop get the loop count in B : Note: we take
7265      only the lower order byte since shifting
7266      more that 32 bits make no sense anyway, ( the
7267      largest size of an object can be only 32 bits ) */
7268
7269   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7270   emitcode ("inc", "b");
7271   freeAsmop (right, NULL, ic, TRUE);
7272   aopOp (left, ic, FALSE, FALSE);
7273   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7274
7275   /* now move the left to the result if they are not the
7276      same */
7277   if (!sameRegs (AOP (left), AOP (result)) &&
7278       AOP_SIZE (result) > 1)
7279     {
7280
7281       size = AOP_SIZE (result);
7282       offset = 0;
7283       _startLazyDPSEvaluation ();
7284       while (size--)
7285         {
7286           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7287           if (*l == '@' && IS_AOP_PREG (result))
7288             {
7289
7290               emitcode ("mov", "a,%s", l);
7291               aopPut (AOP (result), "a", offset);
7292             }
7293           else
7294             aopPut (AOP (result), l, offset);
7295           offset++;
7296         }
7297       _endLazyDPSEvaluation ();
7298     }
7299
7300   tlbl = newiTempLabel (NULL);
7301   tlbl1 = newiTempLabel (NULL);
7302   size = AOP_SIZE (result);
7303   offset = size - 1;
7304
7305   /* if it is only one byte then */
7306   if (size == 1)
7307     {
7308       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7309       MOVA (l);
7310       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7311       emitcode ("", "%05d$:", tlbl->key + 100);
7312       CLRC;
7313       emitcode ("rrc", "a");
7314       emitcode ("", "%05d$:", tlbl1->key + 100);
7315       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7316       aopPut (AOP (result), "a", 0);
7317       goto release;
7318     }
7319
7320   reAdjustPreg (AOP (result));
7321   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7322   emitcode ("", "%05d$:", tlbl->key + 100);
7323   CLRC;
7324   _startLazyDPSEvaluation ();
7325   while (size--)
7326     {
7327       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7328       MOVA (l);
7329       emitcode ("rrc", "a");
7330       aopPut (AOP (result), "a", offset--);
7331     }
7332   _endLazyDPSEvaluation ();
7333   reAdjustPreg (AOP (result));
7334
7335   emitcode ("", "%05d$:", tlbl1->key + 100);
7336   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7337
7338 release:
7339   freeAsmop (left, NULL, ic, TRUE);
7340   freeAsmop (result, NULL, ic, TRUE);
7341 }
7342
7343 /*-----------------------------------------------------------------*/
7344 /* genUnpackBits - generates code for unpacking bits               */
7345 /*-----------------------------------------------------------------*/
7346 static void
7347 genUnpackBits (operand * result, char *rname, int ptype)
7348 {
7349   int shCnt;
7350   int rlen = 0;
7351   sym_link *etype;
7352   int offset = 0;
7353
7354   D (emitcode (";", "genUnpackBits ");
7355     );
7356
7357   etype = getSpec (operandType (result));
7358
7359   /* read the first byte  */
7360   switch (ptype)
7361     {
7362
7363     case POINTER:
7364     case IPOINTER:
7365       emitcode ("mov", "a,@%s", rname);
7366       break;
7367
7368     case PPOINTER:
7369       emitcode ("movx", "a,@%s", rname);
7370       break;
7371
7372     case FPOINTER:
7373       emitcode ("movx", "a,@dptr");
7374       break;
7375
7376     case CPOINTER:
7377       emitcode ("clr", "a");
7378       emitcode ("movc", "a", "@a+dptr");
7379       break;
7380
7381     case GPOINTER:
7382       emitcode ("lcall", "__gptrget");
7383       break;
7384     }
7385
7386   /* if we have bitdisplacement then it fits   */
7387   /* into this byte completely or if length is */
7388   /* less than a byte                          */
7389   if ((shCnt = SPEC_BSTR (etype)) ||
7390       (SPEC_BLEN (etype) <= 8))
7391     {
7392
7393       /* shift right acc */
7394       AccRsh (shCnt);
7395
7396       emitcode ("anl", "a,#0x%02x",
7397                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7398       aopPut (AOP (result), "a", offset);
7399       return;
7400     }
7401
7402   /* bit field did not fit in a byte  */
7403   rlen = SPEC_BLEN (etype) - 8;
7404   aopPut (AOP (result), "a", offset++);
7405
7406   while (1)
7407     {
7408
7409       switch (ptype)
7410         {
7411         case POINTER:
7412         case IPOINTER:
7413           emitcode ("inc", "%s", rname);
7414           emitcode ("mov", "a,@%s", rname);
7415           break;
7416
7417         case PPOINTER:
7418           emitcode ("inc", "%s", rname);
7419           emitcode ("movx", "a,@%s", rname);
7420           break;
7421
7422         case FPOINTER:
7423           emitcode ("inc", "dptr");
7424           emitcode ("movx", "a,@dptr");
7425           break;
7426
7427         case CPOINTER:
7428           emitcode ("clr", "a");
7429           emitcode ("inc", "dptr");
7430           emitcode ("movc", "a", "@a+dptr");
7431           break;
7432
7433         case GPOINTER:
7434           emitcode ("inc", "dptr");
7435           emitcode ("lcall", "__gptrget");
7436           break;
7437         }
7438
7439       rlen -= 8;
7440       /* if we are done */
7441       if (rlen < 8)
7442         break;
7443
7444       aopPut (AOP (result), "a", offset++);
7445
7446     }
7447
7448   if (rlen)
7449     {
7450       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7451       aopPut (AOP (result), "a", offset);
7452     }
7453
7454   return;
7455 }
7456
7457
7458 /*-----------------------------------------------------------------*/
7459 /* genDataPointerGet - generates code when ptr offset is known     */
7460 /*-----------------------------------------------------------------*/
7461 static void
7462 genDataPointerGet (operand * left,
7463                    operand * result,
7464                    iCode * ic)
7465 {
7466   char *l;
7467   char buffer[256];
7468   int size, offset = 0;
7469   aopOp (result, ic, TRUE, FALSE);
7470
7471   /* get the string representation of the name */
7472   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7473   size = AOP_SIZE (result);
7474   _startLazyDPSEvaluation ();
7475   while (size--)
7476     {
7477       if (offset)
7478         sprintf (buffer, "(%s + %d)", l + 1, offset);
7479       else
7480         sprintf (buffer, "%s", l + 1);
7481       aopPut (AOP (result), buffer, offset++);
7482     }
7483   _endLazyDPSEvaluation ();
7484
7485   freeAsmop (left, NULL, ic, TRUE);
7486   freeAsmop (result, NULL, ic, TRUE);
7487 }
7488
7489 /*-----------------------------------------------------------------*/
7490 /* genNearPointerGet - emitcode for near pointer fetch             */
7491 /*-----------------------------------------------------------------*/
7492 static void
7493 genNearPointerGet (operand * left,
7494                    operand * result,
7495                    iCode * ic)
7496 {
7497   asmop *aop = NULL;
7498   regs *preg = NULL;
7499   char *rname;
7500   sym_link *rtype, *retype, *letype;
7501   sym_link *ltype = operandType (left);
7502   char buffer[80];
7503
7504   rtype = operandType (result);
7505   retype = getSpec (rtype);
7506   letype = getSpec (ltype);
7507
7508   aopOp (left, ic, FALSE, FALSE);
7509
7510   /* if left is rematerialisable and
7511      result is not bit variable type and
7512      the left is pointer to data space i.e
7513      lower 128 bytes of space */
7514   if (AOP_TYPE (left) == AOP_IMMD &&
7515       !IS_BITVAR (retype) &&
7516       !IS_BITVAR (letype) &&
7517       DCL_TYPE (ltype) == POINTER)
7518     {
7519       genDataPointerGet (left, result, ic);
7520       return;
7521     }
7522
7523   /* if the value is already in a pointer register
7524      then don't need anything more */
7525   if (!AOP_INPREG (AOP (left)))
7526     {
7527       /* otherwise get a free pointer register */
7528       aop = newAsmop (0);
7529       preg = getFreePtr (ic, &aop, FALSE);
7530       emitcode ("mov", "%s,%s",
7531                 preg->name,
7532                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7533       rname = preg->name;
7534     }
7535   else
7536     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7537
7538   freeAsmop (left, NULL, ic, TRUE);
7539   aopOp (result, ic, FALSE, FALSE);
7540
7541   /* if bitfield then unpack the bits */
7542   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7543     genUnpackBits (result, rname, POINTER);
7544   else
7545     {
7546       /* we have can just get the values */
7547       int size = AOP_SIZE (result);
7548       int offset = 0;
7549
7550       while (size--)
7551         {
7552           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7553             {
7554
7555               emitcode ("mov", "a,@%s", rname);
7556               aopPut (AOP (result), "a", offset);
7557             }
7558           else
7559             {
7560               sprintf (buffer, "@%s", rname);
7561               aopPut (AOP (result), buffer, offset);
7562             }
7563           offset++;
7564           if (size)
7565             emitcode ("inc", "%s", rname);
7566         }
7567     }
7568
7569   /* now some housekeeping stuff */
7570   if (aop)
7571     {
7572       /* we had to allocate for this iCode */
7573       freeAsmop (NULL, aop, ic, TRUE);
7574     }
7575   else
7576     {
7577       /* we did not allocate which means left
7578          already in a pointer register, then
7579          if size > 0 && this could be used again
7580          we have to point it back to where it
7581          belongs */
7582       if (AOP_SIZE (result) > 1 &&
7583           !OP_SYMBOL (left)->remat &&
7584           (OP_SYMBOL (left)->liveTo > ic->seq ||
7585            ic->depth))
7586         {
7587           int size = AOP_SIZE (result) - 1;
7588           while (size--)
7589             emitcode ("dec", "%s", rname);
7590         }
7591     }
7592
7593   /* done */
7594   freeAsmop (result, NULL, ic, TRUE);
7595
7596 }
7597
7598 /*-----------------------------------------------------------------*/
7599 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7600 /*-----------------------------------------------------------------*/
7601 static void
7602 genPagedPointerGet (operand * left,
7603                     operand * result,
7604                     iCode * ic)
7605 {
7606   asmop *aop = NULL;
7607   regs *preg = NULL;
7608   char *rname;
7609   sym_link *rtype, *retype, *letype;
7610
7611   rtype = operandType (result);
7612   retype = getSpec (rtype);
7613   letype = getSpec (operandType (left));
7614   aopOp (left, ic, FALSE, FALSE);
7615
7616   /* if the value is already in a pointer register
7617      then don't need anything more */
7618   if (!AOP_INPREG (AOP (left)))
7619     {
7620       /* otherwise get a free pointer register */
7621       aop = newAsmop (0);
7622       preg = getFreePtr (ic, &aop, FALSE);
7623       emitcode ("mov", "%s,%s",
7624                 preg->name,
7625                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7626       rname = preg->name;
7627     }
7628   else
7629     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7630
7631   freeAsmop (left, NULL, ic, TRUE);
7632   aopOp (result, ic, FALSE, FALSE);
7633
7634   /* if bitfield then unpack the bits */
7635   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7636     genUnpackBits (result, rname, PPOINTER);
7637   else
7638     {
7639       /* we have can just get the values */
7640       int size = AOP_SIZE (result);
7641       int offset = 0;
7642
7643       while (size--)
7644         {
7645
7646           emitcode ("movx", "a,@%s", rname);
7647           aopPut (AOP (result), "a", offset);
7648
7649           offset++;
7650
7651           if (size)
7652             emitcode ("inc", "%s", rname);
7653         }
7654     }
7655
7656   /* now some housekeeping stuff */
7657   if (aop)
7658     {
7659       /* we had to allocate for this iCode */
7660       freeAsmop (NULL, aop, ic, TRUE);
7661     }
7662   else
7663     {
7664       /* we did not allocate which means left
7665          already in a pointer register, then
7666          if size > 0 && this could be used again
7667          we have to point it back to where it
7668          belongs */
7669       if (AOP_SIZE (result) > 1 &&
7670           !OP_SYMBOL (left)->remat &&
7671           (OP_SYMBOL (left)->liveTo > ic->seq ||
7672            ic->depth))
7673         {
7674           int size = AOP_SIZE (result) - 1;
7675           while (size--)
7676             emitcode ("dec", "%s", rname);
7677         }
7678     }
7679
7680   /* done */
7681   freeAsmop (result, NULL, ic, TRUE);
7682
7683
7684 }
7685
7686 /*-----------------------------------------------------------------*/
7687 /* genFarPointerGet - gget value from far space                    */
7688 /*-----------------------------------------------------------------*/
7689 static void
7690 genFarPointerGet (operand * left,
7691                   operand * result, iCode * ic)
7692 {
7693   int size, offset;
7694   sym_link *retype = getSpec (operandType (result));
7695   sym_link *letype = getSpec (operandType (left));
7696   D (emitcode (";", "genFarPointerGet");
7697     );
7698
7699   aopOp (left, ic, FALSE, FALSE);
7700
7701   /* if the operand is already in dptr
7702      then we do nothing else we move the value to dptr */
7703   if (AOP_TYPE (left) != AOP_STR)
7704     {
7705       /* if this is remateriazable */
7706       if (AOP_TYPE (left) == AOP_IMMD)
7707         {
7708           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7709         }
7710       else
7711         {
7712           /* we need to get it byte by byte */
7713           _startLazyDPSEvaluation ();
7714           if (AOP_TYPE (left) != AOP_DPTR)
7715             {
7716               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7717               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7718               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7719             }
7720           else
7721             {
7722               /* We need to generate a load to DPTR indirect through DPTR. */
7723               D (emitcode (";", "genFarPointerGet -- indirection special case.");
7724                 );
7725               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7726               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7727               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7728               emitcode ("pop", "dph");
7729               emitcode ("pop", "dpl");
7730             }
7731           _endLazyDPSEvaluation ();
7732         }
7733     }
7734   /* so dptr know contains the address */
7735   freeAsmop (left, NULL, ic, TRUE);
7736   aopOp (result, ic, FALSE, TRUE);
7737
7738   /* if bit then unpack */
7739   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7740     genUnpackBits (result, "dptr", FPOINTER);
7741   else
7742     {
7743       size = AOP_SIZE (result);
7744       offset = 0;
7745
7746       _startLazyDPSEvaluation ();
7747       while (size--)
7748         {
7749
7750           genSetDPTR (0);
7751           _flushLazyDPS ();
7752
7753           emitcode ("movx", "a,@dptr");
7754           if (size)
7755             emitcode ("inc", "dptr");
7756
7757           aopPut (AOP (result), "a", offset++);
7758         }
7759       _endLazyDPSEvaluation ();
7760     }
7761
7762   freeAsmop (result, NULL, ic, TRUE);
7763 }
7764
7765 /*-----------------------------------------------------------------*/
7766 /* emitcodePointerGet - gget value from code space                  */
7767 /*-----------------------------------------------------------------*/
7768 static void
7769 emitcodePointerGet (operand * left,
7770                     operand * result, iCode * ic)
7771 {
7772   int size, offset;
7773   sym_link *retype = getSpec (operandType (result));
7774
7775   aopOp (left, ic, FALSE, FALSE);
7776
7777   /* if the operand is already in dptr
7778      then we do nothing else we move the value to dptr */
7779   if (AOP_TYPE (left) != AOP_STR)
7780     {
7781       /* if this is remateriazable */
7782       if (AOP_TYPE (left) == AOP_IMMD)
7783         {
7784           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7785         }
7786       else
7787         {                       /* we need to get it byte by byte */
7788           _startLazyDPSEvaluation ();
7789           if (AOP_TYPE (left) != AOP_DPTR)
7790             {
7791               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7792               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7793               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7794             }
7795           else
7796             {
7797               /* We need to generate a load to DPTR indirect through DPTR. */
7798               D (emitcode (";", "gencodePointerGet -- indirection special case.");
7799                 );
7800               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7801               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7802               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7803               emitcode ("pop", "dph");
7804               emitcode ("pop", "dpl");
7805             }
7806           _endLazyDPSEvaluation ();
7807         }
7808     }
7809   /* so dptr know contains the address */
7810   freeAsmop (left, NULL, ic, TRUE);
7811   aopOp (result, ic, FALSE, TRUE);
7812
7813   /* if bit then unpack */
7814   if (IS_BITVAR (retype))
7815     genUnpackBits (result, "dptr", CPOINTER);
7816   else
7817     {
7818       size = AOP_SIZE (result);
7819       offset = 0;
7820
7821       _startLazyDPSEvaluation ();
7822       while (size--)
7823         {
7824           genSetDPTR (0);
7825           _flushLazyDPS ();
7826
7827           emitcode ("clr", "a");
7828           emitcode ("movc", "a,@a+dptr");
7829           if (size)
7830             emitcode ("inc", "dptr");
7831           aopPut (AOP (result), "a", offset++);
7832         }
7833       _endLazyDPSEvaluation ();
7834     }
7835
7836   freeAsmop (result, NULL, ic, TRUE);
7837 }
7838
7839 /*-----------------------------------------------------------------*/
7840 /* genGenPointerGet - gget value from generic pointer space        */
7841 /*-----------------------------------------------------------------*/
7842 static void
7843 genGenPointerGet (operand * left,
7844                   operand * result, iCode * ic)
7845 {
7846   int size, offset;
7847   sym_link *retype = getSpec (operandType (result));
7848   sym_link *letype = getSpec (operandType (left));
7849
7850   D (emitcode (";", "genGenPointerGet "); );
7851
7852   aopOp (left, ic, FALSE, TRUE);
7853
7854   /* if the operand is already in dptr
7855      then we do nothing else we move the value to dptr */
7856   if (AOP_TYPE (left) != AOP_STR)
7857     {
7858       /* if this is remateriazable */
7859       if (AOP_TYPE (left) == AOP_IMMD)
7860         {
7861           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7862           emitcode ("mov", "b,#%d", pointerCode (retype));
7863         }
7864       else
7865         {                       /* we need to get it byte by byte */
7866           _startLazyDPSEvaluation ();
7867           if (AOP(left)->type==AOP_DPTR2) {
7868             char *l;
7869             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7870             genSetDPTR(0);
7871             _flushLazyDPS();
7872             emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7873             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7874             genSetDPTR(0);
7875             _flushLazyDPS();
7876             emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7877             l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7878             genSetDPTR(0);
7879             _flushLazyDPS();
7880             emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7881             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7882           } else {
7883             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7884             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7885             emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7886             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7887           }
7888           _endLazyDPSEvaluation ();
7889         }
7890     }
7891   /* so dptr know contains the address */
7892   freeAsmop (left, NULL, ic, TRUE);
7893   aopOp (result, ic, FALSE, TRUE);
7894
7895   /* if bit then unpack */
7896   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7897     genUnpackBits (result, "dptr", GPOINTER);
7898   else
7899     {
7900       size = AOP_SIZE (result);
7901       offset = 0;
7902
7903       while (size--)
7904         {
7905           emitcode ("lcall", "__gptrget");
7906           aopPut (AOP (result), "a", offset++);
7907           if (size)
7908             emitcode ("inc", "dptr");
7909         }
7910     }
7911
7912   freeAsmop (result, NULL, ic, TRUE);
7913 }
7914
7915 /*-----------------------------------------------------------------*/
7916 /* genPointerGet - generate code for pointer get                   */
7917 /*-----------------------------------------------------------------*/
7918 static void
7919 genPointerGet (iCode * ic)
7920 {
7921   operand *left, *result;
7922   sym_link *type, *etype;
7923   int p_type;
7924
7925   D (emitcode (";", "genPointerGet ");
7926     );
7927
7928   left = IC_LEFT (ic);
7929   result = IC_RESULT (ic);
7930
7931   /* depending on the type of pointer we need to
7932      move it to the correct pointer register */
7933   type = operandType (left);
7934   etype = getSpec (type);
7935   /* if left is of type of pointer then it is simple */
7936   if (IS_PTR (type) && !IS_FUNC (type->next))
7937     p_type = DCL_TYPE (type);
7938   else
7939     {
7940       /* we have to go by the storage class */
7941       p_type = PTR_TYPE (SPEC_OCLS (etype));
7942     }
7943
7944   /* now that we have the pointer type we assign
7945      the pointer values */
7946   switch (p_type)
7947     {
7948
7949     case POINTER:
7950     case IPOINTER:
7951       genNearPointerGet (left, result, ic);
7952       break;
7953
7954     case PPOINTER:
7955       genPagedPointerGet (left, result, ic);
7956       break;
7957
7958     case FPOINTER:
7959       genFarPointerGet (left, result, ic);
7960       break;
7961
7962     case CPOINTER:
7963       emitcodePointerGet (left, result, ic);
7964       break;
7965
7966     case GPOINTER:
7967       genGenPointerGet (left, result, ic);
7968       break;
7969     }
7970
7971 }
7972
7973 /*-----------------------------------------------------------------*/
7974 /* genPackBits - generates code for packed bit storage             */
7975 /*-----------------------------------------------------------------*/
7976 static void
7977 genPackBits (sym_link * etype,
7978              operand * right,
7979              char *rname, int p_type)
7980 {
7981   int shCount = 0;
7982   int offset = 0;
7983   int rLen = 0;
7984   int blen, bstr;
7985   char *l;
7986
7987   blen = SPEC_BLEN (etype);
7988   bstr = SPEC_BSTR (etype);
7989
7990   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
7991   MOVA (l);
7992
7993   /* if the bit lenth is less than or    */
7994   /* it exactly fits a byte then         */
7995   if (SPEC_BLEN (etype) <= 8)
7996     {
7997       shCount = SPEC_BSTR (etype);
7998
7999       /* shift left acc */
8000       AccLsh (shCount);
8001
8002       if (SPEC_BLEN (etype) < 8)
8003         {                       /* if smaller than a byte */
8004
8005
8006           switch (p_type)
8007             {
8008             case POINTER:
8009               emitcode ("mov", "b,a");
8010               emitcode ("mov", "a,@%s", rname);
8011               break;
8012
8013             case FPOINTER:
8014               emitcode ("mov", "b,a");
8015               emitcode ("movx", "a,@dptr");
8016               break;
8017
8018             case GPOINTER:
8019               emitcode ("push", "b");
8020               emitcode ("push", "acc");
8021               emitcode ("lcall", "__gptrget");
8022               emitcode ("pop", "b");
8023               break;
8024             }
8025
8026           emitcode ("anl", "a,#0x%02x", (unsigned char)
8027                     ((unsigned char) (0xFF << (blen + bstr)) |
8028                      (unsigned char) (0xFF >> (8 - bstr))));
8029           emitcode ("orl", "a,b");
8030           if (p_type == GPOINTER)
8031             emitcode ("pop", "b");
8032         }
8033     }
8034
8035   switch (p_type)
8036     {
8037     case POINTER:
8038       emitcode ("mov", "@%s,a", rname);
8039       break;
8040
8041     case FPOINTER:
8042       emitcode ("movx", "@dptr,a");
8043       break;
8044
8045     case GPOINTER:
8046       emitcode ("lcall", "__gptrput");
8047       break;
8048     }
8049
8050   /* if we r done */
8051   if (SPEC_BLEN (etype) <= 8)
8052     return;
8053
8054   emitcode ("inc", "%s", rname);
8055   rLen = SPEC_BLEN (etype);
8056
8057   /* now generate for lengths greater than one byte */
8058   while (1)
8059     {
8060
8061       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8062
8063       rLen -= 8;
8064       if (rLen < 8)
8065         break;
8066
8067       switch (p_type)
8068         {
8069         case POINTER:
8070           if (*l == '@')
8071             {
8072               MOVA (l);
8073               emitcode ("mov", "@%s,a", rname);
8074             }
8075           else
8076             emitcode ("mov", "@%s,%s", rname, l);
8077           break;
8078
8079         case FPOINTER:
8080           MOVA (l);
8081           emitcode ("movx", "@dptr,a");
8082           break;
8083
8084         case GPOINTER:
8085           MOVA (l);
8086           emitcode ("lcall", "__gptrput");
8087           break;
8088         }
8089       emitcode ("inc", "%s", rname);
8090     }
8091
8092   MOVA (l);
8093
8094   /* last last was not complete */
8095   if (rLen)
8096     {
8097       /* save the byte & read byte */
8098       switch (p_type)
8099         {
8100         case POINTER:
8101           emitcode ("mov", "b,a");
8102           emitcode ("mov", "a,@%s", rname);
8103           break;
8104
8105         case FPOINTER:
8106           emitcode ("mov", "b,a");
8107           emitcode ("movx", "a,@dptr");
8108           break;
8109
8110         case GPOINTER:
8111           emitcode ("push", "b");
8112           emitcode ("push", "acc");
8113           emitcode ("lcall", "__gptrget");
8114           emitcode ("pop", "b");
8115           break;
8116         }
8117
8118       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8119       emitcode ("orl", "a,b");
8120     }
8121
8122   if (p_type == GPOINTER)
8123     emitcode ("pop", "b");
8124
8125   switch (p_type)
8126     {
8127
8128     case POINTER:
8129       emitcode ("mov", "@%s,a", rname);
8130       break;
8131
8132     case FPOINTER:
8133       emitcode ("movx", "@dptr,a");
8134       break;
8135
8136     case GPOINTER:
8137       emitcode ("lcall", "__gptrput");
8138       break;
8139     }
8140 }
8141 /*-----------------------------------------------------------------*/
8142 /* genDataPointerSet - remat pointer to data space                 */
8143 /*-----------------------------------------------------------------*/
8144 static void
8145 genDataPointerSet (operand * right,
8146                    operand * result,
8147                    iCode * ic)
8148 {
8149   int size, offset = 0;
8150   char *l, buffer[256];
8151
8152   aopOp (right, ic, FALSE, FALSE);
8153
8154   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8155   size = AOP_SIZE (right);
8156   while (size--)
8157     {
8158       if (offset)
8159         sprintf (buffer, "(%s + %d)", l + 1, offset);
8160       else
8161         sprintf (buffer, "%s", l + 1);
8162       emitcode ("mov", "%s,%s", buffer,
8163                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8164     }
8165
8166   freeAsmop (right, NULL, ic, TRUE);
8167   freeAsmop (result, NULL, ic, TRUE);
8168 }
8169
8170 /*-----------------------------------------------------------------*/
8171 /* genNearPointerSet - emitcode for near pointer put                */
8172 /*-----------------------------------------------------------------*/
8173 static void
8174 genNearPointerSet (operand * right,
8175                    operand * result,
8176                    iCode * ic)
8177 {
8178   asmop *aop = NULL;
8179   regs *preg = NULL;
8180   char *rname, *l;
8181   sym_link *retype, *letype;
8182   sym_link *ptype = operandType (result);
8183
8184   retype = getSpec (operandType (right));
8185   letype = getSpec (ptype);
8186
8187   aopOp (result, ic, FALSE, FALSE);
8188
8189   /* if the result is rematerializable &
8190      in data space & not a bit variable */
8191   if (AOP_TYPE (result) == AOP_IMMD &&
8192       DCL_TYPE (ptype) == POINTER &&
8193       !IS_BITVAR (retype) &&
8194       !IS_BITVAR (letype))
8195     {
8196       genDataPointerSet (right, result, ic);
8197       return;
8198     }
8199
8200   /* if the value is already in a pointer register
8201      then don't need anything more */
8202   if (!AOP_INPREG (AOP (result)))
8203     {
8204       /* otherwise get a free pointer register */
8205       aop = newAsmop (0);
8206       preg = getFreePtr (ic, &aop, FALSE);
8207       emitcode ("mov", "%s,%s",
8208                 preg->name,
8209                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8210       rname = preg->name;
8211     }
8212   else
8213     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8214
8215   freeAsmop (result, NULL, ic, TRUE);
8216   aopOp (right, ic, FALSE, FALSE);
8217
8218   /* if bitfield then unpack the bits */
8219   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8220     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8221   else
8222     {
8223       /* we have can just get the values */
8224       int size = AOP_SIZE (right);
8225       int offset = 0;
8226
8227       while (size--)
8228         {
8229           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8230           if (*l == '@')
8231             {
8232               MOVA (l);
8233               emitcode ("mov", "@%s,a", rname);
8234             }
8235           else
8236             emitcode ("mov", "@%s,%s", rname, l);
8237           if (size)
8238             emitcode ("inc", "%s", rname);
8239           offset++;
8240         }
8241     }
8242
8243   /* now some housekeeping stuff */
8244   if (aop)
8245     {
8246       /* we had to allocate for this iCode */
8247       freeAsmop (NULL, aop, ic, TRUE);
8248     }
8249   else
8250     {
8251       /* we did not allocate which means left
8252          already in a pointer register, then
8253          if size > 0 && this could be used again
8254          we have to point it back to where it
8255          belongs */
8256       if (AOP_SIZE (right) > 1 &&
8257           !OP_SYMBOL (result)->remat &&
8258           (OP_SYMBOL (result)->liveTo > ic->seq ||
8259            ic->depth))
8260         {
8261           int size = AOP_SIZE (right) - 1;
8262           while (size--)
8263             emitcode ("dec", "%s", rname);
8264         }
8265     }
8266
8267   /* done */
8268   freeAsmop (right, NULL, ic, TRUE);
8269
8270
8271 }
8272
8273 /*-----------------------------------------------------------------*/
8274 /* genPagedPointerSet - emitcode for Paged pointer put             */
8275 /*-----------------------------------------------------------------*/
8276 static void
8277 genPagedPointerSet (operand * right,
8278                     operand * result,
8279                     iCode * ic)
8280 {
8281   asmop *aop = NULL;
8282   regs *preg = NULL;
8283   char *rname, *l;
8284   sym_link *retype, *letype;
8285
8286   retype = getSpec (operandType (right));
8287   letype = getSpec (operandType (result));
8288
8289   aopOp (result, ic, FALSE, FALSE);
8290
8291   /* if the value is already in a pointer register
8292      then don't need anything more */
8293   if (!AOP_INPREG (AOP (result)))
8294     {
8295       /* otherwise get a free pointer register */
8296       aop = newAsmop (0);
8297       preg = getFreePtr (ic, &aop, FALSE);
8298       emitcode ("mov", "%s,%s",
8299                 preg->name,
8300                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8301       rname = preg->name;
8302     }
8303   else
8304     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8305
8306   freeAsmop (result, NULL, ic, TRUE);
8307   aopOp (right, ic, FALSE, FALSE);
8308
8309   /* if bitfield then unpack the bits */
8310   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8311     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8312   else
8313     {
8314       /* we have can just get the values */
8315       int size = AOP_SIZE (right);
8316       int offset = 0;
8317
8318       while (size--)
8319         {
8320           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8321
8322           MOVA (l);
8323           emitcode ("movx", "@%s,a", rname);
8324
8325           if (size)
8326             emitcode ("inc", "%s", rname);
8327
8328           offset++;
8329         }
8330     }
8331
8332   /* now some housekeeping stuff */
8333   if (aop)
8334     {
8335       /* we had to allocate for this iCode */
8336       freeAsmop (NULL, aop, ic, TRUE);
8337     }
8338   else
8339     {
8340       /* we did not allocate which means left
8341          already in a pointer register, then
8342          if size > 0 && this could be used again
8343          we have to point it back to where it
8344          belongs */
8345       if (AOP_SIZE (right) > 1 &&
8346           !OP_SYMBOL (result)->remat &&
8347           (OP_SYMBOL (result)->liveTo > ic->seq ||
8348            ic->depth))
8349         {
8350           int size = AOP_SIZE (right) - 1;
8351           while (size--)
8352             emitcode ("dec", "%s", rname);
8353         }
8354     }
8355
8356   /* done */
8357   freeAsmop (right, NULL, ic, TRUE);
8358
8359
8360 }
8361
8362 /*-----------------------------------------------------------------*/
8363 /* genFarPointerSet - set value from far space                     */
8364 /*-----------------------------------------------------------------*/
8365 static void
8366 genFarPointerSet (operand * right,
8367                   operand * result, iCode * ic)
8368 {
8369   int size, offset;
8370   sym_link *retype = getSpec (operandType (right));
8371   sym_link *letype = getSpec (operandType (result));
8372
8373   aopOp (result, ic, FALSE, FALSE);
8374
8375   /* if the operand is already in dptr
8376      then we do nothing else we move the value to dptr */
8377   if (AOP_TYPE (result) != AOP_STR)
8378     {
8379       /* if this is remateriazable */
8380       if (AOP_TYPE (result) == AOP_IMMD)
8381         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8382       else
8383         {
8384           /* we need to get it byte by byte */
8385           _startLazyDPSEvaluation ();
8386           if (AOP_TYPE (result) != AOP_DPTR)
8387             {
8388               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8389               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8390               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8391             }
8392           else
8393             {
8394               /* We need to generate a load to DPTR indirect through DPTR. */
8395               D (emitcode (";", "genFarPointerSet -- indirection special case.");
8396                 );
8397               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8398               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8399               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8400               emitcode ("pop", "dph");
8401               emitcode ("pop", "dpl");
8402             }
8403           _endLazyDPSEvaluation ();
8404         }
8405     }
8406   /* so dptr know contains the address */
8407   freeAsmop (result, NULL, ic, TRUE);
8408   aopOp (right, ic, FALSE, TRUE);
8409
8410   /* if bit then unpack */
8411   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8412     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8413   else
8414     {
8415       size = AOP_SIZE (right);
8416       offset = 0;
8417
8418       _startLazyDPSEvaluation ();
8419       while (size--)
8420         {
8421           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8422           MOVA (l);
8423
8424           genSetDPTR (0);
8425           _flushLazyDPS ();
8426
8427           emitcode ("movx", "@dptr,a");
8428           if (size)
8429             emitcode ("inc", "dptr");
8430         }
8431       _endLazyDPSEvaluation ();
8432     }
8433
8434   freeAsmop (right, NULL, ic, TRUE);
8435 }
8436
8437 /*-----------------------------------------------------------------*/
8438 /* genGenPointerSet - set value from generic pointer space         */
8439 /*-----------------------------------------------------------------*/
8440 static void
8441 genGenPointerSet (operand * right,
8442                   operand * result, iCode * ic)
8443 {
8444   int size, offset;
8445   sym_link *retype = getSpec (operandType (right));
8446   sym_link *letype = getSpec (operandType (result));
8447
8448   aopOp (result, ic, FALSE, TRUE);
8449
8450   /* if the operand is already in dptr
8451      then we do nothing else we move the value to dptr */
8452   if (AOP_TYPE (result) != AOP_STR)
8453     {
8454       _startLazyDPSEvaluation ();
8455       /* if this is remateriazable */
8456       if (AOP_TYPE (result) == AOP_IMMD)
8457         {
8458           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8459           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8460         }
8461       else
8462         {                       /* we need to get it byte by byte */
8463           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8464           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8465           emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8466           emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8467         }
8468       _endLazyDPSEvaluation ();
8469     }
8470   /* so dptr know contains the address */
8471   freeAsmop (result, NULL, ic, TRUE);
8472   aopOp (right, ic, FALSE, TRUE);
8473
8474   /* if bit then unpack */
8475   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8476     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8477   else
8478     {
8479       size = AOP_SIZE (right);
8480       offset = 0;
8481
8482       _startLazyDPSEvaluation ();
8483       while (size--)
8484         {
8485           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8486           MOVA (l);
8487
8488           genSetDPTR (0);
8489           _flushLazyDPS ();
8490
8491           emitcode ("lcall", "__gptrput");
8492           if (size)
8493             emitcode ("inc", "dptr");
8494         }
8495       _endLazyDPSEvaluation ();
8496     }
8497
8498   freeAsmop (right, NULL, ic, TRUE);
8499 }
8500
8501 /*-----------------------------------------------------------------*/
8502 /* genPointerSet - stores the value into a pointer location        */
8503 /*-----------------------------------------------------------------*/
8504 static void
8505 genPointerSet (iCode * ic)
8506 {
8507   operand *right, *result;
8508   sym_link *type, *etype;
8509   int p_type;
8510
8511   D (emitcode (";", "genPointerSet ");
8512     );
8513
8514   right = IC_RIGHT (ic);
8515   result = IC_RESULT (ic);
8516
8517   /* depending on the type of pointer we need to
8518      move it to the correct pointer register */
8519   type = operandType (result);
8520   etype = getSpec (type);
8521   /* if left is of type of pointer then it is simple */
8522   if (IS_PTR (type) && !IS_FUNC (type->next))
8523     {
8524       p_type = DCL_TYPE (type);
8525     }
8526   else
8527     {
8528       /* we have to go by the storage class */
8529       p_type = PTR_TYPE (SPEC_OCLS (etype));
8530     }
8531
8532   /* now that we have the pointer type we assign
8533      the pointer values */
8534   switch (p_type)
8535     {
8536
8537     case POINTER:
8538     case IPOINTER:
8539       genNearPointerSet (right, result, ic);
8540       break;
8541
8542     case PPOINTER:
8543       genPagedPointerSet (right, result, ic);
8544       break;
8545
8546     case FPOINTER:
8547       genFarPointerSet (right, result, ic);
8548       break;
8549
8550     case GPOINTER:
8551       genGenPointerSet (right, result, ic);
8552       break;
8553     }
8554
8555 }
8556
8557 /*-----------------------------------------------------------------*/
8558 /* genIfx - generate code for Ifx statement                        */
8559 /*-----------------------------------------------------------------*/
8560 static void
8561 genIfx (iCode * ic, iCode * popIc)
8562 {
8563   operand *cond = IC_COND (ic);
8564   int isbit = 0;
8565
8566   D (emitcode (";", "genIfx ");
8567     );
8568
8569   aopOp (cond, ic, FALSE, FALSE);
8570
8571   /* get the value into acc */
8572   if (AOP_TYPE (cond) != AOP_CRY)
8573     toBoolean (cond);
8574   else
8575     isbit = 1;
8576   /* the result is now in the accumulator */
8577   freeAsmop (cond, NULL, ic, TRUE);
8578
8579   /* if there was something to be popped then do it */
8580   if (popIc)
8581     genIpop (popIc);
8582
8583   /* if the condition is  a bit variable */
8584   if (isbit && IS_ITEMP (cond) &&
8585       SPIL_LOC (cond))
8586     genIfxJump (ic, SPIL_LOC (cond)->rname);
8587   else if (isbit && !IS_ITEMP (cond))
8588     genIfxJump (ic, OP_SYMBOL (cond)->rname);
8589   else
8590     genIfxJump (ic, "a");
8591
8592   ic->generated = 1;
8593 }
8594
8595 /*-----------------------------------------------------------------*/
8596 /* genAddrOf - generates code for address of                       */
8597 /*-----------------------------------------------------------------*/
8598 static void
8599 genAddrOf (iCode * ic)
8600 {
8601   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8602   int size, offset;
8603
8604   D (emitcode (";", "genAddrOf ");
8605     );
8606
8607   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8608
8609   /* if the operand is on the stack then we
8610      need to get the stack offset of this
8611      variable */
8612   if (sym->onStack)
8613     {
8614       /* if it has an offset then we need to compute
8615          it */
8616       if (sym->stack)
8617         {
8618           emitcode ("mov", "a,_bp");
8619           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8620           aopPut (AOP (IC_RESULT (ic)), "a", 0);
8621         }
8622       else
8623         {
8624           /* we can just move _bp */
8625           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8626         }
8627       /* fill the result with zero */
8628       size = AOP_SIZE (IC_RESULT (ic)) - 1;
8629
8630
8631       if (options.stack10bit && size < (FPTRSIZE - 1))
8632         {
8633           fprintf (stderr,
8634                    "*** warning: pointer to stack var truncated.\n");
8635         }
8636
8637       offset = 1;
8638       while (size--)
8639         {
8640           /* Yuck! */
8641           if (options.stack10bit && offset == 2)
8642             {
8643               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8644             }
8645           else
8646             {
8647               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8648             }
8649         }
8650
8651       goto release;
8652     }
8653
8654   /* object not on stack then we need the name */
8655   size = AOP_SIZE (IC_RESULT (ic));
8656   offset = 0;
8657
8658   while (size--)
8659     {
8660       char s[SDCC_NAME_MAX];
8661       if (offset)
8662         sprintf (s, "#(%s >> %d)",
8663                  sym->rname,
8664                  offset * 8);
8665       else
8666         sprintf (s, "#%s", sym->rname);
8667       aopPut (AOP (IC_RESULT (ic)), s, offset++);
8668     }
8669
8670 release:
8671   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8672
8673 }
8674
8675 /*-----------------------------------------------------------------*/
8676 /* genFarFarAssign - assignment when both are in far space         */
8677 /*-----------------------------------------------------------------*/
8678 static void
8679 genFarFarAssign (operand * result, operand * right, iCode * ic)
8680 {
8681   int size = AOP_SIZE (right);
8682   int offset = 0;
8683   char *l;
8684
8685   if (size > 1)
8686     {
8687       /* This is a net loss for size == 1, but a big gain
8688        * otherwise.
8689        */
8690       D (emitcode (";", "genFarFarAssign (improved)");
8691         );
8692
8693       aopOp (result, ic, TRUE, TRUE);
8694
8695       _startLazyDPSEvaluation ();
8696       while (size--)
8697         {
8698           aopPut (AOP (result),
8699                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8700           offset++;
8701         }
8702       _endLazyDPSEvaluation ();
8703       freeAsmop (result, NULL, ic, FALSE);
8704       freeAsmop (right, NULL, ic, FALSE);
8705     }
8706   else
8707     {
8708       D (emitcode (";", "genFarFarAssign ");
8709         );
8710
8711       /* first push the right side on to the stack */
8712       _startLazyDPSEvaluation ();
8713       while (size--)
8714         {
8715           l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8716           MOVA (l);
8717           emitcode ("push", "acc");
8718         }
8719
8720       freeAsmop (right, NULL, ic, FALSE);
8721       /* now assign DPTR to result */
8722       aopOp (result, ic, FALSE, FALSE);
8723       size = AOP_SIZE (result);
8724       while (size--)
8725         {
8726           emitcode ("pop", "acc");
8727           aopPut (AOP (result), "a", --offset);
8728         }
8729       freeAsmop (result, NULL, ic, FALSE);
8730       _endLazyDPSEvaluation ();
8731     }
8732 }
8733
8734 /*-----------------------------------------------------------------*/
8735 /* genAssign - generate code for assignment                        */
8736 /*-----------------------------------------------------------------*/
8737 static void
8738 genAssign (iCode * ic)
8739 {
8740   operand *result, *right;
8741   int size, offset;
8742   unsigned long lit = 0L;
8743
8744   D (emitcode (";", "genAssign ");
8745     );
8746
8747   result = IC_RESULT (ic);
8748   right = IC_RIGHT (ic);
8749
8750   /* if they are the same */
8751   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8752     return;
8753
8754   aopOp (right, ic, FALSE, FALSE);
8755
8756   emitcode (";", "genAssign: resultIsFar = %s",
8757             isOperandInFarSpace (result) ?
8758             "TRUE" : "FALSE");
8759
8760   /* special case both in far space */
8761   if ((AOP_TYPE (right) == AOP_DPTR ||
8762        AOP_TYPE (right) == AOP_DPTR2) &&
8763   /* IS_TRUE_SYMOP(result)       && */
8764       isOperandInFarSpace (result))
8765     {
8766       genFarFarAssign (result, right, ic);
8767       return;
8768     }
8769
8770   aopOp (result, ic, TRUE, FALSE);
8771
8772   /* if they are the same registers */
8773   if (sameRegs (AOP (right), AOP (result)))
8774     goto release;
8775
8776   /* if the result is a bit */
8777   if (AOP_TYPE (result) == AOP_CRY)
8778     {
8779
8780       /* if the right size is a literal then
8781          we know what the value is */
8782       if (AOP_TYPE (right) == AOP_LIT)
8783         {
8784           if (((int) operandLitValue (right)))
8785             aopPut (AOP (result), one, 0);
8786           else
8787             aopPut (AOP (result), zero, 0);
8788           goto release;
8789         }
8790
8791       /* the right is also a bit variable */
8792       if (AOP_TYPE (right) == AOP_CRY)
8793         {
8794           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8795           aopPut (AOP (result), "c", 0);
8796           goto release;
8797         }
8798
8799       /* we need to or */
8800       toBoolean (right);
8801       aopPut (AOP (result), "a", 0);
8802       goto release;
8803     }
8804
8805   /* bit variables done */
8806   /* general case */
8807   size = AOP_SIZE (result);
8808   offset = 0;
8809   if (AOP_TYPE (right) == AOP_LIT)
8810     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8811
8812   if ((size > 1) &&
8813       (AOP_TYPE (result) != AOP_REG) &&
8814       (AOP_TYPE (right) == AOP_LIT) &&
8815       !IS_FLOAT (operandType (right)))
8816     {
8817       D (emitcode (";", "Kevin's better literal load code");
8818         );
8819       _startLazyDPSEvaluation ();
8820       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8821         {
8822           aopPut (AOP (result),
8823                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8824                   offset);
8825           offset++;
8826           size--;
8827         }
8828       /* And now fill the rest with zeros. */
8829       if (size)
8830         {
8831           emitcode ("clr", "a");
8832         }
8833       while (size--)
8834         {
8835           aopPut (AOP (result), "a", offset++);
8836         }
8837       _endLazyDPSEvaluation ();
8838     }
8839   else
8840     {
8841       _startLazyDPSEvaluation ();
8842       while (size--)
8843         {
8844           aopPut (AOP (result),
8845                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8846                   offset);
8847           offset++;
8848         }
8849       _endLazyDPSEvaluation ();
8850     }
8851
8852 release:
8853   freeAsmop (right, NULL, ic, FALSE);
8854   freeAsmop (result, NULL, ic, TRUE);
8855 }
8856
8857 /*-----------------------------------------------------------------*/
8858 /* genJumpTab - generates code for jump table                      */
8859 /*-----------------------------------------------------------------*/
8860 static void
8861 genJumpTab (iCode * ic)
8862 {
8863   symbol *jtab;
8864   char *l;
8865
8866   D (emitcode (";", "genJumpTab ");
8867     );
8868
8869   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8870   /* get the condition into accumulator */
8871   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8872   MOVA (l);
8873   /* multiply by four! */
8874   emitcode ("add", "a,acc");
8875   emitcode ("add", "a,acc");
8876   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8877
8878   jtab = newiTempLabel (NULL);
8879   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8880   emitcode ("jmp", "@a+dptr");
8881   emitcode ("", "%05d$:", jtab->key + 100);
8882   /* now generate the jump labels */
8883   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8884        jtab = setNextItem (IC_JTLABELS (ic)))
8885     emitcode ("ljmp", "%05d$", jtab->key + 100);
8886
8887 }
8888
8889 /*-----------------------------------------------------------------*/
8890 /* genCast - gen code for casting                                  */
8891 /*-----------------------------------------------------------------*/
8892 static void
8893 genCast (iCode * ic)
8894 {
8895   operand *result = IC_RESULT (ic);
8896   sym_link *ctype = operandType (IC_LEFT (ic));
8897   sym_link *rtype = operandType (IC_RIGHT (ic));
8898   operand *right = IC_RIGHT (ic);
8899   int size, offset;
8900
8901   D (emitcode (";", "genCast ");
8902     );
8903
8904   /* if they are equivalent then do nothing */
8905   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8906     return;
8907
8908   aopOp (right, ic, FALSE, FALSE);
8909   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8910
8911   /* if the result is a bit */
8912   if (AOP_TYPE (result) == AOP_CRY)
8913     {
8914       /* if the right size is a literal then
8915          we know what the value is */
8916       if (AOP_TYPE (right) == AOP_LIT)
8917         {
8918           if (((int) operandLitValue (right)))
8919             aopPut (AOP (result), one, 0);
8920           else
8921             aopPut (AOP (result), zero, 0);
8922
8923           goto release;
8924         }
8925
8926       /* the right is also a bit variable */
8927       if (AOP_TYPE (right) == AOP_CRY)
8928         {
8929           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8930           aopPut (AOP (result), "c", 0);
8931           goto release;
8932         }
8933
8934       /* we need to or */
8935       toBoolean (right);
8936       aopPut (AOP (result), "a", 0);
8937       goto release;
8938     }
8939
8940   /* if they are the same size : or less */
8941   if (AOP_SIZE (result) <= AOP_SIZE (right))
8942     {
8943
8944       /* if they are in the same place */
8945       if (sameRegs (AOP (right), AOP (result)))
8946         goto release;
8947
8948       /* if they in different places then copy */
8949       size = AOP_SIZE (result);
8950       offset = 0;
8951       _startLazyDPSEvaluation ();
8952       while (size--)
8953         {
8954           aopPut (AOP (result),
8955                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8956                   offset);
8957           offset++;
8958         }
8959       _endLazyDPSEvaluation ();
8960       goto release;
8961     }
8962
8963
8964   /* if the result is of type pointer */
8965   if (IS_PTR (ctype))
8966     {
8967
8968       int p_type;
8969       sym_link *type = operandType (right);
8970
8971       /* pointer to generic pointer */
8972       if (IS_GENPTR (ctype))
8973         {
8974           char *l = zero;
8975
8976           if (IS_PTR (type))
8977             {
8978               p_type = DCL_TYPE (type);
8979             }
8980           else
8981             {
8982 #if OLD_CAST_BEHAVIOR
8983               /* KV: we are converting a non-pointer type to
8984                * a generic pointer. This (ifdef'd out) code
8985                * says that the resulting generic pointer
8986                * should have the same class as the storage
8987                * location of the non-pointer variable.
8988                *
8989                * For example, converting an int (which happens
8990                * to be stored in DATA space) to a pointer results
8991                * in a DATA generic pointer; if the original int
8992                * in XDATA space, so will be the resulting pointer.
8993                *
8994                * I don't like that behavior, and thus this change:
8995                * all such conversions will be forced to XDATA and
8996                * throw a warning. If you want some non-XDATA
8997                * type, or you want to suppress the warning, you
8998                * must go through an intermediate cast, like so:
8999                *
9000                * char _generic *gp = (char _xdata *)(intVar);
9001                */
9002               sym_link *etype = getSpec (type);
9003
9004               /* we have to go by the storage class */
9005               if (SPEC_OCLS (etype) != generic)
9006                 {
9007                   p_type = PTR_TYPE (SPEC_OCLS (etype));
9008                 }
9009               else
9010 #endif
9011                 {
9012                   /* Converting unknown class (i.e. register variable)
9013                    * to generic pointer. This is not good, but
9014                    * we'll make a guess (and throw a warning).
9015                    */
9016                   p_type = FPOINTER;
9017                   werror (W_INT_TO_GEN_PTR_CAST);
9018                 }
9019             }
9020
9021           /* the first two bytes are known */
9022           size = GPTRSIZE - 1;
9023           offset = 0;
9024           _startLazyDPSEvaluation ();
9025           while (size--)
9026             {
9027               aopPut (AOP (result),
9028                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9029                       offset);
9030               offset++;
9031             }
9032           _endLazyDPSEvaluation ();
9033
9034           /* the last byte depending on type */
9035           switch (p_type)
9036             {
9037             case IPOINTER:
9038             case POINTER:
9039               l = zero;
9040               break;
9041             case FPOINTER:
9042               l = one;
9043               break;
9044             case CPOINTER:
9045               l = "#0x02";
9046               break;
9047             case PPOINTER:
9048               l = "#0x03";
9049               break;
9050
9051             default:
9052               /* this should never happen */
9053               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9054                       "got unknown pointer type");
9055               exit (1);
9056             }
9057           aopPut (AOP (result), l, GPTRSIZE - 1);
9058           goto release;
9059         }
9060
9061       /* just copy the pointers */
9062       size = AOP_SIZE (result);
9063       offset = 0;
9064       _startLazyDPSEvaluation ();
9065       while (size--)
9066         {
9067           aopPut (AOP (result),
9068                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9069                   offset);
9070           offset++;
9071         }
9072       _endLazyDPSEvaluation ();
9073       goto release;
9074     }
9075
9076   /* so we now know that the size of destination is greater
9077      than the size of the source */
9078   /* we move to result for the size of source */
9079   size = AOP_SIZE (right);
9080   offset = 0;
9081   _startLazyDPSEvaluation ();
9082   while (size--)
9083     {
9084       aopPut (AOP (result),
9085               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9086               offset);
9087       offset++;
9088     }
9089   _endLazyDPSEvaluation ();
9090
9091   /* now depending on the sign of the source && destination */
9092   size = AOP_SIZE (result) - AOP_SIZE (right);
9093   /* if unsigned or not an integral type */
9094   /* also, if the source is a bit, we don't need to sign extend, because
9095    * it can't possibly have set the sign bit.
9096    */
9097   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9098     {
9099       while (size--)
9100         {
9101           aopPut (AOP (result), zero, offset++);
9102         }
9103     }
9104   else
9105     {
9106       /* we need to extend the sign :{ */
9107       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9108                         FALSE, FALSE, TRUE);
9109       MOVA (l);
9110       emitcode ("rlc", "a");
9111       emitcode ("subb", "a,acc");
9112       while (size--)
9113         aopPut (AOP (result), "a", offset++);
9114     }
9115
9116   /* we are done hurray !!!! */
9117
9118 release:
9119   freeAsmop (right, NULL, ic, TRUE);
9120   freeAsmop (result, NULL, ic, TRUE);
9121
9122 }
9123
9124 /*-----------------------------------------------------------------*/
9125 /* genDjnz - generate decrement & jump if not zero instrucion      */
9126 /*-----------------------------------------------------------------*/
9127 static int
9128 genDjnz (iCode * ic, iCode * ifx)
9129 {
9130   symbol *lbl, *lbl1;
9131   if (!ifx)
9132     return 0;
9133
9134   /* if the if condition has a false label
9135      then we cannot save */
9136   if (IC_FALSE (ifx))
9137     return 0;
9138
9139   /* if the minus is not of the form
9140      a = a - 1 */
9141   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9142       !IS_OP_LITERAL (IC_RIGHT (ic)))
9143     return 0;
9144
9145   if (operandLitValue (IC_RIGHT (ic)) != 1)
9146     return 0;
9147
9148   /* if the size of this greater than one then no
9149      saving */
9150   if (getSize (operandType (IC_RESULT (ic))) > 1)
9151     return 0;
9152
9153   /* otherwise we can save BIG */
9154   lbl = newiTempLabel (NULL);
9155   lbl1 = newiTempLabel (NULL);
9156
9157   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9158
9159   if (IS_AOP_PREG (IC_RESULT (ic)))
9160     {
9161       emitcode ("dec", "%s",
9162                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9163       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9164       emitcode ("jnz", "%05d$", lbl->key + 100);
9165     }
9166   else
9167     {
9168       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
9169                 lbl->key + 100);
9170     }
9171   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9172   emitcode ("", "%05d$:", lbl->key + 100);
9173   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9174   emitcode ("", "%05d$:", lbl1->key + 100);
9175
9176   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9177   ifx->generated = 1;
9178   return 1;
9179 }
9180
9181 /*-----------------------------------------------------------------*/
9182 /* genReceive - generate code for a receive iCode                  */
9183 /*-----------------------------------------------------------------*/
9184 static void
9185 genReceive (iCode * ic)
9186 {
9187
9188   D (emitcode (";", "genReceive ");
9189     );
9190
9191   if (isOperandInFarSpace (IC_RESULT (ic)) &&
9192       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9193        IS_TRUE_SYMOP (IC_RESULT (ic))))
9194     {
9195       int size = getSize (operandType (IC_RESULT (ic)));
9196       int offset = fReturnSizeDS390 - size;
9197       while (size--)
9198         {
9199           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9200                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9201           offset++;
9202         }
9203       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9204       size = AOP_SIZE (IC_RESULT (ic));
9205       offset = 0;
9206       while (size--)
9207         {
9208           emitcode ("pop", "acc");
9209           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9210         }
9211
9212     }
9213   else
9214     {
9215       _G.accInUse++;
9216       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9217       _G.accInUse--;
9218       assignResultValue (IC_RESULT (ic));
9219     }
9220
9221   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9222 }
9223
9224 /*-----------------------------------------------------------------*/
9225 /* gen390Code - generate code for Dallas 390 based controllers     */
9226 /*-----------------------------------------------------------------*/
9227 void
9228 gen390Code (iCode * lic)
9229 {
9230   iCode *ic;
9231   int cln = 0;
9232
9233   lineHead = lineCurr = NULL;
9234
9235 #if 0
9236   //REMOVE ME!!!
9237   /* print the allocation information */
9238   if (allocInfo)
9239     printAllocInfo (currFunc, codeOutFile);
9240 #endif
9241   /* if debug information required */
9242   if (options.debug && currFunc)
9243     {
9244       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9245       _G.debugLine = 1;
9246       if (IS_STATIC (currFunc->etype))
9247         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9248       else
9249         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9250       _G.debugLine = 0;
9251     }
9252   /* stack pointer name */
9253   if (options.useXstack)
9254     spname = "_spx";
9255   else
9256     spname = "sp";
9257
9258
9259   for (ic = lic; ic; ic = ic->next)
9260     {
9261
9262       if (cln != ic->lineno)
9263         {
9264           if (options.debug)
9265             {
9266               _G.debugLine = 1;
9267               emitcode ("", "C$%s$%d$%d$%d ==.",
9268                         FileBaseName (ic->filename), ic->lineno,
9269                         ic->level, ic->block);
9270               _G.debugLine = 0;
9271             }
9272           emitcode (";", "%s %d", ic->filename, ic->lineno);
9273           cln = ic->lineno;
9274         }
9275       /* if the result is marked as
9276          spilt and rematerializable or code for
9277          this has already been generated then
9278          do nothing */
9279       if (resultRemat (ic) || ic->generated)
9280         continue;
9281
9282       /* depending on the operation */
9283       switch (ic->op)
9284         {
9285         case '!':
9286           genNot (ic);
9287           break;
9288
9289         case '~':
9290           genCpl (ic);
9291           break;
9292
9293         case UNARYMINUS:
9294           genUminus (ic);
9295           break;
9296
9297         case IPUSH:
9298           genIpush (ic);
9299           break;
9300
9301         case IPOP:
9302           /* IPOP happens only when trying to restore a
9303              spilt live range, if there is an ifx statement
9304              following this pop then the if statement might
9305              be using some of the registers being popped which
9306              would destory the contents of the register so
9307              we need to check for this condition and handle it */
9308           if (ic->next &&
9309               ic->next->op == IFX &&
9310               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9311             genIfx (ic->next, ic);
9312           else
9313             genIpop (ic);
9314           break;
9315
9316         case CALL:
9317           genCall (ic);
9318           break;
9319
9320         case PCALL:
9321           genPcall (ic);
9322           break;
9323
9324         case FUNCTION:
9325           genFunction (ic);
9326           break;
9327
9328         case ENDFUNCTION:
9329           genEndFunction (ic);
9330           break;
9331
9332         case RETURN:
9333           genRet (ic);
9334           break;
9335
9336         case LABEL:
9337           genLabel (ic);
9338           break;
9339
9340         case GOTO:
9341           genGoto (ic);
9342           break;
9343
9344         case '+':
9345           genPlus (ic);
9346           break;
9347
9348         case '-':
9349           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9350             genMinus (ic);
9351           break;
9352
9353         case '*':
9354           genMult (ic);
9355           break;
9356
9357         case '/':
9358           genDiv (ic);
9359           break;
9360
9361         case '%':
9362           genMod (ic);
9363           break;
9364
9365         case '>':
9366           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9367           break;
9368
9369         case '<':
9370           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9371           break;
9372
9373         case LE_OP:
9374         case GE_OP:
9375         case NE_OP:
9376
9377           /* note these two are xlated by algebraic equivalence
9378              during parsing SDCC.y */
9379           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9380                   "got '>=' or '<=' shouldn't have come here");
9381           break;
9382
9383         case EQ_OP:
9384           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9385           break;
9386
9387         case AND_OP:
9388           genAndOp (ic);
9389           break;
9390
9391         case OR_OP:
9392           genOrOp (ic);
9393           break;
9394
9395         case '^':
9396           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9397           break;
9398
9399         case '|':
9400           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9401           break;
9402
9403         case BITWISEAND:
9404           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9405           break;
9406
9407         case INLINEASM:
9408           genInline (ic);
9409           break;
9410
9411         case RRC:
9412           genRRC (ic);
9413           break;
9414
9415         case RLC:
9416           genRLC (ic);
9417           break;
9418
9419         case GETHBIT:
9420           genGetHbit (ic);
9421           break;
9422
9423         case LEFT_OP:
9424           genLeftShift (ic);
9425           break;
9426
9427         case RIGHT_OP:
9428           genRightShift (ic);
9429           break;
9430
9431         case GET_VALUE_AT_ADDRESS:
9432           genPointerGet (ic);
9433           break;
9434
9435         case '=':
9436           if (POINTER_SET (ic))
9437             genPointerSet (ic);
9438           else
9439             genAssign (ic);
9440           break;
9441
9442         case IFX:
9443           genIfx (ic, NULL);
9444           break;
9445
9446         case ADDRESS_OF:
9447           genAddrOf (ic);
9448           break;
9449
9450         case JUMPTABLE:
9451           genJumpTab (ic);
9452           break;
9453
9454         case CAST:
9455           genCast (ic);
9456           break;
9457
9458         case RECEIVE:
9459           genReceive (ic);
9460           break;
9461
9462         case SEND:
9463           addSet (&_G.sendSet, ic);
9464           break;
9465
9466         default:
9467           ic = ic;
9468           /*      piCode(ic,stdout); */
9469
9470         }
9471     }
9472
9473
9474   /* now we are ready to call the
9475      peep hole optimizer */
9476   if (!options.nopeep)
9477     peepHole (&lineHead);
9478
9479   /* now do the actual printing */
9480   printLine (lineHead, codeOutFile);
9481   return;
9482 }