More DS400 support
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for DS80C390
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "common.h"
34 #include "ralloc.h"
35 #include "gen.h"
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #define BETTER_LITERAL_SHIFT
40
41 char *aopLiteral (value * val, int offset);
42 extern int allocInfo;
43
44 /* this is the down and dirty file with all kinds of
45    kludgy & hacky stuff. This is what it is all about
46    CODE GENERATION for a specific MCU . some of the
47    routines may be reusable, will have to see */
48
49 static char *zero = "#0";
50 static char *one = "#1";
51 static char *spname;
52
53 #define D(x) x
54
55 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
56 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
57
58 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
59 static char *fReturn24[] =
60 {"dpl", "dph", "dpx", "b", "a"};
61 static char *fReturn16[] =
62 {"dpl", "dph", "b", "a"};
63 static char **fReturn = fReturn24;
64 static char *accUse[] =
65 {"a", "b"};
66 static char *dptrn[2][3];
67 static char *javaRet[] = { "r0","r1","r2","r3"};
68 static short rbank = -1;
69
70 static struct
71   {
72     short r0Pushed;
73     short r1Pushed;
74     short accInUse;
75     short bInUse;
76     short inLine;
77     short debugLine;
78     short nRegsSaved;
79     short dptrInUse;
80     short dptr1InUse;
81     set *sendSet;
82   }
83 _G;
84
85 static char *rb1regs[] = {
86     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
87 };
88
89 static void saveRBank (int, iCode *, bool);
90
91 #define RESULTONSTACK(x) \
92                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
93                          IC_RESULT(x)->aop->type == AOP_STK )
94
95 #define MOVA(x) _movA(x)
96 #define MOVB(x) _movB(x)
97                 
98 #define CLRC    emitcode("clr","c")
99 #define SETC    emitcode("setb","c")
100
101 // A scratch register which will be used to hold
102 // result bytes from operands in far space via DPTR2.
103 #define DP2_RESULT_REG  "_ap"
104
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
107
108 static unsigned char SLMask[] =
109 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
110  0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] =
112 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113  0x07, 0x03, 0x01, 0x00};
114
115 #define LSB     0
116 #define MSB16   1
117 #define MSB24   2
118 #define MSB32   3
119 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
120                                 symbol *lbl = newiTempLabel(NULL);              \
121                                 emitcode ("setb","F1");                         \
122                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
123                                 emitcode ("clr","F1");                          \
124                                 emitcode ("","!tlabeldef",lbl->key+100);        \
125                         }}
126 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
127                                 symbol *lbl = newiTempLabel(NULL);              \
128                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
129                                 emitcode ("setb","EA");                         \
130                                 emitcode ("","!tlabeldef",lbl->key+100);        \
131                         }}
132
133
134 /*-----------------------------------------------------------------*/
135 /* emitcode - writes the code into a file : for now it is simple    */
136 /*-----------------------------------------------------------------*/
137 static void
138 emitcode (char *inst, char *fmt,...)
139 {
140     va_list ap;
141     char lb[INITIAL_INLINEASM];
142     char *lbp = lb;
143     
144     va_start (ap, fmt);
145     
146     if (inst && *inst)
147     {
148         if (fmt && *fmt)
149         {
150             SNPRINTF (lb, sizeof(lb), "%s\t", inst);
151         }
152         else
153         {
154             SNPRINTF (lb, sizeof(lb), "%s", inst);
155         }
156         
157         tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), 
158                    fmt, ap);
159     }
160     else
161     {
162         tvsprintf (lb, sizeof(lb), fmt, ap);
163     }
164     
165
166     while (isspace (*lbp))
167     {
168         lbp++;
169     }
170
171     if (lbp && *lbp)
172     {
173         lineCurr = (lineCurr ?
174                     connectLine (lineCurr, newLineNode (lb)) :
175                     (lineHead = newLineNode (lb)));
176     }
177     
178     lineCurr->isInline = _G.inLine;
179     lineCurr->isDebug = _G.debugLine;
180     va_end (ap);
181 }
182
183 //
184 // Move the passed value into A unless it is already there.
185 // 
186 static void
187 _movA(const char *s)
188 {
189     if (strcmp(s,"a") && strcmp(s,"acc"))
190     { 
191         emitcode("mov","a,%s",s);
192     } 
193 }
194
195 //
196 // Move the passed value into B unless it is already there.
197 // 
198 static void
199 _movB(const char *s)
200 {
201     if (strcmp(s,"b"))
202     { 
203         emitcode("mov","b,%s",s);
204     } 
205 }
206
207 /*-----------------------------------------------------------------*/
208 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
209 /*-----------------------------------------------------------------*/
210 static regs *
211 getFreePtr (iCode * ic, asmop ** aopp, bool result)
212 {
213   bool r0iu, r1iu;
214   bool r0ou, r1ou;
215
216   /* the logic: if r0 & r1 used in the instruction
217      then we are in trouble otherwise */
218
219   /* first check if r0 & r1 are used by this
220      instruction, in which case we are in trouble */
221   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
222   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
223   if (r0iu && r1iu) {
224       goto endOfWorld;
225     }
226
227   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
228   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
229
230   /* if no usage of r0 then return it */
231   if (!r0iu && !r0ou)
232     {
233       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
234       (*aopp)->type = AOP_R0;
235
236       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
237     }
238
239   /* if no usage of r1 then return it */
240   if (!r1iu && !r1ou)
241     {
242       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
243       (*aopp)->type = AOP_R1;
244
245       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
246     }
247
248   /* now we know they both have usage */
249   /* if r0 not used in this instruction */
250   if (!r0iu)
251     {
252       /* push it if not already pushed */
253       if (!_G.r0Pushed)
254         {
255           emitcode ("push", "%s",
256                     ds390_regWithIdx (R0_IDX)->dname);
257           _G.r0Pushed++;
258         }
259
260       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
261       (*aopp)->type = AOP_R0;
262
263       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
264     }
265
266   /* if r1 not used then */
267
268   if (!r1iu)
269     {
270       /* push it if not already pushed */
271       if (!_G.r1Pushed)
272         {
273           emitcode ("push", "%s",
274                     ds390_regWithIdx (R1_IDX)->dname);
275           _G.r1Pushed++;
276         }
277
278       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
279       (*aopp)->type = AOP_R1;
280       return ds390_regWithIdx (R1_IDX);
281     }
282
283 endOfWorld:
284   /* I said end of world but not quite end of world yet */
285   /* if this is a result then we can push it on the stack */
286   if (result)
287     {
288       (*aopp)->type = AOP_STK;
289       return NULL;
290     }
291
292   /* other wise this is true end of the world */
293   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
294           "getFreePtr should never reach here");
295   exit (1);
296     
297   return NULL; // notreached, but makes compiler happy.
298 }
299
300 /*-----------------------------------------------------------------*/
301 /* newAsmop - creates a new asmOp                                  */
302 /*-----------------------------------------------------------------*/
303 static asmop *
304 newAsmop (short type)
305 {
306   asmop *aop;
307
308   aop = Safe_calloc (1, sizeof (asmop));
309   aop->type = type;
310   return aop;
311 }
312
313 static int _currentDPS;         /* Current processor DPS. */
314 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
315 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
316
317 /*-----------------------------------------------------------------*/
318 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
319 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
320 /* alternate DPTR (DPL1/DPH1/DPX1).          */
321 /*-----------------------------------------------------------------*/
322 static void
323 genSetDPTR (int n)
324 {
325
326   /* If we are doing lazy evaluation, simply note the desired
327    * change, but don't emit any code yet.
328    */
329   if (_lazyDPS)
330     {
331       _desiredDPS = n;
332       return;
333     }
334
335   if (!n)
336     {
337       emitcode ("mov", "dps,#0");
338     }
339   else
340     {
341       TR_DPTR("#1");
342       emitcode ("mov", "dps,#1");
343     }
344 }
345
346 /*-----------------------------------------------------------------*/
347 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
348 /*                   */
349 /* Any code that operates on DPTR (NB: not on the individual     */
350 /* components, like DPH) *must* call _flushLazyDPS() before using  */
351 /* DPTR within a lazy DPS evaluation block.        */
352 /*                   */
353 /* Note that aopPut and aopGet already contain the proper calls to */
354 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
355 /* DPS evaluation block.             */
356 /*                   */
357 /* Also, _flushLazyDPS must be called before any flow control      */
358 /* operations that could potentially branch out of the block.    */
359 /*                         */
360 /* Lazy DPS evaluation is simply an optimization (though an      */
361 /* important one), so if in doubt, leave it out.       */
362 /*-----------------------------------------------------------------*/
363 static void
364 _startLazyDPSEvaluation (void)
365 {
366   _currentDPS = 0;
367   _desiredDPS = 0;
368 #ifdef BETTER_LITERAL_SHIFT  
369   _lazyDPS++;
370 #else
371   _lazyDPS = 1;
372 #endif  
373 }
374
375 /*-----------------------------------------------------------------*/
376 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
377 /* desired one. Call before using DPTR within a lazy DPS evaluation */
378 /* block.                */
379 /*-----------------------------------------------------------------*/
380 static void
381 _flushLazyDPS (void)
382 {
383   if (!_lazyDPS)
384     {
385       /* nothing to do. */
386       return;
387     }
388
389   if (_desiredDPS != _currentDPS)
390     {
391       if (_desiredDPS)
392         {
393           emitcode ("inc", "dps");
394         }
395       else
396         {
397           emitcode ("dec", "dps");
398         }
399       _currentDPS = _desiredDPS;
400     }
401 }
402
403 /*-----------------------------------------------------------------*/
404 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
405 /*                   */
406 /* Forces us back to the safe state (standard DPTR selected).    */
407 /*-----------------------------------------------------------------*/
408 static void
409 _endLazyDPSEvaluation (void)
410 {
411 #ifdef BETTER_LITERAL_SHIFT  
412   _lazyDPS--;
413 #else
414   _lazyDPS = 0;
415 #endif    
416   if (!_lazyDPS)
417   {
418     if (_currentDPS)
419     {
420       genSetDPTR (0);
421       _flushLazyDPS ();
422     }
423     _currentDPS = 0;
424     _desiredDPS = 0;
425   }
426 }
427
428
429
430 /*-----------------------------------------------------------------*/
431 /* pointerCode - returns the code for a pointer type               */
432 /*-----------------------------------------------------------------*/
433 static int
434 pointerCode (sym_link * etype)
435 {
436
437   return PTR_TYPE (SPEC_OCLS (etype));
438
439 }
440
441 /*-----------------------------------------------------------------*/
442 /* aopForSym - for a true symbol                                   */
443 /*-----------------------------------------------------------------*/
444 static asmop *
445 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
446 {
447   asmop *aop;
448   memmap *space = SPEC_OCLS (sym->etype);
449
450   /* if already has one */
451   if (sym->aop)
452     return sym->aop;
453
454   /* assign depending on the storage class */
455   /* if it is on the stack or indirectly addressable */
456   /* space we need to assign either r0 or r1 to it   */
457   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
458     {
459       sym->aop = aop = newAsmop (0);
460       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
461       aop->size = getSize (sym->type);
462
463       /* now assign the address of the variable to
464          the pointer register */
465       if (aop->type != AOP_STK)
466         {
467
468           if (sym->onStack)
469             {
470               if (_G.accInUse)
471                 emitcode ("push", "acc");
472
473               if (_G.bInUse)
474                 emitcode ("push", "b");
475
476               emitcode ("mov", "a,_bp");
477               emitcode ("add", "a,#!constbyte",
478                         ((sym->stack < 0) ?
479                          ((char) (sym->stack - _G.nRegsSaved)) :
480                          ((char) sym->stack)) & 0xff);
481               emitcode ("mov", "%s,a",
482                         aop->aopu.aop_ptr->name);
483
484               if (_G.bInUse)
485                 emitcode ("pop", "b");
486
487               if (_G.accInUse)
488                 emitcode ("pop", "acc");
489             }
490           else
491             emitcode ("mov", "%s,#%s",
492                       aop->aopu.aop_ptr->name,
493                       sym->rname);
494           aop->paged = space->paged;
495         }
496       else
497         aop->aopu.aop_stk = sym->stack;
498       return aop;
499     }
500
501   if (sym->onStack && options.stack10bit)
502     {
503         short stack_val = -((sym->stack < 0) ?
504                             ((short) (sym->stack - _G.nRegsSaved)) :
505                             ((short) sym->stack)) ;
506         if (useDP2 && _G.dptr1InUse) {
507             emitcode ("push","dpl1");
508             emitcode ("push","dph1");
509             emitcode ("push","dpx1");
510         } else if (_G.dptrInUse ) {
511             emitcode ("push","dpl");
512             emitcode ("push","dph");
513             emitcode ("push","dpx");
514         }
515       /* It's on the 10 bit stack, which is located in
516        * far data space.
517        */           
518         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
519             if (useDP2) {
520                 if (options.model == MODEL_FLAT24)
521                 {
522                     emitcode ("mov", "dpx1,#!constbyte",
523                               (options.stack_loc >> 16) & 0xff);
524                 }
525                 emitcode ("mov", "dph1,_bpx+1");
526                 
527                 emitcode ("mov", "dpl1,_bpx");
528                 emitcode ("mov","dps,#1");
529             } else {
530                 if (options.model == MODEL_FLAT24)
531                 {
532                     emitcode ("mov", "dpx,#!constbyte",
533                               (options.stack_loc >> 16) & 0xff);
534                 }
535                 emitcode ("mov", "dph,_bpx+1");
536                 emitcode ("mov", "dpl,_bpx");
537             }
538             stack_val = -stack_val;
539             while (stack_val--) {
540                 emitcode ("inc","dptr");
541             }
542             if (useDP2) {
543                 emitcode("mov","dps,#0");
544             }
545         }  else {
546             if (_G.accInUse)
547                 emitcode ("push", "acc");
548             
549             if (_G.bInUse)
550                 emitcode ("push", "b");
551         
552             emitcode ("mov", "a,_bpx");
553             emitcode ("clr","c");
554             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
555             emitcode ("mov","b,a");
556             emitcode ("mov","a,_bpx+1");
557             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
558             if (useDP2) {
559                 if (options.model == MODEL_FLAT24)
560                 {
561                     emitcode ("mov", "dpx1,#!constbyte",
562                               (options.stack_loc >> 16) & 0xff);
563                 }
564                 emitcode ("mov", "dph1,a");
565                 emitcode ("mov", "dpl1,b");
566             } else {
567                 if (options.model == MODEL_FLAT24)
568                 {
569                     emitcode ("mov", "dpx,#!constbyte",
570                               (options.stack_loc >> 16) & 0xff);
571                 }
572                 emitcode ("mov", "dph,a");
573                 emitcode ("mov", "dpl,b");
574             }
575             
576             if (_G.bInUse)
577                 emitcode ("pop", "b");
578             
579             if (_G.accInUse)
580                 emitcode ("pop", "acc");
581         }
582         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
583         aop->size = getSize (sym->type);
584         return aop;
585     }
586
587   /* if in bit space */
588   if (IN_BITSPACE (space))
589     {
590       sym->aop = aop = newAsmop (AOP_CRY);
591       aop->aopu.aop_dir = sym->rname;
592       aop->size = getSize (sym->type);
593       return aop;
594     }
595   /* if it is in direct space */
596   if (IN_DIRSPACE (space))
597     {
598       sym->aop = aop = newAsmop (AOP_DIR);
599       aop->aopu.aop_dir = sym->rname;
600       aop->size = getSize (sym->type);
601       return aop;
602     }
603
604   /* special case for a function */
605   if (IS_FUNC (sym->type))
606     {
607       sym->aop = aop = newAsmop (AOP_IMMD);
608       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);   
609       aop->size = FPTRSIZE;
610       return aop;
611     }
612   
613   /* only remaining is far space */
614   /* in which case DPTR gets the address */
615   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
616   if (useDP2)
617     {
618       genSetDPTR (1);
619       _flushLazyDPS ();
620       emitcode ("mov", "dptr,#%s", sym->rname);
621       genSetDPTR (0);
622     }
623   else
624     {
625       emitcode ("mov", "dptr,#%s", sym->rname);
626     }
627   aop->size = getSize (sym->type);
628
629   /* if it is in code space */
630   if (IN_CODESPACE (space))
631     aop->code = 1;
632
633   return aop;
634 }
635
636 /*-----------------------------------------------------------------*/
637 /* aopForRemat - rematerialzes an object                           */
638 /*-----------------------------------------------------------------*/
639 static asmop *
640 aopForRemat (symbol * sym)
641 {
642   iCode *ic = sym->rematiCode;
643   asmop *aop = newAsmop (AOP_IMMD);
644   int ptr_type =0;
645   int val = 0;
646
647   for (;;)
648     {
649       if (ic->op == '+')
650         val += (int) operandLitValue (IC_RIGHT (ic));
651       else if (ic->op == '-')
652         val -= (int) operandLitValue (IC_RIGHT (ic));
653       else if (IS_CAST_ICODE(ic)) {
654               sym_link *from_type = operandType(IC_RIGHT(ic));
655               aop->aopu.aop_immd.from_cast_remat = 1;
656               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
657               ptr_type = DCL_TYPE(from_type);
658               if (ptr_type == IPOINTER) {
659                 // bug #481053
660                 ptr_type = POINTER;
661               }
662               continue ;
663       } else break;
664       
665       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
666     }
667
668   if (val)
669   {
670       SNPRINTF (buffer, sizeof(buffer),
671                 "(%s %c 0x%04x)",
672                 OP_SYMBOL (IC_LEFT (ic))->rname,
673                 val >= 0 ? '+' : '-',
674                 abs (val) & 0xffffff);
675   }
676   else 
677   {
678       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
679       {
680           SNPRINTF(buffer, sizeof(buffer), 
681                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
682       }
683       else
684       {
685           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
686       }
687   }
688
689   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
690   /* set immd2 field if required */
691   if (aop->aopu.aop_immd.from_cast_remat) 
692   {
693       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
694       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
695   }
696
697   return aop;
698 }
699
700 /*-----------------------------------------------------------------*/
701 /* aopHasRegs - returns true if aop has regs between from-to       */
702 /*-----------------------------------------------------------------*/
703 static int aopHasRegs(asmop *aop, int from, int to)
704 {
705     int size =0;
706
707     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
708
709     for (; size < aop->size ; size++) {
710         int reg;
711         for (reg = from ; reg <= to ; reg++)
712             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
713     }
714     return 0;
715 }
716
717 /*-----------------------------------------------------------------*/
718 /* regsInCommon - two operands have some registers in common       */
719 /*-----------------------------------------------------------------*/
720 static bool
721 regsInCommon (operand * op1, operand * op2)
722 {
723   symbol *sym1, *sym2;
724   int i;
725
726   /* if they have registers in common */
727   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
728     return FALSE;
729
730   sym1 = OP_SYMBOL (op1);
731   sym2 = OP_SYMBOL (op2);
732
733   if (sym1->nRegs == 0 || sym2->nRegs == 0)
734     return FALSE;
735
736   for (i = 0; i < sym1->nRegs; i++)
737     {
738       int j;
739       if (!sym1->regs[i])
740         continue;
741
742       for (j = 0; j < sym2->nRegs; j++)
743         {
744           if (!sym2->regs[j])
745             continue;
746
747           if (sym2->regs[j] == sym1->regs[i])
748             return TRUE;
749         }
750     }
751
752   return FALSE;
753 }
754
755 /*-----------------------------------------------------------------*/
756 /* operandsEqu - equivalent                                        */
757 /*-----------------------------------------------------------------*/
758 static bool
759 operandsEqu (operand * op1, operand * op2)
760 {
761   symbol *sym1, *sym2;
762
763   /* if they not symbols */
764   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
765     return FALSE;
766
767   sym1 = OP_SYMBOL (op1);
768   sym2 = OP_SYMBOL (op2);
769
770   /* if both are itemps & one is spilt
771      and the other is not then false */
772   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
773       sym1->isspilt != sym2->isspilt)
774     return FALSE;
775
776   /* if they are the same */
777   if (sym1 == sym2)
778     return TRUE;
779
780   if (strcmp (sym1->rname, sym2->rname) == 0)
781     return TRUE;
782
783
784   /* if left is a tmp & right is not */
785   if (IS_ITEMP (op1) &&
786       !IS_ITEMP (op2) &&
787       sym1->isspilt &&
788       (sym1->usl.spillLoc == sym2))
789     return TRUE;
790
791   if (IS_ITEMP (op2) &&
792       !IS_ITEMP (op1) &&
793       sym2->isspilt &&
794       sym1->level > 0 &&
795       (sym2->usl.spillLoc == sym1))
796     return TRUE;
797
798   return FALSE;
799 }
800
801 /*-----------------------------------------------------------------*/
802 /* sameRegs - two asmops have the same registers                   */
803 /*-----------------------------------------------------------------*/
804 static bool
805 sameRegs (asmop * aop1, asmop * aop2)
806 {
807   int i;
808
809   if (aop1 == aop2)
810     {
811       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
812         {
813           return FALSE;
814         }
815       return TRUE;
816     }
817
818   if (aop1->type != AOP_REG ||
819       aop2->type != AOP_REG)
820     return FALSE;
821
822   if (aop1->size != aop2->size)
823     return FALSE;
824
825   for (i = 0; i < aop1->size; i++)
826     if (aop1->aopu.aop_reg[i] !=
827         aop2->aopu.aop_reg[i])
828       return FALSE;
829
830   return TRUE;
831 }
832
833 /*-----------------------------------------------------------------*/
834 /* aopOp - allocates an asmop for an operand  :                    */
835 /*-----------------------------------------------------------------*/
836 static void
837 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
838 {
839   asmop *aop;
840   symbol *sym;
841   int i;
842
843   if (!op)
844     return;
845
846   /* if this a literal */
847   if (IS_OP_LITERAL (op))
848     {
849       op->aop = aop = newAsmop (AOP_LIT);
850       aop->aopu.aop_lit = op->operand.valOperand;
851       aop->size = getSize (operandType (op));
852       return;
853     }
854
855   /* if already has a asmop then continue */
856   if (op->aop)
857     return;
858
859   /* if the underlying symbol has a aop */
860   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
861     {
862       op->aop = OP_SYMBOL (op)->aop;
863       return;
864     }
865
866   /* if this is a true symbol */
867   if (IS_TRUE_SYMOP (op))
868     {
869       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
870       return;
871     }
872
873   /* this is a temporary : this has
874      only four choices :
875      a) register
876      b) spillocation
877      c) rematerialize
878      d) conditional
879      e) can be a return use only */
880
881   sym = OP_SYMBOL (op);
882
883
884   /* if the type is a conditional */
885   if (sym->regType == REG_CND)
886     {
887       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
888       aop->size = 0;
889       return;
890     }
891
892   /* if it is spilt then two situations
893      a) is rematerialize
894      b) has a spill location */
895   if (sym->isspilt || sym->nRegs == 0)
896     {
897
898       /* rematerialize it NOW */
899       if (sym->remat)
900         {
901           sym->aop = op->aop = aop =
902             aopForRemat (sym);
903           aop->size = getSize (sym->type);
904           return;
905         }
906
907       if (sym->accuse)
908         {
909           int i;
910           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
911           aop->size = getSize (sym->type);
912           for (i = 0; i < 2; i++)
913             aop->aopu.aop_str[i] = accUse[i];
914           return;
915         }
916
917       if (sym->ruonly)
918         {
919           int i;
920
921           if (useDP2)
922             {
923               /* a AOP_STR uses DPTR, but DPTR is already in use;
924                * we're just hosed.
925                */
926                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
927             }
928
929           aop = op->aop = sym->aop = newAsmop (AOP_STR);
930           aop->size = getSize (sym->type);
931           for (i = 0; i < (int) fReturnSizeDS390; i++)
932             aop->aopu.aop_str[i] = fReturn[i];
933           return;
934         }
935       
936       if (sym->dptr) { /* has been allocated to a DPTRn */
937           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
938           aop->size = getSize (sym->type);
939           aop->aopu.dptr = sym->dptr;
940           return ;
941       }
942       /* else spill location  */
943       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
944           /* force a new aop if sizes differ */
945           sym->usl.spillLoc->aop = NULL;
946       }
947       sym->aop = op->aop = aop =
948         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
949       aop->size = getSize (sym->type);
950       return;
951     }
952
953   /* must be in a register */
954   sym->aop = op->aop = aop = newAsmop (AOP_REG);
955   aop->size = sym->nRegs;
956   for (i = 0; i < sym->nRegs; i++)
957     aop->aopu.aop_reg[i] = sym->regs[i];
958 }
959
960 /*-----------------------------------------------------------------*/
961 /* freeAsmop - free up the asmop given to an operand               */
962 /*----------------------------------------------------------------*/
963 static void
964 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
965 {
966   asmop *aop;
967
968   if (!op)
969     aop = aaop;
970   else
971     aop = op->aop;
972
973   if (!aop)
974     return;
975
976   if (aop->freed)
977     goto dealloc;
978
979   aop->freed = 1;
980
981   /* depending on the asmop type only three cases need work AOP_RO
982      , AOP_R1 && AOP_STK */
983   switch (aop->type)
984     {
985     case AOP_R0:
986       if (_G.r0Pushed)
987         {
988           if (pop)
989             {
990               emitcode ("pop", "ar0");
991               _G.r0Pushed--;
992             }
993         }
994       bitVectUnSetBit (ic->rUsed, R0_IDX);
995       break;
996
997     case AOP_R1:
998       if (_G.r1Pushed)
999         {
1000           if (pop)
1001             {
1002               emitcode ("pop", "ar1");
1003               _G.r1Pushed--;
1004             }
1005         }
1006       bitVectUnSetBit (ic->rUsed, R1_IDX);
1007       break;
1008
1009     case AOP_STK:
1010       {
1011         int sz = aop->size;
1012         int stk = aop->aopu.aop_stk + aop->size;
1013         bitVectUnSetBit (ic->rUsed, R0_IDX);
1014         bitVectUnSetBit (ic->rUsed, R1_IDX);
1015
1016         getFreePtr (ic, &aop, FALSE);
1017
1018         if (options.stack10bit)
1019           {
1020             /* I'm not sure what to do here yet... */
1021             /* #STUB */
1022             fprintf (stderr,
1023                      "*** Warning: probably generating bad code for "
1024                      "10 bit stack mode.\n");
1025           }
1026
1027         if (stk)
1028           {
1029             emitcode ("mov", "a,_bp");
1030             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1031             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1032           }
1033         else
1034           {
1035             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1036           }
1037
1038         while (sz--)
1039           {
1040             emitcode ("pop", "acc");
1041             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1042             if (!sz)
1043               break;
1044             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1045           }
1046         op->aop = aop;
1047         freeAsmop (op, NULL, ic, TRUE);
1048         if (_G.r0Pushed)
1049           {
1050             emitcode ("pop", "ar0");
1051             _G.r0Pushed--;
1052           }
1053
1054         if (_G.r1Pushed)
1055           {
1056             emitcode ("pop", "ar1");
1057             _G.r1Pushed--;
1058           }
1059       }
1060     case AOP_DPTR2:
1061         if (_G.dptr1InUse) {
1062             emitcode ("pop","dpx1");
1063             emitcode ("pop","dph1");
1064             emitcode ("pop","dpl1");
1065         }
1066         break;
1067     case AOP_DPTR:
1068         if (_G.dptrInUse) {
1069             emitcode ("pop","dpx");
1070             emitcode ("pop","dph");
1071             emitcode ("pop","dpl");
1072         }
1073         break;
1074     }
1075 dealloc:
1076   /* all other cases just dealloc */
1077   if (op)
1078     {
1079       op->aop = NULL;
1080       if (IS_SYMOP (op))
1081         {
1082           OP_SYMBOL (op)->aop = NULL;
1083           /* if the symbol has a spill */
1084           if (SPIL_LOC (op))
1085             SPIL_LOC (op)->aop = NULL;
1086         }
1087     }
1088 }
1089
1090 #define DEFAULT_ACC_WARNING 0
1091 static int saveAccWarn = DEFAULT_ACC_WARNING;
1092
1093 /*-------------------------------------------------------------------*/
1094 /* aopGet - for fetching value of the aop                            */
1095 /*                                                                   */
1096 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1097 /* in the accumulator. Set it to the name of a free register         */
1098 /* if acc must be preserved; the register will be used to preserve   */
1099 /* acc temporarily and to return the result byte.                    */
1100 /*-------------------------------------------------------------------*/
1101
1102 static char *
1103 aopGet (asmop *aop,
1104         int   offset,
1105         bool  bit16,
1106         bool  dname,
1107         char  *saveAcc)
1108 {
1109   /* offset is greater than
1110      size then zero */
1111   if (offset > (aop->size - 1) &&
1112       aop->type != AOP_LIT)
1113     return zero;
1114
1115   /* depending on type */
1116   switch (aop->type)
1117     {
1118
1119     case AOP_R0:
1120     case AOP_R1:
1121       /* if we need to increment it */
1122       while (offset > aop->coff)
1123         {
1124           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1125           aop->coff++;
1126         }
1127
1128       while (offset < aop->coff)
1129         {
1130           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1131           aop->coff--;
1132         }
1133
1134       aop->coff = offset;
1135       if (aop->paged)
1136         {
1137           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1138           return (dname ? "acc" : "a");
1139         }
1140       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1141       return Safe_strdup(buffer);       
1142
1143     case AOP_DPTRn:
1144         assert(offset <= 3);
1145         return dptrn[aop->aopu.dptr][offset];
1146
1147     case AOP_DPTR:
1148     case AOP_DPTR2:
1149
1150       if (aop->type == AOP_DPTR2)
1151         {
1152           genSetDPTR (1);
1153         }
1154         
1155       if (saveAcc)
1156         {
1157             TR_AP("#1");
1158 //          if (aop->type != AOP_DPTR2)
1159 //          {
1160 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1161 //              emitcode(";", "spanky: saveAcc for DPTR");
1162 //          }
1163             
1164             emitcode ("xch", "a, %s", saveAcc);
1165         }
1166
1167       _flushLazyDPS ();
1168
1169       while (offset > aop->coff)
1170         {
1171           emitcode ("inc", "dptr");
1172           aop->coff++;
1173         }
1174
1175       while (offset < aop->coff)
1176         {
1177           emitcode ("lcall", "__decdptr");
1178           aop->coff--;
1179         }
1180
1181       aop->coff = offset;
1182       if (aop->code)
1183         {
1184           emitcode ("clr", "a");
1185           emitcode ("movc", "a,@a+dptr");
1186         }
1187       else
1188         {
1189           emitcode ("movx", "a,@dptr");
1190         }
1191
1192       if (aop->type == AOP_DPTR2)
1193         {
1194           genSetDPTR (0);
1195         }
1196         
1197         if (saveAcc)
1198         {
1199        TR_AP("#2");
1200               emitcode ("xch", "a, %s", saveAcc);
1201 //            if (strcmp(saveAcc, "_ap"))
1202 //            {
1203 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1204 //            }
1205                   
1206               return saveAcc;
1207         }
1208       return (dname ? "acc" : "a");
1209
1210     case AOP_IMMD:
1211       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1212       {
1213           SNPRINTF(buffer, sizeof(buffer), 
1214                    "%s",aop->aopu.aop_immd.aop_immd2);
1215       } 
1216       else if (bit16)
1217       {
1218          SNPRINTF(buffer, sizeof(buffer), 
1219                   "#%s", aop->aopu.aop_immd.aop_immd1);
1220       }
1221       else if (offset) 
1222       {
1223           switch (offset) {
1224           case 1:
1225               tsprintf(buffer, sizeof(buffer),
1226                        "#!his",aop->aopu.aop_immd.aop_immd1);
1227               break;
1228           case 2:
1229               tsprintf(buffer, sizeof(buffer), 
1230                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1231               break;
1232           case 3:
1233               tsprintf(buffer, sizeof(buffer),
1234                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1235               break;
1236           default: /* should not need this (just in case) */
1237               SNPRINTF (buffer, sizeof(buffer), 
1238                         "#(%s >> %d)",
1239                        aop->aopu.aop_immd.aop_immd1,
1240                        offset * 8);
1241           }
1242       }
1243       else
1244       {
1245         SNPRINTF (buffer, sizeof(buffer), 
1246                   "#%s", aop->aopu.aop_immd.aop_immd1);
1247       }
1248       return Safe_strdup(buffer);       
1249
1250     case AOP_DIR:
1251       if (offset)
1252       {
1253         SNPRINTF (buffer, sizeof(buffer),
1254                   "(%s + %d)",
1255                  aop->aopu.aop_dir,
1256                  offset);
1257       }
1258       else
1259       {
1260         SNPRINTF(buffer, sizeof(buffer), 
1261                  "%s", aop->aopu.aop_dir);
1262       }
1263
1264       return Safe_strdup(buffer);
1265
1266     case AOP_REG:
1267       if (dname)
1268         return aop->aopu.aop_reg[offset]->dname;
1269       else
1270         return aop->aopu.aop_reg[offset]->name;
1271
1272     case AOP_CRY:
1273       emitcode ("clr", "a");
1274       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1275       emitcode ("rlc", "a");
1276       return (dname ? "acc" : "a");
1277
1278     case AOP_ACC:
1279       if (!offset && dname)
1280         return "acc";
1281       return aop->aopu.aop_str[offset];
1282
1283     case AOP_LIT:
1284       return aopLiteral (aop->aopu.aop_lit, offset);
1285
1286     case AOP_STR:
1287       aop->coff = offset;
1288       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1289           dname)
1290         return "acc";
1291
1292       return aop->aopu.aop_str[offset];
1293
1294     }
1295
1296   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1297           "aopget got unsupported aop->type");
1298   exit (1);
1299     
1300   return NULL;  // not reached, but makes compiler happy.
1301 }
1302 /*-----------------------------------------------------------------*/
1303 /* aopPut - puts a string for a aop                                */
1304 /*-----------------------------------------------------------------*/
1305 static void
1306 aopPut (asmop * aop, char *s, int offset)
1307 {
1308   if (aop->size && offset > (aop->size - 1))
1309     {
1310       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1311               "aopPut got offset > aop->size");
1312       exit (1);
1313     }
1314
1315   /* will assign value to value */
1316   /* depending on where it is ofcourse */
1317   switch (aop->type)
1318     {
1319     case AOP_DIR:
1320         if (offset)
1321         {
1322             SNPRINTF (buffer, sizeof(buffer),
1323                       "(%s + %d)",
1324                       aop->aopu.aop_dir, offset);
1325         }
1326         else
1327         {
1328             SNPRINTF (buffer, sizeof(buffer), 
1329                      "%s", aop->aopu.aop_dir);
1330         }
1331         
1332
1333         if (strcmp (buffer, s))
1334         {
1335             emitcode ("mov", "%s,%s", buffer, s);
1336         }
1337       break;
1338
1339     case AOP_REG:
1340       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1341           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1342         {
1343           if (*s == '@' ||
1344               strcmp (s, "r0") == 0 ||
1345               strcmp (s, "r1") == 0 ||
1346               strcmp (s, "r2") == 0 ||
1347               strcmp (s, "r3") == 0 ||
1348               strcmp (s, "r4") == 0 ||
1349               strcmp (s, "r5") == 0 ||
1350               strcmp (s, "r6") == 0 ||
1351               strcmp (s, "r7") == 0)
1352             {
1353                 emitcode ("mov", "%s,%s",
1354                           aop->aopu.aop_reg[offset]->dname, s);
1355             }
1356             else
1357             {
1358                 emitcode ("mov", "%s,%s",
1359                           aop->aopu.aop_reg[offset]->name, s);
1360             }
1361         }
1362       break;
1363
1364     case AOP_DPTRn:
1365         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1366         break;
1367
1368     case AOP_DPTR:
1369     case AOP_DPTR2:
1370
1371       if (aop->type == AOP_DPTR2)
1372         {
1373           genSetDPTR (1);
1374         }
1375       _flushLazyDPS ();
1376
1377       if (aop->code)
1378         {
1379           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1380                   "aopPut writting to code space");
1381           exit (1);
1382         }
1383
1384       while (offset > aop->coff)
1385         {
1386           aop->coff++;
1387           emitcode ("inc", "dptr");
1388         }
1389
1390       while (offset < aop->coff)
1391         {
1392           aop->coff--;
1393           emitcode ("lcall", "__decdptr");
1394         }
1395
1396       aop->coff = offset;
1397
1398       /* if not in accumulater */
1399       MOVA (s);
1400
1401       emitcode ("movx", "@dptr,a");
1402
1403       if (aop->type == AOP_DPTR2)
1404         {
1405           genSetDPTR (0);
1406         }
1407       break;
1408
1409     case AOP_R0:
1410     case AOP_R1:
1411       while (offset > aop->coff)
1412         {
1413           aop->coff++;
1414           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1415         }
1416       while (offset < aop->coff)
1417         {
1418           aop->coff--;
1419           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1420         }
1421       aop->coff = offset;
1422
1423       if (aop->paged)
1424         {
1425           MOVA (s);
1426           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1427
1428         }
1429       else if (*s == '@')
1430         {
1431           MOVA (s);
1432           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1433         }
1434       else if (strcmp (s, "r0") == 0 ||
1435                strcmp (s, "r1") == 0 ||
1436                strcmp (s, "r2") == 0 ||
1437                strcmp (s, "r3") == 0 ||
1438                strcmp (s, "r4") == 0 ||
1439                strcmp (s, "r5") == 0 ||
1440                strcmp (s, "r6") == 0 ||
1441                strcmp (s, "r7") == 0)
1442         {
1443           char buff[10];
1444           SNPRINTF(buff, sizeof(buff), 
1445                    "a%s", s);
1446           emitcode ("mov", "@%s,%s",
1447                     aop->aopu.aop_ptr->name, buff);
1448         }
1449         else
1450         {
1451             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1452         }
1453       break;
1454
1455     case AOP_STK:
1456       if (strcmp (s, "a") == 0)
1457         emitcode ("push", "acc");
1458       else
1459         if (*s=='@') {
1460           MOVA(s);
1461           emitcode ("push", "acc");
1462         } else {
1463           emitcode ("push", s);
1464         }
1465
1466       break;
1467
1468     case AOP_CRY:
1469       /* if bit variable */
1470       if (!aop->aopu.aop_dir)
1471         {
1472           emitcode ("clr", "a");
1473           emitcode ("rlc", "a");
1474         }
1475       else
1476         {
1477           if (s == zero)
1478             emitcode ("clr", "%s", aop->aopu.aop_dir);
1479           else if (s == one)
1480             emitcode ("setb", "%s", aop->aopu.aop_dir);
1481           else if (!strcmp (s, "c"))
1482             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1483           else
1484             {
1485               if (strcmp (s, "a"))
1486                 {
1487                   MOVA (s);
1488                 }
1489               {
1490                 /* set C, if a >= 1 */
1491                 emitcode ("add", "a,#!constbyte",0xff);
1492                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1493               }
1494             }
1495         }
1496       break;
1497
1498     case AOP_STR:
1499       aop->coff = offset;
1500       if (strcmp (aop->aopu.aop_str[offset], s))
1501         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1502       break;
1503
1504     case AOP_ACC:
1505       aop->coff = offset;
1506       if (!offset && (strcmp (s, "acc") == 0))
1507         break;
1508
1509       if (strcmp (aop->aopu.aop_str[offset], s))
1510         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1511       break;
1512
1513     default:
1514       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1515               "aopPut got unsupported aop->type");
1516       exit (1);
1517     }
1518
1519 }
1520
1521
1522 /*--------------------------------------------------------------------*/
1523 /* reAdjustPreg - points a register back to where it should (coff==0) */
1524 /*--------------------------------------------------------------------*/
1525 static void
1526 reAdjustPreg (asmop * aop)
1527 {
1528   if ((aop->coff==0) || (aop->size <= 1)) {
1529     return;
1530   }
1531
1532   switch (aop->type)
1533     {
1534     case AOP_R0:
1535     case AOP_R1:
1536       while (aop->coff--)
1537         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1538       break;
1539     case AOP_DPTR:
1540     case AOP_DPTR2:
1541       if (aop->type == AOP_DPTR2)
1542         {
1543           genSetDPTR (1);
1544           _flushLazyDPS ();
1545         }
1546       while (aop->coff--)
1547         {
1548           emitcode ("lcall", "__decdptr");
1549         }
1550
1551       if (aop->type == AOP_DPTR2)
1552         {
1553           genSetDPTR (0);
1554         }
1555       break;
1556
1557     }
1558   aop->coff=0;
1559 }
1560
1561 #define AOP(op) op->aop
1562 #define AOP_TYPE(op) AOP(op)->type
1563 #define AOP_SIZE(op) AOP(op)->size
1564 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1565                        AOP_TYPE(x) == AOP_R0))
1566
1567 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1568                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1569                          AOP(x)->paged))
1570
1571 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1572                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1573                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1574 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1575 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1576 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1577
1578 // The following two macros can be used even if the aop has not yet been aopOp'd.
1579 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1580 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1581
1582 /* Workaround for DS80C390 bug: div ab may return bogus results
1583  * if A is accessed in instruction immediately before the div.
1584  *
1585  * Will be fixed in B4 rev of processor, Dallas claims.
1586  */
1587
1588 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1589     if (!AOP_NEEDSACC(RIGHT))         \
1590     {               \
1591       /* We can load A first, then B, since     \
1592        * B (the RIGHT operand) won't clobber A,   \
1593        * thus avoiding touching A right before the div. \
1594        */             \
1595       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1596       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1597       MOVA(L);            \
1598       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1599       MOVB(L); \
1600     }               \
1601     else              \
1602     {               \
1603       /* Just stuff in a nop after loading A. */    \
1604       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1605       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1606       MOVA(L);            \
1607       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1608     }
1609
1610 /*-----------------------------------------------------------------*/
1611 /* genNotFloat - generates not for float operations              */
1612 /*-----------------------------------------------------------------*/
1613 static void
1614 genNotFloat (operand * op, operand * res)
1615 {
1616   int size, offset;
1617   symbol *tlbl;
1618
1619   D (emitcode (";", "genNotFloat "););
1620
1621   /* we will put 127 in the first byte of
1622      the result */
1623   aopPut (AOP (res), "#127", 0);
1624   size = AOP_SIZE (op) - 1;
1625   offset = 1;
1626
1627   _startLazyDPSEvaluation ();
1628   MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL));
1629
1630   while (size--)
1631     {
1632       emitcode ("orl", "a,%s",
1633                 aopGet (op->aop,
1634                         offset++, FALSE, FALSE,
1635                         DP2_RESULT_REG));
1636     }
1637   _endLazyDPSEvaluation ();
1638
1639   tlbl = newiTempLabel (NULL);
1640   aopPut (res->aop, one, 1);
1641   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1642   aopPut (res->aop, zero, 1);
1643   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1644
1645   size = res->aop->size - 2;
1646   offset = 2;
1647   /* put zeros in the rest */
1648   while (size--)
1649     aopPut (res->aop, zero, offset++);
1650 }
1651
1652 /*-----------------------------------------------------------------*/
1653 /* opIsGptr: returns non-zero if the passed operand is       */
1654 /* a generic pointer type.             */
1655 /*-----------------------------------------------------------------*/
1656 static int
1657 opIsGptr (operand * op)
1658 {
1659   sym_link *type = operandType (op);
1660
1661   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1662     {
1663       return 1;
1664     }
1665   return 0;
1666 }
1667
1668 /*-----------------------------------------------------------------*/
1669 /* getDataSize - get the operand data size                         */
1670 /*-----------------------------------------------------------------*/
1671 static int
1672 getDataSize (operand * op)
1673 {
1674   int size;
1675   size = AOP_SIZE (op);
1676   if (size == GPTRSIZE)
1677     {
1678       sym_link *type = operandType (op);
1679       if (IS_GENPTR (type))
1680         {
1681           /* generic pointer; arithmetic operations
1682            * should ignore the high byte (pointer type).
1683            */
1684           size--;
1685         }
1686     }
1687   return size;
1688 }
1689
1690 /*-----------------------------------------------------------------*/
1691 /* outAcc - output Acc                                             */
1692 /*-----------------------------------------------------------------*/
1693 static void
1694 outAcc (operand * result)
1695 {
1696   int size, offset;
1697   size = getDataSize (result);
1698   if (size)
1699     {
1700       aopPut (AOP (result), "a", 0);
1701       size--;
1702       offset = 1;
1703       /* unsigned or positive */
1704       while (size--)
1705         {
1706           aopPut (AOP (result), zero, offset++);
1707         }
1708     }
1709 }
1710
1711 /*-----------------------------------------------------------------*/
1712 /* outBitC - output a bit C                                        */
1713 /*-----------------------------------------------------------------*/
1714 static void
1715 outBitC (operand * result)
1716 {
1717   /* if the result is bit */
1718   if (AOP_TYPE (result) == AOP_CRY)
1719     {
1720       aopPut (AOP (result), "c", 0);
1721     }
1722   else
1723     {
1724       emitcode ("clr", "a");
1725       emitcode ("rlc", "a");
1726       outAcc (result);
1727     }
1728 }
1729
1730 /*-----------------------------------------------------------------*/
1731 /* toBoolean - emit code for orl a,operator(sizeop)                */
1732 /*-----------------------------------------------------------------*/
1733 static void
1734 toBoolean (operand * oper)
1735 {
1736   int   size = AOP_SIZE (oper) - 1;
1737   int   offset = 1;
1738   bool usedB = FALSE;
1739
1740   /* The generic part of a generic pointer should
1741    * not participate in it's truth value.
1742    *
1743    * i.e. 0x10000000 is zero.
1744    */
1745   if (opIsGptr (oper))
1746     {
1747       D (emitcode (";", "toBoolean: generic ptr special case."););
1748       size--;
1749     }
1750
1751   _startLazyDPSEvaluation ();
1752   if (AOP_NEEDSACC (oper) && size)
1753     {
1754       usedB = TRUE;
1755       if (_G.bInUse)
1756       {
1757           emitcode ("push", "b");
1758       }
1759       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1760     }
1761   else
1762     {
1763       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1764     }
1765     
1766   while (size--)
1767     {
1768       if (usedB)
1769         {
1770           emitcode ("orl", "b,%s",
1771                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1772         }
1773       else
1774         {
1775           emitcode ("orl", "a,%s",
1776                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1777         }
1778     }
1779   _endLazyDPSEvaluation ();
1780
1781   if (usedB)
1782     {
1783       emitcode ("mov", "a,b");
1784       if (_G.bInUse)
1785       {
1786           emitcode ("pop", "b");
1787       }
1788         
1789     }
1790 }
1791
1792
1793 /*-----------------------------------------------------------------*/
1794 /* genNot - generate code for ! operation                          */
1795 /*-----------------------------------------------------------------*/
1796 static void
1797 genNot (iCode * ic)
1798 {
1799   symbol *tlbl;
1800   sym_link *optype = operandType (IC_LEFT (ic));
1801
1802   D (emitcode (";", "genNot "););
1803
1804   /* assign asmOps to operand & result */
1805   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1806   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1807
1808   /* if in bit space then a special case */
1809   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1810     {
1811       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1812       emitcode ("cpl", "c");
1813       outBitC (IC_RESULT (ic));
1814       goto release;
1815     }
1816
1817   /* if type float then do float */
1818   if (IS_FLOAT (optype))
1819     {
1820       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1821       goto release;
1822     }
1823
1824   toBoolean (IC_LEFT (ic));
1825
1826   tlbl = newiTempLabel (NULL);
1827   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1828   emitcode ("", "!tlabeldef", tlbl->key + 100);
1829   outBitC (IC_RESULT (ic));
1830
1831 release:
1832   /* release the aops */
1833   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1834   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1835 }
1836
1837
1838 /*-----------------------------------------------------------------*/
1839 /* genCpl - generate code for complement                           */
1840 /*-----------------------------------------------------------------*/
1841 static void
1842 genCpl (iCode * ic)
1843 {
1844   int offset = 0;
1845   int size;
1846   symbol *tlbl;
1847
1848   D (emitcode (";", "genCpl "););
1849
1850
1851   /* assign asmOps to operand & result */
1852   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1853   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1854
1855   /* special case if in bit space */
1856   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1857     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1858       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1859       emitcode ("cpl", "c");
1860       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1861       goto release;
1862     }
1863     tlbl=newiTempLabel(NULL);
1864     emitcode ("cjne", "%s,#0x01,%05d$", 
1865               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1866     emitcode ("", "%05d$:", tlbl->key+100);
1867     outBitC (IC_RESULT(ic));
1868     goto release;
1869   }
1870
1871   size = AOP_SIZE (IC_RESULT (ic));
1872   _startLazyDPSEvaluation ();
1873   while (size--)
1874     {
1875       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1876       emitcode ("cpl", "a");
1877       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1878     }
1879   _endLazyDPSEvaluation ();
1880
1881
1882 release:
1883   /* release the aops */
1884   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1885   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1886 }
1887
1888 /*-----------------------------------------------------------------*/
1889 /* genUminusFloat - unary minus for floating points                */
1890 /*-----------------------------------------------------------------*/
1891 static void
1892 genUminusFloat (operand * op, operand * result)
1893 {
1894   int size, offset = 0;
1895     
1896   D(emitcode (";", "genUminusFloat"););
1897   
1898   /* for this we just copy and then flip the bit */
1899     
1900   _startLazyDPSEvaluation ();
1901   size = AOP_SIZE (op) - 1;
1902
1903   while (size--)
1904   {
1905       aopPut (AOP (result),
1906               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1907               offset);
1908       offset++;
1909     }
1910   
1911   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1912
1913   emitcode ("cpl", "acc.7");
1914   aopPut (AOP (result), "a", offset);    
1915   _endLazyDPSEvaluation ();
1916 }
1917
1918 /*-----------------------------------------------------------------*/
1919 /* genUminus - unary minus code generation                         */
1920 /*-----------------------------------------------------------------*/
1921 static void
1922 genUminus (iCode * ic)
1923 {
1924   int offset, size;
1925   sym_link *optype;
1926
1927   D (emitcode (";", "genUminus "););
1928
1929   /* assign asmops */
1930   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1931   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1932
1933   /* if both in bit space then special
1934      case */
1935   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1936       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1937     {
1938
1939       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1940       emitcode ("cpl", "c");
1941       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1942       goto release;
1943     }
1944
1945   optype = operandType (IC_LEFT (ic));
1946
1947   /* if float then do float stuff */
1948   if (IS_FLOAT (optype))
1949     {
1950       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1951       goto release;
1952     }
1953
1954   /* otherwise subtract from zero */
1955   size = AOP_SIZE (IC_LEFT (ic));
1956   offset = 0;
1957   _startLazyDPSEvaluation ();
1958   while (size--)
1959     {
1960       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1961       if (!strcmp (l, "a"))
1962         {
1963           if (offset == 0)
1964             SETC;
1965           emitcode ("cpl", "a");
1966           emitcode ("addc", "a,#0");
1967         }
1968       else
1969         {
1970           if (offset == 0)
1971             CLRC;
1972           emitcode ("clr", "a");
1973           emitcode ("subb", "a,%s", l);
1974         }
1975       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1976     }
1977   _endLazyDPSEvaluation ();
1978
1979   /* if any remaining bytes in the result */
1980   /* we just need to propagate the sign   */
1981   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1982     {
1983       emitcode ("rlc", "a");
1984       emitcode ("subb", "a,acc");
1985       while (size--)
1986         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1987     }
1988
1989 release:
1990   /* release the aops */
1991   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1992   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1993 }
1994
1995 /*-----------------------------------------------------------------*/
1996 /* savermask - saves registers in the mask                         */
1997 /*-----------------------------------------------------------------*/
1998 static void savermask(bitVect *rs_mask)
1999 {
2000     int i;
2001     if (options.useXstack) {
2002         if (bitVectBitValue (rs_mask, R0_IDX))
2003             emitcode ("mov", "b,r0");
2004         emitcode ("mov", "r0,%s", spname);
2005         for (i = 0; i < ds390_nRegs; i++) {
2006             if (bitVectBitValue (rs_mask, i)) {
2007                 if (i == R0_IDX)
2008                     emitcode ("mov", "a,b");
2009                 else
2010                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2011                 emitcode ("movx", "@r0,a");
2012                 emitcode ("inc", "r0");
2013             }
2014         }
2015         emitcode ("mov", "%s,r0", spname);
2016         if (bitVectBitValue (rs_mask, R0_IDX))
2017             emitcode ("mov", "r0,b");
2018     } else {
2019         for (i = 0; i < ds390_nRegs; i++) {
2020             if (bitVectBitValue (rs_mask, i))
2021                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2022         }
2023     }
2024 }
2025
2026 /*-----------------------------------------------------------------*/
2027 /* saveRegisters - will look for a call and save the registers     */
2028 /*-----------------------------------------------------------------*/
2029 static void
2030 saveRegisters (iCode * lic)
2031 {
2032   iCode *ic;
2033   bitVect *rsave;
2034
2035   /* look for call */
2036   for (ic = lic; ic; ic = ic->next)
2037     if (ic->op == CALL || ic->op == PCALL)
2038       break;
2039
2040   if (!ic)
2041     {
2042       fprintf (stderr, "found parameter push with no function call\n");
2043       return;
2044     }
2045
2046   /* if the registers have been saved already then
2047      do nothing */
2048   if (ic->regsSaved 
2049       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2050     return ;
2051
2052   /* special case if DPTR alive across a function call then must save it 
2053      even though callee saves */
2054   if (IS_SYMOP(IC_LEFT(ic)) &&
2055       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2056       int i;
2057       rsave = newBitVect(ic->rMask->size);
2058       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2059           if (bitVectBitValue(ic->rMask,i))
2060               rsave = bitVectSetBit(rsave,i);
2061       }
2062       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2063   } else {
2064     /* safe the registers in use at this time but skip the
2065        ones for the result */
2066     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2067                            ds390_rUmaskForOp (IC_RESULT(ic)));
2068   }
2069   ic->regsSaved = 1;
2070   savermask(rsave);
2071 }
2072
2073 /*-----------------------------------------------------------------*/
2074 /* usavermask - restore registers with mask                        */
2075 /*-----------------------------------------------------------------*/
2076 static void unsavermask(bitVect *rs_mask)
2077 {
2078     int i;
2079     if (options.useXstack) {
2080         emitcode ("mov", "r0,%s", spname);
2081         for (i = ds390_nRegs; i >= 0; i--) {
2082             if (bitVectBitValue (rs_mask, i)) {
2083                 emitcode ("dec", "r0");
2084                 emitcode ("movx", "a,@r0");
2085                 if (i == R0_IDX)
2086                     emitcode ("mov", "b,a");
2087                 else
2088                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2089             }       
2090         }
2091         emitcode ("mov", "%s,r0", spname);
2092         if (bitVectBitValue (rs_mask, R0_IDX))
2093             emitcode ("mov", "r0,b");
2094     } else {
2095         for (i = ds390_nRegs; i >= 0; i--) {
2096             if (bitVectBitValue (rs_mask, i))
2097                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2098         }
2099     }
2100 }
2101
2102 /*-----------------------------------------------------------------*/
2103 /* unsaveRegisters - pop the pushed registers                      */
2104 /*-----------------------------------------------------------------*/
2105 static void
2106 unsaveRegisters (iCode * ic)
2107 {
2108   bitVect *rsave;
2109
2110   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2111       int i;
2112       rsave = newBitVect(ic->rMask->size);
2113       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2114           if (bitVectBitValue(ic->rMask,i))
2115               rsave = bitVectSetBit(rsave,i);
2116       }
2117       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2118   } else {
2119     /* restore the registers in use at this time but skip the
2120        ones for the result */
2121     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2122                            ds390_rUmaskForOp (IC_RESULT(ic)));
2123   }
2124   unsavermask(rsave);
2125 }
2126
2127
2128 /*-----------------------------------------------------------------*/
2129 /* pushSide -                */
2130 /*-----------------------------------------------------------------*/
2131 static void
2132 pushSide (operand * oper, int size)
2133 {
2134   int offset = 0;
2135   _startLazyDPSEvaluation ();
2136   while (size--)
2137     {
2138       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2139       if (AOP_TYPE (oper) != AOP_REG &&
2140           AOP_TYPE (oper) != AOP_DIR &&
2141           strcmp (l, "a"))
2142         {
2143           emitcode ("mov", "a,%s", l);
2144           emitcode ("push", "acc");
2145         }
2146       else
2147         emitcode ("push", "%s", l);
2148     }
2149   _endLazyDPSEvaluation ();
2150 }
2151
2152 /*-----------------------------------------------------------------*/
2153 /* assignResultValue -               */
2154 /*-----------------------------------------------------------------*/
2155 static void
2156 assignResultValue (operand * oper)
2157 {
2158   int offset = 0;
2159   int size = AOP_SIZE (oper);
2160   bool pushedAcc = FALSE;
2161
2162   if (size == fReturnSizeDS390)
2163   {
2164       /* I don't think this case can ever happen... */
2165       /* ACC is the last part of this. If writing the result
2166        * uses AC, we must preserve it.
2167        */
2168       if (AOP_NEEDSACC(oper))
2169       {
2170           emitcode(";", "assignResultValue special case for ACC.");
2171           emitcode("push", "acc");
2172           pushedAcc = TRUE;
2173           size--;
2174       }
2175   }
2176     
2177     
2178   _startLazyDPSEvaluation ();
2179   while (size--)
2180     {
2181       aopPut (AOP (oper), fReturn[offset], offset);
2182       offset++;
2183     }
2184   _endLazyDPSEvaluation ();
2185     
2186   if (pushedAcc)
2187     {
2188         emitcode("pop", "acc");
2189         aopPut(AOP(oper), "a", offset);
2190     }
2191 }
2192
2193
2194 /*-----------------------------------------------------------------*/
2195 /* genXpush - pushes onto the external stack                       */
2196 /*-----------------------------------------------------------------*/
2197 static void
2198 genXpush (iCode * ic)
2199 {
2200   asmop *aop = newAsmop (0);
2201   regs *r;
2202   int size, offset = 0;
2203
2204   D (emitcode (";", "genXpush ");
2205     );
2206
2207   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2208   r = getFreePtr (ic, &aop, FALSE);
2209
2210
2211   emitcode ("mov", "%s,_spx", r->name);
2212
2213   size = AOP_SIZE (IC_LEFT (ic));
2214   _startLazyDPSEvaluation ();
2215   while (size--)
2216     {
2217
2218       MOVA (aopGet (AOP (IC_LEFT (ic)),
2219                         offset++, FALSE, FALSE, NULL));
2220       emitcode ("movx", "@%s,a", r->name);
2221       emitcode ("inc", "%s", r->name);
2222
2223     }
2224   _endLazyDPSEvaluation ();
2225
2226
2227   emitcode ("mov", "_spx,%s", r->name);
2228
2229   freeAsmop (NULL, aop, ic, TRUE);
2230   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2231 }
2232
2233 /*-----------------------------------------------------------------*/
2234 /* genIpush - generate code for pushing this gets a little complex  */
2235 /*-----------------------------------------------------------------*/
2236 static void
2237 genIpush (iCode * ic)
2238 {
2239   int size, offset = 0;
2240   char *l;
2241
2242   D (emitcode (";", "genIpush ");
2243     );
2244
2245   /* if this is not a parm push : ie. it is spill push
2246      and spill push is always done on the local stack */
2247   if (!ic->parmPush)
2248     {
2249
2250       /* and the item is spilt then do nothing */
2251       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2252         return;
2253
2254       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2255       size = AOP_SIZE (IC_LEFT (ic));
2256       /* push it on the stack */
2257       _startLazyDPSEvaluation ();
2258       while (size--)
2259         {
2260           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2261           if (*l == '#')
2262             {
2263               MOVA (l);
2264               l = "acc";
2265             }
2266           emitcode ("push", "%s", l);
2267         }
2268       _endLazyDPSEvaluation ();
2269       return;
2270     }
2271
2272   /* this is a paramter push: in this case we call
2273      the routine to find the call and save those
2274      registers that need to be saved */
2275   saveRegisters (ic);
2276
2277   /* if use external stack then call the external
2278      stack pushing routine */
2279   if (options.useXstack)
2280     {
2281       genXpush (ic);
2282       return;
2283     }
2284
2285   /* then do the push */
2286   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2287
2288   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2289   size = AOP_SIZE (IC_LEFT (ic));
2290
2291   _startLazyDPSEvaluation ();
2292   while (size--)
2293     {
2294       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2295       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2296           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2297           strcmp (l, "acc"))
2298         {
2299           emitcode ("mov", "a,%s", l);
2300           emitcode ("push", "acc");
2301         }
2302       else
2303         {
2304             emitcode ("push", "%s", l);
2305         }
2306     }
2307   _endLazyDPSEvaluation ();
2308
2309   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2310 }
2311
2312 /*-----------------------------------------------------------------*/
2313 /* genIpop - recover the registers: can happen only for spilling   */
2314 /*-----------------------------------------------------------------*/
2315 static void
2316 genIpop (iCode * ic)
2317 {
2318   int size, offset;
2319
2320   D (emitcode (";", "genIpop ");
2321     );
2322
2323
2324   /* if the temp was not pushed then */
2325   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2326     return;
2327
2328   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2329   size = AOP_SIZE (IC_LEFT (ic));
2330   offset = (size - 1);
2331   _startLazyDPSEvaluation ();
2332   while (size--)
2333     {
2334       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2335                                      FALSE, TRUE, NULL));
2336     }
2337   _endLazyDPSEvaluation ();
2338
2339   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2340 }
2341
2342 /*-----------------------------------------------------------------*/
2343 /* unsaveRBank - restores the resgister bank from stack            */
2344 /*-----------------------------------------------------------------*/
2345 static void
2346 unsaveRBank (int bank, iCode * ic, bool popPsw)
2347 {
2348   int i;
2349   asmop *aop = NULL;
2350   regs *r = NULL;
2351
2352   if (options.useXstack)
2353   {
2354       if (!ic)
2355       {
2356           /* Assume r0 is available for use. */
2357           r = ds390_regWithIdx (R0_IDX);;          
2358       } 
2359       else
2360       {
2361           aop = newAsmop (0);
2362           r = getFreePtr (ic, &aop, FALSE);
2363       }
2364       emitcode ("mov", "%s,_spx", r->name);      
2365   }
2366   
2367   if (popPsw)
2368     {
2369       if (options.useXstack)
2370       {
2371           emitcode ("movx", "a,@%s", r->name);
2372           emitcode ("mov", "psw,a");
2373           emitcode ("dec", "%s", r->name);
2374         }
2375       else
2376       {
2377         emitcode ("pop", "psw");
2378       }
2379     }
2380
2381   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2382     {
2383       if (options.useXstack)
2384         {
2385           emitcode ("movx", "a,@%s", r->name);
2386           emitcode ("mov", "(%s+%d),a",
2387                     regs390[i].base, 8 * bank + regs390[i].offset);
2388           emitcode ("dec", "%s", r->name);
2389
2390         }
2391       else
2392         emitcode ("pop", "(%s+%d)",
2393                   regs390[i].base, 8 * bank + regs390[i].offset);
2394     }
2395
2396   if (options.useXstack)
2397     {
2398       emitcode ("mov", "_spx,%s", r->name);
2399     }
2400     
2401   if (aop)
2402   {
2403       freeAsmop (NULL, aop, ic, TRUE);  
2404   }    
2405 }
2406
2407 /*-----------------------------------------------------------------*/
2408 /* saveRBank - saves an entire register bank on the stack          */
2409 /*-----------------------------------------------------------------*/
2410 static void
2411 saveRBank (int bank, iCode * ic, bool pushPsw)
2412 {
2413   int i;
2414   asmop *aop = NULL;
2415   regs *r = NULL;
2416
2417   if (options.useXstack)
2418     {
2419         if (!ic)
2420         {
2421           /* Assume r0 is available for use. */
2422                   r = ds390_regWithIdx (R0_IDX);;
2423         }
2424         else
2425         {
2426           aop = newAsmop (0);
2427           r = getFreePtr (ic, &aop, FALSE);
2428         }
2429         emitcode ("mov", "%s,_spx", r->name);    
2430     }
2431
2432   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2433     {
2434       if (options.useXstack)
2435         {
2436           emitcode ("inc", "%s", r->name);
2437           emitcode ("mov", "a,(%s+%d)",
2438                     regs390[i].base, 8 * bank + regs390[i].offset);
2439           emitcode ("movx", "@%s,a", r->name);
2440         }
2441       else
2442         emitcode ("push", "(%s+%d)",
2443                   regs390[i].base, 8 * bank + regs390[i].offset);
2444     }
2445
2446   if (pushPsw)
2447     {
2448       if (options.useXstack)
2449         {
2450           emitcode ("mov", "a,psw");
2451           emitcode ("movx", "@%s,a", r->name);
2452           emitcode ("inc", "%s", r->name);
2453           emitcode ("mov", "_spx,%s", r->name);
2454         }
2455       else
2456       {
2457         emitcode ("push", "psw");
2458       }
2459
2460       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2461     }
2462   
2463   if (aop)
2464   {
2465        freeAsmop (NULL, aop, ic, TRUE);
2466   }    
2467     
2468   if (ic)
2469   {  
2470       ic->bankSaved = 1;
2471   }
2472 }
2473
2474 /*-----------------------------------------------------------------*/
2475 /* genSend - gen code for SEND                                     */
2476 /*-----------------------------------------------------------------*/
2477 static void genSend(set *sendSet)
2478 {
2479     iCode *sic;
2480     int sendCount = 0 ;
2481     static int rb1_count = 0;
2482
2483     for (sic = setFirstItem (sendSet); sic;
2484          sic = setNextItem (sendSet)) {     
2485         int size, offset = 0;
2486         
2487         size=getSize(operandType(IC_LEFT(sic)));
2488         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2489         if (sendCount == 0) { /* first parameter */
2490             // we know that dpl(hxb) is the result, so
2491             rb1_count = 0 ;
2492             _startLazyDPSEvaluation ();
2493             if (size>1) {
2494                 aopOp (IC_LEFT (sic), sic, FALSE, 
2495                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2496             } else {
2497                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2498             }
2499             while (size--) {
2500                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2501                                   FALSE, FALSE, NULL);
2502                 if (strcmp (l, fReturn[offset])) {
2503                     emitcode ("mov", "%s,%s",
2504                               fReturn[offset],
2505                               l);
2506                 }
2507                 offset++;
2508             }
2509             _endLazyDPSEvaluation ();
2510             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2511             rb1_count =0;
2512         } else { /* if more parameter in registers */
2513             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2514             while (size--) {
2515                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2516                                                                 FALSE, FALSE, NULL));
2517             }
2518             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2519         }
2520         sendCount++;
2521     }
2522 }
2523
2524 static void
2525 adjustEsp(const char *reg)
2526 {
2527     emitcode ("anl","%s,#3", reg);
2528     if (TARGET_IS_DS400)
2529     {
2530         emitcode ("orl","%s,#!constbyte",
2531                   reg,
2532                   (options.stack_loc >> 8) & 0xff);
2533     }
2534 }
2535
2536 /*-----------------------------------------------------------------*/
2537 /* genCall - generates a call statement                            */
2538 /*-----------------------------------------------------------------*/
2539 static void
2540 genCall (iCode * ic)
2541 {
2542   sym_link *dtype;
2543   bool restoreBank = FALSE;
2544   bool swapBanks = FALSE;
2545
2546   D (emitcode (";", "genCall "););
2547
2548   /* if we are calling a not _naked function that is not using
2549      the same register bank then we need to save the
2550      destination registers on the stack */
2551   dtype = operandType (IC_LEFT (ic));
2552   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2553       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2554       IFFUNC_ISISR (currFunc->type))
2555   {
2556       if (!ic->bankSaved) 
2557       {
2558            /* This is unexpected; the bank should have been saved in
2559             * genFunction.
2560             */
2561            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2562            restoreBank = TRUE;
2563       }
2564       swapBanks = TRUE;
2565   }
2566   
2567     /* if caller saves & we have not saved then */
2568     if (!ic->regsSaved)
2569       saveRegisters (ic);
2570   
2571   /* if send set is not empty the assign */
2572   /* We've saved all the registers we care about;
2573   * therefore, we may clobber any register not used
2574   * in the calling convention (i.e. anything not in
2575   * fReturn.
2576   */
2577   if (_G.sendSet)
2578     {
2579         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2580             genSend(reverseSet(_G.sendSet));
2581         } else {
2582             genSend(_G.sendSet);
2583         }
2584       _G.sendSet = NULL;
2585     }  
2586     
2587   if (swapBanks)
2588   {
2589         emitcode ("mov", "psw,#!constbyte", 
2590            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2591   }
2592
2593   /* make the call */
2594   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2595                             OP_SYMBOL (IC_LEFT (ic))->rname :
2596                             OP_SYMBOL (IC_LEFT (ic))->name));
2597
2598   if (swapBanks)
2599   {
2600        emitcode ("mov", "psw,#!constbyte", 
2601           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2602   }
2603
2604   /* if we need assign a result value */
2605   if ((IS_ITEMP (IC_RESULT (ic)) &&
2606        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2607         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2608         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2609       IS_TRUE_SYMOP (IC_RESULT (ic)))
2610     {
2611       if (isOperandInFarSpace (IC_RESULT (ic))
2612           && getSize (operandType (IC_RESULT (ic))) <= 2)
2613         {
2614           int size = getSize (operandType (IC_RESULT (ic)));
2615
2616           /* Special case for 1 or 2 byte return in far space. */
2617           MOVA (fReturn[0]);
2618           if (size > 1)
2619             {
2620               emitcode ("mov", "b,%s", fReturn[1]);
2621             }
2622
2623           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2624           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2625
2626           if (size > 1)
2627             {
2628               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2629             }
2630           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2631         }
2632       else
2633         {
2634           _G.accInUse++;
2635           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2636           _G.accInUse--;
2637
2638           assignResultValue (IC_RESULT (ic));
2639
2640           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2641         }
2642     }
2643
2644   /* adjust the stack for parameters if
2645      required */
2646   if (ic->parmBytes) {
2647       int i;
2648       if (options.stack10bit) {
2649           if (ic->parmBytes <= 10) {
2650               emitcode(";","stack adjustment for parms");
2651               for (i=0; i < ic->parmBytes ; i++) {
2652                   emitcode("pop","acc");
2653               }
2654           } else {            
2655               PROTECT_SP;
2656               emitcode ("clr","c");
2657               emitcode ("mov","a,sp");
2658               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2659               emitcode ("mov","sp,a");
2660               emitcode ("mov","a,esp");
2661               adjustEsp("a");
2662               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2663               emitcode ("mov","esp,a");   
2664               UNPROTECT_SP;
2665           }
2666       } else {
2667           if (ic->parmBytes > 3) {
2668               emitcode ("mov", "a,%s", spname);
2669               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2670               emitcode ("mov", "%s,a", spname);
2671           } else
2672               for (i = 0; i < ic->parmBytes; i++)
2673                   emitcode ("dec", "%s", spname);
2674       }
2675   }
2676
2677   /* if we hade saved some registers then unsave them */
2678   if (ic->regsSaved)
2679     unsaveRegisters (ic);
2680
2681   /* if register bank was saved then pop them */
2682   if (restoreBank)
2683     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2684 }
2685
2686 /*-----------------------------------------------------------------*/
2687 /* genPcall - generates a call by pointer statement                */
2688 /*-----------------------------------------------------------------*/
2689 static void
2690 genPcall (iCode * ic)
2691 {
2692   sym_link *dtype;
2693   symbol *rlbl = newiTempLabel (NULL);
2694   bool restoreBank=FALSE;
2695
2696   D (emitcode (";", "genPcall ");
2697     );
2698
2699
2700   /* if caller saves & we have not saved then */
2701   if (!ic->regsSaved)
2702     saveRegisters (ic);
2703
2704   /* if we are calling a function that is not using
2705      the same register bank then we need to save the
2706      destination registers on the stack */
2707   dtype = operandType (IC_LEFT (ic));
2708   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2709       IFFUNC_ISISR (currFunc->type) &&
2710       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2711     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2712     restoreBank=TRUE;
2713   }
2714
2715   /* push the return address on to the stack */
2716   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2717   emitcode ("push", "acc");
2718   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2719   emitcode ("push", "acc");
2720
2721   if (options.model == MODEL_FLAT24)
2722     {
2723       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2724       emitcode ("push", "acc");
2725     }
2726
2727   /* now push the calling address */
2728   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2729
2730   pushSide (IC_LEFT (ic), FPTRSIZE);
2731
2732   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2733
2734   /* if send set is not empty the assign */
2735   if (_G.sendSet)
2736     {
2737         genSend(reverseSet(_G.sendSet));
2738         _G.sendSet = NULL;
2739     }
2740
2741   emitcode ("ret", "");
2742   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2743
2744
2745   /* if we need assign a result value */
2746   if ((IS_ITEMP (IC_RESULT (ic)) &&
2747        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2748         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2749       IS_TRUE_SYMOP (IC_RESULT (ic)))
2750     {
2751
2752       _G.accInUse++;
2753       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2754       _G.accInUse--;
2755
2756       assignResultValue (IC_RESULT (ic));
2757
2758       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2759     }
2760
2761   /* adjust the stack for parameters if
2762      required */
2763   if (ic->parmBytes)
2764     {
2765       int i;
2766       if (options.stack10bit) {
2767           if (ic->parmBytes <= 10) {
2768               emitcode(";","stack adjustment for parms");
2769               for (i=0; i < ic->parmBytes ; i++) {
2770                   emitcode("pop","acc");
2771               }
2772           } else {            
2773               PROTECT_SP;
2774               emitcode ("clr","c");
2775               emitcode ("mov","a,sp");
2776               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2777               emitcode ("mov","sp,a");
2778               emitcode ("mov","a,esp");
2779               adjustEsp("a");
2780               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2781               emitcode ("mov","esp,a");   
2782               UNPROTECT_SP;
2783           }
2784       } else {
2785           if (ic->parmBytes > 3) {
2786               emitcode ("mov", "a,%s", spname);
2787               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2788               emitcode ("mov", "%s,a", spname);
2789           }
2790           else
2791               for (i = 0; i < ic->parmBytes; i++)
2792                   emitcode ("dec", "%s", spname);
2793           
2794       }
2795     }
2796   /* if register bank was saved then unsave them */
2797   if (restoreBank)
2798     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2799   
2800   /* if we hade saved some registers then
2801      unsave them */
2802   if (ic->regsSaved)
2803     unsaveRegisters (ic);
2804
2805 }
2806
2807 /*-----------------------------------------------------------------*/
2808 /* resultRemat - result  is rematerializable                       */
2809 /*-----------------------------------------------------------------*/
2810 static int
2811 resultRemat (iCode * ic)
2812 {
2813   if (SKIP_IC (ic) || ic->op == IFX)
2814     return 0;
2815
2816   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2817     {
2818       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2819       if (sym->remat && !POINTER_SET (ic))
2820         return 1;
2821     }
2822
2823   return 0;
2824 }
2825
2826 #if defined(__BORLANDC__) || defined(_MSC_VER)
2827 #define STRCASECMP stricmp
2828 #else
2829 #define STRCASECMP strcasecmp
2830 #endif
2831
2832 /*-----------------------------------------------------------------*/
2833 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2834 /*-----------------------------------------------------------------*/
2835 static int
2836 regsCmp(void *p1, void *p2)
2837 {
2838   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2839 }
2840
2841 static bool
2842 inExcludeList (char *s)
2843 {
2844   const char *p = setFirstItem(options.excludeRegsSet);
2845
2846   if (p == NULL || STRCASECMP(p, "none") == 0)
2847     return FALSE;
2848
2849
2850   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2851 }
2852
2853 /*-----------------------------------------------------------------*/
2854 /* genFunction - generated code for function entry                 */
2855 /*-----------------------------------------------------------------*/
2856 static void
2857 genFunction (iCode * ic)
2858 {
2859   symbol *sym;
2860   sym_link *ftype;
2861   bool   switchedPSW = FALSE;
2862
2863   D (emitcode (";", "genFunction "););
2864
2865   _G.nRegsSaved = 0;
2866   /* create the function header */
2867   emitcode (";", "-----------------------------------------");
2868   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2869   emitcode (";", "-----------------------------------------");
2870
2871   emitcode ("", "%s:", sym->rname);
2872   ftype = operandType (IC_LEFT (ic));
2873
2874   if (IFFUNC_ISNAKED(ftype))
2875   {
2876       emitcode(";", "naked function: no prologue.");
2877       return;
2878   }
2879   
2880   if (options.stack_probe) 
2881       emitcode ("lcall","__stack_probe");
2882   /* if critical function then turn interrupts off */
2883   if (IFFUNC_ISCRITICAL (ftype))
2884     emitcode ("clr", "ea");
2885
2886   /* here we need to generate the equates for the
2887      register bank if required */
2888   if (FUNC_REGBANK (ftype) != rbank)
2889     {
2890       int i;
2891
2892       rbank = FUNC_REGBANK (ftype);
2893       for (i = 0; i < ds390_nRegs; i++)
2894         {
2895           if (regs390[i].print) {
2896               if (strcmp (regs390[i].base, "0") == 0)
2897                   emitcode ("", "%s !equ !constbyte",
2898                             regs390[i].dname,
2899                             8 * rbank + regs390[i].offset);
2900               else
2901                   emitcode ("", "%s !equ %s + !constbyte",
2902                             regs390[i].dname,
2903                             regs390[i].base,
2904                             8 * rbank + regs390[i].offset);
2905           }
2906         }
2907     }
2908
2909   /* if this is an interrupt service routine then
2910      save acc, b, dpl, dph  */
2911   if (IFFUNC_ISISR (sym->type))
2912       { /* is ISR */
2913       if (!inExcludeList ("acc"))
2914         emitcode ("push", "acc");
2915       if (!inExcludeList ("b"))
2916         emitcode ("push", "b");
2917       if (!inExcludeList ("dpl"))
2918         emitcode ("push", "dpl");
2919       if (!inExcludeList ("dph"))
2920         emitcode ("push", "dph");
2921       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2922         {
2923           emitcode ("push", "dpx");
2924           /* Make sure we're using standard DPTR */
2925           emitcode ("push", "dps");
2926           emitcode ("mov", "dps,#0");
2927           if (options.stack10bit)
2928             {
2929               /* This ISR could conceivably use DPTR2. Better save it. */
2930               emitcode ("push", "dpl1");
2931               emitcode ("push", "dph1");
2932               emitcode ("push", "dpx1");
2933               emitcode ("push",  DP2_RESULT_REG);
2934             }
2935         }
2936       /* if this isr has no bank i.e. is going to
2937          run with bank 0 , then we need to save more
2938          registers :-) */
2939       if (!FUNC_REGBANK (sym->type))
2940         {
2941             int i;
2942
2943           /* if this function does not call any other
2944              function then we can be economical and
2945              save only those registers that are used */
2946           if (!IFFUNC_HASFCALL(sym->type))
2947             {
2948
2949               /* if any registers used */
2950               if (sym->regsUsed)
2951                 {
2952                   /* save the registers used */
2953                   for (i = 0; i < sym->regsUsed->size; i++)
2954                     {
2955                       if (bitVectBitValue (sym->regsUsed, i) ||
2956                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2957                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2958                     }
2959                 }
2960
2961             }
2962           else
2963             {
2964               /* this function has  a function call cannot
2965                  determines register usage so we will have to push the
2966                  entire bank */
2967               saveRBank (0, ic, FALSE);
2968               if (options.parms_in_bank1) {
2969                   for (i=0; i < 8 ; i++ ) {
2970                       emitcode ("push","%s",rb1regs[i]);
2971                   }
2972               }
2973             }
2974         }
2975         else
2976         {
2977             /* This ISR uses a non-zero bank.
2978              *
2979              * We assume that the bank is available for our
2980              * exclusive use.
2981              *
2982              * However, if this ISR calls a function which uses some
2983              * other bank, we must save that bank entirely.
2984              */
2985             unsigned long banksToSave = 0;
2986             
2987             if (IFFUNC_HASFCALL(sym->type))
2988             {
2989
2990 #define MAX_REGISTER_BANKS 4
2991
2992                 iCode *i;
2993                 int ix;
2994
2995                 for (i = ic; i; i = i->next)
2996                 {
2997                     if (i->op == ENDFUNCTION)
2998                     {
2999                         /* we got to the end OK. */
3000                         break;
3001                     }
3002                     
3003                     if (i->op == CALL)
3004                     {
3005                         sym_link *dtype;
3006                         
3007                         dtype = operandType (IC_LEFT(i));
3008                         if (dtype 
3009                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3010                         {
3011                              /* Mark this bank for saving. */
3012                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3013                              {
3014                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3015                              }
3016                              else
3017                              {
3018                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3019                              }
3020                              
3021                              /* And note that we don't need to do it in 
3022                               * genCall.
3023                               */
3024                              i->bankSaved = 1;
3025                         }
3026                     }
3027                     if (i->op == PCALL)
3028                     {
3029                         /* This is a mess; we have no idea what
3030                          * register bank the called function might
3031                          * use.
3032                          *
3033                          * The only thing I can think of to do is
3034                          * throw a warning and hope.
3035                          */
3036                         werror(W_FUNCPTR_IN_USING_ISR);   
3037                     }
3038                 }
3039
3040                 if (banksToSave && options.useXstack)
3041                 {
3042                     /* Since we aren't passing it an ic, 
3043                      * saveRBank will assume r0 is available to abuse.
3044                      *
3045                      * So switch to our (trashable) bank now, so
3046                      * the caller's R0 isn't trashed.
3047                      */
3048                     emitcode ("push", "psw");
3049                     emitcode ("mov", "psw,#!constbyte", 
3050                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3051                     switchedPSW = TRUE;
3052                 }
3053                 
3054                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3055                 {
3056                      if (banksToSave & (1 << ix))
3057                      {
3058                          saveRBank(ix, NULL, FALSE);
3059                      }
3060                 }
3061             }
3062             // TODO: this needs a closer look
3063             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3064         }
3065     }
3066   else
3067     {
3068       /* if callee-save to be used for this function
3069          then save the registers being used in this function */
3070       if (IFFUNC_CALLEESAVES(sym->type))
3071         {
3072           int i;
3073
3074           /* if any registers used */
3075           if (sym->regsUsed)
3076             {
3077               /* save the registers used */
3078               for (i = 0; i < sym->regsUsed->size; i++)
3079                 {
3080                   if (bitVectBitValue (sym->regsUsed, i) ||
3081                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3082                     {
3083                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3084                       _G.nRegsSaved++;
3085                     }
3086                 }
3087             }
3088         }
3089     }
3090
3091   /* set the register bank to the desired value */
3092   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3093    && !switchedPSW)
3094     {
3095       emitcode ("push", "psw");
3096       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3097     }
3098
3099   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3100        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3101       if (options.stack10bit) {
3102           emitcode ("push","_bpx");
3103           emitcode ("push","_bpx+1");
3104           emitcode ("mov","_bpx,%s",spname);
3105           emitcode ("mov","_bpx+1,esp");
3106           adjustEsp("_bpx+1");
3107       } else {
3108           if (options.useXstack) {
3109               emitcode ("mov", "r0,%s", spname);
3110               emitcode ("mov", "a,_bp");
3111               emitcode ("movx", "@r0,a");
3112               emitcode ("inc", "%s", spname);
3113           } else {
3114               /* set up the stack */
3115               emitcode ("push", "_bp"); /* save the callers stack  */
3116           }
3117           emitcode ("mov", "_bp,%s", spname);
3118       }
3119   }
3120
3121   /* adjust the stack for the function */
3122   if (sym->stack) {
3123       int i = sym->stack;
3124       if (options.stack10bit) {
3125           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3126           assert (sym->recvSize <= 4);
3127           if (sym->stack <= 8) {
3128               while (i--) emitcode ("push","acc");
3129           } else {
3130               PROTECT_SP;
3131               emitcode ("mov","a,sp");
3132               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3133               emitcode ("mov","sp,a");
3134               emitcode ("mov","a,esp");
3135               adjustEsp("a");
3136               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3137               emitcode ("mov","esp,a");
3138               UNPROTECT_SP;
3139           }
3140       } else {
3141           if (i > 256)
3142               werror (W_STACK_OVERFLOW, sym->name);
3143           
3144           if (i > 3 && sym->recvSize < 4) {
3145               
3146               emitcode ("mov", "a,sp");
3147               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3148               emitcode ("mov", "sp,a");
3149               
3150           } else
3151               while (i--)
3152                   emitcode ("inc", "sp");
3153       }
3154   }
3155
3156   if (sym->xstack)
3157     {
3158
3159       emitcode ("mov", "a,_spx");
3160       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3161       emitcode ("mov", "_spx,a");
3162     }
3163
3164 }
3165
3166 /*-----------------------------------------------------------------*/
3167 /* genEndFunction - generates epilogue for functions               */
3168 /*-----------------------------------------------------------------*/
3169 static void
3170 genEndFunction (iCode * ic)
3171 {
3172   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3173
3174   D (emitcode (";", "genEndFunction "););
3175
3176   if (IFFUNC_ISNAKED(sym->type))
3177   {
3178       emitcode(";", "naked function: no epilogue.");
3179       return;
3180   }
3181
3182   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3183        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3184
3185       if (options.stack10bit) {
3186           PROTECT_SP;     
3187           emitcode ("mov", "sp,_bpx", spname);
3188           emitcode ("mov", "esp,_bpx+1", spname);
3189           UNPROTECT_SP;
3190       } else {
3191           emitcode ("mov", "%s,_bp", spname);
3192       }
3193   }
3194
3195   /* if use external stack but some variables were
3196      added to the local stack then decrement the
3197      local stack */
3198   if (options.useXstack && sym->stack) {
3199       emitcode ("mov", "a,sp");
3200       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3201       emitcode ("mov", "sp,a");
3202   }
3203
3204
3205   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3206        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3207
3208       if (options.useXstack) {
3209           emitcode ("mov", "r0,%s", spname);
3210           emitcode ("movx", "a,@r0");
3211           emitcode ("mov", "_bp,a");
3212           emitcode ("dec", "%s", spname);
3213       } else {
3214           if (options.stack10bit) {
3215               emitcode ("pop", "_bpx+1");
3216               emitcode ("pop", "_bpx");
3217           } else {
3218               emitcode ("pop", "_bp");
3219           }
3220       }
3221   }
3222
3223   /* restore the register bank  */
3224   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3225   {
3226     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3227      || !options.useXstack)
3228     {
3229         /* Special case of ISR using non-zero bank with useXstack
3230          * is handled below.
3231          */
3232         emitcode ("pop", "psw");
3233     }
3234   } 
3235
3236   if (IFFUNC_ISISR (sym->type))
3237       { /* is ISR */  
3238
3239       /* now we need to restore the registers */
3240       /* if this isr has no bank i.e. is going to
3241          run with bank 0 , then we need to save more
3242          registers :-) */
3243       if (!FUNC_REGBANK (sym->type))
3244         {
3245             int i;
3246           /* if this function does not call any other
3247              function then we can be economical and
3248              save only those registers that are used */
3249           if (!IFFUNC_HASFCALL(sym->type))
3250             {
3251
3252               /* if any registers used */
3253               if (sym->regsUsed)
3254                 {
3255                   /* save the registers used */
3256                   for (i = sym->regsUsed->size; i >= 0; i--)
3257                     {
3258                       if (bitVectBitValue (sym->regsUsed, i) ||
3259                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3260                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3261                     }
3262                 }
3263
3264             }
3265           else
3266             {
3267               /* this function has  a function call cannot
3268                  determines register usage so we will have to pop the
3269                  entire bank */
3270               if (options.parms_in_bank1) {
3271                   for (i = 7 ; i >= 0 ; i-- ) {
3272                       emitcode ("pop","%s",rb1regs[i]);
3273                   }
3274               }
3275               unsaveRBank (0, ic, FALSE);
3276             }
3277         }
3278         else
3279         {
3280             /* This ISR uses a non-zero bank.
3281              *
3282              * Restore any register banks saved by genFunction
3283              * in reverse order.
3284              */
3285             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3286             int ix;
3287           
3288             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3289             {
3290                 if (savedBanks & (1 << ix))
3291                 {
3292                     unsaveRBank(ix, NULL, FALSE);
3293                 }
3294             }
3295             
3296             if (options.useXstack)
3297             {
3298                 /* Restore bank AFTER calling unsaveRBank,
3299                  * since it can trash r0.
3300                  */
3301                 emitcode ("pop", "psw");
3302             }
3303         }
3304
3305       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3306         {
3307           if (options.stack10bit)
3308             {
3309               emitcode ("pop", DP2_RESULT_REG);
3310               emitcode ("pop", "dpx1");
3311               emitcode ("pop", "dph1");
3312               emitcode ("pop", "dpl1");
3313             }
3314           emitcode ("pop", "dps");
3315           emitcode ("pop", "dpx");
3316         }
3317       if (!inExcludeList ("dph"))
3318         emitcode ("pop", "dph");
3319       if (!inExcludeList ("dpl"))
3320         emitcode ("pop", "dpl");
3321       if (!inExcludeList ("b"))
3322         emitcode ("pop", "b");
3323       if (!inExcludeList ("acc"))
3324         emitcode ("pop", "acc");
3325
3326       if (IFFUNC_ISCRITICAL (sym->type))
3327         emitcode ("setb", "ea");
3328
3329       /* if debug then send end of function */
3330       if (options.debug && currFunc) {
3331           _G.debugLine = 1;
3332           emitcode ("", "C$%s$%d$%d$%d ==.",
3333                     FileBaseName (ic->filename), currFunc->lastLine,
3334                     ic->level, ic->block);
3335           if (IS_STATIC (currFunc->etype))
3336             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3337           else
3338             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3339           _G.debugLine = 0;
3340         }
3341
3342       emitcode ("reti", "");
3343     }
3344   else
3345     {
3346       if (IFFUNC_ISCRITICAL (sym->type))
3347         emitcode ("setb", "ea");
3348
3349       if (IFFUNC_CALLEESAVES(sym->type))
3350         {
3351           int i;
3352
3353           /* if any registers used */
3354           if (sym->regsUsed)
3355             {
3356               /* save the registers used */
3357               for (i = sym->regsUsed->size; i >= 0; i--)
3358                 {
3359                   if (bitVectBitValue (sym->regsUsed, i) ||
3360                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3361                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3362                 }
3363             }
3364
3365         }
3366
3367       /* if debug then send end of function */
3368       if (options.debug && currFunc)
3369         {
3370           _G.debugLine = 1;
3371           emitcode ("", "C$%s$%d$%d$%d ==.",
3372                     FileBaseName (ic->filename), currFunc->lastLine,
3373                     ic->level, ic->block);
3374           if (IS_STATIC (currFunc->etype))
3375             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3376           else
3377             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3378           _G.debugLine = 0;
3379         }
3380
3381       emitcode ("ret", "");
3382     }
3383
3384 }
3385
3386 /*-----------------------------------------------------------------*/
3387 /* genJavaNativeRet - generate code for return JavaNative          */
3388 /*-----------------------------------------------------------------*/
3389 static void genJavaNativeRet(iCode *ic)
3390 {
3391     int i, size;
3392
3393     aopOp (IC_LEFT (ic), ic, FALSE, 
3394            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3395     size = AOP_SIZE (IC_LEFT (ic));
3396
3397     assert (size <= 4);
3398
3399     /* it is assigned to GPR0-R3 then push them */
3400     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3401         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3402         for (i = 0 ; i < size ; i++ ) {
3403             emitcode ("push","%s",
3404                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3405         }
3406         for (i = (size-1) ; i >= 0 ; i--) {
3407             emitcode ("pop","a%s",javaRet[i]);
3408         }
3409     } else {
3410         for (i = 0 ; i < size ; i++) 
3411             emitcode ("mov","%s,%s",javaRet[i],
3412                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3413     }
3414     for (i = size ; i < 4 ; i++ )
3415             emitcode ("mov","%s,#0",javaRet[i]);
3416     return;
3417 }
3418
3419 /*-----------------------------------------------------------------*/
3420 /* genRet - generate code for return statement                     */
3421 /*-----------------------------------------------------------------*/
3422 static void
3423 genRet (iCode * ic)
3424 {
3425   int size, offset = 0, pushed = 0;
3426
3427   D (emitcode (";", "genRet "););
3428
3429   /* if we have no return value then
3430      just generate the "ret" */
3431   if (!IC_LEFT (ic))
3432     goto jumpret;
3433
3434   /* if this is a JavaNative function then return 
3435      value in different register */
3436   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3437       genJavaNativeRet(ic);
3438       goto jumpret;
3439   }
3440   /* we have something to return then
3441      move the return value into place */
3442   aopOp (IC_LEFT (ic), ic, FALSE, 
3443          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3444   size = AOP_SIZE (IC_LEFT (ic));
3445
3446   _startLazyDPSEvaluation ();
3447   while (size--)
3448     {
3449       char *l;
3450       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3451         {
3452           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3453                       FALSE, TRUE, NULL);
3454           emitcode ("push", "%s", l);
3455           pushed++;
3456         }
3457       else
3458         {
3459           /* Since A is the last element of fReturn,
3460            * is is OK to clobber it in the aopGet.
3461            */
3462           l = aopGet (AOP (IC_LEFT (ic)), offset,
3463                       FALSE, FALSE, NULL);
3464           if (strcmp (fReturn[offset], l))
3465             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3466         }
3467     }
3468   _endLazyDPSEvaluation ();
3469
3470   if (pushed)
3471     {
3472       while (pushed)
3473         {
3474           pushed--;
3475           if (strcmp (fReturn[pushed], "a"))
3476             emitcode ("pop", fReturn[pushed]);
3477           else
3478             emitcode ("pop", "acc");
3479         }
3480     }
3481   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3482
3483 jumpret:
3484   /* generate a jump to the return label
3485      if the next is not the return statement */
3486   if (!(ic->next && ic->next->op == LABEL &&
3487         IC_LABEL (ic->next) == returnLabel))
3488
3489     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3490
3491 }
3492
3493 /*-----------------------------------------------------------------*/
3494 /* genLabel - generates a label                                    */
3495 /*-----------------------------------------------------------------*/
3496 static void
3497 genLabel (iCode * ic)
3498 {
3499   /* special case never generate */
3500   if (IC_LABEL (ic) == entryLabel)
3501     return;
3502
3503   D (emitcode (";", "genLabel ");
3504     );
3505
3506   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3507 }
3508
3509 /*-----------------------------------------------------------------*/
3510 /* genGoto - generates a ljmp                                      */
3511 /*-----------------------------------------------------------------*/
3512 static void
3513 genGoto (iCode * ic)
3514 {
3515   D (emitcode (";", "genGoto ");
3516     );
3517   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3518 }
3519
3520 /*-----------------------------------------------------------------*/
3521 /* findLabelBackwards: walks back through the iCode chain looking  */
3522 /* for the given label. Returns number of iCode instructions     */
3523 /* between that label and given ic.          */
3524 /* Returns zero if label not found.          */
3525 /*-----------------------------------------------------------------*/
3526 static int
3527 findLabelBackwards (iCode * ic, int key)
3528 {
3529   int count = 0;
3530
3531   while (ic->prev)
3532     {
3533       ic = ic->prev;
3534       count++;
3535
3536       /* If we have any pushes or pops, we cannot predict the distance.
3537          I don't like this at all, this should be dealt with in the 
3538          back-end */
3539       if (ic->op == IPUSH || ic->op == IPOP) {
3540         return 0;
3541       }
3542
3543       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3544         {
3545           /* printf("findLabelBackwards = %d\n", count); */
3546           return count;
3547         }
3548     }
3549
3550   return 0;
3551 }
3552
3553 /*-----------------------------------------------------------------*/
3554 /* genPlusIncr :- does addition with increment if possible         */
3555 /*-----------------------------------------------------------------*/
3556 static bool
3557 genPlusIncr (iCode * ic)
3558 {
3559   unsigned int icount;
3560   unsigned int size = getDataSize (IC_RESULT (ic));
3561
3562   /* will try to generate an increment */
3563   /* if the right side is not a literal
3564      we cannot */
3565   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3566     return FALSE;
3567
3568   /* if the literal value of the right hand side
3569      is greater than 4 then it is not worth it */
3570   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3571     return FALSE;
3572
3573   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3574       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3575       while (icount--) {
3576           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3577       }
3578       return TRUE;
3579   }
3580   /* if increment 16 bits in register */
3581   if (
3582        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3583        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3584        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3585        (size > 1) &&
3586        (icount == 1))
3587     {
3588       symbol  *tlbl;
3589       int     emitTlbl;
3590       int     labelRange;
3591       char    *l;
3592
3593       /* If the next instruction is a goto and the goto target
3594        * is <= 5 instructions previous to this, we can generate
3595        * jumps straight to that target.
3596        */
3597       if (ic->next && ic->next->op == GOTO
3598           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3599           && labelRange <= 5)
3600         {
3601           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3602           tlbl = IC_LABEL (ic->next);
3603           emitTlbl = 0;
3604         }
3605       else
3606         {
3607           tlbl = newiTempLabel (NULL);
3608           emitTlbl = 1;
3609         }
3610         
3611       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3612       emitcode ("inc", "%s", l);
3613       
3614       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3615           IS_AOP_PREG (IC_RESULT (ic)))
3616       {   
3617         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3618       }
3619       else
3620       {
3621           emitcode ("clr", "a");
3622           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3623       }
3624
3625       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3626       emitcode ("inc", "%s", l);
3627       if (size > 2)
3628         {
3629             if (!strcmp(l, "acc"))
3630             {
3631                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3632             }
3633             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3634                      IS_AOP_PREG (IC_RESULT (ic)))
3635             {
3636                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3637             }
3638             else
3639             {
3640                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3641             }
3642
3643             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3644             emitcode ("inc", "%s", l);
3645         }
3646       if (size > 3)
3647         {
3648             if (!strcmp(l, "acc"))
3649             {
3650                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3651             }
3652             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3653                      IS_AOP_PREG (IC_RESULT (ic)))
3654             {
3655                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3656             }
3657             else
3658             {
3659                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3660             }
3661
3662             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3663             emitcode ("inc", "%s", l);  }
3664
3665       if (emitTlbl)
3666         {
3667           emitcode ("", "!tlabeldef", tlbl->key + 100);
3668         }
3669       return TRUE;
3670     }
3671
3672   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3673       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3674       options.model == MODEL_FLAT24 ) {
3675
3676       switch (size) {
3677       case 3:
3678           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3679       case 2:
3680           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3681       case 1:
3682           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3683           break;
3684       }
3685       while (icount--) emitcode ("inc","dptr");      
3686       return TRUE;
3687   }
3688
3689   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3690       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3691       icount <= 5 ) {
3692       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3693       while (icount--) emitcode ("inc","dptr");
3694       emitcode ("mov","dps,#0");
3695       return TRUE;
3696   }
3697
3698   /* if the sizes are greater than 1 then we cannot */
3699   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3700       AOP_SIZE (IC_LEFT (ic)) > 1)
3701     return FALSE;
3702
3703   /* we can if the aops of the left & result match or
3704      if they are in registers and the registers are the
3705      same */
3706   if (
3707        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3708        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3709        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3710     {
3711
3712       if (icount > 3)
3713         {
3714           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3715           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3716           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3717         }
3718       else
3719         {
3720
3721           _startLazyDPSEvaluation ();
3722           while (icount--)
3723             {
3724               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3725             }
3726           _endLazyDPSEvaluation ();
3727         }
3728
3729       return TRUE;
3730     }
3731
3732   return FALSE;
3733 }
3734
3735 /*-----------------------------------------------------------------*/
3736 /* outBitAcc - output a bit in acc                                 */
3737 /*-----------------------------------------------------------------*/
3738 static void
3739 outBitAcc (operand * result)
3740 {
3741   symbol *tlbl = newiTempLabel (NULL);
3742   /* if the result is a bit */
3743   if (AOP_TYPE (result) == AOP_CRY)
3744     {
3745       aopPut (AOP (result), "a", 0);
3746     }
3747   else
3748     {
3749       emitcode ("jz", "!tlabel", tlbl->key + 100);
3750       emitcode ("mov", "a,%s", one);
3751       emitcode ("", "!tlabeldef", tlbl->key + 100);
3752       outAcc (result);
3753     }
3754 }
3755
3756 /*-----------------------------------------------------------------*/
3757 /* genPlusBits - generates code for addition of two bits           */
3758 /*-----------------------------------------------------------------*/
3759 static void
3760 genPlusBits (iCode * ic)
3761 {
3762   D (emitcode (";", "genPlusBits "););
3763     
3764   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3765     {
3766       symbol *lbl = newiTempLabel (NULL);
3767       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3768       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3769       emitcode ("cpl", "c");
3770       emitcode ("", "!tlabeldef", (lbl->key + 100));
3771       outBitC (IC_RESULT (ic));
3772     }
3773   else
3774     {
3775       emitcode ("clr", "a");
3776       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3777       emitcode ("rlc", "a");
3778       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3779       emitcode ("addc", "a,#0");
3780       outAcc (IC_RESULT (ic));
3781     }
3782 }
3783
3784 static void
3785 adjustArithmeticResult (iCode * ic)
3786 {
3787   if (opIsGptr (IC_RESULT (ic)) &&
3788       opIsGptr (IC_LEFT (ic)) &&
3789       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3790     {
3791       aopPut (AOP (IC_RESULT (ic)),
3792               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3793               GPTRSIZE - 1);
3794     }
3795
3796   if (opIsGptr (IC_RESULT (ic)) &&
3797       opIsGptr (IC_RIGHT (ic)) &&
3798       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3799     {
3800       aopPut (AOP (IC_RESULT (ic)),
3801             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3802               GPTRSIZE - 1);
3803     }
3804
3805   if (opIsGptr (IC_RESULT (ic)) &&
3806       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3807       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3808       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3809       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3810     {
3811       char buff[5];
3812       SNPRINTF (buff, sizeof(buff), 
3813                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3814       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3815     }
3816 }
3817
3818 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3819 // generates the result if possible. If result is generated, returns TRUE; otherwise
3820 // returns false and caller must deal with fact that result isn't aopOp'd.
3821 bool aopOp3(iCode * ic)
3822 {
3823     bool dp1InUse, dp2InUse;
3824     bool useDp2;
3825     
3826     // First, generate the right opcode. DPTR may be used if neither left nor result are
3827     // of type AOP_STR.
3828     
3829 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3830 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3831 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3832 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3833 //      );
3834 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3835 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3836 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3837 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3838 //      );
3839     
3840     // Right uses DPTR unless left or result is an AOP_STR; however,
3841     // if right is an AOP_STR, it must use DPTR regardless.
3842     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3843      && !AOP_IS_STR(IC_RIGHT(ic)))
3844     {
3845         useDp2 = TRUE;
3846     }
3847     else
3848     {
3849         useDp2 = FALSE;
3850     }
3851         
3852     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3853     
3854     // if the right used DPTR, left MUST use DPTR2.
3855     // if the right used DPTR2, left MUST use DPTR.
3856     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3857     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3858     // enabling us to assign DPTR to result.
3859      
3860     if (AOP_USESDPTR(IC_RIGHT(ic)))
3861     {
3862         useDp2 = TRUE;
3863     }
3864     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3865     {
3866         useDp2 = FALSE;
3867     }
3868     else
3869     {
3870         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3871         {
3872             useDp2 = TRUE;
3873         }
3874         else
3875         {
3876             useDp2 = FALSE;
3877         }
3878     }
3879
3880     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3881     
3882     // We've op'd the left & right. So, if left or right are the same operand as result, 
3883     // we know aopOp will succeed, and we can just do it & bail.
3884     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3885         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3886     {
3887 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3888         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3889         return TRUE;
3890     }
3891     
3892     // Note which dptrs are currently in use.
3893     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3894     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3895     
3896     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3897     // generate it.
3898     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3899     {
3900         return FALSE;
3901     }
3902     
3903     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3904     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3905     {
3906         return FALSE;
3907     }
3908     
3909     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3910     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3911     {
3912         return FALSE;
3913     }
3914
3915     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3916
3917     // Some sanity checking...
3918     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3919     {
3920         fprintf(stderr,
3921                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3922                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3923         emitcode(";", ">>> unexpected DPTR here.");
3924     }
3925     
3926     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3927     {
3928         fprintf(stderr,
3929                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3930                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3931         emitcode(";", ">>> unexpected DPTR2 here.");
3932     }    
3933     
3934     return TRUE;
3935 }
3936
3937 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3938 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3939 // will be set TRUE. The caller must then handle the case specially, noting
3940 // that the IC_RESULT operand is not aopOp'd.
3941 // 
3942 #define AOP_OP_3_NOFATAL(ic, rc) \
3943             do { rc = !aopOp3(ic); } while (0)
3944
3945 // aopOp the left & right operands of an ic.
3946 #define AOP_OP_2(ic) \
3947     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3948     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3949
3950 // convienience macro.
3951 #define AOP_SET_LOCALS(ic) \
3952     left = IC_LEFT(ic); \
3953     right = IC_RIGHT(ic); \
3954     result = IC_RESULT(ic);
3955
3956
3957 // Given an integer value of pushedSize bytes on the stack,
3958 // adjust it to be resultSize bytes, either by discarding
3959 // the most significant bytes or by zero-padding.
3960 //
3961 // On exit from this macro, pushedSize will have been adjusted to
3962 // equal resultSize, and ACC may be trashed.
3963 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3964       /* If the pushed data is bigger than the result,          \
3965        * simply discard unused bytes. Icky, but works.          \
3966        */                                                       \
3967       while (pushedSize > resultSize)                           \
3968       {                                                         \
3969           D (emitcode (";", "discarding unused result byte."););\
3970           emitcode ("pop", "acc");                              \
3971           pushedSize--;                                         \
3972       }                                                         \
3973       if (pushedSize < resultSize)                              \
3974       {                                                         \
3975           emitcode ("clr", "a");                                \
3976           /* Conversly, we haven't pushed enough here.          \
3977            * just zero-pad, and all is well.                    \
3978            */                                                   \
3979           while (pushedSize < resultSize)                       \
3980           {                                                     \
3981               emitcode("push", "acc");                          \
3982               pushedSize++;                                     \
3983           }                                                     \
3984       }                                                         \
3985       assert(pushedSize == resultSize);
3986
3987 /*-----------------------------------------------------------------*/
3988 /* genPlus - generates code for addition                           */
3989 /*-----------------------------------------------------------------*/
3990 static void
3991 genPlus (iCode * ic)
3992 {
3993   int size, offset = 0;
3994   bool pushResult;
3995   int rSize;
3996
3997   D (emitcode (";", "genPlus "););
3998
3999   /* special cases :- */
4000   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4001       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4002       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4003       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4004       if (size <= 9) {
4005           while (size--) emitcode ("inc","dptr");
4006       } else {
4007           emitcode ("mov","a,dpl");
4008           emitcode ("add","a,#!constbyte",size & 0xff);
4009           emitcode ("mov","dpl,a");
4010           emitcode ("mov","a,dph");
4011           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4012           emitcode ("mov","dph,a");
4013           emitcode ("mov","a,dpx");
4014           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4015           emitcode ("mov","dpx,a");
4016       }
4017       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4018       return ;
4019   }
4020   if ( IS_SYMOP(IC_LEFT(ic)) && 
4021        OP_SYMBOL(IC_LEFT(ic))->remat &&
4022        isOperandInFarSpace(IC_RIGHT(ic))) {
4023       operand *op = IC_RIGHT(ic);
4024       IC_RIGHT(ic) = IC_LEFT(ic);
4025       IC_LEFT(ic) = op;
4026   }
4027                 
4028   AOP_OP_3_NOFATAL (ic, pushResult);
4029     
4030   if (pushResult)
4031     {
4032       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4033     }
4034
4035   if (!pushResult)
4036     {
4037       /* if literal, literal on the right or
4038          if left requires ACC or right is already
4039          in ACC */
4040       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4041        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4042           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4043         {
4044           operand *t = IC_RIGHT (ic);
4045           IC_RIGHT (ic) = IC_LEFT (ic);
4046           IC_LEFT (ic) = t;
4047           emitcode (";", "Swapped plus args.");
4048         }
4049
4050       /* if both left & right are in bit
4051          space */
4052       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4053           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4054         {
4055           genPlusBits (ic);
4056           goto release;
4057         }
4058
4059       /* if left in bit space & right literal */
4060       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4061           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4062         {
4063           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4064           /* if result in bit space */
4065           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4066             {
4067               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4068                 emitcode ("cpl", "c");
4069               outBitC (IC_RESULT (ic));
4070             }
4071           else
4072             {
4073               size = getDataSize (IC_RESULT (ic));
4074               _startLazyDPSEvaluation ();
4075               while (size--)
4076                 {
4077                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4078                   emitcode ("addc", "a,#0");
4079                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4080                 }
4081               _endLazyDPSEvaluation ();
4082             }
4083           goto release;
4084         }
4085
4086       /* if I can do an increment instead
4087          of add then GOOD for ME */
4088       if (genPlusIncr (ic) == TRUE)
4089         {
4090           emitcode (";", "did genPlusIncr");
4091           goto release;
4092         }
4093
4094     }
4095   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4096
4097   _startLazyDPSEvaluation ();
4098   while (size--)
4099     {
4100       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4101         {
4102           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4103           if (offset == 0)
4104             emitcode ("add", "a,%s",
4105                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4106           else
4107             emitcode ("addc", "a,%s",
4108                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4109         }
4110       else
4111         {
4112           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4113           {
4114               /* right is going to use ACC or we would have taken the
4115                * above branch.
4116                */
4117               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4118        TR_AP("#3");
4119               D(emitcode(";", "+ AOP_ACC special case."););
4120               emitcode("xch", "a, %s", DP2_RESULT_REG);
4121           }
4122           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4123           if (offset == 0)
4124           {
4125             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4126             {
4127          TR_AP("#4");
4128                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4129             }
4130             else
4131             {
4132                 emitcode ("add", "a,%s",
4133                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4134                                   DP2_RESULT_REG));
4135             }
4136           }
4137           else
4138           {
4139             emitcode ("addc", "a,%s",
4140                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4141                           DP2_RESULT_REG));
4142           }
4143         }
4144       if (!pushResult)
4145         {
4146           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4147         }
4148       else
4149         {
4150           emitcode ("push", "acc");
4151         }
4152       offset++;
4153     }
4154   _endLazyDPSEvaluation ();
4155
4156   if (pushResult)
4157     {
4158       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4159
4160       size = getDataSize (IC_LEFT (ic));
4161       rSize = getDataSize (IC_RESULT (ic));
4162
4163       ADJUST_PUSHED_RESULT(size, rSize);
4164
4165       _startLazyDPSEvaluation ();
4166       while (size--)
4167         {
4168           emitcode ("pop", "acc");
4169           aopPut (AOP (IC_RESULT (ic)), "a", size);
4170         }
4171       _endLazyDPSEvaluation ();
4172     }
4173
4174   adjustArithmeticResult (ic);
4175
4176 release:
4177   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4178   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4179   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4180 }
4181
4182 /*-----------------------------------------------------------------*/
4183 /* genMinusDec :- does subtraction with deccrement if possible     */
4184 /*-----------------------------------------------------------------*/
4185 static bool
4186 genMinusDec (iCode * ic)
4187 {
4188   unsigned int icount;
4189   unsigned int size = getDataSize (IC_RESULT (ic));
4190
4191   /* will try to generate an increment */
4192   /* if the right side is not a literal
4193      we cannot */
4194   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4195     return FALSE;
4196
4197   /* if the literal value of the right hand side
4198      is greater than 4 then it is not worth it */
4199   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4200     return FALSE;
4201
4202   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4203       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4204       while (icount--) {
4205           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4206       }
4207       return TRUE;
4208   }
4209   /* if decrement 16 bits in register */
4210   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4211       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4212       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4213       (size > 1) &&
4214       (icount == 1))
4215     {
4216       symbol *tlbl;
4217       int    emitTlbl;
4218       int    labelRange;
4219       char   *l;
4220
4221       /* If the next instruction is a goto and the goto target
4222          * is <= 5 instructions previous to this, we can generate
4223          * jumps straight to that target.
4224        */
4225       if (ic->next && ic->next->op == GOTO
4226           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4227           && labelRange <= 5)
4228         {
4229           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4230           tlbl = IC_LABEL (ic->next);
4231           emitTlbl = 0;
4232         }
4233       else
4234         {
4235           tlbl = newiTempLabel (NULL);
4236           emitTlbl = 1;
4237         }
4238
4239       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4240       emitcode ("dec", "%s", l);
4241  
4242       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4243           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4244           IS_AOP_PREG (IC_RESULT (ic)))
4245       {     
4246           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4247       }
4248       else
4249       {
4250           emitcode ("mov", "a,#!constbyte",0xff);
4251           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4252       }
4253       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4254       emitcode ("dec", "%s", l);
4255       if (size > 2)
4256         {
4257             if (!strcmp(l, "acc"))
4258             {
4259                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4260             }
4261             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4262                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4263                      IS_AOP_PREG (IC_RESULT (ic)))
4264             {       
4265                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4266             }
4267             else
4268             {
4269                 emitcode ("mov", "a,#!constbyte",0xff);
4270                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4271             }
4272             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4273             emitcode ("dec", "%s", l);
4274         }
4275       if (size > 3)
4276         {
4277             if (!strcmp(l, "acc"))
4278             {
4279                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4280             }
4281             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4282                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4283                      IS_AOP_PREG (IC_RESULT (ic)))
4284             {       
4285                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4286             }
4287             else
4288             {
4289                 emitcode ("mov", "a,#!constbyte",0xff);
4290                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4291             }       
4292             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4293             emitcode ("dec", "%s", l);
4294         }
4295       if (emitTlbl)
4296         {
4297           emitcode ("", "!tlabeldef", tlbl->key + 100);
4298         }
4299       return TRUE;
4300     }
4301
4302   /* if the sizes are greater than 1 then we cannot */
4303   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4304       AOP_SIZE (IC_LEFT (ic)) > 1)
4305     return FALSE;
4306
4307   /* we can if the aops of the left & result match or
4308      if they are in registers and the registers are the
4309      same */
4310   if (
4311        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4312        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4313        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4314     {
4315
4316       _startLazyDPSEvaluation ();
4317       while (icount--)
4318         {
4319           emitcode ("dec", "%s",
4320                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4321         }
4322       _endLazyDPSEvaluation ();
4323
4324       return TRUE;
4325     }
4326
4327   return FALSE;
4328 }
4329
4330 /*-----------------------------------------------------------------*/
4331 /* addSign - complete with sign                                    */
4332 /*-----------------------------------------------------------------*/
4333 static void
4334 addSign (operand * result, int offset, int sign)
4335 {
4336   int size = (getDataSize (result) - offset);
4337   if (size > 0)
4338     {
4339       _startLazyDPSEvaluation();
4340       if (sign)
4341         {
4342           emitcode ("rlc", "a");
4343           emitcode ("subb", "a,acc");
4344           while (size--)
4345           {
4346             aopPut (AOP (result), "a", offset++);
4347           }
4348         }
4349       else
4350       {
4351         while (size--)
4352         {
4353           aopPut (AOP (result), zero, offset++);
4354         }
4355       }
4356       _endLazyDPSEvaluation();
4357     }
4358 }
4359
4360 /*-----------------------------------------------------------------*/
4361 /* genMinusBits - generates code for subtraction  of two bits      */
4362 /*-----------------------------------------------------------------*/
4363 static void
4364 genMinusBits (iCode * ic)
4365 {
4366   symbol *lbl = newiTempLabel (NULL);
4367
4368   D (emitcode (";", "genMinusBits "););
4369
4370   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4371     {
4372       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4373       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4374       emitcode ("cpl", "c");
4375       emitcode ("", "!tlabeldef", (lbl->key + 100));
4376       outBitC (IC_RESULT (ic));
4377     }
4378   else
4379     {
4380       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4381       emitcode ("subb", "a,acc");
4382       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4383       emitcode ("inc", "a");
4384       emitcode ("", "!tlabeldef", (lbl->key + 100));
4385       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4386       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4387     }
4388 }
4389
4390 /*-----------------------------------------------------------------*/
4391 /* genMinus - generates code for subtraction                       */
4392 /*-----------------------------------------------------------------*/
4393 static void
4394 genMinus (iCode * ic)
4395 {
4396     int size, offset = 0;
4397     int rSize;
4398     long lit = 0L;
4399     bool pushResult;
4400
4401     D (emitcode (";", "genMinus "););
4402
4403     AOP_OP_3_NOFATAL(ic, pushResult);   
4404
4405     if (!pushResult)
4406     {
4407       /* special cases :- */
4408       /* if both left & right are in bit space */
4409       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4410           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4411         {
4412           genMinusBits (ic);
4413           goto release;
4414         }
4415
4416       /* if I can do an decrement instead
4417          of subtract then GOOD for ME */
4418       if (genMinusDec (ic) == TRUE)
4419         goto release;
4420
4421     }
4422
4423   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4424
4425   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4426     {
4427       CLRC;
4428     }
4429   else
4430     {
4431       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4432       lit = -lit;
4433     }
4434
4435
4436   /* if literal, add a,#-lit, else normal subb */
4437   _startLazyDPSEvaluation ();
4438   while (size--) {
4439       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4440           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4441               emitcode ("mov","b,%s",
4442                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4443               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4444               emitcode ("subb","a,b");
4445           } else {
4446               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4447               emitcode ("subb", "a,%s",
4448                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4449                                 DP2_RESULT_REG));
4450           }
4451       } else {
4452           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4453           /* first add without previous c */
4454           if (!offset) {
4455               if (!size && lit==-1) {
4456                   emitcode ("dec", "a");
4457               } else {
4458                   emitcode ("add", "a,#!constbyte",
4459                             (unsigned int) (lit & 0x0FFL));
4460               }
4461           } else {
4462               emitcode ("addc", "a,#!constbyte",
4463                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4464           }
4465       }
4466       
4467       if (pushResult) {
4468           emitcode ("push", "acc");
4469       } else {
4470           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4471       }
4472       offset++;
4473   }
4474   _endLazyDPSEvaluation ();
4475   
4476   if (pushResult)
4477     {
4478       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4479
4480       size = getDataSize (IC_LEFT (ic));
4481       rSize = getDataSize (IC_RESULT (ic));
4482
4483       ADJUST_PUSHED_RESULT(size, rSize);
4484
4485       _startLazyDPSEvaluation ();
4486       while (size--)
4487         {
4488           emitcode ("pop", "acc");
4489           aopPut (AOP (IC_RESULT (ic)), "a", size);
4490         }
4491       _endLazyDPSEvaluation ();
4492     }
4493
4494   adjustArithmeticResult (ic);
4495
4496 release:
4497   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4498   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4499   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4500 }
4501
4502
4503 /*-----------------------------------------------------------------*/
4504 /* genMultbits :- multiplication of bits                           */
4505 /*-----------------------------------------------------------------*/
4506 static void
4507 genMultbits (operand * left,
4508              operand * right,
4509              operand * result,
4510              iCode   * ic)
4511 {
4512   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4513   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4514   aopOp(result, ic, TRUE, FALSE);
4515   outBitC (result);
4516 }
4517
4518
4519 /*-----------------------------------------------------------------*/
4520 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4521 /*-----------------------------------------------------------------*/
4522 static void
4523 genMultOneByte (operand * left,
4524                 operand * right,
4525                 operand * result,
4526                 iCode   * ic)
4527 {
4528   sym_link *opetype = operandType (result);
4529   symbol *lbl;
4530
4531
4532   /* (if two literals: the value is computed before) */
4533   /* if one literal, literal on the right */
4534   if (AOP_TYPE (left) == AOP_LIT)
4535     {
4536       operand *t = right;
4537       right = left;
4538       left = t;
4539       emitcode (";", "swapped left and right");
4540     }
4541
4542   if (SPEC_USIGN(opetype)
4543       // ignore the sign of left and right, what else can we do?
4544       || (SPEC_USIGN(operandType(left)) && 
4545           SPEC_USIGN(operandType(right)))) {
4546     // just an unsigned 8*8=8/16 multiply
4547     //emitcode (";","unsigned");
4548     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4549     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4550     emitcode ("mul", "ab");
4551    
4552     _G.accInUse++; _G.bInUse++;
4553     aopOp(result, ic, TRUE, FALSE);
4554       
4555       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4556       {
4557           // this should never happen
4558           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4559                    AOP_SIZE(result), __FILE__, lineno);
4560           exit (1);
4561       }      
4562       
4563     aopPut (AOP (result), "a", 0);
4564     _G.accInUse--; _G.bInUse--;
4565     if (AOP_SIZE(result)==2) 
4566     {
4567       aopPut (AOP (result), "b", 1);
4568     }
4569     return;
4570   }
4571
4572   // we have to do a signed multiply
4573
4574   emitcode (";", "signed");
4575   emitcode ("clr", "F0"); // reset sign flag
4576   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4577
4578   lbl=newiTempLabel(NULL);
4579   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4580   // left side is negative, 8-bit two's complement, this fails for -128
4581   emitcode ("setb", "F0"); // set sign flag
4582   emitcode ("cpl", "a");
4583   emitcode ("inc", "a");
4584
4585   emitcode ("", "!tlabeldef", lbl->key+100);
4586
4587   /* if literal */
4588   if (AOP_TYPE(right)==AOP_LIT) {
4589     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4590     /* AND literal negative */
4591     if ((int) val < 0) {
4592       emitcode ("cpl", "F0"); // complement sign flag
4593       emitcode ("mov", "b,#!constbyte", -val);
4594     } else {
4595       emitcode ("mov", "b,#!constbyte", val);
4596     }
4597   } else {
4598     lbl=newiTempLabel(NULL);
4599     emitcode ("mov", "b,a");
4600     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4601     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4602     // right side is negative, 8-bit two's complement
4603     emitcode ("cpl", "F0"); // complement sign flag
4604     emitcode ("cpl", "a");
4605     emitcode ("inc", "a");
4606     emitcode ("", "!tlabeldef", lbl->key+100);
4607   }
4608   emitcode ("mul", "ab");
4609     
4610   _G.accInUse++;_G.bInUse++;
4611   aopOp(result, ic, TRUE, FALSE);
4612     
4613   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4614   {
4615     // this should never happen
4616       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4617                AOP_SIZE(result), __FILE__, lineno);
4618       exit (1);
4619   }    
4620     
4621   lbl=newiTempLabel(NULL);
4622   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4623   // only ONE op was negative, we have to do a 8/16-bit two's complement
4624   emitcode ("cpl", "a"); // lsb
4625   if (AOP_SIZE(result)==1) {
4626     emitcode ("inc", "a");
4627   } else {
4628     emitcode ("add", "a,#1");
4629     emitcode ("xch", "a,b");
4630     emitcode ("cpl", "a"); // msb
4631     emitcode ("addc", "a,#0");
4632     emitcode ("xch", "a,b");
4633   }
4634
4635   emitcode ("", "!tlabeldef", lbl->key+100);
4636   aopPut (AOP (result), "a", 0);
4637   _G.accInUse--;_G.bInUse--;
4638   if (AOP_SIZE(result)==2) {
4639     aopPut (AOP (result), "b", 1);
4640   }
4641 }
4642
4643 /*-----------------------------------------------------------------*/
4644 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4645 /*-----------------------------------------------------------------*/
4646 static void genMultTwoByte (operand *left, operand *right, 
4647                             operand *result, iCode *ic)
4648 {
4649         sym_link *retype = getSpec(operandType(right));
4650         sym_link *letype = getSpec(operandType(left));
4651         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4652         symbol *lbl;
4653
4654         if (AOP_TYPE (left) == AOP_LIT) {
4655                 operand *t = right;
4656                 right = left;
4657                 left = t;
4658         }
4659         /* save EA bit in F1 */
4660         lbl = newiTempLabel(NULL);
4661         emitcode ("setb","F1");
4662         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4663         emitcode ("clr","F1");
4664         emitcode("","!tlabeldef",lbl->key+100);
4665
4666         /* load up MB with right */
4667         if (!umult) {
4668                 emitcode("clr","F0");
4669                 if (AOP_TYPE(right) == AOP_LIT) {
4670                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4671                         if (val < 0) {
4672                                 emitcode("setb","F0");
4673                                 val = -val;
4674                         }
4675                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4676                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4677                 } else {
4678                         lbl = newiTempLabel(NULL);
4679                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4680                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4681                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4682                         emitcode ("xch", "a,b");
4683                         emitcode ("cpl","a");
4684                         emitcode ("add", "a,#1");
4685                         emitcode ("xch", "a,b");
4686                         emitcode ("cpl", "a"); // msb
4687                         emitcode ("addc", "a,#0");
4688                         emitcode ("setb","F0");
4689                         emitcode ("","!tlabeldef",lbl->key+100);
4690                         emitcode ("mov","mb,b");
4691                         emitcode ("mov","mb,a");
4692                 }
4693         } else {
4694                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4695                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4696         }
4697         /* load up MA with left */
4698         if (!umult) {
4699                 lbl = newiTempLabel(NULL);
4700                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4701                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4702                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4703                 emitcode ("xch", "a,b");
4704                 emitcode ("cpl","a");
4705                 emitcode ("add", "a,#1");
4706                 emitcode ("xch", "a,b");
4707                 emitcode ("cpl", "a"); // msb
4708                 emitcode ("addc","a,#0");
4709                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4710                 emitcode ("setb","F0");
4711                 emitcode ("","!tlabeldef",lbl->key+100);
4712                 emitcode ("mov","ma,b");
4713                 emitcode ("mov","ma,a");
4714         } else {
4715                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4716                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4717         }
4718         /* wait for multiplication to finish */
4719         lbl = newiTempLabel(NULL);
4720         emitcode("","!tlabeldef", lbl->key+100);
4721         emitcode("mov","a,mcnt1");
4722         emitcode("anl","a,#!constbyte",0x80);
4723         emitcode("jnz","!tlabel",lbl->key+100);
4724         
4725         freeAsmop (left, NULL, ic, TRUE);
4726         freeAsmop (right, NULL, ic,TRUE);
4727         aopOp(result, ic, TRUE, FALSE);
4728
4729         /* if unsigned then simple */   
4730         if (umult) {
4731                 emitcode ("mov","a,ma");
4732                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4733                 emitcode ("mov","a,ma");
4734                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4735                 aopPut(AOP(result),"ma",1);
4736                 aopPut(AOP(result),"ma",0);
4737         } else {
4738                 emitcode("push","ma");
4739                 emitcode("push","ma");
4740                 emitcode("push","ma");
4741                 MOVA("ma");
4742                 /* negate result if needed */
4743                 lbl = newiTempLabel(NULL);      
4744                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4745                 emitcode("cpl","a");
4746                 emitcode("add","a,#1");
4747                 emitcode("","!tlabeldef", lbl->key+100);
4748                 if (AOP_TYPE(result) == AOP_ACC)
4749                 {
4750                     D(emitcode(";", "ACC special case."););
4751                     /* We know result is the only live aop, and 
4752                      * it's obviously not a DPTR2, so AP is available.
4753                      */
4754                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4755                 }
4756                 else
4757                 {
4758                     aopPut(AOP(result),"a",0);
4759                 }
4760             
4761                 emitcode("pop","acc");
4762                 lbl = newiTempLabel(NULL);      
4763                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4764                 emitcode("cpl","a");
4765                 emitcode("addc","a,#0");
4766                 emitcode("","!tlabeldef", lbl->key+100);
4767                 aopPut(AOP(result),"a",1);
4768                 emitcode("pop","acc");
4769                 if (AOP_SIZE(result) >= 3) {
4770                         lbl = newiTempLabel(NULL);      
4771                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4772                         emitcode("cpl","a");
4773                         emitcode("addc","a,#0");                        
4774                         emitcode("","!tlabeldef", lbl->key+100);
4775                         aopPut(AOP(result),"a",2);
4776                 }
4777                 emitcode("pop","acc");
4778                 if (AOP_SIZE(result) >= 4) {
4779                         lbl = newiTempLabel(NULL);      
4780                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4781                         emitcode("cpl","a");
4782                         emitcode("addc","a,#0");                        
4783                         emitcode("","!tlabeldef", lbl->key+100);
4784                         aopPut(AOP(result),"a",3);
4785                 }
4786                 if (AOP_TYPE(result) == AOP_ACC)
4787                 {
4788                     /* We stashed the result away above. */
4789                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4790                 }           
4791                 
4792         }
4793         freeAsmop (result, NULL, ic, TRUE);
4794
4795         /* restore EA bit in F1 */
4796         lbl = newiTempLabel(NULL);
4797         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4798         emitcode ("setb","EA");
4799         emitcode("","!tlabeldef",lbl->key+100);
4800         return ;
4801 }
4802
4803 /*-----------------------------------------------------------------*/
4804 /* genMult - generates code for multiplication                     */
4805 /*-----------------------------------------------------------------*/
4806 static void
4807 genMult (iCode * ic)
4808 {
4809   operand *left = IC_LEFT (ic);
4810   operand *right = IC_RIGHT (ic);
4811   operand *result = IC_RESULT (ic);
4812
4813   D (emitcode (";", "genMult "););
4814
4815   /* assign the amsops */
4816   AOP_OP_2 (ic);
4817
4818   /* special cases first */
4819   /* both are bits */
4820   if (AOP_TYPE (left) == AOP_CRY &&
4821       AOP_TYPE (right) == AOP_CRY)
4822     {
4823       genMultbits (left, right, result, ic);
4824       goto release;
4825     }
4826
4827   /* if both are of size == 1 */
4828   if (AOP_SIZE (left) == 1 &&
4829       AOP_SIZE (right) == 1)
4830     {
4831       genMultOneByte (left, right, result, ic);
4832       goto release;
4833     }
4834
4835   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4836           /* use the ds390 ARITHMETIC accel UNIT */
4837           genMultTwoByte (left, right, result, ic);
4838           return ;
4839   }
4840   /* should have been converted to function call */
4841   assert (0);
4842
4843 release:
4844   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4846   freeAsmop (result, NULL, ic, TRUE);
4847 }
4848
4849 /*-----------------------------------------------------------------*/
4850 /* genDivbits :- division of bits                                  */
4851 /*-----------------------------------------------------------------*/
4852 static void
4853 genDivbits (operand * left,
4854             operand * right,
4855             operand * result,
4856             iCode   * ic)
4857 {
4858
4859   char *l;
4860
4861   /* the result must be bit */
4862   LOAD_AB_FOR_DIV (left, right, l);
4863   emitcode ("div", "ab");
4864   emitcode ("rrc", "a");
4865   aopOp(result, ic, TRUE, FALSE);
4866     
4867   aopPut (AOP (result), "c", 0);
4868 }
4869
4870 /*-----------------------------------------------------------------*/
4871 /* genDivOneByte : 8 bit division                                  */
4872 /*-----------------------------------------------------------------*/
4873 static void
4874 genDivOneByte (operand * left,
4875                operand * right,
4876                operand * result,
4877                iCode   * ic)
4878 {
4879   sym_link *opetype = operandType (result);
4880   char *l;
4881   symbol *lbl;
4882   int size, offset;
4883
4884   offset = 1;
4885   /* signed or unsigned */
4886   if (SPEC_USIGN (opetype))
4887     {
4888         /* unsigned is easy */
4889         LOAD_AB_FOR_DIV (left, right, l);
4890         emitcode ("div", "ab");
4891
4892         _G.accInUse++;
4893         aopOp(result, ic, TRUE, FALSE);
4894         aopPut (AOP (result), "a", 0);
4895         _G.accInUse--;
4896
4897         size = AOP_SIZE (result) - 1;
4898         
4899         while (size--)
4900         {
4901             aopPut (AOP (result), zero, offset++);
4902         }
4903       return;
4904     }
4905
4906   /* signed is a little bit more difficult */
4907
4908   /* save the signs of the operands */
4909   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4910   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4911   emitcode ("push", "acc");     /* save it on the stack */
4912
4913   /* now sign adjust for both left & right */
4914   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4915   lbl = newiTempLabel (NULL);
4916   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4917   emitcode ("cpl", "a");
4918   emitcode ("inc", "a");
4919   emitcode ("", "!tlabeldef", (lbl->key + 100));
4920   emitcode ("mov", "b,a");
4921
4922   /* sign adjust left side */
4923   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4924
4925   lbl = newiTempLabel (NULL);
4926   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4927   emitcode ("cpl", "a");
4928   emitcode ("inc", "a");
4929   emitcode ("", "!tlabeldef", (lbl->key + 100));
4930
4931   /* now the division */
4932   emitcode ("nop", "; workaround for DS80C390 div bug.");
4933   emitcode ("div", "ab");
4934   /* we are interested in the lower order
4935      only */
4936   emitcode ("mov", "b,a");
4937   lbl = newiTempLabel (NULL);
4938   emitcode ("pop", "acc");
4939   /* if there was an over flow we don't
4940      adjust the sign of the result */
4941   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4942   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4943   CLRC;
4944   emitcode ("clr", "a");
4945   emitcode ("subb", "a,b");
4946   emitcode ("mov", "b,a");
4947   emitcode ("", "!tlabeldef", (lbl->key + 100));
4948
4949   /* now we are done */
4950   _G.accInUse++;     _G.bInUse++;
4951     aopOp(result, ic, TRUE, FALSE);
4952     
4953     aopPut (AOP (result), "b", 0);
4954     
4955     size = AOP_SIZE (result) - 1;
4956     
4957     if (size > 0)
4958     {
4959       emitcode ("mov", "c,b.7");
4960       emitcode ("subb", "a,acc");
4961     }
4962     while (size--)
4963     {
4964         aopPut (AOP (result), "a", offset++);
4965     }
4966     _G.accInUse--;     _G.bInUse--;
4967
4968 }
4969
4970 /*-----------------------------------------------------------------*/
4971 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4972 /*-----------------------------------------------------------------*/
4973 static void genDivTwoByte (operand *left, operand *right, 
4974                             operand *result, iCode *ic)
4975 {
4976         sym_link *retype = getSpec(operandType(right));
4977         sym_link *letype = getSpec(operandType(left));
4978         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4979         symbol *lbl;
4980
4981         /* save EA bit in F1 */
4982         lbl = newiTempLabel(NULL);
4983         emitcode ("setb","F1");
4984         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4985         emitcode ("clr","F1");
4986         emitcode("","!tlabeldef",lbl->key+100);
4987
4988         /* load up MA with left */
4989         if (!umult) {
4990                 emitcode("clr","F0");
4991                 lbl = newiTempLabel(NULL);
4992                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4993                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4994                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4995                 emitcode ("xch", "a,b");
4996                 emitcode ("cpl","a");
4997                 emitcode ("add", "a,#1");
4998                 emitcode ("xch", "a,b");
4999                 emitcode ("cpl", "a"); // msb
5000                 emitcode ("addc","a,#0");
5001                 emitcode ("setb","F0");
5002                 emitcode ("","!tlabeldef",lbl->key+100);
5003                 emitcode ("mov","ma,b");
5004                 emitcode ("mov","ma,a");
5005         } else {
5006                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5007                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5008         }
5009
5010         /* load up MB with right */
5011         if (!umult) {
5012                 if (AOP_TYPE(right) == AOP_LIT) {
5013                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
5014                         if (val < 0) {
5015                                 lbl = newiTempLabel(NULL);
5016                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5017                                 emitcode("setb","F0");
5018                                 emitcode ("","!tlabeldef",lbl->key+100);
5019                                 val = -val;
5020                         } 
5021                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5022                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5023                 } else {
5024                         lbl = newiTempLabel(NULL);
5025                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5026                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5027                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5028                         emitcode ("xch", "a,b");
5029                         emitcode ("cpl","a");
5030                         emitcode ("add", "a,#1");
5031                         emitcode ("xch", "a,b");
5032                         emitcode ("cpl", "a"); // msb
5033                         emitcode ("addc", "a,#0");
5034                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5035                         emitcode ("setb","F0");
5036                         emitcode ("","!tlabeldef",lbl->key+100);
5037                         emitcode ("mov","mb,b");
5038                         emitcode ("mov","mb,a");
5039                 }
5040         } else {
5041                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5042                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5043         }
5044
5045         /* wait for multiplication to finish */
5046         lbl = newiTempLabel(NULL);
5047         emitcode("","!tlabeldef", lbl->key+100);
5048         emitcode("mov","a,mcnt1");
5049         emitcode("anl","a,#!constbyte",0x80);
5050         emitcode("jnz","!tlabel",lbl->key+100);
5051         
5052         freeAsmop (left, NULL, ic, TRUE);
5053         freeAsmop (right, NULL, ic,TRUE);
5054         aopOp(result, ic, TRUE, FALSE);
5055
5056         /* if unsigned then simple */   
5057         if (umult) {
5058                 aopPut(AOP(result),"ma",1);
5059                 aopPut(AOP(result),"ma",0);
5060         } else {
5061                 emitcode("push","ma");
5062                 MOVA("ma");
5063                 /* negate result if needed */
5064                 lbl = newiTempLabel(NULL);      
5065                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5066                 emitcode("cpl","a");
5067                 emitcode("add","a,#1");
5068                 emitcode("","!tlabeldef", lbl->key+100);
5069                 aopPut(AOP(result),"a",0);
5070                 emitcode("pop","acc");
5071                 lbl = newiTempLabel(NULL);      
5072                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5073                 emitcode("cpl","a");
5074                 emitcode("addc","a,#0");
5075                 emitcode("","!tlabeldef", lbl->key+100);
5076                 aopPut(AOP(result),"a",1);
5077         }
5078         freeAsmop (result, NULL, ic, TRUE);
5079         /* restore EA bit in F1 */
5080         lbl = newiTempLabel(NULL);
5081         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5082         emitcode ("setb","EA");
5083         emitcode("","!tlabeldef",lbl->key+100);
5084         return ;
5085 }
5086
5087 /*-----------------------------------------------------------------*/
5088 /* genDiv - generates code for division                            */
5089 /*-----------------------------------------------------------------*/
5090 static void
5091 genDiv (iCode * ic)
5092 {
5093   operand *left = IC_LEFT (ic);
5094   operand *right = IC_RIGHT (ic);
5095   operand *result = IC_RESULT (ic);
5096
5097   D (emitcode (";", "genDiv "););
5098
5099   /* assign the amsops */
5100   AOP_OP_2 (ic);
5101
5102   /* special cases first */
5103   /* both are bits */
5104   if (AOP_TYPE (left) == AOP_CRY &&
5105       AOP_TYPE (right) == AOP_CRY)
5106     {
5107       genDivbits (left, right, result, ic);
5108       goto release;
5109     }
5110
5111   /* if both are of size == 1 */
5112   if (AOP_SIZE (left) == 1 &&
5113       AOP_SIZE (right) == 1)
5114     {
5115       genDivOneByte (left, right, result, ic);
5116       goto release;
5117     }
5118
5119   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5120           /* use the ds390 ARITHMETIC accel UNIT */
5121           genDivTwoByte (left, right, result, ic);
5122           return ;
5123   }
5124   /* should have been converted to function call */
5125   assert (0);
5126 release:
5127   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5128   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5129   freeAsmop (result, NULL, ic, TRUE);
5130 }
5131
5132 /*-----------------------------------------------------------------*/
5133 /* genModbits :- modulus of bits                                   */
5134 /*-----------------------------------------------------------------*/
5135 static void
5136 genModbits (operand * left,
5137             operand * right,
5138             operand * result,
5139             iCode   * ic)
5140 {
5141
5142   char *l;
5143
5144   /* the result must be bit */
5145   LOAD_AB_FOR_DIV (left, right, l);
5146   emitcode ("div", "ab");
5147   emitcode ("mov", "a,b");
5148   emitcode ("rrc", "a");
5149   aopOp(result, ic, TRUE, FALSE);
5150   aopPut (AOP (result), "c", 0);
5151 }
5152
5153 /*-----------------------------------------------------------------*/
5154 /* genModOneByte : 8 bit modulus                                   */
5155 /*-----------------------------------------------------------------*/
5156 static void
5157 genModOneByte (operand * left,
5158                operand * right,
5159                operand * result,
5160                iCode   * ic)
5161 {
5162   sym_link *opetype = operandType (result);
5163   char *l;
5164   symbol *lbl;
5165
5166   /* signed or unsigned */
5167   if (SPEC_USIGN (opetype))
5168     {
5169       /* unsigned is easy */
5170       LOAD_AB_FOR_DIV (left, right, l);
5171       emitcode ("div", "ab");
5172       aopOp(result, ic, TRUE, FALSE);   
5173       aopPut (AOP (result), "b", 0);
5174       return;
5175     }
5176
5177   /* signed is a little bit more difficult */
5178
5179   /* save the signs of the operands */
5180   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5181
5182   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5183   emitcode ("push", "acc");     /* save it on the stack */
5184
5185   /* now sign adjust for both left & right */
5186   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5187
5188   lbl = newiTempLabel (NULL);
5189   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5190   emitcode ("cpl", "a");
5191   emitcode ("inc", "a");
5192   emitcode ("", "!tlabeldef", (lbl->key + 100));
5193   emitcode ("mov", "b,a");
5194
5195   /* sign adjust left side */
5196   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5197
5198   lbl = newiTempLabel (NULL);
5199   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5200   emitcode ("cpl", "a");
5201   emitcode ("inc", "a");
5202   emitcode ("", "!tlabeldef", (lbl->key + 100));
5203
5204   /* now the multiplication */
5205   emitcode ("nop", "; workaround for DS80C390 div bug.");
5206   emitcode ("div", "ab");
5207   /* we are interested in the lower order
5208      only */
5209   lbl = newiTempLabel (NULL);
5210   emitcode ("pop", "acc");
5211   /* if there was an over flow we don't
5212      adjust the sign of the result */
5213   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5214   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5215   CLRC;
5216   emitcode ("clr", "a");
5217   emitcode ("subb", "a,b");
5218   emitcode ("mov", "b,a");
5219   emitcode ("", "!tlabeldef", (lbl->key + 100));
5220   
5221   _G.bInUse++;
5222   /* now we are done */
5223   aopOp(result, ic, TRUE, FALSE);    
5224   aopPut (AOP (result), "b", 0);
5225   _G.bInUse--;
5226
5227 }
5228
5229 /*-----------------------------------------------------------------*/
5230 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5231 /*-----------------------------------------------------------------*/
5232 static void genModTwoByte (operand *left, operand *right, 
5233                             operand *result, iCode *ic)
5234 {
5235         sym_link *retype = getSpec(operandType(right));
5236         sym_link *letype = getSpec(operandType(left));
5237         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5238         symbol *lbl;
5239
5240         /* load up MA with left */
5241         /* save EA bit in F1 */
5242         lbl = newiTempLabel(NULL);
5243         emitcode ("setb","F1");
5244         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5245         emitcode ("clr","F1");
5246         emitcode("","!tlabeldef",lbl->key+100);
5247
5248         if (!umult) {
5249                 lbl = newiTempLabel(NULL);
5250                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5251                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5252                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5253                 emitcode ("xch", "a,b");
5254                 emitcode ("cpl","a");
5255                 emitcode ("add", "a,#1");
5256                 emitcode ("xch", "a,b");
5257                 emitcode ("cpl", "a"); // msb
5258                 emitcode ("addc","a,#0");
5259                 emitcode ("","!tlabeldef",lbl->key+100);
5260                 emitcode ("mov","ma,b");
5261                 emitcode ("mov","ma,a");
5262         } else {
5263                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5264                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5265         }
5266
5267         /* load up MB with right */
5268         if (!umult) {
5269                 if (AOP_TYPE(right) == AOP_LIT) {
5270                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
5271                         if (val < 0) {
5272                                 val = -val;
5273                         } 
5274                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5275                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5276                 } else {
5277                         lbl = newiTempLabel(NULL);
5278                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5279                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5280                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5281                         emitcode ("xch", "a,b");
5282                         emitcode ("cpl","a");
5283                         emitcode ("add", "a,#1");
5284                         emitcode ("xch", "a,b");
5285                         emitcode ("cpl", "a"); // msb
5286                         emitcode ("addc", "a,#0");
5287                         emitcode ("","!tlabeldef",lbl->key+100);
5288                         emitcode ("mov","mb,b");
5289                         emitcode ("mov","mb,a");
5290                 }
5291         } else {
5292                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5293                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5294         }
5295
5296         /* wait for multiplication to finish */
5297         lbl = newiTempLabel(NULL);
5298         emitcode("","!tlabeldef", lbl->key+100);
5299         emitcode("mov","a,mcnt1");
5300         emitcode("anl","a,#!constbyte",0x80);
5301         emitcode("jnz","!tlabel",lbl->key+100);
5302         
5303         freeAsmop (left, NULL, ic, TRUE);
5304         freeAsmop (right, NULL, ic,TRUE);
5305         aopOp(result, ic, TRUE, FALSE);
5306
5307         aopPut(AOP(result),"mb",1);
5308         aopPut(AOP(result),"mb",0);
5309         freeAsmop (result, NULL, ic, TRUE);
5310
5311         /* restore EA bit in F1 */
5312         lbl = newiTempLabel(NULL);
5313         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5314         emitcode ("setb","EA");
5315         emitcode("","!tlabeldef",lbl->key+100);
5316         return ;
5317 }
5318
5319 /*-----------------------------------------------------------------*/
5320 /* genMod - generates code for division                            */
5321 /*-----------------------------------------------------------------*/
5322 static void
5323 genMod (iCode * ic)
5324 {
5325   operand *left = IC_LEFT (ic);
5326   operand *right = IC_RIGHT (ic);
5327   operand *result = IC_RESULT (ic);
5328
5329   D (emitcode (";", "genMod "); );
5330
5331   /* assign the amsops */
5332   AOP_OP_2 (ic);
5333
5334   /* special cases first */
5335   /* both are bits */
5336   if (AOP_TYPE (left) == AOP_CRY &&
5337       AOP_TYPE (right) == AOP_CRY)
5338     {
5339       genModbits (left, right, result, ic);
5340       goto release;
5341     }
5342
5343   /* if both are of size == 1 */
5344   if (AOP_SIZE (left) == 1 &&
5345       AOP_SIZE (right) == 1)
5346     {
5347       genModOneByte (left, right, result, ic);
5348       goto release;
5349     }
5350
5351   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5352           /* use the ds390 ARITHMETIC accel UNIT */
5353           genModTwoByte (left, right, result, ic);
5354           return ;
5355   }
5356
5357   /* should have been converted to function call */
5358   assert (0);
5359
5360 release:
5361   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5362   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5363   freeAsmop (result, NULL, ic, TRUE);
5364 }
5365
5366 /*-----------------------------------------------------------------*/
5367 /* genIfxJump :- will create a jump depending on the ifx           */
5368 /*-----------------------------------------------------------------*/
5369 static void
5370 genIfxJump (iCode * ic, char *jval)
5371 {
5372   symbol *jlbl;
5373   symbol *tlbl = newiTempLabel (NULL);
5374   char *inst;
5375
5376   D (emitcode (";", "genIfxJump"););
5377
5378   /* if true label then we jump if condition
5379      supplied is true */
5380   if (IC_TRUE (ic))
5381     {
5382       jlbl = IC_TRUE (ic);
5383       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5384                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5385     }
5386   else
5387     {
5388       /* false label is present */
5389       jlbl = IC_FALSE (ic);
5390       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5391                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5392     }
5393   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5394     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5395   else
5396     emitcode (inst, "!tlabel", tlbl->key + 100);
5397   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5398   emitcode ("", "!tlabeldef", tlbl->key + 100);
5399
5400   /* mark the icode as generated */
5401   ic->generated = 1;
5402 }
5403
5404 /*-----------------------------------------------------------------*/
5405 /* genCmp :- greater or less than comparison                       */
5406 /*-----------------------------------------------------------------*/
5407 static void
5408 genCmp (operand * left, operand * right,
5409         iCode * ic, iCode * ifx, int sign)
5410 {
5411   int size, offset = 0;
5412   unsigned long lit = 0L;
5413   operand *result;
5414
5415   D (emitcode (";", "genCmp"););
5416
5417   result = IC_RESULT (ic);
5418
5419   /* if left & right are bit variables */
5420   if (AOP_TYPE (left) == AOP_CRY &&
5421       AOP_TYPE (right) == AOP_CRY)
5422     {
5423       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5424       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5425     }
5426   else
5427     {
5428       /* subtract right from left if at the
5429          end the carry flag is set then we know that
5430          left is greater than right */
5431       size = max (AOP_SIZE (left), AOP_SIZE (right));
5432
5433       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5434       if ((size == 1) && !sign 
5435           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5436         {
5437           symbol *lbl = newiTempLabel (NULL);
5438           emitcode ("cjne", "%s,%s,!tlabel",
5439                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5440                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5441                     lbl->key + 100);
5442           emitcode ("", "!tlabeldef", lbl->key + 100);
5443         }
5444       else
5445         {
5446           if (AOP_TYPE (right) == AOP_LIT)
5447             {
5448               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5449               /* optimize if(x < 0) or if(x >= 0) */
5450               if (lit == 0L)
5451                 {
5452                   if (!sign)
5453                     {
5454                       CLRC;
5455                     }
5456                   else
5457                     {
5458                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5459
5460                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5461                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5462
5463                       aopOp (result, ic, FALSE, FALSE);
5464
5465                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5466                         {
5467                           freeAsmop (result, NULL, ic, TRUE);
5468                           genIfxJump (ifx, "acc.7");
5469                           return;
5470                         }
5471                       else
5472                         {
5473                           emitcode ("rlc", "a");
5474                         }
5475                       goto release_freedLR;
5476                     }
5477                   goto release;
5478                 }
5479             }
5480           CLRC;
5481           while (size--)
5482             {
5483               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5484               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5485               // emitcode (";", "genCmp #2");
5486               if (sign && (size == 0))
5487                 {
5488                   // emitcode (";", "genCmp #3");
5489                   emitcode ("xrl", "a,#!constbyte",0x80);
5490                   if (AOP_TYPE (right) == AOP_LIT)
5491                     {
5492                       unsigned long lit = (unsigned long)
5493                       floatFromVal (AOP (right)->aopu.aop_lit);
5494                       // emitcode (";", "genCmp #3.1");
5495                       emitcode ("subb", "a,#!constbyte",
5496                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5497                     }
5498                   else
5499                     {
5500                       // emitcode (";", "genCmp #3.2");
5501                       saveAccWarn = 0;  
5502                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5503                       saveAccWarn = DEFAULT_ACC_WARNING;
5504                       emitcode ("xrl", "b,#!constbyte",0x80);
5505                       emitcode ("subb", "a,b");
5506                     }
5507                 }
5508               else
5509                 {
5510                   const char *s;
5511
5512                   // emitcode (";", "genCmp #4");
5513                   saveAccWarn = 0;
5514                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5515                   saveAccWarn = DEFAULT_ACC_WARNING;
5516
5517                   emitcode ("subb", "a,%s", s);
5518                 }
5519             }
5520         }
5521     }
5522
5523 release:
5524 /* Don't need the left & right operands any more; do need the result. */
5525   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5527
5528   aopOp (result, ic, FALSE, FALSE);
5529
5530 release_freedLR:
5531
5532   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5533     {
5534       outBitC (result);
5535     }
5536   else
5537     {
5538       /* if the result is used in the next
5539          ifx conditional branch then generate
5540          code a little differently */
5541       if (ifx)
5542         {
5543           genIfxJump (ifx, "c");
5544         }
5545       else
5546         {
5547           outBitC (result);
5548         }
5549       /* leave the result in acc */
5550     }
5551   freeAsmop (result, NULL, ic, TRUE);
5552 }
5553
5554 /*-----------------------------------------------------------------*/
5555 /* genCmpGt :- greater than comparison                             */
5556 /*-----------------------------------------------------------------*/
5557 static void
5558 genCmpGt (iCode * ic, iCode * ifx)
5559 {
5560   operand *left, *right;
5561   sym_link *letype, *retype;
5562   int sign;
5563
5564   D (emitcode (";", "genCmpGt ");
5565     );
5566
5567   left = IC_LEFT (ic);
5568   right = IC_RIGHT (ic);
5569
5570   letype = getSpec (operandType (left));
5571   retype = getSpec (operandType (right));
5572   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5573
5574   /* assign the left & right amsops */
5575   AOP_OP_2 (ic);
5576
5577   genCmp (right, left, ic, ifx, sign);
5578 }
5579
5580 /*-----------------------------------------------------------------*/
5581 /* genCmpLt - less than comparisons                                */
5582 /*-----------------------------------------------------------------*/
5583 static void
5584 genCmpLt (iCode * ic, iCode * ifx)
5585 {
5586   operand *left, *right;
5587   sym_link *letype, *retype;
5588   int sign;
5589
5590   D (emitcode (";", "genCmpLt "););
5591
5592   left = IC_LEFT (ic);
5593   right = IC_RIGHT (ic);
5594
5595   letype = getSpec (operandType (left));
5596   retype = getSpec (operandType (right));
5597   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5598
5599   /* assign the left & right amsops */
5600   AOP_OP_2 (ic);
5601
5602   genCmp (left, right, ic, ifx, sign);
5603 }
5604
5605 /*-----------------------------------------------------------------*/
5606 /* gencjneshort - compare and jump if not equal                    */
5607 /*-----------------------------------------------------------------*/
5608 static void
5609 gencjneshort (operand * left, operand * right, symbol * lbl)
5610 {
5611   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5612   int offset = 0;
5613   unsigned long lit = 0L;
5614
5615   D (emitcode (";", "gencjneshort");
5616     );
5617
5618   /* if the left side is a literal or
5619      if the right is in a pointer register and left
5620      is not */
5621   if ((AOP_TYPE (left) == AOP_LIT) ||
5622       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5623     {
5624       operand *t = right;
5625       right = left;
5626       left = t;
5627     }
5628
5629   if (AOP_TYPE (right) == AOP_LIT)
5630     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5631
5632   if (opIsGptr (left) || opIsGptr (right))
5633     {
5634       /* We are comparing a generic pointer to something.
5635        * Exclude the generic type byte from the comparison.
5636        */
5637       size--;
5638       D (emitcode (";", "cjneshort: generic ptr special case."););
5639     }
5640
5641
5642   /* if the right side is a literal then anything goes */
5643   if (AOP_TYPE (right) == AOP_LIT &&
5644       AOP_TYPE (left) != AOP_DIR)
5645     {
5646       while (size--)
5647         {
5648           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5649           emitcode ("cjne", "a,%s,!tlabel",
5650                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5651                     lbl->key + 100);
5652           offset++;
5653         }
5654     }
5655
5656   /* if the right side is in a register or in direct space or
5657      if the left is a pointer register & right is not */
5658   else if (AOP_TYPE (right) == AOP_REG ||
5659            AOP_TYPE (right) == AOP_DIR ||
5660            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5661            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5662     {
5663       while (size--)
5664         {
5665           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5666           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5667               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5668             emitcode ("jnz", "!tlabel", lbl->key + 100);
5669           else
5670             emitcode ("cjne", "a,%s,!tlabel",
5671                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5672                       lbl->key + 100);
5673           offset++;
5674         }
5675     }
5676   else
5677     {
5678       /* right is a pointer reg need both a & b */
5679       while (size--)
5680         {
5681           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5682           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5683           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5684           offset++;
5685         }
5686     }
5687 }
5688
5689 /*-----------------------------------------------------------------*/
5690 /* gencjne - compare and jump if not equal                         */
5691 /*-----------------------------------------------------------------*/
5692 static void
5693 gencjne (operand * left, operand * right, symbol * lbl)
5694 {
5695   symbol *tlbl = newiTempLabel (NULL);
5696
5697   D (emitcode (";", "gencjne");
5698     );
5699
5700   gencjneshort (left, right, lbl);
5701
5702   emitcode ("mov", "a,%s", one);
5703   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5704   emitcode ("", "!tlabeldef", lbl->key + 100);
5705   emitcode ("clr", "a");
5706   emitcode ("", "!tlabeldef", tlbl->key + 100);
5707 }
5708
5709 /*-----------------------------------------------------------------*/
5710 /* genCmpEq - generates code for equal to                          */
5711 /*-----------------------------------------------------------------*/
5712 static void
5713 genCmpEq (iCode * ic, iCode * ifx)
5714 {
5715   operand *left, *right, *result;
5716
5717   D (emitcode (";", "genCmpEq ");
5718     );
5719
5720   AOP_OP_2 (ic);
5721   AOP_SET_LOCALS (ic);
5722
5723   /* if literal, literal on the right or
5724      if the right is in a pointer register and left
5725      is not */
5726   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5727       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5728     {
5729       operand *t = IC_RIGHT (ic);
5730       IC_RIGHT (ic) = IC_LEFT (ic);
5731       IC_LEFT (ic) = t;
5732     }
5733
5734   if (ifx &&                    /* !AOP_SIZE(result) */
5735       OP_SYMBOL (result) &&
5736       OP_SYMBOL (result)->regType == REG_CND)
5737     {
5738       symbol *tlbl;
5739       /* if they are both bit variables */
5740       if (AOP_TYPE (left) == AOP_CRY &&
5741           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5742         {
5743           if (AOP_TYPE (right) == AOP_LIT)
5744             {
5745               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5746               if (lit == 0L)
5747                 {
5748                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5749                   emitcode ("cpl", "c");
5750                 }
5751               else if (lit == 1L)
5752                 {
5753                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5754                 }
5755               else
5756                 {
5757                   emitcode ("clr", "c");
5758                 }
5759               /* AOP_TYPE(right) == AOP_CRY */
5760             }
5761           else
5762             {
5763               symbol *lbl = newiTempLabel (NULL);
5764               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5765               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5766               emitcode ("cpl", "c");
5767               emitcode ("", "!tlabeldef", (lbl->key + 100));
5768             }
5769           /* if true label then we jump if condition
5770              supplied is true */
5771           tlbl = newiTempLabel (NULL);
5772           if (IC_TRUE (ifx))
5773             {
5774               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5775               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5776             }
5777           else
5778             {
5779               emitcode ("jc", "!tlabel", tlbl->key + 100);
5780               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5781             }
5782           emitcode ("", "!tlabeldef", tlbl->key + 100);
5783         }
5784       else
5785         {
5786           tlbl = newiTempLabel (NULL);
5787           gencjneshort (left, right, tlbl);
5788           if (IC_TRUE (ifx))
5789             {
5790               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5791               emitcode ("", "!tlabeldef", tlbl->key + 100);
5792             }
5793           else
5794             {
5795               symbol *lbl = newiTempLabel (NULL);
5796               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5797               emitcode ("", "!tlabeldef", tlbl->key + 100);
5798               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5799               emitcode ("", "!tlabeldef", lbl->key + 100);
5800             }
5801         }
5802       /* mark the icode as generated */
5803       ifx->generated = 1;
5804
5805       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5806       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5807       return;
5808     }
5809
5810   /* if they are both bit variables */
5811   if (AOP_TYPE (left) == AOP_CRY &&
5812       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5813     {
5814       if (AOP_TYPE (right) == AOP_LIT)
5815         {
5816           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5817           if (lit == 0L)
5818             {
5819               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5820               emitcode ("cpl", "c");
5821             }
5822           else if (lit == 1L)
5823             {
5824               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5825             }
5826           else
5827             {
5828               emitcode ("clr", "c");
5829             }
5830           /* AOP_TYPE(right) == AOP_CRY */
5831         }
5832       else
5833         {
5834           symbol *lbl = newiTempLabel (NULL);
5835           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5836           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5837           emitcode ("cpl", "c");
5838           emitcode ("", "!tlabeldef", (lbl->key + 100));
5839         }
5840
5841       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5842       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5843
5844       aopOp (result, ic, TRUE, FALSE);
5845
5846       /* c = 1 if egal */
5847       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5848         {
5849           outBitC (result);
5850           goto release;
5851         }
5852       if (ifx)
5853         {
5854           genIfxJump (ifx, "c");
5855           goto release;
5856         }
5857       /* if the result is used in an arithmetic operation
5858          then put the result in place */
5859       outBitC (result);
5860     }
5861   else
5862     {
5863       gencjne (left, right, newiTempLabel (NULL));
5864
5865       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5866       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5867
5868       aopOp (result, ic, TRUE, FALSE);
5869
5870       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5871         {
5872           aopPut (AOP (result), "a", 0);
5873           goto release;
5874         }
5875       if (ifx)
5876         {
5877           genIfxJump (ifx, "a");
5878           goto release;
5879         }
5880       /* if the result is used in an arithmetic operation
5881          then put the result in place */
5882       if (AOP_TYPE (result) != AOP_CRY)
5883         outAcc (result);
5884       /* leave the result in acc */
5885     }
5886
5887 release:
5888   freeAsmop (result, NULL, ic, TRUE);
5889 }
5890
5891 /*-----------------------------------------------------------------*/
5892 /* ifxForOp - returns the icode containing the ifx for operand     */
5893 /*-----------------------------------------------------------------*/
5894 static iCode *
5895 ifxForOp (operand * op, iCode * ic)
5896 {
5897   /* if true symbol then needs to be assigned */
5898   if (IS_TRUE_SYMOP (op))
5899     return NULL;
5900
5901   /* if this has register type condition and
5902      the next instruction is ifx with the same operand
5903      and live to of the operand is upto the ifx only then */
5904   if (ic->next &&
5905       ic->next->op == IFX &&
5906       IC_COND (ic->next)->key == op->key &&
5907       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5908     return ic->next;
5909
5910   return NULL;
5911 }
5912 /*-----------------------------------------------------------------*/
5913 /* hasInc - operand is incremented before any other use            */
5914 /*-----------------------------------------------------------------*/
5915 static iCode *
5916 hasInc (operand *op, iCode *ic, int osize)
5917 {
5918   sym_link *type = operandType(op);
5919   sym_link *retype = getSpec (type);
5920   iCode *lic = ic->next;
5921   int isize ;
5922   
5923   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5924   if (!IS_SYMOP(op)) return NULL;
5925
5926   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5927   if (IS_AGGREGATE(type->next)) return NULL;
5928   if (osize != (isize = getSize(type->next))) return NULL;
5929
5930   while (lic) {
5931       /* if operand of the form op = op + <sizeof *op> */
5932       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5933           isOperandEqual(IC_RESULT(lic),op) && 
5934           isOperandLiteral(IC_RIGHT(lic)) &&
5935           operandLitValue(IC_RIGHT(lic)) == isize) {
5936           return lic;
5937       }
5938       /* if the operand used or deffed */
5939       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5940           return NULL;
5941       }
5942       /* if GOTO or IFX */
5943       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5944       lic = lic->next;
5945   }
5946   return NULL;
5947 }
5948
5949 /*-----------------------------------------------------------------*/
5950 /* genAndOp - for && operation                                     */
5951 /*-----------------------------------------------------------------*/
5952 static void
5953 genAndOp (iCode * ic)
5954 {
5955   operand *left, *right, *result;
5956   symbol *tlbl;
5957
5958   D (emitcode (";", "genAndOp "););
5959
5960   /* note here that && operations that are in an
5961      if statement are taken away by backPatchLabels
5962      only those used in arthmetic operations remain */
5963   AOP_OP_2 (ic);
5964   AOP_SET_LOCALS (ic);
5965
5966   /* if both are bit variables */
5967   if (AOP_TYPE (left) == AOP_CRY &&
5968       AOP_TYPE (right) == AOP_CRY)
5969     {
5970       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5971       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5972       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5973       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5974   
5975       aopOp (result,ic,FALSE, FALSE);
5976       outBitC (result);
5977     }
5978   else
5979     {
5980       tlbl = newiTempLabel (NULL);
5981       toBoolean (left);
5982       emitcode ("jz", "!tlabel", tlbl->key + 100);
5983       toBoolean (right);
5984       emitcode ("", "!tlabeldef", tlbl->key + 100);
5985       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5987   
5988       aopOp (result,ic,FALSE, FALSE);
5989       outBitAcc (result);
5990     }
5991     freeAsmop (result, NULL, ic, TRUE);
5992 }
5993
5994
5995 /*-----------------------------------------------------------------*/
5996 /* genOrOp - for || operation                                      */
5997 /*-----------------------------------------------------------------*/
5998 static void
5999 genOrOp (iCode * ic)
6000 {
6001   operand *left, *right, *result;
6002   symbol *tlbl;
6003
6004   D (emitcode (";", "genOrOp "););
6005
6006   /* note here that || operations that are in an
6007      if statement are taken away by backPatchLabels
6008      only those used in arthmetic operations remain */
6009   AOP_OP_2 (ic);
6010   AOP_SET_LOCALS (ic);
6011
6012   /* if both are bit variables */
6013   if (AOP_TYPE (left) == AOP_CRY &&
6014       AOP_TYPE (right) == AOP_CRY)
6015     {
6016       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6017       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6018       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6019       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6020   
6021       aopOp (result,ic,FALSE, FALSE);
6022       
6023       outBitC (result);
6024     }
6025   else
6026     {
6027       tlbl = newiTempLabel (NULL);
6028       toBoolean (left);
6029       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6030       toBoolean (right);
6031       emitcode ("", "!tlabeldef", tlbl->key + 100);
6032       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6033       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6034   
6035       aopOp (result,ic,FALSE, FALSE);
6036       
6037       outBitAcc (result);
6038     }
6039
6040   freeAsmop (result, NULL, ic, TRUE);
6041 }
6042
6043 /*-----------------------------------------------------------------*/
6044 /* isLiteralBit - test if lit == 2^n                               */
6045 /*-----------------------------------------------------------------*/
6046 static int
6047 isLiteralBit (unsigned long lit)
6048 {
6049   unsigned long pw[32] =
6050   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6051    0x100L, 0x200L, 0x400L, 0x800L,
6052    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6053    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6054    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6055    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6056    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6057   int idx;
6058
6059   for (idx = 0; idx < 32; idx++)
6060     if (lit == pw[idx])
6061       return idx + 1;
6062   return 0;
6063 }
6064
6065 /*-----------------------------------------------------------------*/
6066 /* continueIfTrue -                                                */
6067 /*-----------------------------------------------------------------*/
6068 static void
6069 continueIfTrue (iCode * ic)
6070 {
6071   if (IC_TRUE (ic))
6072     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6073   ic->generated = 1;
6074 }
6075
6076 /*-----------------------------------------------------------------*/
6077 /* jmpIfTrue -                                                     */
6078 /*-----------------------------------------------------------------*/
6079 static void
6080 jumpIfTrue (iCode * ic)
6081 {
6082   if (!IC_TRUE (ic))
6083     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6084   ic->generated = 1;
6085 }
6086
6087 /*-----------------------------------------------------------------*/
6088 /* jmpTrueOrFalse -                                                */
6089 /*-----------------------------------------------------------------*/
6090 static void
6091 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6092 {
6093   // ugly but optimized by peephole
6094   if (IC_TRUE (ic))
6095     {
6096       symbol *nlbl = newiTempLabel (NULL);
6097       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6098       emitcode ("", "!tlabeldef", tlbl->key + 100);
6099       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6100       emitcode ("", "!tlabeldef", nlbl->key + 100);
6101     }
6102   else
6103     {
6104       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6105       emitcode ("", "!tlabeldef", tlbl->key + 100);
6106     }
6107   ic->generated = 1;
6108 }
6109
6110 // Generate code to perform a bit-wise logic operation
6111 // on two operands in far space (assumed to already have been 
6112 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6113 // in far space. This requires pushing the result on the stack
6114 // then popping it into the result.
6115 static void
6116 genFarFarLogicOp(iCode *ic, char *logicOp)
6117 {
6118       int size, resultSize, compSize;
6119       int offset = 0;
6120       
6121       TR_AP("#5");
6122       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6123       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6124                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6125       
6126       _startLazyDPSEvaluation();
6127       for (size = compSize; (size--); offset++)
6128       {
6129           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6130           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6131           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6132           
6133           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6134           emitcode ("push", "acc");
6135       }
6136       _endLazyDPSEvaluation();
6137      
6138       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6139       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6140       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6141      
6142       resultSize = AOP_SIZE(IC_RESULT(ic));
6143
6144       ADJUST_PUSHED_RESULT(compSize, resultSize);
6145
6146       _startLazyDPSEvaluation();
6147       while (compSize--)
6148       {
6149           emitcode ("pop", "acc");
6150           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6151       }
6152       _endLazyDPSEvaluation();
6153       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6154 }
6155
6156
6157 /*-----------------------------------------------------------------*/
6158 /* genAnd  - code for and                                          */
6159 /*-----------------------------------------------------------------*/
6160 static void
6161 genAnd (iCode * ic, iCode * ifx)
6162 {
6163   operand *left, *right, *result;
6164   int size, offset = 0;
6165   unsigned long lit = 0L;
6166   int bytelit;
6167   char buff[10];
6168   bool pushResult;
6169
6170   D (emitcode (";", "genAnd "););
6171
6172   AOP_OP_3_NOFATAL (ic, pushResult);
6173   AOP_SET_LOCALS (ic);
6174
6175   if (pushResult)
6176   {
6177       genFarFarLogicOp(ic, "anl");
6178       return;
6179   }  
6180
6181 #ifdef DEBUG_TYPE
6182   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6183             AOP_TYPE (result),
6184             AOP_TYPE (left), AOP_TYPE (right));
6185   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6186             AOP_SIZE (result),
6187             AOP_SIZE (left), AOP_SIZE (right));
6188 #endif
6189
6190   /* if left is a literal & right is not then exchange them */
6191   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6192 #ifdef LOGIC_OPS_BROKEN      
6193     ||  AOP_NEEDSACC (left)
6194 #endif
6195     )
6196     {
6197       operand *tmp = right;
6198       right = left;
6199       left = tmp;
6200     }
6201
6202   /* if result = right then exchange them */
6203   if (sameRegs (AOP (result), AOP (right)))
6204     {
6205       operand *tmp = right;
6206       right = left;
6207       left = tmp;
6208     }
6209
6210   /* if right is bit then exchange them */
6211   if (AOP_TYPE (right) == AOP_CRY &&
6212       AOP_TYPE (left) != AOP_CRY)
6213     {
6214       operand *tmp = right;
6215       right = left;
6216       left = tmp;
6217     }
6218   if (AOP_TYPE (right) == AOP_LIT)
6219     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6220
6221   size = AOP_SIZE (result);
6222
6223   // if(bit & yy)
6224   // result = bit & yy;
6225   if (AOP_TYPE (left) == AOP_CRY)
6226     {
6227       // c = bit & literal;
6228       if (AOP_TYPE (right) == AOP_LIT)
6229         {
6230           if (lit & 1)
6231             {
6232               if (size && sameRegs (AOP (result), AOP (left)))
6233                 // no change
6234                 goto release;
6235               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6236             }
6237           else
6238             {
6239               // bit(result) = 0;
6240               if (size && (AOP_TYPE (result) == AOP_CRY))
6241                 {
6242                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6243                   goto release;
6244                 }
6245               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6246                 {
6247                   jumpIfTrue (ifx);
6248                   goto release;
6249                 }
6250               emitcode ("clr", "c");
6251             }
6252         }
6253       else
6254         {
6255           if (AOP_TYPE (right) == AOP_CRY)
6256             {
6257               // c = bit & bit;
6258               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6259               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6260             }
6261           else
6262             {
6263               // c = bit & val;
6264               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6265               // c = lsb
6266               emitcode ("rrc", "a");
6267               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6268             }
6269         }
6270       // bit = c
6271       // val = c
6272       if (size)
6273         outBitC (result);
6274       // if(bit & ...)
6275       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6276         genIfxJump (ifx, "c");
6277       goto release;
6278     }
6279
6280   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6281   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6282   if ((AOP_TYPE (right) == AOP_LIT) &&
6283       (AOP_TYPE (result) == AOP_CRY) &&
6284       (AOP_TYPE (left) != AOP_CRY))
6285     {
6286       int posbit = isLiteralBit (lit);
6287       /* left &  2^n */
6288       if (posbit)
6289         {
6290           posbit--;
6291           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6292           // bit = left & 2^n
6293           if (size)
6294             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6295           // if(left &  2^n)
6296           else
6297             {
6298               if (ifx)
6299                 {
6300                   SNPRINTF (buff, sizeof(buff), 
6301                             "acc.%d", posbit & 0x07);
6302                   genIfxJump (ifx, buff);
6303                 }
6304               else 
6305                   {
6306                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6307                   }
6308               goto release;
6309             }
6310         }
6311       else
6312         {
6313           symbol *tlbl = newiTempLabel (NULL);
6314           int sizel = AOP_SIZE (left);
6315           if (size)
6316             emitcode ("setb", "c");
6317           while (sizel--)
6318             {
6319               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6320                 {
6321                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6322                   // byte ==  2^n ?
6323                   if ((posbit = isLiteralBit (bytelit)) != 0)
6324                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6325                   else
6326                     {
6327                       if (bytelit != 0x0FFL)
6328                         emitcode ("anl", "a,%s",
6329                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6330                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6331                     }
6332                 }
6333               offset++;
6334             }
6335           // bit = left & literal
6336           if (size)
6337             {
6338               emitcode ("clr", "c");
6339               emitcode ("", "!tlabeldef", tlbl->key + 100);
6340             }
6341           // if(left & literal)
6342           else
6343             {
6344               if (ifx)
6345                 jmpTrueOrFalse (ifx, tlbl);
6346               goto release;
6347             }
6348         }
6349       outBitC (result);
6350       goto release;
6351     }
6352
6353   /* if left is same as result */
6354   if (sameRegs (AOP (result), AOP (left)))
6355     {
6356       for (; size--; offset++)
6357         {
6358           if (AOP_TYPE (right) == AOP_LIT)
6359             {
6360               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6361                 continue;
6362               else if (bytelit == 0)
6363                 aopPut (AOP (result), zero, offset);
6364               else if (IS_AOP_PREG (result))
6365                 {
6366                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6367                   emitcode ("anl", "a,%s",
6368                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6369                   aopPut (AOP (result), "a", offset);
6370                 }
6371               else
6372                 emitcode ("anl", "%s,%s",
6373                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6374                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6375             }
6376           else
6377             {
6378               if (AOP_TYPE (left) == AOP_ACC)
6379                 emitcode ("anl", "a,%s",
6380                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6381               else
6382                 {
6383                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6384                   if (IS_AOP_PREG (result))
6385                     {
6386                       emitcode ("anl", "a,%s",
6387                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6388                       aopPut (AOP (result), "a", offset);
6389                     }
6390                   else
6391                     emitcode ("anl", "%s,a",
6392                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6393                 }
6394             }
6395         }
6396     }
6397   else
6398     {
6399       // left & result in different registers
6400       if (AOP_TYPE (result) == AOP_CRY)
6401         {
6402           // result = bit
6403           // if(size), result in bit
6404           // if(!size && ifx), conditional oper: if(left & right)
6405           symbol *tlbl = newiTempLabel (NULL);
6406           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6407           if (size)
6408             emitcode ("setb", "c");
6409           while (sizer--)
6410             {
6411               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6412                 emitcode ("anl", "a,%s",
6413                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6414               } else {
6415                 if (AOP_TYPE(left)==AOP_ACC) {
6416                   emitcode("mov", "b,a");
6417                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6418                   emitcode("anl", "a,b");
6419                 }else {
6420                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6421                   emitcode ("anl", "a,%s",
6422                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6423                 }
6424               }
6425               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6426               offset++;
6427             }
6428           if (size)
6429             {
6430               CLRC;
6431               emitcode ("", "!tlabeldef", tlbl->key + 100);
6432               outBitC (result);
6433             }
6434           else if (ifx)
6435             jmpTrueOrFalse (ifx, tlbl);
6436         }
6437       else
6438         {
6439           for (; (size--); offset++)
6440             {
6441               // normal case
6442               // result = left & right
6443               if (AOP_TYPE (right) == AOP_LIT)
6444                 {
6445                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6446                     {
6447                       aopPut (AOP (result),
6448                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6449                               offset);
6450                       continue;
6451                     }
6452                   else if (bytelit == 0)
6453                     {
6454                       aopPut (AOP (result), zero, offset);
6455                       continue;
6456                     }
6457                   D (emitcode (";", "better literal AND."););
6458                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6459                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6460                                                     FALSE, FALSE, DP2_RESULT_REG));
6461
6462                 }
6463               else
6464                 {
6465                   // faster than result <- left, anl result,right
6466                   // and better if result is SFR
6467                   if (AOP_TYPE (left) == AOP_ACC)
6468                     {
6469                       emitcode ("anl", "a,%s", 
6470                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6471                     }
6472                   else
6473                     {
6474                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6475                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6476                       {
6477                           emitcode("mov", "b,a");
6478                           rOp = "b";
6479                       }
6480                         
6481                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6482                       emitcode ("anl", "a,%s", rOp);
6483                     }                   
6484                 }
6485               aopPut (AOP (result), "a", offset);
6486             }
6487         }
6488     }
6489
6490 release:
6491   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6492   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6493   freeAsmop (result, NULL, ic, TRUE);
6494 }
6495
6496
6497 /*-----------------------------------------------------------------*/
6498 /* genOr  - code for or                                            */
6499 /*-----------------------------------------------------------------*/
6500 static void
6501 genOr (iCode * ic, iCode * ifx)
6502 {
6503   operand *left, *right, *result;
6504   int size, offset = 0;
6505   unsigned long lit = 0L;
6506   bool     pushResult;
6507
6508   D (emitcode (";", "genOr "););
6509
6510   AOP_OP_3_NOFATAL (ic, pushResult);
6511   AOP_SET_LOCALS (ic);
6512
6513   if (pushResult)
6514   {
6515       genFarFarLogicOp(ic, "orl");
6516       return;
6517   }
6518
6519
6520 #ifdef DEBUG_TYPE
6521   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6522             AOP_TYPE (result),
6523             AOP_TYPE (left), AOP_TYPE (right));
6524   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6525             AOP_SIZE (result),
6526             AOP_SIZE (left), AOP_SIZE (right));
6527 #endif
6528
6529   /* if left is a literal & right is not then exchange them */
6530   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6531 #ifdef LOGIC_OPS_BROKEN
6532    || AOP_NEEDSACC (left) // I think this is a net loss now.
6533 #endif      
6534       )
6535     {
6536       operand *tmp = right;
6537       right = left;
6538       left = tmp;
6539     }
6540
6541   /* if result = right then exchange them */
6542   if (sameRegs (AOP (result), AOP (right)))
6543     {
6544       operand *tmp = right;
6545       right = left;
6546       left = tmp;
6547     }
6548
6549   /* if right is bit then exchange them */
6550   if (AOP_TYPE (right) == AOP_CRY &&
6551       AOP_TYPE (left) != AOP_CRY)
6552     {
6553       operand *tmp = right;
6554       right = left;
6555       left = tmp;
6556     }
6557   if (AOP_TYPE (right) == AOP_LIT)
6558     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6559
6560   size = AOP_SIZE (result);
6561
6562   // if(bit | yy)
6563   // xx = bit | yy;
6564   if (AOP_TYPE (left) == AOP_CRY)
6565     {
6566       if (AOP_TYPE (right) == AOP_LIT)
6567         {
6568           // c = bit & literal;
6569           if (lit)
6570             {
6571               // lit != 0 => result = 1
6572               if (AOP_TYPE (result) == AOP_CRY)
6573                 {
6574                   if (size)
6575                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6576                   else if (ifx)
6577                     continueIfTrue (ifx);
6578                   goto release;
6579                 }
6580               emitcode ("setb", "c");
6581             }
6582           else
6583             {
6584               // lit == 0 => result = left
6585               if (size && sameRegs (AOP (result), AOP (left)))
6586                 goto release;
6587               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6588             }
6589         }
6590       else
6591         {
6592           if (AOP_TYPE (right) == AOP_CRY)
6593             {
6594               // c = bit | bit;
6595               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6596               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6597             }
6598           else
6599             {
6600               // c = bit | val;
6601               symbol *tlbl = newiTempLabel (NULL);
6602               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6603                 emitcode ("setb", "c");
6604               emitcode ("jb", "%s,!tlabel",
6605                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6606               toBoolean (right);
6607               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6608               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6609                 {
6610                   jmpTrueOrFalse (ifx, tlbl);
6611                   goto release;
6612                 }
6613               else
6614                 {
6615                   CLRC;
6616                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6617                 }
6618             }
6619         }
6620       // bit = c
6621       // val = c
6622       if (size)
6623         outBitC (result);
6624       // if(bit | ...)
6625       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6626            genIfxJump (ifx, "c");
6627       goto release;
6628     }
6629
6630   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6631   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6632   if ((AOP_TYPE (right) == AOP_LIT) &&
6633       (AOP_TYPE (result) == AOP_CRY) &&
6634       (AOP_TYPE (left) != AOP_CRY))
6635     {
6636       if (lit)
6637         {
6638           // result = 1
6639           if (size)
6640             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6641           else
6642             continueIfTrue (ifx);
6643           goto release;
6644         }
6645       else
6646         {
6647           // lit = 0, result = boolean(left)
6648           if (size)
6649             emitcode ("setb", "c");
6650           toBoolean (right);
6651           if (size)
6652             {
6653               symbol *tlbl = newiTempLabel (NULL);
6654               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6655               CLRC;
6656               emitcode ("", "!tlabeldef", tlbl->key + 100);
6657             }
6658           else
6659             {
6660               genIfxJump (ifx, "a");
6661               goto release;
6662             }
6663         }
6664       outBitC (result);
6665       goto release;
6666     }
6667
6668   /* if left is same as result */
6669   if (sameRegs (AOP (result), AOP (left)))
6670     {
6671       for (; size--; offset++)
6672         {
6673           if (AOP_TYPE (right) == AOP_LIT)
6674             {
6675               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6676                 {
6677                   continue;
6678                 }
6679               else
6680                 {
6681                   if (IS_AOP_PREG (left))
6682                     {
6683                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6684                       emitcode ("orl", "a,%s",
6685                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6686                       aopPut (AOP (result), "a", offset);
6687                     }
6688                   else
6689                     {
6690                       emitcode ("orl", "%s,%s",
6691                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6692                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6693                     }
6694                 }
6695             }
6696           else
6697             {
6698               if (AOP_TYPE (left) == AOP_ACC)
6699                 {
6700                   emitcode ("orl", "a,%s",
6701                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6702                 }
6703               else
6704                 {
6705                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6706                   if (IS_AOP_PREG (left))
6707                     {
6708                       emitcode ("orl", "a,%s", 
6709                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6710                       aopPut (AOP (result), "a", offset);
6711                     }
6712                   else
6713                     {
6714                       emitcode ("orl", "%s,a",
6715                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6716                     }
6717                 }
6718             }
6719         }
6720     }
6721   else
6722     {
6723       // left & result in different registers
6724       if (AOP_TYPE (result) == AOP_CRY)
6725         {
6726           // result = bit
6727           // if(size), result in bit
6728           // if(!size && ifx), conditional oper: if(left | right)
6729           symbol *tlbl = newiTempLabel (NULL);
6730           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6731           if (size)
6732             emitcode ("setb", "c");
6733           while (sizer--)
6734             {
6735               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6736                 emitcode ("orl", "a,%s",
6737                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6738               } else {
6739                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6740                 emitcode ("orl", "a,%s",
6741                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6742               }
6743               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6744               offset++;
6745             }
6746           if (size)
6747             {
6748               CLRC;
6749               emitcode ("", "!tlabeldef", tlbl->key + 100);
6750               outBitC (result);
6751             }
6752           else if (ifx)
6753             jmpTrueOrFalse (ifx, tlbl);
6754         }
6755       else
6756         {
6757             _startLazyDPSEvaluation();
6758           for (; (size--); offset++)
6759             {
6760               // normal case
6761               // result = left & right
6762               if (AOP_TYPE (right) == AOP_LIT)
6763                 {
6764                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6765                     {
6766                       aopPut (AOP (result),
6767                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6768                               offset);
6769                       continue;
6770                     }
6771                   D (emitcode (";", "better literal OR."););
6772                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6773                   emitcode ("orl", "a, %s",
6774                             aopGet (AOP (right), offset,
6775                                     FALSE, FALSE, DP2_RESULT_REG));
6776
6777                 }
6778               else
6779                 {
6780                   // faster than result <- left, anl result,right
6781                   // and better if result is SFR
6782                   if (AOP_TYPE (left) == AOP_ACC)
6783                     {
6784                       emitcode ("orl", "a,%s",
6785                                 aopGet (AOP (right), offset,
6786                                         FALSE, FALSE, DP2_RESULT_REG));
6787                     }
6788                   else
6789                     {
6790                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6791                         
6792                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6793                       {
6794                           emitcode("mov", "b,a");
6795                           rOp = "b";
6796                       }
6797                         
6798                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6799                       emitcode ("orl", "a,%s", rOp);
6800                     }
6801                 }
6802               aopPut (AOP (result), "a", offset);
6803             }
6804             _endLazyDPSEvaluation();
6805         }
6806     }
6807
6808 release:
6809   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6810   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6811   freeAsmop (result, NULL, ic, TRUE);
6812 }
6813
6814 /*-----------------------------------------------------------------*/
6815 /* genXor - code for xclusive or                                   */
6816 /*-----------------------------------------------------------------*/
6817 static void
6818 genXor (iCode * ic, iCode * ifx)
6819 {
6820   operand *left, *right, *result;
6821   int size, offset = 0;
6822   unsigned long lit = 0L;
6823   bool pushResult;
6824
6825   D (emitcode (";", "genXor "););
6826
6827   AOP_OP_3_NOFATAL (ic, pushResult);
6828   AOP_SET_LOCALS (ic);
6829
6830   if (pushResult)
6831   {
6832       genFarFarLogicOp(ic, "xrl");
6833       return;
6834   }  
6835
6836 #ifdef DEBUG_TYPE
6837   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6838             AOP_TYPE (result),
6839             AOP_TYPE (left), AOP_TYPE (right));
6840   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6841             AOP_SIZE (result),
6842             AOP_SIZE (left), AOP_SIZE (right));
6843 #endif
6844
6845   /* if left is a literal & right is not ||
6846      if left needs acc & right does not */
6847   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6848 #ifdef LOGIC_OPS_BROKEN      
6849       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6850 #endif
6851      )
6852     {
6853       operand *tmp = right;
6854       right = left;
6855       left = tmp;
6856     }
6857
6858   /* if result = right then exchange them */
6859   if (sameRegs (AOP (result), AOP (right)))
6860     {
6861       operand *tmp = right;
6862       right = left;
6863       left = tmp;
6864     }
6865
6866   /* if right is bit then exchange them */
6867   if (AOP_TYPE (right) == AOP_CRY &&
6868       AOP_TYPE (left) != AOP_CRY)
6869     {
6870       operand *tmp = right;
6871       right = left;
6872       left = tmp;
6873     }
6874   if (AOP_TYPE (right) == AOP_LIT)
6875     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6876
6877   size = AOP_SIZE (result);
6878
6879   // if(bit ^ yy)
6880   // xx = bit ^ yy;
6881   if (AOP_TYPE (left) == AOP_CRY)
6882     {
6883       if (AOP_TYPE (right) == AOP_LIT)
6884         {
6885           // c = bit & literal;
6886           if (lit >> 1)
6887             {
6888               // lit>>1  != 0 => result = 1
6889               if (AOP_TYPE (result) == AOP_CRY)
6890                 {
6891                   if (size)
6892                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6893                   else if (ifx)
6894                     continueIfTrue (ifx);
6895                   goto release;
6896                 }
6897               emitcode ("setb", "c");
6898             }
6899           else
6900             {
6901               // lit == (0 or 1)
6902               if (lit == 0)
6903                 {
6904                   // lit == 0, result = left
6905                   if (size && sameRegs (AOP (result), AOP (left)))
6906                     goto release;
6907                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6908                 }
6909               else
6910                 {
6911                   // lit == 1, result = not(left)
6912                   if (size && sameRegs (AOP (result), AOP (left)))
6913                     {
6914                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6915                       goto release;
6916                     }
6917                   else
6918                     {
6919                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6920                       emitcode ("cpl", "c");
6921                     }
6922                 }
6923             }
6924
6925         }
6926       else
6927         {
6928           // right != literal
6929           symbol *tlbl = newiTempLabel (NULL);
6930           if (AOP_TYPE (right) == AOP_CRY)
6931             {
6932               // c = bit ^ bit;
6933               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6934             }
6935           else
6936             {
6937               int sizer = AOP_SIZE (right);
6938               // c = bit ^ val
6939               // if val>>1 != 0, result = 1
6940               emitcode ("setb", "c");
6941               while (sizer)
6942                 {
6943                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6944                   if (sizer == 1)
6945                     // test the msb of the lsb
6946                     emitcode ("anl", "a,#!constbyte",0xfe);
6947                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6948                   sizer--;
6949                 }
6950               // val = (0,1)
6951               emitcode ("rrc", "a");
6952             }
6953           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6954           emitcode ("cpl", "c");
6955           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6956         }
6957       // bit = c
6958       // val = c
6959       if (size)
6960         outBitC (result);
6961       // if(bit | ...)
6962       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6963         genIfxJump (ifx, "c");
6964       goto release;
6965     }
6966
6967   if (sameRegs (AOP (result), AOP (left)))
6968     {
6969       /* if left is same as result */
6970       for (; size--; offset++)
6971         {
6972           if (AOP_TYPE (right) == AOP_LIT)
6973             {
6974               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6975                 continue;
6976               else if (IS_AOP_PREG (left))
6977                 {
6978                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6979                   emitcode ("xrl", "a,%s",
6980                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6981                   aopPut (AOP (result), "a", offset);
6982                 }
6983               else
6984                 emitcode ("xrl", "%s,%s",
6985                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6986                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6987             }
6988           else
6989             {
6990               if (AOP_TYPE (left) == AOP_ACC)
6991                 emitcode ("xrl", "a,%s",
6992                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6993               else
6994                 {
6995                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6996                   if (IS_AOP_PREG (left))
6997                     {
6998                       emitcode ("xrl", "a,%s",
6999                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7000                       aopPut (AOP (result), "a", offset);
7001                     }
7002                   else
7003                     emitcode ("xrl", "%s,a",
7004                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7005                 }
7006             }
7007         }
7008     }
7009   else
7010     {
7011       // left & result in different registers
7012       if (AOP_TYPE (result) == AOP_CRY)
7013         {
7014           // result = bit
7015           // if(size), result in bit
7016           // if(!size && ifx), conditional oper: if(left ^ right)
7017           symbol *tlbl = newiTempLabel (NULL);
7018           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7019                   
7020           if (size)
7021             emitcode ("setb", "c");
7022           while (sizer--)
7023             {
7024               if ((AOP_TYPE (right) == AOP_LIT) &&
7025                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7026                 {
7027                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7028                 }
7029               else
7030                 {
7031                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7032                     emitcode ("xrl", "a,%s",
7033                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7034                   } else {
7035                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7036                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7037                       {
7038                           emitcode("mov", "b,a");
7039                           rOp = "b";
7040                       }
7041                         
7042                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7043                       emitcode ("xrl", "a,%s", rOp);                  
7044                   }
7045                 }
7046               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7047               offset++;
7048             }
7049           if (size)
7050             {
7051               CLRC;
7052               emitcode ("", "!tlabeldef", tlbl->key + 100);
7053               outBitC (result);
7054             }
7055           else if (ifx)
7056             jmpTrueOrFalse (ifx, tlbl);
7057         }
7058       else
7059         {
7060         for (; (size--); offset++)
7061           {
7062             // normal case
7063             // result = left & right
7064             if (AOP_TYPE (right) == AOP_LIT)
7065               {
7066                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7067                   {
7068                     aopPut (AOP (result),
7069                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7070                             offset);
7071                     continue;
7072                   }
7073                 D (emitcode (";", "better literal XOR."););
7074                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7075                 emitcode ("xrl", "a, %s",
7076                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7077               }
7078             else
7079               {
7080                 // faster than result <- left, anl result,right
7081                 // and better if result is SFR
7082                 if (AOP_TYPE (left) == AOP_ACC)
7083                   {
7084                     emitcode ("xrl", "a,%s",
7085                               aopGet (AOP (right), offset,
7086                                       FALSE, FALSE, DP2_RESULT_REG));
7087                   }
7088                 else
7089                   {
7090                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7091                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7092                       {
7093                           emitcode("mov", "b,a");
7094                           rOp = "b";
7095                       }
7096                         
7097                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7098                       emitcode ("xrl", "a,%s", rOp);
7099                   }
7100               }
7101             aopPut (AOP (result), "a", offset);
7102           }
7103         }
7104         
7105     }
7106
7107 release:
7108   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7109   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7110   freeAsmop (result, NULL, ic, TRUE);
7111 }
7112
7113 /*-----------------------------------------------------------------*/
7114 /* genInline - write the inline code out                           */
7115 /*-----------------------------------------------------------------*/
7116 static void
7117 genInline (iCode * ic)
7118 {
7119   char *buffer, *bp, *bp1;
7120
7121   D (emitcode (";", "genInline "); );
7122
7123   _G.inLine += (!options.asmpeep);
7124
7125   buffer = Safe_strdup(IC_INLINE(ic));
7126   bp = buffer;
7127   bp1 = buffer;
7128
7129   /* emit each line as a code */
7130   while (*bp)
7131     {
7132       if (*bp == '\n')
7133         {
7134           *bp++ = '\0';
7135           emitcode (bp1, "");
7136           bp1 = bp;
7137         }
7138       else
7139         {
7140           if (*bp == ':')
7141             {
7142               bp++;
7143               *bp = '\0';
7144               bp++;
7145               emitcode (bp1, "");
7146               bp1 = bp;
7147             }
7148           else
7149             bp++;
7150         }
7151     }
7152   if (bp1 != bp)
7153     emitcode (bp1, "");
7154   /*     emitcode("",buffer); */
7155   _G.inLine -= (!options.asmpeep);
7156 }
7157
7158 /*-----------------------------------------------------------------*/
7159 /* genRRC - rotate right with carry                                */
7160 /*-----------------------------------------------------------------*/
7161 static void
7162 genRRC (iCode * ic)
7163 {
7164   operand *left, *result;
7165   int     size, offset;
7166
7167   D (emitcode (";", "genRRC "););
7168
7169   /* rotate right with carry */
7170   left = IC_LEFT (ic);
7171   result = IC_RESULT (ic);
7172   aopOp (left, ic, FALSE, FALSE);
7173   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7174
7175   /* move it to the result */
7176   size = AOP_SIZE (result);
7177   offset = size - 1;
7178   CLRC;
7179
7180   _startLazyDPSEvaluation ();
7181   while (size--)
7182     {
7183       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7184       emitcode ("rrc", "a");
7185       if (AOP_SIZE (result) > 1)
7186         aopPut (AOP (result), "a", offset--);
7187     }
7188   _endLazyDPSEvaluation ();
7189
7190   /* now we need to put the carry into the
7191      highest order byte of the result */
7192   if (AOP_SIZE (result) > 1)
7193     {
7194       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7195     }
7196   emitcode ("mov", "acc.7,c");
7197   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7198   freeAsmop (left, NULL, ic, TRUE);
7199   freeAsmop (result, NULL, ic, TRUE);
7200 }
7201
7202 /*-----------------------------------------------------------------*/
7203 /* genRLC - generate code for rotate left with carry               */
7204 /*-----------------------------------------------------------------*/
7205 static void
7206 genRLC (iCode * ic)
7207 {
7208   operand *left, *result;
7209   int size, offset;
7210   char *l;
7211
7212   D (emitcode (";", "genRLC "););
7213
7214   /* rotate right with carry */
7215   left = IC_LEFT (ic);
7216   result = IC_RESULT (ic);
7217   aopOp (left, ic, FALSE, FALSE);
7218   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7219
7220   /* move it to the result */
7221   size = AOP_SIZE (result);
7222   offset = 0;
7223   if (size--)
7224     {
7225       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7226       MOVA (l);
7227       emitcode ("add", "a,acc");
7228       if (AOP_SIZE (result) > 1)
7229         {
7230           aopPut (AOP (result), "a", offset++);
7231         }
7232
7233       _startLazyDPSEvaluation ();
7234       while (size--)
7235         {
7236           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7237           MOVA (l);
7238           emitcode ("rlc", "a");
7239           if (AOP_SIZE (result) > 1)
7240             aopPut (AOP (result), "a", offset++);
7241         }
7242       _endLazyDPSEvaluation ();
7243     }
7244   /* now we need to put the carry into the
7245      highest order byte of the result */
7246   if (AOP_SIZE (result) > 1)
7247     {
7248       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7249       MOVA (l);
7250     }
7251   emitcode ("mov", "acc.0,c");
7252   aopPut (AOP (result), "a", 0);
7253   freeAsmop (left, NULL, ic, TRUE);
7254   freeAsmop (result, NULL, ic, TRUE);
7255 }
7256
7257 /*-----------------------------------------------------------------*/
7258 /* genGetHbit - generates code get highest order bit               */
7259 /*-----------------------------------------------------------------*/
7260 static void
7261 genGetHbit (iCode * ic)
7262 {
7263   operand *left, *result;
7264   left = IC_LEFT (ic);
7265   result = IC_RESULT (ic);
7266   aopOp (left, ic, FALSE, FALSE);
7267   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7268
7269   D (emitcode (";", "genGetHbit "););
7270
7271   /* get the highest order byte into a */
7272   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7273   if (AOP_TYPE (result) == AOP_CRY)
7274     {
7275       emitcode ("rlc", "a");
7276       outBitC (result);
7277     }
7278   else
7279     {
7280       emitcode ("rl", "a");
7281       emitcode ("anl", "a,#1");
7282       outAcc (result);
7283     }
7284
7285
7286   freeAsmop (left, NULL, ic, TRUE);
7287   freeAsmop (result, NULL, ic, TRUE);
7288 }
7289
7290 /*-----------------------------------------------------------------*/
7291 /* AccRol - rotate left accumulator by known count                 */
7292 /*-----------------------------------------------------------------*/
7293 static void
7294 AccRol (int shCount)
7295 {
7296   shCount &= 0x0007;            // shCount : 0..7
7297
7298   switch (shCount)
7299     {
7300     case 0:
7301       break;
7302     case 1:
7303       emitcode ("rl", "a");
7304       break;
7305     case 2:
7306       emitcode ("rl", "a");
7307       emitcode ("rl", "a");
7308       break;
7309     case 3:
7310       emitcode ("swap", "a");
7311       emitcode ("rr", "a");
7312       break;
7313     case 4:
7314       emitcode ("swap", "a");
7315       break;
7316     case 5:
7317       emitcode ("swap", "a");
7318       emitcode ("rl", "a");
7319       break;
7320     case 6:
7321       emitcode ("rr", "a");
7322       emitcode ("rr", "a");
7323       break;
7324     case 7:
7325       emitcode ("rr", "a");
7326       break;
7327     }
7328 }
7329
7330 /*-----------------------------------------------------------------*/
7331 /* AccLsh - left shift accumulator by known count                  */
7332 /*-----------------------------------------------------------------*/
7333 static void
7334 AccLsh (int shCount)
7335 {
7336   if (shCount != 0)
7337     {
7338       if (shCount == 1)
7339         emitcode ("add", "a,acc");
7340       else if (shCount == 2)
7341         {
7342           emitcode ("add", "a,acc");
7343           emitcode ("add", "a,acc");
7344         }
7345       else
7346         {
7347           /* rotate left accumulator */
7348           AccRol (shCount);
7349           /* and kill the lower order bits */
7350           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7351         }
7352     }
7353 }
7354
7355 /*-----------------------------------------------------------------*/
7356 /* AccRsh - right shift accumulator by known count                 */
7357 /*-----------------------------------------------------------------*/
7358 static void
7359 AccRsh (int shCount)
7360 {
7361   if (shCount != 0)
7362     {
7363       if (shCount == 1)
7364         {
7365           CLRC;
7366           emitcode ("rrc", "a");
7367         }
7368       else
7369         {
7370           /* rotate right accumulator */
7371           AccRol (8 - shCount);
7372           /* and kill the higher order bits */
7373           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7374         }
7375     }
7376 }
7377
7378 #ifdef BETTER_LITERAL_SHIFT
7379 /*-----------------------------------------------------------------*/
7380 /* AccSRsh - signed right shift accumulator by known count                 */
7381 /*-----------------------------------------------------------------*/
7382 static void
7383 AccSRsh (int shCount)
7384 {
7385   symbol *tlbl;
7386   if (shCount != 0)
7387     {
7388       if (shCount == 1)
7389         {
7390           emitcode ("mov", "c,acc.7");
7391           emitcode ("rrc", "a");
7392         }
7393       else if (shCount == 2)
7394         {
7395           emitcode ("mov", "c,acc.7");
7396           emitcode ("rrc", "a");
7397           emitcode ("mov", "c,acc.7");
7398           emitcode ("rrc", "a");
7399         }
7400       else
7401         {
7402           tlbl = newiTempLabel (NULL);
7403           /* rotate right accumulator */
7404           AccRol (8 - shCount);
7405           /* and kill the higher order bits */
7406           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7407           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7408           emitcode ("orl", "a,#!constbyte",
7409                     (unsigned char) ~SRMask[shCount]);
7410           emitcode ("", "!tlabeldef", tlbl->key + 100);
7411         }
7412     }
7413 }
7414 #endif
7415
7416 #ifdef BETTER_LITERAL_SHIFT
7417 /*-----------------------------------------------------------------*/
7418 /* shiftR1Left2Result - shift right one byte from left to result   */
7419 /*-----------------------------------------------------------------*/
7420 static void
7421 shiftR1Left2Result (operand * left, int offl,
7422                     operand * result, int offr,
7423                     int shCount, int sign)
7424 {
7425   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7426   /* shift right accumulator */
7427   if (sign)
7428     AccSRsh (shCount);
7429   else
7430     AccRsh (shCount);
7431   aopPut (AOP (result), "a", offr);
7432 }
7433 #endif
7434
7435 #ifdef BETTER_LITERAL_SHIFT
7436 /*-----------------------------------------------------------------*/
7437 /* shiftL1Left2Result - shift left one byte from left to result    */
7438 /*-----------------------------------------------------------------*/
7439 static void
7440 shiftL1Left2Result (operand * left, int offl,
7441                     operand * result, int offr, int shCount)
7442 {
7443   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7444   /* shift left accumulator */
7445   AccLsh (shCount);
7446   aopPut (AOP (result), "a", offr);
7447 }
7448 #endif
7449
7450 #ifdef BETTER_LITERAL_SHIFT
7451 /*-----------------------------------------------------------------*/
7452 /* movLeft2Result - move byte from left to result                  */
7453 /*-----------------------------------------------------------------*/
7454 static void
7455 movLeft2Result (operand * left, int offl,
7456                 operand * result, int offr, int sign)
7457 {
7458   char *l;
7459   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7460   {
7461       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7462
7463       if (*l == '@' && (IS_AOP_PREG (result)))
7464       {
7465           emitcode ("mov", "a,%s", l);
7466           aopPut (AOP (result), "a", offr);
7467       }
7468       else
7469       {
7470           if (!sign)
7471           {
7472             aopPut (AOP (result), l, offr);
7473           }
7474           else
7475             {
7476               /* MSB sign in acc.7 ! */
7477               if (getDataSize (left) == offl + 1)
7478                 {
7479                   emitcode ("mov", "a,%s", l);
7480                   aopPut (AOP (result), "a", offr);
7481                 }
7482             }
7483       }
7484   }
7485 }
7486 #endif
7487
7488 #ifdef BETTER_LITERAL_SHIFT
7489 /*-----------------------------------------------------------------*/
7490 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7491 /*-----------------------------------------------------------------*/
7492 static void
7493 AccAXRrl1 (char *x)
7494 {
7495   emitcode ("rrc", "a");
7496   emitcode ("xch", "a,%s", x);
7497   emitcode ("rrc", "a");
7498   emitcode ("xch", "a,%s", x);
7499 }
7500 #endif
7501
7502 #ifdef BETTER_LITERAL_SHIFT
7503 //REMOVE ME!!!
7504 /*-----------------------------------------------------------------*/
7505 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7506 /*-----------------------------------------------------------------*/
7507 static void
7508 AccAXLrl1 (char *x)
7509 {
7510   emitcode ("xch", "a,%s", x);
7511   emitcode ("rlc", "a");
7512   emitcode ("xch", "a,%s", x);
7513   emitcode ("rlc", "a");
7514 }
7515 #endif
7516
7517 #ifdef BETTER_LITERAL_SHIFT
7518 /*-----------------------------------------------------------------*/
7519 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7520 /*-----------------------------------------------------------------*/
7521 static void
7522 AccAXLsh1 (char *x)
7523 {
7524   emitcode ("xch", "a,%s", x);
7525   emitcode ("add", "a,acc");
7526   emitcode ("xch", "a,%s", x);
7527   emitcode ("rlc", "a");
7528 }
7529 #endif
7530
7531 #ifdef BETTER_LITERAL_SHIFT
7532 /*-----------------------------------------------------------------*/
7533 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7534 /*-----------------------------------------------------------------*/
7535 static void
7536 AccAXLsh (char *x, int shCount)
7537 {
7538   switch (shCount)
7539     {
7540     case 0:
7541       break;
7542     case 1:
7543       AccAXLsh1 (x);
7544       break;
7545     case 2:
7546       AccAXLsh1 (x);
7547       AccAXLsh1 (x);
7548       break;
7549     case 3:
7550     case 4:
7551     case 5:                     // AAAAABBB:CCCCCDDD
7552
7553       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7554
7555       emitcode ("anl", "a,#!constbyte",
7556                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7557
7558       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7559
7560       AccRol (shCount);         // DDDCCCCC:BBB00000
7561
7562       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7563
7564       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7565
7566       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7567
7568       emitcode ("anl", "a,#!constbyte",
7569                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7570
7571       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7572
7573       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7574
7575       break;
7576     case 6:                     // AAAAAABB:CCCCCCDD
7577       emitcode ("anl", "a,#!constbyte",
7578                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7579       emitcode ("mov", "c,acc.0");      // c = B
7580       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7581 #if 0
7582       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7583       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7584 #else
7585       emitcode("rrc","a"); 
7586       emitcode("xch","a,%s", x); 
7587       emitcode("rrc","a"); 
7588       emitcode("mov","c,acc.0"); //<< get correct bit 
7589       emitcode("xch","a,%s", x); 
7590
7591       emitcode("rrc","a"); 
7592       emitcode("xch","a,%s", x); 
7593       emitcode("rrc","a"); 
7594       emitcode("xch","a,%s", x); 
7595 #endif
7596       break;
7597     case 7:                     // a:x <<= 7
7598
7599       emitcode ("anl", "a,#!constbyte",
7600                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7601
7602       emitcode ("mov", "c,acc.0");      // c = B
7603
7604       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7605
7606       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7607
7608       break;
7609     default:
7610       break;
7611     }
7612 }
7613 #endif
7614
7615 #ifdef BETTER_LITERAL_SHIFT
7616 //REMOVE ME!!!
7617 /*-----------------------------------------------------------------*/
7618 /* AccAXRsh - right shift a:x known count (0..7)                   */
7619 /*-----------------------------------------------------------------*/
7620 static void
7621 AccAXRsh (char *x, int shCount)
7622 {
7623   switch (shCount)
7624     {
7625     case 0:
7626       break;
7627     case 1:
7628       CLRC;
7629       AccAXRrl1 (x);            // 0->a:x
7630
7631       break;
7632     case 2:
7633       CLRC;
7634       AccAXRrl1 (x);            // 0->a:x
7635
7636       CLRC;
7637       AccAXRrl1 (x);            // 0->a:x
7638
7639       break;
7640     case 3:
7641     case 4:
7642     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7643
7644       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7645
7646       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7647
7648       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7649
7650       emitcode ("anl", "a,#!constbyte",
7651                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7652
7653       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7654
7655       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7656
7657       emitcode ("anl", "a,#!constbyte",
7658                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7659
7660       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7661
7662       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7663
7664       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7665
7666       break;
7667     case 6:                     // AABBBBBB:CCDDDDDD
7668
7669       emitcode ("mov", "c,acc.7");
7670       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7671
7672       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7673
7674       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7675
7676       emitcode ("anl", "a,#!constbyte",
7677                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7678
7679       break;
7680     case 7:                     // ABBBBBBB:CDDDDDDD
7681
7682       emitcode ("mov", "c,acc.7");      // c = A
7683
7684       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7685
7686       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7687
7688       emitcode ("anl", "a,#!constbyte",
7689                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7690
7691       break;
7692     default:
7693       break;
7694     }
7695 }
7696 #endif
7697
7698 #ifdef BETTER_LITERAL_SHIFT
7699 /*-----------------------------------------------------------------*/
7700 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7701 /*-----------------------------------------------------------------*/
7702 static void
7703 AccAXRshS (char *x, int shCount)
7704 {
7705   symbol *tlbl;
7706   switch (shCount)
7707     {
7708     case 0:
7709       break;
7710     case 1:
7711       emitcode ("mov", "c,acc.7");
7712       AccAXRrl1 (x);            // s->a:x
7713
7714       break;
7715     case 2:
7716       emitcode ("mov", "c,acc.7");
7717       AccAXRrl1 (x);            // s->a:x
7718
7719       emitcode ("mov", "c,acc.7");
7720       AccAXRrl1 (x);            // s->a:x
7721
7722       break;
7723     case 3:
7724     case 4:
7725     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7726
7727       tlbl = newiTempLabel (NULL);
7728       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7729
7730       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7731
7732       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7733
7734       emitcode ("anl", "a,#!constbyte",
7735                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7736
7737       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7738
7739       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7740
7741       emitcode ("anl", "a,#!constbyte",
7742                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7743
7744       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7745
7746       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7747
7748       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7749
7750       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7751       emitcode ("orl", "a,#!constbyte",
7752                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7753
7754       emitcode ("", "!tlabeldef", tlbl->key + 100);
7755       break;                    // SSSSAAAA:BBBCCCCC
7756
7757     case 6:                     // AABBBBBB:CCDDDDDD
7758
7759       tlbl = newiTempLabel (NULL);
7760       emitcode ("mov", "c,acc.7");
7761       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7762
7763       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7764
7765       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7766
7767       emitcode ("anl", "a,#!constbyte",
7768                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7769
7770       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7771       emitcode ("orl", "a,#!constbyte",
7772                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7773
7774       emitcode ("", "!tlabeldef", tlbl->key + 100);
7775       break;
7776     case 7:                     // ABBBBBBB:CDDDDDDD
7777
7778       tlbl = newiTempLabel (NULL);
7779       emitcode ("mov", "c,acc.7");      // c = A
7780
7781       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7782
7783       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7784
7785       emitcode ("anl", "a,#!constbyte",
7786                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7787
7788       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7789       emitcode ("orl", "a,#!constbyte",
7790                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7791
7792       emitcode ("", "!tlabeldef", tlbl->key + 100);
7793       break;
7794     default:
7795       break;
7796     }
7797 }
7798 #endif
7799
7800 #ifdef BETTER_LITERAL_SHIFT
7801 static void
7802 _loadLeftIntoAx(char    **lsb, 
7803                 operand *left, 
7804                 operand *result,
7805                 int     offl,
7806                 int     offr)
7807 {
7808   // Get the initial value from left into a pair of registers.
7809   // MSB must be in A, LSB can be any register.
7810   //
7811   // If the result is held in registers, it is an optimization
7812   // if the LSB can be held in the register which will hold the,
7813   // result LSB since this saves us from having to copy it into
7814   // the result following AccAXLsh.
7815   //
7816   // If the result is addressed indirectly, this is not a gain.
7817   if (AOP_NEEDSACC(result))
7818   {
7819        char *leftByte;
7820        
7821        _startLazyDPSEvaluation();
7822       if (AOP_TYPE(left) == AOP_DPTR2)
7823        {
7824            // Get MSB in A.
7825            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7826            // get LSB in DP2_RESULT_REG.
7827            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7828            assert(!strcmp(leftByte, DP2_RESULT_REG));
7829        }
7830        else
7831        {
7832            // get LSB into DP2_RESULT_REG
7833            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7834            if (strcmp(leftByte, DP2_RESULT_REG))
7835            {
7836                TR_AP("#7");
7837                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7838            }
7839            // And MSB in A.
7840            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7841            assert(strcmp(leftByte, DP2_RESULT_REG));
7842            MOVA(leftByte);
7843        }
7844        _endLazyDPSEvaluation();
7845        *lsb = DP2_RESULT_REG;
7846   }
7847   else
7848   {
7849       if (sameRegs (AOP (result), AOP (left)) &&
7850         ((offl + MSB16) == offr))
7851       {
7852           /* don't crash result[offr] */
7853           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7854           emitcode ("xch", "a,%s", 
7855                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7856       }
7857       else
7858       {
7859           movLeft2Result (left, offl, result, offr, 0);
7860           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7861       }
7862       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7863       assert(strcmp(*lsb,"a"));      
7864   }
7865 }
7866
7867 static void
7868 _storeAxResults(char    *lsb,
7869                 operand *result,
7870                 int     offr)
7871 {
7872   _startLazyDPSEvaluation();
7873   if (AOP_NEEDSACC(result))
7874   {
7875       /* We have to explicitly update the result LSB.
7876        */
7877       emitcode("xch","a,%s", lsb);
7878       aopPut(AOP(result), "a", offr);
7879       emitcode("mov","a,%s", lsb);
7880   }
7881   if (getDataSize (result) > 1)
7882   {
7883       aopPut (AOP (result), "a", offr + MSB16);
7884   }
7885   _endLazyDPSEvaluation();
7886 }
7887
7888 /*-----------------------------------------------------------------*/
7889 /* shiftL2Left2Result - shift left two bytes from left to result   */
7890 /*-----------------------------------------------------------------*/
7891 static void
7892 shiftL2Left2Result (operand * left, int offl,
7893                     operand * result, int offr, int shCount)
7894 {
7895   char *lsb;
7896
7897   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7898   
7899   AccAXLsh (lsb, shCount);
7900   
7901   _storeAxResults(lsb, result, offr);
7902 }
7903 #endif
7904
7905 #ifdef BETTER_LITERAL_SHIFT
7906 /*-----------------------------------------------------------------*/
7907 /* shiftR2Left2Result - shift right two bytes from left to result  */
7908 /*-----------------------------------------------------------------*/
7909 static void
7910 shiftR2Left2Result (operand * left, int offl,
7911                     operand * result, int offr,
7912                     int shCount, int sign)
7913 {
7914   char *lsb;
7915   
7916   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7917   
7918   /* a:x >> shCount (x = lsb(result)) */
7919   if (sign)
7920   {
7921      AccAXRshS(lsb, shCount);
7922   }
7923   else
7924   {
7925     AccAXRsh(lsb, shCount);
7926   }
7927   
7928   _storeAxResults(lsb, result, offr);
7929 }
7930 #endif
7931
7932 /*-----------------------------------------------------------------*/
7933 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7934 /*-----------------------------------------------------------------*/
7935 static void
7936 shiftLLeftOrResult (operand * left, int offl,
7937                     operand * result, int offr, int shCount)
7938 {
7939   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7940   /* shift left accumulator */
7941   AccLsh (shCount);
7942   /* or with result */
7943   emitcode ("orl", "a,%s",
7944             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7945   /* back to result */
7946   aopPut (AOP (result), "a", offr);
7947 }
7948
7949 #if 0
7950 //REMOVE ME!!!
7951 /*-----------------------------------------------------------------*/
7952 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7953 /*-----------------------------------------------------------------*/
7954 static void
7955 shiftRLeftOrResult (operand * left, int offl,
7956                     operand * result, int offr, int shCount)
7957 {
7958   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7959   /* shift right accumulator */
7960   AccRsh (shCount);
7961   /* or with result */
7962   emitcode ("orl", "a,%s",
7963             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7964   /* back to result */
7965   aopPut (AOP (result), "a", offr);
7966 }
7967 #endif
7968
7969 #ifdef BETTER_LITERAL_SHIFT
7970 /*-----------------------------------------------------------------*/
7971 /* genlshOne - left shift a one byte quantity by known count       */
7972 /*-----------------------------------------------------------------*/
7973 static void
7974 genlshOne (operand * result, operand * left, int shCount)
7975 {
7976   D (emitcode (";", "genlshOne "););
7977   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7978 }
7979 #endif
7980
7981 #ifdef BETTER_LITERAL_SHIFT
7982 /*-----------------------------------------------------------------*/
7983 /* genlshTwo - left shift two bytes by known amount != 0           */
7984 /*-----------------------------------------------------------------*/
7985 static void
7986 genlshTwo (operand * result, operand * left, int shCount)
7987 {
7988   int size;
7989
7990   D (emitcode (";", "genlshTwo "););
7991
7992   size = getDataSize (result);
7993
7994   /* if shCount >= 8 */
7995   if (shCount >= 8)
7996   {
7997       shCount -= 8;
7998
7999       _startLazyDPSEvaluation();
8000
8001       if (size > 1)
8002         {
8003           if (shCount)
8004           {
8005             _endLazyDPSEvaluation();
8006             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8007             aopPut (AOP (result), zero, LSB);       
8008           }
8009           else
8010           {
8011             movLeft2Result (left, LSB, result, MSB16, 0);
8012             aopPut (AOP (result), zero, LSB);
8013             _endLazyDPSEvaluation();
8014           }
8015         }
8016         else
8017         {
8018           aopPut (AOP (result), zero, LSB);
8019           _endLazyDPSEvaluation();
8020         }
8021   }
8022
8023   /*  1 <= shCount <= 7 */
8024   else
8025     {
8026       if (size == 1)
8027       {
8028         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8029       }
8030       else
8031       {
8032         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8033       }
8034     }
8035 }
8036 #endif
8037
8038 #if 0
8039 //REMOVE ME!!!
8040 /*-----------------------------------------------------------------*/
8041 /* shiftLLong - shift left one long from left to result            */
8042 /* offl = LSB or MSB16                                             */
8043 /*-----------------------------------------------------------------*/
8044 static void
8045 shiftLLong (operand * left, operand * result, int offr)
8046 {
8047   char *l;
8048   int size = AOP_SIZE (result);
8049
8050   if (size >= LSB + offr)
8051     {
8052       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8053       MOVA (l);
8054       emitcode ("add", "a,acc");
8055       if (sameRegs (AOP (left), AOP (result)) &&
8056           size >= MSB16 + offr && offr != LSB)
8057         emitcode ("xch", "a,%s",
8058                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8059       else
8060         aopPut (AOP (result), "a", LSB + offr);
8061     }
8062
8063   if (size >= MSB16 + offr)
8064     {
8065       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8066         {
8067           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8068         }
8069       emitcode ("rlc", "a");
8070       if (sameRegs (AOP (left), AOP (result)) &&
8071           size >= MSB24 + offr && offr != LSB)
8072         emitcode ("xch", "a,%s",
8073                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8074       else
8075         aopPut (AOP (result), "a", MSB16 + offr);
8076     }
8077
8078   if (size >= MSB24 + offr)
8079     {
8080       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8081         {
8082           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8083         }
8084       emitcode ("rlc", "a");
8085       if (sameRegs (AOP (left), AOP (result)) &&
8086           size >= MSB32 + offr && offr != LSB)
8087         emitcode ("xch", "a,%s",
8088                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8089       else
8090         aopPut (AOP (result), "a", MSB24 + offr);
8091     }
8092
8093   if (size > MSB32 + offr)
8094     {
8095       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8096         {
8097           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8098         }
8099       emitcode ("rlc", "a");
8100       aopPut (AOP (result), "a", MSB32 + offr);
8101     }
8102   if (offr != LSB)
8103     aopPut (AOP (result), zero, LSB);
8104 }
8105 #endif
8106
8107 #if 0
8108 //REMOVE ME!!!
8109 /*-----------------------------------------------------------------*/
8110 /* genlshFour - shift four byte by a known amount != 0             */
8111 /*-----------------------------------------------------------------*/
8112 static void
8113 genlshFour (operand * result, operand * left, int shCount)
8114 {
8115   int size;
8116
8117   D (emitcode (";", "genlshFour ");
8118     );
8119
8120   size = AOP_SIZE (result);
8121
8122   /* if shifting more that 3 bytes */
8123   if (shCount >= 24)
8124     {
8125       shCount -= 24;
8126       if (shCount)
8127         /* lowest order of left goes to the highest
8128            order of the destination */
8129         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8130       else
8131         movLeft2Result (left, LSB, result, MSB32, 0);
8132       aopPut (AOP (result), zero, LSB);
8133       aopPut (AOP (result), zero, MSB16);
8134       aopPut (AOP (result), zero, MSB24);
8135       return;
8136     }
8137
8138   /* more than two bytes */
8139   else if (shCount >= 16)
8140     {
8141       /* lower order two bytes goes to higher order two bytes */
8142       shCount -= 16;
8143       /* if some more remaining */
8144       if (shCount)
8145         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8146       else
8147         {
8148           movLeft2Result (left, MSB16, result, MSB32, 0);
8149           movLeft2Result (left, LSB, result, MSB24, 0);
8150         }
8151       aopPut (AOP (result), zero, MSB16);
8152       aopPut (AOP (result), zero, LSB);
8153       return;
8154     }
8155
8156   /* if more than 1 byte */
8157   else if (shCount >= 8)
8158     {
8159       /* lower order three bytes goes to higher order  three bytes */
8160       shCount -= 8;
8161       if (size == 2)
8162         {
8163           if (shCount)
8164             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8165           else
8166             movLeft2Result (left, LSB, result, MSB16, 0);
8167         }
8168       else
8169         {                       /* size = 4 */
8170           if (shCount == 0)
8171             {
8172               movLeft2Result (left, MSB24, result, MSB32, 0);
8173               movLeft2Result (left, MSB16, result, MSB24, 0);
8174               movLeft2Result (left, LSB, result, MSB16, 0);
8175               aopPut (AOP (result), zero, LSB);
8176             }
8177           else if (shCount == 1)
8178             shiftLLong (left, result, MSB16);
8179           else
8180             {
8181               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8182               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8183               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8184               aopPut (AOP (result), zero, LSB);
8185             }
8186         }
8187     }
8188
8189   /* 1 <= shCount <= 7 */
8190   else if (shCount <= 2)
8191     {
8192       shiftLLong (left, result, LSB);
8193       if (shCount == 2)
8194         shiftLLong (result, result, LSB);
8195     }
8196   /* 3 <= shCount <= 7, optimize */
8197   else
8198     {
8199       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8200       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8201       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8202     }
8203 }
8204 #endif
8205
8206 #ifdef BETTER_LITERAL_SHIFT
8207 /*-----------------------------------------------------------------*/
8208 /* genLeftShiftLiteral - left shifting by known count              */
8209 /*-----------------------------------------------------------------*/
8210 static bool
8211 genLeftShiftLiteral (operand * left,
8212                      operand * right,
8213                      operand * result,
8214                      iCode * ic)
8215 {
8216   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8217   int size;
8218
8219   size = getSize (operandType (result));
8220
8221   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8222
8223   /* We only handle certain easy cases so far. */
8224   if ((shCount != 0)
8225    && (shCount < (size * 8))
8226    && (size != 1)
8227    && (size != 2))
8228   {
8229       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8230       return FALSE;
8231   }
8232
8233   freeAsmop (right, NULL, ic, TRUE);
8234
8235   aopOp(left, ic, FALSE, FALSE);
8236   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8237
8238 #if 0 // debug spew
8239   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8240   {
8241         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8242         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8243         {
8244            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8245         }
8246   }
8247   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8248   {
8249         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8250         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8251         {
8252            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8253         }       
8254   }  
8255 #endif
8256   
8257 #if VIEW_SIZE
8258   emitcode ("; shift left ", "result %d, left %d", size,
8259             AOP_SIZE (left));
8260 #endif
8261
8262   /* I suppose that the left size >= result size */
8263   if (shCount == 0)
8264   {
8265         _startLazyDPSEvaluation();
8266         while (size--)
8267         {
8268           movLeft2Result (left, size, result, size, 0);
8269         }
8270         _endLazyDPSEvaluation();
8271   }
8272   else if (shCount >= (size * 8))
8273   {
8274     _startLazyDPSEvaluation();
8275     while (size--)
8276     {
8277       aopPut (AOP (result), zero, size);
8278     }
8279     _endLazyDPSEvaluation();
8280   }
8281   else
8282   {
8283       switch (size)
8284         {
8285         case 1:
8286           genlshOne (result, left, shCount);
8287           break;
8288
8289         case 2:
8290           genlshTwo (result, left, shCount);
8291           break;
8292 #if 0
8293         case 4:
8294           genlshFour (result, left, shCount);
8295           break;
8296 #endif
8297         default:
8298           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8299           break;
8300         }
8301     }
8302   freeAsmop (left, NULL, ic, TRUE);
8303   freeAsmop (result, NULL, ic, TRUE);
8304   return TRUE;
8305 }
8306 #endif
8307
8308 /*-----------------------------------------------------------------*/
8309 /* genLeftShift - generates code for left shifting                 */
8310 /*-----------------------------------------------------------------*/
8311 static void
8312 genLeftShift (iCode * ic)
8313 {
8314   operand *left, *right, *result;
8315   int size, offset;
8316   char *l;
8317   symbol *tlbl, *tlbl1;
8318
8319   D (emitcode (";", "genLeftShift "););
8320
8321   right = IC_RIGHT (ic);
8322   left = IC_LEFT (ic);
8323   result = IC_RESULT (ic);
8324
8325   aopOp (right, ic, FALSE, FALSE);
8326
8327
8328 #ifdef BETTER_LITERAL_SHIFT
8329   /* if the shift count is known then do it
8330      as efficiently as possible */
8331   if (AOP_TYPE (right) == AOP_LIT)
8332     {
8333       if (genLeftShiftLiteral (left, right, result, ic))
8334       {
8335         return;
8336       }
8337     }
8338 #endif
8339
8340   /* shift count is unknown then we have to form
8341      a loop get the loop count in B : Note: we take
8342      only the lower order byte since shifting
8343      more that 32 bits make no sense anyway, ( the
8344      largest size of an object can be only 32 bits ) */
8345
8346   if (AOP_TYPE (right) == AOP_LIT)
8347   {
8348       /* Really should be handled by genLeftShiftLiteral,
8349        * but since I'm too lazy to fix that today, at least we can make
8350        * some small improvement.
8351        */
8352        emitcode("mov", "b,#!constbyte",
8353                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8354   }
8355   else
8356   {
8357       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8358       emitcode ("inc", "b");
8359   }
8360   freeAsmop (right, NULL, ic, TRUE);
8361   aopOp (left, ic, FALSE, FALSE);
8362   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8363
8364   /* now move the left to the result if they are not the
8365      same */
8366   if (!sameRegs (AOP (left), AOP (result)) &&
8367       AOP_SIZE (result) > 1)
8368     {
8369
8370       size = AOP_SIZE (result);
8371       offset = 0;
8372       _startLazyDPSEvaluation ();
8373       while (size--)
8374         {
8375           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8376           if (*l == '@' && (IS_AOP_PREG (result)))
8377             {
8378
8379               emitcode ("mov", "a,%s", l);
8380               aopPut (AOP (result), "a", offset);
8381             }
8382           else
8383             aopPut (AOP (result), l, offset);
8384           offset++;
8385         }
8386       _endLazyDPSEvaluation ();
8387     }
8388
8389   tlbl = newiTempLabel (NULL);
8390   size = AOP_SIZE (result);
8391   offset = 0;
8392   tlbl1 = newiTempLabel (NULL);
8393
8394   /* if it is only one byte then */
8395   if (size == 1)
8396     {
8397       symbol *tlbl1 = newiTempLabel (NULL);
8398
8399       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8400       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8401       emitcode ("", "!tlabeldef", tlbl->key + 100);
8402       emitcode ("add", "a,acc");
8403       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8404       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8405       aopPut (AOP (result), "a", 0);
8406       goto release;
8407     }
8408
8409   reAdjustPreg (AOP (result));
8410
8411   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8412   emitcode ("", "!tlabeldef", tlbl->key + 100);
8413   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8414   emitcode ("add", "a,acc");
8415   aopPut (AOP (result), "a", offset++);
8416   _startLazyDPSEvaluation ();
8417   while (--size)
8418     {
8419       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8420       emitcode ("rlc", "a");
8421       aopPut (AOP (result), "a", offset++);
8422     }
8423   _endLazyDPSEvaluation ();
8424   reAdjustPreg (AOP (result));
8425
8426   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8427   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8428 release:
8429   freeAsmop (left, NULL, ic, TRUE);
8430   freeAsmop (result, NULL, ic, TRUE);
8431 }
8432
8433 #ifdef BETTER_LITERAL_SHIFT
8434 /*-----------------------------------------------------------------*/
8435 /* genrshOne - right shift a one byte quantity by known count      */
8436 /*-----------------------------------------------------------------*/
8437 static void
8438 genrshOne (operand * result, operand * left,
8439            int shCount, int sign)
8440 {
8441   D (emitcode (";", "genrshOne"););
8442   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8443 }
8444 #endif
8445
8446 #ifdef BETTER_LITERAL_SHIFT
8447 /*-----------------------------------------------------------------*/
8448 /* genrshTwo - right shift two bytes by known amount != 0          */
8449 /*-----------------------------------------------------------------*/
8450 static void
8451 genrshTwo (operand * result, operand * left,
8452            int shCount, int sign)
8453 {
8454   D (emitcode (";", "genrshTwo"););
8455
8456   /* if shCount >= 8 */
8457   if (shCount >= 8)
8458     {
8459       shCount -= 8;
8460       _startLazyDPSEvaluation();
8461       if (shCount)
8462       {
8463         shiftR1Left2Result (left, MSB16, result, LSB,
8464                             shCount, sign);
8465       }                     
8466       else
8467       {
8468         movLeft2Result (left, MSB16, result, LSB, sign);
8469       }
8470       addSign (result, MSB16, sign);
8471       _endLazyDPSEvaluation();
8472     }
8473
8474   /*  1 <= shCount <= 7 */
8475   else
8476   {
8477     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8478   }
8479 }
8480 #endif
8481
8482 /*-----------------------------------------------------------------*/
8483 /* shiftRLong - shift right one long from left to result           */
8484 /* offl = LSB or MSB16                                             */
8485 /*-----------------------------------------------------------------*/
8486 static void
8487 shiftRLong (operand * left, int offl,
8488             operand * result, int sign)
8489 {
8490   int isSameRegs=sameRegs(AOP(left),AOP(result));
8491
8492   if (isSameRegs && offl>1) {
8493     // we are in big trouble, but this shouldn't happen
8494     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8495   }
8496
8497   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8498   
8499   if (offl==MSB16) {
8500     // shift is > 8
8501     if (sign) {
8502       emitcode ("rlc", "a");
8503       emitcode ("subb", "a,acc");
8504       emitcode ("xch", "a,%s",
8505                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8506     } else {
8507       aopPut (AOP(result), zero, MSB32);
8508     }
8509   }
8510
8511   if (!sign) {
8512     emitcode ("clr", "c");
8513   } else {
8514     emitcode ("mov", "c,acc.7");
8515   }
8516
8517   emitcode ("rrc", "a");
8518
8519   if (isSameRegs && offl==MSB16) {
8520     emitcode ("xch",
8521               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8522   } else {
8523     aopPut (AOP (result), "a", MSB32);
8524     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8525   }
8526
8527   emitcode ("rrc", "a");
8528   if (isSameRegs && offl==1) {
8529     emitcode ("xch", "a,%s",
8530               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8531   } else {
8532     aopPut (AOP (result), "a", MSB24);
8533     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8534   }
8535   emitcode ("rrc", "a");
8536   aopPut (AOP (result), "a", MSB16 - offl);
8537
8538   if (offl == LSB)
8539     {
8540       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8541       emitcode ("rrc", "a");
8542       aopPut (AOP (result), "a", LSB);
8543     }
8544 }
8545
8546 /*-----------------------------------------------------------------*/
8547 /* genrshFour - shift four byte by a known amount != 0             */
8548 /*-----------------------------------------------------------------*/
8549 static void
8550 genrshFour (operand * result, operand * left,
8551             int shCount, int sign)
8552 {
8553   D (emitcode (";", "genrshFour"););
8554
8555   /* if shifting more that 3 bytes */
8556   if (shCount >= 24)
8557     {
8558       shCount -= 24;
8559       _startLazyDPSEvaluation();
8560       if (shCount)
8561         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8562       else
8563         movLeft2Result (left, MSB32, result, LSB, sign);
8564       addSign (result, MSB16, sign);
8565       _endLazyDPSEvaluation();
8566     }
8567   else if (shCount >= 16)
8568     {
8569       shCount -= 16;
8570       _startLazyDPSEvaluation();
8571       if (shCount)
8572         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8573       else
8574         {
8575           movLeft2Result (left, MSB24, result, LSB, 0);
8576           movLeft2Result (left, MSB32, result, MSB16, sign);
8577         }
8578       addSign (result, MSB24, sign);
8579       _endLazyDPSEvaluation();
8580     }
8581   else if (shCount >= 8)
8582     {
8583       shCount -= 8;
8584       _startLazyDPSEvaluation();
8585       if (shCount == 1)
8586         {
8587             shiftRLong (left, MSB16, result, sign);
8588         }
8589       else if (shCount == 0)
8590         {
8591           movLeft2Result (left, MSB16, result, LSB, 0);
8592           movLeft2Result (left, MSB24, result, MSB16, 0);
8593           movLeft2Result (left, MSB32, result, MSB24, sign);
8594           addSign (result, MSB32, sign);
8595         }
8596       else
8597         {
8598           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8599           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8600           /* the last shift is signed */
8601           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8602           addSign (result, MSB32, sign);
8603         }
8604         _endLazyDPSEvaluation();
8605     }
8606   else
8607     {   
8608         /* 1 <= shCount <= 7 */
8609       if (shCount <= 2)
8610         {
8611           shiftRLong (left, LSB, result, sign);
8612           if (shCount == 2)
8613             shiftRLong (result, LSB, result, sign);
8614         }
8615       else
8616         {
8617           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8618           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8619           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8620         }
8621     }
8622 }
8623
8624 #ifdef BETTER_LITERAL_SHIFT
8625 /*-----------------------------------------------------------------*/
8626 /* genRightShiftLiteral - right shifting by known count            */
8627 /*-----------------------------------------------------------------*/
8628 static bool
8629 genRightShiftLiteral (operand * left,
8630                       operand * right,
8631                       operand * result,
8632                       iCode * ic,
8633                       int sign)
8634 {
8635   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8636   int size;
8637
8638   size = getSize (operandType (result));
8639
8640   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8641
8642   /* We only handle certain easy cases so far. */
8643   if ((shCount != 0)
8644    && (shCount < (size * 8))
8645    && (size != 1)
8646    && (size != 2)
8647    && (size != 4))
8648   {
8649       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8650       return FALSE;
8651   }
8652
8653   freeAsmop (right, NULL, ic, TRUE);
8654
8655   aopOp (left, ic, FALSE, FALSE);
8656   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8657
8658 #if VIEW_SIZE
8659   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8660             AOP_SIZE (left));
8661 #endif
8662
8663   /* test the LEFT size !!! */
8664
8665   /* I suppose that the left size >= result size */
8666   if (shCount == 0)
8667   {
8668       size = getDataSize (result);
8669       _startLazyDPSEvaluation();
8670       while (size--)
8671       {
8672         movLeft2Result (left, size, result, size, 0);
8673       }
8674       _endLazyDPSEvaluation();
8675   }
8676   else if (shCount >= (size * 8))
8677     {
8678       if (sign)
8679       {
8680         /* get sign in acc.7 */
8681         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8682       }
8683       addSign (result, LSB, sign);
8684     }
8685   else
8686     {
8687       switch (size)
8688         {
8689         case 1:
8690           genrshOne (result, left, shCount, sign);
8691           break;
8692
8693         case 2:
8694           genrshTwo (result, left, shCount, sign);
8695           break;
8696 #if 1
8697         case 4:
8698           genrshFour (result, left, shCount, sign);
8699           break;
8700 #endif    
8701         default:
8702           break;
8703         }
8704     }
8705   freeAsmop (left, NULL, ic, TRUE);
8706   freeAsmop (result, NULL, ic, TRUE);
8707   
8708   return TRUE;
8709 }
8710 #endif
8711
8712 /*-----------------------------------------------------------------*/
8713 /* genSignedRightShift - right shift of signed number              */
8714 /*-----------------------------------------------------------------*/
8715 static void
8716 genSignedRightShift (iCode * ic)
8717 {
8718   operand *right, *left, *result;
8719   int size, offset;
8720   char *l;
8721   symbol *tlbl, *tlbl1;
8722
8723   D (emitcode (";", "genSignedRightShift "););
8724
8725   /* we do it the hard way put the shift count in b
8726      and loop thru preserving the sign */
8727
8728   right = IC_RIGHT (ic);
8729   left = IC_LEFT (ic);
8730   result = IC_RESULT (ic);
8731
8732   aopOp (right, ic, FALSE, FALSE);
8733
8734 #ifdef BETTER_LITERAL_SHIFT
8735   if (AOP_TYPE (right) == AOP_LIT)
8736     {
8737       if (genRightShiftLiteral (left, right, result, ic, 1))
8738       {
8739         return;
8740       }
8741     }
8742 #endif
8743   /* shift count is unknown then we have to form
8744      a loop get the loop count in B : Note: we take
8745      only the lower order byte since shifting
8746      more that 32 bits make no sense anyway, ( the
8747      largest size of an object can be only 32 bits ) */
8748
8749   if (AOP_TYPE (right) == AOP_LIT)
8750   {
8751       /* Really should be handled by genRightShiftLiteral,
8752        * but since I'm too lazy to fix that today, at least we can make
8753        * some small improvement.
8754        */
8755        emitcode("mov", "b,#!constbyte",
8756                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8757   }
8758   else
8759   {
8760         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8761         emitcode ("inc", "b");
8762   }
8763   freeAsmop (right, NULL, ic, TRUE);
8764   aopOp (left, ic, FALSE, FALSE);
8765   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8766
8767   /* now move the left to the result if they are not the
8768      same */
8769   if (!sameRegs (AOP (left), AOP (result)) &&
8770       AOP_SIZE (result) > 1)
8771     {
8772
8773       size = AOP_SIZE (result);
8774       offset = 0;
8775       _startLazyDPSEvaluation ();
8776       while (size--)
8777         {
8778           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8779           if (*l == '@' && IS_AOP_PREG (result))
8780             {
8781
8782               emitcode ("mov", "a,%s", l);
8783               aopPut (AOP (result), "a", offset);
8784             }
8785           else
8786             aopPut (AOP (result), l, offset);
8787           offset++;
8788         }
8789       _endLazyDPSEvaluation ();
8790     }
8791
8792   /* mov the highest order bit to OVR */
8793   tlbl = newiTempLabel (NULL);
8794   tlbl1 = newiTempLabel (NULL);
8795
8796   size = AOP_SIZE (result);
8797   offset = size - 1;
8798   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8799   emitcode ("rlc", "a");
8800   emitcode ("mov", "ov,c");
8801   /* if it is only one byte then */
8802   if (size == 1)
8803     {
8804       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8805       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8806       emitcode ("", "!tlabeldef", tlbl->key + 100);
8807       emitcode ("mov", "c,ov");
8808       emitcode ("rrc", "a");
8809       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8810       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8811       aopPut (AOP (result), "a", 0);
8812       goto release;
8813     }
8814
8815   reAdjustPreg (AOP (result));
8816   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8817   emitcode ("", "!tlabeldef", tlbl->key + 100);
8818   emitcode ("mov", "c,ov");
8819   _startLazyDPSEvaluation ();
8820   while (size--)
8821     {
8822       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8823       emitcode ("rrc", "a");
8824       aopPut (AOP (result), "a", offset--);
8825     }
8826   _endLazyDPSEvaluation ();
8827   reAdjustPreg (AOP (result));
8828   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8829   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8830
8831 release:
8832   freeAsmop (left, NULL, ic, TRUE);
8833   freeAsmop (result, NULL, ic, TRUE);
8834 }
8835
8836 /*-----------------------------------------------------------------*/
8837 /* genRightShift - generate code for right shifting                */
8838 /*-----------------------------------------------------------------*/
8839 static void
8840 genRightShift (iCode * ic)
8841 {
8842   operand *right, *left, *result;
8843   sym_link *retype;
8844   int size, offset;
8845   char *l;
8846   symbol *tlbl, *tlbl1;
8847
8848   D (emitcode (";", "genRightShift "););
8849
8850   /* if signed then we do it the hard way preserve the
8851      sign bit moving it inwards */
8852   retype = getSpec (operandType (IC_RESULT (ic)));
8853
8854   if (!SPEC_USIGN (retype))
8855     {
8856       genSignedRightShift (ic);
8857       return;
8858     }
8859
8860   /* signed & unsigned types are treated the same : i.e. the
8861      signed is NOT propagated inwards : quoting from the
8862      ANSI - standard : "for E1 >> E2, is equivalent to division
8863      by 2**E2 if unsigned or if it has a non-negative value,
8864      otherwise the result is implementation defined ", MY definition
8865      is that the sign does not get propagated */
8866
8867   right = IC_RIGHT (ic);
8868   left = IC_LEFT (ic);
8869   result = IC_RESULT (ic);
8870
8871   aopOp (right, ic, FALSE, FALSE);
8872
8873 #ifdef BETTER_LITERAL_SHIFT
8874   /* if the shift count is known then do it
8875      as efficiently as possible */
8876   if (AOP_TYPE (right) == AOP_LIT)
8877     {
8878       if (genRightShiftLiteral (left, right, result, ic, 0))
8879       {
8880         return;
8881       }
8882     }
8883 #endif
8884
8885   /* shift count is unknown then we have to form
8886      a loop get the loop count in B : Note: we take
8887      only the lower order byte since shifting
8888      more that 32 bits make no sense anyway, ( the
8889      largest size of an object can be only 32 bits ) */
8890   
8891   if (AOP_TYPE (right) == AOP_LIT)
8892   {
8893       /* Really should be handled by genRightShiftLiteral,
8894        * but since I'm too lazy to fix that today, at least we can make
8895        * some small improvement.
8896        */
8897        emitcode("mov", "b,#!constbyte",
8898                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8899   }
8900   else
8901   {
8902       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8903       emitcode ("inc", "b");
8904   }
8905   freeAsmop (right, NULL, ic, TRUE);
8906   aopOp (left, ic, FALSE, FALSE);
8907   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8908
8909   /* now move the left to the result if they are not the
8910      same */
8911   if (!sameRegs (AOP (left), AOP (result)) &&
8912       AOP_SIZE (result) > 1)
8913     {
8914
8915       size = AOP_SIZE (result);
8916       offset = 0;
8917       _startLazyDPSEvaluation ();
8918       while (size--)
8919         {
8920           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8921           if (*l == '@' && IS_AOP_PREG (result))
8922             {
8923
8924               emitcode ("mov", "a,%s", l);
8925               aopPut (AOP (result), "a", offset);
8926             }
8927           else
8928             aopPut (AOP (result), l, offset);
8929           offset++;
8930         }
8931       _endLazyDPSEvaluation ();
8932     }
8933
8934   tlbl = newiTempLabel (NULL);
8935   tlbl1 = newiTempLabel (NULL);
8936   size = AOP_SIZE (result);
8937   offset = size - 1;
8938
8939   /* if it is only one byte then */
8940   if (size == 1)
8941     {
8942       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8943       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8944       emitcode ("", "!tlabeldef", tlbl->key + 100);
8945       CLRC;
8946       emitcode ("rrc", "a");
8947       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8948       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8949       aopPut (AOP (result), "a", 0);
8950       goto release;
8951     }
8952
8953   reAdjustPreg (AOP (result));
8954   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8955   emitcode ("", "!tlabeldef", tlbl->key + 100);
8956   CLRC;
8957   _startLazyDPSEvaluation ();
8958   while (size--)
8959     {
8960       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8961       emitcode ("rrc", "a");
8962       aopPut (AOP (result), "a", offset--);
8963     }
8964   _endLazyDPSEvaluation ();
8965   reAdjustPreg (AOP (result));
8966
8967   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8968   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8969
8970 release:
8971   freeAsmop (left, NULL, ic, TRUE);
8972   freeAsmop (result, NULL, ic, TRUE);
8973 }
8974
8975 /*-----------------------------------------------------------------*/
8976 /* genUnpackBits - generates code for unpacking bits               */
8977 /*-----------------------------------------------------------------*/
8978 static void
8979 genUnpackBits (operand * result, char *rname, int ptype)
8980 {
8981   int shCnt;
8982   int rlen;
8983   sym_link *etype;
8984   int offset = 0;
8985
8986   D (emitcode (";", "genUnpackBits "););
8987
8988   etype = getSpec (operandType (result));
8989
8990   /* read the first byte  */
8991   switch (ptype)
8992     {
8993
8994     case POINTER:
8995     case IPOINTER:
8996       emitcode ("mov", "a,@%s", rname);
8997       break;
8998
8999     case PPOINTER:
9000       emitcode ("movx", "a,@%s", rname);
9001       break;
9002
9003     case FPOINTER:
9004       emitcode ("movx", "a,@dptr");
9005       break;
9006
9007     case CPOINTER:
9008       emitcode ("clr", "a");
9009       emitcode ("movc", "a,@a+dptr");
9010       break;
9011
9012     case GPOINTER:
9013       emitcode ("lcall", "__gptrget");
9014       break;
9015     }
9016
9017   /* if we have bitdisplacement then it fits   */
9018   /* into this byte completely or if length is */
9019   /* less than a byte                          */
9020   if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
9021     {
9022
9023       /* shift right acc */
9024       AccRsh (shCnt);
9025
9026       emitcode ("anl", "a,#!constbyte",
9027                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
9028       aopPut (AOP (result), "a", offset);
9029       return;
9030     }
9031
9032   /* bit field did not fit in a byte  */
9033   rlen = SPEC_BLEN (etype) - 8;
9034   aopPut (AOP (result), "a", offset++);
9035
9036   while (1)
9037     {
9038
9039       switch (ptype)
9040         {
9041         case POINTER:
9042         case IPOINTER:
9043           emitcode ("inc", "%s", rname);
9044           emitcode ("mov", "a,@%s", rname);
9045           break;
9046
9047         case PPOINTER:
9048           emitcode ("inc", "%s", rname);
9049           emitcode ("movx", "a,@%s", rname);
9050           break;
9051
9052         case FPOINTER:
9053           emitcode ("inc", "dptr");
9054           emitcode ("movx", "a,@dptr");
9055           break;
9056
9057         case CPOINTER:
9058           emitcode ("clr", "a");
9059           emitcode ("inc", "dptr");
9060           emitcode ("movc", "a,@a+dptr");
9061           break;
9062
9063         case GPOINTER:
9064           emitcode ("inc", "dptr");
9065           emitcode ("lcall", "__gptrget");
9066           break;
9067         }
9068
9069       rlen -= 8;
9070       /* if we are done */
9071       if (rlen < 8)
9072         break;
9073
9074       aopPut (AOP (result), "a", offset++);
9075
9076     }
9077
9078   if (rlen)
9079     {
9080       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9081       aopPut (AOP (result), "a", offset);
9082     }
9083
9084   return;
9085 }
9086
9087
9088 /*-----------------------------------------------------------------*/
9089 /* genDataPointerGet - generates code when ptr offset is known     */
9090 /*-----------------------------------------------------------------*/
9091 static void
9092 genDataPointerGet (operand * left,
9093                    operand * result,
9094                    iCode * ic)
9095 {
9096   char *l;
9097   char buff[256];
9098   int size, offset = 0;
9099   aopOp (result, ic, TRUE, FALSE);
9100
9101   /* get the string representation of the name */
9102   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9103   size = AOP_SIZE (result);
9104   _startLazyDPSEvaluation ();
9105   while (size--)
9106     {
9107         if (offset)
9108         {
9109             SNPRINTF (buff, sizeof(buff), 
9110                       "(%s + %d)", l + 1, offset);
9111         }
9112         else
9113         {
9114             SNPRINTF (buff, sizeof(buff), 
9115                       "%s", l + 1);
9116         }
9117       aopPut (AOP (result), buff, offset++);
9118     }
9119   _endLazyDPSEvaluation ();
9120
9121   freeAsmop (left, NULL, ic, TRUE);
9122   freeAsmop (result, NULL, ic, TRUE);
9123 }
9124
9125 /*-----------------------------------------------------------------*/
9126 /* genNearPointerGet - emitcode for near pointer fetch             */
9127 /*-----------------------------------------------------------------*/
9128 static void
9129 genNearPointerGet (operand * left,
9130                    operand * result,
9131                    iCode * ic,
9132                    iCode *pi)
9133 {
9134   asmop *aop = NULL;
9135   regs *preg;
9136   char *rname;
9137   sym_link *rtype, *retype, *letype;
9138   sym_link *ltype = operandType (left);
9139   char buff[80];
9140
9141   rtype = operandType (result);
9142   retype = getSpec (rtype);
9143   letype = getSpec (ltype);
9144
9145   aopOp (left, ic, FALSE, FALSE);
9146
9147   /* if left is rematerialisable and
9148      result is not bit variable type and
9149      the left is pointer to data space i.e
9150      lower 128 bytes of space */
9151   if (AOP_TYPE (left) == AOP_IMMD &&
9152       !IS_BITVAR (retype) &&
9153       !IS_BITVAR (letype) &&
9154       DCL_TYPE (ltype) == POINTER)
9155     {
9156       genDataPointerGet (left, result, ic);
9157       return;
9158     }
9159
9160   /* if the value is already in a pointer register
9161      then don't need anything more */
9162   if (!AOP_INPREG (AOP (left)))
9163     {
9164       /* otherwise get a free pointer register */
9165       aop = newAsmop (0);
9166       preg = getFreePtr (ic, &aop, FALSE);
9167       emitcode ("mov", "%s,%s",
9168                 preg->name,
9169                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9170       rname = preg->name;
9171     }
9172   else
9173     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9174
9175   freeAsmop (left, NULL, ic, TRUE);
9176   aopOp (result, ic, FALSE, FALSE);
9177
9178   /* if bitfield then unpack the bits */
9179   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9180     genUnpackBits (result, rname, POINTER);
9181   else
9182     {
9183       /* we have can just get the values */
9184       int size = AOP_SIZE (result);
9185       int offset = 0;
9186
9187       while (size--)
9188         {
9189           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9190             {
9191
9192               emitcode ("mov", "a,@%s", rname);
9193               aopPut (AOP (result), "a", offset);
9194             }
9195           else
9196             {
9197               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9198               aopPut (AOP (result), buff, offset);
9199             }
9200           offset++;
9201           if (size || pi)
9202             {
9203                 emitcode ("inc", "%s", rname);
9204             }
9205         }
9206     }
9207
9208   /* now some housekeeping stuff */
9209   if (aop)
9210     {
9211       /* we had to allocate for this iCode */
9212       if (pi) { /* post increment present */
9213         aopPut(AOP ( left ),rname,0);
9214       }
9215       freeAsmop (NULL, aop, ic, TRUE);
9216     }
9217   else
9218     {
9219       /* we did not allocate which means left
9220          already in a pointer register, then
9221          if size > 0 && this could be used again
9222          we have to point it back to where it
9223          belongs */
9224       if (AOP_SIZE (result) > 1 &&
9225           !OP_SYMBOL (left)->remat &&
9226           (OP_SYMBOL (left)->liveTo > ic->seq ||
9227            ic->depth) &&
9228           !pi)
9229         {
9230           int size = AOP_SIZE (result) - 1;
9231           while (size--)
9232             emitcode ("dec", "%s", rname);
9233         }
9234     }
9235
9236   /* done */
9237   freeAsmop (result, NULL, ic, TRUE);
9238   if (pi) pi->generated = 1;
9239 }
9240
9241 /*-----------------------------------------------------------------*/
9242 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9243 /*-----------------------------------------------------------------*/
9244 static void
9245 genPagedPointerGet (operand * left,
9246                     operand * result,
9247                     iCode * ic,
9248                     iCode * pi)
9249 {
9250   asmop *aop = NULL;
9251   regs *preg;
9252   char *rname;
9253   sym_link *rtype, *retype, *letype;
9254
9255   rtype = operandType (result);
9256   retype = getSpec (rtype);
9257   letype = getSpec (operandType (left));
9258   aopOp (left, ic, FALSE, FALSE);
9259
9260   /* if the value is already in a pointer register
9261      then don't need anything more */
9262   if (!AOP_INPREG (AOP (left)))
9263     {
9264       /* otherwise get a free pointer register */
9265       aop = newAsmop (0);
9266       preg = getFreePtr (ic, &aop, FALSE);
9267       emitcode ("mov", "%s,%s",
9268                 preg->name,
9269                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9270       rname = preg->name;
9271     }
9272   else
9273     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9274
9275   freeAsmop (left, NULL, ic, TRUE);
9276   aopOp (result, ic, FALSE, FALSE);
9277
9278   /* if bitfield then unpack the bits */
9279   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9280     genUnpackBits (result, rname, PPOINTER);
9281   else
9282     {
9283       /* we have can just get the values */
9284       int size = AOP_SIZE (result);
9285       int offset = 0;
9286
9287       while (size--)
9288         {
9289
9290           emitcode ("movx", "a,@%s", rname);
9291           aopPut (AOP (result), "a", offset);
9292
9293           offset++;
9294
9295           if (size || pi)
9296             emitcode ("inc", "%s", rname);
9297         }
9298     }
9299
9300   /* now some housekeeping stuff */
9301   if (aop)
9302     {
9303       /* we had to allocate for this iCode */
9304       if (pi) aopPut ( AOP (left), rname, 0);
9305       freeAsmop (NULL, aop, ic, TRUE);
9306     }
9307   else
9308     {
9309       /* we did not allocate which means left
9310          already in a pointer register, then
9311          if size > 0 && this could be used again
9312          we have to point it back to where it
9313          belongs */
9314       if (AOP_SIZE (result) > 1 &&
9315           !OP_SYMBOL (left)->remat &&
9316           (OP_SYMBOL (left)->liveTo > ic->seq ||
9317            ic->depth) &&
9318           !pi)
9319         {
9320           int size = AOP_SIZE (result) - 1;
9321           while (size--)
9322             emitcode ("dec", "%s", rname);
9323         }
9324     }
9325
9326   /* done */
9327   freeAsmop (result, NULL, ic, TRUE);
9328   if (pi) pi->generated = 1;
9329 }
9330
9331 /*-----------------------------------------------------------------*/
9332 /* genFarPointerGet - gget value from far space                    */
9333 /*-----------------------------------------------------------------*/
9334 static void
9335 genFarPointerGet (operand * left,
9336                   operand * result, iCode * ic, iCode *pi)
9337 {
9338     int size, offset, dopi=1;
9339   sym_link *retype = getSpec (operandType (result));
9340   sym_link *letype = getSpec (operandType (left));
9341   D (emitcode (";", "genFarPointerGet"););
9342
9343   aopOp (left, ic, FALSE, FALSE);
9344
9345   /* if the operand is already in dptr
9346      then we do nothing else we move the value to dptr */
9347   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9348     {
9349       /* if this is remateriazable */
9350       if (AOP_TYPE (left) == AOP_IMMD)
9351         {
9352           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9353         }
9354       else
9355         {
9356           /* we need to get it byte by byte */
9357           _startLazyDPSEvaluation ();
9358           if (AOP_TYPE (left) != AOP_DPTR)
9359             {
9360               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9361               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9362               if (options.model == MODEL_FLAT24)
9363                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9364             }
9365           else
9366             {
9367               /* We need to generate a load to DPTR indirect through DPTR. */
9368               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9369               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9370               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9371               if (options.model == MODEL_FLAT24)
9372                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9373               emitcode ("pop", "dph");
9374               emitcode ("pop", "dpl");
9375               dopi =0;
9376             }
9377           _endLazyDPSEvaluation ();
9378         }
9379     }
9380   /* so dptr know contains the address */
9381   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9382
9383   /* if bit then unpack */
9384   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9385       if (AOP_INDPTRn(left)) {
9386           genSetDPTR(AOP(left)->aopu.dptr);
9387       }
9388       genUnpackBits (result, "dptr", FPOINTER);
9389       if (AOP_INDPTRn(left)) {
9390           genSetDPTR(0);
9391       }
9392   } else
9393     {
9394       size = AOP_SIZE (result);
9395       offset = 0;
9396
9397       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9398           while (size--) {
9399               genSetDPTR(AOP(left)->aopu.dptr);
9400               emitcode ("movx", "a,@dptr");
9401               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9402                   emitcode ("inc", "dptr");
9403               genSetDPTR (0);
9404               aopPut (AOP (result), "a", offset++);
9405           }
9406       } else {
9407           _startLazyDPSEvaluation ();
9408           while (size--) {
9409               if (AOP_INDPTRn(left)) {
9410                   genSetDPTR(AOP(left)->aopu.dptr);
9411               } else {
9412                   genSetDPTR (0);
9413               }
9414               _flushLazyDPS ();
9415               
9416               emitcode ("movx", "a,@dptr");
9417               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9418                   emitcode ("inc", "dptr");
9419               
9420               aopPut (AOP (result), "a", offset++);
9421           }
9422           _endLazyDPSEvaluation ();
9423       }
9424     }
9425   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9426       if (!AOP_INDPTRn(left)) {
9427           _startLazyDPSEvaluation ();
9428           aopPut ( AOP (left), "dpl", 0);
9429           aopPut ( AOP (left), "dph", 1);
9430           if (options.model == MODEL_FLAT24)
9431               aopPut ( AOP (left), "dpx", 2);
9432           _endLazyDPSEvaluation ();
9433       }
9434     pi->generated = 1;
9435   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9436              AOP_SIZE(result) > 1 &&
9437              IS_SYMOP(left) &&
9438              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9439       
9440       size = AOP_SIZE (result) - 1;
9441       if (AOP_INDPTRn(left)) {
9442           genSetDPTR(AOP(left)->aopu.dptr);
9443       }
9444       while (size--) emitcode ("lcall","__decdptr");
9445       if (AOP_INDPTRn(left)) {
9446           genSetDPTR(0);
9447       }
9448   }
9449
9450   freeAsmop (left, NULL, ic, TRUE);
9451   freeAsmop (result, NULL, ic, TRUE);
9452 }
9453
9454 /*-----------------------------------------------------------------*/
9455 /* genCodePointerGet - get value from code space                  */
9456 /*-----------------------------------------------------------------*/
9457 static void
9458 genCodePointerGet (operand * left,
9459                     operand * result, iCode * ic, iCode *pi)
9460 {
9461   int size, offset, dopi=1;
9462   sym_link *retype = getSpec (operandType (result));
9463
9464   aopOp (left, ic, FALSE, FALSE);
9465
9466   /* if the operand is already in dptr
9467      then we do nothing else we move the value to dptr */
9468   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9469     {
9470       /* if this is remateriazable */
9471       if (AOP_TYPE (left) == AOP_IMMD)
9472         {
9473           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9474         }
9475       else
9476         {                       /* we need to get it byte by byte */
9477           _startLazyDPSEvaluation ();
9478           if (AOP_TYPE (left) != AOP_DPTR)
9479             {
9480               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9481               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9482               if (options.model == MODEL_FLAT24)
9483                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9484             }
9485           else
9486             {
9487               /* We need to generate a load to DPTR indirect through DPTR. */
9488               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9489               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9490               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9491               if (options.model == MODEL_FLAT24)
9492                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9493               emitcode ("pop", "dph");
9494               emitcode ("pop", "dpl");
9495               dopi=0;
9496             }
9497           _endLazyDPSEvaluation ();
9498         }
9499     }
9500   /* so dptr know contains the address */
9501   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9502
9503   /* if bit then unpack */
9504   if (IS_BITVAR (retype)) {
9505       if (AOP_INDPTRn(left)) {
9506           genSetDPTR(AOP(left)->aopu.dptr);
9507       }
9508       genUnpackBits (result, "dptr", CPOINTER);
9509       if (AOP_INDPTRn(left)) {
9510           genSetDPTR(0);
9511       }
9512   } else
9513     {
9514       size = AOP_SIZE (result);
9515       offset = 0;
9516       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9517           while (size--) {
9518               genSetDPTR(AOP(left)->aopu.dptr);
9519               emitcode ("clr", "a");
9520               emitcode ("movc", "a,@a+dptr");
9521               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9522                   emitcode ("inc", "dptr");
9523               genSetDPTR (0);
9524               aopPut (AOP (result), "a", offset++);
9525           }
9526       } else {
9527           _startLazyDPSEvaluation ();
9528           while (size--)
9529               {
9530                   if (AOP_INDPTRn(left)) {
9531                       genSetDPTR(AOP(left)->aopu.dptr);
9532                   } else {
9533                       genSetDPTR (0);
9534                   }
9535                   _flushLazyDPS ();
9536                   
9537                   emitcode ("clr", "a");
9538                   emitcode ("movc", "a,@a+dptr");
9539                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9540                       emitcode ("inc", "dptr");
9541                   aopPut (AOP (result), "a", offset++);
9542               }
9543           _endLazyDPSEvaluation ();
9544       }
9545     }
9546   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9547       if (!AOP_INDPTRn(left)) {
9548           _startLazyDPSEvaluation ();
9549           
9550           aopPut ( AOP (left), "dpl", 0);
9551           aopPut ( AOP (left), "dph", 1);
9552           if (options.model == MODEL_FLAT24)
9553               aopPut ( AOP (left), "dpx", 2);
9554
9555           _endLazyDPSEvaluation ();
9556       }
9557       pi->generated = 1;
9558   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9559              AOP_SIZE(result) > 1 &&
9560              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9561       
9562       size = AOP_SIZE (result) - 1;
9563       if (AOP_INDPTRn(left)) {
9564           genSetDPTR(AOP(left)->aopu.dptr);
9565       }
9566       while (size--) emitcode ("lcall","__decdptr");
9567       if (AOP_INDPTRn(left)) {
9568           genSetDPTR(0);
9569       }
9570   }
9571   
9572   freeAsmop (left, NULL, ic, TRUE);
9573   freeAsmop (result, NULL, ic, TRUE);
9574 }
9575
9576 /*-----------------------------------------------------------------*/
9577 /* genGenPointerGet - gget value from generic pointer space        */
9578 /*-----------------------------------------------------------------*/
9579 static void
9580 genGenPointerGet (operand * left,
9581                   operand * result, iCode * ic, iCode * pi)
9582 {
9583   int size, offset;
9584   sym_link *retype = getSpec (operandType (result));
9585   sym_link *letype = getSpec (operandType (left));
9586
9587   D (emitcode (";", "genGenPointerGet "); );
9588
9589   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9590
9591   /* if the operand is already in dptr
9592      then we do nothing else we move the value to dptr */
9593   if (AOP_TYPE (left) != AOP_STR)
9594     {
9595       /* if this is remateriazable */
9596       if (AOP_TYPE (left) == AOP_IMMD)
9597         {
9598           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9599           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9600             {
9601                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9602             }
9603             else
9604             {
9605                 emitcode ("mov", "b,#%d", pointerCode (retype));
9606             }
9607         }
9608       else
9609         {                       /* we need to get it byte by byte */
9610             _startLazyDPSEvaluation ();
9611             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9612             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9613             if (options.model == MODEL_FLAT24) {
9614                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9615                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9616             } else {
9617                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9618             }
9619             _endLazyDPSEvaluation ();
9620         }
9621     }
9622
9623   /* so dptr-b now contains the address */
9624   _G.bInUse++;
9625   aopOp (result, ic, FALSE, TRUE);
9626   _G.bInUse--;
9627
9628   /* if bit then unpack */
9629   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9630   {
9631     genUnpackBits (result, "dptr", GPOINTER);
9632   }
9633   else
9634     {
9635         size = AOP_SIZE (result);
9636         offset = 0;
9637
9638         while (size--)
9639         {
9640             if (size)
9641             {
9642                 // Get two bytes at a time, results in _AP & A.
9643                 // dptr will be incremented ONCE by __gptrgetWord.
9644                 //
9645                 // Note: any change here must be coordinated
9646                 // with the implementation of __gptrgetWord
9647                 // in device/lib/_gptrget.c
9648                 emitcode ("lcall", "__gptrgetWord");
9649                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9650                 aopPut (AOP (result), "a", offset++);
9651                 size--;
9652             }
9653             else
9654             {
9655                 // Only one byte to get.
9656                 emitcode ("lcall", "__gptrget");
9657                 aopPut (AOP (result), "a", offset++);
9658             }
9659             
9660             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9661             {
9662                 emitcode ("inc", "dptr");
9663             }
9664         }
9665     }
9666
9667   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9668     _startLazyDPSEvaluation ();
9669       
9670     aopPut ( AOP (left), "dpl", 0);
9671     aopPut ( AOP (left), "dph", 1);
9672     if (options.model == MODEL_FLAT24) {
9673         aopPut ( AOP (left), "dpx", 2);
9674         aopPut ( AOP (left), "b", 3);   
9675     } else  aopPut ( AOP (left), "b", 2);       
9676     
9677     _endLazyDPSEvaluation ();
9678       
9679     pi->generated = 1;
9680   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9681              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9682       
9683       size = AOP_SIZE (result) - 1;
9684       while (size--) emitcode ("lcall","__decdptr");
9685   }
9686
9687   freeAsmop (left, NULL, ic, TRUE);
9688   freeAsmop (result, NULL, ic, TRUE);
9689 }
9690
9691 /*-----------------------------------------------------------------*/
9692 /* genPointerGet - generate code for pointer get                   */
9693 /*-----------------------------------------------------------------*/
9694 static void
9695 genPointerGet (iCode * ic, iCode *pi)
9696 {
9697   operand *left, *result;
9698   sym_link *type, *etype;
9699   int p_type;
9700
9701   D (emitcode (";", "genPointerGet ");
9702     );
9703
9704   left = IC_LEFT (ic);
9705   result = IC_RESULT (ic);
9706
9707   /* depending on the type of pointer we need to
9708      move it to the correct pointer register */
9709   type = operandType (left);
9710   etype = getSpec (type);
9711   /* if left is of type of pointer then it is simple */
9712   if (IS_PTR (type) && !IS_FUNC (type->next))
9713     p_type = DCL_TYPE (type);
9714   else
9715     {
9716       /* we have to go by the storage class */
9717       p_type = PTR_TYPE (SPEC_OCLS (etype));
9718     }
9719   /* special case when cast remat */
9720   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9721       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9722           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9723           type = operandType (left);
9724           p_type = DCL_TYPE (type);
9725   }
9726   /* now that we have the pointer type we assign
9727      the pointer values */
9728   switch (p_type)
9729     {
9730
9731     case POINTER:
9732     case IPOINTER:
9733       genNearPointerGet (left, result, ic, pi);
9734       break;
9735
9736     case PPOINTER:
9737       genPagedPointerGet (left, result, ic, pi);
9738       break;
9739
9740     case FPOINTER:
9741       genFarPointerGet (left, result, ic, pi);
9742       break;
9743
9744     case CPOINTER:
9745       genCodePointerGet (left, result, ic, pi);
9746       break;
9747
9748     case GPOINTER:
9749       genGenPointerGet (left, result, ic, pi);
9750       break;
9751     }
9752
9753 }
9754
9755 /*-----------------------------------------------------------------*/
9756 /* genPackBits - generates code for packed bit storage             */
9757 /*-----------------------------------------------------------------*/
9758 static void
9759 genPackBits (sym_link * etype,
9760              operand * right,
9761              char *rname, int p_type)
9762 {
9763   int offset = 0;
9764   int rLen;
9765   int blen, bstr;
9766   char *l;
9767
9768   blen = SPEC_BLEN (etype);
9769   bstr = SPEC_BSTR (etype);
9770
9771   MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9772
9773   /* if the bit lenth is less than or    */
9774   /* it exactly fits a byte then         */
9775   if (SPEC_BLEN (etype) <= 8)
9776     {
9777       /* shift left acc */
9778       AccLsh (SPEC_BSTR (etype));
9779
9780       if (SPEC_BLEN (etype) < 8)
9781         {                       /* if smaller than a byte */
9782
9783
9784           switch (p_type)
9785             {
9786             case POINTER:
9787               emitcode ("mov", "b,a");
9788               emitcode ("mov", "a,@%s", rname);
9789               break;
9790
9791             case FPOINTER:
9792               emitcode ("mov", "b,a");
9793               emitcode ("movx", "a,@dptr");
9794               break;
9795
9796             case GPOINTER:
9797               emitcode ("push", "b");
9798               emitcode ("push", "acc");
9799               emitcode ("lcall", "__gptrget");
9800               emitcode ("pop", "b");
9801               break;
9802             }
9803
9804           emitcode ("anl", "a,#!constbyte", (unsigned char)
9805                     ((unsigned char) (0xFF << (blen + bstr)) |
9806                      (unsigned char) (0xFF >> (8 - bstr))));
9807           emitcode ("orl", "a,b");
9808           if (p_type == GPOINTER)
9809             emitcode ("pop", "b");
9810         }
9811     }
9812
9813   switch (p_type)
9814     {
9815     case POINTER:
9816       emitcode ("mov", "@%s,a", rname);
9817       break;
9818
9819     case FPOINTER:
9820       emitcode ("movx", "@dptr,a");
9821       break;
9822
9823     case GPOINTER:
9824       emitcode ("lcall", "__gptrput");
9825       break;
9826     }
9827
9828   /* if we r done */
9829   if (SPEC_BLEN (etype) <= 8)
9830     return;
9831
9832   emitcode ("inc", "%s", rname);
9833   rLen = SPEC_BLEN (etype);
9834
9835   /* now generate for lengths greater than one byte */
9836   while (1)
9837     {
9838
9839       l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9840
9841       rLen -= 8;
9842       if (rLen < 8)
9843         break;
9844
9845       switch (p_type)
9846         {
9847         case POINTER:
9848           if (*l == '@')
9849             {
9850               MOVA (l);
9851               emitcode ("mov", "@%s,a", rname);
9852             }
9853           else
9854             emitcode ("mov", "@%s,%s", rname, l);
9855           break;
9856
9857         case FPOINTER:
9858           MOVA (l);
9859           emitcode ("movx", "@dptr,a");
9860           break;
9861
9862         case GPOINTER:
9863           MOVA (l);
9864           emitcode ("lcall", "__gptrput");
9865           break;
9866         }
9867       emitcode ("inc", "%s", rname);
9868     }
9869
9870   MOVA (l);
9871
9872   /* last last was not complete */
9873   if (rLen)
9874     {
9875       /* save the byte & read byte */
9876       switch (p_type)
9877         {
9878         case POINTER:
9879           emitcode ("mov", "b,a");
9880           emitcode ("mov", "a,@%s", rname);
9881           break;
9882
9883         case FPOINTER:
9884           emitcode ("mov", "b,a");
9885           emitcode ("movx", "a,@dptr");
9886           break;
9887
9888         case GPOINTER:
9889           emitcode ("push", "b");
9890           emitcode ("push", "acc");
9891           emitcode ("lcall", "__gptrget");
9892           emitcode ("pop", "b");
9893           break;
9894         }
9895
9896       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9897       emitcode ("orl", "a,b");
9898     }
9899
9900   if (p_type == GPOINTER)
9901     emitcode ("pop", "b");
9902
9903   switch (p_type)
9904     {
9905
9906     case POINTER:
9907       emitcode ("mov", "@%s,a", rname);
9908       break;
9909
9910     case FPOINTER:
9911       emitcode ("movx", "@dptr,a");
9912       break;
9913
9914     case GPOINTER:
9915       emitcode ("lcall", "__gptrput");
9916       break;
9917     }
9918 }
9919 /*-----------------------------------------------------------------*/
9920 /* genDataPointerSet - remat pointer to data space                 */
9921 /*-----------------------------------------------------------------*/
9922 static void
9923 genDataPointerSet (operand * right,
9924                    operand * result,
9925                    iCode * ic)
9926 {
9927   int size, offset = 0;
9928   char *l, buff[256];
9929
9930   aopOp (right, ic, FALSE, FALSE);
9931
9932   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9933   size = AOP_SIZE (right);
9934   while (size--)
9935     {
9936       if (offset)
9937         {
9938             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9939         }
9940       else
9941         {
9942             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9943         }
9944         
9945       emitcode ("mov", "%s,%s", buff,
9946                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9947     }
9948
9949   freeAsmop (right, NULL, ic, TRUE);
9950   freeAsmop (result, NULL, ic, TRUE);
9951 }
9952
9953 /*-----------------------------------------------------------------*/
9954 /* genNearPointerSet - emitcode for near pointer put                */
9955 /*-----------------------------------------------------------------*/
9956 static void
9957 genNearPointerSet (operand * right,
9958                    operand * result,
9959                    iCode * ic,
9960                    iCode * pi)
9961 {
9962   asmop *aop = NULL;
9963   char *rname, *l;
9964   sym_link *retype, *letype;
9965   sym_link *ptype = operandType (result);
9966
9967   retype = getSpec (operandType (right));
9968   letype = getSpec (ptype);
9969
9970   aopOp (result, ic, FALSE, FALSE);
9971
9972   /* if the result is rematerializable &
9973      in data space & not a bit variable */
9974   if (AOP_TYPE (result) == AOP_IMMD &&
9975       DCL_TYPE (ptype) == POINTER &&
9976       !IS_BITVAR (retype) &&
9977       !IS_BITVAR (letype))
9978     {
9979       genDataPointerSet (right, result, ic);
9980       return;
9981     }
9982
9983   /* if the value is already in a pointer register
9984      then don't need anything more */
9985   if (!AOP_INPREG (AOP (result)))
9986     {
9987       /* otherwise get a free pointer register */
9988       regs *preg;
9989         
9990       aop = newAsmop (0);
9991       preg = getFreePtr (ic, &aop, FALSE);
9992       emitcode ("mov", "%s,%s",
9993                 preg->name,
9994                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9995       rname = preg->name;
9996     }
9997   else
9998     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9999
10000   aopOp (right, ic, FALSE, FALSE);
10001
10002   /* if bitfield then unpack the bits */
10003   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10004     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10005   else
10006     {
10007       /* we have can just get the values */
10008       int size = AOP_SIZE (right);
10009       int offset = 0;
10010
10011       while (size--)
10012         {
10013           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10014           if (*l == '@')
10015             {
10016               MOVA (l);
10017               emitcode ("mov", "@%s,a", rname);
10018             }
10019           else
10020             emitcode ("mov", "@%s,%s", rname, l);
10021           if (size || pi)
10022             emitcode ("inc", "%s", rname);
10023           offset++;
10024         }
10025     }
10026
10027   /* now some housekeeping stuff */
10028   if (aop)
10029     {
10030       /* we had to allocate for this iCode */
10031       if (pi) aopPut (AOP (result),rname,0);
10032       freeAsmop (NULL, aop, ic, TRUE);
10033     }
10034   else
10035     {
10036       /* we did not allocate which means left
10037          already in a pointer register, then
10038          if size > 0 && this could be used again
10039          we have to point it back to where it
10040          belongs */
10041       if (AOP_SIZE (right) > 1 &&
10042           !OP_SYMBOL (result)->remat &&
10043           (OP_SYMBOL (result)->liveTo > ic->seq ||
10044            ic->depth) &&
10045           !pi)
10046         {
10047           int size = AOP_SIZE (right) - 1;
10048           while (size--)
10049             emitcode ("dec", "%s", rname);
10050         }
10051     }
10052
10053   /* done */
10054   if (pi) pi->generated = 1;
10055   freeAsmop (result, NULL, ic, TRUE);
10056   freeAsmop (right, NULL, ic, TRUE);
10057
10058
10059 }
10060
10061 /*-----------------------------------------------------------------*/
10062 /* genPagedPointerSet - emitcode for Paged pointer put             */
10063 /*-----------------------------------------------------------------*/
10064 static void
10065 genPagedPointerSet (operand * right,
10066                     operand * result,
10067                     iCode * ic,
10068                     iCode *pi)
10069 {
10070   asmop *aop = NULL;
10071   char *rname;
10072   sym_link *retype, *letype;
10073
10074   retype = getSpec (operandType (right));
10075   letype = getSpec (operandType (result));
10076
10077   aopOp (result, ic, FALSE, FALSE);
10078
10079   /* if the value is already in a pointer register
10080      then don't need anything more */
10081   if (!AOP_INPREG (AOP (result)))
10082     {
10083       /* otherwise get a free pointer register */
10084       regs *preg;
10085         
10086       aop = newAsmop (0);
10087       preg = getFreePtr (ic, &aop, FALSE);
10088       emitcode ("mov", "%s,%s",
10089                 preg->name,
10090                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10091       rname = preg->name;
10092     }
10093   else
10094     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10095
10096   aopOp (right, ic, FALSE, FALSE);
10097
10098   /* if bitfield then unpack the bits */
10099   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10100     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10101   else
10102     {
10103       /* we have can just get the values */
10104       int size = AOP_SIZE (right);
10105       int offset = 0;
10106
10107       while (size--)
10108         {
10109           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10110
10111           emitcode ("movx", "@%s,a", rname);
10112
10113           if (size || pi)
10114             emitcode ("inc", "%s", rname);
10115
10116           offset++;
10117         }
10118     }
10119
10120   /* now some housekeeping stuff */
10121   if (aop)
10122     {
10123       if (pi) aopPut (AOP (result),rname,0);
10124       /* we had to allocate for this iCode */
10125       freeAsmop (NULL, aop, ic, TRUE);
10126     }
10127   else
10128     {
10129       /* we did not allocate which means left
10130          already in a pointer register, then
10131          if size > 0 && this could be used again
10132          we have to point it back to where it
10133          belongs */
10134       if (AOP_SIZE (right) > 1 &&
10135           !OP_SYMBOL (result)->remat &&
10136           (OP_SYMBOL (result)->liveTo > ic->seq ||
10137            ic->depth) &&
10138           !pi)
10139         {
10140           int size = AOP_SIZE (right) - 1;
10141           while (size--)
10142             emitcode ("dec", "%s", rname);
10143         }
10144     }
10145
10146   /* done */
10147   if (pi) pi->generated = 1;
10148   freeAsmop (result, NULL, ic, TRUE);
10149   freeAsmop (right, NULL, ic, TRUE);
10150
10151
10152 }
10153
10154 /*-----------------------------------------------------------------*/
10155 /* genFarPointerSet - set value from far space                     */
10156 /*-----------------------------------------------------------------*/
10157 static void
10158 genFarPointerSet (operand * right,
10159                   operand * result, iCode * ic, iCode *pi)
10160 {
10161   int size, offset, dopi=1;
10162   sym_link *retype = getSpec (operandType (right));
10163   sym_link *letype = getSpec (operandType (result));
10164
10165   aopOp (result, ic, FALSE, FALSE);
10166
10167   /* if the operand is already in dptr
10168      then we do nothing else we move the value to dptr */
10169   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10170     {
10171       /* if this is remateriazable */
10172       if (AOP_TYPE (result) == AOP_IMMD)
10173         emitcode ("mov", "dptr,%s", 
10174                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10175       else
10176         {
10177           /* we need to get it byte by byte */
10178           _startLazyDPSEvaluation ();
10179           if (AOP_TYPE (result) != AOP_DPTR)
10180             {
10181               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10182               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10183               if (options.model == MODEL_FLAT24)
10184                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10185             }
10186           else
10187             {
10188               /* We need to generate a load to DPTR indirect through DPTR. */
10189               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10190                 
10191               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10192               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10193               if (options.model == MODEL_FLAT24)
10194                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10195               emitcode ("pop", "dph");
10196               emitcode ("pop", "dpl");
10197               dopi=0;
10198             }
10199           _endLazyDPSEvaluation ();
10200         }
10201     }
10202   /* so dptr know contains the address */
10203   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10204
10205   /* if bit then unpack */
10206   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10207       if (AOP_INDPTRn(result)) {
10208           genSetDPTR(AOP(result)->aopu.dptr);
10209       }
10210       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10211       if (AOP_INDPTRn(result)) {
10212           genSetDPTR(0);
10213       }
10214   } else {
10215       size = AOP_SIZE (right);
10216       offset = 0;
10217       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10218           while (size--) {
10219               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10220               
10221               genSetDPTR(AOP(result)->aopu.dptr);
10222               emitcode ("movx", "@dptr,a");
10223               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10224                   emitcode ("inc", "dptr");
10225               genSetDPTR (0);
10226           }
10227       } else {
10228           _startLazyDPSEvaluation ();
10229           while (size--) {
10230               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10231               
10232               if (AOP_INDPTRn(result)) {
10233                   genSetDPTR(AOP(result)->aopu.dptr);
10234               } else {
10235                   genSetDPTR (0);
10236               }
10237               _flushLazyDPS ();
10238               
10239               emitcode ("movx", "@dptr,a");
10240               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10241                   emitcode ("inc", "dptr");
10242           }
10243           _endLazyDPSEvaluation ();
10244       }
10245   }
10246   
10247   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10248       if (!AOP_INDPTRn(result)) {
10249           _startLazyDPSEvaluation ();
10250           
10251           aopPut (AOP(result),"dpl",0);
10252           aopPut (AOP(result),"dph",1);
10253           if (options.model == MODEL_FLAT24)
10254               aopPut (AOP(result),"dpx",2);
10255
10256           _endLazyDPSEvaluation ();
10257       }
10258       pi->generated=1;
10259   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10260              AOP_SIZE(right) > 1 &&
10261              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10262       
10263       size = AOP_SIZE (right) - 1;
10264       if (AOP_INDPTRn(result)) {
10265           genSetDPTR(AOP(result)->aopu.dptr);
10266       } 
10267       while (size--) emitcode ("lcall","__decdptr");
10268       if (AOP_INDPTRn(result)) {
10269           genSetDPTR(0);
10270       }
10271   }
10272   freeAsmop (result, NULL, ic, TRUE);
10273   freeAsmop (right, NULL, ic, TRUE);
10274 }
10275
10276 /*-----------------------------------------------------------------*/
10277 /* genGenPointerSet - set value from generic pointer space         */
10278 /*-----------------------------------------------------------------*/
10279 static void
10280 genGenPointerSet (operand * right,
10281                   operand * result, iCode * ic, iCode *pi)
10282 {
10283   int size, offset;
10284   sym_link *retype = getSpec (operandType (right));
10285   sym_link *letype = getSpec (operandType (result));
10286
10287   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10288
10289   /* if the operand is already in dptr
10290      then we do nothing else we move the value to dptr */
10291   if (AOP_TYPE (result) != AOP_STR)
10292     {
10293       _startLazyDPSEvaluation ();
10294       /* if this is remateriazable */
10295       if (AOP_TYPE (result) == AOP_IMMD)
10296         {
10297           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10298           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10299           {
10300               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10301           }
10302           else
10303           {
10304               emitcode ("mov", 
10305                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10306           }
10307         }
10308       else
10309         {                       /* we need to get it byte by byte */
10310           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10311           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10312           if (options.model == MODEL_FLAT24) {
10313             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10314             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10315           } else {
10316             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10317           }
10318         }
10319       _endLazyDPSEvaluation ();
10320     }
10321   /* so dptr + b now contains the address */
10322   _G.bInUse++;
10323   aopOp (right, ic, FALSE, TRUE);
10324   _G.bInUse--;
10325     
10326
10327   /* if bit then unpack */
10328   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10329     {
10330         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10331     }
10332   else
10333     {
10334         size = AOP_SIZE (right);
10335         offset = 0;
10336
10337         _startLazyDPSEvaluation ();
10338         while (size--)
10339         {
10340             if (size)
10341             {
10342                 // Set two bytes at a time, passed in _AP & A.
10343                 // dptr will be incremented ONCE by __gptrputWord.
10344                 //
10345                 // Note: any change here must be coordinated
10346                 // with the implementation of __gptrputWord
10347                 // in device/lib/_gptrput.c
10348                 emitcode("mov", "_ap, %s", 
10349                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10350                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10351                 
10352                 genSetDPTR (0);
10353                 _flushLazyDPS ();
10354                 emitcode ("lcall", "__gptrputWord");
10355                 size--;
10356             }
10357             else
10358             {
10359                 // Only one byte to put.
10360                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10361
10362                 genSetDPTR (0);
10363                 _flushLazyDPS ();               
10364                 emitcode ("lcall", "__gptrput");
10365             }
10366             
10367             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10368             {
10369                 emitcode ("inc", "dptr");
10370             }
10371         }
10372         _endLazyDPSEvaluation ();
10373     }
10374
10375   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10376       _startLazyDPSEvaluation ();
10377       
10378       aopPut (AOP(result),"dpl",0);
10379       aopPut (AOP(result),"dph",1);
10380       if (options.model == MODEL_FLAT24) {
10381           aopPut (AOP(result),"dpx",2);
10382           aopPut (AOP(result),"b",3);
10383       } else {
10384           aopPut (AOP(result),"b",2);
10385       }
10386       _endLazyDPSEvaluation ();
10387       
10388       pi->generated=1;
10389   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10390              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10391       
10392       size = AOP_SIZE (right) - 1;
10393       while (size--) emitcode ("lcall","__decdptr");
10394   }
10395   freeAsmop (result, NULL, ic, TRUE);
10396   freeAsmop (right, NULL, ic, TRUE);
10397 }
10398
10399 /*-----------------------------------------------------------------*/
10400 /* genPointerSet - stores the value into a pointer location        */
10401 /*-----------------------------------------------------------------*/
10402 static void
10403 genPointerSet (iCode * ic, iCode *pi)
10404 {
10405   operand *right, *result;
10406   sym_link *type, *etype;
10407   int p_type;
10408
10409   D (emitcode (";", "genPointerSet "););
10410
10411   right = IC_RIGHT (ic);
10412   result = IC_RESULT (ic);
10413
10414   /* depending on the type of pointer we need to
10415      move it to the correct pointer register */
10416   type = operandType (result);
10417   etype = getSpec (type);
10418   /* if left is of type of pointer then it is simple */
10419   if (IS_PTR (type) && !IS_FUNC (type->next))
10420     {
10421       p_type = DCL_TYPE (type);
10422     }
10423   else
10424     {
10425       /* we have to go by the storage class */
10426       p_type = PTR_TYPE (SPEC_OCLS (etype));
10427     }
10428   /* special case when cast remat */
10429   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10430       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10431           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10432           type = operandType (result);
10433           p_type = DCL_TYPE (type);
10434   }
10435
10436   /* now that we have the pointer type we assign
10437      the pointer values */
10438   switch (p_type)
10439     {
10440
10441     case POINTER:
10442     case IPOINTER:
10443       genNearPointerSet (right, result, ic, pi);
10444       break;
10445
10446     case PPOINTER:
10447       genPagedPointerSet (right, result, ic, pi);
10448       break;
10449
10450     case FPOINTER:
10451       genFarPointerSet (right, result, ic, pi);
10452       break;
10453
10454     case GPOINTER:
10455       genGenPointerSet (right, result, ic, pi);
10456       break;
10457
10458     default:
10459       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10460               "genPointerSet: illegal pointer type");
10461     }
10462
10463 }
10464
10465 /*-----------------------------------------------------------------*/
10466 /* genIfx - generate code for Ifx statement                        */
10467 /*-----------------------------------------------------------------*/
10468 static void
10469 genIfx (iCode * ic, iCode * popIc)
10470 {
10471   operand *cond = IC_COND (ic);
10472   int isbit = 0;
10473
10474   D (emitcode (";", "genIfx "););
10475
10476   aopOp (cond, ic, FALSE, FALSE);
10477
10478   /* get the value into acc */
10479   if (AOP_TYPE (cond) != AOP_CRY)
10480     {
10481         toBoolean (cond);
10482     }
10483   else
10484     {
10485         isbit = 1;
10486     }
10487     
10488   /* the result is now in the accumulator */
10489   freeAsmop (cond, NULL, ic, TRUE);
10490
10491   /* if there was something to be popped then do it */
10492   if (popIc)
10493     genIpop (popIc);
10494
10495   /* if the condition is  a bit variable */
10496   if (isbit && IS_ITEMP (cond) &&
10497       SPIL_LOC (cond))
10498     {
10499         genIfxJump (ic, SPIL_LOC (cond)->rname);
10500     }
10501   else if (isbit && !IS_ITEMP (cond))
10502     {
10503         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10504     }
10505   else
10506     {
10507         genIfxJump (ic, "a");
10508     }
10509
10510   ic->generated = 1;
10511 }
10512
10513 /*-----------------------------------------------------------------*/
10514 /* genAddrOf - generates code for address of                       */
10515 /*-----------------------------------------------------------------*/
10516 static void
10517 genAddrOf (iCode * ic)
10518 {
10519   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10520   int size, offset;
10521
10522   D (emitcode (";", "genAddrOf ");
10523     );
10524
10525   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10526
10527   /* if the operand is on the stack then we
10528      need to get the stack offset of this
10529      variable */
10530   if (sym->onStack) {
10531       
10532       /* if 10 bit stack */
10533       if (options.stack10bit) {
10534           char buff[10];
10535           int  offset;
10536           
10537           tsprintf(buff, sizeof(buff), 
10538                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10539           /* if it has an offset then we need to compute it */
10540 /*        emitcode ("subb", "a,#!constbyte", */
10541 /*                  -((sym->stack < 0) ? */
10542 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10543 /*                    ((short) sym->stack)) & 0xff); */
10544 /*        emitcode ("mov","b,a"); */
10545 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10546 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10547 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10548           if (sym->stack) {
10549               emitcode ("mov", "a,_bpx");
10550               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10551                                              ((char) (sym->stack - _G.nRegsSaved)) :
10552                                              ((char) sym->stack )) & 0xff);
10553               emitcode ("mov", "b,a");
10554               emitcode ("mov", "a,_bpx+1");
10555               
10556               offset = (((sym->stack < 0) ? 
10557                          ((short) (sym->stack - _G.nRegsSaved)) :
10558                          ((short) sym->stack )) >> 8) & 0xff;
10559           
10560               emitcode ("addc","a,#!constbyte", offset);
10561
10562               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10563               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10564               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10565           } else {
10566               /* we can just move _bp */
10567               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10568               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10569               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10570           }       
10571       } else {
10572           /* if it has an offset then we need to compute it */
10573           if (sym->stack) {
10574               emitcode ("mov", "a,_bp");
10575               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10576               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10577           } else {
10578               /* we can just move _bp */
10579               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10580           }
10581           /* fill the result with zero */
10582           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10583           
10584           
10585           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10586               fprintf (stderr,
10587                        "*** warning: pointer to stack var truncated.\n");
10588           }
10589
10590           offset = 1;
10591           while (size--) {
10592               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10593           }      
10594       }
10595       goto release;
10596   }
10597
10598   /* object not on stack then we need the name */
10599   size = AOP_SIZE (IC_RESULT (ic));
10600   offset = 0;
10601
10602   while (size--)
10603     {
10604       char s[SDCC_NAME_MAX];
10605       if (offset) {
10606           switch (offset) {
10607           case 1:
10608               tsprintf(s, sizeof(s), "#!his",sym->rname);
10609               break;
10610           case 2:
10611               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10612               break;
10613           case 3:
10614               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10615               break;
10616           default: /* should not need this (just in case) */
10617               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10618                        sym->rname,
10619                        offset * 8);
10620           }
10621       } 
10622       else
10623       {
10624           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10625       }
10626         
10627       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10628     }
10629
10630 release:
10631   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10632
10633 }
10634
10635 #if 0 // obsolete, and buggy for != xdata
10636 /*-----------------------------------------------------------------*/
10637 /* genArrayInit - generates code for address of                       */
10638 /*-----------------------------------------------------------------*/
10639 static void
10640 genArrayInit (iCode * ic)
10641 {
10642     literalList *iLoop;
10643     int         ix, count;
10644     int         elementSize = 0, eIndex;
10645     unsigned    val, lastVal;
10646     sym_link    *type;
10647     operand     *left=IC_LEFT(ic);
10648     
10649     D (emitcode (";", "genArrayInit "););
10650
10651     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10652     
10653     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10654     {
10655         // Load immediate value into DPTR.
10656         emitcode("mov", "dptr, %s",
10657              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10658     }
10659     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10660     {
10661 #if 0
10662       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10663               "Unexpected operand to genArrayInit.\n");
10664       exit(1);
10665 #else
10666       // a regression because of SDCCcse.c:1.52
10667       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10668       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10669       if (options.model == MODEL_FLAT24)
10670         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10671 #endif
10672     }
10673     
10674     type = operandType(IC_LEFT(ic));
10675     
10676     if (type && type->next)
10677     {
10678         elementSize = getSize(type->next);
10679     }
10680     else
10681     {
10682         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10683                                 "can't determine element size in genArrayInit.\n");
10684         exit(1);
10685     }
10686     
10687     iLoop = IC_ARRAYILIST(ic);
10688     lastVal = 0xffff;
10689     
10690     while (iLoop)
10691     {
10692         bool firstpass = TRUE;
10693         
10694         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10695                  iLoop->count, (int)iLoop->literalValue, elementSize);
10696         
10697         ix = iLoop->count;
10698         
10699         while (ix)
10700         {
10701             symbol *tlbl = NULL;
10702             
10703             count = ix > 256 ? 256 : ix;
10704             
10705             if (count > 1)
10706             {
10707                 tlbl = newiTempLabel (NULL);
10708                 if (firstpass || (count & 0xff))
10709                 {
10710                     emitcode("mov", "b, #!constbyte", count & 0xff);
10711                 }
10712                 
10713                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10714             }
10715             
10716             firstpass = FALSE;
10717                 
10718             for (eIndex = 0; eIndex < elementSize; eIndex++)
10719             {
10720                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10721                 if (val != lastVal)
10722                 {
10723                     emitcode("mov", "a, #!constbyte", val);
10724                     lastVal = val;
10725                 }
10726                 
10727                 emitcode("movx", "@dptr, a");
10728                 emitcode("inc", "dptr");
10729             }
10730             
10731             if (count > 1)
10732             {
10733                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10734             }
10735             
10736             ix -= count;
10737         }
10738         
10739         iLoop = iLoop->next;
10740     }
10741     
10742     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10743 }
10744 #endif
10745
10746 /*-----------------------------------------------------------------*/
10747 /* genFarFarAssign - assignment when both are in far space         */
10748 /*-----------------------------------------------------------------*/
10749 static void
10750 genFarFarAssign (operand * result, operand * right, iCode * ic)
10751 {
10752   int size = AOP_SIZE (right);
10753   int offset = 0;
10754   symbol *rSym = NULL;
10755
10756   if (size == 1)
10757   {
10758       /* quick & easy case. */
10759       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10760       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10761       freeAsmop (right, NULL, ic, FALSE);
10762       /* now assign DPTR to result */
10763       _G.accInUse++;
10764       aopOp(result, ic, FALSE, FALSE);
10765       _G.accInUse--;
10766       aopPut(AOP(result), "a", 0);
10767       freeAsmop(result, NULL, ic, FALSE);
10768       return;
10769   }
10770   
10771   /* See if we've got an underlying symbol to abuse. */
10772   if (IS_SYMOP(result) && OP_SYMBOL(result))
10773   {
10774       if (IS_TRUE_SYMOP(result))
10775       {
10776           rSym = OP_SYMBOL(result);
10777       }
10778       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10779       {
10780           rSym = OP_SYMBOL(result)->usl.spillLoc;
10781       }
10782   }
10783              
10784   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10785   {
10786       /* We can use the '390 auto-toggle feature to good effect here. */
10787       
10788       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10789       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10790       emitcode ("mov", "dptr,#%s", rSym->rname); 
10791       /* DP2 = result, DP1 = right, DP1 is current. */
10792       while (size)
10793       {
10794           emitcode("movx", "a,@dptr");
10795           emitcode("movx", "@dptr,a");
10796           if (--size)
10797           {
10798                emitcode("inc", "dptr");
10799                emitcode("inc", "dptr");
10800           }
10801       }
10802       emitcode("mov", "dps,#0");
10803       freeAsmop (right, NULL, ic, FALSE);
10804 #if 0
10805 some alternative code for processors without auto-toggle
10806 no time to test now, so later well put in...kpb
10807         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10808         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10809         emitcode ("mov", "dptr,#%s", rSym->rname); 
10810         /* DP2 = result, DP1 = right, DP1 is current. */
10811         while (size)
10812         {
10813           --size;
10814           emitcode("movx", "a,@dptr");
10815           if (size)
10816             emitcode("inc", "dptr");
10817           emitcode("inc", "dps");
10818           emitcode("movx", "@dptr,a");
10819           if (size)
10820             emitcode("inc", "dptr");
10821           emitcode("inc", "dps");
10822         }
10823         emitcode("mov", "dps,#0");
10824         freeAsmop (right, NULL, ic, FALSE);
10825 #endif
10826   }
10827   else
10828   {
10829       D (emitcode (";", "genFarFarAssign"););
10830       aopOp (result, ic, TRUE, TRUE);
10831
10832       _startLazyDPSEvaluation ();
10833       
10834       while (size--)
10835         {
10836           aopPut (AOP (result),
10837                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10838           offset++;
10839         }
10840       _endLazyDPSEvaluation ();
10841       freeAsmop (result, NULL, ic, FALSE);
10842       freeAsmop (right, NULL, ic, FALSE);
10843   }
10844 }
10845
10846 /*-----------------------------------------------------------------*/
10847 /* genAssign - generate code for assignment                        */
10848 /*-----------------------------------------------------------------*/
10849 static void
10850 genAssign (iCode * ic)
10851 {
10852   operand *result, *right;
10853   int size, offset;
10854   unsigned long lit = 0L;
10855
10856   D (emitcode (";", "genAssign ");
10857     );
10858
10859   result = IC_RESULT (ic);
10860   right = IC_RIGHT (ic);
10861
10862   /* if they are the same */
10863   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10864     return;
10865
10866   aopOp (right, ic, FALSE, FALSE);
10867
10868   emitcode (";", "genAssign: resultIsFar = %s",
10869             isOperandInFarSpace (result) ?
10870             "TRUE" : "FALSE");
10871
10872   /* special case both in far space */
10873   if ((AOP_TYPE (right) == AOP_DPTR ||
10874        AOP_TYPE (right) == AOP_DPTR2) &&
10875   /* IS_TRUE_SYMOP(result)       && */
10876       isOperandInFarSpace (result))
10877     {
10878       genFarFarAssign (result, right, ic);
10879       return;
10880     }
10881
10882   aopOp (result, ic, TRUE, FALSE);
10883
10884   /* if they are the same registers */
10885   if (sameRegs (AOP (right), AOP (result)))
10886     goto release;
10887
10888   /* if the result is a bit */
10889   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10890     {
10891       /* if the right size is a literal then
10892          we know what the value is */
10893       if (AOP_TYPE (right) == AOP_LIT)
10894         {
10895           if (((int) operandLitValue (right)))
10896             aopPut (AOP (result), one, 0);
10897           else
10898             aopPut (AOP (result), zero, 0);
10899           goto release;
10900         }
10901
10902       /* the right is also a bit variable */
10903       if (AOP_TYPE (right) == AOP_CRY)
10904         {
10905           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10906           aopPut (AOP (result), "c", 0);
10907           goto release;
10908         }
10909
10910       /* we need to or */
10911       toBoolean (right);
10912       aopPut (AOP (result), "a", 0);
10913       goto release;
10914     }
10915
10916   /* bit variables done */
10917   /* general case */
10918   size = AOP_SIZE (result);
10919   offset = 0;
10920   if (AOP_TYPE (right) == AOP_LIT)
10921     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10922
10923   if ((size > 1) &&
10924       (AOP_TYPE (result) != AOP_REG) &&
10925       (AOP_TYPE (right) == AOP_LIT) &&
10926       !IS_FLOAT (operandType (right)))
10927     {
10928       _startLazyDPSEvaluation ();
10929       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10930         {
10931           aopPut (AOP (result),
10932                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10933                   offset);
10934           offset++;
10935           size--;
10936         }
10937       /* And now fill the rest with zeros. */
10938       if (size)
10939         {
10940           emitcode ("clr", "a");
10941         }
10942       while (size--)
10943         {
10944           aopPut (AOP (result), "a", offset++);
10945         }
10946       _endLazyDPSEvaluation ();
10947     }
10948   else
10949     {
10950       _startLazyDPSEvaluation ();
10951       while (size--)
10952         {
10953           aopPut (AOP (result),
10954                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10955                   offset);
10956           offset++;
10957         }
10958       _endLazyDPSEvaluation ();
10959     }
10960
10961 release:
10962   freeAsmop (right, NULL, ic, FALSE);
10963   freeAsmop (result, NULL, ic, TRUE);
10964 }
10965
10966 /*-----------------------------------------------------------------*/
10967 /* genJumpTab - generates code for jump table                      */
10968 /*-----------------------------------------------------------------*/
10969 static void
10970 genJumpTab (iCode * ic)
10971 {
10972   symbol *jtab;
10973   char *l;
10974
10975   D (emitcode (";", "genJumpTab ");
10976     );
10977
10978   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10979   /* get the condition into accumulator */
10980   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10981   MOVA (l);
10982   /* multiply by four! */
10983   emitcode ("add", "a,acc");
10984   emitcode ("add", "a,acc");
10985   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10986
10987   jtab = newiTempLabel (NULL);
10988   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10989   emitcode ("jmp", "@a+dptr");
10990   emitcode ("", "!tlabeldef", jtab->key + 100);
10991   /* now generate the jump labels */
10992   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10993        jtab = setNextItem (IC_JTLABELS (ic)))
10994     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10995
10996 }
10997
10998 /*-----------------------------------------------------------------*/
10999 /* genCast - gen code for casting                                  */
11000 /*-----------------------------------------------------------------*/
11001 static void
11002 genCast (iCode * ic)
11003 {
11004   operand *result = IC_RESULT (ic);
11005   sym_link *ctype = operandType (IC_LEFT (ic));
11006   sym_link *rtype = operandType (IC_RIGHT (ic));
11007   operand *right = IC_RIGHT (ic);
11008   int size, offset;
11009
11010   D (emitcode (";", "genCast "););
11011
11012   /* if they are equivalent then do nothing */
11013   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11014     return;
11015
11016   aopOp (right, ic, FALSE, FALSE);
11017   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11018
11019   /* if the result is a bit */
11020   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11021   if (IS_BITVAR(OP_SYMBOL(result)->type))
11022     {
11023       /* if the right size is a literal then
11024          we know what the value is */
11025       if (AOP_TYPE (right) == AOP_LIT)
11026         {
11027           if (((int) operandLitValue (right)))
11028             aopPut (AOP (result), one, 0);
11029           else
11030             aopPut (AOP (result), zero, 0);
11031
11032           goto release;
11033         }
11034
11035       /* the right is also a bit variable */
11036       if (AOP_TYPE (right) == AOP_CRY)
11037         {
11038           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11039           aopPut (AOP (result), "c", 0);
11040           goto release;
11041         }
11042
11043       /* we need to or */
11044       toBoolean (right);
11045       aopPut (AOP (result), "a", 0);
11046       goto release;
11047     }
11048
11049   /* if they are the same size : or less */
11050   if (AOP_SIZE (result) <= AOP_SIZE (right))
11051     {
11052
11053       /* if they are in the same place */
11054       if (sameRegs (AOP (right), AOP (result)))
11055         goto release;
11056
11057       /* if they in different places then copy */
11058       size = AOP_SIZE (result);
11059       offset = 0;
11060       _startLazyDPSEvaluation ();
11061       while (size--)
11062         {
11063           aopPut (AOP (result),
11064                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11065                   offset);
11066           offset++;
11067         }
11068       _endLazyDPSEvaluation ();
11069       goto release;
11070     }
11071
11072
11073   /* if the result is of type pointer */
11074   if (IS_PTR (ctype))
11075     {
11076
11077       int p_type;
11078       sym_link *type = operandType (right);
11079
11080       /* pointer to generic pointer */
11081       if (IS_GENPTR (ctype))
11082         {
11083           if (IS_PTR (type))
11084             {
11085               p_type = DCL_TYPE (type);
11086             }
11087           else
11088             {
11089 #if OLD_CAST_BEHAVIOR
11090               /* KV: we are converting a non-pointer type to
11091                * a generic pointer. This (ifdef'd out) code
11092                * says that the resulting generic pointer
11093                * should have the same class as the storage
11094                * location of the non-pointer variable.
11095                *
11096                * For example, converting an int (which happens
11097                * to be stored in DATA space) to a pointer results
11098                * in a DATA generic pointer; if the original int
11099                * in XDATA space, so will be the resulting pointer.
11100                *
11101                * I don't like that behavior, and thus this change:
11102                * all such conversions will be forced to XDATA and
11103                * throw a warning. If you want some non-XDATA
11104                * type, or you want to suppress the warning, you
11105                * must go through an intermediate cast, like so:
11106                *
11107                * char _generic *gp = (char _xdata *)(intVar);
11108                */
11109               sym_link *etype = getSpec (type);
11110
11111               /* we have to go by the storage class */
11112               if (SPEC_OCLS (etype) != generic)
11113                 {
11114                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11115                 }
11116               else
11117 #endif
11118                 {
11119                   /* Converting unknown class (i.e. register variable)
11120                    * to generic pointer. This is not good, but
11121                    * we'll make a guess (and throw a warning).
11122                    */
11123                   p_type = FPOINTER;
11124                   werror (W_INT_TO_GEN_PTR_CAST);
11125                 }
11126             }
11127
11128           /* the first two bytes are known */
11129           size = GPTRSIZE - 1;
11130           offset = 0;
11131           _startLazyDPSEvaluation ();
11132           while (size--)
11133             {
11134               aopPut (AOP (result),
11135                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11136                       offset);
11137               offset++;
11138             }
11139           _endLazyDPSEvaluation ();
11140
11141           /* the last byte depending on type */
11142             {
11143                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11144                 char gpValStr[10];
11145             
11146                 if (gpVal == -1)
11147                 {
11148                     // pointerTypeToGPByte will have bitched.
11149                     exit(1);
11150                 }
11151             
11152                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11153                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11154             }
11155           goto release;
11156         }
11157
11158       /* just copy the pointers */
11159       size = AOP_SIZE (result);
11160       offset = 0;
11161       _startLazyDPSEvaluation ();
11162       while (size--)
11163         {
11164           aopPut (AOP (result),
11165                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11166                   offset);
11167           offset++;
11168         }
11169       _endLazyDPSEvaluation ();
11170       goto release;
11171     }
11172
11173   /* so we now know that the size of destination is greater
11174      than the size of the source */
11175   /* we move to result for the size of source */
11176   size = AOP_SIZE (right);
11177   offset = 0;
11178   _startLazyDPSEvaluation ();
11179   while (size--)
11180     {
11181       aopPut (AOP (result),
11182               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11183               offset);
11184       offset++;
11185     }
11186   _endLazyDPSEvaluation ();
11187
11188   /* now depending on the sign of the source && destination */
11189   size = AOP_SIZE (result) - AOP_SIZE (right);
11190   /* if unsigned or not an integral type */
11191   /* also, if the source is a bit, we don't need to sign extend, because
11192    * it can't possibly have set the sign bit.
11193    */
11194   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11195     {
11196       while (size--)
11197         {
11198           aopPut (AOP (result), zero, offset++);
11199         }
11200     }
11201   else
11202     {
11203       /* we need to extend the sign :{ */
11204       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11205                         FALSE, FALSE, NULL));
11206       emitcode ("rlc", "a");
11207       emitcode ("subb", "a,acc");
11208       while (size--)
11209         aopPut (AOP (result), "a", offset++);
11210     }
11211
11212   /* we are done hurray !!!! */
11213
11214 release:
11215   freeAsmop (right, NULL, ic, TRUE);
11216   freeAsmop (result, NULL, ic, TRUE);
11217
11218 }
11219
11220 /*-----------------------------------------------------------------*/
11221 /* genDjnz - generate decrement & jump if not zero instrucion      */
11222 /*-----------------------------------------------------------------*/
11223 static int
11224 genDjnz (iCode * ic, iCode * ifx)
11225 {
11226   symbol *lbl, *lbl1;
11227   if (!ifx)
11228     return 0;
11229
11230   /* if the if condition has a false label
11231      then we cannot save */
11232   if (IC_FALSE (ifx))
11233     return 0;
11234
11235   /* if the minus is not of the form
11236      a = a - 1 */
11237   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11238       !IS_OP_LITERAL (IC_RIGHT (ic)))
11239     return 0;
11240
11241   if (operandLitValue (IC_RIGHT (ic)) != 1)
11242     return 0;
11243
11244   /* if the size of this greater than one then no
11245      saving */
11246   if (getSize (operandType (IC_RESULT (ic))) > 1)
11247     return 0;
11248
11249   /* otherwise we can save BIG */
11250   D(emitcode(";", "genDjnz"););
11251
11252   lbl = newiTempLabel (NULL);
11253   lbl1 = newiTempLabel (NULL);
11254
11255   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11256
11257   if (AOP_NEEDSACC(IC_RESULT(ic)))
11258   {
11259       /* If the result is accessed indirectly via
11260        * the accumulator, we must explicitly write
11261        * it back after the decrement.
11262        */
11263       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11264       
11265       if (strcmp(rByte, "a"))
11266       {
11267            /* Something is hopelessly wrong */
11268            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11269                    __FILE__, __LINE__);
11270            /* We can just give up; the generated code will be inefficient,
11271             * but what the hey.
11272             */
11273            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11274            return 0;
11275       }
11276       emitcode ("dec", "%s", rByte);
11277       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11278       emitcode ("jnz", "!tlabel", lbl->key + 100);
11279   }
11280   else if (IS_AOP_PREG (IC_RESULT (ic)))
11281     {
11282       emitcode ("dec", "%s",
11283                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11284       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11285       emitcode ("jnz", "!tlabel", lbl->key + 100);
11286     }
11287   else
11288     {
11289       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11290                 lbl->key + 100);
11291     }
11292   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11293   emitcode ("", "!tlabeldef", lbl->key + 100);
11294   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11295   emitcode ("", "!tlabeldef", lbl1->key + 100);
11296
11297   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11298   ifx->generated = 1;
11299   return 1;
11300 }
11301
11302 /*-----------------------------------------------------------------*/
11303 /* genReceive - generate code for a receive iCode                  */
11304 /*-----------------------------------------------------------------*/
11305 static void
11306 genReceive (iCode * ic)
11307 {
11308     int size = getSize (operandType (IC_RESULT (ic)));
11309     int offset = 0;
11310     int rb1off ;
11311     
11312     D (emitcode (";", "genReceive "););
11313
11314     if (ic->argreg == 1) 
11315     {
11316         /* first parameter */
11317         if (AOP_IS_STR(IC_RESULT(ic)))
11318         {
11319             /* Nothing to do: it's already in the proper place. */
11320             return;
11321         }
11322         else
11323         {
11324             bool useDp2;
11325             
11326             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11327                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11328                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11329             
11330             _G.accInUse++;
11331             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11332             _G.accInUse--; 
11333             
11334             /* Sanity checking... */
11335             if (AOP_USESDPTR(IC_RESULT(ic)))
11336             {
11337                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11338                         "genReceive got unexpected DPTR.");
11339             }
11340             assignResultValue (IC_RESULT (ic));
11341         }
11342     } 
11343     else 
11344     { 
11345         /* second receive onwards */
11346         /* this gets a little tricky since unused recevies will be
11347          eliminated, we have saved the reg in the type field . and
11348          we use that to figure out which register to use */
11349         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11350         rb1off = ic->argreg;
11351         while (size--) 
11352         {
11353             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11354         }
11355     }
11356     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11357 }
11358
11359 /*-----------------------------------------------------------------*/
11360 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11361 /*-----------------------------------------------------------------*/
11362 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11363 {
11364     operand *from , *to , *count;
11365     symbol *lbl;
11366     bitVect *rsave;
11367     int i;
11368
11369     /* we know it has to be 3 parameters */
11370     assert (nparms == 3);
11371     
11372     rsave = newBitVect(16);
11373     /* save DPTR if it needs to be saved */
11374     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11375             if (bitVectBitValue(ic->rMask,i))
11376                     rsave = bitVectSetBit(rsave,i);
11377     }
11378     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11379                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11380     savermask(rsave);
11381     
11382     to = parms[0];
11383     from = parms[1];
11384     count = parms[2];
11385
11386     aopOp (from, ic->next, FALSE, FALSE);
11387
11388     /* get from into DPTR1 */
11389     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11390     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11391     if (options.model == MODEL_FLAT24) {
11392         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11393     }
11394
11395     freeAsmop (from, NULL, ic, FALSE);
11396     aopOp (to, ic, FALSE, FALSE);
11397     /* get "to" into DPTR */
11398     /* if the operand is already in dptr
11399        then we do nothing else we move the value to dptr */
11400     if (AOP_TYPE (to) != AOP_STR) {
11401         /* if already in DPTR then we need to push */
11402         if (AOP_TYPE(to) == AOP_DPTR) {
11403             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11404             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11405             if (options.model == MODEL_FLAT24)
11406                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11407             emitcode ("pop", "dph");
11408             emitcode ("pop", "dpl");        
11409         } else {
11410             _startLazyDPSEvaluation ();
11411             /* if this is remateriazable */
11412             if (AOP_TYPE (to) == AOP_IMMD) {
11413                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11414             } else {                    /* we need to get it byte by byte */
11415                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11416                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11417                 if (options.model == MODEL_FLAT24) {
11418                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11419                 }
11420             }
11421             _endLazyDPSEvaluation ();
11422         }
11423     }
11424     freeAsmop (to, NULL, ic, FALSE);
11425     _G.dptrInUse = _G.dptr1InUse = 1;
11426     aopOp (count, ic->next->next, FALSE,FALSE);
11427     lbl =newiTempLabel(NULL);
11428
11429     /* now for the actual copy */
11430     if (AOP_TYPE(count) == AOP_LIT && 
11431         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11432         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11433         if (fromc) {
11434             emitcode ("lcall","__bi_memcpyc2x_s");
11435         } else {
11436             emitcode ("lcall","__bi_memcpyx2x_s");
11437         }
11438         freeAsmop (count, NULL, ic, FALSE);
11439     } else {
11440         symbol *lbl1 = newiTempLabel(NULL);
11441         
11442         emitcode (";"," Auto increment but no djnz");
11443         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11444         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11445         freeAsmop (count, NULL, ic, FALSE);
11446         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11447         emitcode ("","!tlabeldef",lbl->key+100);
11448         if (fromc) {
11449             emitcode ("clr","a");
11450             emitcode ("movc", "a,@a+dptr");
11451         } else 
11452             emitcode ("movx", "a,@dptr");
11453         emitcode ("movx", "@dptr,a");
11454         emitcode ("inc", "dptr");
11455         emitcode ("inc", "dptr");
11456         emitcode ("mov","a,b");
11457         emitcode ("orl","a,_ap");
11458         emitcode ("jz","!tlabel",lbl1->key+100);
11459         emitcode ("mov","a,_ap");
11460         emitcode ("add","a,#!constbyte",0xFF);
11461         emitcode ("mov","_ap,a");
11462         emitcode ("mov","a,b");
11463         emitcode ("addc","a,#!constbyte",0xFF);
11464         emitcode ("mov","b,a");
11465         emitcode ("sjmp","!tlabel",lbl->key+100);
11466         emitcode ("","!tlabeldef",lbl1->key+100);
11467     }
11468     emitcode ("mov", "dps,#0"); 
11469     _G.dptrInUse = _G.dptr1InUse = 0;
11470     unsavermask(rsave);
11471
11472 }
11473
11474 /*-----------------------------------------------------------------*/
11475 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11476 /*-----------------------------------------------------------------*/
11477 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11478 {
11479     operand *from , *to , *count;
11480     symbol *lbl,*lbl2;
11481     bitVect *rsave;
11482     int i;
11483
11484     /* we know it has to be 3 parameters */
11485     assert (nparms == 3);
11486     
11487     rsave = newBitVect(16);
11488     /* save DPTR if it needs to be saved */
11489     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11490             if (bitVectBitValue(ic->rMask,i))
11491                     rsave = bitVectSetBit(rsave,i);
11492     }
11493     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11494                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11495     savermask(rsave);
11496     
11497     to = parms[0];
11498     from = parms[1];
11499     count = parms[2];
11500
11501     aopOp (from, ic->next, FALSE, FALSE);
11502
11503     /* get from into DPTR1 */
11504     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11505     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11506     if (options.model == MODEL_FLAT24) {
11507         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11508     }
11509
11510     freeAsmop (from, NULL, ic, FALSE);
11511     aopOp (to, ic, FALSE, FALSE);
11512     /* get "to" into DPTR */
11513     /* if the operand is already in dptr
11514        then we do nothing else we move the value to dptr */
11515     if (AOP_TYPE (to) != AOP_STR) {
11516         /* if already in DPTR then we need to push */
11517         if (AOP_TYPE(to) == AOP_DPTR) {
11518             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11519             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11520             if (options.model == MODEL_FLAT24)
11521                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11522             emitcode ("pop", "dph");
11523             emitcode ("pop", "dpl");        
11524         } else {
11525             _startLazyDPSEvaluation ();
11526             /* if this is remateriazable */
11527             if (AOP_TYPE (to) == AOP_IMMD) {
11528                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11529             } else {                    /* we need to get it byte by byte */
11530                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11531                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11532                 if (options.model == MODEL_FLAT24) {
11533                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11534                 }
11535             }
11536             _endLazyDPSEvaluation ();
11537         }
11538     }
11539     freeAsmop (to, NULL, ic, FALSE);
11540     _G.dptrInUse = _G.dptr1InUse = 1;
11541     aopOp (count, ic->next->next, FALSE,FALSE);
11542     lbl =newiTempLabel(NULL);
11543     lbl2 =newiTempLabel(NULL);
11544
11545     /* now for the actual compare */
11546     if (AOP_TYPE(count) == AOP_LIT && 
11547         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11548         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11549         if (fromc)
11550             emitcode("lcall","__bi_memcmpc2x_s");
11551         else
11552             emitcode("lcall","__bi_memcmpx2x_s");
11553         freeAsmop (count, NULL, ic, FALSE);
11554         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11555         aopPut(AOP(IC_RESULT(ic)),"a",0);
11556         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11557     } else {
11558         symbol *lbl1 = newiTempLabel(NULL);
11559
11560         emitcode("push","ar0");         
11561         emitcode (";"," Auto increment but no djnz");
11562         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11563         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11564         freeAsmop (count, NULL, ic, FALSE);
11565         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11566         emitcode ("","!tlabeldef",lbl->key+100);
11567         if (fromc) {
11568             emitcode ("clr","a");
11569             emitcode ("movc", "a,@a+dptr");
11570         } else 
11571             emitcode ("movx", "a,@dptr");
11572         emitcode ("mov","r0,a");
11573         emitcode ("movx", "a,@dptr");
11574         emitcode ("clr","c");
11575         emitcode ("subb","a,r0");
11576         emitcode ("jnz","!tlabel",lbl2->key+100);
11577         emitcode ("inc", "dptr");
11578         emitcode ("inc", "dptr");
11579         emitcode ("mov","a,b");
11580         emitcode ("orl","a,_ap");
11581         emitcode ("jz","!tlabel",lbl1->key+100);
11582         emitcode ("mov","a,_ap");
11583         emitcode ("add","a,#!constbyte",0xFF);
11584         emitcode ("mov","_ap,a");
11585         emitcode ("mov","a,b");
11586         emitcode ("addc","a,#!constbyte",0xFF);
11587         emitcode ("mov","b,a");
11588         emitcode ("sjmp","!tlabel",lbl->key+100);
11589         emitcode ("","!tlabeldef",lbl1->key+100);
11590         emitcode ("clr","a");
11591         emitcode ("","!tlabeldef",lbl2->key+100);
11592         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11593         aopPut(AOP(IC_RESULT(ic)),"a",0);
11594         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11595         emitcode("pop","ar0");
11596         emitcode ("mov", "dps,#0");      
11597     }
11598     _G.dptrInUse = _G.dptr1InUse = 0;
11599     unsavermask(rsave);
11600
11601 }
11602
11603 /*-----------------------------------------------------------------*/
11604 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11605 /* port, first parameter output area second parameter pointer to   */
11606 /* port third parameter count                                      */
11607 /*-----------------------------------------------------------------*/
11608 static void genInp( iCode *ic, int nparms, operand **parms)
11609 {
11610     operand *from , *to , *count;
11611     symbol *lbl;
11612     bitVect *rsave;
11613     int i;
11614
11615     /* we know it has to be 3 parameters */
11616     assert (nparms == 3);
11617     
11618     rsave = newBitVect(16);
11619     /* save DPTR if it needs to be saved */
11620     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11621             if (bitVectBitValue(ic->rMask,i))
11622                     rsave = bitVectSetBit(rsave,i);
11623     }
11624     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11625                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11626     savermask(rsave);
11627     
11628     to = parms[0];
11629     from = parms[1];
11630     count = parms[2];
11631
11632     aopOp (from, ic->next, FALSE, FALSE);
11633
11634     /* get from into DPTR1 */
11635     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11636     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11637     if (options.model == MODEL_FLAT24) {
11638         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11639     }
11640
11641     freeAsmop (from, NULL, ic, FALSE);
11642     aopOp (to, ic, FALSE, FALSE);
11643     /* get "to" into DPTR */
11644     /* if the operand is already in dptr
11645        then we do nothing else we move the value to dptr */
11646     if (AOP_TYPE (to) != AOP_STR) {
11647         /* if already in DPTR then we need to push */
11648         if (AOP_TYPE(to) == AOP_DPTR) {
11649             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11650             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11651             if (options.model == MODEL_FLAT24)
11652                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11653             emitcode ("pop", "dph");
11654             emitcode ("pop", "dpl");        
11655         } else {
11656             _startLazyDPSEvaluation ();
11657             /* if this is remateriazable */
11658             if (AOP_TYPE (to) == AOP_IMMD) {
11659                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11660             } else {                    /* we need to get it byte by byte */
11661                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11662                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11663                 if (options.model == MODEL_FLAT24) {
11664                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11665                 }
11666             }
11667             _endLazyDPSEvaluation ();
11668         }
11669     }
11670     freeAsmop (to, NULL, ic, FALSE);
11671
11672     _G.dptrInUse = _G.dptr1InUse = 1;
11673     aopOp (count, ic->next->next, FALSE,FALSE);
11674     lbl =newiTempLabel(NULL);
11675
11676     /* now for the actual copy */
11677     if (AOP_TYPE(count) == AOP_LIT && 
11678         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11679         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11680         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11681         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11682         freeAsmop (count, NULL, ic, FALSE);
11683         emitcode ("","!tlabeldef",lbl->key+100);
11684         emitcode ("movx", "a,@dptr");   /* read data from port */
11685         emitcode ("dec","dps");         /* switch to DPTR */
11686         emitcode ("movx", "@dptr,a");   /* save into location */
11687         emitcode ("inc", "dptr");       /* point to next area */
11688         emitcode ("inc","dps");         /* switch to DPTR2 */
11689         emitcode ("djnz","b,!tlabel",lbl->key+100);
11690     } else {
11691         symbol *lbl1 = newiTempLabel(NULL);
11692         
11693         emitcode (";"," Auto increment but no djnz");
11694         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11695         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11696         freeAsmop (count, NULL, ic, FALSE);
11697         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11698         emitcode ("","!tlabeldef",lbl->key+100);
11699         emitcode ("movx", "a,@dptr");
11700         emitcode ("dec","dps");         /* switch to DPTR */
11701         emitcode ("movx", "@dptr,a");
11702         emitcode ("inc", "dptr");
11703         emitcode ("inc","dps");         /* switch to DPTR2 */
11704 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11705 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11706         emitcode ("mov","a,b");
11707         emitcode ("orl","a,_ap");
11708         emitcode ("jz","!tlabel",lbl1->key+100);
11709         emitcode ("mov","a,_ap");
11710         emitcode ("add","a,#!constbyte",0xFF);
11711         emitcode ("mov","_ap,a");
11712         emitcode ("mov","a,b");
11713         emitcode ("addc","a,#!constbyte",0xFF);
11714         emitcode ("mov","b,a");
11715         emitcode ("sjmp","!tlabel",lbl->key+100);
11716         emitcode ("","!tlabeldef",lbl1->key+100);
11717     }
11718     emitcode ("mov", "dps,#0"); 
11719     _G.dptrInUse = _G.dptr1InUse = 0;
11720     unsavermask(rsave);
11721
11722 }
11723
11724 /*-----------------------------------------------------------------*/
11725 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11726 /* port, first parameter output area second parameter pointer to   */
11727 /* port third parameter count                                      */
11728 /*-----------------------------------------------------------------*/
11729 static void genOutp( iCode *ic, int nparms, operand **parms)
11730 {
11731     operand *from , *to , *count;
11732     symbol *lbl;
11733     bitVect *rsave;
11734     int i;
11735
11736     /* we know it has to be 3 parameters */
11737     assert (nparms == 3);
11738     
11739     rsave = newBitVect(16);
11740     /* save DPTR if it needs to be saved */
11741     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11742             if (bitVectBitValue(ic->rMask,i))
11743                     rsave = bitVectSetBit(rsave,i);
11744     }
11745     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11746                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11747     savermask(rsave);
11748     
11749     to = parms[0];
11750     from = parms[1];
11751     count = parms[2];
11752
11753     aopOp (from, ic->next, FALSE, FALSE);
11754
11755     /* get from into DPTR1 */
11756     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11757     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11758     if (options.model == MODEL_FLAT24) {
11759         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11760     }
11761
11762     freeAsmop (from, NULL, ic, FALSE);
11763     aopOp (to, ic, FALSE, FALSE);
11764     /* get "to" into DPTR */
11765     /* if the operand is already in dptr
11766        then we do nothing else we move the value to dptr */
11767     if (AOP_TYPE (to) != AOP_STR) {
11768         /* if already in DPTR then we need to push */
11769         if (AOP_TYPE(to) == AOP_DPTR) {
11770             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11771             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11772             if (options.model == MODEL_FLAT24)
11773                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11774             emitcode ("pop", "dph");
11775             emitcode ("pop", "dpl");        
11776         } else {
11777             _startLazyDPSEvaluation ();
11778             /* if this is remateriazable */
11779             if (AOP_TYPE (to) == AOP_IMMD) {
11780                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11781             } else {                    /* we need to get it byte by byte */
11782                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11783                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11784                 if (options.model == MODEL_FLAT24) {
11785                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11786                 }
11787             }
11788             _endLazyDPSEvaluation ();
11789         }
11790     }
11791     freeAsmop (to, NULL, ic, FALSE);
11792
11793     _G.dptrInUse = _G.dptr1InUse = 1;
11794     aopOp (count, ic->next->next, FALSE,FALSE);
11795     lbl =newiTempLabel(NULL);
11796
11797     /* now for the actual copy */
11798     if (AOP_TYPE(count) == AOP_LIT && 
11799         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11800         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11801         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11802         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11803         emitcode ("","!tlabeldef",lbl->key+100);
11804         emitcode ("movx", "a,@dptr");   /* read data from port */
11805         emitcode ("inc","dps");         /* switch to DPTR2 */
11806         emitcode ("movx", "@dptr,a");   /* save into location */
11807         emitcode ("inc", "dptr");       /* point to next area */
11808         emitcode ("dec","dps");         /* switch to DPTR */
11809         emitcode ("djnz","b,!tlabel",lbl->key+100);
11810         freeAsmop (count, NULL, ic, FALSE);
11811     } else {
11812         symbol *lbl1 = newiTempLabel(NULL);
11813         
11814         emitcode (";"," Auto increment but no djnz");
11815         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11816         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11817         freeAsmop (count, NULL, ic, FALSE);
11818         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11819         emitcode ("","!tlabeldef",lbl->key+100);
11820         emitcode ("movx", "a,@dptr");
11821         emitcode ("inc", "dptr");
11822         emitcode ("inc","dps");         /* switch to DPTR2 */
11823         emitcode ("movx", "@dptr,a");
11824         emitcode ("dec","dps");         /* switch to DPTR */
11825         emitcode ("mov","a,b");
11826         emitcode ("orl","a,_ap");
11827         emitcode ("jz","!tlabel",lbl1->key+100);
11828         emitcode ("mov","a,_ap");
11829         emitcode ("add","a,#!constbyte",0xFF);
11830         emitcode ("mov","_ap,a");
11831         emitcode ("mov","a,b");
11832         emitcode ("addc","a,#!constbyte",0xFF);
11833         emitcode ("mov","b,a");
11834         emitcode ("sjmp","!tlabel",lbl->key+100);
11835         emitcode ("","!tlabeldef",lbl1->key+100);
11836     }
11837     emitcode ("mov", "dps,#0"); 
11838     _G.dptrInUse = _G.dptr1InUse = 0;
11839     unsavermask(rsave);
11840
11841 }
11842
11843 /*-----------------------------------------------------------------*/
11844 /* genSwapW - swap lower & high order bytes                        */
11845 /*-----------------------------------------------------------------*/
11846 static void genSwapW(iCode *ic, int nparms, operand **parms)
11847 {
11848     operand *dest;
11849     operand *src;
11850     assert (nparms==1);
11851
11852     src = parms[0];
11853     dest=IC_RESULT(ic);
11854
11855     assert(getSize(operandType(src))==2);
11856
11857     aopOp (src, ic, FALSE, FALSE);
11858     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11859     _G.accInUse++;
11860     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11861     _G.accInUse--;
11862     freeAsmop (src, NULL, ic, FALSE);
11863     
11864     aopOp (dest,ic, FALSE, FALSE);
11865     aopPut(AOP(dest),"b",0);
11866     aopPut(AOP(dest),"a",1);
11867     freeAsmop (dest, NULL, ic, FALSE);    
11868 }
11869
11870 /*-----------------------------------------------------------------*/
11871 /* genMemsetX - gencode for memSetX data                           */
11872 /*-----------------------------------------------------------------*/
11873 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11874 {
11875     operand *to , *val , *count;
11876     symbol *lbl;
11877     char *l;
11878     int i;
11879     bitVect *rsave;
11880
11881     /* we know it has to be 3 parameters */
11882     assert (nparms == 3);
11883     
11884     to = parms[0];
11885     val = parms[1];
11886     count = parms[2];
11887         
11888     /* save DPTR if it needs to be saved */
11889     rsave = newBitVect(16);
11890     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11891             if (bitVectBitValue(ic->rMask,i))
11892                     rsave = bitVectSetBit(rsave,i);
11893     }
11894     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11895                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11896     savermask(rsave);
11897
11898     aopOp (to, ic, FALSE, FALSE);
11899     /* get "to" into DPTR */
11900     /* if the operand is already in dptr
11901        then we do nothing else we move the value to dptr */
11902     if (AOP_TYPE (to) != AOP_STR) {
11903         /* if already in DPTR then we need to push */
11904         if (AOP_TYPE(to) == AOP_DPTR) {
11905             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11906             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11907             if (options.model == MODEL_FLAT24)
11908                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11909             emitcode ("pop", "dph");
11910             emitcode ("pop", "dpl");        
11911         } else {
11912             _startLazyDPSEvaluation ();
11913             /* if this is remateriazable */
11914             if (AOP_TYPE (to) == AOP_IMMD) {
11915                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11916             } else {                    /* we need to get it byte by byte */
11917                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11918                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11919                 if (options.model == MODEL_FLAT24) {
11920                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11921                 }
11922             }
11923             _endLazyDPSEvaluation ();
11924         }
11925     }
11926     freeAsmop (to, NULL, ic, FALSE);
11927
11928     aopOp (val, ic->next->next, FALSE,FALSE);
11929     aopOp (count, ic->next->next, FALSE,FALSE);    
11930     lbl =newiTempLabel(NULL);
11931     /* now for the actual copy */
11932     if (AOP_TYPE(count) == AOP_LIT && 
11933         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11934         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11935         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11936         MOVA(l);
11937         emitcode ("","!tlabeldef",lbl->key+100);
11938         emitcode ("movx", "@dptr,a");
11939         emitcode ("inc", "dptr");
11940         emitcode ("djnz","b,!tlabel",lbl->key+100);
11941     } else {
11942         symbol *lbl1 = newiTempLabel(NULL);
11943         
11944         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11945         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11946         emitcode ("","!tlabeldef",lbl->key+100);
11947         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11948         emitcode ("movx", "@dptr,a");
11949         emitcode ("inc", "dptr");
11950         emitcode ("mov","a,b");
11951         emitcode ("orl","a,_ap");
11952         emitcode ("jz","!tlabel",lbl1->key+100);
11953         emitcode ("mov","a,_ap");
11954         emitcode ("add","a,#!constbyte",0xFF);
11955         emitcode ("mov","_ap,a");
11956         emitcode ("mov","a,b");
11957         emitcode ("addc","a,#!constbyte",0xFF);
11958         emitcode ("mov","b,a");
11959         emitcode ("sjmp","!tlabel",lbl->key+100);
11960         emitcode ("","!tlabeldef",lbl1->key+100);
11961     }
11962     freeAsmop (count, NULL, ic, FALSE);
11963     unsavermask(rsave);
11964 }
11965
11966 /*-----------------------------------------------------------------*/
11967 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11968 /*-----------------------------------------------------------------*/
11969 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11970 {
11971         bitVect *rsave ;
11972         operand *pnum, *result;
11973         int i;
11974     
11975         assert (nparms==1);
11976         /* save registers that need to be saved */
11977         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11978                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11979     
11980         pnum = parms[0]; 
11981         aopOp (pnum, ic, FALSE, FALSE);
11982         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11983         freeAsmop (pnum, NULL, ic, FALSE);
11984         emitcode ("lcall","NatLib_LoadPrimitive");
11985         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11986         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11987             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11988                 for (i = (size-1) ; i >= 0 ; i-- ) {
11989                         emitcode ("push","a%s",javaRet[i]);
11990                 }
11991                 for (i=0; i < size ; i++ ) {
11992                         emitcode ("pop","a%s",
11993                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11994                 }
11995         } else {
11996                 for (i = 0 ; i < size ; i++ ) {
11997                         aopPut(AOP(result),javaRet[i],i);
11998                 }
11999         }    
12000         freeAsmop (result, NULL, ic, FALSE);
12001         unsavermask(rsave);
12002 }
12003
12004 /*-----------------------------------------------------------------*/
12005 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12006 /*-----------------------------------------------------------------*/
12007 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12008 {
12009         bitVect *rsave ;
12010         operand *pnum, *result;
12011         int size = 3;
12012         int i;
12013     
12014         assert (nparms==1);
12015         /* save registers that need to be saved */
12016         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12017                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12018     
12019         pnum = parms[0]; 
12020         aopOp (pnum, ic, FALSE, FALSE);
12021         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12022         freeAsmop (pnum, NULL, ic, FALSE);
12023         emitcode ("lcall","NatLib_LoadPointer");
12024         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12025         if (AOP_TYPE(result)!=AOP_STR) {
12026                 for (i = 0 ; i < size ; i++ ) {
12027                         aopPut(AOP(result),fReturn[i],i);
12028                 }
12029         }    
12030         freeAsmop (result, NULL, ic, FALSE);
12031         unsavermask(rsave);
12032 }
12033
12034 /*-----------------------------------------------------------------*/
12035 /* genNatLibInstallStateBlock -                                    */
12036 /*-----------------------------------------------------------------*/
12037 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12038                                        operand **parms, const char *name)
12039 {
12040         bitVect *rsave ;
12041         operand *psb, *handle;
12042         assert (nparms==2);
12043
12044         /* save registers that need to be saved */
12045         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12046                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12047         psb = parms[0];
12048         handle = parms[1];
12049
12050         /* put pointer to state block into DPTR1 */
12051         aopOp (psb, ic, FALSE, FALSE);
12052         if (AOP_TYPE (psb) == AOP_IMMD) {
12053                 emitcode ("mov","dps,#1");
12054                 emitcode ("mov", "dptr,%s",
12055                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12056                 emitcode ("mov","dps,#0");
12057         } else {
12058                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12059                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12060                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12061         }
12062         freeAsmop (psb, NULL, ic, FALSE);
12063
12064         /* put libraryID into DPTR */
12065         emitcode ("mov","dptr,#LibraryID");
12066
12067         /* put handle into r3:r2 */
12068         aopOp (handle, ic, FALSE, FALSE);
12069         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12070                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12071                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12072                 emitcode ("pop","ar3");
12073                 emitcode ("pop","ar2");
12074         } else {        
12075                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12076                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12077         }
12078         freeAsmop (psb, NULL, ic, FALSE);
12079
12080         /* make the call */
12081         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12082
12083         /* put return value into place*/
12084         _G.accInUse++;
12085         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12086         _G.accInUse--;
12087         aopPut(AOP(IC_RESULT(ic)),"a",0);
12088         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12089         unsavermask(rsave);
12090 }
12091
12092 /*-----------------------------------------------------------------*/
12093 /* genNatLibRemoveStateBlock -                                     */
12094 /*-----------------------------------------------------------------*/
12095 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12096 {
12097         bitVect *rsave ;
12098
12099         assert(nparms==0);
12100
12101         /* save registers that need to be saved */
12102         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12103                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12104
12105         /* put libraryID into DPTR */
12106         emitcode ("mov","dptr,#LibraryID");
12107         /* make the call */
12108         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12109         unsavermask(rsave);
12110 }
12111
12112 /*-----------------------------------------------------------------*/
12113 /* genNatLibGetStateBlock -                                        */
12114 /*-----------------------------------------------------------------*/
12115 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12116                                    operand **parms,const char *name)
12117 {
12118         bitVect *rsave ;
12119         symbol *lbl = newiTempLabel(NULL);
12120         
12121         assert(nparms==0);
12122         /* save registers that need to be saved */
12123         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12124                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12125
12126         /* put libraryID into DPTR */
12127         emitcode ("mov","dptr,#LibraryID");
12128         /* make the call */
12129         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12130         emitcode ("jnz","!tlabel",lbl->key+100);
12131
12132         /* put return value into place */
12133         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12134         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12135                 emitcode ("push","ar3");
12136                 emitcode ("push","ar2");
12137                 emitcode ("pop","%s",
12138                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12139                 emitcode ("pop","%s",
12140                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12141         } else {
12142                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12143                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12144         }
12145         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12146         emitcode ("","!tlabeldef",lbl->key+100);
12147         unsavermask(rsave);
12148 }
12149
12150 /*-----------------------------------------------------------------*/
12151 /* genMMMalloc -                                                   */
12152 /*-----------------------------------------------------------------*/
12153 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12154                          int size, const char *name)
12155 {
12156         bitVect *rsave ;
12157         operand *bsize;
12158         symbol *rsym;
12159         symbol *lbl = newiTempLabel(NULL);
12160
12161         assert (nparms == 1);
12162         /* save registers that need to be saved */
12163         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12164                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12165         
12166         bsize=parms[0];
12167         aopOp (bsize,ic,FALSE,FALSE);
12168
12169         /* put the size in R4-R2 */
12170         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12171                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12172                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12173                 if (size==3) {
12174                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12175                         emitcode("pop","ar4");
12176                 }
12177                 emitcode("pop","ar3");
12178                 emitcode("pop","ar2");          
12179         } else {
12180                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12181                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12182                 if (size==3) {
12183                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12184                 }
12185         }
12186         freeAsmop (bsize, NULL, ic, FALSE);
12187
12188         /* make the call */
12189         emitcode ("lcall","MM_%s",name);
12190         emitcode ("jz","!tlabel",lbl->key+100);
12191         emitcode ("mov","r2,#!constbyte",0xff);
12192         emitcode ("mov","r3,#!constbyte",0xff);
12193         emitcode ("","!tlabeldef",lbl->key+100);
12194         /* we don't care about the pointer : we just save the handle */
12195         rsym = OP_SYMBOL(IC_RESULT(ic));
12196         if (rsym->liveFrom != rsym->liveTo) {
12197                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12198                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12199                         emitcode ("push","ar3");
12200                         emitcode ("push","ar2");
12201                         emitcode ("pop","%s",
12202                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12203                         emitcode ("pop","%s",
12204                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12205                 } else {
12206                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12207                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12208                 }
12209                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12210         }
12211         unsavermask(rsave);
12212 }
12213
12214 /*-----------------------------------------------------------------*/
12215 /* genMMDeref -                                                    */
12216 /*-----------------------------------------------------------------*/
12217 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12218 {
12219         bitVect *rsave ;
12220         operand *handle;
12221
12222         assert (nparms == 1);
12223         /* save registers that need to be saved */
12224         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12225                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12226         
12227         handle=parms[0];
12228         aopOp (handle,ic,FALSE,FALSE);
12229
12230         /* put the size in R4-R2 */
12231         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12232                 emitcode("push","%s",
12233                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12234                 emitcode("push","%s",
12235                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12236                 emitcode("pop","ar3");
12237                 emitcode("pop","ar2");          
12238         } else {
12239                 emitcode ("mov","r2,%s",
12240                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12241                 emitcode ("mov","r3,%s",
12242                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12243         }
12244         freeAsmop (handle, NULL, ic, FALSE);
12245
12246         /* make the call */
12247         emitcode ("lcall","MM_Deref");
12248         
12249         {
12250                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12251                 if (rsym->liveFrom != rsym->liveTo) {                   
12252                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12253                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12254                             _startLazyDPSEvaluation ();
12255                             
12256                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12257                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12258                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12259
12260                             _endLazyDPSEvaluation ();
12261                             
12262                         }
12263                 }
12264         }
12265         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12266         unsavermask(rsave);
12267 }
12268
12269 /*-----------------------------------------------------------------*/
12270 /* genMMUnrestrictedPersist -                                      */
12271 /*-----------------------------------------------------------------*/
12272 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12273 {
12274         bitVect *rsave ;
12275         operand *handle;
12276
12277         assert (nparms == 1);
12278         /* save registers that need to be saved */
12279         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12280                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12281         
12282         handle=parms[0];
12283         aopOp (handle,ic,FALSE,FALSE);
12284
12285         /* put the size in R3-R2 */
12286         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12287                 emitcode("push","%s",
12288                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12289                 emitcode("push","%s",
12290                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12291                 emitcode("pop","ar3");
12292                 emitcode("pop","ar2");          
12293         } else {
12294                 emitcode ("mov","r2,%s",
12295                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12296                 emitcode ("mov","r3,%s",
12297                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12298         }
12299         freeAsmop (handle, NULL, ic, FALSE);
12300
12301         /* make the call */
12302         emitcode ("lcall","MM_UnrestrictedPersist");
12303
12304         {
12305                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12306                 if (rsym->liveFrom != rsym->liveTo) {   
12307                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12308                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12309                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12310                 }
12311         }
12312         unsavermask(rsave);
12313 }
12314
12315 /*-----------------------------------------------------------------*/
12316 /* genSystemExecJavaProcess -                                      */
12317 /*-----------------------------------------------------------------*/
12318 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12319 {
12320         bitVect *rsave ;
12321         operand *handle, *pp;
12322
12323         assert (nparms==2);
12324         /* save registers that need to be saved */
12325         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12326                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12327         
12328         pp = parms[0];
12329         handle = parms[1];
12330         
12331         /* put the handle in R3-R2 */
12332         aopOp (handle,ic,FALSE,FALSE);
12333         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12334                 emitcode("push","%s",
12335                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12336                 emitcode("push","%s",
12337                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12338                 emitcode("pop","ar3");
12339                 emitcode("pop","ar2");          
12340         } else {
12341                 emitcode ("mov","r2,%s",
12342                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12343                 emitcode ("mov","r3,%s",
12344                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12345         }
12346         freeAsmop (handle, NULL, ic, FALSE);
12347         
12348         /* put pointer in DPTR */
12349         aopOp (pp,ic,FALSE,FALSE);
12350         if (AOP_TYPE(pp) == AOP_IMMD) {
12351                 emitcode ("mov", "dptr,%s",
12352                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12353         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12354                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12355                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12356                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12357         }
12358         freeAsmop (handle, NULL, ic, FALSE);
12359
12360         /* make the call */
12361         emitcode ("lcall","System_ExecJavaProcess");
12362         
12363         /* put result in place */
12364         {
12365                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12366                 if (rsym->liveFrom != rsym->liveTo) {   
12367                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12368                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12369                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12370                 }
12371         }
12372         
12373         unsavermask(rsave);
12374 }
12375
12376 /*-----------------------------------------------------------------*/
12377 /* genSystemRTCRegisters -                                         */
12378 /*-----------------------------------------------------------------*/
12379 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12380                                   char *name)
12381 {
12382         bitVect *rsave ;
12383         operand *pp;
12384
12385         assert (nparms==1);
12386         /* save registers that need to be saved */
12387         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12388                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12389         
12390         pp=parms[0];
12391         /* put pointer in DPTR */
12392         aopOp (pp,ic,FALSE,FALSE);
12393         if (AOP_TYPE (pp) == AOP_IMMD) {
12394                 emitcode ("mov","dps,#1");
12395                 emitcode ("mov", "dptr,%s", 
12396                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12397                 emitcode ("mov","dps,#0");
12398         } else {
12399                 emitcode ("mov","dpl1,%s",
12400                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12401                 emitcode ("mov","dph1,%s",
12402                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12403                 emitcode ("mov","dpx1,%s",
12404                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12405         }
12406         freeAsmop (pp, NULL, ic, FALSE);
12407
12408         /* make the call */
12409         emitcode ("lcall","System_%sRTCRegisters",name);
12410
12411         unsavermask(rsave);
12412 }
12413
12414 /*-----------------------------------------------------------------*/
12415 /* genSystemThreadSleep -                                          */
12416 /*-----------------------------------------------------------------*/
12417 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12418 {
12419         bitVect *rsave ;
12420         operand *to, *s;
12421
12422         assert (nparms==1);
12423         /* save registers that need to be saved */
12424         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12425                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12426
12427         to = parms[0];
12428         aopOp(to,ic,FALSE,FALSE);
12429         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12430             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12431                 emitcode ("push","%s",
12432                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12433                 emitcode ("push","%s",
12434                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12435                 emitcode ("push","%s",
12436                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12437                 emitcode ("push","%s",
12438                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12439                 emitcode ("pop","ar3");
12440                 emitcode ("pop","ar2");
12441                 emitcode ("pop","ar1");
12442                 emitcode ("pop","ar0");
12443         } else {
12444                 emitcode ("mov","r0,%s",
12445                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12446                 emitcode ("mov","r1,%s",
12447                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12448                 emitcode ("mov","r2,%s",
12449                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12450                 emitcode ("mov","r3,%s",
12451                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12452         }
12453         freeAsmop (to, NULL, ic, FALSE);
12454
12455         /* suspend in acc */
12456         s = parms[1];
12457         aopOp(s,ic,FALSE,FALSE);
12458         emitcode ("mov","a,%s",
12459                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12460         freeAsmop (s, NULL, ic, FALSE);
12461
12462         /* make the call */
12463         emitcode ("lcall","System_%s",name);
12464
12465         unsavermask(rsave);
12466 }
12467
12468 /*-----------------------------------------------------------------*/
12469 /* genSystemThreadResume -                                         */
12470 /*-----------------------------------------------------------------*/
12471 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12472 {
12473         bitVect *rsave ;
12474         operand *tid,*pid;
12475
12476         assert (nparms==2);
12477         /* save registers that need to be saved */
12478         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12479                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12480         
12481         tid = parms[0];
12482         pid = parms[1];
12483         
12484         /* PID in R0 */
12485         aopOp(pid,ic,FALSE,FALSE);
12486         emitcode ("mov","r0,%s",
12487                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12488         freeAsmop (pid, NULL, ic, FALSE);
12489         
12490         /* tid into ACC */
12491         aopOp(tid,ic,FALSE,FALSE);
12492         emitcode ("mov","a,%s",
12493                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12494         freeAsmop (tid, NULL, ic, FALSE);
12495         
12496         emitcode ("lcall","System_ThreadResume");
12497
12498         /* put result into place */
12499         {
12500                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12501                 if (rsym->liveFrom != rsym->liveTo) {   
12502                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12503                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12504                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12505                 }
12506         }
12507         unsavermask(rsave);
12508 }
12509
12510 /*-----------------------------------------------------------------*/
12511 /* genSystemProcessResume -                                        */
12512 /*-----------------------------------------------------------------*/
12513 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12514 {
12515         bitVect *rsave ;
12516         operand *pid;
12517
12518         assert (nparms==1);
12519         /* save registers that need to be saved */
12520         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12521                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12522         
12523         pid = parms[0];
12524         
12525         /* pid into ACC */
12526         aopOp(pid,ic,FALSE,FALSE);
12527         emitcode ("mov","a,%s",
12528                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12529         freeAsmop (pid, NULL, ic, FALSE);
12530         
12531         emitcode ("lcall","System_ProcessResume");
12532
12533         unsavermask(rsave);
12534 }
12535
12536 /*-----------------------------------------------------------------*/
12537 /* genSystem -                                                     */
12538 /*-----------------------------------------------------------------*/
12539 static void genSystem (iCode *ic,int nparms,char *name)
12540 {
12541         assert(nparms == 0);
12542
12543         emitcode ("lcall","System_%s",name);
12544 }
12545
12546 /*-----------------------------------------------------------------*/
12547 /* genSystemPoll -                                                  */
12548 /*-----------------------------------------------------------------*/
12549 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12550 {
12551         bitVect *rsave ;
12552         operand *fp;
12553
12554         assert (nparms==1);
12555         /* save registers that need to be saved */
12556         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12557                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12558
12559         fp = parms[0];
12560         aopOp (fp,ic,FALSE,FALSE);
12561         if (AOP_TYPE (fp) == AOP_IMMD) {
12562                 emitcode ("mov", "dptr,%s", 
12563                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12564         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12565                 emitcode ("mov","dpl,%s",
12566                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12567                 emitcode ("mov","dph,%s",
12568                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12569                 emitcode ("mov","dpx,%s",
12570                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12571         }
12572         freeAsmop (fp, NULL, ic, FALSE);
12573
12574         emitcode ("lcall","System_%sPoll",name);
12575
12576         /* put result into place */
12577         {
12578                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12579                 if (rsym->liveFrom != rsym->liveTo) {   
12580                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12581                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12582                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12583                 }
12584         }
12585         unsavermask(rsave);
12586 }
12587
12588 /*-----------------------------------------------------------------*/
12589 /* genSystemGetCurrentID -                                         */
12590 /*-----------------------------------------------------------------*/
12591 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12592 {
12593         assert (nparms==0);
12594
12595         emitcode ("lcall","System_GetCurrent%sId",name);
12596         /* put result into place */
12597         {
12598                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12599                 if (rsym->liveFrom != rsym->liveTo) {   
12600                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12601                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12602                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12603                 }
12604         }
12605 }
12606
12607 /*-----------------------------------------------------------------*/
12608 /* genBuiltIn - calls the appropriate function to  generating code */
12609 /* for a built in function                                         */
12610 /*-----------------------------------------------------------------*/
12611 static void genBuiltIn (iCode *ic)
12612 {
12613         operand *bi_parms[MAX_BUILTIN_ARGS];
12614         int nbi_parms;
12615         iCode *bi_iCode;
12616         symbol *bif;
12617
12618         /* get all the arguments for a built in function */
12619         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12620
12621         /* which function is it */
12622         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12623         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12624                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12625         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12626                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12627         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12628                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12629         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12630                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12631         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12632                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12633         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12634                 genInp(bi_iCode,nbi_parms,bi_parms);
12635         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12636                 genOutp(bi_iCode,nbi_parms,bi_parms);
12637         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12638                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12639                 /* JavaNative builtIns */               
12640         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12641                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12642         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12643                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12644         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12645                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12646         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12647                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12648         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12649                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12650         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12651                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12652         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12653                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12654         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12655                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12656         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12657                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12658         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12659                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12660         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12661                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12662         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12663                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12664         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12665                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12666         } else if (strcmp(bif->name,"MM_Free")==0) {
12667                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12668         } else if (strcmp(bif->name,"MM_Deref")==0) {
12669                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12670         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12671                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12672         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12673                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12674         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12675                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12676         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12677                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12678         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12679                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12680         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12681                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12682         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12683                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12684         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12685                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12686         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12687                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12688         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12689                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12690         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12691                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12692         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12693                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12694         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12695                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12696         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12697                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12698         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12699                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12700         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12701                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12702         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12703                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12704         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12705                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12706         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12707                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12708         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12709                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12710         } else {
12711                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12712                 return ;
12713         }
12714         return ;    
12715 }
12716
12717 /*-----------------------------------------------------------------*/
12718 /* gen390Code - generate code for Dallas 390 based controllers     */
12719 /*-----------------------------------------------------------------*/
12720 void
12721 gen390Code (iCode * lic)
12722 {
12723   iCode *ic;
12724   int cln = 0;
12725
12726   lineHead = lineCurr = NULL;
12727   dptrn[1][0] = "dpl1";
12728   dptrn[1][1] = "dph1";
12729   dptrn[1][2] = "dpx1";
12730   
12731   if (options.model == MODEL_FLAT24) {
12732     fReturnSizeDS390 = 5;
12733     fReturn = fReturn24;
12734   } else {
12735     fReturnSizeDS390 = 4;
12736     fReturn = fReturn16;
12737     options.stack10bit=0;
12738   }
12739 #if 1
12740   /* print the allocation information */
12741   if (allocInfo && currFunc)
12742     printAllocInfo (currFunc, codeOutFile);
12743 #endif
12744   /* if debug information required */
12745   if (options.debug && currFunc)
12746     {
12747       debugFile->writeFunction(currFunc);
12748       _G.debugLine = 1;
12749       if (IS_STATIC (currFunc->etype))
12750         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12751       else
12752         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12753       _G.debugLine = 0;
12754     }
12755   /* stack pointer name */
12756   if (options.useXstack)
12757     spname = "_spx";
12758   else
12759     spname = "sp";
12760
12761
12762   for (ic = lic; ic; ic = ic->next)
12763     {
12764
12765       if (ic->lineno && cln != ic->lineno)
12766         {
12767           if (options.debug)
12768             {
12769               _G.debugLine = 1;
12770               emitcode ("", "C$%s$%d$%d$%d ==.",
12771                         FileBaseName (ic->filename), ic->lineno,
12772                         ic->level, ic->block);
12773               _G.debugLine = 0;
12774             }
12775           if (!options.noCcodeInAsm) {
12776             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12777                       printCLine(ic->filename, ic->lineno));
12778           }
12779           cln = ic->lineno;
12780         }
12781       if (options.iCodeInAsm) {
12782         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12783       }
12784       /* if the result is marked as
12785          spilt and rematerializable or code for
12786          this has already been generated then
12787          do nothing */
12788       if (resultRemat (ic) || ic->generated)
12789         continue;
12790
12791       /* depending on the operation */
12792       switch (ic->op)
12793         {
12794         case '!':
12795           genNot (ic);
12796           break;
12797
12798         case '~':
12799           genCpl (ic);
12800           break;
12801
12802         case UNARYMINUS:
12803           genUminus (ic);
12804           break;
12805
12806         case IPUSH:
12807           genIpush (ic);
12808           break;
12809
12810         case IPOP:
12811           /* IPOP happens only when trying to restore a
12812              spilt live range, if there is an ifx statement
12813              following this pop then the if statement might
12814              be using some of the registers being popped which
12815              would destory the contents of the register so
12816              we need to check for this condition and handle it */
12817           if (ic->next &&
12818               ic->next->op == IFX &&
12819               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12820             genIfx (ic->next, ic);
12821           else
12822             genIpop (ic);
12823           break;
12824
12825         case CALL:
12826           genCall (ic);
12827           break;
12828
12829         case PCALL:
12830           genPcall (ic);
12831           break;
12832
12833         case FUNCTION:
12834           genFunction (ic);
12835           break;
12836
12837         case ENDFUNCTION:
12838           genEndFunction (ic);
12839           break;
12840
12841         case RETURN:
12842           genRet (ic);
12843           break;
12844
12845         case LABEL:
12846           genLabel (ic);
12847           break;
12848
12849         case GOTO:
12850           genGoto (ic);
12851           break;
12852
12853         case '+':
12854           genPlus (ic);
12855           break;
12856
12857         case '-':
12858           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12859             genMinus (ic);
12860           break;
12861
12862         case '*':
12863           genMult (ic);
12864           break;
12865
12866         case '/':
12867           genDiv (ic);
12868           break;
12869
12870         case '%':
12871           genMod (ic);
12872           break;
12873
12874         case '>':
12875           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12876           break;
12877
12878         case '<':
12879           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12880           break;
12881
12882         case LE_OP:
12883         case GE_OP:
12884         case NE_OP:
12885
12886           /* note these two are xlated by algebraic equivalence
12887              during parsing SDCC.y */
12888           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12889                   "got '>=' or '<=' shouldn't have come here");
12890           break;
12891
12892         case EQ_OP:
12893           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12894           break;
12895
12896         case AND_OP:
12897           genAndOp (ic);
12898           break;
12899
12900         case OR_OP:
12901           genOrOp (ic);
12902           break;
12903
12904         case '^':
12905           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12906           break;
12907
12908         case '|':
12909           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12910           break;
12911
12912         case BITWISEAND:
12913           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12914           break;
12915
12916         case INLINEASM:
12917           genInline (ic);
12918           break;
12919
12920         case RRC:
12921           genRRC (ic);
12922           break;
12923
12924         case RLC:
12925           genRLC (ic);
12926           break;
12927
12928         case GETHBIT:
12929           genGetHbit (ic);
12930           break;
12931
12932         case LEFT_OP:
12933           genLeftShift (ic);
12934           break;
12935
12936         case RIGHT_OP:
12937           genRightShift (ic);
12938           break;
12939
12940         case GET_VALUE_AT_ADDRESS:
12941           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12942           break;
12943
12944         case '=':
12945           if (POINTER_SET (ic))
12946             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12947           else
12948             genAssign (ic);
12949           break;
12950
12951         case IFX:
12952           genIfx (ic, NULL);
12953           break;
12954
12955         case ADDRESS_OF:
12956           genAddrOf (ic);
12957           break;
12958
12959         case JUMPTABLE:
12960           genJumpTab (ic);
12961           break;
12962
12963         case CAST:
12964           genCast (ic);
12965           break;
12966
12967         case RECEIVE:
12968           genReceive (ic);
12969           break;
12970
12971         case SEND:
12972           if (ic->builtinSEND) genBuiltIn(ic);
12973           else addSet (&_G.sendSet, ic);
12974           break;
12975
12976 #if 0 // obsolete, and buggy for != xdata
12977         case ARRAYINIT:
12978             genArrayInit(ic);
12979             break;
12980 #endif
12981             
12982         default:
12983           ic = ic;
12984         }
12985     }
12986
12987
12988   /* now we are ready to call the
12989      peep hole optimizer */
12990   if (!options.nopeep)
12991     peepHole (&lineHead);
12992
12993   /* now do the actual printing */
12994   printLine (lineHead, codeOutFile);
12995   return;
12996 }