fixed bug #741761
[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 /* leftRightUseAcc - returns size of accumulator use by operands   */
443 /*-----------------------------------------------------------------*/
444 static int
445 leftRightUseAcc(iCode *ic)
446 {
447   int accuse = 0;
448   
449   if (ic && IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic))
450       && OP_SYMBOL (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic))->accuse)
451     accuse = (accuse < OP_SYMBOL (IC_LEFT (ic))->nRegs)
452              ? OP_SYMBOL (IC_LEFT (ic))->nRegs : accuse;
453     
454   if (ic && IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic))
455       && OP_SYMBOL (IC_RIGHT (ic)) && OP_SYMBOL (IC_RIGHT (ic))->accuse)
456     accuse = (accuse < OP_SYMBOL (IC_RIGHT (ic))->nRegs)
457              ? OP_SYMBOL (IC_RIGHT (ic))->nRegs : accuse;
458
459   return accuse;
460 }
461
462 /*-----------------------------------------------------------------*/
463 /* aopForSym - for a true symbol                                   */
464 /*-----------------------------------------------------------------*/
465 static asmop *
466 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
467 {
468   asmop *aop;
469   memmap *space = SPEC_OCLS (sym->etype);
470   int accuse = leftRightUseAcc (ic);
471
472   /* if already has one */
473   if (sym->aop)
474     return sym->aop;
475
476   /* assign depending on the storage class */
477   /* if it is on the stack or indirectly addressable */
478   /* space we need to assign either r0 or r1 to it   */
479   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
480     {
481       sym->aop = aop = newAsmop (0);
482       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
483       aop->size = getSize (sym->type);
484
485       /* now assign the address of the variable to
486          the pointer register */
487       if (aop->type != AOP_STK)
488         {
489
490           if (sym->onStack)
491             {
492               if (_G.accInUse || accuse)
493                 emitcode ("push", "acc");
494
495               if (_G.bInUse || (accuse>1))
496                 emitcode ("push", "b");
497
498               emitcode ("mov", "a,_bp");
499               emitcode ("add", "a,#!constbyte",
500                         ((sym->stack < 0) ?
501                          ((char) (sym->stack - _G.nRegsSaved)) :
502                          ((char) sym->stack)) & 0xff);
503               emitcode ("mov", "%s,a",
504                         aop->aopu.aop_ptr->name);
505
506               if (_G.bInUse || (accuse>1))
507                 emitcode ("pop", "b");
508
509               if (_G.accInUse || accuse)
510                 emitcode ("pop", "acc");
511             }
512           else
513             emitcode ("mov", "%s,#%s",
514                       aop->aopu.aop_ptr->name,
515                       sym->rname);
516           aop->paged = space->paged;
517         }
518       else
519         aop->aopu.aop_stk = sym->stack;
520       return aop;
521     }
522
523   if (sym->onStack && options.stack10bit)
524     {
525         short stack_val = -((sym->stack < 0) ?
526                             ((short) (sym->stack - _G.nRegsSaved)) :
527                             ((short) sym->stack)) ;
528         if (useDP2 && _G.dptr1InUse) {
529             emitcode ("push","dpl1");
530             emitcode ("push","dph1");
531             emitcode ("push","dpx1");
532         } else if (_G.dptrInUse ) {
533             emitcode ("push","dpl");
534             emitcode ("push","dph");
535             emitcode ("push","dpx");
536         }
537       /* It's on the 10 bit stack, which is located in
538        * far data space.
539        */           
540         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
541             if (useDP2) {
542                 if (options.model == MODEL_FLAT24)
543                 {
544                     emitcode ("mov", "dpx1,#!constbyte",
545                               (options.stack_loc >> 16) & 0xff);
546                 }
547                 emitcode ("mov", "dph1,_bpx+1");
548                 
549                 emitcode ("mov", "dpl1,_bpx");
550                 emitcode ("mov","dps,#1");
551             } else {
552                 if (options.model == MODEL_FLAT24)
553                 {
554                     emitcode ("mov", "dpx,#!constbyte",
555                               (options.stack_loc >> 16) & 0xff);
556                 }
557                 emitcode ("mov", "dph,_bpx+1");
558                 emitcode ("mov", "dpl,_bpx");
559             }
560             stack_val = -stack_val;
561             while (stack_val--) {
562                 emitcode ("inc","dptr");
563             }
564             if (useDP2) {
565                 emitcode("mov","dps,#0");
566             }
567         }  else {
568             if (_G.accInUse || accuse)
569                 emitcode ("push", "acc");
570             
571             if (_G.bInUse || (accuse>1))
572                 emitcode ("push", "b");
573         
574             emitcode ("mov", "a,_bpx");
575             emitcode ("clr","c");
576             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
577             emitcode ("mov","b,a");
578             emitcode ("mov","a,_bpx+1");
579             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
580             if (useDP2) {
581                 if (options.model == MODEL_FLAT24)
582                 {
583                     emitcode ("mov", "dpx1,#!constbyte",
584                               (options.stack_loc >> 16) & 0xff);
585                 }
586                 emitcode ("mov", "dph1,a");
587                 emitcode ("mov", "dpl1,b");
588             } else {
589                 if (options.model == MODEL_FLAT24)
590                 {
591                     emitcode ("mov", "dpx,#!constbyte",
592                               (options.stack_loc >> 16) & 0xff);
593                 }
594                 emitcode ("mov", "dph,a");
595                 emitcode ("mov", "dpl,b");
596             }
597             
598             if (_G.bInUse || (accuse>1))
599                 emitcode ("pop", "b");
600             
601             if (_G.accInUse || accuse)
602                 emitcode ("pop", "acc");
603         }
604         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
605         aop->size = getSize (sym->type);
606         return aop;
607     }
608
609   /* if in bit space */
610   if (IN_BITSPACE (space))
611     {
612       sym->aop = aop = newAsmop (AOP_CRY);
613       aop->aopu.aop_dir = sym->rname;
614       aop->size = getSize (sym->type);
615       return aop;
616     }
617   /* if it is in direct space */
618   if (IN_DIRSPACE (space))
619     {
620       sym->aop = aop = newAsmop (AOP_DIR);
621       aop->aopu.aop_dir = sym->rname;
622       aop->size = getSize (sym->type);
623       return aop;
624     }
625
626   /* special case for a function */
627   if (IS_FUNC (sym->type) && !(sym->isitmp))
628     {
629       sym->aop = aop = newAsmop (AOP_IMMD);
630       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
631       aop->size = FPTRSIZE;
632       return aop;
633     }
634
635   /* only remaining is far space */
636   /* in which case DPTR gets the address */
637   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
638   if (useDP2)
639     {
640       genSetDPTR (1);
641       _flushLazyDPS ();
642       emitcode ("mov", "dptr,#%s", sym->rname);
643       genSetDPTR (0);
644     }
645   else
646     {
647       emitcode ("mov", "dptr,#%s", sym->rname);
648     }
649   aop->size = getSize (sym->type);
650
651   /* if it is in code space */
652   if (IN_CODESPACE (space))
653     aop->code = 1;
654
655   return aop;
656 }
657
658 /*-----------------------------------------------------------------*/
659 /* aopForRemat - rematerialzes an object                           */
660 /*-----------------------------------------------------------------*/
661 static asmop *
662 aopForRemat (symbol * sym)
663 {
664   iCode *ic = sym->rematiCode;
665   asmop *aop = newAsmop (AOP_IMMD);
666   int ptr_type =0;
667   int val = 0;
668
669   for (;;)
670     {
671       if (ic->op == '+')
672         val += (int) operandLitValue (IC_RIGHT (ic));
673       else if (ic->op == '-')
674         val -= (int) operandLitValue (IC_RIGHT (ic));
675       else if (IS_CAST_ICODE(ic)) {
676               sym_link *from_type = operandType(IC_RIGHT(ic));
677               aop->aopu.aop_immd.from_cast_remat = 1;
678               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
679               ptr_type = DCL_TYPE(from_type);
680               if (ptr_type == IPOINTER) {
681                 // bug #481053
682                 ptr_type = POINTER;
683               }
684               continue ;
685       } else break;
686       
687       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
688     }
689
690   if (val)
691   {
692       SNPRINTF (buffer, sizeof(buffer),
693                 "(%s %c 0x%04x)",
694                 OP_SYMBOL (IC_LEFT (ic))->rname,
695                 val >= 0 ? '+' : '-',
696                 abs (val) & 0xffffff);
697   }
698   else 
699   {
700       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
701       {
702           SNPRINTF(buffer, sizeof(buffer), 
703                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
704       }
705       else
706       {
707           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
708       }
709   }
710
711   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
712   /* set immd2 field if required */
713   if (aop->aopu.aop_immd.from_cast_remat) 
714   {
715       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
716       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
717   }
718
719   return aop;
720 }
721
722 /*-----------------------------------------------------------------*/
723 /* aopHasRegs - returns true if aop has regs between from-to       */
724 /*-----------------------------------------------------------------*/
725 static int aopHasRegs(asmop *aop, int from, int to)
726 {
727     int size =0;
728
729     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
730
731     for (; size < aop->size ; size++) {
732         int reg;
733         for (reg = from ; reg <= to ; reg++)
734             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
735     }
736     return 0;
737 }
738
739 /*-----------------------------------------------------------------*/
740 /* regsInCommon - two operands have some registers in common       */
741 /*-----------------------------------------------------------------*/
742 static bool
743 regsInCommon (operand * op1, operand * op2)
744 {
745   symbol *sym1, *sym2;
746   int i;
747
748   /* if they have registers in common */
749   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
750     return FALSE;
751
752   sym1 = OP_SYMBOL (op1);
753   sym2 = OP_SYMBOL (op2);
754
755   if (sym1->nRegs == 0 || sym2->nRegs == 0)
756     return FALSE;
757
758   for (i = 0; i < sym1->nRegs; i++)
759     {
760       int j;
761       if (!sym1->regs[i])
762         continue;
763
764       for (j = 0; j < sym2->nRegs; j++)
765         {
766           if (!sym2->regs[j])
767             continue;
768
769           if (sym2->regs[j] == sym1->regs[i])
770             return TRUE;
771         }
772     }
773
774   return FALSE;
775 }
776
777 /*-----------------------------------------------------------------*/
778 /* operandsEqu - equivalent                                        */
779 /*-----------------------------------------------------------------*/
780 static bool
781 operandsEqu (operand * op1, operand * op2)
782 {
783   symbol *sym1, *sym2;
784
785   /* if they not symbols */
786   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
787     return FALSE;
788
789   sym1 = OP_SYMBOL (op1);
790   sym2 = OP_SYMBOL (op2);
791
792   /* if both are itemps & one is spilt
793      and the other is not then false */
794   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
795       sym1->isspilt != sym2->isspilt)
796     return FALSE;
797
798   /* if they are the same */
799   if (sym1 == sym2)
800     return TRUE;
801
802   if (strcmp (sym1->rname, sym2->rname) == 0)
803     return TRUE;
804
805
806   /* if left is a tmp & right is not */
807   if (IS_ITEMP (op1) &&
808       !IS_ITEMP (op2) &&
809       sym1->isspilt &&
810       (sym1->usl.spillLoc == sym2))
811     return TRUE;
812
813   if (IS_ITEMP (op2) &&
814       !IS_ITEMP (op1) &&
815       sym2->isspilt &&
816       sym1->level > 0 &&
817       (sym2->usl.spillLoc == sym1))
818     return TRUE;
819
820   return FALSE;
821 }
822
823 /*-----------------------------------------------------------------*/
824 /* sameRegs - two asmops have the same registers                   */
825 /*-----------------------------------------------------------------*/
826 static bool
827 sameRegs (asmop * aop1, asmop * aop2)
828 {
829   int i;
830
831   if (aop1 == aop2)
832     {
833       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
834         {
835           return FALSE;
836         }
837       return TRUE;
838     }
839
840   if (aop1->type != AOP_REG ||
841       aop2->type != AOP_REG)
842     return FALSE;
843
844   if (aop1->size != aop2->size)
845     return FALSE;
846
847   for (i = 0; i < aop1->size; i++)
848     if (aop1->aopu.aop_reg[i] !=
849         aop2->aopu.aop_reg[i])
850       return FALSE;
851
852   return TRUE;
853 }
854
855 /*-----------------------------------------------------------------*/
856 /* aopOp - allocates an asmop for an operand  :                    */
857 /*-----------------------------------------------------------------*/
858 static void
859 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
860 {
861   asmop *aop;
862   symbol *sym;
863   int i;
864
865   if (!op)
866     return;
867
868   /* if this a literal */
869   if (IS_OP_LITERAL (op))
870     {
871       op->aop = aop = newAsmop (AOP_LIT);
872       aop->aopu.aop_lit = op->operand.valOperand;
873       aop->size = getSize (operandType (op));
874       return;
875     }
876
877   /* if already has a asmop then continue */
878   if (op->aop)
879     return;
880
881   /* if the underlying symbol has a aop */
882   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
883     {
884       op->aop = OP_SYMBOL (op)->aop;
885       return;
886     }
887
888   /* if this is a true symbol */
889   if (IS_TRUE_SYMOP (op))
890     {
891       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
892       return;
893     }
894
895   /* this is a temporary : this has
896      only four choices :
897      a) register
898      b) spillocation
899      c) rematerialize
900      d) conditional
901      e) can be a return use only */
902
903   sym = OP_SYMBOL (op);
904
905
906   /* if the type is a conditional */
907   if (sym->regType == REG_CND)
908     {
909       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
910       aop->size = 0;
911       return;
912     }
913
914   /* if it is spilt then two situations
915      a) is rematerialize
916      b) has a spill location */
917   if (sym->isspilt || sym->nRegs == 0)
918     {
919
920       /* rematerialize it NOW */
921       if (sym->remat)
922         {
923           sym->aop = op->aop = aop =
924             aopForRemat (sym);
925           aop->size = getSize (sym->type);
926           return;
927         }
928
929       if (sym->accuse)
930         {
931           int i;
932           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
933           aop->size = getSize (sym->type);
934           for (i = 0; i < 2; i++)
935             aop->aopu.aop_str[i] = accUse[i];
936           return;
937         }
938
939       if (sym->ruonly)
940         {
941           int i;
942
943           if (useDP2)
944             {
945               /* a AOP_STR uses DPTR, but DPTR is already in use;
946                * we're just hosed.
947                */
948                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
949             }
950
951           aop = op->aop = sym->aop = newAsmop (AOP_STR);
952           aop->size = getSize (sym->type);
953           for (i = 0; i < (int) fReturnSizeDS390; i++)
954             aop->aopu.aop_str[i] = fReturn[i];
955           return;
956         }
957       
958       if (sym->dptr) { /* has been allocated to a DPTRn */
959           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
960           aop->size = getSize (sym->type);
961           aop->aopu.dptr = sym->dptr;
962           return ;
963       }
964       /* else spill location  */
965       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
966           /* force a new aop if sizes differ */
967           sym->usl.spillLoc->aop = NULL;
968       }
969       sym->aop = op->aop = aop =
970         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
971       aop->size = getSize (sym->type);
972       return;
973     }
974
975   /* must be in a register */
976   sym->aop = op->aop = aop = newAsmop (AOP_REG);
977   aop->size = sym->nRegs;
978   for (i = 0; i < sym->nRegs; i++)
979     aop->aopu.aop_reg[i] = sym->regs[i];
980 }
981
982 /*-----------------------------------------------------------------*/
983 /* freeAsmop - free up the asmop given to an operand               */
984 /*----------------------------------------------------------------*/
985 static void
986 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
987 {
988   asmop *aop;
989
990   if (!op)
991     aop = aaop;
992   else
993     aop = op->aop;
994
995   if (!aop)
996     return;
997
998   if (aop->freed)
999     goto dealloc;
1000
1001   aop->freed = 1;
1002
1003   /* depending on the asmop type only three cases need work AOP_RO
1004      , AOP_R1 && AOP_STK */
1005   switch (aop->type)
1006     {
1007     case AOP_R0:
1008       if (_G.r0Pushed)
1009         {
1010           if (pop)
1011             {
1012               emitcode ("pop", "ar0");
1013               _G.r0Pushed--;
1014             }
1015         }
1016       bitVectUnSetBit (ic->rUsed, R0_IDX);
1017       break;
1018
1019     case AOP_R1:
1020       if (_G.r1Pushed)
1021         {
1022           if (pop)
1023             {
1024               emitcode ("pop", "ar1");
1025               _G.r1Pushed--;
1026             }
1027         }
1028       bitVectUnSetBit (ic->rUsed, R1_IDX);
1029       break;
1030
1031     case AOP_STK:
1032       {
1033         int sz = aop->size;
1034         int stk = aop->aopu.aop_stk + aop->size;
1035         bitVectUnSetBit (ic->rUsed, R0_IDX);
1036         bitVectUnSetBit (ic->rUsed, R1_IDX);
1037
1038         getFreePtr (ic, &aop, FALSE);
1039
1040         if (options.stack10bit)
1041           {
1042             /* I'm not sure what to do here yet... */
1043             /* #STUB */
1044             fprintf (stderr,
1045                      "*** Warning: probably generating bad code for "
1046                      "10 bit stack mode.\n");
1047           }
1048
1049         if (stk)
1050           {
1051             emitcode ("mov", "a,_bp");
1052             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1053             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1054           }
1055         else
1056           {
1057             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1058           }
1059
1060         while (sz--)
1061           {
1062             emitcode ("pop", "acc");
1063             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1064             if (!sz)
1065               break;
1066             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1067           }
1068         op->aop = aop;
1069         freeAsmop (op, NULL, ic, TRUE);
1070         if (_G.r0Pushed)
1071           {
1072             emitcode ("pop", "ar0");
1073             _G.r0Pushed--;
1074           }
1075
1076         if (_G.r1Pushed)
1077           {
1078             emitcode ("pop", "ar1");
1079             _G.r1Pushed--;
1080           }
1081       }
1082     case AOP_DPTR2:
1083         if (_G.dptr1InUse) {
1084             emitcode ("pop","dpx1");
1085             emitcode ("pop","dph1");
1086             emitcode ("pop","dpl1");
1087         }
1088         break;
1089     case AOP_DPTR:
1090         if (_G.dptrInUse) {
1091             emitcode ("pop","dpx");
1092             emitcode ("pop","dph");
1093             emitcode ("pop","dpl");
1094         }
1095         break;
1096     }
1097 dealloc:
1098   /* all other cases just dealloc */
1099   if (op)
1100     {
1101       op->aop = NULL;
1102       if (IS_SYMOP (op))
1103         {
1104           OP_SYMBOL (op)->aop = NULL;
1105           /* if the symbol has a spill */
1106           if (SPIL_LOC (op))
1107             SPIL_LOC (op)->aop = NULL;
1108         }
1109     }
1110 }
1111
1112 #define DEFAULT_ACC_WARNING 0
1113 static int saveAccWarn = DEFAULT_ACC_WARNING;
1114
1115 /*-------------------------------------------------------------------*/
1116 /* aopGet - for fetching value of the aop                            */
1117 /*                                                                   */
1118 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1119 /* in the accumulator. Set it to the name of a free register         */
1120 /* if acc must be preserved; the register will be used to preserve   */
1121 /* acc temporarily and to return the result byte.                    */
1122 /*-------------------------------------------------------------------*/
1123
1124 static char *
1125 aopGet (asmop *aop,
1126         int   offset,
1127         bool  bit16,
1128         bool  dname,
1129         char  *saveAcc)
1130 {
1131   /* offset is greater than
1132      size then zero */
1133   if (offset > (aop->size - 1) &&
1134       aop->type != AOP_LIT)
1135     return zero;
1136
1137   /* depending on type */
1138   switch (aop->type)
1139     {
1140
1141     case AOP_R0:
1142     case AOP_R1:
1143       /* if we need to increment it */
1144       while (offset > aop->coff)
1145         {
1146           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1147           aop->coff++;
1148         }
1149
1150       while (offset < aop->coff)
1151         {
1152           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1153           aop->coff--;
1154         }
1155
1156       aop->coff = offset;
1157       if (aop->paged)
1158         {
1159           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1160           return (dname ? "acc" : "a");
1161         }
1162       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1163       return Safe_strdup(buffer);       
1164
1165     case AOP_DPTRn:
1166         assert(offset <= 3);
1167         return dptrn[aop->aopu.dptr][offset];
1168
1169     case AOP_DPTR:
1170     case AOP_DPTR2:
1171
1172       if (aop->type == AOP_DPTR2)
1173         {
1174           genSetDPTR (1);
1175         }
1176         
1177       if (saveAcc)
1178         {
1179             TR_AP("#1");
1180 //          if (aop->type != AOP_DPTR2)
1181 //          {
1182 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1183 //              emitcode(";", "spanky: saveAcc for DPTR");
1184 //          }
1185             
1186             emitcode ("xch", "a, %s", saveAcc);
1187         }
1188
1189       _flushLazyDPS ();
1190
1191       while (offset > aop->coff)
1192         {
1193           emitcode ("inc", "dptr");
1194           aop->coff++;
1195         }
1196
1197       while (offset < aop->coff)
1198         {
1199           emitcode ("lcall", "__decdptr");
1200           aop->coff--;
1201         }
1202
1203       aop->coff = offset;
1204       if (aop->code)
1205         {
1206           emitcode ("clr", "a");
1207           emitcode ("movc", "a,@a+dptr");
1208         }
1209       else
1210         {
1211           emitcode ("movx", "a,@dptr");
1212         }
1213
1214       if (aop->type == AOP_DPTR2)
1215         {
1216           genSetDPTR (0);
1217         }
1218         
1219         if (saveAcc)
1220         {
1221        TR_AP("#2");
1222               emitcode ("xch", "a, %s", saveAcc);
1223 //            if (strcmp(saveAcc, "_ap"))
1224 //            {
1225 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1226 //            }
1227                   
1228               return saveAcc;
1229         }
1230       return (dname ? "acc" : "a");
1231
1232     case AOP_IMMD:
1233       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1234       {
1235           SNPRINTF(buffer, sizeof(buffer), 
1236                    "%s",aop->aopu.aop_immd.aop_immd2);
1237       } 
1238       else if (bit16)
1239       {
1240          SNPRINTF(buffer, sizeof(buffer), 
1241                   "#%s", aop->aopu.aop_immd.aop_immd1);
1242       }
1243       else if (offset) 
1244       {
1245           switch (offset) {
1246           case 1:
1247               tsprintf(buffer, sizeof(buffer),
1248                        "#!his",aop->aopu.aop_immd.aop_immd1);
1249               break;
1250           case 2:
1251               tsprintf(buffer, sizeof(buffer), 
1252                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1253               break;
1254           case 3:
1255               tsprintf(buffer, sizeof(buffer),
1256                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1257               break;
1258           default: /* should not need this (just in case) */
1259               SNPRINTF (buffer, sizeof(buffer), 
1260                         "#(%s >> %d)",
1261                        aop->aopu.aop_immd.aop_immd1,
1262                        offset * 8);
1263           }
1264       }
1265       else
1266       {
1267         SNPRINTF (buffer, sizeof(buffer), 
1268                   "#%s", aop->aopu.aop_immd.aop_immd1);
1269       }
1270       return Safe_strdup(buffer);       
1271
1272     case AOP_DIR:
1273       if (offset)
1274       {
1275         SNPRINTF (buffer, sizeof(buffer),
1276                   "(%s + %d)",
1277                  aop->aopu.aop_dir,
1278                  offset);
1279       }
1280       else
1281       {
1282         SNPRINTF(buffer, sizeof(buffer), 
1283                  "%s", aop->aopu.aop_dir);
1284       }
1285
1286       return Safe_strdup(buffer);
1287
1288     case AOP_REG:
1289       if (dname)
1290         return aop->aopu.aop_reg[offset]->dname;
1291       else
1292         return aop->aopu.aop_reg[offset]->name;
1293
1294     case AOP_CRY:
1295       emitcode ("clr", "a");
1296       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1297       emitcode ("rlc", "a");
1298       return (dname ? "acc" : "a");
1299
1300     case AOP_ACC:
1301       if (!offset && dname)
1302         return "acc";
1303       return aop->aopu.aop_str[offset];
1304
1305     case AOP_LIT:
1306       return aopLiteral (aop->aopu.aop_lit, offset);
1307
1308     case AOP_STR:
1309       aop->coff = offset;
1310       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1311           dname)
1312         return "acc";
1313
1314       return aop->aopu.aop_str[offset];
1315
1316     }
1317
1318   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1319           "aopget got unsupported aop->type");
1320   exit (1);
1321     
1322   return NULL;  // not reached, but makes compiler happy.
1323 }
1324 /*-----------------------------------------------------------------*/
1325 /* aopPut - puts a string for a aop                                */
1326 /*-----------------------------------------------------------------*/
1327 static void
1328 aopPut (asmop * aop, char *s, int offset)
1329 {
1330   if (aop->size && offset > (aop->size - 1))
1331     {
1332       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1333               "aopPut got offset > aop->size");
1334       exit (1);
1335     }
1336
1337   /* will assign value to value */
1338   /* depending on where it is ofcourse */
1339   switch (aop->type)
1340     {
1341     case AOP_DIR:
1342         if (offset)
1343         {
1344             SNPRINTF (buffer, sizeof(buffer),
1345                       "(%s + %d)",
1346                       aop->aopu.aop_dir, offset);
1347         }
1348         else
1349         {
1350             SNPRINTF (buffer, sizeof(buffer), 
1351                      "%s", aop->aopu.aop_dir);
1352         }
1353         
1354
1355         if (strcmp (buffer, s))
1356         {
1357             emitcode ("mov", "%s,%s", buffer, s);
1358         }
1359       break;
1360
1361     case AOP_REG:
1362       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1363           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1364         {
1365           if (*s == '@' ||
1366               strcmp (s, "r0") == 0 ||
1367               strcmp (s, "r1") == 0 ||
1368               strcmp (s, "r2") == 0 ||
1369               strcmp (s, "r3") == 0 ||
1370               strcmp (s, "r4") == 0 ||
1371               strcmp (s, "r5") == 0 ||
1372               strcmp (s, "r6") == 0 ||
1373               strcmp (s, "r7") == 0)
1374             {
1375                 emitcode ("mov", "%s,%s",
1376                           aop->aopu.aop_reg[offset]->dname, s);
1377             }
1378             else
1379             {
1380                 emitcode ("mov", "%s,%s",
1381                           aop->aopu.aop_reg[offset]->name, s);
1382             }
1383         }
1384       break;
1385
1386     case AOP_DPTRn:
1387         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1388         break;
1389
1390     case AOP_DPTR:
1391     case AOP_DPTR2:
1392
1393       if (aop->type == AOP_DPTR2)
1394         {
1395           genSetDPTR (1);
1396         }
1397       _flushLazyDPS ();
1398
1399       if (aop->code)
1400         {
1401           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1402                   "aopPut writting to code space");
1403           exit (1);
1404         }
1405
1406       while (offset > aop->coff)
1407         {
1408           aop->coff++;
1409           emitcode ("inc", "dptr");
1410         }
1411
1412       while (offset < aop->coff)
1413         {
1414           aop->coff--;
1415           emitcode ("lcall", "__decdptr");
1416         }
1417
1418       aop->coff = offset;
1419
1420       /* if not in accumulater */
1421       MOVA (s);
1422
1423       emitcode ("movx", "@dptr,a");
1424
1425       if (aop->type == AOP_DPTR2)
1426         {
1427           genSetDPTR (0);
1428         }
1429       break;
1430
1431     case AOP_R0:
1432     case AOP_R1:
1433       while (offset > aop->coff)
1434         {
1435           aop->coff++;
1436           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1437         }
1438       while (offset < aop->coff)
1439         {
1440           aop->coff--;
1441           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1442         }
1443       aop->coff = offset;
1444
1445       if (aop->paged)
1446         {
1447           MOVA (s);
1448           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1449
1450         }
1451       else if (*s == '@')
1452         {
1453           MOVA (s);
1454           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1455         }
1456       else if (strcmp (s, "r0") == 0 ||
1457                strcmp (s, "r1") == 0 ||
1458                strcmp (s, "r2") == 0 ||
1459                strcmp (s, "r3") == 0 ||
1460                strcmp (s, "r4") == 0 ||
1461                strcmp (s, "r5") == 0 ||
1462                strcmp (s, "r6") == 0 ||
1463                strcmp (s, "r7") == 0)
1464         {
1465           char buff[10];
1466           SNPRINTF(buff, sizeof(buff), 
1467                    "a%s", s);
1468           emitcode ("mov", "@%s,%s",
1469                     aop->aopu.aop_ptr->name, buff);
1470         }
1471         else
1472         {
1473             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1474         }
1475       break;
1476
1477     case AOP_STK:
1478       if (strcmp (s, "a") == 0)
1479         emitcode ("push", "acc");
1480       else
1481         if (*s=='@') {
1482           MOVA(s);
1483           emitcode ("push", "acc");
1484         } else {
1485           emitcode ("push", s);
1486         }
1487
1488       break;
1489
1490     case AOP_CRY:
1491       /* if bit variable */
1492       if (!aop->aopu.aop_dir)
1493         {
1494           emitcode ("clr", "a");
1495           emitcode ("rlc", "a");
1496         }
1497       else
1498         {
1499           if (s == zero)
1500             emitcode ("clr", "%s", aop->aopu.aop_dir);
1501           else if (s == one)
1502             emitcode ("setb", "%s", aop->aopu.aop_dir);
1503           else if (!strcmp (s, "c"))
1504             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1505           else
1506             {
1507               if (strcmp (s, "a"))
1508                 {
1509                   MOVA (s);
1510                 }
1511               {
1512                 /* set C, if a >= 1 */
1513                 emitcode ("add", "a,#!constbyte",0xff);
1514                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1515               }
1516             }
1517         }
1518       break;
1519
1520     case AOP_STR:
1521       aop->coff = offset;
1522       if (strcmp (aop->aopu.aop_str[offset], s))
1523         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1524       break;
1525
1526     case AOP_ACC:
1527       aop->coff = offset;
1528       if (!offset && (strcmp (s, "acc") == 0))
1529         break;
1530
1531       if (strcmp (aop->aopu.aop_str[offset], s))
1532         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1533       break;
1534
1535     default:
1536       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1537               "aopPut got unsupported aop->type");
1538       exit (1);
1539     }
1540
1541 }
1542
1543
1544 /*--------------------------------------------------------------------*/
1545 /* reAdjustPreg - points a register back to where it should (coff==0) */
1546 /*--------------------------------------------------------------------*/
1547 static void
1548 reAdjustPreg (asmop * aop)
1549 {
1550   if ((aop->coff==0) || (aop->size <= 1)) {
1551     return;
1552   }
1553
1554   switch (aop->type)
1555     {
1556     case AOP_R0:
1557     case AOP_R1:
1558       while (aop->coff--)
1559         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1560       break;
1561     case AOP_DPTR:
1562     case AOP_DPTR2:
1563       if (aop->type == AOP_DPTR2)
1564         {
1565           genSetDPTR (1);
1566           _flushLazyDPS ();
1567         }
1568       while (aop->coff--)
1569         {
1570           emitcode ("lcall", "__decdptr");
1571         }
1572
1573       if (aop->type == AOP_DPTR2)
1574         {
1575           genSetDPTR (0);
1576         }
1577       break;
1578
1579     }
1580   aop->coff=0;
1581 }
1582
1583 #define AOP(op) op->aop
1584 #define AOP_TYPE(op) AOP(op)->type
1585 #define AOP_SIZE(op) AOP(op)->size
1586 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1587                        AOP_TYPE(x) == AOP_R0))
1588
1589 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1590                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1591                          AOP(x)->paged))
1592
1593 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1594                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1595                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1596 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1597 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1598 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1599
1600 // The following two macros can be used even if the aop has not yet been aopOp'd.
1601 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1602 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1603
1604 /* Workaround for DS80C390 bug: div ab may return bogus results
1605  * if A is accessed in instruction immediately before the div.
1606  *
1607  * Will be fixed in B4 rev of processor, Dallas claims.
1608  */
1609
1610 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1611     if (!AOP_NEEDSACC(RIGHT))         \
1612     {               \
1613       /* We can load A first, then B, since     \
1614        * B (the RIGHT operand) won't clobber A,   \
1615        * thus avoiding touching A right before the div. \
1616        */             \
1617       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1618       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1619       MOVA(L);            \
1620       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1621       MOVB(L); \
1622     }               \
1623     else              \
1624     {               \
1625       /* Just stuff in a nop after loading A. */    \
1626       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1627       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1628       MOVA(L);            \
1629       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1630     }
1631
1632
1633 /*-----------------------------------------------------------------*/
1634 /* opIsGptr: returns non-zero if the passed operand is       */
1635 /* a generic pointer type.             */
1636 /*-----------------------------------------------------------------*/
1637 static int
1638 opIsGptr (operand * op)
1639 {
1640   sym_link *type = operandType (op);
1641
1642   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1643     {
1644       return 1;
1645     }
1646   return 0;
1647 }
1648
1649 /*-----------------------------------------------------------------*/
1650 /* getDataSize - get the operand data size                         */
1651 /*-----------------------------------------------------------------*/
1652 static int
1653 getDataSize (operand * op)
1654 {
1655   int size;
1656   size = AOP_SIZE (op);
1657   if (size == GPTRSIZE)
1658     {
1659       sym_link *type = operandType (op);
1660       if (IS_GENPTR (type))
1661         {
1662           /* generic pointer; arithmetic operations
1663            * should ignore the high byte (pointer type).
1664            */
1665           size--;
1666         }
1667     }
1668   return size;
1669 }
1670
1671 /*-----------------------------------------------------------------*/
1672 /* outAcc - output Acc                                             */
1673 /*-----------------------------------------------------------------*/
1674 static void
1675 outAcc (operand * result)
1676 {
1677   int size, offset;
1678   size = getDataSize (result);
1679   if (size)
1680     {
1681       aopPut (AOP (result), "a", 0);
1682       size--;
1683       offset = 1;
1684       /* unsigned or positive */
1685       while (size--)
1686         {
1687           aopPut (AOP (result), zero, offset++);
1688         }
1689     }
1690 }
1691
1692 /*-----------------------------------------------------------------*/
1693 /* outBitC - output a bit C                                        */
1694 /*-----------------------------------------------------------------*/
1695 static void
1696 outBitC (operand * result)
1697 {
1698   /* if the result is bit */
1699   if (AOP_TYPE (result) == AOP_CRY)
1700     {
1701       aopPut (AOP (result), "c", 0);
1702     }
1703   else
1704     {
1705       emitcode ("clr", "a");
1706       emitcode ("rlc", "a");
1707       outAcc (result);
1708     }
1709 }
1710
1711 /*-----------------------------------------------------------------*/
1712 /* toBoolean - emit code for orl a,operator(sizeop)                */
1713 /*-----------------------------------------------------------------*/
1714 static void
1715 toBoolean (operand * oper)
1716 {
1717   int   size = AOP_SIZE (oper) - 1;
1718   int   offset = 1;
1719   bool usedB = FALSE;
1720
1721   /* The generic part of a generic pointer should
1722    * not participate in it's truth value.
1723    *
1724    * i.e. 0x10000000 is zero.
1725    */
1726   if (opIsGptr (oper))
1727     {
1728       D (emitcode (";", "toBoolean: generic ptr special case."););
1729       size--;
1730     }
1731
1732   _startLazyDPSEvaluation ();
1733   if (AOP_NEEDSACC (oper) && size)
1734     {
1735       usedB = TRUE;
1736       if (_G.bInUse)
1737       {
1738           emitcode ("push", "b");
1739       }
1740       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1741     }
1742   else
1743     {
1744       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1745     }
1746     
1747   while (size--)
1748     {
1749       if (usedB)
1750         {
1751           emitcode ("orl", "b,%s",
1752                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1753         }
1754       else
1755         {
1756           emitcode ("orl", "a,%s",
1757                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1758         }
1759     }
1760   _endLazyDPSEvaluation ();
1761
1762   if (usedB)
1763     {
1764       emitcode ("mov", "a,b");
1765       if (_G.bInUse)
1766       {
1767           emitcode ("pop", "b");
1768       }
1769         
1770     }
1771 }
1772
1773
1774 /*-----------------------------------------------------------------*/
1775 /* genNot - generate code for ! operation                          */
1776 /*-----------------------------------------------------------------*/
1777 static void
1778 genNot (iCode * ic)
1779 {
1780   symbol *tlbl;
1781
1782   D (emitcode (";", "genNot "););
1783
1784   /* assign asmOps to operand & result */
1785   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1786   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1787
1788   /* if in bit space then a special case */
1789   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1790     {
1791       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1792       emitcode ("cpl", "c");
1793       outBitC (IC_RESULT (ic));
1794       goto release;
1795     }
1796
1797   toBoolean (IC_LEFT (ic));
1798
1799   tlbl = newiTempLabel (NULL);
1800   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1801   emitcode ("", "!tlabeldef", tlbl->key + 100);
1802   outBitC (IC_RESULT (ic));
1803
1804 release:
1805   /* release the aops */
1806   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1807   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1808 }
1809
1810
1811 /*-----------------------------------------------------------------*/
1812 /* genCpl - generate code for complement                           */
1813 /*-----------------------------------------------------------------*/
1814 static void
1815 genCpl (iCode * ic)
1816 {
1817   int offset = 0;
1818   int size;
1819   symbol *tlbl;
1820
1821   D (emitcode (";", "genCpl "););
1822
1823
1824   /* assign asmOps to operand & result */
1825   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1826   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1827
1828   /* special case if in bit space */
1829   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1830     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1831       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1832       emitcode ("cpl", "c");
1833       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1834       goto release;
1835     }
1836     tlbl=newiTempLabel(NULL);
1837     emitcode ("cjne", "%s,#0x01,%05d$", 
1838               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1839     emitcode ("", "%05d$:", tlbl->key+100);
1840     outBitC (IC_RESULT(ic));
1841     goto release;
1842   }
1843
1844   size = AOP_SIZE (IC_RESULT (ic));
1845   _startLazyDPSEvaluation ();
1846   while (size--)
1847     {
1848       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1849       emitcode ("cpl", "a");
1850       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1851     }
1852   _endLazyDPSEvaluation ();
1853
1854
1855 release:
1856   /* release the aops */
1857   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1858   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1859 }
1860
1861 /*-----------------------------------------------------------------*/
1862 /* genUminusFloat - unary minus for floating points                */
1863 /*-----------------------------------------------------------------*/
1864 static void
1865 genUminusFloat (operand * op, operand * result)
1866 {
1867   int size, offset = 0;
1868     
1869   D(emitcode (";", "genUminusFloat"););
1870   
1871   /* for this we just copy and then flip the bit */
1872     
1873   _startLazyDPSEvaluation ();
1874   size = AOP_SIZE (op) - 1;
1875
1876   while (size--)
1877   {
1878       aopPut (AOP (result),
1879               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1880               offset);
1881       offset++;
1882     }
1883   
1884   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1885
1886   emitcode ("cpl", "acc.7");
1887   aopPut (AOP (result), "a", offset);    
1888   _endLazyDPSEvaluation ();
1889 }
1890
1891 /*-----------------------------------------------------------------*/
1892 /* genUminus - unary minus code generation                         */
1893 /*-----------------------------------------------------------------*/
1894 static void
1895 genUminus (iCode * ic)
1896 {
1897   int offset, size;
1898   sym_link *optype;
1899
1900   D (emitcode (";", "genUminus "););
1901
1902   /* assign asmops */
1903   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1904   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1905
1906   /* if both in bit space then special
1907      case */
1908   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1909       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1910     {
1911
1912       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1913       emitcode ("cpl", "c");
1914       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1915       goto release;
1916     }
1917
1918   optype = operandType (IC_LEFT (ic));
1919
1920   /* if float then do float stuff */
1921   if (IS_FLOAT (optype))
1922     {
1923       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1924       goto release;
1925     }
1926
1927   /* otherwise subtract from zero */
1928   size = AOP_SIZE (IC_LEFT (ic));
1929   offset = 0;
1930   _startLazyDPSEvaluation ();
1931   while (size--)
1932     {
1933       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1934       if (!strcmp (l, "a"))
1935         {
1936           if (offset == 0)
1937             SETC;
1938           emitcode ("cpl", "a");
1939           emitcode ("addc", "a,#0");
1940         }
1941       else
1942         {
1943           if (offset == 0)
1944             CLRC;
1945           emitcode ("clr", "a");
1946           emitcode ("subb", "a,%s", l);
1947         }
1948       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1949     }
1950   _endLazyDPSEvaluation ();
1951
1952   /* if any remaining bytes in the result */
1953   /* we just need to propagate the sign   */
1954   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1955     {
1956       emitcode ("rlc", "a");
1957       emitcode ("subb", "a,acc");
1958       while (size--)
1959         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1960     }
1961
1962 release:
1963   /* release the aops */
1964   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1965   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1966 }
1967
1968 /*-----------------------------------------------------------------*/
1969 /* savermask - saves registers in the mask                         */
1970 /*-----------------------------------------------------------------*/
1971 static void savermask(bitVect *rs_mask)
1972 {
1973     int i;
1974     if (options.useXstack) {
1975         if (bitVectBitValue (rs_mask, R0_IDX))
1976             emitcode ("mov", "b,r0");
1977         emitcode ("mov", "r0,%s", spname);
1978         for (i = 0; i < ds390_nRegs; i++) {
1979             if (bitVectBitValue (rs_mask, i)) {
1980                 if (i == R0_IDX)
1981                     emitcode ("mov", "a,b");
1982                 else
1983                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1984                 emitcode ("movx", "@r0,a");
1985                 emitcode ("inc", "r0");
1986             }
1987         }
1988         emitcode ("mov", "%s,r0", spname);
1989         if (bitVectBitValue (rs_mask, R0_IDX))
1990             emitcode ("mov", "r0,b");
1991     } else {
1992         for (i = 0; i < ds390_nRegs; i++) {
1993             if (bitVectBitValue (rs_mask, i))
1994                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1995         }
1996     }
1997 }
1998
1999 /*-----------------------------------------------------------------*/
2000 /* saveRegisters - will look for a call and save the registers     */
2001 /*-----------------------------------------------------------------*/
2002 static void
2003 saveRegisters (iCode * lic)
2004 {
2005   iCode *ic;
2006   bitVect *rsave;
2007
2008   /* look for call */
2009   for (ic = lic; ic; ic = ic->next)
2010     if (ic->op == CALL || ic->op == PCALL)
2011       break;
2012
2013   if (!ic)
2014     {
2015       fprintf (stderr, "found parameter push with no function call\n");
2016       return;
2017     }
2018
2019   /* if the registers have been saved already then
2020      do nothing */
2021   if (ic->regsSaved 
2022       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2023     return ;
2024
2025   /* special case if DPTR alive across a function call then must save it 
2026      even though callee saves */
2027   if (IS_SYMOP(IC_LEFT(ic)) &&
2028       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2029       int i;
2030       rsave = newBitVect(ic->rMask->size);
2031       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2032           if (bitVectBitValue(ic->rMask,i))
2033               rsave = bitVectSetBit(rsave,i);
2034       }
2035       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2036   } else {
2037     /* safe the registers in use at this time but skip the
2038        ones for the result */
2039     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2040                            ds390_rUmaskForOp (IC_RESULT(ic)));
2041   }
2042   ic->regsSaved = 1;
2043   savermask(rsave);
2044 }
2045
2046 /*-----------------------------------------------------------------*/
2047 /* usavermask - restore registers with mask                        */
2048 /*-----------------------------------------------------------------*/
2049 static void unsavermask(bitVect *rs_mask)
2050 {
2051     int i;
2052     if (options.useXstack) {
2053         emitcode ("mov", "r0,%s", spname);
2054         for (i = ds390_nRegs; i >= 0; i--) {
2055             if (bitVectBitValue (rs_mask, i)) {
2056                 emitcode ("dec", "r0");
2057                 emitcode ("movx", "a,@r0");
2058                 if (i == R0_IDX)
2059                     emitcode ("mov", "b,a");
2060                 else
2061                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2062             }       
2063         }
2064         emitcode ("mov", "%s,r0", spname);
2065         if (bitVectBitValue (rs_mask, R0_IDX))
2066             emitcode ("mov", "r0,b");
2067     } else {
2068         for (i = ds390_nRegs; i >= 0; i--) {
2069             if (bitVectBitValue (rs_mask, i))
2070                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2071         }
2072     }
2073 }
2074
2075 /*-----------------------------------------------------------------*/
2076 /* unsaveRegisters - pop the pushed registers                      */
2077 /*-----------------------------------------------------------------*/
2078 static void
2079 unsaveRegisters (iCode * ic)
2080 {
2081   bitVect *rsave;
2082
2083   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2084       int i;
2085       rsave = newBitVect(ic->rMask->size);
2086       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2087           if (bitVectBitValue(ic->rMask,i))
2088               rsave = bitVectSetBit(rsave,i);
2089       }
2090       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2091   } else {
2092     /* restore the registers in use at this time but skip the
2093        ones for the result */
2094     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2095                            ds390_rUmaskForOp (IC_RESULT(ic)));
2096   }
2097   unsavermask(rsave);
2098 }
2099
2100
2101 /*-----------------------------------------------------------------*/
2102 /* pushSide -                */
2103 /*-----------------------------------------------------------------*/
2104 static void
2105 pushSide (operand * oper, int size)
2106 {
2107   int offset = 0;
2108   _startLazyDPSEvaluation ();
2109   while (size--)
2110     {
2111       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2112       if (AOP_TYPE (oper) != AOP_REG &&
2113           AOP_TYPE (oper) != AOP_DIR &&
2114           strcmp (l, "a"))
2115         {
2116           emitcode ("mov", "a,%s", l);
2117           emitcode ("push", "acc");
2118         }
2119       else
2120         emitcode ("push", "%s", l);
2121     }
2122   _endLazyDPSEvaluation ();
2123 }
2124
2125 /*-----------------------------------------------------------------*/
2126 /* assignResultValue -               */
2127 /*-----------------------------------------------------------------*/
2128 static void
2129 assignResultValue (operand * oper)
2130 {
2131   int offset = 0;
2132   int size = AOP_SIZE (oper);
2133   bool pushedAcc = FALSE;
2134
2135   if (size == fReturnSizeDS390)
2136   {
2137       /* I don't think this case can ever happen... */
2138       /* ACC is the last part of this. If writing the result
2139        * uses AC, we must preserve it.
2140        */
2141       if (AOP_NEEDSACC(oper))
2142       {
2143           emitcode(";", "assignResultValue special case for ACC.");
2144           emitcode("push", "acc");
2145           pushedAcc = TRUE;
2146           size--;
2147       }
2148   }
2149     
2150     
2151   _startLazyDPSEvaluation ();
2152   while (size--)
2153     {
2154       aopPut (AOP (oper), fReturn[offset], offset);
2155       offset++;
2156     }
2157   _endLazyDPSEvaluation ();
2158     
2159   if (pushedAcc)
2160     {
2161         emitcode("pop", "acc");
2162         aopPut(AOP(oper), "a", offset);
2163     }
2164 }
2165
2166
2167 /*-----------------------------------------------------------------*/
2168 /* genXpush - pushes onto the external stack                       */
2169 /*-----------------------------------------------------------------*/
2170 static void
2171 genXpush (iCode * ic)
2172 {
2173   asmop *aop = newAsmop (0);
2174   regs *r;
2175   int size, offset = 0;
2176
2177   D (emitcode (";", "genXpush ");
2178     );
2179
2180   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2181   r = getFreePtr (ic, &aop, FALSE);
2182
2183
2184   emitcode ("mov", "%s,_spx", r->name);
2185
2186   size = AOP_SIZE (IC_LEFT (ic));
2187   _startLazyDPSEvaluation ();
2188   while (size--)
2189     {
2190
2191       MOVA (aopGet (AOP (IC_LEFT (ic)),
2192                         offset++, FALSE, FALSE, NULL));
2193       emitcode ("movx", "@%s,a", r->name);
2194       emitcode ("inc", "%s", r->name);
2195
2196     }
2197   _endLazyDPSEvaluation ();
2198
2199
2200   emitcode ("mov", "_spx,%s", r->name);
2201
2202   freeAsmop (NULL, aop, ic, TRUE);
2203   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2204 }
2205
2206 /*-----------------------------------------------------------------*/
2207 /* genIpush - generate code for pushing this gets a little complex  */
2208 /*-----------------------------------------------------------------*/
2209 static void
2210 genIpush (iCode * ic)
2211 {
2212   int size, offset = 0;
2213   char *l;
2214
2215   D (emitcode (";", "genIpush ");
2216     );
2217
2218   /* if this is not a parm push : ie. it is spill push
2219      and spill push is always done on the local stack */
2220   if (!ic->parmPush)
2221     {
2222
2223       /* and the item is spilt then do nothing */
2224       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2225         return;
2226
2227       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2228       size = AOP_SIZE (IC_LEFT (ic));
2229       /* push it on the stack */
2230       _startLazyDPSEvaluation ();
2231       while (size--)
2232         {
2233           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2234           if (*l == '#')
2235             {
2236               MOVA (l);
2237               l = "acc";
2238             }
2239           emitcode ("push", "%s", l);
2240         }
2241       _endLazyDPSEvaluation ();
2242       return;
2243     }
2244
2245   /* this is a paramter push: in this case we call
2246      the routine to find the call and save those
2247      registers that need to be saved */
2248   saveRegisters (ic);
2249
2250   /* if use external stack then call the external
2251      stack pushing routine */
2252   if (options.useXstack)
2253     {
2254       genXpush (ic);
2255       return;
2256     }
2257
2258   /* then do the push */
2259   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2260
2261   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2262   size = AOP_SIZE (IC_LEFT (ic));
2263
2264   _startLazyDPSEvaluation ();
2265   while (size--)
2266     {
2267       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2268       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2269           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2270           strcmp (l, "acc"))
2271         {
2272           emitcode ("mov", "a,%s", l);
2273           emitcode ("push", "acc");
2274         }
2275       else
2276         {
2277             emitcode ("push", "%s", l);
2278         }
2279     }
2280   _endLazyDPSEvaluation ();
2281
2282   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2283 }
2284
2285 /*-----------------------------------------------------------------*/
2286 /* genIpop - recover the registers: can happen only for spilling   */
2287 /*-----------------------------------------------------------------*/
2288 static void
2289 genIpop (iCode * ic)
2290 {
2291   int size, offset;
2292
2293   D (emitcode (";", "genIpop ");
2294     );
2295
2296
2297   /* if the temp was not pushed then */
2298   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2299     return;
2300
2301   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2302   size = AOP_SIZE (IC_LEFT (ic));
2303   offset = (size - 1);
2304   _startLazyDPSEvaluation ();
2305   while (size--)
2306     {
2307       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2308                                      FALSE, TRUE, NULL));
2309     }
2310   _endLazyDPSEvaluation ();
2311
2312   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2313 }
2314
2315 /*-----------------------------------------------------------------*/
2316 /* unsaveRBank - restores the resgister bank from stack            */
2317 /*-----------------------------------------------------------------*/
2318 static void
2319 unsaveRBank (int bank, iCode * ic, bool popPsw)
2320 {
2321   int i;
2322   asmop *aop = NULL;
2323   regs *r = NULL;
2324
2325   if (options.useXstack)
2326   {
2327       if (!ic)
2328       {
2329           /* Assume r0 is available for use. */
2330           r = ds390_regWithIdx (R0_IDX);;          
2331       } 
2332       else
2333       {
2334           aop = newAsmop (0);
2335           r = getFreePtr (ic, &aop, FALSE);
2336       }
2337       emitcode ("mov", "%s,_spx", r->name);      
2338   }
2339   
2340   if (popPsw)
2341     {
2342       if (options.useXstack)
2343       {
2344           emitcode ("movx", "a,@%s", r->name);
2345           emitcode ("mov", "psw,a");
2346           emitcode ("dec", "%s", r->name);
2347         }
2348       else
2349       {
2350         emitcode ("pop", "psw");
2351       }
2352     }
2353
2354   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2355     {
2356       if (options.useXstack)
2357         {
2358           emitcode ("movx", "a,@%s", r->name);
2359           emitcode ("mov", "(%s+%d),a",
2360                     regs390[i].base, 8 * bank + regs390[i].offset);
2361           emitcode ("dec", "%s", r->name);
2362
2363         }
2364       else
2365         emitcode ("pop", "(%s+%d)",
2366                   regs390[i].base, 8 * bank + regs390[i].offset);
2367     }
2368
2369   if (options.useXstack)
2370     {
2371       emitcode ("mov", "_spx,%s", r->name);
2372     }
2373     
2374   if (aop)
2375   {
2376       freeAsmop (NULL, aop, ic, TRUE);  
2377   }    
2378 }
2379
2380 /*-----------------------------------------------------------------*/
2381 /* saveRBank - saves an entire register bank on the stack          */
2382 /*-----------------------------------------------------------------*/
2383 static void
2384 saveRBank (int bank, iCode * ic, bool pushPsw)
2385 {
2386   int i;
2387   asmop *aop = NULL;
2388   regs *r = NULL;
2389
2390   if (options.useXstack)
2391     {
2392         if (!ic)
2393         {
2394           /* Assume r0 is available for use. */
2395                   r = ds390_regWithIdx (R0_IDX);;
2396         }
2397         else
2398         {
2399           aop = newAsmop (0);
2400           r = getFreePtr (ic, &aop, FALSE);
2401         }
2402         emitcode ("mov", "%s,_spx", r->name);    
2403     }
2404
2405   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2406     {
2407       if (options.useXstack)
2408         {
2409           emitcode ("inc", "%s", r->name);
2410           emitcode ("mov", "a,(%s+%d)",
2411                     regs390[i].base, 8 * bank + regs390[i].offset);
2412           emitcode ("movx", "@%s,a", r->name);
2413         }
2414       else
2415         emitcode ("push", "(%s+%d)",
2416                   regs390[i].base, 8 * bank + regs390[i].offset);
2417     }
2418
2419   if (pushPsw)
2420     {
2421       if (options.useXstack)
2422         {
2423           emitcode ("mov", "a,psw");
2424           emitcode ("movx", "@%s,a", r->name);
2425           emitcode ("inc", "%s", r->name);
2426           emitcode ("mov", "_spx,%s", r->name);
2427         }
2428       else
2429       {
2430         emitcode ("push", "psw");
2431       }
2432
2433       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2434     }
2435   
2436   if (aop)
2437   {
2438        freeAsmop (NULL, aop, ic, TRUE);
2439   }    
2440     
2441   if (ic)
2442   {  
2443       ic->bankSaved = 1;
2444   }
2445 }
2446
2447 /*-----------------------------------------------------------------*/
2448 /* genSend - gen code for SEND                                     */
2449 /*-----------------------------------------------------------------*/
2450 static void genSend(set *sendSet)
2451 {
2452     iCode *sic;
2453     int sendCount = 0 ;
2454     static int rb1_count = 0;
2455
2456     for (sic = setFirstItem (sendSet); sic;
2457          sic = setNextItem (sendSet)) {     
2458         int size, offset = 0;
2459         
2460         size=getSize(operandType(IC_LEFT(sic)));
2461         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2462         if (sendCount == 0) { /* first parameter */
2463             // we know that dpl(hxb) is the result, so
2464             rb1_count = 0 ;
2465             _startLazyDPSEvaluation ();
2466             if (size>1) {
2467                 aopOp (IC_LEFT (sic), sic, FALSE, 
2468                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2469             } else {
2470                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2471             }
2472             while (size--) {
2473                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2474                                   FALSE, FALSE, NULL);
2475                 if (strcmp (l, fReturn[offset])) {
2476                     emitcode ("mov", "%s,%s",
2477                               fReturn[offset],
2478                               l);
2479                 }
2480                 offset++;
2481             }
2482             _endLazyDPSEvaluation ();
2483             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2484             rb1_count =0;
2485         } else { /* if more parameter in registers */
2486             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2487             while (size--) {
2488                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2489                                                                 FALSE, FALSE, NULL));
2490             }
2491             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2492         }
2493         sendCount++;
2494     }
2495 }
2496
2497 static void
2498 adjustEsp(const char *reg)
2499 {
2500     emitcode ("anl","%s,#3", reg);
2501     if (TARGET_IS_DS400)
2502     {
2503         emitcode ("orl","%s,#!constbyte",
2504                   reg,
2505                   (options.stack_loc >> 8) & 0xff);
2506     }
2507 }
2508
2509 /*-----------------------------------------------------------------*/
2510 /* genCall - generates a call statement                            */
2511 /*-----------------------------------------------------------------*/
2512 static void
2513 genCall (iCode * ic)
2514 {
2515   sym_link *dtype;
2516   bool restoreBank = FALSE;
2517   bool swapBanks = FALSE;
2518
2519   D (emitcode (";", "genCall "););
2520
2521   /* if we are calling a not _naked function that is not using
2522      the same register bank then we need to save the
2523      destination registers on the stack */
2524   dtype = operandType (IC_LEFT (ic));
2525   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2526       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2527       IFFUNC_ISISR (currFunc->type))
2528   {
2529       if (!ic->bankSaved) 
2530       {
2531            /* This is unexpected; the bank should have been saved in
2532             * genFunction.
2533             */
2534            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2535            restoreBank = TRUE;
2536       }
2537       swapBanks = TRUE;
2538   }
2539   
2540     /* if caller saves & we have not saved then */
2541     if (!ic->regsSaved)
2542       saveRegisters (ic);
2543   
2544   /* if send set is not empty the assign */
2545   /* We've saved all the registers we care about;
2546   * therefore, we may clobber any register not used
2547   * in the calling convention (i.e. anything not in
2548   * fReturn.
2549   */
2550   if (_G.sendSet)
2551     {
2552         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2553             genSend(reverseSet(_G.sendSet));
2554         } else {
2555             genSend(_G.sendSet);
2556         }
2557       _G.sendSet = NULL;
2558     }  
2559     
2560   if (swapBanks)
2561   {
2562         emitcode ("mov", "psw,#!constbyte", 
2563            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2564   }
2565
2566   /* make the call */
2567   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2568                             OP_SYMBOL (IC_LEFT (ic))->rname :
2569                             OP_SYMBOL (IC_LEFT (ic))->name));
2570
2571   if (swapBanks)
2572   {
2573        emitcode ("mov", "psw,#!constbyte", 
2574           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2575   }
2576
2577   /* if we need assign a result value */
2578   if ((IS_ITEMP (IC_RESULT (ic)) &&
2579        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2580         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2581         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2582       IS_TRUE_SYMOP (IC_RESULT (ic)))
2583     {
2584       if (isOperandInFarSpace (IC_RESULT (ic))
2585           && getSize (operandType (IC_RESULT (ic))) <= 2)
2586         {
2587           int size = getSize (operandType (IC_RESULT (ic)));
2588
2589           /* Special case for 1 or 2 byte return in far space. */
2590           MOVA (fReturn[0]);
2591           if (size > 1)
2592             {
2593               emitcode ("mov", "b,%s", fReturn[1]);
2594             }
2595
2596           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2597           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2598
2599           if (size > 1)
2600             {
2601               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2602             }
2603           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2604         }
2605       else
2606         {
2607           _G.accInUse++;
2608           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2609           _G.accInUse--;
2610
2611           assignResultValue (IC_RESULT (ic));
2612
2613           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2614         }
2615     }
2616
2617   /* adjust the stack for parameters if
2618      required */
2619   if (ic->parmBytes) {
2620       int i;
2621       if (options.stack10bit) {
2622           if (ic->parmBytes <= 10) {
2623               emitcode(";","stack adjustment for parms");
2624               for (i=0; i < ic->parmBytes ; i++) {
2625                   emitcode("pop","acc");
2626               }
2627           } else {            
2628               PROTECT_SP;
2629               emitcode ("clr","c");
2630               emitcode ("mov","a,sp");
2631               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2632               emitcode ("mov","sp,a");
2633               emitcode ("mov","a,esp");
2634               adjustEsp("a");
2635               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2636               emitcode ("mov","esp,a");   
2637               UNPROTECT_SP;
2638           }
2639       } else {
2640           if (ic->parmBytes > 3) {
2641               emitcode ("mov", "a,%s", spname);
2642               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2643               emitcode ("mov", "%s,a", spname);
2644           } else
2645               for (i = 0; i < ic->parmBytes; i++)
2646                   emitcode ("dec", "%s", spname);
2647       }
2648   }
2649
2650   /* if we hade saved some registers then unsave them */
2651   if (ic->regsSaved)
2652     unsaveRegisters (ic);
2653
2654   /* if register bank was saved then pop them */
2655   if (restoreBank)
2656     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2657 }
2658
2659 /*-----------------------------------------------------------------*/
2660 /* genPcall - generates a call by pointer statement                */
2661 /*-----------------------------------------------------------------*/
2662 static void
2663 genPcall (iCode * ic)
2664 {
2665   sym_link *dtype;
2666   symbol *rlbl = newiTempLabel (NULL);
2667   bool restoreBank=FALSE;
2668
2669   D (emitcode (";", "genPcall ");
2670     );
2671
2672
2673   /* if caller saves & we have not saved then */
2674   if (!ic->regsSaved)
2675     saveRegisters (ic);
2676
2677   /* if we are calling a function that is not using
2678      the same register bank then we need to save the
2679      destination registers on the stack */
2680   dtype = operandType (IC_LEFT (ic));
2681   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2682       IFFUNC_ISISR (currFunc->type) &&
2683       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2684     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2685     restoreBank=TRUE;
2686   }
2687
2688   /* push the return address on to the stack */
2689   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2690   emitcode ("push", "acc");
2691   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2692   emitcode ("push", "acc");
2693
2694   if (options.model == MODEL_FLAT24)
2695     {
2696       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2697       emitcode ("push", "acc");
2698     }
2699
2700   /* now push the calling address */
2701   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2702
2703   pushSide (IC_LEFT (ic), FPTRSIZE);
2704
2705   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2706
2707   /* if send set is not empty the assign */
2708   if (_G.sendSet)
2709     {
2710         genSend(reverseSet(_G.sendSet));
2711         _G.sendSet = NULL;
2712     }
2713
2714   emitcode ("ret", "");
2715   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2716
2717
2718   /* if we need assign a result value */
2719   if ((IS_ITEMP (IC_RESULT (ic)) &&
2720        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2721         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2722       IS_TRUE_SYMOP (IC_RESULT (ic)))
2723     {
2724
2725       _G.accInUse++;
2726       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2727       _G.accInUse--;
2728
2729       assignResultValue (IC_RESULT (ic));
2730
2731       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2732     }
2733
2734   /* adjust the stack for parameters if
2735      required */
2736   if (ic->parmBytes)
2737     {
2738       int i;
2739       if (options.stack10bit) {
2740           if (ic->parmBytes <= 10) {
2741               emitcode(";","stack adjustment for parms");
2742               for (i=0; i < ic->parmBytes ; i++) {
2743                   emitcode("pop","acc");
2744               }
2745           } else {            
2746               PROTECT_SP;
2747               emitcode ("clr","c");
2748               emitcode ("mov","a,sp");
2749               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2750               emitcode ("mov","sp,a");
2751               emitcode ("mov","a,esp");
2752               adjustEsp("a");
2753               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2754               emitcode ("mov","esp,a");   
2755               UNPROTECT_SP;
2756           }
2757       } else {
2758           if (ic->parmBytes > 3) {
2759               emitcode ("mov", "a,%s", spname);
2760               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2761               emitcode ("mov", "%s,a", spname);
2762           }
2763           else
2764               for (i = 0; i < ic->parmBytes; i++)
2765                   emitcode ("dec", "%s", spname);
2766           
2767       }
2768     }
2769   /* if register bank was saved then unsave them */
2770   if (restoreBank)
2771     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2772   
2773   /* if we hade saved some registers then
2774      unsave them */
2775   if (ic->regsSaved)
2776     unsaveRegisters (ic);
2777
2778 }
2779
2780 /*-----------------------------------------------------------------*/
2781 /* resultRemat - result  is rematerializable                       */
2782 /*-----------------------------------------------------------------*/
2783 static int
2784 resultRemat (iCode * ic)
2785 {
2786   if (SKIP_IC (ic) || ic->op == IFX)
2787     return 0;
2788
2789   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2790     {
2791       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2792       if (sym->remat && !POINTER_SET (ic))
2793         return 1;
2794     }
2795
2796   return 0;
2797 }
2798
2799 #if defined(__BORLANDC__) || defined(_MSC_VER)
2800 #define STRCASECMP stricmp
2801 #else
2802 #define STRCASECMP strcasecmp
2803 #endif
2804
2805 /*-----------------------------------------------------------------*/
2806 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2807 /*-----------------------------------------------------------------*/
2808 static int
2809 regsCmp(void *p1, void *p2)
2810 {
2811   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2812 }
2813
2814 static bool
2815 inExcludeList (char *s)
2816 {
2817   const char *p = setFirstItem(options.excludeRegsSet);
2818
2819   if (p == NULL || STRCASECMP(p, "none") == 0)
2820     return FALSE;
2821
2822
2823   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2824 }
2825
2826 /*-----------------------------------------------------------------*/
2827 /* genFunction - generated code for function entry                 */
2828 /*-----------------------------------------------------------------*/
2829 static void
2830 genFunction (iCode * ic)
2831 {
2832   symbol *sym;
2833   sym_link *ftype;
2834   bool   switchedPSW = FALSE;
2835
2836   D (emitcode (";", "genFunction "););
2837
2838   _G.nRegsSaved = 0;
2839   /* create the function header */
2840   emitcode (";", "-----------------------------------------");
2841   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2842   emitcode (";", "-----------------------------------------");
2843
2844   emitcode ("", "%s:", sym->rname);
2845   ftype = operandType (IC_LEFT (ic));
2846
2847   if (IFFUNC_ISNAKED(ftype))
2848   {
2849       emitcode(";", "naked function: no prologue.");
2850       return;
2851   }
2852   
2853   if (options.stack_probe) 
2854       emitcode ("lcall","__stack_probe");
2855   /* if critical function then turn interrupts off */
2856   if (IFFUNC_ISCRITICAL (ftype))
2857     emitcode ("clr", "ea");
2858
2859   /* here we need to generate the equates for the
2860      register bank if required */
2861   if (FUNC_REGBANK (ftype) != rbank)
2862     {
2863       int i;
2864
2865       rbank = FUNC_REGBANK (ftype);
2866       for (i = 0; i < ds390_nRegs; i++)
2867         {
2868           if (regs390[i].print) {
2869               if (strcmp (regs390[i].base, "0") == 0)
2870                   emitcode ("", "%s !equ !constbyte",
2871                             regs390[i].dname,
2872                             8 * rbank + regs390[i].offset);
2873               else
2874                   emitcode ("", "%s !equ %s + !constbyte",
2875                             regs390[i].dname,
2876                             regs390[i].base,
2877                             8 * rbank + regs390[i].offset);
2878           }
2879         }
2880     }
2881
2882   /* if this is an interrupt service routine then
2883      save acc, b, dpl, dph  */
2884   if (IFFUNC_ISISR (sym->type))
2885       { /* is ISR */
2886       if (!inExcludeList ("acc"))
2887         emitcode ("push", "acc");
2888       if (!inExcludeList ("b"))
2889         emitcode ("push", "b");
2890       if (!inExcludeList ("dpl"))
2891         emitcode ("push", "dpl");
2892       if (!inExcludeList ("dph"))
2893         emitcode ("push", "dph");
2894       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2895         {
2896           emitcode ("push", "dpx");
2897           /* Make sure we're using standard DPTR */
2898           emitcode ("push", "dps");
2899           emitcode ("mov", "dps,#0");
2900           if (options.stack10bit)
2901             {
2902               /* This ISR could conceivably use DPTR2. Better save it. */
2903               emitcode ("push", "dpl1");
2904               emitcode ("push", "dph1");
2905               emitcode ("push", "dpx1");
2906               emitcode ("push",  DP2_RESULT_REG);
2907             }
2908         }
2909       /* if this isr has no bank i.e. is going to
2910          run with bank 0 , then we need to save more
2911          registers :-) */
2912       if (!FUNC_REGBANK (sym->type))
2913         {
2914             int i;
2915
2916           /* if this function does not call any other
2917              function then we can be economical and
2918              save only those registers that are used */
2919           if (!IFFUNC_HASFCALL(sym->type))
2920             {
2921
2922               /* if any registers used */
2923               if (sym->regsUsed)
2924                 {
2925                   /* save the registers used */
2926                   for (i = 0; i < sym->regsUsed->size; i++)
2927                     {
2928                       if (bitVectBitValue (sym->regsUsed, i) ||
2929                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2930                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2931                     }
2932                 }
2933
2934             }
2935           else
2936             {
2937               /* this function has  a function call cannot
2938                  determines register usage so we will have to push the
2939                  entire bank */
2940               saveRBank (0, ic, FALSE);
2941               if (options.parms_in_bank1) {
2942                   for (i=0; i < 8 ; i++ ) {
2943                       emitcode ("push","%s",rb1regs[i]);
2944                   }
2945               }
2946             }
2947         }
2948         else
2949         {
2950             /* This ISR uses a non-zero bank.
2951              *
2952              * We assume that the bank is available for our
2953              * exclusive use.
2954              *
2955              * However, if this ISR calls a function which uses some
2956              * other bank, we must save that bank entirely.
2957              */
2958             unsigned long banksToSave = 0;
2959             
2960             if (IFFUNC_HASFCALL(sym->type))
2961             {
2962
2963 #define MAX_REGISTER_BANKS 4
2964
2965                 iCode *i;
2966                 int ix;
2967
2968                 for (i = ic; i; i = i->next)
2969                 {
2970                     if (i->op == ENDFUNCTION)
2971                     {
2972                         /* we got to the end OK. */
2973                         break;
2974                     }
2975                     
2976                     if (i->op == CALL)
2977                     {
2978                         sym_link *dtype;
2979                         
2980                         dtype = operandType (IC_LEFT(i));
2981                         if (dtype 
2982                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2983                         {
2984                              /* Mark this bank for saving. */
2985                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2986                              {
2987                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2988                              }
2989                              else
2990                              {
2991                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2992                              }
2993                              
2994                              /* And note that we don't need to do it in 
2995                               * genCall.
2996                               */
2997                              i->bankSaved = 1;
2998                         }
2999                     }
3000                     if (i->op == PCALL)
3001                     {
3002                         /* This is a mess; we have no idea what
3003                          * register bank the called function might
3004                          * use.
3005                          *
3006                          * The only thing I can think of to do is
3007                          * throw a warning and hope.
3008                          */
3009                         werror(W_FUNCPTR_IN_USING_ISR);   
3010                     }
3011                 }
3012
3013                 if (banksToSave && options.useXstack)
3014                 {
3015                     /* Since we aren't passing it an ic, 
3016                      * saveRBank will assume r0 is available to abuse.
3017                      *
3018                      * So switch to our (trashable) bank now, so
3019                      * the caller's R0 isn't trashed.
3020                      */
3021                     emitcode ("push", "psw");
3022                     emitcode ("mov", "psw,#!constbyte", 
3023                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3024                     switchedPSW = TRUE;
3025                 }
3026                 
3027                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3028                 {
3029                      if (banksToSave & (1 << ix))
3030                      {
3031                          saveRBank(ix, NULL, FALSE);
3032                      }
3033                 }
3034             }
3035             // TODO: this needs a closer look
3036             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3037         }
3038     }
3039   else
3040     {
3041       /* if callee-save to be used for this function
3042          then save the registers being used in this function */
3043       if (IFFUNC_CALLEESAVES(sym->type))
3044         {
3045           int i;
3046
3047           /* if any registers used */
3048           if (sym->regsUsed)
3049             {
3050               /* save the registers used */
3051               for (i = 0; i < sym->regsUsed->size; i++)
3052                 {
3053                   if (bitVectBitValue (sym->regsUsed, i) ||
3054                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3055                     {
3056                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3057                       _G.nRegsSaved++;
3058                     }
3059                 }
3060             }
3061         }
3062     }
3063
3064   /* set the register bank to the desired value */
3065   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3066    && !switchedPSW)
3067     {
3068       emitcode ("push", "psw");
3069       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3070     }
3071
3072   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3073        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3074       if (options.stack10bit) {
3075           emitcode ("push","_bpx");
3076           emitcode ("push","_bpx+1");
3077           emitcode ("mov","_bpx,%s",spname);
3078           emitcode ("mov","_bpx+1,esp");
3079           adjustEsp("_bpx+1");
3080       } else {
3081           if (options.useXstack) {
3082               emitcode ("mov", "r0,%s", spname);
3083               emitcode ("mov", "a,_bp");
3084               emitcode ("movx", "@r0,a");
3085               emitcode ("inc", "%s", spname);
3086           } else {
3087               /* set up the stack */
3088               emitcode ("push", "_bp"); /* save the callers stack  */
3089           }
3090           emitcode ("mov", "_bp,%s", spname);
3091       }
3092   }
3093
3094   /* adjust the stack for the function */
3095   if (sym->stack) {
3096       int i = sym->stack;
3097       if (options.stack10bit) {
3098           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3099           assert (sym->recvSize <= 4);
3100           if (sym->stack <= 8) {
3101               while (i--) emitcode ("push","acc");
3102           } else {
3103               PROTECT_SP;
3104               emitcode ("mov","a,sp");
3105               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3106               emitcode ("mov","sp,a");
3107               emitcode ("mov","a,esp");
3108               adjustEsp("a");
3109               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3110               emitcode ("mov","esp,a");
3111               UNPROTECT_SP;
3112           }
3113       } else {
3114           if (i > 256)
3115               werror (W_STACK_OVERFLOW, sym->name);
3116           
3117           if (i > 3 && sym->recvSize < 4) {
3118               
3119               emitcode ("mov", "a,sp");
3120               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3121               emitcode ("mov", "sp,a");
3122               
3123           } else
3124               while (i--)
3125                   emitcode ("inc", "sp");
3126       }
3127   }
3128
3129   if (sym->xstack)
3130     {
3131
3132       emitcode ("mov", "a,_spx");
3133       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3134       emitcode ("mov", "_spx,a");
3135     }
3136
3137 }
3138
3139 /*-----------------------------------------------------------------*/
3140 /* genEndFunction - generates epilogue for functions               */
3141 /*-----------------------------------------------------------------*/
3142 static void
3143 genEndFunction (iCode * ic)
3144 {
3145   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3146
3147   D (emitcode (";", "genEndFunction "););
3148
3149   if (IFFUNC_ISNAKED(sym->type))
3150   {
3151       emitcode(";", "naked function: no epilogue.");
3152       return;
3153   }
3154
3155   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3156        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3157
3158       if (options.stack10bit) {
3159           PROTECT_SP;     
3160           emitcode ("mov", "sp,_bpx", spname);
3161           emitcode ("mov", "esp,_bpx+1", spname);
3162           UNPROTECT_SP;
3163       } else {
3164           emitcode ("mov", "%s,_bp", spname);
3165       }
3166   }
3167
3168   /* if use external stack but some variables were
3169      added to the local stack then decrement the
3170      local stack */
3171   if (options.useXstack && sym->stack) {
3172       emitcode ("mov", "a,sp");
3173       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3174       emitcode ("mov", "sp,a");
3175   }
3176
3177
3178   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3179        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3180
3181       if (options.useXstack) {
3182           emitcode ("mov", "r0,%s", spname);
3183           emitcode ("movx", "a,@r0");
3184           emitcode ("mov", "_bp,a");
3185           emitcode ("dec", "%s", spname);
3186       } else {
3187           if (options.stack10bit) {
3188               emitcode ("pop", "_bpx+1");
3189               emitcode ("pop", "_bpx");
3190           } else {
3191               emitcode ("pop", "_bp");
3192           }
3193       }
3194   }
3195
3196   /* restore the register bank  */
3197   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3198   {
3199     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3200      || !options.useXstack)
3201     {
3202         /* Special case of ISR using non-zero bank with useXstack
3203          * is handled below.
3204          */
3205         emitcode ("pop", "psw");
3206     }
3207   } 
3208
3209   if (IFFUNC_ISISR (sym->type))
3210       { /* is ISR */  
3211
3212       /* now we need to restore the registers */
3213       /* if this isr has no bank i.e. is going to
3214          run with bank 0 , then we need to save more
3215          registers :-) */
3216       if (!FUNC_REGBANK (sym->type))
3217         {
3218             int i;
3219           /* if this function does not call any other
3220              function then we can be economical and
3221              save only those registers that are used */
3222           if (!IFFUNC_HASFCALL(sym->type))
3223             {
3224
3225               /* if any registers used */
3226               if (sym->regsUsed)
3227                 {
3228                   /* save the registers used */
3229                   for (i = sym->regsUsed->size; i >= 0; i--)
3230                     {
3231                       if (bitVectBitValue (sym->regsUsed, i) ||
3232                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3233                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3234                     }
3235                 }
3236
3237             }
3238           else
3239             {
3240               /* this function has  a function call cannot
3241                  determines register usage so we will have to pop the
3242                  entire bank */
3243               if (options.parms_in_bank1) {
3244                   for (i = 7 ; i >= 0 ; i-- ) {
3245                       emitcode ("pop","%s",rb1regs[i]);
3246                   }
3247               }
3248               unsaveRBank (0, ic, FALSE);
3249             }
3250         }
3251         else
3252         {
3253             /* This ISR uses a non-zero bank.
3254              *
3255              * Restore any register banks saved by genFunction
3256              * in reverse order.
3257              */
3258             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3259             int ix;
3260           
3261             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3262             {
3263                 if (savedBanks & (1 << ix))
3264                 {
3265                     unsaveRBank(ix, NULL, FALSE);
3266                 }
3267             }
3268             
3269             if (options.useXstack)
3270             {
3271                 /* Restore bank AFTER calling unsaveRBank,
3272                  * since it can trash r0.
3273                  */
3274                 emitcode ("pop", "psw");
3275             }
3276         }
3277
3278       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3279         {
3280           if (options.stack10bit)
3281             {
3282               emitcode ("pop", DP2_RESULT_REG);
3283               emitcode ("pop", "dpx1");
3284               emitcode ("pop", "dph1");
3285               emitcode ("pop", "dpl1");
3286             }
3287           emitcode ("pop", "dps");
3288           emitcode ("pop", "dpx");
3289         }
3290       if (!inExcludeList ("dph"))
3291         emitcode ("pop", "dph");
3292       if (!inExcludeList ("dpl"))
3293         emitcode ("pop", "dpl");
3294       if (!inExcludeList ("b"))
3295         emitcode ("pop", "b");
3296       if (!inExcludeList ("acc"))
3297         emitcode ("pop", "acc");
3298
3299       if (IFFUNC_ISCRITICAL (sym->type))
3300         emitcode ("setb", "ea");
3301
3302       /* if debug then send end of function */
3303       if (options.debug && currFunc) {
3304           _G.debugLine = 1;
3305           emitcode ("", "C$%s$%d$%d$%d ==.",
3306                     FileBaseName (ic->filename), currFunc->lastLine,
3307                     ic->level, ic->block);
3308           if (IS_STATIC (currFunc->etype))
3309             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3310           else
3311             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3312           _G.debugLine = 0;
3313         }
3314
3315       emitcode ("reti", "");
3316     }
3317   else
3318     {
3319       if (IFFUNC_ISCRITICAL (sym->type))
3320         emitcode ("setb", "ea");
3321
3322       if (IFFUNC_CALLEESAVES(sym->type))
3323         {
3324           int i;
3325
3326           /* if any registers used */
3327           if (sym->regsUsed)
3328             {
3329               /* save the registers used */
3330               for (i = sym->regsUsed->size; i >= 0; i--)
3331                 {
3332                   if (bitVectBitValue (sym->regsUsed, i) ||
3333                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3334                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3335                 }
3336             }
3337
3338         }
3339
3340       /* if debug then send end of function */
3341       if (options.debug && currFunc)
3342         {
3343           _G.debugLine = 1;
3344           emitcode ("", "C$%s$%d$%d$%d ==.",
3345                     FileBaseName (ic->filename), currFunc->lastLine,
3346                     ic->level, ic->block);
3347           if (IS_STATIC (currFunc->etype))
3348             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3349           else
3350             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3351           _G.debugLine = 0;
3352         }
3353
3354       emitcode ("ret", "");
3355     }
3356
3357 }
3358
3359 /*-----------------------------------------------------------------*/
3360 /* genJavaNativeRet - generate code for return JavaNative          */
3361 /*-----------------------------------------------------------------*/
3362 static void genJavaNativeRet(iCode *ic)
3363 {
3364     int i, size;
3365
3366     aopOp (IC_LEFT (ic), ic, FALSE, 
3367            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3368     size = AOP_SIZE (IC_LEFT (ic));
3369
3370     assert (size <= 4);
3371
3372     /* it is assigned to GPR0-R3 then push them */
3373     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3374         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3375         for (i = 0 ; i < size ; i++ ) {
3376             emitcode ("push","%s",
3377                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3378         }
3379         for (i = (size-1) ; i >= 0 ; i--) {
3380             emitcode ("pop","a%s",javaRet[i]);
3381         }
3382     } else {
3383         for (i = 0 ; i < size ; i++) 
3384             emitcode ("mov","%s,%s",javaRet[i],
3385                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3386     }
3387     for (i = size ; i < 4 ; i++ )
3388             emitcode ("mov","%s,#0",javaRet[i]);
3389     return;
3390 }
3391
3392 /*-----------------------------------------------------------------*/
3393 /* genRet - generate code for return statement                     */
3394 /*-----------------------------------------------------------------*/
3395 static void
3396 genRet (iCode * ic)
3397 {
3398   int size, offset = 0, pushed = 0;
3399
3400   D (emitcode (";", "genRet "););
3401
3402   /* if we have no return value then
3403      just generate the "ret" */
3404   if (!IC_LEFT (ic))
3405     goto jumpret;
3406
3407   /* if this is a JavaNative function then return 
3408      value in different register */
3409   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3410       genJavaNativeRet(ic);
3411       goto jumpret;
3412   }
3413   /* we have something to return then
3414      move the return value into place */
3415   aopOp (IC_LEFT (ic), ic, FALSE, 
3416          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3417   size = AOP_SIZE (IC_LEFT (ic));
3418
3419   _startLazyDPSEvaluation ();
3420   while (size--)
3421     {
3422       char *l;
3423       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3424         {
3425           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3426                       FALSE, TRUE, NULL);
3427           emitcode ("push", "%s", l);
3428           pushed++;
3429         }
3430       else
3431         {
3432           /* Since A is the last element of fReturn,
3433            * is is OK to clobber it in the aopGet.
3434            */
3435           l = aopGet (AOP (IC_LEFT (ic)), offset,
3436                       FALSE, FALSE, NULL);
3437           if (strcmp (fReturn[offset], l))
3438             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3439         }
3440     }
3441   _endLazyDPSEvaluation ();
3442
3443   if (pushed)
3444     {
3445       while (pushed)
3446         {
3447           pushed--;
3448           if (strcmp (fReturn[pushed], "a"))
3449             emitcode ("pop", fReturn[pushed]);
3450           else
3451             emitcode ("pop", "acc");
3452         }
3453     }
3454   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3455
3456 jumpret:
3457   /* generate a jump to the return label
3458      if the next is not the return statement */
3459   if (!(ic->next && ic->next->op == LABEL &&
3460         IC_LABEL (ic->next) == returnLabel))
3461
3462     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3463
3464 }
3465
3466 /*-----------------------------------------------------------------*/
3467 /* genLabel - generates a label                                    */
3468 /*-----------------------------------------------------------------*/
3469 static void
3470 genLabel (iCode * ic)
3471 {
3472   /* special case never generate */
3473   if (IC_LABEL (ic) == entryLabel)
3474     return;
3475
3476   D (emitcode (";", "genLabel ");
3477     );
3478
3479   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3480 }
3481
3482 /*-----------------------------------------------------------------*/
3483 /* genGoto - generates a ljmp                                      */
3484 /*-----------------------------------------------------------------*/
3485 static void
3486 genGoto (iCode * ic)
3487 {
3488   D (emitcode (";", "genGoto ");
3489     );
3490   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3491 }
3492
3493 /*-----------------------------------------------------------------*/
3494 /* findLabelBackwards: walks back through the iCode chain looking  */
3495 /* for the given label. Returns number of iCode instructions     */
3496 /* between that label and given ic.          */
3497 /* Returns zero if label not found.          */
3498 /*-----------------------------------------------------------------*/
3499 static int
3500 findLabelBackwards (iCode * ic, int key)
3501 {
3502   int count = 0;
3503
3504   while (ic->prev)
3505     {
3506       ic = ic->prev;
3507       count++;
3508
3509       /* If we have any pushes or pops, we cannot predict the distance.
3510          I don't like this at all, this should be dealt with in the 
3511          back-end */
3512       if (ic->op == IPUSH || ic->op == IPOP) {
3513         return 0;
3514       }
3515
3516       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3517         {
3518           /* printf("findLabelBackwards = %d\n", count); */
3519           return count;
3520         }
3521     }
3522
3523   return 0;
3524 }
3525
3526 /*-----------------------------------------------------------------*/
3527 /* genPlusIncr :- does addition with increment if possible         */
3528 /*-----------------------------------------------------------------*/
3529 static bool
3530 genPlusIncr (iCode * ic)
3531 {
3532   unsigned int icount;
3533   unsigned int size = getDataSize (IC_RESULT (ic));
3534
3535   /* will try to generate an increment */
3536   /* if the right side is not a literal
3537      we cannot */
3538   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3539     return FALSE;
3540
3541   /* if the literal value of the right hand side
3542      is greater than 4 then it is not worth it */
3543   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3544     return FALSE;
3545
3546   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3547       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3548       while (icount--) {
3549           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3550       }
3551       return TRUE;
3552   }
3553   /* if increment 16 bits in register */
3554   if (
3555        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3556        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3557        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3558        (size > 1) &&
3559        (icount == 1))
3560     {
3561       symbol  *tlbl;
3562       int     emitTlbl;
3563       int     labelRange;
3564       char    *l;
3565
3566       /* If the next instruction is a goto and the goto target
3567        * is <= 5 instructions previous to this, we can generate
3568        * jumps straight to that target.
3569        */
3570       if (ic->next && ic->next->op == GOTO
3571           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3572           && labelRange <= 5)
3573         {
3574           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3575           tlbl = IC_LABEL (ic->next);
3576           emitTlbl = 0;
3577         }
3578       else
3579         {
3580           tlbl = newiTempLabel (NULL);
3581           emitTlbl = 1;
3582         }
3583         
3584       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3585       emitcode ("inc", "%s", l);
3586       
3587       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3588           IS_AOP_PREG (IC_RESULT (ic)))
3589       {   
3590         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3591       }
3592       else
3593       {
3594           emitcode ("clr", "a");
3595           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3596       }
3597
3598       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3599       emitcode ("inc", "%s", l);
3600       if (size > 2)
3601         {
3602             if (!strcmp(l, "acc"))
3603             {
3604                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3605             }
3606             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3607                      IS_AOP_PREG (IC_RESULT (ic)))
3608             {
3609                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3610             }
3611             else
3612             {
3613                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3614             }
3615
3616             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3617             emitcode ("inc", "%s", l);
3618         }
3619       if (size > 3)
3620         {
3621             if (!strcmp(l, "acc"))
3622             {
3623                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3624             }
3625             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3626                      IS_AOP_PREG (IC_RESULT (ic)))
3627             {
3628                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3629             }
3630             else
3631             {
3632                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3633             }
3634
3635             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3636             emitcode ("inc", "%s", l);  }
3637
3638       if (emitTlbl)
3639         {
3640           emitcode ("", "!tlabeldef", tlbl->key + 100);
3641         }
3642       return TRUE;
3643     }
3644
3645   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3646       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3647       options.model == MODEL_FLAT24 ) {
3648
3649       switch (size) {
3650       case 3:
3651           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3652       case 2:
3653           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3654       case 1:
3655           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3656           break;
3657       }
3658       while (icount--) emitcode ("inc","dptr");      
3659       return TRUE;
3660   }
3661
3662   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3663       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3664       icount <= 5 ) {
3665       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3666       while (icount--) emitcode ("inc","dptr");
3667       emitcode ("mov","dps,#0");
3668       return TRUE;
3669   }
3670
3671   /* if the sizes are greater than 1 then we cannot */
3672   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3673       AOP_SIZE (IC_LEFT (ic)) > 1)
3674     return FALSE;
3675
3676   /* we can if the aops of the left & result match or
3677      if they are in registers and the registers are the
3678      same */
3679   if (
3680        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3681        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3682        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3683     {
3684
3685       if (icount > 3)
3686         {
3687           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3688           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3689           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3690         }
3691       else
3692         {
3693
3694           _startLazyDPSEvaluation ();
3695           while (icount--)
3696             {
3697               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3698             }
3699           _endLazyDPSEvaluation ();
3700         }
3701
3702       return TRUE;
3703     }
3704
3705   return FALSE;
3706 }
3707
3708 /*-----------------------------------------------------------------*/
3709 /* outBitAcc - output a bit in acc                                 */
3710 /*-----------------------------------------------------------------*/
3711 static void
3712 outBitAcc (operand * result)
3713 {
3714   symbol *tlbl = newiTempLabel (NULL);
3715   /* if the result is a bit */
3716   if (AOP_TYPE (result) == AOP_CRY)
3717     {
3718       aopPut (AOP (result), "a", 0);
3719     }
3720   else
3721     {
3722       emitcode ("jz", "!tlabel", tlbl->key + 100);
3723       emitcode ("mov", "a,%s", one);
3724       emitcode ("", "!tlabeldef", tlbl->key + 100);
3725       outAcc (result);
3726     }
3727 }
3728
3729 /*-----------------------------------------------------------------*/
3730 /* genPlusBits - generates code for addition of two bits           */
3731 /*-----------------------------------------------------------------*/
3732 static void
3733 genPlusBits (iCode * ic)
3734 {
3735   D (emitcode (";", "genPlusBits "););
3736     
3737   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3738     {
3739       symbol *lbl = newiTempLabel (NULL);
3740       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3741       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3742       emitcode ("cpl", "c");
3743       emitcode ("", "!tlabeldef", (lbl->key + 100));
3744       outBitC (IC_RESULT (ic));
3745     }
3746   else
3747     {
3748       emitcode ("clr", "a");
3749       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3750       emitcode ("rlc", "a");
3751       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3752       emitcode ("addc", "a,#0");
3753       outAcc (IC_RESULT (ic));
3754     }
3755 }
3756
3757 static void
3758 adjustArithmeticResult (iCode * ic)
3759 {
3760   if (opIsGptr (IC_RESULT (ic)) &&
3761       opIsGptr (IC_LEFT (ic)) &&
3762       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3763     {
3764       aopPut (AOP (IC_RESULT (ic)),
3765               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3766               GPTRSIZE - 1);
3767     }
3768
3769   if (opIsGptr (IC_RESULT (ic)) &&
3770       opIsGptr (IC_RIGHT (ic)) &&
3771       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3772     {
3773       aopPut (AOP (IC_RESULT (ic)),
3774             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3775               GPTRSIZE - 1);
3776     }
3777
3778   if (opIsGptr (IC_RESULT (ic)) &&
3779       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3780       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3781       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3782       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3783     {
3784       char buff[5];
3785       SNPRINTF (buff, sizeof(buff), 
3786                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3787       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3788     }
3789 }
3790
3791 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3792 // generates the result if possible. If result is generated, returns TRUE; otherwise
3793 // returns false and caller must deal with fact that result isn't aopOp'd.
3794 bool aopOp3(iCode * ic)
3795 {
3796     bool dp1InUse, dp2InUse;
3797     bool useDp2;
3798     
3799     // First, generate the right opcode. DPTR may be used if neither left nor result are
3800     // of type AOP_STR.
3801     
3802 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3803 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3804 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3805 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3806 //      );
3807 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3808 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3809 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3810 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3811 //      );
3812     
3813     // Right uses DPTR unless left or result is an AOP_STR; however,
3814     // if right is an AOP_STR, it must use DPTR regardless.
3815     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3816      && !AOP_IS_STR(IC_RIGHT(ic)))
3817     {
3818         useDp2 = TRUE;
3819     }
3820     else
3821     {
3822         useDp2 = FALSE;
3823     }
3824         
3825     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3826     
3827     // if the right used DPTR, left MUST use DPTR2.
3828     // if the right used DPTR2, left MUST use DPTR.
3829     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3830     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3831     // enabling us to assign DPTR to result.
3832      
3833     if (AOP_USESDPTR(IC_RIGHT(ic)))
3834     {
3835         useDp2 = TRUE;
3836     }
3837     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3838     {
3839         useDp2 = FALSE;
3840     }
3841     else
3842     {
3843         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3844         {
3845             useDp2 = TRUE;
3846         }
3847         else
3848         {
3849             useDp2 = FALSE;
3850         }
3851     }
3852
3853     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3854     
3855     // We've op'd the left & right. So, if left or right are the same operand as result, 
3856     // we know aopOp will succeed, and we can just do it & bail.
3857     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3858         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3859     {
3860 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3861         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3862         return TRUE;
3863     }
3864     
3865     // Note which dptrs are currently in use.
3866     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3867     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3868     
3869     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3870     // generate it.
3871     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3872     {
3873         return FALSE;
3874     }
3875     
3876     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3877     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3878     {
3879         return FALSE;
3880     }
3881     
3882     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3883     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3884     {
3885         return FALSE;
3886     }
3887
3888     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3889
3890     // Some sanity checking...
3891     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3892     {
3893         fprintf(stderr,
3894                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3895                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3896         emitcode(";", ">>> unexpected DPTR here.");
3897     }
3898     
3899     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3900     {
3901         fprintf(stderr,
3902                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3903                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3904         emitcode(";", ">>> unexpected DPTR2 here.");
3905     }    
3906     
3907     return TRUE;
3908 }
3909
3910 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3911 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3912 // will be set TRUE. The caller must then handle the case specially, noting
3913 // that the IC_RESULT operand is not aopOp'd.
3914 // 
3915 #define AOP_OP_3_NOFATAL(ic, rc) \
3916             do { rc = !aopOp3(ic); } while (0)
3917
3918 // aopOp the left & right operands of an ic.
3919 #define AOP_OP_2(ic) \
3920     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3921     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3922
3923 // convienience macro.
3924 #define AOP_SET_LOCALS(ic) \
3925     left = IC_LEFT(ic); \
3926     right = IC_RIGHT(ic); \
3927     result = IC_RESULT(ic);
3928
3929
3930 // Given an integer value of pushedSize bytes on the stack,
3931 // adjust it to be resultSize bytes, either by discarding
3932 // the most significant bytes or by zero-padding.
3933 //
3934 // On exit from this macro, pushedSize will have been adjusted to
3935 // equal resultSize, and ACC may be trashed.
3936 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3937       /* If the pushed data is bigger than the result,          \
3938        * simply discard unused bytes. Icky, but works.          \
3939        */                                                       \
3940       while (pushedSize > resultSize)                           \
3941       {                                                         \
3942           D (emitcode (";", "discarding unused result byte."););\
3943           emitcode ("pop", "acc");                              \
3944           pushedSize--;                                         \
3945       }                                                         \
3946       if (pushedSize < resultSize)                              \
3947       {                                                         \
3948           emitcode ("clr", "a");                                \
3949           /* Conversly, we haven't pushed enough here.          \
3950            * just zero-pad, and all is well.                    \
3951            */                                                   \
3952           while (pushedSize < resultSize)                       \
3953           {                                                     \
3954               emitcode("push", "acc");                          \
3955               pushedSize++;                                     \
3956           }                                                     \
3957       }                                                         \
3958       assert(pushedSize == resultSize);
3959
3960 /*-----------------------------------------------------------------*/
3961 /* genPlus - generates code for addition                           */
3962 /*-----------------------------------------------------------------*/
3963 static void
3964 genPlus (iCode * ic)
3965 {
3966   int size, offset = 0;
3967   bool pushResult;
3968   int rSize;
3969
3970   D (emitcode (";", "genPlus "););
3971
3972   /* special cases :- */
3973   if ( AOP_IS_STR(IC_LEFT(ic)) &&
3974       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3975       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3976       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3977       if (size <= 9) {
3978           while (size--) emitcode ("inc","dptr");
3979       } else {
3980           emitcode ("mov","a,dpl");
3981           emitcode ("add","a,#!constbyte",size & 0xff);
3982           emitcode ("mov","dpl,a");
3983           emitcode ("mov","a,dph");
3984           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3985           emitcode ("mov","dph,a");
3986           emitcode ("mov","a,dpx");
3987           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3988           emitcode ("mov","dpx,a");
3989       }
3990       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3991       return ;
3992   }
3993   if ( IS_SYMOP(IC_LEFT(ic)) && 
3994        OP_SYMBOL(IC_LEFT(ic))->remat &&
3995        isOperandInFarSpace(IC_RIGHT(ic))) {
3996       operand *op = IC_RIGHT(ic);
3997       IC_RIGHT(ic) = IC_LEFT(ic);
3998       IC_LEFT(ic) = op;
3999   }
4000                 
4001   AOP_OP_3_NOFATAL (ic, pushResult);
4002     
4003   if (pushResult)
4004     {
4005       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4006     }
4007
4008   if (!pushResult)
4009     {
4010       /* if literal, literal on the right or
4011          if left requires ACC or right is already
4012          in ACC */
4013       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4014        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4015           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4016         {
4017           operand *t = IC_RIGHT (ic);
4018           IC_RIGHT (ic) = IC_LEFT (ic);
4019           IC_LEFT (ic) = t;
4020           emitcode (";", "Swapped plus args.");
4021         }
4022
4023       /* if both left & right are in bit
4024          space */
4025       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4026           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4027         {
4028           genPlusBits (ic);
4029           goto release;
4030         }
4031
4032       /* if left in bit space & right literal */
4033       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4034           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4035         {
4036           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4037           /* if result in bit space */
4038           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4039             {
4040               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4041                 emitcode ("cpl", "c");
4042               outBitC (IC_RESULT (ic));
4043             }
4044           else
4045             {
4046               size = getDataSize (IC_RESULT (ic));
4047               _startLazyDPSEvaluation ();
4048               while (size--)
4049                 {
4050                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4051                   emitcode ("addc", "a,#0");
4052                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4053                 }
4054               _endLazyDPSEvaluation ();
4055             }
4056           goto release;
4057         }
4058
4059       /* if I can do an increment instead
4060          of add then GOOD for ME */
4061       if (genPlusIncr (ic) == TRUE)
4062         {
4063           emitcode (";", "did genPlusIncr");
4064           goto release;
4065         }
4066
4067     }
4068   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4069
4070   _startLazyDPSEvaluation ();
4071   while (size--)
4072     {
4073       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4074         {
4075           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4076           if (offset == 0)
4077             emitcode ("add", "a,%s",
4078                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4079           else
4080             emitcode ("addc", "a,%s",
4081                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4082         }
4083       else
4084         {
4085           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4086           {
4087               /* right is going to use ACC or we would have taken the
4088                * above branch.
4089                */
4090               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4091        TR_AP("#3");
4092               D(emitcode(";", "+ AOP_ACC special case."););
4093               emitcode("xch", "a, %s", DP2_RESULT_REG);
4094           }
4095           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4096           if (offset == 0)
4097           {
4098             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4099             {
4100          TR_AP("#4");
4101                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4102             }
4103             else
4104             {
4105                 emitcode ("add", "a,%s",
4106                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4107                                   DP2_RESULT_REG));
4108             }
4109           }
4110           else
4111           {
4112             emitcode ("addc", "a,%s",
4113                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4114                           DP2_RESULT_REG));
4115           }
4116         }
4117       if (!pushResult)
4118         {
4119           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4120         }
4121       else
4122         {
4123           emitcode ("push", "acc");
4124         }
4125       offset++;
4126     }
4127   _endLazyDPSEvaluation ();
4128
4129   if (pushResult)
4130     {
4131       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4132
4133       size = getDataSize (IC_LEFT (ic));
4134       rSize = getDataSize (IC_RESULT (ic));
4135
4136       ADJUST_PUSHED_RESULT(size, rSize);
4137
4138       _startLazyDPSEvaluation ();
4139       while (size--)
4140         {
4141           emitcode ("pop", "acc");
4142           aopPut (AOP (IC_RESULT (ic)), "a", size);
4143         }
4144       _endLazyDPSEvaluation ();
4145     }
4146
4147   adjustArithmeticResult (ic);
4148
4149 release:
4150   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4151   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4152   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4153 }
4154
4155 /*-----------------------------------------------------------------*/
4156 /* genMinusDec :- does subtraction with deccrement if possible     */
4157 /*-----------------------------------------------------------------*/
4158 static bool
4159 genMinusDec (iCode * ic)
4160 {
4161   unsigned int icount;
4162   unsigned int size = getDataSize (IC_RESULT (ic));
4163
4164   /* will try to generate an increment */
4165   /* if the right side is not a literal
4166      we cannot */
4167   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4168     return FALSE;
4169
4170   /* if the literal value of the right hand side
4171      is greater than 4 then it is not worth it */
4172   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4173     return FALSE;
4174
4175   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4176       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4177       while (icount--) {
4178           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4179       }
4180       return TRUE;
4181   }
4182   /* if decrement 16 bits in register */
4183   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4184       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4185       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4186       (size > 1) &&
4187       (icount == 1))
4188     {
4189       symbol *tlbl;
4190       int    emitTlbl;
4191       int    labelRange;
4192       char   *l;
4193
4194       /* If the next instruction is a goto and the goto target
4195          * is <= 5 instructions previous to this, we can generate
4196          * jumps straight to that target.
4197        */
4198       if (ic->next && ic->next->op == GOTO
4199           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4200           && labelRange <= 5)
4201         {
4202           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4203           tlbl = IC_LABEL (ic->next);
4204           emitTlbl = 0;
4205         }
4206       else
4207         {
4208           tlbl = newiTempLabel (NULL);
4209           emitTlbl = 1;
4210         }
4211
4212       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4213       emitcode ("dec", "%s", l);
4214  
4215       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4216           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4217           IS_AOP_PREG (IC_RESULT (ic)))
4218       {     
4219           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4220       }
4221       else
4222       {
4223           emitcode ("mov", "a,#!constbyte",0xff);
4224           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4225       }
4226       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4227       emitcode ("dec", "%s", l);
4228       if (size > 2)
4229         {
4230             if (!strcmp(l, "acc"))
4231             {
4232                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4233             }
4234             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4235                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4236                      IS_AOP_PREG (IC_RESULT (ic)))
4237             {       
4238                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4239             }
4240             else
4241             {
4242                 emitcode ("mov", "a,#!constbyte",0xff);
4243                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4244             }
4245             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4246             emitcode ("dec", "%s", l);
4247         }
4248       if (size > 3)
4249         {
4250             if (!strcmp(l, "acc"))
4251             {
4252                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4253             }
4254             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4255                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4256                      IS_AOP_PREG (IC_RESULT (ic)))
4257             {       
4258                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4259             }
4260             else
4261             {
4262                 emitcode ("mov", "a,#!constbyte",0xff);
4263                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4264             }       
4265             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4266             emitcode ("dec", "%s", l);
4267         }
4268       if (emitTlbl)
4269         {
4270           emitcode ("", "!tlabeldef", tlbl->key + 100);
4271         }
4272       return TRUE;
4273     }
4274
4275   /* if the sizes are greater than 1 then we cannot */
4276   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4277       AOP_SIZE (IC_LEFT (ic)) > 1)
4278     return FALSE;
4279
4280   /* we can if the aops of the left & result match or
4281      if they are in registers and the registers are the
4282      same */
4283   if (
4284        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4285        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4286        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4287     {
4288
4289       _startLazyDPSEvaluation ();
4290       while (icount--)
4291         {
4292           emitcode ("dec", "%s",
4293                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4294         }
4295       _endLazyDPSEvaluation ();
4296
4297       return TRUE;
4298     }
4299
4300   return FALSE;
4301 }
4302
4303 /*-----------------------------------------------------------------*/
4304 /* addSign - complete with sign                                    */
4305 /*-----------------------------------------------------------------*/
4306 static void
4307 addSign (operand * result, int offset, int sign)
4308 {
4309   int size = (getDataSize (result) - offset);
4310   if (size > 0)
4311     {
4312       _startLazyDPSEvaluation();
4313       if (sign)
4314         {
4315           emitcode ("rlc", "a");
4316           emitcode ("subb", "a,acc");
4317           while (size--)
4318           {
4319             aopPut (AOP (result), "a", offset++);
4320           }
4321         }
4322       else
4323       {
4324         while (size--)
4325         {
4326           aopPut (AOP (result), zero, offset++);
4327         }
4328       }
4329       _endLazyDPSEvaluation();
4330     }
4331 }
4332
4333 /*-----------------------------------------------------------------*/
4334 /* genMinusBits - generates code for subtraction  of two bits      */
4335 /*-----------------------------------------------------------------*/
4336 static void
4337 genMinusBits (iCode * ic)
4338 {
4339   symbol *lbl = newiTempLabel (NULL);
4340
4341   D (emitcode (";", "genMinusBits "););
4342
4343   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4344     {
4345       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4346       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4347       emitcode ("cpl", "c");
4348       emitcode ("", "!tlabeldef", (lbl->key + 100));
4349       outBitC (IC_RESULT (ic));
4350     }
4351   else
4352     {
4353       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4354       emitcode ("subb", "a,acc");
4355       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4356       emitcode ("inc", "a");
4357       emitcode ("", "!tlabeldef", (lbl->key + 100));
4358       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4359       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4360     }
4361 }
4362
4363 /*-----------------------------------------------------------------*/
4364 /* genMinus - generates code for subtraction                       */
4365 /*-----------------------------------------------------------------*/
4366 static void
4367 genMinus (iCode * ic)
4368 {
4369     int size, offset = 0;
4370     int rSize;
4371     long lit = 0L;
4372     bool pushResult;
4373
4374     D (emitcode (";", "genMinus "););
4375
4376     AOP_OP_3_NOFATAL(ic, pushResult);   
4377
4378     if (!pushResult)
4379     {
4380       /* special cases :- */
4381       /* if both left & right are in bit space */
4382       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4383           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4384         {
4385           genMinusBits (ic);
4386           goto release;
4387         }
4388
4389       /* if I can do an decrement instead
4390          of subtract then GOOD for ME */
4391       if (genMinusDec (ic) == TRUE)
4392         goto release;
4393
4394     }
4395
4396   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4397
4398   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4399     {
4400       CLRC;
4401     }
4402   else
4403     {
4404       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4405       lit = -lit;
4406     }
4407
4408
4409   /* if literal, add a,#-lit, else normal subb */
4410   _startLazyDPSEvaluation ();
4411   while (size--) {
4412       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4413           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4414               emitcode ("mov","b,%s",
4415                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4416               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4417               emitcode ("subb","a,b");
4418           } else {
4419               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4420               emitcode ("subb", "a,%s",
4421                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4422                                 DP2_RESULT_REG));
4423           }
4424       } else {
4425           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4426           /* first add without previous c */
4427           if (!offset) {
4428               if (!size && lit==-1) {
4429                   emitcode ("dec", "a");
4430               } else {
4431                   emitcode ("add", "a,#!constbyte",
4432                             (unsigned int) (lit & 0x0FFL));
4433               }
4434           } else {
4435               emitcode ("addc", "a,#!constbyte",
4436                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4437           }
4438       }
4439       
4440       if (pushResult) {
4441           emitcode ("push", "acc");
4442       } else {
4443           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4444       }
4445       offset++;
4446   }
4447   _endLazyDPSEvaluation ();
4448   
4449   if (pushResult)
4450     {
4451       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4452
4453       size = getDataSize (IC_LEFT (ic));
4454       rSize = getDataSize (IC_RESULT (ic));
4455
4456       ADJUST_PUSHED_RESULT(size, rSize);
4457
4458       _startLazyDPSEvaluation ();
4459       while (size--)
4460         {
4461           emitcode ("pop", "acc");
4462           aopPut (AOP (IC_RESULT (ic)), "a", size);
4463         }
4464       _endLazyDPSEvaluation ();
4465     }
4466
4467   adjustArithmeticResult (ic);
4468
4469 release:
4470   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4471   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4472   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4473 }
4474
4475
4476 /*-----------------------------------------------------------------*/
4477 /* genMultbits :- multiplication of bits                           */
4478 /*-----------------------------------------------------------------*/
4479 static void
4480 genMultbits (operand * left,
4481              operand * right,
4482              operand * result,
4483              iCode   * ic)
4484 {
4485   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4486   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4487   aopOp(result, ic, TRUE, FALSE);
4488   outBitC (result);
4489 }
4490
4491
4492 /*-----------------------------------------------------------------*/
4493 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4494 /*-----------------------------------------------------------------*/
4495 static void
4496 genMultOneByte (operand * left,
4497                 operand * right,
4498                 operand * result,
4499                 iCode   * ic)
4500 {
4501   sym_link *opetype = operandType (result);
4502   symbol *lbl;
4503
4504
4505   /* (if two literals: the value is computed before) */
4506   /* if one literal, literal on the right */
4507   if (AOP_TYPE (left) == AOP_LIT)
4508     {
4509       operand *t = right;
4510       right = left;
4511       left = t;
4512       emitcode (";", "swapped left and right");
4513     }
4514
4515   if (SPEC_USIGN(opetype)
4516       // ignore the sign of left and right, what else can we do?
4517       || (SPEC_USIGN(operandType(left)) && 
4518           SPEC_USIGN(operandType(right)))) {
4519     // just an unsigned 8*8=8/16 multiply
4520     //emitcode (";","unsigned");
4521     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4522     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4523     emitcode ("mul", "ab");
4524    
4525     _G.accInUse++; _G.bInUse++;
4526     aopOp(result, ic, TRUE, FALSE);
4527       
4528       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4529       {
4530           // this should never happen
4531           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4532                    AOP_SIZE(result), __FILE__, lineno);
4533           exit (1);
4534       }      
4535       
4536     aopPut (AOP (result), "a", 0);
4537     _G.accInUse--; _G.bInUse--;
4538     if (AOP_SIZE(result)==2) 
4539     {
4540       aopPut (AOP (result), "b", 1);
4541     }
4542     return;
4543   }
4544
4545   // we have to do a signed multiply
4546
4547   emitcode (";", "signed");
4548   emitcode ("clr", "F0"); // reset sign flag
4549   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4550
4551   lbl=newiTempLabel(NULL);
4552   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4553   // left side is negative, 8-bit two's complement, this fails for -128
4554   emitcode ("setb", "F0"); // set sign flag
4555   emitcode ("cpl", "a");
4556   emitcode ("inc", "a");
4557
4558   emitcode ("", "!tlabeldef", lbl->key+100);
4559
4560   /* if literal */
4561   if (AOP_TYPE(right)==AOP_LIT) {
4562     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4563     /* AND literal negative */
4564     if ((int) val < 0) {
4565       emitcode ("cpl", "F0"); // complement sign flag
4566       emitcode ("mov", "b,#!constbyte", -val);
4567     } else {
4568       emitcode ("mov", "b,#!constbyte", val);
4569     }
4570   } else {
4571     lbl=newiTempLabel(NULL);
4572     emitcode ("mov", "b,a");
4573     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4574     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4575     // right side is negative, 8-bit two's complement
4576     emitcode ("cpl", "F0"); // complement sign flag
4577     emitcode ("cpl", "a");
4578     emitcode ("inc", "a");
4579     emitcode ("", "!tlabeldef", lbl->key+100);
4580   }
4581   emitcode ("mul", "ab");
4582     
4583   _G.accInUse++;_G.bInUse++;
4584   aopOp(result, ic, TRUE, FALSE);
4585     
4586   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4587   {
4588     // this should never happen
4589       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4590                AOP_SIZE(result), __FILE__, lineno);
4591       exit (1);
4592   }    
4593     
4594   lbl=newiTempLabel(NULL);
4595   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4596   // only ONE op was negative, we have to do a 8/16-bit two's complement
4597   emitcode ("cpl", "a"); // lsb
4598   if (AOP_SIZE(result)==1) {
4599     emitcode ("inc", "a");
4600   } else {
4601     emitcode ("add", "a,#1");
4602     emitcode ("xch", "a,b");
4603     emitcode ("cpl", "a"); // msb
4604     emitcode ("addc", "a,#0");
4605     emitcode ("xch", "a,b");
4606   }
4607
4608   emitcode ("", "!tlabeldef", lbl->key+100);
4609   aopPut (AOP (result), "a", 0);
4610   _G.accInUse--;_G.bInUse--;
4611   if (AOP_SIZE(result)==2) {
4612     aopPut (AOP (result), "b", 1);
4613   }
4614 }
4615
4616 /*-----------------------------------------------------------------*/
4617 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4618 /*-----------------------------------------------------------------*/
4619 static void genMultTwoByte (operand *left, operand *right, 
4620                             operand *result, iCode *ic)
4621 {
4622         sym_link *retype = getSpec(operandType(right));
4623         sym_link *letype = getSpec(operandType(left));
4624         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4625         symbol *lbl;
4626
4627         if (AOP_TYPE (left) == AOP_LIT) {
4628                 operand *t = right;
4629                 right = left;
4630                 left = t;
4631         }
4632         /* save EA bit in F1 */
4633         lbl = newiTempLabel(NULL);
4634         emitcode ("setb","F1");
4635         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4636         emitcode ("clr","F1");
4637         emitcode("","!tlabeldef",lbl->key+100);
4638
4639         /* load up MB with right */
4640         if (!umult) {
4641                 emitcode("clr","F0");
4642                 if (AOP_TYPE(right) == AOP_LIT) {
4643                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4644                         if (val < 0) {
4645                                 emitcode("setb","F0");
4646                                 val = -val;
4647                         }
4648                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4649                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4650                 } else {
4651                         lbl = newiTempLabel(NULL);
4652                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4653                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4654                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4655                         emitcode ("xch", "a,b");
4656                         emitcode ("cpl","a");
4657                         emitcode ("add", "a,#1");
4658                         emitcode ("xch", "a,b");
4659                         emitcode ("cpl", "a"); // msb
4660                         emitcode ("addc", "a,#0");
4661                         emitcode ("setb","F0");
4662                         emitcode ("","!tlabeldef",lbl->key+100);
4663                         emitcode ("mov","mb,b");
4664                         emitcode ("mov","mb,a");
4665                 }
4666         } else {
4667                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4668                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4669         }
4670         /* load up MA with left */
4671         if (!umult) {
4672                 lbl = newiTempLabel(NULL);
4673                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4674                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4675                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4676                 emitcode ("xch", "a,b");
4677                 emitcode ("cpl","a");
4678                 emitcode ("add", "a,#1");
4679                 emitcode ("xch", "a,b");
4680                 emitcode ("cpl", "a"); // msb
4681                 emitcode ("addc","a,#0");
4682                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4683                 emitcode ("setb","F0");
4684                 emitcode ("","!tlabeldef",lbl->key+100);
4685                 emitcode ("mov","ma,b");
4686                 emitcode ("mov","ma,a");
4687         } else {
4688                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4689                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4690         }
4691         /* wait for multiplication to finish */
4692         lbl = newiTempLabel(NULL);
4693         emitcode("","!tlabeldef", lbl->key+100);
4694         emitcode("mov","a,mcnt1");
4695         emitcode("anl","a,#!constbyte",0x80);
4696         emitcode("jnz","!tlabel",lbl->key+100);
4697         
4698         freeAsmop (left, NULL, ic, TRUE);
4699         freeAsmop (right, NULL, ic,TRUE);
4700         aopOp(result, ic, TRUE, FALSE);
4701
4702         /* if unsigned then simple */   
4703         if (umult) {
4704                 emitcode ("mov","a,ma");
4705                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4706                 emitcode ("mov","a,ma");
4707                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4708                 aopPut(AOP(result),"ma",1);
4709                 aopPut(AOP(result),"ma",0);
4710         } else {
4711                 emitcode("push","ma");
4712                 emitcode("push","ma");
4713                 emitcode("push","ma");
4714                 MOVA("ma");
4715                 /* negate result if needed */
4716                 lbl = newiTempLabel(NULL);      
4717                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4718                 emitcode("cpl","a");
4719                 emitcode("add","a,#1");
4720                 emitcode("","!tlabeldef", lbl->key+100);
4721                 if (AOP_TYPE(result) == AOP_ACC)
4722                 {
4723                     D(emitcode(";", "ACC special case."););
4724                     /* We know result is the only live aop, and 
4725                      * it's obviously not a DPTR2, so AP is available.
4726                      */
4727                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4728                 }
4729                 else
4730                 {
4731                     aopPut(AOP(result),"a",0);
4732                 }
4733             
4734                 emitcode("pop","acc");
4735                 lbl = newiTempLabel(NULL);      
4736                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4737                 emitcode("cpl","a");
4738                 emitcode("addc","a,#0");
4739                 emitcode("","!tlabeldef", lbl->key+100);
4740                 aopPut(AOP(result),"a",1);
4741                 emitcode("pop","acc");
4742                 if (AOP_SIZE(result) >= 3) {
4743                         lbl = newiTempLabel(NULL);      
4744                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4745                         emitcode("cpl","a");
4746                         emitcode("addc","a,#0");                        
4747                         emitcode("","!tlabeldef", lbl->key+100);
4748                         aopPut(AOP(result),"a",2);
4749                 }
4750                 emitcode("pop","acc");
4751                 if (AOP_SIZE(result) >= 4) {
4752                         lbl = newiTempLabel(NULL);      
4753                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4754                         emitcode("cpl","a");
4755                         emitcode("addc","a,#0");                        
4756                         emitcode("","!tlabeldef", lbl->key+100);
4757                         aopPut(AOP(result),"a",3);
4758                 }
4759                 if (AOP_TYPE(result) == AOP_ACC)
4760                 {
4761                     /* We stashed the result away above. */
4762                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4763                 }           
4764                 
4765         }
4766         freeAsmop (result, NULL, ic, TRUE);
4767
4768         /* restore EA bit in F1 */
4769         lbl = newiTempLabel(NULL);
4770         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4771         emitcode ("setb","EA");
4772         emitcode("","!tlabeldef",lbl->key+100);
4773         return ;
4774 }
4775
4776 /*-----------------------------------------------------------------*/
4777 /* genMult - generates code for multiplication                     */
4778 /*-----------------------------------------------------------------*/
4779 static void
4780 genMult (iCode * ic)
4781 {
4782   operand *left = IC_LEFT (ic);
4783   operand *right = IC_RIGHT (ic);
4784   operand *result = IC_RESULT (ic);
4785
4786   D (emitcode (";", "genMult "););
4787
4788   /* assign the amsops */
4789   AOP_OP_2 (ic);
4790
4791   /* special cases first */
4792   /* both are bits */
4793   if (AOP_TYPE (left) == AOP_CRY &&
4794       AOP_TYPE (right) == AOP_CRY)
4795     {
4796       genMultbits (left, right, result, ic);
4797       goto release;
4798     }
4799
4800   /* if both are of size == 1 */
4801   if (AOP_SIZE (left) == 1 &&
4802       AOP_SIZE (right) == 1)
4803     {
4804       genMultOneByte (left, right, result, ic);
4805       goto release;
4806     }
4807
4808   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4809           /* use the ds390 ARITHMETIC accel UNIT */
4810           genMultTwoByte (left, right, result, ic);
4811           return ;
4812   }
4813   /* should have been converted to function call */
4814   assert (0);
4815
4816 release:
4817   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4818   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4819   freeAsmop (result, NULL, ic, TRUE);
4820 }
4821
4822 /*-----------------------------------------------------------------*/
4823 /* genDivbits :- division of bits                                  */
4824 /*-----------------------------------------------------------------*/
4825 static void
4826 genDivbits (operand * left,
4827             operand * right,
4828             operand * result,
4829             iCode   * ic)
4830 {
4831
4832   char *l;
4833
4834   /* the result must be bit */
4835   LOAD_AB_FOR_DIV (left, right, l);
4836   emitcode ("div", "ab");
4837   emitcode ("rrc", "a");
4838   aopOp(result, ic, TRUE, FALSE);
4839     
4840   aopPut (AOP (result), "c", 0);
4841 }
4842
4843 /*-----------------------------------------------------------------*/
4844 /* genDivOneByte : 8 bit division                                  */
4845 /*-----------------------------------------------------------------*/
4846 static void
4847 genDivOneByte (operand * left,
4848                operand * right,
4849                operand * result,
4850                iCode   * ic)
4851 {
4852   sym_link *opetype = operandType (result);
4853   char *l;
4854   symbol *lbl;
4855   int size, offset;
4856
4857   offset = 1;
4858   /* signed or unsigned */
4859   if (SPEC_USIGN (opetype))
4860     {
4861         /* unsigned is easy */
4862         LOAD_AB_FOR_DIV (left, right, l);
4863         emitcode ("div", "ab");
4864
4865         _G.accInUse++;
4866         aopOp(result, ic, TRUE, FALSE);
4867         aopPut (AOP (result), "a", 0);
4868         _G.accInUse--;
4869
4870         size = AOP_SIZE (result) - 1;
4871         
4872         while (size--)
4873         {
4874             aopPut (AOP (result), zero, offset++);
4875         }
4876       return;
4877     }
4878
4879   /* signed is a little bit more difficult */
4880
4881   /* save the signs of the operands */
4882   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4883   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4884   emitcode ("push", "acc");     /* save it on the stack */
4885
4886   /* now sign adjust for both left & right */
4887   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4888   lbl = newiTempLabel (NULL);
4889   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4890   emitcode ("cpl", "a");
4891   emitcode ("inc", "a");
4892   emitcode ("", "!tlabeldef", (lbl->key + 100));
4893   emitcode ("mov", "b,a");
4894
4895   /* sign adjust left side */
4896   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4897
4898   lbl = newiTempLabel (NULL);
4899   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4900   emitcode ("cpl", "a");
4901   emitcode ("inc", "a");
4902   emitcode ("", "!tlabeldef", (lbl->key + 100));
4903
4904   /* now the division */
4905   emitcode ("nop", "; workaround for DS80C390 div bug.");
4906   emitcode ("div", "ab");
4907   /* we are interested in the lower order
4908      only */
4909   emitcode ("mov", "b,a");
4910   lbl = newiTempLabel (NULL);
4911   emitcode ("pop", "acc");
4912   /* if there was an over flow we don't
4913      adjust the sign of the result */
4914   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4915   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4916   CLRC;
4917   emitcode ("clr", "a");
4918   emitcode ("subb", "a,b");
4919   emitcode ("mov", "b,a");
4920   emitcode ("", "!tlabeldef", (lbl->key + 100));
4921
4922   /* now we are done */
4923   _G.accInUse++;     _G.bInUse++;
4924     aopOp(result, ic, TRUE, FALSE);
4925     
4926     aopPut (AOP (result), "b", 0);
4927     
4928     size = AOP_SIZE (result) - 1;
4929     
4930     if (size > 0)
4931     {
4932       emitcode ("mov", "c,b.7");
4933       emitcode ("subb", "a,acc");
4934     }
4935     while (size--)
4936     {
4937         aopPut (AOP (result), "a", offset++);
4938     }
4939     _G.accInUse--;     _G.bInUse--;
4940
4941 }
4942
4943 /*-----------------------------------------------------------------*/
4944 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4945 /*-----------------------------------------------------------------*/
4946 static void genDivTwoByte (operand *left, operand *right, 
4947                             operand *result, iCode *ic)
4948 {
4949         sym_link *retype = getSpec(operandType(right));
4950         sym_link *letype = getSpec(operandType(left));
4951         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4952         symbol *lbl;
4953
4954         /* save EA bit in F1 */
4955         lbl = newiTempLabel(NULL);
4956         emitcode ("setb","F1");
4957         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4958         emitcode ("clr","F1");
4959         emitcode("","!tlabeldef",lbl->key+100);
4960
4961         /* load up MA with left */
4962         if (!umult) {
4963                 emitcode("clr","F0");
4964                 lbl = newiTempLabel(NULL);
4965                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4966                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4967                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4968                 emitcode ("xch", "a,b");
4969                 emitcode ("cpl","a");
4970                 emitcode ("add", "a,#1");
4971                 emitcode ("xch", "a,b");
4972                 emitcode ("cpl", "a"); // msb
4973                 emitcode ("addc","a,#0");
4974                 emitcode ("setb","F0");
4975                 emitcode ("","!tlabeldef",lbl->key+100);
4976                 emitcode ("mov","ma,b");
4977                 emitcode ("mov","ma,a");
4978         } else {
4979                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4980                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4981         }
4982
4983         /* load up MB with right */
4984         if (!umult) {
4985                 if (AOP_TYPE(right) == AOP_LIT) {
4986                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4987                         if (val < 0) {
4988                                 lbl = newiTempLabel(NULL);
4989                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4990                                 emitcode("setb","F0");
4991                                 emitcode ("","!tlabeldef",lbl->key+100);
4992                                 val = -val;
4993                         } 
4994                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4995                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4996                 } else {
4997                         lbl = newiTempLabel(NULL);
4998                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4999                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5000                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5001                         emitcode ("xch", "a,b");
5002                         emitcode ("cpl","a");
5003                         emitcode ("add", "a,#1");
5004                         emitcode ("xch", "a,b");
5005                         emitcode ("cpl", "a"); // msb
5006                         emitcode ("addc", "a,#0");
5007                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5008                         emitcode ("setb","F0");
5009                         emitcode ("","!tlabeldef",lbl->key+100);
5010                         emitcode ("mov","mb,b");
5011                         emitcode ("mov","mb,a");
5012                 }
5013         } else {
5014                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5015                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5016         }
5017
5018         /* wait for multiplication to finish */
5019         lbl = newiTempLabel(NULL);
5020         emitcode("","!tlabeldef", lbl->key+100);
5021         emitcode("mov","a,mcnt1");
5022         emitcode("anl","a,#!constbyte",0x80);
5023         emitcode("jnz","!tlabel",lbl->key+100);
5024         
5025         freeAsmop (left, NULL, ic, TRUE);
5026         freeAsmop (right, NULL, ic,TRUE);
5027         aopOp(result, ic, TRUE, FALSE);
5028
5029         /* if unsigned then simple */   
5030         if (umult) {
5031                 aopPut(AOP(result),"ma",1);
5032                 aopPut(AOP(result),"ma",0);
5033         } else {
5034                 emitcode("push","ma");
5035                 MOVA("ma");
5036                 /* negate result if needed */
5037                 lbl = newiTempLabel(NULL);      
5038                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5039                 emitcode("cpl","a");
5040                 emitcode("add","a,#1");
5041                 emitcode("","!tlabeldef", lbl->key+100);
5042                 aopPut(AOP(result),"a",0);
5043                 emitcode("pop","acc");
5044                 lbl = newiTempLabel(NULL);      
5045                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5046                 emitcode("cpl","a");
5047                 emitcode("addc","a,#0");
5048                 emitcode("","!tlabeldef", lbl->key+100);
5049                 aopPut(AOP(result),"a",1);
5050         }
5051         freeAsmop (result, NULL, ic, TRUE);
5052         /* restore EA bit in F1 */
5053         lbl = newiTempLabel(NULL);
5054         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5055         emitcode ("setb","EA");
5056         emitcode("","!tlabeldef",lbl->key+100);
5057         return ;
5058 }
5059
5060 /*-----------------------------------------------------------------*/
5061 /* genDiv - generates code for division                            */
5062 /*-----------------------------------------------------------------*/
5063 static void
5064 genDiv (iCode * ic)
5065 {
5066   operand *left = IC_LEFT (ic);
5067   operand *right = IC_RIGHT (ic);
5068   operand *result = IC_RESULT (ic);
5069
5070   D (emitcode (";", "genDiv "););
5071
5072   /* assign the amsops */
5073   AOP_OP_2 (ic);
5074
5075   /* special cases first */
5076   /* both are bits */
5077   if (AOP_TYPE (left) == AOP_CRY &&
5078       AOP_TYPE (right) == AOP_CRY)
5079     {
5080       genDivbits (left, right, result, ic);
5081       goto release;
5082     }
5083
5084   /* if both are of size == 1 */
5085   if (AOP_SIZE (left) == 1 &&
5086       AOP_SIZE (right) == 1)
5087     {
5088       genDivOneByte (left, right, result, ic);
5089       goto release;
5090     }
5091
5092   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5093           /* use the ds390 ARITHMETIC accel UNIT */
5094           genDivTwoByte (left, right, result, ic);
5095           return ;
5096   }
5097   /* should have been converted to function call */
5098   assert (0);
5099 release:
5100   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5101   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5102   freeAsmop (result, NULL, ic, TRUE);
5103 }
5104
5105 /*-----------------------------------------------------------------*/
5106 /* genModbits :- modulus of bits                                   */
5107 /*-----------------------------------------------------------------*/
5108 static void
5109 genModbits (operand * left,
5110             operand * right,
5111             operand * result,
5112             iCode   * ic)
5113 {
5114
5115   char *l;
5116
5117   /* the result must be bit */
5118   LOAD_AB_FOR_DIV (left, right, l);
5119   emitcode ("div", "ab");
5120   emitcode ("mov", "a,b");
5121   emitcode ("rrc", "a");
5122   aopOp(result, ic, TRUE, FALSE);
5123   aopPut (AOP (result), "c", 0);
5124 }
5125
5126 /*-----------------------------------------------------------------*/
5127 /* genModOneByte : 8 bit modulus                                   */
5128 /*-----------------------------------------------------------------*/
5129 static void
5130 genModOneByte (operand * left,
5131                operand * right,
5132                operand * result,
5133                iCode   * ic)
5134 {
5135   sym_link *opetype = operandType (result);
5136   char *l;
5137   symbol *lbl;
5138
5139   /* signed or unsigned */
5140   if (SPEC_USIGN (opetype))
5141     {
5142       /* unsigned is easy */
5143       LOAD_AB_FOR_DIV (left, right, l);
5144       emitcode ("div", "ab");
5145       aopOp(result, ic, TRUE, FALSE);   
5146       aopPut (AOP (result), "b", 0);
5147       return;
5148     }
5149
5150   /* signed is a little bit more difficult */
5151
5152   /* save the signs of the operands */
5153   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5154
5155   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5156   emitcode ("push", "acc");     /* save it on the stack */
5157
5158   /* now sign adjust for both left & right */
5159   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5160
5161   lbl = newiTempLabel (NULL);
5162   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5163   emitcode ("cpl", "a");
5164   emitcode ("inc", "a");
5165   emitcode ("", "!tlabeldef", (lbl->key + 100));
5166   emitcode ("mov", "b,a");
5167
5168   /* sign adjust left side */
5169   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5170
5171   lbl = newiTempLabel (NULL);
5172   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5173   emitcode ("cpl", "a");
5174   emitcode ("inc", "a");
5175   emitcode ("", "!tlabeldef", (lbl->key + 100));
5176
5177   /* now the multiplication */
5178   emitcode ("nop", "; workaround for DS80C390 div bug.");
5179   emitcode ("div", "ab");
5180   /* we are interested in the lower order
5181      only */
5182   lbl = newiTempLabel (NULL);
5183   emitcode ("pop", "acc");
5184   /* if there was an over flow we don't
5185      adjust the sign of the result */
5186   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5187   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5188   CLRC;
5189   emitcode ("clr", "a");
5190   emitcode ("subb", "a,b");
5191   emitcode ("mov", "b,a");
5192   emitcode ("", "!tlabeldef", (lbl->key + 100));
5193   
5194   _G.bInUse++;
5195   /* now we are done */
5196   aopOp(result, ic, TRUE, FALSE);    
5197   aopPut (AOP (result), "b", 0);
5198   _G.bInUse--;
5199
5200 }
5201
5202 /*-----------------------------------------------------------------*/
5203 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5204 /*-----------------------------------------------------------------*/
5205 static void genModTwoByte (operand *left, operand *right, 
5206                             operand *result, iCode *ic)
5207 {
5208         sym_link *retype = getSpec(operandType(right));
5209         sym_link *letype = getSpec(operandType(left));
5210         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5211         symbol *lbl;
5212
5213         /* load up MA with left */
5214         /* save EA bit in F1 */
5215         lbl = newiTempLabel(NULL);
5216         emitcode ("setb","F1");
5217         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5218         emitcode ("clr","F1");
5219         emitcode("","!tlabeldef",lbl->key+100);
5220
5221         if (!umult) {
5222                 lbl = newiTempLabel(NULL);
5223                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5224                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5225                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5226                 emitcode ("xch", "a,b");
5227                 emitcode ("cpl","a");
5228                 emitcode ("add", "a,#1");
5229                 emitcode ("xch", "a,b");
5230                 emitcode ("cpl", "a"); // msb
5231                 emitcode ("addc","a,#0");
5232                 emitcode ("","!tlabeldef",lbl->key+100);
5233                 emitcode ("mov","ma,b");
5234                 emitcode ("mov","ma,a");
5235         } else {
5236                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5237                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5238         }
5239
5240         /* load up MB with right */
5241         if (!umult) {
5242                 if (AOP_TYPE(right) == AOP_LIT) {
5243                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5244                         if (val < 0) {
5245                                 val = -val;
5246                         } 
5247                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5248                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5249                 } else {
5250                         lbl = newiTempLabel(NULL);
5251                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5252                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5253                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5254                         emitcode ("xch", "a,b");
5255                         emitcode ("cpl","a");
5256                         emitcode ("add", "a,#1");
5257                         emitcode ("xch", "a,b");
5258                         emitcode ("cpl", "a"); // msb
5259                         emitcode ("addc", "a,#0");
5260                         emitcode ("","!tlabeldef",lbl->key+100);
5261                         emitcode ("mov","mb,b");
5262                         emitcode ("mov","mb,a");
5263                 }
5264         } else {
5265                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5266                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5267         }
5268
5269         /* wait for multiplication to finish */
5270         lbl = newiTempLabel(NULL);
5271         emitcode("","!tlabeldef", lbl->key+100);
5272         emitcode("mov","a,mcnt1");
5273         emitcode("anl","a,#!constbyte",0x80);
5274         emitcode("jnz","!tlabel",lbl->key+100);
5275         
5276         freeAsmop (left, NULL, ic, TRUE);
5277         freeAsmop (right, NULL, ic,TRUE);
5278         aopOp(result, ic, TRUE, FALSE);
5279
5280         aopPut(AOP(result),"mb",1);
5281         aopPut(AOP(result),"mb",0);
5282         freeAsmop (result, NULL, ic, TRUE);
5283
5284         /* restore EA bit in F1 */
5285         lbl = newiTempLabel(NULL);
5286         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5287         emitcode ("setb","EA");
5288         emitcode("","!tlabeldef",lbl->key+100);
5289         return ;
5290 }
5291
5292 /*-----------------------------------------------------------------*/
5293 /* genMod - generates code for division                            */
5294 /*-----------------------------------------------------------------*/
5295 static void
5296 genMod (iCode * ic)
5297 {
5298   operand *left = IC_LEFT (ic);
5299   operand *right = IC_RIGHT (ic);
5300   operand *result = IC_RESULT (ic);
5301
5302   D (emitcode (";", "genMod "); );
5303
5304   /* assign the amsops */
5305   AOP_OP_2 (ic);
5306
5307   /* special cases first */
5308   /* both are bits */
5309   if (AOP_TYPE (left) == AOP_CRY &&
5310       AOP_TYPE (right) == AOP_CRY)
5311     {
5312       genModbits (left, right, result, ic);
5313       goto release;
5314     }
5315
5316   /* if both are of size == 1 */
5317   if (AOP_SIZE (left) == 1 &&
5318       AOP_SIZE (right) == 1)
5319     {
5320       genModOneByte (left, right, result, ic);
5321       goto release;
5322     }
5323
5324   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5325           /* use the ds390 ARITHMETIC accel UNIT */
5326           genModTwoByte (left, right, result, ic);
5327           return ;
5328   }
5329
5330   /* should have been converted to function call */
5331   assert (0);
5332
5333 release:
5334   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5335   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5336   freeAsmop (result, NULL, ic, TRUE);
5337 }
5338
5339 /*-----------------------------------------------------------------*/
5340 /* genIfxJump :- will create a jump depending on the ifx           */
5341 /*-----------------------------------------------------------------*/
5342 static void
5343 genIfxJump (iCode * ic, char *jval)
5344 {
5345   symbol *jlbl;
5346   symbol *tlbl = newiTempLabel (NULL);
5347   char *inst;
5348
5349   D (emitcode (";", "genIfxJump"););
5350
5351   /* if true label then we jump if condition
5352      supplied is true */
5353   if (IC_TRUE (ic))
5354     {
5355       jlbl = IC_TRUE (ic);
5356       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5357                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5358     }
5359   else
5360     {
5361       /* false label is present */
5362       jlbl = IC_FALSE (ic);
5363       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5364                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5365     }
5366   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5367     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5368   else
5369     emitcode (inst, "!tlabel", tlbl->key + 100);
5370   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5371   emitcode ("", "!tlabeldef", tlbl->key + 100);
5372
5373   /* mark the icode as generated */
5374   ic->generated = 1;
5375 }
5376
5377 /*-----------------------------------------------------------------*/
5378 /* genCmp :- greater or less than comparison                       */
5379 /*-----------------------------------------------------------------*/
5380 static void
5381 genCmp (operand * left, operand * right,
5382         iCode * ic, iCode * ifx, int sign)
5383 {
5384   int size, offset = 0;
5385   unsigned long lit = 0L;
5386   operand *result;
5387
5388   D (emitcode (";", "genCmp"););
5389
5390   result = IC_RESULT (ic);
5391
5392   /* if left & right are bit variables */
5393   if (AOP_TYPE (left) == AOP_CRY &&
5394       AOP_TYPE (right) == AOP_CRY)
5395     {
5396       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5397       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5398     }
5399   else
5400     {
5401       /* subtract right from left if at the
5402          end the carry flag is set then we know that
5403          left is greater than right */
5404       size = max (AOP_SIZE (left), AOP_SIZE (right));
5405
5406       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5407       if ((size == 1) && !sign 
5408           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5409         {
5410           symbol *lbl = newiTempLabel (NULL);
5411           emitcode ("cjne", "%s,%s,!tlabel",
5412                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5413                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5414                     lbl->key + 100);
5415           emitcode ("", "!tlabeldef", lbl->key + 100);
5416         }
5417       else
5418         {
5419           if (AOP_TYPE (right) == AOP_LIT)
5420             {
5421               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5422               /* optimize if(x < 0) or if(x >= 0) */
5423               if (lit == 0L)
5424                 {
5425                   if (!sign)
5426                     {
5427                       CLRC;
5428                     }
5429                   else
5430                     {
5431                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5432
5433                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5434                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5435
5436                       aopOp (result, ic, FALSE, FALSE);
5437
5438                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5439                         {
5440                           freeAsmop (result, NULL, ic, TRUE);
5441                           genIfxJump (ifx, "acc.7");
5442                           return;
5443                         }
5444                       else
5445                         {
5446                           emitcode ("rlc", "a");
5447                         }
5448                       goto release_freedLR;
5449                     }
5450                   goto release;
5451                 }
5452             }
5453           CLRC;
5454           while (size--)
5455             {
5456               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5457               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5458               // emitcode (";", "genCmp #2");
5459               if (sign && (size == 0))
5460                 {
5461                   // emitcode (";", "genCmp #3");
5462                   emitcode ("xrl", "a,#!constbyte",0x80);
5463                   if (AOP_TYPE (right) == AOP_LIT)
5464                     {
5465                       unsigned long lit = (unsigned long)
5466                       floatFromVal (AOP (right)->aopu.aop_lit);
5467                       // emitcode (";", "genCmp #3.1");
5468                       emitcode ("subb", "a,#!constbyte",
5469                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5470                     }
5471                   else
5472                     {
5473                       // emitcode (";", "genCmp #3.2");
5474                       saveAccWarn = 0;  
5475                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5476                       saveAccWarn = DEFAULT_ACC_WARNING;
5477                       emitcode ("xrl", "b,#!constbyte",0x80);
5478                       emitcode ("subb", "a,b");
5479                     }
5480                 }
5481               else
5482                 {
5483                   const char *s;
5484
5485                   // emitcode (";", "genCmp #4");
5486                   saveAccWarn = 0;
5487                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5488                   saveAccWarn = DEFAULT_ACC_WARNING;
5489
5490                   emitcode ("subb", "a,%s", s);
5491                 }
5492             }
5493         }
5494     }
5495
5496 release:
5497 /* Don't need the left & right operands any more; do need the result. */
5498   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5499   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5500
5501   aopOp (result, ic, FALSE, FALSE);
5502
5503 release_freedLR:
5504
5505   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5506     {
5507       outBitC (result);
5508     }
5509   else
5510     {
5511       /* if the result is used in the next
5512          ifx conditional branch then generate
5513          code a little differently */
5514       if (ifx)
5515         {
5516           genIfxJump (ifx, "c");
5517         }
5518       else
5519         {
5520           outBitC (result);
5521         }
5522       /* leave the result in acc */
5523     }
5524   freeAsmop (result, NULL, ic, TRUE);
5525 }
5526
5527 /*-----------------------------------------------------------------*/
5528 /* genCmpGt :- greater than comparison                             */
5529 /*-----------------------------------------------------------------*/
5530 static void
5531 genCmpGt (iCode * ic, iCode * ifx)
5532 {
5533   operand *left, *right;
5534   sym_link *letype, *retype;
5535   int sign;
5536
5537   D (emitcode (";", "genCmpGt ");
5538     );
5539
5540   left = IC_LEFT (ic);
5541   right = IC_RIGHT (ic);
5542
5543   letype = getSpec (operandType (left));
5544   retype = getSpec (operandType (right));
5545   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5546
5547   /* assign the left & right amsops */
5548   AOP_OP_2 (ic);
5549
5550   genCmp (right, left, ic, ifx, sign);
5551 }
5552
5553 /*-----------------------------------------------------------------*/
5554 /* genCmpLt - less than comparisons                                */
5555 /*-----------------------------------------------------------------*/
5556 static void
5557 genCmpLt (iCode * ic, iCode * ifx)
5558 {
5559   operand *left, *right;
5560   sym_link *letype, *retype;
5561   int sign;
5562
5563   D (emitcode (";", "genCmpLt "););
5564
5565   left = IC_LEFT (ic);
5566   right = IC_RIGHT (ic);
5567
5568   letype = getSpec (operandType (left));
5569   retype = getSpec (operandType (right));
5570   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5571
5572   /* assign the left & right amsops */
5573   AOP_OP_2 (ic);
5574
5575   genCmp (left, right, ic, ifx, sign);
5576 }
5577
5578 /*-----------------------------------------------------------------*/
5579 /* gencjneshort - compare and jump if not equal                    */
5580 /*-----------------------------------------------------------------*/
5581 static void
5582 gencjneshort (operand * left, operand * right, symbol * lbl)
5583 {
5584   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5585   int offset = 0;
5586   unsigned long lit = 0L;
5587
5588   D (emitcode (";", "gencjneshort");
5589     );
5590
5591   /* if the left side is a literal or
5592      if the right is in a pointer register and left
5593      is not */
5594   if ((AOP_TYPE (left) == AOP_LIT) ||
5595       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5596     {
5597       operand *t = right;
5598       right = left;
5599       left = t;
5600     }
5601
5602   if (AOP_TYPE (right) == AOP_LIT)
5603     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5604
5605   if (opIsGptr (left) || opIsGptr (right))
5606     {
5607       /* We are comparing a generic pointer to something.
5608        * Exclude the generic type byte from the comparison.
5609        */
5610       size--;
5611       D (emitcode (";", "cjneshort: generic ptr special case."););
5612     }
5613
5614
5615   /* if the right side is a literal then anything goes */
5616   if (AOP_TYPE (right) == AOP_LIT &&
5617       AOP_TYPE (left) != AOP_DIR)
5618     {
5619       while (size--)
5620         {
5621           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5622           emitcode ("cjne", "a,%s,!tlabel",
5623                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5624                     lbl->key + 100);
5625           offset++;
5626         }
5627     }
5628
5629   /* if the right side is in a register or in direct space or
5630      if the left is a pointer register & right is not */
5631   else if (AOP_TYPE (right) == AOP_REG ||
5632            AOP_TYPE (right) == AOP_DIR ||
5633            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5634            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5635     {
5636       while (size--)
5637         {
5638           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5639           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5640               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5641             emitcode ("jnz", "!tlabel", lbl->key + 100);
5642           else
5643             emitcode ("cjne", "a,%s,!tlabel",
5644                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5645                       lbl->key + 100);
5646           offset++;
5647         }
5648     }
5649   else
5650     {
5651       /* right is a pointer reg need both a & b */
5652       while (size--)
5653         {
5654           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5655           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5656           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5657           offset++;
5658         }
5659     }
5660 }
5661
5662 /*-----------------------------------------------------------------*/
5663 /* gencjne - compare and jump if not equal                         */
5664 /*-----------------------------------------------------------------*/
5665 static void
5666 gencjne (operand * left, operand * right, symbol * lbl)
5667 {
5668   symbol *tlbl = newiTempLabel (NULL);
5669
5670   D (emitcode (";", "gencjne");
5671     );
5672
5673   gencjneshort (left, right, lbl);
5674
5675   emitcode ("mov", "a,%s", one);
5676   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5677   emitcode ("", "!tlabeldef", lbl->key + 100);
5678   emitcode ("clr", "a");
5679   emitcode ("", "!tlabeldef", tlbl->key + 100);
5680 }
5681
5682 /*-----------------------------------------------------------------*/
5683 /* genCmpEq - generates code for equal to                          */
5684 /*-----------------------------------------------------------------*/
5685 static void
5686 genCmpEq (iCode * ic, iCode * ifx)
5687 {
5688   operand *left, *right, *result;
5689
5690   D (emitcode (";", "genCmpEq ");
5691     );
5692
5693   AOP_OP_2 (ic);
5694   AOP_SET_LOCALS (ic);
5695
5696   /* if literal, literal on the right or
5697      if the right is in a pointer register and left
5698      is not */
5699   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5700       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5701     {
5702       operand *t = IC_RIGHT (ic);
5703       IC_RIGHT (ic) = IC_LEFT (ic);
5704       IC_LEFT (ic) = t;
5705     }
5706
5707   if (ifx &&                    /* !AOP_SIZE(result) */
5708       OP_SYMBOL (result) &&
5709       OP_SYMBOL (result)->regType == REG_CND)
5710     {
5711       symbol *tlbl;
5712       /* if they are both bit variables */
5713       if (AOP_TYPE (left) == AOP_CRY &&
5714           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5715         {
5716           if (AOP_TYPE (right) == AOP_LIT)
5717             {
5718               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5719               if (lit == 0L)
5720                 {
5721                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5722                   emitcode ("cpl", "c");
5723                 }
5724               else if (lit == 1L)
5725                 {
5726                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5727                 }
5728               else
5729                 {
5730                   emitcode ("clr", "c");
5731                 }
5732               /* AOP_TYPE(right) == AOP_CRY */
5733             }
5734           else
5735             {
5736               symbol *lbl = newiTempLabel (NULL);
5737               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5738               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5739               emitcode ("cpl", "c");
5740               emitcode ("", "!tlabeldef", (lbl->key + 100));
5741             }
5742           /* if true label then we jump if condition
5743              supplied is true */
5744           tlbl = newiTempLabel (NULL);
5745           if (IC_TRUE (ifx))
5746             {
5747               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5748               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5749             }
5750           else
5751             {
5752               emitcode ("jc", "!tlabel", tlbl->key + 100);
5753               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5754             }
5755           emitcode ("", "!tlabeldef", tlbl->key + 100);
5756         }
5757       else
5758         {
5759           tlbl = newiTempLabel (NULL);
5760           gencjneshort (left, right, tlbl);
5761           if (IC_TRUE (ifx))
5762             {
5763               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5764               emitcode ("", "!tlabeldef", tlbl->key + 100);
5765             }
5766           else
5767             {
5768               symbol *lbl = newiTempLabel (NULL);
5769               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5770               emitcode ("", "!tlabeldef", tlbl->key + 100);
5771               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5772               emitcode ("", "!tlabeldef", lbl->key + 100);
5773             }
5774         }
5775       /* mark the icode as generated */
5776       ifx->generated = 1;
5777
5778       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5779       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5780       return;
5781     }
5782
5783   /* if they are both bit variables */
5784   if (AOP_TYPE (left) == AOP_CRY &&
5785       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5786     {
5787       if (AOP_TYPE (right) == AOP_LIT)
5788         {
5789           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5790           if (lit == 0L)
5791             {
5792               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5793               emitcode ("cpl", "c");
5794             }
5795           else if (lit == 1L)
5796             {
5797               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5798             }
5799           else
5800             {
5801               emitcode ("clr", "c");
5802             }
5803           /* AOP_TYPE(right) == AOP_CRY */
5804         }
5805       else
5806         {
5807           symbol *lbl = newiTempLabel (NULL);
5808           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5809           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5810           emitcode ("cpl", "c");
5811           emitcode ("", "!tlabeldef", (lbl->key + 100));
5812         }
5813
5814       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5815       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5816
5817       aopOp (result, ic, TRUE, FALSE);
5818
5819       /* c = 1 if egal */
5820       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5821         {
5822           outBitC (result);
5823           goto release;
5824         }
5825       if (ifx)
5826         {
5827           genIfxJump (ifx, "c");
5828           goto release;
5829         }
5830       /* if the result is used in an arithmetic operation
5831          then put the result in place */
5832       outBitC (result);
5833     }
5834   else
5835     {
5836       gencjne (left, right, newiTempLabel (NULL));
5837
5838       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5839       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5840
5841       aopOp (result, ic, TRUE, FALSE);
5842
5843       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5844         {
5845           aopPut (AOP (result), "a", 0);
5846           goto release;
5847         }
5848       if (ifx)
5849         {
5850           genIfxJump (ifx, "a");
5851           goto release;
5852         }
5853       /* if the result is used in an arithmetic operation
5854          then put the result in place */
5855       if (AOP_TYPE (result) != AOP_CRY)
5856         outAcc (result);
5857       /* leave the result in acc */
5858     }
5859
5860 release:
5861   freeAsmop (result, NULL, ic, TRUE);
5862 }
5863
5864 /*-----------------------------------------------------------------*/
5865 /* ifxForOp - returns the icode containing the ifx for operand     */
5866 /*-----------------------------------------------------------------*/
5867 static iCode *
5868 ifxForOp (operand * op, iCode * ic)
5869 {
5870   /* if true symbol then needs to be assigned */
5871   if (IS_TRUE_SYMOP (op))
5872     return NULL;
5873
5874   /* if this has register type condition and
5875      the next instruction is ifx with the same operand
5876      and live to of the operand is upto the ifx only then */
5877   if (ic->next &&
5878       ic->next->op == IFX &&
5879       IC_COND (ic->next)->key == op->key &&
5880       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5881     return ic->next;
5882
5883   return NULL;
5884 }
5885 /*-----------------------------------------------------------------*/
5886 /* hasInc - operand is incremented before any other use            */
5887 /*-----------------------------------------------------------------*/
5888 static iCode *
5889 hasInc (operand *op, iCode *ic, int osize)
5890 {
5891   sym_link *type = operandType(op);
5892   sym_link *retype = getSpec (type);
5893   iCode *lic = ic->next;
5894   int isize ;
5895   
5896   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5897   if (!IS_SYMOP(op)) return NULL;
5898
5899   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5900   if (IS_AGGREGATE(type->next)) return NULL;
5901   if (osize != (isize = getSize(type->next))) return NULL;
5902
5903   while (lic) {
5904       /* if operand of the form op = op + <sizeof *op> */
5905       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5906           isOperandEqual(IC_RESULT(lic),op) && 
5907           isOperandLiteral(IC_RIGHT(lic)) &&
5908           operandLitValue(IC_RIGHT(lic)) == isize) {
5909           return lic;
5910       }
5911       /* if the operand used or deffed */
5912       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5913           return NULL;
5914       }
5915       /* if GOTO or IFX */
5916       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5917       lic = lic->next;
5918   }
5919   return NULL;
5920 }
5921
5922 /*-----------------------------------------------------------------*/
5923 /* genAndOp - for && operation                                     */
5924 /*-----------------------------------------------------------------*/
5925 static void
5926 genAndOp (iCode * ic)
5927 {
5928   operand *left, *right, *result;
5929   symbol *tlbl;
5930
5931   D (emitcode (";", "genAndOp "););
5932
5933   /* note here that && operations that are in an
5934      if statement are taken away by backPatchLabels
5935      only those used in arthmetic operations remain */
5936   AOP_OP_2 (ic);
5937   AOP_SET_LOCALS (ic);
5938
5939   /* if both are bit variables */
5940   if (AOP_TYPE (left) == AOP_CRY &&
5941       AOP_TYPE (right) == AOP_CRY)
5942     {
5943       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5944       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5945       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5946       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5947   
5948       aopOp (result,ic,FALSE, FALSE);
5949       outBitC (result);
5950     }
5951   else
5952     {
5953       tlbl = newiTempLabel (NULL);
5954       toBoolean (left);
5955       emitcode ("jz", "!tlabel", tlbl->key + 100);
5956       toBoolean (right);
5957       emitcode ("", "!tlabeldef", tlbl->key + 100);
5958       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5959       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5960   
5961       aopOp (result,ic,FALSE, FALSE);
5962       outBitAcc (result);
5963     }
5964     freeAsmop (result, NULL, ic, TRUE);
5965 }
5966
5967
5968 /*-----------------------------------------------------------------*/
5969 /* genOrOp - for || operation                                      */
5970 /*-----------------------------------------------------------------*/
5971 static void
5972 genOrOp (iCode * ic)
5973 {
5974   operand *left, *right, *result;
5975   symbol *tlbl;
5976
5977   D (emitcode (";", "genOrOp "););
5978
5979   /* note here that || operations that are in an
5980      if statement are taken away by backPatchLabels
5981      only those used in arthmetic operations remain */
5982   AOP_OP_2 (ic);
5983   AOP_SET_LOCALS (ic);
5984
5985   /* if both are bit variables */
5986   if (AOP_TYPE (left) == AOP_CRY &&
5987       AOP_TYPE (right) == AOP_CRY)
5988     {
5989       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5990       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5991       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5992       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5993   
5994       aopOp (result,ic,FALSE, FALSE);
5995       
5996       outBitC (result);
5997     }
5998   else
5999     {
6000       tlbl = newiTempLabel (NULL);
6001       toBoolean (left);
6002       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6003       toBoolean (right);
6004       emitcode ("", "!tlabeldef", tlbl->key + 100);
6005       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6006       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6007   
6008       aopOp (result,ic,FALSE, FALSE);
6009       
6010       outBitAcc (result);
6011     }
6012
6013   freeAsmop (result, NULL, ic, TRUE);
6014 }
6015
6016 /*-----------------------------------------------------------------*/
6017 /* isLiteralBit - test if lit == 2^n                               */
6018 /*-----------------------------------------------------------------*/
6019 static int
6020 isLiteralBit (unsigned long lit)
6021 {
6022   unsigned long pw[32] =
6023   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6024    0x100L, 0x200L, 0x400L, 0x800L,
6025    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6026    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6027    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6028    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6029    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6030   int idx;
6031
6032   for (idx = 0; idx < 32; idx++)
6033     if (lit == pw[idx])
6034       return idx + 1;
6035   return 0;
6036 }
6037
6038 /*-----------------------------------------------------------------*/
6039 /* continueIfTrue -                                                */
6040 /*-----------------------------------------------------------------*/
6041 static void
6042 continueIfTrue (iCode * ic)
6043 {
6044   if (IC_TRUE (ic))
6045     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6046   ic->generated = 1;
6047 }
6048
6049 /*-----------------------------------------------------------------*/
6050 /* jmpIfTrue -                                                     */
6051 /*-----------------------------------------------------------------*/
6052 static void
6053 jumpIfTrue (iCode * ic)
6054 {
6055   if (!IC_TRUE (ic))
6056     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6057   ic->generated = 1;
6058 }
6059
6060 /*-----------------------------------------------------------------*/
6061 /* jmpTrueOrFalse -                                                */
6062 /*-----------------------------------------------------------------*/
6063 static void
6064 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6065 {
6066   // ugly but optimized by peephole
6067   if (IC_TRUE (ic))
6068     {
6069       symbol *nlbl = newiTempLabel (NULL);
6070       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6071       emitcode ("", "!tlabeldef", tlbl->key + 100);
6072       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6073       emitcode ("", "!tlabeldef", nlbl->key + 100);
6074     }
6075   else
6076     {
6077       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6078       emitcode ("", "!tlabeldef", tlbl->key + 100);
6079     }
6080   ic->generated = 1;
6081 }
6082
6083 // Generate code to perform a bit-wise logic operation
6084 // on two operands in far space (assumed to already have been 
6085 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6086 // in far space. This requires pushing the result on the stack
6087 // then popping it into the result.
6088 static void
6089 genFarFarLogicOp(iCode *ic, char *logicOp)
6090 {
6091       int size, resultSize, compSize;
6092       int offset = 0;
6093       
6094       TR_AP("#5");
6095       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6096       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6097                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6098       
6099       _startLazyDPSEvaluation();
6100       for (size = compSize; (size--); offset++)
6101       {
6102           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6103           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6104           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6105           
6106           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6107           emitcode ("push", "acc");
6108       }
6109       _endLazyDPSEvaluation();
6110      
6111       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6112       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6113       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6114      
6115       resultSize = AOP_SIZE(IC_RESULT(ic));
6116
6117       ADJUST_PUSHED_RESULT(compSize, resultSize);
6118
6119       _startLazyDPSEvaluation();
6120       while (compSize--)
6121       {
6122           emitcode ("pop", "acc");
6123           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6124       }
6125       _endLazyDPSEvaluation();
6126       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6127 }
6128
6129
6130 /*-----------------------------------------------------------------*/
6131 /* genAnd  - code for and                                          */
6132 /*-----------------------------------------------------------------*/
6133 static void
6134 genAnd (iCode * ic, iCode * ifx)
6135 {
6136   operand *left, *right, *result;
6137   int size, offset = 0;
6138   unsigned long lit = 0L;
6139   int bytelit;
6140   char buff[10];
6141   bool pushResult;
6142
6143   D (emitcode (";", "genAnd "););
6144
6145   AOP_OP_3_NOFATAL (ic, pushResult);
6146   AOP_SET_LOCALS (ic);
6147
6148   if (pushResult)
6149   {
6150       genFarFarLogicOp(ic, "anl");
6151       return;
6152   }  
6153
6154 #ifdef DEBUG_TYPE
6155   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6156             AOP_TYPE (result),
6157             AOP_TYPE (left), AOP_TYPE (right));
6158   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6159             AOP_SIZE (result),
6160             AOP_SIZE (left), AOP_SIZE (right));
6161 #endif
6162
6163   /* if left is a literal & right is not then exchange them */
6164   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6165 #ifdef LOGIC_OPS_BROKEN      
6166     ||  AOP_NEEDSACC (left)
6167 #endif
6168     )
6169     {
6170       operand *tmp = right;
6171       right = left;
6172       left = tmp;
6173     }
6174
6175   /* if result = right then exchange them */
6176   if (sameRegs (AOP (result), AOP (right)))
6177     {
6178       operand *tmp = right;
6179       right = left;
6180       left = tmp;
6181     }
6182
6183   /* if right is bit then exchange them */
6184   if (AOP_TYPE (right) == AOP_CRY &&
6185       AOP_TYPE (left) != AOP_CRY)
6186     {
6187       operand *tmp = right;
6188       right = left;
6189       left = tmp;
6190     }
6191   if (AOP_TYPE (right) == AOP_LIT)
6192     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6193
6194   size = AOP_SIZE (result);
6195
6196   // if(bit & yy)
6197   // result = bit & yy;
6198   if (AOP_TYPE (left) == AOP_CRY)
6199     {
6200       // c = bit & literal;
6201       if (AOP_TYPE (right) == AOP_LIT)
6202         {
6203           if (lit & 1)
6204             {
6205               if (size && sameRegs (AOP (result), AOP (left)))
6206                 // no change
6207                 goto release;
6208               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6209             }
6210           else
6211             {
6212               // bit(result) = 0;
6213               if (size && (AOP_TYPE (result) == AOP_CRY))
6214                 {
6215                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6216                   goto release;
6217                 }
6218               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6219                 {
6220                   jumpIfTrue (ifx);
6221                   goto release;
6222                 }
6223               emitcode ("clr", "c");
6224             }
6225         }
6226       else
6227         {
6228           if (AOP_TYPE (right) == AOP_CRY)
6229             {
6230               // c = bit & bit;
6231               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6232               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6233             }
6234           else
6235             {
6236               // c = bit & val;
6237               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6238               // c = lsb
6239               emitcode ("rrc", "a");
6240               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6241             }
6242         }
6243       // bit = c
6244       // val = c
6245       if (size)
6246         outBitC (result);
6247       // if(bit & ...)
6248       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6249         genIfxJump (ifx, "c");
6250       goto release;
6251     }
6252
6253   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6254   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6255   if ((AOP_TYPE (right) == AOP_LIT) &&
6256       (AOP_TYPE (result) == AOP_CRY) &&
6257       (AOP_TYPE (left) != AOP_CRY))
6258     {
6259       int posbit = isLiteralBit (lit);
6260       /* left &  2^n */
6261       if (posbit)
6262         {
6263           posbit--;
6264           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6265           // bit = left & 2^n
6266           if (size)
6267             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6268           // if(left &  2^n)
6269           else
6270             {
6271               if (ifx)
6272                 {
6273                   SNPRINTF (buff, sizeof(buff), 
6274                             "acc.%d", posbit & 0x07);
6275                   genIfxJump (ifx, buff);
6276                 }
6277               else 
6278                   {
6279                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6280                   }
6281               goto release;
6282             }
6283         }
6284       else
6285         {
6286           symbol *tlbl = newiTempLabel (NULL);
6287           int sizel = AOP_SIZE (left);
6288           if (size)
6289             emitcode ("setb", "c");
6290           while (sizel--)
6291             {
6292               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6293                 {
6294                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6295                   // byte ==  2^n ?
6296                   if ((posbit = isLiteralBit (bytelit)) != 0)
6297                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6298                   else
6299                     {
6300                       if (bytelit != 0x0FFL)
6301                         emitcode ("anl", "a,%s",
6302                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6303                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6304                     }
6305                 }
6306               offset++;
6307             }
6308           // bit = left & literal
6309           if (size)
6310             {
6311               emitcode ("clr", "c");
6312               emitcode ("", "!tlabeldef", tlbl->key + 100);
6313             }
6314           // if(left & literal)
6315           else
6316             {
6317               if (ifx)
6318                 jmpTrueOrFalse (ifx, tlbl);
6319               goto release;
6320             }
6321         }
6322       outBitC (result);
6323       goto release;
6324     }
6325
6326   /* if left is same as result */
6327   if (sameRegs (AOP (result), AOP (left)))
6328     {
6329       for (; size--; offset++)
6330         {
6331           if (AOP_TYPE (right) == AOP_LIT)
6332             {
6333               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6334                 continue;
6335               else if (bytelit == 0)
6336                 aopPut (AOP (result), zero, offset);
6337               else if (IS_AOP_PREG (result))
6338                 {
6339                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6340                   emitcode ("anl", "a,%s",
6341                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6342                   aopPut (AOP (result), "a", offset);
6343                 }
6344               else
6345                 emitcode ("anl", "%s,%s",
6346                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6347                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6348             }
6349           else
6350             {
6351               if (AOP_TYPE (left) == AOP_ACC)
6352                 emitcode ("anl", "a,%s",
6353                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6354               else
6355                 {
6356                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6357                   if (IS_AOP_PREG (result))
6358                     {
6359                       emitcode ("anl", "a,%s",
6360                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6361                       aopPut (AOP (result), "a", offset);
6362                     }
6363                   else
6364                     emitcode ("anl", "%s,a",
6365                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6366                 }
6367             }
6368         }
6369     }
6370   else
6371     {
6372       // left & result in different registers
6373       if (AOP_TYPE (result) == AOP_CRY)
6374         {
6375           // result = bit
6376           // if(size), result in bit
6377           // if(!size && ifx), conditional oper: if(left & right)
6378           symbol *tlbl = newiTempLabel (NULL);
6379           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6380           if (size)
6381             emitcode ("setb", "c");
6382           while (sizer--)
6383             {
6384               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6385                 emitcode ("anl", "a,%s",
6386                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6387               } else {
6388                 if (AOP_TYPE(left)==AOP_ACC) {
6389                   emitcode("mov", "b,a");
6390                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6391                   emitcode("anl", "a,b");
6392                 }else {
6393                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6394                   emitcode ("anl", "a,%s",
6395                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6396                 }
6397               }
6398               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6399               offset++;
6400             }
6401           if (size)
6402             {
6403               CLRC;
6404               emitcode ("", "!tlabeldef", tlbl->key + 100);
6405               outBitC (result);
6406             }
6407           else if (ifx)
6408             jmpTrueOrFalse (ifx, tlbl);
6409         }
6410       else
6411         {
6412           for (; (size--); offset++)
6413             {
6414               // normal case
6415               // result = left & right
6416               if (AOP_TYPE (right) == AOP_LIT)
6417                 {
6418                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6419                     {
6420                       aopPut (AOP (result),
6421                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6422                               offset);
6423                       continue;
6424                     }
6425                   else if (bytelit == 0)
6426                     {
6427                       aopPut (AOP (result), zero, offset);
6428                       continue;
6429                     }
6430                   D (emitcode (";", "better literal AND."););
6431                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6432                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6433                                                     FALSE, FALSE, DP2_RESULT_REG));
6434
6435                 }
6436               else
6437                 {
6438                   // faster than result <- left, anl result,right
6439                   // and better if result is SFR
6440                   if (AOP_TYPE (left) == AOP_ACC)
6441                     {
6442                       emitcode ("anl", "a,%s", 
6443                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6444                     }
6445                   else
6446                     {
6447                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6448                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6449                       {
6450                           emitcode("mov", "b,a");
6451                           rOp = "b";
6452                       }
6453                         
6454                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6455                       emitcode ("anl", "a,%s", rOp);
6456                     }                   
6457                 }
6458               aopPut (AOP (result), "a", offset);
6459             }
6460         }
6461     }
6462
6463 release:
6464   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6465   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6466   freeAsmop (result, NULL, ic, TRUE);
6467 }
6468
6469
6470 /*-----------------------------------------------------------------*/
6471 /* genOr  - code for or                                            */
6472 /*-----------------------------------------------------------------*/
6473 static void
6474 genOr (iCode * ic, iCode * ifx)
6475 {
6476   operand *left, *right, *result;
6477   int size, offset = 0;
6478   unsigned long lit = 0L;
6479   bool     pushResult;
6480
6481   D (emitcode (";", "genOr "););
6482
6483   AOP_OP_3_NOFATAL (ic, pushResult);
6484   AOP_SET_LOCALS (ic);
6485
6486   if (pushResult)
6487   {
6488       genFarFarLogicOp(ic, "orl");
6489       return;
6490   }
6491
6492
6493 #ifdef DEBUG_TYPE
6494   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6495             AOP_TYPE (result),
6496             AOP_TYPE (left), AOP_TYPE (right));
6497   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6498             AOP_SIZE (result),
6499             AOP_SIZE (left), AOP_SIZE (right));
6500 #endif
6501
6502   /* if left is a literal & right is not then exchange them */
6503   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6504 #ifdef LOGIC_OPS_BROKEN
6505    || AOP_NEEDSACC (left) // I think this is a net loss now.
6506 #endif      
6507       )
6508     {
6509       operand *tmp = right;
6510       right = left;
6511       left = tmp;
6512     }
6513
6514   /* if result = right then exchange them */
6515   if (sameRegs (AOP (result), AOP (right)))
6516     {
6517       operand *tmp = right;
6518       right = left;
6519       left = tmp;
6520     }
6521
6522   /* if right is bit then exchange them */
6523   if (AOP_TYPE (right) == AOP_CRY &&
6524       AOP_TYPE (left) != AOP_CRY)
6525     {
6526       operand *tmp = right;
6527       right = left;
6528       left = tmp;
6529     }
6530   if (AOP_TYPE (right) == AOP_LIT)
6531     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6532
6533   size = AOP_SIZE (result);
6534
6535   // if(bit | yy)
6536   // xx = bit | yy;
6537   if (AOP_TYPE (left) == AOP_CRY)
6538     {
6539       if (AOP_TYPE (right) == AOP_LIT)
6540         {
6541           // c = bit & literal;
6542           if (lit)
6543             {
6544               // lit != 0 => result = 1
6545               if (AOP_TYPE (result) == AOP_CRY)
6546                 {
6547                   if (size)
6548                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6549                   else if (ifx)
6550                     continueIfTrue (ifx);
6551                   goto release;
6552                 }
6553               emitcode ("setb", "c");
6554             }
6555           else
6556             {
6557               // lit == 0 => result = left
6558               if (size && sameRegs (AOP (result), AOP (left)))
6559                 goto release;
6560               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6561             }
6562         }
6563       else
6564         {
6565           if (AOP_TYPE (right) == AOP_CRY)
6566             {
6567               // c = bit | bit;
6568               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6569               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6570             }
6571           else
6572             {
6573               // c = bit | val;
6574               symbol *tlbl = newiTempLabel (NULL);
6575               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6576                 emitcode ("setb", "c");
6577               emitcode ("jb", "%s,!tlabel",
6578                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6579               toBoolean (right);
6580               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6581               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6582                 {
6583                   jmpTrueOrFalse (ifx, tlbl);
6584                   goto release;
6585                 }
6586               else
6587                 {
6588                   CLRC;
6589                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6590                 }
6591             }
6592         }
6593       // bit = c
6594       // val = c
6595       if (size)
6596         outBitC (result);
6597       // if(bit | ...)
6598       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6599            genIfxJump (ifx, "c");
6600       goto release;
6601     }
6602
6603   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6604   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6605   if ((AOP_TYPE (right) == AOP_LIT) &&
6606       (AOP_TYPE (result) == AOP_CRY) &&
6607       (AOP_TYPE (left) != AOP_CRY))
6608     {
6609       if (lit)
6610         {
6611           // result = 1
6612           if (size)
6613             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6614           else
6615             continueIfTrue (ifx);
6616           goto release;
6617         }
6618       else
6619         {
6620           // lit = 0, result = boolean(left)
6621           if (size)
6622             emitcode ("setb", "c");
6623           toBoolean (right);
6624           if (size)
6625             {
6626               symbol *tlbl = newiTempLabel (NULL);
6627               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6628               CLRC;
6629               emitcode ("", "!tlabeldef", tlbl->key + 100);
6630             }
6631           else
6632             {
6633               genIfxJump (ifx, "a");
6634               goto release;
6635             }
6636         }
6637       outBitC (result);
6638       goto release;
6639     }
6640
6641   /* if left is same as result */
6642   if (sameRegs (AOP (result), AOP (left)))
6643     {
6644       for (; size--; offset++)
6645         {
6646           if (AOP_TYPE (right) == AOP_LIT)
6647             {
6648               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6649                 {
6650                   continue;
6651                 }
6652               else
6653                 {
6654                   if (IS_AOP_PREG (left))
6655                     {
6656                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6657                       emitcode ("orl", "a,%s",
6658                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6659                       aopPut (AOP (result), "a", offset);
6660                     }
6661                   else
6662                     {
6663                       emitcode ("orl", "%s,%s",
6664                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6665                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6666                     }
6667                 }
6668             }
6669           else
6670             {
6671               if (AOP_TYPE (left) == AOP_ACC)
6672                 {
6673                   emitcode ("orl", "a,%s",
6674                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6675                 }
6676               else
6677                 {
6678                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6679                   if (IS_AOP_PREG (left))
6680                     {
6681                       emitcode ("orl", "a,%s", 
6682                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6683                       aopPut (AOP (result), "a", offset);
6684                     }
6685                   else
6686                     {
6687                       emitcode ("orl", "%s,a",
6688                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6689                     }
6690                 }
6691             }
6692         }
6693     }
6694   else
6695     {
6696       // left & result in different registers
6697       if (AOP_TYPE (result) == AOP_CRY)
6698         {
6699           // result = bit
6700           // if(size), result in bit
6701           // if(!size && ifx), conditional oper: if(left | right)
6702           symbol *tlbl = newiTempLabel (NULL);
6703           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6704           if (size)
6705             emitcode ("setb", "c");
6706           while (sizer--)
6707             {
6708               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6709                 emitcode ("orl", "a,%s",
6710                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6711               } else {
6712                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6713                 emitcode ("orl", "a,%s",
6714                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6715               }
6716               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6717               offset++;
6718             }
6719           if (size)
6720             {
6721               CLRC;
6722               emitcode ("", "!tlabeldef", tlbl->key + 100);
6723               outBitC (result);
6724             }
6725           else if (ifx)
6726             jmpTrueOrFalse (ifx, tlbl);
6727         }
6728       else
6729         {
6730             _startLazyDPSEvaluation();
6731           for (; (size--); offset++)
6732             {
6733               // normal case
6734               // result = left & right
6735               if (AOP_TYPE (right) == AOP_LIT)
6736                 {
6737                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6738                     {
6739                       aopPut (AOP (result),
6740                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6741                               offset);
6742                       continue;
6743                     }
6744                   D (emitcode (";", "better literal OR."););
6745                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6746                   emitcode ("orl", "a, %s",
6747                             aopGet (AOP (right), offset,
6748                                     FALSE, FALSE, DP2_RESULT_REG));
6749
6750                 }
6751               else
6752                 {
6753                   // faster than result <- left, anl result,right
6754                   // and better if result is SFR
6755                   if (AOP_TYPE (left) == AOP_ACC)
6756                     {
6757                       emitcode ("orl", "a,%s",
6758                                 aopGet (AOP (right), offset,
6759                                         FALSE, FALSE, DP2_RESULT_REG));
6760                     }
6761                   else
6762                     {
6763                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6764                         
6765                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6766                       {
6767                           emitcode("mov", "b,a");
6768                           rOp = "b";
6769                       }
6770                         
6771                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6772                       emitcode ("orl", "a,%s", rOp);
6773                     }
6774                 }
6775               aopPut (AOP (result), "a", offset);
6776             }
6777             _endLazyDPSEvaluation();
6778         }
6779     }
6780
6781 release:
6782   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6783   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6784   freeAsmop (result, NULL, ic, TRUE);
6785 }
6786
6787 /*-----------------------------------------------------------------*/
6788 /* genXor - code for xclusive or                                   */
6789 /*-----------------------------------------------------------------*/
6790 static void
6791 genXor (iCode * ic, iCode * ifx)
6792 {
6793   operand *left, *right, *result;
6794   int size, offset = 0;
6795   unsigned long lit = 0L;
6796   bool pushResult;
6797
6798   D (emitcode (";", "genXor "););
6799
6800   AOP_OP_3_NOFATAL (ic, pushResult);
6801   AOP_SET_LOCALS (ic);
6802
6803   if (pushResult)
6804   {
6805       genFarFarLogicOp(ic, "xrl");
6806       return;
6807   }  
6808
6809 #ifdef DEBUG_TYPE
6810   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6811             AOP_TYPE (result),
6812             AOP_TYPE (left), AOP_TYPE (right));
6813   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6814             AOP_SIZE (result),
6815             AOP_SIZE (left), AOP_SIZE (right));
6816 #endif
6817
6818   /* if left is a literal & right is not ||
6819      if left needs acc & right does not */
6820   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6821 #ifdef LOGIC_OPS_BROKEN      
6822       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6823 #endif
6824      )
6825     {
6826       operand *tmp = right;
6827       right = left;
6828       left = tmp;
6829     }
6830
6831   /* if result = right then exchange them */
6832   if (sameRegs (AOP (result), AOP (right)))
6833     {
6834       operand *tmp = right;
6835       right = left;
6836       left = tmp;
6837     }
6838
6839   /* if right is bit then exchange them */
6840   if (AOP_TYPE (right) == AOP_CRY &&
6841       AOP_TYPE (left) != AOP_CRY)
6842     {
6843       operand *tmp = right;
6844       right = left;
6845       left = tmp;
6846     }
6847   if (AOP_TYPE (right) == AOP_LIT)
6848     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6849
6850   size = AOP_SIZE (result);
6851
6852   // if(bit ^ yy)
6853   // xx = bit ^ yy;
6854   if (AOP_TYPE (left) == AOP_CRY)
6855     {
6856       if (AOP_TYPE (right) == AOP_LIT)
6857         {
6858           // c = bit & literal;
6859           if (lit >> 1)
6860             {
6861               // lit>>1  != 0 => result = 1
6862               if (AOP_TYPE (result) == AOP_CRY)
6863                 {
6864                   if (size)
6865                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6866                   else if (ifx)
6867                     continueIfTrue (ifx);
6868                   goto release;
6869                 }
6870               emitcode ("setb", "c");
6871             }
6872           else
6873             {
6874               // lit == (0 or 1)
6875               if (lit == 0)
6876                 {
6877                   // lit == 0, result = left
6878                   if (size && sameRegs (AOP (result), AOP (left)))
6879                     goto release;
6880                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6881                 }
6882               else
6883                 {
6884                   // lit == 1, result = not(left)
6885                   if (size && sameRegs (AOP (result), AOP (left)))
6886                     {
6887                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6888                       goto release;
6889                     }
6890                   else
6891                     {
6892                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6893                       emitcode ("cpl", "c");
6894                     }
6895                 }
6896             }
6897
6898         }
6899       else
6900         {
6901           // right != literal
6902           symbol *tlbl = newiTempLabel (NULL);
6903           if (AOP_TYPE (right) == AOP_CRY)
6904             {
6905               // c = bit ^ bit;
6906               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6907             }
6908           else
6909             {
6910               int sizer = AOP_SIZE (right);
6911               // c = bit ^ val
6912               // if val>>1 != 0, result = 1
6913               emitcode ("setb", "c");
6914               while (sizer)
6915                 {
6916                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6917                   if (sizer == 1)
6918                     // test the msb of the lsb
6919                     emitcode ("anl", "a,#!constbyte",0xfe);
6920                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6921                   sizer--;
6922                 }
6923               // val = (0,1)
6924               emitcode ("rrc", "a");
6925             }
6926           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6927           emitcode ("cpl", "c");
6928           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6929         }
6930       // bit = c
6931       // val = c
6932       if (size)
6933         outBitC (result);
6934       // if(bit | ...)
6935       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6936         genIfxJump (ifx, "c");
6937       goto release;
6938     }
6939
6940   if (sameRegs (AOP (result), AOP (left)))
6941     {
6942       /* if left is same as result */
6943       for (; size--; offset++)
6944         {
6945           if (AOP_TYPE (right) == AOP_LIT)
6946             {
6947               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6948                 continue;
6949               else if (IS_AOP_PREG (left))
6950                 {
6951                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6952                   emitcode ("xrl", "a,%s",
6953                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6954                   aopPut (AOP (result), "a", offset);
6955                 }
6956               else
6957                 emitcode ("xrl", "%s,%s",
6958                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6959                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6960             }
6961           else
6962             {
6963               if (AOP_TYPE (left) == AOP_ACC)
6964                 emitcode ("xrl", "a,%s",
6965                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6966               else
6967                 {
6968                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6969                   if (IS_AOP_PREG (left))
6970                     {
6971                       emitcode ("xrl", "a,%s",
6972                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6973                       aopPut (AOP (result), "a", offset);
6974                     }
6975                   else
6976                     emitcode ("xrl", "%s,a",
6977                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6978                 }
6979             }
6980         }
6981     }
6982   else
6983     {
6984       // left & result in different registers
6985       if (AOP_TYPE (result) == AOP_CRY)
6986         {
6987           // result = bit
6988           // if(size), result in bit
6989           // if(!size && ifx), conditional oper: if(left ^ right)
6990           symbol *tlbl = newiTempLabel (NULL);
6991           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6992                   
6993           if (size)
6994             emitcode ("setb", "c");
6995           while (sizer--)
6996             {
6997               if ((AOP_TYPE (right) == AOP_LIT) &&
6998                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6999                 {
7000                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7001                 }
7002               else
7003                 {
7004                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7005                     emitcode ("xrl", "a,%s",
7006                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7007                   } else {
7008                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7009                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7010                       {
7011                           emitcode("mov", "b,a");
7012                           rOp = "b";
7013                       }
7014                         
7015                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7016                       emitcode ("xrl", "a,%s", rOp);                  
7017                   }
7018                 }
7019               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7020               offset++;
7021             }
7022           if (size)
7023             {
7024               CLRC;
7025               emitcode ("", "!tlabeldef", tlbl->key + 100);
7026               outBitC (result);
7027             }
7028           else if (ifx)
7029             jmpTrueOrFalse (ifx, tlbl);
7030         }
7031       else
7032         {
7033         for (; (size--); offset++)
7034           {
7035             // normal case
7036             // result = left & right
7037             if (AOP_TYPE (right) == AOP_LIT)
7038               {
7039                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7040                   {
7041                     aopPut (AOP (result),
7042                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7043                             offset);
7044                     continue;
7045                   }
7046                 D (emitcode (";", "better literal XOR."););
7047                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7048                 emitcode ("xrl", "a, %s",
7049                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7050               }
7051             else
7052               {
7053                 // faster than result <- left, anl result,right
7054                 // and better if result is SFR
7055                 if (AOP_TYPE (left) == AOP_ACC)
7056                   {
7057                     emitcode ("xrl", "a,%s",
7058                               aopGet (AOP (right), offset,
7059                                       FALSE, FALSE, DP2_RESULT_REG));
7060                   }
7061                 else
7062                   {
7063                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7064                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7065                       {
7066                           emitcode("mov", "b,a");
7067                           rOp = "b";
7068                       }
7069                         
7070                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7071                       emitcode ("xrl", "a,%s", rOp);
7072                   }
7073               }
7074             aopPut (AOP (result), "a", offset);
7075           }
7076         }
7077         
7078     }
7079
7080 release:
7081   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7082   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7083   freeAsmop (result, NULL, ic, TRUE);
7084 }
7085
7086 /*-----------------------------------------------------------------*/
7087 /* genInline - write the inline code out                           */
7088 /*-----------------------------------------------------------------*/
7089 static void
7090 genInline (iCode * ic)
7091 {
7092   char *buffer, *bp, *bp1;
7093
7094   D (emitcode (";", "genInline "); );
7095
7096   _G.inLine += (!options.asmpeep);
7097
7098   buffer = Safe_strdup(IC_INLINE(ic));
7099   bp = buffer;
7100   bp1 = buffer;
7101
7102   /* emit each line as a code */
7103   while (*bp)
7104     {
7105       if (*bp == '\n')
7106         {
7107           *bp++ = '\0';
7108           emitcode (bp1, "");
7109           bp1 = bp;
7110         }
7111       else
7112         {
7113           if (*bp == ':')
7114             {
7115               bp++;
7116               *bp = '\0';
7117               bp++;
7118               emitcode (bp1, "");
7119               bp1 = bp;
7120             }
7121           else
7122             bp++;
7123         }
7124     }
7125   if (bp1 != bp)
7126     emitcode (bp1, "");
7127   /*     emitcode("",buffer); */
7128   _G.inLine -= (!options.asmpeep);
7129 }
7130
7131 /*-----------------------------------------------------------------*/
7132 /* genRRC - rotate right with carry                                */
7133 /*-----------------------------------------------------------------*/
7134 static void
7135 genRRC (iCode * ic)
7136 {
7137   operand *left, *result;
7138   int     size, offset;
7139
7140   D (emitcode (";", "genRRC "););
7141
7142   /* rotate right with carry */
7143   left = IC_LEFT (ic);
7144   result = IC_RESULT (ic);
7145   aopOp (left, ic, FALSE, FALSE);
7146   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7147
7148   /* move it to the result */
7149   size = AOP_SIZE (result);
7150   offset = size - 1;
7151   CLRC;
7152
7153   _startLazyDPSEvaluation ();
7154   while (size--)
7155     {
7156       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7157       emitcode ("rrc", "a");
7158       if (AOP_SIZE (result) > 1)
7159         aopPut (AOP (result), "a", offset--);
7160     }
7161   _endLazyDPSEvaluation ();
7162
7163   /* now we need to put the carry into the
7164      highest order byte of the result */
7165   if (AOP_SIZE (result) > 1)
7166     {
7167       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7168     }
7169   emitcode ("mov", "acc.7,c");
7170   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7171   freeAsmop (left, NULL, ic, TRUE);
7172   freeAsmop (result, NULL, ic, TRUE);
7173 }
7174
7175 /*-----------------------------------------------------------------*/
7176 /* genRLC - generate code for rotate left with carry               */
7177 /*-----------------------------------------------------------------*/
7178 static void
7179 genRLC (iCode * ic)
7180 {
7181   operand *left, *result;
7182   int size, offset;
7183   char *l;
7184
7185   D (emitcode (";", "genRLC "););
7186
7187   /* rotate right with carry */
7188   left = IC_LEFT (ic);
7189   result = IC_RESULT (ic);
7190   aopOp (left, ic, FALSE, FALSE);
7191   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7192
7193   /* move it to the result */
7194   size = AOP_SIZE (result);
7195   offset = 0;
7196   if (size--)
7197     {
7198       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7199       MOVA (l);
7200       emitcode ("add", "a,acc");
7201       if (AOP_SIZE (result) > 1)
7202         {
7203           aopPut (AOP (result), "a", offset++);
7204         }
7205
7206       _startLazyDPSEvaluation ();
7207       while (size--)
7208         {
7209           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7210           MOVA (l);
7211           emitcode ("rlc", "a");
7212           if (AOP_SIZE (result) > 1)
7213             aopPut (AOP (result), "a", offset++);
7214         }
7215       _endLazyDPSEvaluation ();
7216     }
7217   /* now we need to put the carry into the
7218      highest order byte of the result */
7219   if (AOP_SIZE (result) > 1)
7220     {
7221       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7222       MOVA (l);
7223     }
7224   emitcode ("mov", "acc.0,c");
7225   aopPut (AOP (result), "a", 0);
7226   freeAsmop (left, NULL, ic, TRUE);
7227   freeAsmop (result, NULL, ic, TRUE);
7228 }
7229
7230 /*-----------------------------------------------------------------*/
7231 /* genGetHbit - generates code get highest order bit               */
7232 /*-----------------------------------------------------------------*/
7233 static void
7234 genGetHbit (iCode * ic)
7235 {
7236   operand *left, *result;
7237   left = IC_LEFT (ic);
7238   result = IC_RESULT (ic);
7239   aopOp (left, ic, FALSE, FALSE);
7240   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7241
7242   D (emitcode (";", "genGetHbit "););
7243
7244   /* get the highest order byte into a */
7245   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7246   if (AOP_TYPE (result) == AOP_CRY)
7247     {
7248       emitcode ("rlc", "a");
7249       outBitC (result);
7250     }
7251   else
7252     {
7253       emitcode ("rl", "a");
7254       emitcode ("anl", "a,#1");
7255       outAcc (result);
7256     }
7257
7258
7259   freeAsmop (left, NULL, ic, TRUE);
7260   freeAsmop (result, NULL, ic, TRUE);
7261 }
7262
7263 /*-----------------------------------------------------------------*/
7264 /* AccRol - rotate left accumulator by known count                 */
7265 /*-----------------------------------------------------------------*/
7266 static void
7267 AccRol (int shCount)
7268 {
7269   shCount &= 0x0007;            // shCount : 0..7
7270
7271   switch (shCount)
7272     {
7273     case 0:
7274       break;
7275     case 1:
7276       emitcode ("rl", "a");
7277       break;
7278     case 2:
7279       emitcode ("rl", "a");
7280       emitcode ("rl", "a");
7281       break;
7282     case 3:
7283       emitcode ("swap", "a");
7284       emitcode ("rr", "a");
7285       break;
7286     case 4:
7287       emitcode ("swap", "a");
7288       break;
7289     case 5:
7290       emitcode ("swap", "a");
7291       emitcode ("rl", "a");
7292       break;
7293     case 6:
7294       emitcode ("rr", "a");
7295       emitcode ("rr", "a");
7296       break;
7297     case 7:
7298       emitcode ("rr", "a");
7299       break;
7300     }
7301 }
7302
7303 /*-----------------------------------------------------------------*/
7304 /* AccLsh - left shift accumulator by known count                  */
7305 /*-----------------------------------------------------------------*/
7306 static void
7307 AccLsh (int shCount)
7308 {
7309   if (shCount != 0)
7310     {
7311       if (shCount == 1)
7312         emitcode ("add", "a,acc");
7313       else if (shCount == 2)
7314         {
7315           emitcode ("add", "a,acc");
7316           emitcode ("add", "a,acc");
7317         }
7318       else
7319         {
7320           /* rotate left accumulator */
7321           AccRol (shCount);
7322           /* and kill the lower order bits */
7323           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7324         }
7325     }
7326 }
7327
7328 /*-----------------------------------------------------------------*/
7329 /* AccRsh - right shift accumulator by known count                 */
7330 /*-----------------------------------------------------------------*/
7331 static void
7332 AccRsh (int shCount)
7333 {
7334   if (shCount != 0)
7335     {
7336       if (shCount == 1)
7337         {
7338           CLRC;
7339           emitcode ("rrc", "a");
7340         }
7341       else
7342         {
7343           /* rotate right accumulator */
7344           AccRol (8 - shCount);
7345           /* and kill the higher order bits */
7346           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7347         }
7348     }
7349 }
7350
7351 #ifdef BETTER_LITERAL_SHIFT
7352 /*-----------------------------------------------------------------*/
7353 /* AccSRsh - signed right shift accumulator by known count                 */
7354 /*-----------------------------------------------------------------*/
7355 static void
7356 AccSRsh (int shCount)
7357 {
7358   symbol *tlbl;
7359   if (shCount != 0)
7360     {
7361       if (shCount == 1)
7362         {
7363           emitcode ("mov", "c,acc.7");
7364           emitcode ("rrc", "a");
7365         }
7366       else if (shCount == 2)
7367         {
7368           emitcode ("mov", "c,acc.7");
7369           emitcode ("rrc", "a");
7370           emitcode ("mov", "c,acc.7");
7371           emitcode ("rrc", "a");
7372         }
7373       else
7374         {
7375           tlbl = newiTempLabel (NULL);
7376           /* rotate right accumulator */
7377           AccRol (8 - shCount);
7378           /* and kill the higher order bits */
7379           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7380           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7381           emitcode ("orl", "a,#!constbyte",
7382                     (unsigned char) ~SRMask[shCount]);
7383           emitcode ("", "!tlabeldef", tlbl->key + 100);
7384         }
7385     }
7386 }
7387 #endif
7388
7389 #ifdef BETTER_LITERAL_SHIFT
7390 /*-----------------------------------------------------------------*/
7391 /* shiftR1Left2Result - shift right one byte from left to result   */
7392 /*-----------------------------------------------------------------*/
7393 static void
7394 shiftR1Left2Result (operand * left, int offl,
7395                     operand * result, int offr,
7396                     int shCount, int sign)
7397 {
7398   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7399   /* shift right accumulator */
7400   if (sign)
7401     AccSRsh (shCount);
7402   else
7403     AccRsh (shCount);
7404   aopPut (AOP (result), "a", offr);
7405 }
7406 #endif
7407
7408 #ifdef BETTER_LITERAL_SHIFT
7409 /*-----------------------------------------------------------------*/
7410 /* shiftL1Left2Result - shift left one byte from left to result    */
7411 /*-----------------------------------------------------------------*/
7412 static void
7413 shiftL1Left2Result (operand * left, int offl,
7414                     operand * result, int offr, int shCount)
7415 {
7416   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7417   /* shift left accumulator */
7418   AccLsh (shCount);
7419   aopPut (AOP (result), "a", offr);
7420 }
7421 #endif
7422
7423 #ifdef BETTER_LITERAL_SHIFT
7424 /*-----------------------------------------------------------------*/
7425 /* movLeft2Result - move byte from left to result                  */
7426 /*-----------------------------------------------------------------*/
7427 static void
7428 movLeft2Result (operand * left, int offl,
7429                 operand * result, int offr, int sign)
7430 {
7431   char *l;
7432   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7433   {
7434       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7435
7436       if (*l == '@' && (IS_AOP_PREG (result)))
7437       {
7438           emitcode ("mov", "a,%s", l);
7439           aopPut (AOP (result), "a", offr);
7440       }
7441       else
7442       {
7443           if (!sign)
7444           {
7445             aopPut (AOP (result), l, offr);
7446           }
7447           else
7448             {
7449               /* MSB sign in acc.7 ! */
7450               if (getDataSize (left) == offl + 1)
7451                 {
7452                   emitcode ("mov", "a,%s", l);
7453                   aopPut (AOP (result), "a", offr);
7454                 }
7455             }
7456       }
7457   }
7458 }
7459 #endif
7460
7461 #ifdef BETTER_LITERAL_SHIFT
7462 /*-----------------------------------------------------------------*/
7463 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7464 /*-----------------------------------------------------------------*/
7465 static void
7466 AccAXRrl1 (char *x)
7467 {
7468   emitcode ("rrc", "a");
7469   emitcode ("xch", "a,%s", x);
7470   emitcode ("rrc", "a");
7471   emitcode ("xch", "a,%s", x);
7472 }
7473 #endif
7474
7475 #ifdef BETTER_LITERAL_SHIFT
7476 //REMOVE ME!!!
7477 /*-----------------------------------------------------------------*/
7478 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7479 /*-----------------------------------------------------------------*/
7480 static void
7481 AccAXLrl1 (char *x)
7482 {
7483   emitcode ("xch", "a,%s", x);
7484   emitcode ("rlc", "a");
7485   emitcode ("xch", "a,%s", x);
7486   emitcode ("rlc", "a");
7487 }
7488 #endif
7489
7490 #ifdef BETTER_LITERAL_SHIFT
7491 /*-----------------------------------------------------------------*/
7492 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7493 /*-----------------------------------------------------------------*/
7494 static void
7495 AccAXLsh1 (char *x)
7496 {
7497   emitcode ("xch", "a,%s", x);
7498   emitcode ("add", "a,acc");
7499   emitcode ("xch", "a,%s", x);
7500   emitcode ("rlc", "a");
7501 }
7502 #endif
7503
7504 #ifdef BETTER_LITERAL_SHIFT
7505 /*-----------------------------------------------------------------*/
7506 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7507 /*-----------------------------------------------------------------*/
7508 static void
7509 AccAXLsh (char *x, int shCount)
7510 {
7511   switch (shCount)
7512     {
7513     case 0:
7514       break;
7515     case 1:
7516       AccAXLsh1 (x);
7517       break;
7518     case 2:
7519       AccAXLsh1 (x);
7520       AccAXLsh1 (x);
7521       break;
7522     case 3:
7523     case 4:
7524     case 5:                     // AAAAABBB:CCCCCDDD
7525
7526       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7527
7528       emitcode ("anl", "a,#!constbyte",
7529                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7530
7531       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7532
7533       AccRol (shCount);         // DDDCCCCC:BBB00000
7534
7535       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7536
7537       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7538
7539       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7540
7541       emitcode ("anl", "a,#!constbyte",
7542                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7543
7544       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7545
7546       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7547
7548       break;
7549     case 6:                     // AAAAAABB:CCCCCCDD
7550       emitcode ("anl", "a,#!constbyte",
7551                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7552       emitcode ("mov", "c,acc.0");      // c = B
7553       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7554 #if 0
7555       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7556       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7557 #else
7558       emitcode("rrc","a"); 
7559       emitcode("xch","a,%s", x); 
7560       emitcode("rrc","a"); 
7561       emitcode("mov","c,acc.0"); //<< get correct bit 
7562       emitcode("xch","a,%s", x); 
7563
7564       emitcode("rrc","a"); 
7565       emitcode("xch","a,%s", x); 
7566       emitcode("rrc","a"); 
7567       emitcode("xch","a,%s", x); 
7568 #endif
7569       break;
7570     case 7:                     // a:x <<= 7
7571
7572       emitcode ("anl", "a,#!constbyte",
7573                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7574
7575       emitcode ("mov", "c,acc.0");      // c = B
7576
7577       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7578
7579       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7580
7581       break;
7582     default:
7583       break;
7584     }
7585 }
7586 #endif
7587
7588 #ifdef BETTER_LITERAL_SHIFT
7589 //REMOVE ME!!!
7590 /*-----------------------------------------------------------------*/
7591 /* AccAXRsh - right shift a:x known count (0..7)                   */
7592 /*-----------------------------------------------------------------*/
7593 static void
7594 AccAXRsh (char *x, int shCount)
7595 {
7596   switch (shCount)
7597     {
7598     case 0:
7599       break;
7600     case 1:
7601       CLRC;
7602       AccAXRrl1 (x);            // 0->a:x
7603
7604       break;
7605     case 2:
7606       CLRC;
7607       AccAXRrl1 (x);            // 0->a:x
7608
7609       CLRC;
7610       AccAXRrl1 (x);            // 0->a:x
7611
7612       break;
7613     case 3:
7614     case 4:
7615     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7616
7617       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7618
7619       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7620
7621       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7622
7623       emitcode ("anl", "a,#!constbyte",
7624                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7625
7626       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7627
7628       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7629
7630       emitcode ("anl", "a,#!constbyte",
7631                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7632
7633       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7634
7635       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7636
7637       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7638
7639       break;
7640     case 6:                     // AABBBBBB:CCDDDDDD
7641
7642       emitcode ("mov", "c,acc.7");
7643       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7644
7645       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7646
7647       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7648
7649       emitcode ("anl", "a,#!constbyte",
7650                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7651
7652       break;
7653     case 7:                     // ABBBBBBB:CDDDDDDD
7654
7655       emitcode ("mov", "c,acc.7");      // c = A
7656
7657       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7658
7659       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7660
7661       emitcode ("anl", "a,#!constbyte",
7662                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7663
7664       break;
7665     default:
7666       break;
7667     }
7668 }
7669 #endif
7670
7671 #ifdef BETTER_LITERAL_SHIFT
7672 /*-----------------------------------------------------------------*/
7673 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7674 /*-----------------------------------------------------------------*/
7675 static void
7676 AccAXRshS (char *x, int shCount)
7677 {
7678   symbol *tlbl;
7679   switch (shCount)
7680     {
7681     case 0:
7682       break;
7683     case 1:
7684       emitcode ("mov", "c,acc.7");
7685       AccAXRrl1 (x);            // s->a:x
7686
7687       break;
7688     case 2:
7689       emitcode ("mov", "c,acc.7");
7690       AccAXRrl1 (x);            // s->a:x
7691
7692       emitcode ("mov", "c,acc.7");
7693       AccAXRrl1 (x);            // s->a:x
7694
7695       break;
7696     case 3:
7697     case 4:
7698     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7699
7700       tlbl = newiTempLabel (NULL);
7701       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7702
7703       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7704
7705       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7706
7707       emitcode ("anl", "a,#!constbyte",
7708                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7709
7710       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7711
7712       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7713
7714       emitcode ("anl", "a,#!constbyte",
7715                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7716
7717       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7718
7719       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7720
7721       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7722
7723       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7724       emitcode ("orl", "a,#!constbyte",
7725                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7726
7727       emitcode ("", "!tlabeldef", tlbl->key + 100);
7728       break;                    // SSSSAAAA:BBBCCCCC
7729
7730     case 6:                     // AABBBBBB:CCDDDDDD
7731
7732       tlbl = newiTempLabel (NULL);
7733       emitcode ("mov", "c,acc.7");
7734       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7735
7736       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7737
7738       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7739
7740       emitcode ("anl", "a,#!constbyte",
7741                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7742
7743       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7744       emitcode ("orl", "a,#!constbyte",
7745                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7746
7747       emitcode ("", "!tlabeldef", tlbl->key + 100);
7748       break;
7749     case 7:                     // ABBBBBBB:CDDDDDDD
7750
7751       tlbl = newiTempLabel (NULL);
7752       emitcode ("mov", "c,acc.7");      // c = A
7753
7754       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7755
7756       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7757
7758       emitcode ("anl", "a,#!constbyte",
7759                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7760
7761       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7762       emitcode ("orl", "a,#!constbyte",
7763                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7764
7765       emitcode ("", "!tlabeldef", tlbl->key + 100);
7766       break;
7767     default:
7768       break;
7769     }
7770 }
7771 #endif
7772
7773 #ifdef BETTER_LITERAL_SHIFT
7774 static void
7775 _loadLeftIntoAx(char    **lsb, 
7776                 operand *left, 
7777                 operand *result,
7778                 int     offl,
7779                 int     offr)
7780 {
7781   // Get the initial value from left into a pair of registers.
7782   // MSB must be in A, LSB can be any register.
7783   //
7784   // If the result is held in registers, it is an optimization
7785   // if the LSB can be held in the register which will hold the,
7786   // result LSB since this saves us from having to copy it into
7787   // the result following AccAXLsh.
7788   //
7789   // If the result is addressed indirectly, this is not a gain.
7790   if (AOP_NEEDSACC(result))
7791   {
7792        char *leftByte;
7793        
7794        _startLazyDPSEvaluation();
7795       if (AOP_TYPE(left) == AOP_DPTR2)
7796        {
7797            // Get MSB in A.
7798            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7799            // get LSB in DP2_RESULT_REG.
7800            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7801            assert(!strcmp(leftByte, DP2_RESULT_REG));
7802        }
7803        else
7804        {
7805            // get LSB into DP2_RESULT_REG
7806            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7807            if (strcmp(leftByte, DP2_RESULT_REG))
7808            {
7809                TR_AP("#7");
7810                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7811            }
7812            // And MSB in A.
7813            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7814            assert(strcmp(leftByte, DP2_RESULT_REG));
7815            MOVA(leftByte);
7816        }
7817        _endLazyDPSEvaluation();
7818        *lsb = DP2_RESULT_REG;
7819   }
7820   else
7821   {
7822       if (sameRegs (AOP (result), AOP (left)) &&
7823         ((offl + MSB16) == offr))
7824       {
7825           /* don't crash result[offr] */
7826           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7827           emitcode ("xch", "a,%s", 
7828                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7829       }
7830       else
7831       {
7832           movLeft2Result (left, offl, result, offr, 0);
7833           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7834       }
7835       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7836       assert(strcmp(*lsb,"a"));      
7837   }
7838 }
7839
7840 static void
7841 _storeAxResults(char    *lsb,
7842                 operand *result,
7843                 int     offr)
7844 {
7845   _startLazyDPSEvaluation();
7846   if (AOP_NEEDSACC(result))
7847   {
7848       /* We have to explicitly update the result LSB.
7849        */
7850       emitcode("xch","a,%s", lsb);
7851       aopPut(AOP(result), "a", offr);
7852       emitcode("mov","a,%s", lsb);
7853   }
7854   if (getDataSize (result) > 1)
7855   {
7856       aopPut (AOP (result), "a", offr + MSB16);
7857   }
7858   _endLazyDPSEvaluation();
7859 }
7860
7861 /*-----------------------------------------------------------------*/
7862 /* shiftL2Left2Result - shift left two bytes from left to result   */
7863 /*-----------------------------------------------------------------*/
7864 static void
7865 shiftL2Left2Result (operand * left, int offl,
7866                     operand * result, int offr, int shCount)
7867 {
7868   char *lsb;
7869
7870   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7871   
7872   AccAXLsh (lsb, shCount);
7873   
7874   _storeAxResults(lsb, result, offr);
7875 }
7876 #endif
7877
7878 #ifdef BETTER_LITERAL_SHIFT
7879 /*-----------------------------------------------------------------*/
7880 /* shiftR2Left2Result - shift right two bytes from left to result  */
7881 /*-----------------------------------------------------------------*/
7882 static void
7883 shiftR2Left2Result (operand * left, int offl,
7884                     operand * result, int offr,
7885                     int shCount, int sign)
7886 {
7887   char *lsb;
7888   
7889   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7890   
7891   /* a:x >> shCount (x = lsb(result)) */
7892   if (sign)
7893   {
7894      AccAXRshS(lsb, shCount);
7895   }
7896   else
7897   {
7898     AccAXRsh(lsb, shCount);
7899   }
7900   
7901   _storeAxResults(lsb, result, offr);
7902 }
7903 #endif
7904
7905 /*-----------------------------------------------------------------*/
7906 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7907 /*-----------------------------------------------------------------*/
7908 static void
7909 shiftLLeftOrResult (operand * left, int offl,
7910                     operand * result, int offr, int shCount)
7911 {
7912   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7913   /* shift left accumulator */
7914   AccLsh (shCount);
7915   /* or with result */
7916   emitcode ("orl", "a,%s",
7917             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7918   /* back to result */
7919   aopPut (AOP (result), "a", offr);
7920 }
7921
7922 #if 0
7923 //REMOVE ME!!!
7924 /*-----------------------------------------------------------------*/
7925 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7926 /*-----------------------------------------------------------------*/
7927 static void
7928 shiftRLeftOrResult (operand * left, int offl,
7929                     operand * result, int offr, int shCount)
7930 {
7931   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7932   /* shift right accumulator */
7933   AccRsh (shCount);
7934   /* or with result */
7935   emitcode ("orl", "a,%s",
7936             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7937   /* back to result */
7938   aopPut (AOP (result), "a", offr);
7939 }
7940 #endif
7941
7942 #ifdef BETTER_LITERAL_SHIFT
7943 /*-----------------------------------------------------------------*/
7944 /* genlshOne - left shift a one byte quantity by known count       */
7945 /*-----------------------------------------------------------------*/
7946 static void
7947 genlshOne (operand * result, operand * left, int shCount)
7948 {
7949   D (emitcode (";", "genlshOne "););
7950   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7951 }
7952 #endif
7953
7954 #ifdef BETTER_LITERAL_SHIFT
7955 /*-----------------------------------------------------------------*/
7956 /* genlshTwo - left shift two bytes by known amount != 0           */
7957 /*-----------------------------------------------------------------*/
7958 static void
7959 genlshTwo (operand * result, operand * left, int shCount)
7960 {
7961   int size;
7962
7963   D (emitcode (";", "genlshTwo "););
7964
7965   size = getDataSize (result);
7966
7967   /* if shCount >= 8 */
7968   if (shCount >= 8)
7969   {
7970       shCount -= 8;
7971
7972       _startLazyDPSEvaluation();
7973
7974       if (size > 1)
7975         {
7976           if (shCount)
7977           {
7978             _endLazyDPSEvaluation();
7979             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7980             aopPut (AOP (result), zero, LSB);       
7981           }
7982           else
7983           {
7984             movLeft2Result (left, LSB, result, MSB16, 0);
7985             aopPut (AOP (result), zero, LSB);
7986             _endLazyDPSEvaluation();
7987           }
7988         }
7989         else
7990         {
7991           aopPut (AOP (result), zero, LSB);
7992           _endLazyDPSEvaluation();
7993         }
7994   }
7995
7996   /*  1 <= shCount <= 7 */
7997   else
7998     {
7999       if (size == 1)
8000       {
8001         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8002       }
8003       else
8004       {
8005         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8006       }
8007     }
8008 }
8009 #endif
8010
8011 #if 0
8012 //REMOVE ME!!!
8013 /*-----------------------------------------------------------------*/
8014 /* shiftLLong - shift left one long from left to result            */
8015 /* offl = LSB or MSB16                                             */
8016 /*-----------------------------------------------------------------*/
8017 static void
8018 shiftLLong (operand * left, operand * result, int offr)
8019 {
8020   char *l;
8021   int size = AOP_SIZE (result);
8022
8023   if (size >= LSB + offr)
8024     {
8025       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8026       MOVA (l);
8027       emitcode ("add", "a,acc");
8028       if (sameRegs (AOP (left), AOP (result)) &&
8029           size >= MSB16 + offr && offr != LSB)
8030         emitcode ("xch", "a,%s",
8031                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8032       else
8033         aopPut (AOP (result), "a", LSB + offr);
8034     }
8035
8036   if (size >= MSB16 + offr)
8037     {
8038       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8039         {
8040           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8041         }
8042       emitcode ("rlc", "a");
8043       if (sameRegs (AOP (left), AOP (result)) &&
8044           size >= MSB24 + offr && offr != LSB)
8045         emitcode ("xch", "a,%s",
8046                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8047       else
8048         aopPut (AOP (result), "a", MSB16 + offr);
8049     }
8050
8051   if (size >= MSB24 + offr)
8052     {
8053       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8054         {
8055           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8056         }
8057       emitcode ("rlc", "a");
8058       if (sameRegs (AOP (left), AOP (result)) &&
8059           size >= MSB32 + offr && offr != LSB)
8060         emitcode ("xch", "a,%s",
8061                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8062       else
8063         aopPut (AOP (result), "a", MSB24 + offr);
8064     }
8065
8066   if (size > MSB32 + offr)
8067     {
8068       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8069         {
8070           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8071         }
8072       emitcode ("rlc", "a");
8073       aopPut (AOP (result), "a", MSB32 + offr);
8074     }
8075   if (offr != LSB)
8076     aopPut (AOP (result), zero, LSB);
8077 }
8078 #endif
8079
8080 #if 0
8081 //REMOVE ME!!!
8082 /*-----------------------------------------------------------------*/
8083 /* genlshFour - shift four byte by a known amount != 0             */
8084 /*-----------------------------------------------------------------*/
8085 static void
8086 genlshFour (operand * result, operand * left, int shCount)
8087 {
8088   int size;
8089
8090   D (emitcode (";", "genlshFour ");
8091     );
8092
8093   size = AOP_SIZE (result);
8094
8095   /* if shifting more that 3 bytes */
8096   if (shCount >= 24)
8097     {
8098       shCount -= 24;
8099       if (shCount)
8100         /* lowest order of left goes to the highest
8101            order of the destination */
8102         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8103       else
8104         movLeft2Result (left, LSB, result, MSB32, 0);
8105       aopPut (AOP (result), zero, LSB);
8106       aopPut (AOP (result), zero, MSB16);
8107       aopPut (AOP (result), zero, MSB24);
8108       return;
8109     }
8110
8111   /* more than two bytes */
8112   else if (shCount >= 16)
8113     {
8114       /* lower order two bytes goes to higher order two bytes */
8115       shCount -= 16;
8116       /* if some more remaining */
8117       if (shCount)
8118         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8119       else
8120         {
8121           movLeft2Result (left, MSB16, result, MSB32, 0);
8122           movLeft2Result (left, LSB, result, MSB24, 0);
8123         }
8124       aopPut (AOP (result), zero, MSB16);
8125       aopPut (AOP (result), zero, LSB);
8126       return;
8127     }
8128
8129   /* if more than 1 byte */
8130   else if (shCount >= 8)
8131     {
8132       /* lower order three bytes goes to higher order  three bytes */
8133       shCount -= 8;
8134       if (size == 2)
8135         {
8136           if (shCount)
8137             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8138           else
8139             movLeft2Result (left, LSB, result, MSB16, 0);
8140         }
8141       else
8142         {                       /* size = 4 */
8143           if (shCount == 0)
8144             {
8145               movLeft2Result (left, MSB24, result, MSB32, 0);
8146               movLeft2Result (left, MSB16, result, MSB24, 0);
8147               movLeft2Result (left, LSB, result, MSB16, 0);
8148               aopPut (AOP (result), zero, LSB);
8149             }
8150           else if (shCount == 1)
8151             shiftLLong (left, result, MSB16);
8152           else
8153             {
8154               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8155               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8156               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8157               aopPut (AOP (result), zero, LSB);
8158             }
8159         }
8160     }
8161
8162   /* 1 <= shCount <= 7 */
8163   else if (shCount <= 2)
8164     {
8165       shiftLLong (left, result, LSB);
8166       if (shCount == 2)
8167         shiftLLong (result, result, LSB);
8168     }
8169   /* 3 <= shCount <= 7, optimize */
8170   else
8171     {
8172       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8173       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8174       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8175     }
8176 }
8177 #endif
8178
8179 #ifdef BETTER_LITERAL_SHIFT
8180 /*-----------------------------------------------------------------*/
8181 /* genLeftShiftLiteral - left shifting by known count              */
8182 /*-----------------------------------------------------------------*/
8183 static bool
8184 genLeftShiftLiteral (operand * left,
8185                      operand * right,
8186                      operand * result,
8187                      iCode * ic)
8188 {
8189   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8190   int size;
8191
8192   size = getSize (operandType (result));
8193
8194   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8195
8196   /* We only handle certain easy cases so far. */
8197   if ((shCount != 0)
8198    && (shCount < (size * 8))
8199    && (size != 1)
8200    && (size != 2))
8201   {
8202       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8203       return FALSE;
8204   }
8205
8206   freeAsmop (right, NULL, ic, TRUE);
8207
8208   aopOp(left, ic, FALSE, FALSE);
8209   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8210
8211 #if 0 // debug spew
8212   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8213   {
8214         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8215         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8216         {
8217            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8218         }
8219   }
8220   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8221   {
8222         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8223         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8224         {
8225            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8226         }       
8227   }  
8228 #endif
8229   
8230 #if VIEW_SIZE
8231   emitcode ("; shift left ", "result %d, left %d", size,
8232             AOP_SIZE (left));
8233 #endif
8234
8235   /* I suppose that the left size >= result size */
8236   if (shCount == 0)
8237   {
8238         _startLazyDPSEvaluation();
8239         while (size--)
8240         {
8241           movLeft2Result (left, size, result, size, 0);
8242         }
8243         _endLazyDPSEvaluation();
8244   }
8245   else if (shCount >= (size * 8))
8246   {
8247     _startLazyDPSEvaluation();
8248     while (size--)
8249     {
8250       aopPut (AOP (result), zero, size);
8251     }
8252     _endLazyDPSEvaluation();
8253   }
8254   else
8255   {
8256       switch (size)
8257         {
8258         case 1:
8259           genlshOne (result, left, shCount);
8260           break;
8261
8262         case 2:
8263           genlshTwo (result, left, shCount);
8264           break;
8265 #if 0
8266         case 4:
8267           genlshFour (result, left, shCount);
8268           break;
8269 #endif
8270         default:
8271           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8272           break;
8273         }
8274     }
8275   freeAsmop (left, NULL, ic, TRUE);
8276   freeAsmop (result, NULL, ic, TRUE);
8277   return TRUE;
8278 }
8279 #endif
8280
8281 /*-----------------------------------------------------------------*/
8282 /* genLeftShift - generates code for left shifting                 */
8283 /*-----------------------------------------------------------------*/
8284 static void
8285 genLeftShift (iCode * ic)
8286 {
8287   operand *left, *right, *result;
8288   int size, offset;
8289   char *l;
8290   symbol *tlbl, *tlbl1;
8291
8292   D (emitcode (";", "genLeftShift "););
8293
8294   right = IC_RIGHT (ic);
8295   left = IC_LEFT (ic);
8296   result = IC_RESULT (ic);
8297
8298   aopOp (right, ic, FALSE, FALSE);
8299
8300
8301 #ifdef BETTER_LITERAL_SHIFT
8302   /* if the shift count is known then do it
8303      as efficiently as possible */
8304   if (AOP_TYPE (right) == AOP_LIT)
8305     {
8306       if (genLeftShiftLiteral (left, right, result, ic))
8307       {
8308         return;
8309       }
8310     }
8311 #endif
8312
8313   /* shift count is unknown then we have to form
8314      a loop get the loop count in B : Note: we take
8315      only the lower order byte since shifting
8316      more that 32 bits make no sense anyway, ( the
8317      largest size of an object can be only 32 bits ) */
8318
8319   if (AOP_TYPE (right) == AOP_LIT)
8320   {
8321       /* Really should be handled by genLeftShiftLiteral,
8322        * but since I'm too lazy to fix that today, at least we can make
8323        * some small improvement.
8324        */
8325        emitcode("mov", "b,#!constbyte",
8326                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8327   }
8328   else
8329   {
8330       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8331       emitcode ("inc", "b");
8332   }
8333   freeAsmop (right, NULL, ic, TRUE);
8334   aopOp (left, ic, FALSE, FALSE);
8335   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8336
8337   /* now move the left to the result if they are not the
8338      same */
8339   if (!sameRegs (AOP (left), AOP (result)) &&
8340       AOP_SIZE (result) > 1)
8341     {
8342
8343       size = AOP_SIZE (result);
8344       offset = 0;
8345       _startLazyDPSEvaluation ();
8346       while (size--)
8347         {
8348           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8349           if (*l == '@' && (IS_AOP_PREG (result)))
8350             {
8351
8352               emitcode ("mov", "a,%s", l);
8353               aopPut (AOP (result), "a", offset);
8354             }
8355           else
8356             aopPut (AOP (result), l, offset);
8357           offset++;
8358         }
8359       _endLazyDPSEvaluation ();
8360     }
8361
8362   tlbl = newiTempLabel (NULL);
8363   size = AOP_SIZE (result);
8364   offset = 0;
8365   tlbl1 = newiTempLabel (NULL);
8366
8367   /* if it is only one byte then */
8368   if (size == 1)
8369     {
8370       symbol *tlbl1 = newiTempLabel (NULL);
8371
8372       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8373       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8374       emitcode ("", "!tlabeldef", tlbl->key + 100);
8375       emitcode ("add", "a,acc");
8376       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8377       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8378       aopPut (AOP (result), "a", 0);
8379       goto release;
8380     }
8381
8382   reAdjustPreg (AOP (result));
8383
8384   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8385   emitcode ("", "!tlabeldef", tlbl->key + 100);
8386   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8387   emitcode ("add", "a,acc");
8388   aopPut (AOP (result), "a", offset++);
8389   _startLazyDPSEvaluation ();
8390   while (--size)
8391     {
8392       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8393       emitcode ("rlc", "a");
8394       aopPut (AOP (result), "a", offset++);
8395     }
8396   _endLazyDPSEvaluation ();
8397   reAdjustPreg (AOP (result));
8398
8399   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8400   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8401 release:
8402   freeAsmop (left, NULL, ic, TRUE);
8403   freeAsmop (result, NULL, ic, TRUE);
8404 }
8405
8406 #ifdef BETTER_LITERAL_SHIFT
8407 /*-----------------------------------------------------------------*/
8408 /* genrshOne - right shift a one byte quantity by known count      */
8409 /*-----------------------------------------------------------------*/
8410 static void
8411 genrshOne (operand * result, operand * left,
8412            int shCount, int sign)
8413 {
8414   D (emitcode (";", "genrshOne"););
8415   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8416 }
8417 #endif
8418
8419 #ifdef BETTER_LITERAL_SHIFT
8420 /*-----------------------------------------------------------------*/
8421 /* genrshTwo - right shift two bytes by known amount != 0          */
8422 /*-----------------------------------------------------------------*/
8423 static void
8424 genrshTwo (operand * result, operand * left,
8425            int shCount, int sign)
8426 {
8427   D (emitcode (";", "genrshTwo"););
8428
8429   /* if shCount >= 8 */
8430   if (shCount >= 8)
8431     {
8432       shCount -= 8;
8433       _startLazyDPSEvaluation();
8434       if (shCount)
8435       {
8436         shiftR1Left2Result (left, MSB16, result, LSB,
8437                             shCount, sign);
8438       }                     
8439       else
8440       {
8441         movLeft2Result (left, MSB16, result, LSB, sign);
8442       }
8443       addSign (result, MSB16, sign);
8444       _endLazyDPSEvaluation();
8445     }
8446
8447   /*  1 <= shCount <= 7 */
8448   else
8449   {
8450     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8451   }
8452 }
8453 #endif
8454
8455 /*-----------------------------------------------------------------*/
8456 /* shiftRLong - shift right one long from left to result           */
8457 /* offl = LSB or MSB16                                             */
8458 /*-----------------------------------------------------------------*/
8459 static void
8460 shiftRLong (operand * left, int offl,
8461             operand * result, int sign)
8462 {
8463   int isSameRegs=sameRegs(AOP(left),AOP(result));
8464
8465   if (isSameRegs && offl>1) {
8466     // we are in big trouble, but this shouldn't happen
8467     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8468   }
8469
8470   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8471   
8472   if (offl==MSB16) {
8473     // shift is > 8
8474     if (sign) {
8475       emitcode ("rlc", "a");
8476       emitcode ("subb", "a,acc");
8477       emitcode ("xch", "a,%s",
8478                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8479     } else {
8480       aopPut (AOP(result), zero, MSB32);
8481     }
8482   }
8483
8484   if (!sign) {
8485     emitcode ("clr", "c");
8486   } else {
8487     emitcode ("mov", "c,acc.7");
8488   }
8489
8490   emitcode ("rrc", "a");
8491
8492   if (isSameRegs && offl==MSB16) {
8493     emitcode ("xch",
8494               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8495   } else {
8496     aopPut (AOP (result), "a", MSB32);
8497     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8498   }
8499
8500   emitcode ("rrc", "a");
8501   if (isSameRegs && offl==1) {
8502     emitcode ("xch", "a,%s",
8503               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8504   } else {
8505     aopPut (AOP (result), "a", MSB24);
8506     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8507   }
8508   emitcode ("rrc", "a");
8509   aopPut (AOP (result), "a", MSB16 - offl);
8510
8511   if (offl == LSB)
8512     {
8513       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8514       emitcode ("rrc", "a");
8515       aopPut (AOP (result), "a", LSB);
8516     }
8517 }
8518
8519 /*-----------------------------------------------------------------*/
8520 /* genrshFour - shift four byte by a known amount != 0             */
8521 /*-----------------------------------------------------------------*/
8522 static void
8523 genrshFour (operand * result, operand * left,
8524             int shCount, int sign)
8525 {
8526   D (emitcode (";", "genrshFour"););
8527
8528   /* if shifting more that 3 bytes */
8529   if (shCount >= 24)
8530     {
8531       shCount -= 24;
8532       _startLazyDPSEvaluation();
8533       if (shCount)
8534         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8535       else
8536         movLeft2Result (left, MSB32, result, LSB, sign);
8537       addSign (result, MSB16, sign);
8538       _endLazyDPSEvaluation();
8539     }
8540   else if (shCount >= 16)
8541     {
8542       shCount -= 16;
8543       _startLazyDPSEvaluation();
8544       if (shCount)
8545         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8546       else
8547         {
8548           movLeft2Result (left, MSB24, result, LSB, 0);
8549           movLeft2Result (left, MSB32, result, MSB16, sign);
8550         }
8551       addSign (result, MSB24, sign);
8552       _endLazyDPSEvaluation();
8553     }
8554   else if (shCount >= 8)
8555     {
8556       shCount -= 8;
8557       _startLazyDPSEvaluation();
8558       if (shCount == 1)
8559         {
8560             shiftRLong (left, MSB16, result, sign);
8561         }
8562       else if (shCount == 0)
8563         {
8564           movLeft2Result (left, MSB16, result, LSB, 0);
8565           movLeft2Result (left, MSB24, result, MSB16, 0);
8566           movLeft2Result (left, MSB32, result, MSB24, sign);
8567           addSign (result, MSB32, sign);
8568         }
8569       else
8570         {
8571           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8572           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8573           /* the last shift is signed */
8574           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8575           addSign (result, MSB32, sign);
8576         }
8577         _endLazyDPSEvaluation();
8578     }
8579   else
8580     {   
8581         /* 1 <= shCount <= 7 */
8582       if (shCount <= 2)
8583         {
8584           shiftRLong (left, LSB, result, sign);
8585           if (shCount == 2)
8586             shiftRLong (result, LSB, result, sign);
8587         }
8588       else
8589         {
8590           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8591           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8592           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8593         }
8594     }
8595 }
8596
8597 #ifdef BETTER_LITERAL_SHIFT
8598 /*-----------------------------------------------------------------*/
8599 /* genRightShiftLiteral - right shifting by known count            */
8600 /*-----------------------------------------------------------------*/
8601 static bool
8602 genRightShiftLiteral (operand * left,
8603                       operand * right,
8604                       operand * result,
8605                       iCode * ic,
8606                       int sign)
8607 {
8608   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8609   int size;
8610
8611   size = getSize (operandType (result));
8612
8613   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8614
8615   /* We only handle certain easy cases so far. */
8616   if ((shCount != 0)
8617    && (shCount < (size * 8))
8618    && (size != 1)
8619    && (size != 2)
8620    && (size != 4))
8621   {
8622       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8623       return FALSE;
8624   }
8625
8626   freeAsmop (right, NULL, ic, TRUE);
8627
8628   aopOp (left, ic, FALSE, FALSE);
8629   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8630
8631 #if VIEW_SIZE
8632   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8633             AOP_SIZE (left));
8634 #endif
8635
8636   /* test the LEFT size !!! */
8637
8638   /* I suppose that the left size >= result size */
8639   if (shCount == 0)
8640   {
8641       size = getDataSize (result);
8642       _startLazyDPSEvaluation();
8643       while (size--)
8644       {
8645         movLeft2Result (left, size, result, size, 0);
8646       }
8647       _endLazyDPSEvaluation();
8648   }
8649   else if (shCount >= (size * 8))
8650     {
8651       if (sign)
8652       {
8653         /* get sign in acc.7 */
8654         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8655       }
8656       addSign (result, LSB, sign);
8657     }
8658   else
8659     {
8660       switch (size)
8661         {
8662         case 1:
8663           genrshOne (result, left, shCount, sign);
8664           break;
8665
8666         case 2:
8667           genrshTwo (result, left, shCount, sign);
8668           break;
8669 #if 1
8670         case 4:
8671           genrshFour (result, left, shCount, sign);
8672           break;
8673 #endif    
8674         default:
8675           break;
8676         }
8677     }
8678   freeAsmop (left, NULL, ic, TRUE);
8679   freeAsmop (result, NULL, ic, TRUE);
8680   
8681   return TRUE;
8682 }
8683 #endif
8684
8685 /*-----------------------------------------------------------------*/
8686 /* genSignedRightShift - right shift of signed number              */
8687 /*-----------------------------------------------------------------*/
8688 static void
8689 genSignedRightShift (iCode * ic)
8690 {
8691   operand *right, *left, *result;
8692   int size, offset;
8693   char *l;
8694   symbol *tlbl, *tlbl1;
8695
8696   D (emitcode (";", "genSignedRightShift "););
8697
8698   /* we do it the hard way put the shift count in b
8699      and loop thru preserving the sign */
8700
8701   right = IC_RIGHT (ic);
8702   left = IC_LEFT (ic);
8703   result = IC_RESULT (ic);
8704
8705   aopOp (right, ic, FALSE, FALSE);
8706
8707 #ifdef BETTER_LITERAL_SHIFT
8708   if (AOP_TYPE (right) == AOP_LIT)
8709     {
8710       if (genRightShiftLiteral (left, right, result, ic, 1))
8711       {
8712         return;
8713       }
8714     }
8715 #endif
8716   /* shift count is unknown then we have to form
8717      a loop get the loop count in B : Note: we take
8718      only the lower order byte since shifting
8719      more that 32 bits make no sense anyway, ( the
8720      largest size of an object can be only 32 bits ) */
8721
8722   if (AOP_TYPE (right) == AOP_LIT)
8723   {
8724       /* Really should be handled by genRightShiftLiteral,
8725        * but since I'm too lazy to fix that today, at least we can make
8726        * some small improvement.
8727        */
8728        emitcode("mov", "b,#!constbyte",
8729                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8730   }
8731   else
8732   {
8733         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8734         emitcode ("inc", "b");
8735   }
8736   freeAsmop (right, NULL, ic, TRUE);
8737   aopOp (left, ic, FALSE, FALSE);
8738   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8739
8740   /* now move the left to the result if they are not the
8741      same */
8742   if (!sameRegs (AOP (left), AOP (result)) &&
8743       AOP_SIZE (result) > 1)
8744     {
8745
8746       size = AOP_SIZE (result);
8747       offset = 0;
8748       _startLazyDPSEvaluation ();
8749       while (size--)
8750         {
8751           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8752           if (*l == '@' && IS_AOP_PREG (result))
8753             {
8754
8755               emitcode ("mov", "a,%s", l);
8756               aopPut (AOP (result), "a", offset);
8757             }
8758           else
8759             aopPut (AOP (result), l, offset);
8760           offset++;
8761         }
8762       _endLazyDPSEvaluation ();
8763     }
8764
8765   /* mov the highest order bit to OVR */
8766   tlbl = newiTempLabel (NULL);
8767   tlbl1 = newiTempLabel (NULL);
8768
8769   size = AOP_SIZE (result);
8770   offset = size - 1;
8771   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8772   emitcode ("rlc", "a");
8773   emitcode ("mov", "ov,c");
8774   /* if it is only one byte then */
8775   if (size == 1)
8776     {
8777       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8778       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8779       emitcode ("", "!tlabeldef", tlbl->key + 100);
8780       emitcode ("mov", "c,ov");
8781       emitcode ("rrc", "a");
8782       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8783       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8784       aopPut (AOP (result), "a", 0);
8785       goto release;
8786     }
8787
8788   reAdjustPreg (AOP (result));
8789   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8790   emitcode ("", "!tlabeldef", tlbl->key + 100);
8791   emitcode ("mov", "c,ov");
8792   _startLazyDPSEvaluation ();
8793   while (size--)
8794     {
8795       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8796       emitcode ("rrc", "a");
8797       aopPut (AOP (result), "a", offset--);
8798     }
8799   _endLazyDPSEvaluation ();
8800   reAdjustPreg (AOP (result));
8801   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8802   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8803
8804 release:
8805   freeAsmop (left, NULL, ic, TRUE);
8806   freeAsmop (result, NULL, ic, TRUE);
8807 }
8808
8809 /*-----------------------------------------------------------------*/
8810 /* genRightShift - generate code for right shifting                */
8811 /*-----------------------------------------------------------------*/
8812 static void
8813 genRightShift (iCode * ic)
8814 {
8815   operand *right, *left, *result;
8816   sym_link *retype;
8817   int size, offset;
8818   char *l;
8819   symbol *tlbl, *tlbl1;
8820
8821   D (emitcode (";", "genRightShift "););
8822
8823   /* if signed then we do it the hard way preserve the
8824      sign bit moving it inwards */
8825   retype = getSpec (operandType (IC_RESULT (ic)));
8826
8827   if (!SPEC_USIGN (retype))
8828     {
8829       genSignedRightShift (ic);
8830       return;
8831     }
8832
8833   /* signed & unsigned types are treated the same : i.e. the
8834      signed is NOT propagated inwards : quoting from the
8835      ANSI - standard : "for E1 >> E2, is equivalent to division
8836      by 2**E2 if unsigned or if it has a non-negative value,
8837      otherwise the result is implementation defined ", MY definition
8838      is that the sign does not get propagated */
8839
8840   right = IC_RIGHT (ic);
8841   left = IC_LEFT (ic);
8842   result = IC_RESULT (ic);
8843
8844   aopOp (right, ic, FALSE, FALSE);
8845
8846 #ifdef BETTER_LITERAL_SHIFT
8847   /* if the shift count is known then do it
8848      as efficiently as possible */
8849   if (AOP_TYPE (right) == AOP_LIT)
8850     {
8851       if (genRightShiftLiteral (left, right, result, ic, 0))
8852       {
8853         return;
8854       }
8855     }
8856 #endif
8857
8858   /* shift count is unknown then we have to form
8859      a loop get the loop count in B : Note: we take
8860      only the lower order byte since shifting
8861      more that 32 bits make no sense anyway, ( the
8862      largest size of an object can be only 32 bits ) */
8863   
8864   if (AOP_TYPE (right) == AOP_LIT)
8865   {
8866       /* Really should be handled by genRightShiftLiteral,
8867        * but since I'm too lazy to fix that today, at least we can make
8868        * some small improvement.
8869        */
8870        emitcode("mov", "b,#!constbyte",
8871                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8872   }
8873   else
8874   {
8875       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8876       emitcode ("inc", "b");
8877   }
8878   freeAsmop (right, NULL, ic, TRUE);
8879   aopOp (left, ic, FALSE, FALSE);
8880   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8881
8882   /* now move the left to the result if they are not the
8883      same */
8884   if (!sameRegs (AOP (left), AOP (result)) &&
8885       AOP_SIZE (result) > 1)
8886     {
8887
8888       size = AOP_SIZE (result);
8889       offset = 0;
8890       _startLazyDPSEvaluation ();
8891       while (size--)
8892         {
8893           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8894           if (*l == '@' && IS_AOP_PREG (result))
8895             {
8896
8897               emitcode ("mov", "a,%s", l);
8898               aopPut (AOP (result), "a", offset);
8899             }
8900           else
8901             aopPut (AOP (result), l, offset);
8902           offset++;
8903         }
8904       _endLazyDPSEvaluation ();
8905     }
8906
8907   tlbl = newiTempLabel (NULL);
8908   tlbl1 = newiTempLabel (NULL);
8909   size = AOP_SIZE (result);
8910   offset = size - 1;
8911
8912   /* if it is only one byte then */
8913   if (size == 1)
8914     {
8915       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8916       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8917       emitcode ("", "!tlabeldef", tlbl->key + 100);
8918       CLRC;
8919       emitcode ("rrc", "a");
8920       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8921       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8922       aopPut (AOP (result), "a", 0);
8923       goto release;
8924     }
8925
8926   reAdjustPreg (AOP (result));
8927   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8928   emitcode ("", "!tlabeldef", tlbl->key + 100);
8929   CLRC;
8930   _startLazyDPSEvaluation ();
8931   while (size--)
8932     {
8933       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8934       emitcode ("rrc", "a");
8935       aopPut (AOP (result), "a", offset--);
8936     }
8937   _endLazyDPSEvaluation ();
8938   reAdjustPreg (AOP (result));
8939
8940   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8941   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8942
8943 release:
8944   freeAsmop (left, NULL, ic, TRUE);
8945   freeAsmop (result, NULL, ic, TRUE);
8946 }
8947
8948
8949 /*-----------------------------------------------------------------*/
8950 /* emitPtrByteGet - emits code to get a byte into A through a      */
8951 /*                  pointer register (R0, R1, or DPTR). The        */
8952 /*                  original value of A can be preserved in B.     */
8953 /*-----------------------------------------------------------------*/
8954 static void
8955 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8956 {
8957   switch (p_type)
8958     {
8959     case IPOINTER:
8960     case POINTER:
8961       if (preserveAinB)
8962         emitcode ("mov", "b,a");
8963       emitcode ("mov", "a,@%s", rname);
8964       break;
8965
8966     case PPOINTER:
8967       if (preserveAinB)
8968         emitcode ("mov", "b,a");
8969       emitcode ("movx", "a,@%s", rname);
8970       break;
8971       
8972     case FPOINTER:
8973       if (preserveAinB)
8974         emitcode ("mov", "b,a");
8975       emitcode ("movx", "a,@dptr");
8976       break;
8977
8978     case CPOINTER:
8979       if (preserveAinB)
8980         emitcode ("mov", "b,a");
8981       emitcode ("clr", "a");
8982       emitcode ("movc", "a,@a+dptr");
8983       break;
8984
8985     case GPOINTER:
8986       if (preserveAinB)
8987         {
8988           emitcode ("push", "b");
8989           emitcode ("push", "acc");
8990         }
8991       emitcode ("lcall", "__gptrget");
8992       if (preserveAinB)
8993         emitcode ("pop", "b");
8994       break;
8995     }
8996 }
8997
8998 /*-----------------------------------------------------------------*/
8999 /* emitPtrByteSet - emits code to set a byte from src through a    */
9000 /*                  pointer register (R0, R1, or DPTR).            */
9001 /*-----------------------------------------------------------------*/
9002 static void
9003 emitPtrByteSet (char *rname, int p_type, char *src)
9004 {
9005   switch (p_type)
9006     {
9007     case IPOINTER:
9008     case POINTER:
9009       if (*src=='@')
9010         {
9011           MOVA (src);
9012           emitcode ("mov", "@%s,a", rname);
9013         }
9014       else
9015         emitcode ("mov", "@%s,%s", rname, src);
9016       break;
9017
9018     case PPOINTER:
9019       MOVA (src);
9020       emitcode ("movx", "@%s,a", rname);
9021       break;
9022       
9023     case FPOINTER:
9024       MOVA (src);
9025       emitcode ("movx", "@dptr,a");
9026       break;
9027
9028     case GPOINTER:
9029       MOVA (src);
9030       emitcode ("lcall", "__gptrput");
9031       break;
9032     }
9033 }
9034
9035 /*-----------------------------------------------------------------*/
9036 /* genUnpackBits - generates code for unpacking bits               */
9037 /*-----------------------------------------------------------------*/
9038 static void
9039 genUnpackBits (operand * result, char *rname, int ptype)
9040 {
9041   int offset = 0;       /* result byte offset */
9042   int rsize;            /* result size */
9043   int rlen = 0;         /* remaining bitfield length */
9044   sym_link *etype;      /* bitfield type information */
9045   int blen;             /* bitfield length */
9046   int bstr;             /* bitfield starting bit within byte */
9047
9048   D(emitcode (";     genUnpackBits",""));
9049
9050   etype = getSpec (operandType (result));
9051   rsize = getSize (operandType (result));
9052   blen = SPEC_BLEN (etype);
9053   bstr = SPEC_BSTR (etype);
9054
9055   /* If the bitfield length is less than a byte */
9056   if (blen < 8)
9057     {
9058       emitPtrByteGet (rname, ptype, FALSE);
9059       AccRsh (bstr);
9060       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9061       aopPut (AOP (result), "a", offset++);
9062       goto finish;
9063     }
9064
9065   /* Bit field did not fit in a byte. Copy all
9066      but the partial byte at the end.  */
9067   for (rlen=blen;rlen>=8;rlen-=8)
9068     {
9069       emitPtrByteGet (rname, ptype, FALSE);
9070       aopPut (AOP (result), "a", offset++);
9071       if (rlen>8)
9072         emitcode ("inc", "%s", rname);
9073     }
9074
9075   /* Handle the partial byte at the end */
9076   if (rlen)
9077     {
9078       emitPtrByteGet (rname, ptype, FALSE);
9079       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9080       aopPut (AOP (result), "a", offset++);
9081     }
9082
9083 finish:
9084   if (offset < rsize)
9085     {
9086       rsize -= offset;
9087       while (rsize--)
9088         aopPut (AOP (result), zero, offset++);
9089     }
9090 }
9091
9092
9093 /*-----------------------------------------------------------------*/
9094 /* genDataPointerGet - generates code when ptr offset is known     */
9095 /*-----------------------------------------------------------------*/
9096 static void
9097 genDataPointerGet (operand * left,
9098                    operand * result,
9099                    iCode * ic)
9100 {
9101   char *l;
9102   char buff[256];
9103   int size, offset = 0;
9104   aopOp (result, ic, TRUE, FALSE);
9105
9106   /* get the string representation of the name */
9107   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9108   size = AOP_SIZE (result);
9109   _startLazyDPSEvaluation ();
9110   while (size--)
9111     {
9112         if (offset)
9113         {
9114             SNPRINTF (buff, sizeof(buff), 
9115                       "(%s + %d)", l + 1, offset);
9116         }
9117         else
9118         {
9119             SNPRINTF (buff, sizeof(buff), 
9120                       "%s", l + 1);
9121         }
9122       aopPut (AOP (result), buff, offset++);
9123     }
9124   _endLazyDPSEvaluation ();
9125
9126   freeAsmop (left, NULL, ic, TRUE);
9127   freeAsmop (result, NULL, ic, TRUE);
9128 }
9129
9130 /*-----------------------------------------------------------------*/
9131 /* genNearPointerGet - emitcode for near pointer fetch             */
9132 /*-----------------------------------------------------------------*/
9133 static void
9134 genNearPointerGet (operand * left,
9135                    operand * result,
9136                    iCode * ic,
9137                    iCode *pi)
9138 {
9139   asmop *aop = NULL;
9140   regs *preg;
9141   char *rname;
9142   sym_link *rtype, *retype, *letype;
9143   sym_link *ltype = operandType (left);
9144   char buff[80];
9145
9146   rtype = operandType (result);
9147   retype = getSpec (rtype);
9148   letype = getSpec (ltype);
9149
9150   aopOp (left, ic, FALSE, FALSE);
9151
9152   /* if left is rematerialisable and
9153      result is not bit variable type and
9154      the left is pointer to data space i.e
9155      lower 128 bytes of space */
9156   if (AOP_TYPE (left) == AOP_IMMD &&
9157       !IS_BITVAR (retype) &&
9158       !IS_BITVAR (letype) &&
9159       DCL_TYPE (ltype) == POINTER)
9160     {
9161       genDataPointerGet (left, result, ic);
9162       return;
9163     }
9164
9165   /* if the value is already in a pointer register
9166      then don't need anything more */
9167   if (!AOP_INPREG (AOP (left)))
9168     {
9169       /* otherwise get a free pointer register */
9170       aop = newAsmop (0);
9171       preg = getFreePtr (ic, &aop, FALSE);
9172       emitcode ("mov", "%s,%s",
9173                 preg->name,
9174                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9175       rname = preg->name;
9176     }
9177   else
9178     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9179
9180   freeAsmop (left, NULL, ic, TRUE);
9181   aopOp (result, ic, FALSE, FALSE);
9182
9183   /* if bitfield then unpack the bits */
9184   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9185     genUnpackBits (result, rname, POINTER);
9186   else
9187     {
9188       /* we have can just get the values */
9189       int size = AOP_SIZE (result);
9190       int offset = 0;
9191
9192       while (size--)
9193         {
9194           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9195             {
9196
9197               emitcode ("mov", "a,@%s", rname);
9198               aopPut (AOP (result), "a", offset);
9199             }
9200           else
9201             {
9202               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9203               aopPut (AOP (result), buff, offset);
9204             }
9205           offset++;
9206           if (size || pi)
9207             {
9208                 emitcode ("inc", "%s", rname);
9209             }
9210         }
9211     }
9212
9213   /* now some housekeeping stuff */
9214   if (aop)
9215     {
9216       /* we had to allocate for this iCode */
9217       if (pi) { /* post increment present */
9218         aopPut(AOP ( left ),rname,0);
9219       }
9220       freeAsmop (NULL, aop, ic, TRUE);
9221     }
9222   else
9223     {
9224       /* we did not allocate which means left
9225          already in a pointer register, then
9226          if size > 0 && this could be used again
9227          we have to point it back to where it
9228          belongs */
9229       if (AOP_SIZE (result) > 1 &&
9230           !OP_SYMBOL (left)->remat &&
9231           (OP_SYMBOL (left)->liveTo > ic->seq ||
9232            ic->depth) &&
9233           !pi)
9234         {
9235           int size = AOP_SIZE (result) - 1;
9236           while (size--)
9237             emitcode ("dec", "%s", rname);
9238         }
9239     }
9240
9241   /* done */
9242   freeAsmop (result, NULL, ic, TRUE);
9243   if (pi) pi->generated = 1;
9244 }
9245
9246 /*-----------------------------------------------------------------*/
9247 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9248 /*-----------------------------------------------------------------*/
9249 static void
9250 genPagedPointerGet (operand * left,
9251                     operand * result,
9252                     iCode * ic,
9253                     iCode * pi)
9254 {
9255   asmop *aop = NULL;
9256   regs *preg;
9257   char *rname;
9258   sym_link *rtype, *retype, *letype;
9259
9260   rtype = operandType (result);
9261   retype = getSpec (rtype);
9262   letype = getSpec (operandType (left));
9263   aopOp (left, ic, FALSE, FALSE);
9264
9265   /* if the value is already in a pointer register
9266      then don't need anything more */
9267   if (!AOP_INPREG (AOP (left)))
9268     {
9269       /* otherwise get a free pointer register */
9270       aop = newAsmop (0);
9271       preg = getFreePtr (ic, &aop, FALSE);
9272       emitcode ("mov", "%s,%s",
9273                 preg->name,
9274                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9275       rname = preg->name;
9276     }
9277   else
9278     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9279
9280   freeAsmop (left, NULL, ic, TRUE);
9281   aopOp (result, ic, FALSE, FALSE);
9282
9283   /* if bitfield then unpack the bits */
9284   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9285     genUnpackBits (result, rname, PPOINTER);
9286   else
9287     {
9288       /* we have can just get the values */
9289       int size = AOP_SIZE (result);
9290       int offset = 0;
9291
9292       while (size--)
9293         {
9294
9295           emitcode ("movx", "a,@%s", rname);
9296           aopPut (AOP (result), "a", offset);
9297
9298           offset++;
9299
9300           if (size || pi)
9301             emitcode ("inc", "%s", rname);
9302         }
9303     }
9304
9305   /* now some housekeeping stuff */
9306   if (aop)
9307     {
9308       /* we had to allocate for this iCode */
9309       if (pi) aopPut ( AOP (left), rname, 0);
9310       freeAsmop (NULL, aop, ic, TRUE);
9311     }
9312   else
9313     {
9314       /* we did not allocate which means left
9315          already in a pointer register, then
9316          if size > 0 && this could be used again
9317          we have to point it back to where it
9318          belongs */
9319       if (AOP_SIZE (result) > 1 &&
9320           !OP_SYMBOL (left)->remat &&
9321           (OP_SYMBOL (left)->liveTo > ic->seq ||
9322            ic->depth) &&
9323           !pi)
9324         {
9325           int size = AOP_SIZE (result) - 1;
9326           while (size--)
9327             emitcode ("dec", "%s", rname);
9328         }
9329     }
9330
9331   /* done */
9332   freeAsmop (result, NULL, ic, TRUE);
9333   if (pi) pi->generated = 1;
9334 }
9335
9336 /*-----------------------------------------------------------------*/
9337 /* genFarPointerGet - gget value from far space                    */
9338 /*-----------------------------------------------------------------*/
9339 static void
9340 genFarPointerGet (operand * left,
9341                   operand * result, iCode * ic, iCode *pi)
9342 {
9343     int size, offset, dopi=1;
9344   sym_link *retype = getSpec (operandType (result));
9345   sym_link *letype = getSpec (operandType (left));
9346   D (emitcode (";", "genFarPointerGet"););
9347
9348   aopOp (left, ic, FALSE, FALSE);
9349
9350   /* if the operand is already in dptr
9351      then we do nothing else we move the value to dptr */
9352   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9353     {
9354       /* if this is remateriazable */
9355       if (AOP_TYPE (left) == AOP_IMMD)
9356         {
9357           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9358         }
9359       else
9360         {
9361           /* we need to get it byte by byte */
9362           _startLazyDPSEvaluation ();
9363           if (AOP_TYPE (left) != AOP_DPTR)
9364             {
9365               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9366               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9367               if (options.model == MODEL_FLAT24)
9368                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9369             }
9370           else
9371             {
9372               /* We need to generate a load to DPTR indirect through DPTR. */
9373               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9374               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9375               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9376               if (options.model == MODEL_FLAT24)
9377                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9378               emitcode ("pop", "dph");
9379               emitcode ("pop", "dpl");
9380               dopi =0;
9381             }
9382           _endLazyDPSEvaluation ();
9383         }
9384     }
9385   /* so dptr know contains the address */
9386   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9387
9388   /* if bit then unpack */
9389   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9390       if (AOP_INDPTRn(left)) {
9391           genSetDPTR(AOP(left)->aopu.dptr);
9392       }
9393       genUnpackBits (result, "dptr", FPOINTER);
9394       if (AOP_INDPTRn(left)) {
9395           genSetDPTR(0);
9396       }
9397   } else
9398     {
9399       size = AOP_SIZE (result);
9400       offset = 0;
9401
9402       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9403           while (size--) {
9404               genSetDPTR(AOP(left)->aopu.dptr);
9405               emitcode ("movx", "a,@dptr");
9406               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9407                   emitcode ("inc", "dptr");
9408               genSetDPTR (0);
9409               aopPut (AOP (result), "a", offset++);
9410           }
9411       } else {
9412           _startLazyDPSEvaluation ();
9413           while (size--) {
9414               if (AOP_INDPTRn(left)) {
9415                   genSetDPTR(AOP(left)->aopu.dptr);
9416               } else {
9417                   genSetDPTR (0);
9418               }
9419               _flushLazyDPS ();
9420               
9421               emitcode ("movx", "a,@dptr");
9422               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9423                   emitcode ("inc", "dptr");
9424               
9425               aopPut (AOP (result), "a", offset++);
9426           }
9427           _endLazyDPSEvaluation ();
9428       }
9429     }
9430   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9431       if (!AOP_INDPTRn(left)) {
9432           _startLazyDPSEvaluation ();
9433           aopPut ( AOP (left), "dpl", 0);
9434           aopPut ( AOP (left), "dph", 1);
9435           if (options.model == MODEL_FLAT24)
9436               aopPut ( AOP (left), "dpx", 2);
9437           _endLazyDPSEvaluation ();
9438       }
9439     pi->generated = 1;
9440   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9441              AOP_SIZE(result) > 1 &&
9442              IS_SYMOP(left) &&
9443              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9444       
9445       size = AOP_SIZE (result) - 1;
9446       if (AOP_INDPTRn(left)) {
9447           genSetDPTR(AOP(left)->aopu.dptr);
9448       }
9449       while (size--) emitcode ("lcall","__decdptr");
9450       if (AOP_INDPTRn(left)) {
9451           genSetDPTR(0);
9452       }
9453   }
9454
9455   freeAsmop (left, NULL, ic, TRUE);
9456   freeAsmop (result, NULL, ic, TRUE);
9457 }
9458
9459 /*-----------------------------------------------------------------*/
9460 /* genCodePointerGet - get value from code space                  */
9461 /*-----------------------------------------------------------------*/
9462 static void
9463 genCodePointerGet (operand * left,
9464                     operand * result, iCode * ic, iCode *pi)
9465 {
9466   int size, offset, dopi=1;
9467   sym_link *retype = getSpec (operandType (result));
9468
9469   aopOp (left, ic, FALSE, FALSE);
9470
9471   /* if the operand is already in dptr
9472      then we do nothing else we move the value to dptr */
9473   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9474     {
9475       /* if this is remateriazable */
9476       if (AOP_TYPE (left) == AOP_IMMD)
9477         {
9478           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9479         }
9480       else
9481         {                       /* we need to get it byte by byte */
9482           _startLazyDPSEvaluation ();
9483           if (AOP_TYPE (left) != AOP_DPTR)
9484             {
9485               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9486               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9487               if (options.model == MODEL_FLAT24)
9488                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9489             }
9490           else
9491             {
9492               /* We need to generate a load to DPTR indirect through DPTR. */
9493               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9494               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9495               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9496               if (options.model == MODEL_FLAT24)
9497                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9498               emitcode ("pop", "dph");
9499               emitcode ("pop", "dpl");
9500               dopi=0;
9501             }
9502           _endLazyDPSEvaluation ();
9503         }
9504     }
9505   /* so dptr know contains the address */
9506   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9507
9508   /* if bit then unpack */
9509   if (IS_BITVAR (retype)) {
9510       if (AOP_INDPTRn(left)) {
9511           genSetDPTR(AOP(left)->aopu.dptr);
9512       }
9513       genUnpackBits (result, "dptr", CPOINTER);
9514       if (AOP_INDPTRn(left)) {
9515           genSetDPTR(0);
9516       }
9517   } else
9518     {
9519       size = AOP_SIZE (result);
9520       offset = 0;
9521       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9522           while (size--) {
9523               genSetDPTR(AOP(left)->aopu.dptr);
9524               emitcode ("clr", "a");
9525               emitcode ("movc", "a,@a+dptr");
9526               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9527                   emitcode ("inc", "dptr");
9528               genSetDPTR (0);
9529               aopPut (AOP (result), "a", offset++);
9530           }
9531       } else {
9532           _startLazyDPSEvaluation ();
9533           while (size--)
9534               {
9535                   if (AOP_INDPTRn(left)) {
9536                       genSetDPTR(AOP(left)->aopu.dptr);
9537                   } else {
9538                       genSetDPTR (0);
9539                   }
9540                   _flushLazyDPS ();
9541                   
9542                   emitcode ("clr", "a");
9543                   emitcode ("movc", "a,@a+dptr");
9544                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9545                       emitcode ("inc", "dptr");
9546                   aopPut (AOP (result), "a", offset++);
9547               }
9548           _endLazyDPSEvaluation ();
9549       }
9550     }
9551   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9552       if (!AOP_INDPTRn(left)) {
9553           _startLazyDPSEvaluation ();
9554           
9555           aopPut ( AOP (left), "dpl", 0);
9556           aopPut ( AOP (left), "dph", 1);
9557           if (options.model == MODEL_FLAT24)
9558               aopPut ( AOP (left), "dpx", 2);
9559
9560           _endLazyDPSEvaluation ();
9561       }
9562       pi->generated = 1;
9563   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9564              AOP_SIZE(result) > 1 &&
9565              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9566       
9567       size = AOP_SIZE (result) - 1;
9568       if (AOP_INDPTRn(left)) {
9569           genSetDPTR(AOP(left)->aopu.dptr);
9570       }
9571       while (size--) emitcode ("lcall","__decdptr");
9572       if (AOP_INDPTRn(left)) {
9573           genSetDPTR(0);
9574       }
9575   }
9576   
9577   freeAsmop (left, NULL, ic, TRUE);
9578   freeAsmop (result, NULL, ic, TRUE);
9579 }
9580
9581 /*-----------------------------------------------------------------*/
9582 /* genGenPointerGet - gget value from generic pointer space        */
9583 /*-----------------------------------------------------------------*/
9584 static void
9585 genGenPointerGet (operand * left,
9586                   operand * result, iCode * ic, iCode * pi)
9587 {
9588   int size, offset;
9589   sym_link *retype = getSpec (operandType (result));
9590   sym_link *letype = getSpec (operandType (left));
9591
9592   D (emitcode (";", "genGenPointerGet "); );
9593
9594   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9595
9596   /* if the operand is already in dptr
9597      then we do nothing else we move the value to dptr */
9598   if (AOP_TYPE (left) != AOP_STR)
9599     {
9600       /* if this is remateriazable */
9601       if (AOP_TYPE (left) == AOP_IMMD)
9602         {
9603           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9604           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9605             {
9606                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9607             }
9608             else
9609             {
9610                 emitcode ("mov", "b,#%d", pointerCode (retype));
9611             }
9612         }
9613       else
9614         {                       /* we need to get it byte by byte */
9615             _startLazyDPSEvaluation ();
9616             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9617             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9618             if (options.model == MODEL_FLAT24) {
9619                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9620                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9621             } else {
9622                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9623             }
9624             _endLazyDPSEvaluation ();
9625         }
9626     }
9627
9628   /* so dptr-b now contains the address */
9629   _G.bInUse++;
9630   aopOp (result, ic, FALSE, TRUE);
9631   _G.bInUse--;
9632
9633   /* if bit then unpack */
9634   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9635   {
9636     genUnpackBits (result, "dptr", GPOINTER);
9637   }
9638   else
9639     {
9640         size = AOP_SIZE (result);
9641         offset = 0;
9642
9643         while (size--)
9644         {
9645             if (size)
9646             {
9647                 // Get two bytes at a time, results in _AP & A.
9648                 // dptr will be incremented ONCE by __gptrgetWord.
9649                 //
9650                 // Note: any change here must be coordinated
9651                 // with the implementation of __gptrgetWord
9652                 // in device/lib/_gptrget.c
9653                 emitcode ("lcall", "__gptrgetWord");
9654                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9655                 aopPut (AOP (result), "a", offset++);
9656                 size--;
9657             }
9658             else
9659             {
9660                 // Only one byte to get.
9661                 emitcode ("lcall", "__gptrget");
9662                 aopPut (AOP (result), "a", offset++);
9663             }
9664             
9665             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9666             {
9667                 emitcode ("inc", "dptr");
9668             }
9669         }
9670     }
9671
9672   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9673     _startLazyDPSEvaluation ();
9674       
9675     aopPut ( AOP (left), "dpl", 0);
9676     aopPut ( AOP (left), "dph", 1);
9677     if (options.model == MODEL_FLAT24) {
9678         aopPut ( AOP (left), "dpx", 2);
9679         aopPut ( AOP (left), "b", 3);   
9680     } else  aopPut ( AOP (left), "b", 2);       
9681     
9682     _endLazyDPSEvaluation ();
9683       
9684     pi->generated = 1;
9685   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9686              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9687       
9688       size = AOP_SIZE (result) - 1;
9689       while (size--) emitcode ("lcall","__decdptr");
9690   }
9691
9692   freeAsmop (left, NULL, ic, TRUE);
9693   freeAsmop (result, NULL, ic, TRUE);
9694 }
9695
9696 /*-----------------------------------------------------------------*/
9697 /* genPointerGet - generate code for pointer get                   */
9698 /*-----------------------------------------------------------------*/
9699 static void
9700 genPointerGet (iCode * ic, iCode *pi)
9701 {
9702   operand *left, *result;
9703   sym_link *type, *etype;
9704   int p_type;
9705
9706   D (emitcode (";", "genPointerGet ");
9707     );
9708
9709   left = IC_LEFT (ic);
9710   result = IC_RESULT (ic);
9711
9712   /* depending on the type of pointer we need to
9713      move it to the correct pointer register */
9714   type = operandType (left);
9715   etype = getSpec (type);
9716   /* if left is of type of pointer then it is simple */
9717   if (IS_PTR (type) && !IS_FUNC (type->next))
9718     p_type = DCL_TYPE (type);
9719   else
9720     {
9721       /* we have to go by the storage class */
9722       p_type = PTR_TYPE (SPEC_OCLS (etype));
9723     }
9724   /* special case when cast remat */
9725   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9726       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9727           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9728           type = operandType (left);
9729           p_type = DCL_TYPE (type);
9730   }
9731   /* now that we have the pointer type we assign
9732      the pointer values */
9733   switch (p_type)
9734     {
9735
9736     case POINTER:
9737     case IPOINTER:
9738       genNearPointerGet (left, result, ic, pi);
9739       break;
9740
9741     case PPOINTER:
9742       genPagedPointerGet (left, result, ic, pi);
9743       break;
9744
9745     case FPOINTER:
9746       genFarPointerGet (left, result, ic, pi);
9747       break;
9748
9749     case CPOINTER:
9750       genCodePointerGet (left, result, ic, pi);
9751       break;
9752
9753     case GPOINTER:
9754       genGenPointerGet (left, result, ic, pi);
9755       break;
9756     }
9757
9758 }
9759
9760 /*-----------------------------------------------------------------*/
9761 /* genPackBits - generates code for packed bit storage             */
9762 /*-----------------------------------------------------------------*/
9763 static void
9764 genPackBits (sym_link * etype,
9765              operand * right,
9766              char *rname, int p_type)
9767 {
9768   int offset = 0;       /* source byte offset */
9769   int rlen = 0;         /* remaining bitfield length */
9770   int blen;             /* bitfield length */
9771   int bstr;             /* bitfield starting bit within byte */
9772   int litval;           /* source literal value (if AOP_LIT) */
9773   unsigned char mask;   /* bitmask within current byte */
9774
9775   D(emitcode (";     genPackBits",""));
9776
9777   blen = SPEC_BLEN (etype);
9778   bstr = SPEC_BSTR (etype);
9779
9780   /* If the bitfield length is less than a byte */
9781   if (blen < 8)
9782     {
9783       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9784               (unsigned char) (0xFF >> (8 - bstr)));
9785
9786       if (AOP_TYPE (right) == AOP_LIT)
9787         {
9788           /* Case with a bitfield length <8 and literal source
9789           */
9790           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9791           litval <<= bstr;
9792           litval &= (~mask) & 0xff;
9793           emitPtrByteGet (rname, p_type, FALSE);
9794           if ((mask|litval)!=0xff)
9795             emitcode ("anl","a,#!constbyte", mask);
9796           if (litval)
9797             emitcode ("orl","a,#!constbyte", litval);
9798         }
9799       else
9800         {
9801           if ((blen==1) && (p_type!=GPOINTER))
9802             {
9803               /* Case with a bitfield length == 1 and no generic pointer
9804               */
9805               if (AOP_TYPE (right) == AOP_CRY)
9806                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9807               else
9808                 {
9809                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9810                   emitcode ("rrc","a");
9811                 }
9812               emitPtrByteGet (rname, p_type, FALSE);
9813               emitcode ("mov","acc.%d,c",bstr);
9814             }
9815           else
9816             {
9817               /* Case with a bitfield length < 8 and arbitrary source
9818               */
9819               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9820               /* shift and mask source value */
9821               AccLsh (bstr);
9822               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9823
9824               /* transfer A to B and get next byte */
9825               emitPtrByteGet (rname, p_type, TRUE);
9826
9827               emitcode ("anl", "a,#!constbyte", mask);
9828               emitcode ("orl", "a,b");
9829               if (p_type == GPOINTER)
9830                 emitcode ("pop", "b");
9831            }
9832         }
9833
9834       emitPtrByteSet (rname, p_type, "a");
9835       return;
9836     }
9837
9838   /* Bit length is greater than 7 bits. In this case, copy  */
9839   /* all except the partial byte at the end                 */
9840   for (rlen=blen;rlen>=8;rlen-=8)
9841     {
9842       emitPtrByteSet (rname, p_type, 
9843                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9844       if (rlen>8)
9845         emitcode ("inc", "%s", rname);
9846     }
9847
9848   /* If there was a partial byte at the end */
9849   if (rlen)
9850     {
9851       mask = (((unsigned char) -1 << rlen) & 0xff);
9852       
9853       if (AOP_TYPE (right) == AOP_LIT)
9854         {
9855           /* Case with partial byte and literal source
9856           */
9857           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9858           litval >>= (blen-rlen);
9859           litval &= (~mask) & 0xff;
9860           emitPtrByteGet (rname, p_type, FALSE);
9861           if ((mask|litval)!=0xff)
9862             emitcode ("anl","a,#!constbyte", mask);
9863           if (litval)
9864             emitcode ("orl","a,#!constbyte", litval);
9865         }
9866       else
9867         {
9868           /* Case with partial byte and arbitrary source
9869           */
9870           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9871           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9872
9873           /* transfer A to B and get next byte */
9874           emitPtrByteGet (rname, p_type, TRUE);
9875
9876           emitcode ("anl", "a,#!constbyte", mask);
9877           emitcode ("orl", "a,b");
9878           if (p_type == GPOINTER)
9879             emitcode ("pop", "b");
9880         }
9881       emitPtrByteSet (rname, p_type, "a");
9882     }
9883
9884 }
9885
9886
9887 /*-----------------------------------------------------------------*/
9888 /* genDataPointerSet - remat pointer to data space                 */
9889 /*-----------------------------------------------------------------*/
9890 static void
9891 genDataPointerSet (operand * right,
9892                    operand * result,
9893                    iCode * ic)
9894 {
9895   int size, offset = 0;
9896   char *l, buff[256];
9897
9898   aopOp (right, ic, FALSE, FALSE);
9899
9900   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9901   size = AOP_SIZE (right);
9902   while (size--)
9903     {
9904       if (offset)
9905         {
9906             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9907         }
9908       else
9909         {
9910             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9911         }
9912         
9913       emitcode ("mov", "%s,%s", buff,
9914                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9915     }
9916
9917   freeAsmop (right, NULL, ic, TRUE);
9918   freeAsmop (result, NULL, ic, TRUE);
9919 }
9920
9921 /*-----------------------------------------------------------------*/
9922 /* genNearPointerSet - emitcode for near pointer put                */
9923 /*-----------------------------------------------------------------*/
9924 static void
9925 genNearPointerSet (operand * right,
9926                    operand * result,
9927                    iCode * ic,
9928                    iCode * pi)
9929 {
9930   asmop *aop = NULL;
9931   char *rname, *l;
9932   sym_link *retype, *letype;
9933   sym_link *ptype = operandType (result);
9934
9935   retype = getSpec (operandType (right));
9936   letype = getSpec (ptype);
9937
9938   aopOp (result, ic, FALSE, FALSE);
9939
9940   /* if the result is rematerializable &
9941      in data space & not a bit variable */
9942   if (AOP_TYPE (result) == AOP_IMMD &&
9943       DCL_TYPE (ptype) == POINTER &&
9944       !IS_BITVAR (retype) &&
9945       !IS_BITVAR (letype))
9946     {
9947       genDataPointerSet (right, result, ic);
9948       return;
9949     }
9950
9951   /* if the value is already in a pointer register
9952      then don't need anything more */
9953   if (!AOP_INPREG (AOP (result)))
9954     {
9955       /* otherwise get a free pointer register */
9956       regs *preg;
9957         
9958       aop = newAsmop (0);
9959       preg = getFreePtr (ic, &aop, FALSE);
9960       emitcode ("mov", "%s,%s",
9961                 preg->name,
9962                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9963       rname = preg->name;
9964     }
9965   else
9966     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9967
9968   aopOp (right, ic, FALSE, FALSE);
9969
9970   /* if bitfield then unpack the bits */
9971   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9972     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9973   else
9974     {
9975       /* we have can just get the values */
9976       int size = AOP_SIZE (right);
9977       int offset = 0;
9978
9979       while (size--)
9980         {
9981           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9982           if (*l == '@')
9983             {
9984               MOVA (l);
9985               emitcode ("mov", "@%s,a", rname);
9986             }
9987           else
9988             emitcode ("mov", "@%s,%s", rname, l);
9989           if (size || pi)
9990             emitcode ("inc", "%s", rname);
9991           offset++;
9992         }
9993     }
9994
9995   /* now some housekeeping stuff */
9996   if (aop)
9997     {
9998       /* we had to allocate for this iCode */
9999       if (pi) aopPut (AOP (result),rname,0);
10000       freeAsmop (NULL, aop, ic, TRUE);
10001     }
10002   else
10003     {
10004       /* we did not allocate which means left
10005          already in a pointer register, then
10006          if size > 0 && this could be used again
10007          we have to point it back to where it
10008          belongs */
10009       if (AOP_SIZE (right) > 1 &&
10010           !OP_SYMBOL (result)->remat &&
10011           (OP_SYMBOL (result)->liveTo > ic->seq ||
10012            ic->depth) &&
10013           !pi)
10014         {
10015           int size = AOP_SIZE (right) - 1;
10016           while (size--)
10017             emitcode ("dec", "%s", rname);
10018         }
10019     }
10020
10021   /* done */
10022   if (pi) pi->generated = 1;
10023   freeAsmop (result, NULL, ic, TRUE);
10024   freeAsmop (right, NULL, ic, TRUE);
10025
10026
10027 }
10028
10029 /*-----------------------------------------------------------------*/
10030 /* genPagedPointerSet - emitcode for Paged pointer put             */
10031 /*-----------------------------------------------------------------*/
10032 static void
10033 genPagedPointerSet (operand * right,
10034                     operand * result,
10035                     iCode * ic,
10036                     iCode *pi)
10037 {
10038   asmop *aop = NULL;
10039   char *rname;
10040   sym_link *retype, *letype;
10041
10042   retype = getSpec (operandType (right));
10043   letype = getSpec (operandType (result));
10044
10045   aopOp (result, ic, FALSE, FALSE);
10046
10047   /* if the value is already in a pointer register
10048      then don't need anything more */
10049   if (!AOP_INPREG (AOP (result)))
10050     {
10051       /* otherwise get a free pointer register */
10052       regs *preg;
10053         
10054       aop = newAsmop (0);
10055       preg = getFreePtr (ic, &aop, FALSE);
10056       emitcode ("mov", "%s,%s",
10057                 preg->name,
10058                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10059       rname = preg->name;
10060     }
10061   else
10062     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10063
10064   aopOp (right, ic, FALSE, FALSE);
10065
10066   /* if bitfield then unpack the bits */
10067   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10068     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10069   else
10070     {
10071       /* we have can just get the values */
10072       int size = AOP_SIZE (right);
10073       int offset = 0;
10074
10075       while (size--)
10076         {
10077           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10078
10079           emitcode ("movx", "@%s,a", rname);
10080
10081           if (size || pi)
10082             emitcode ("inc", "%s", rname);
10083
10084           offset++;
10085         }
10086     }
10087
10088   /* now some housekeeping stuff */
10089   if (aop)
10090     {
10091       if (pi) aopPut (AOP (result),rname,0);
10092       /* we had to allocate for this iCode */
10093       freeAsmop (NULL, aop, ic, TRUE);
10094     }
10095   else
10096     {
10097       /* we did not allocate which means left
10098          already in a pointer register, then
10099          if size > 0 && this could be used again
10100          we have to point it back to where it
10101          belongs */
10102       if (AOP_SIZE (right) > 1 &&
10103           !OP_SYMBOL (result)->remat &&
10104           (OP_SYMBOL (result)->liveTo > ic->seq ||
10105            ic->depth) &&
10106           !pi)
10107         {
10108           int size = AOP_SIZE (right) - 1;
10109           while (size--)
10110             emitcode ("dec", "%s", rname);
10111         }
10112     }
10113
10114   /* done */
10115   if (pi) pi->generated = 1;
10116   freeAsmop (result, NULL, ic, TRUE);
10117   freeAsmop (right, NULL, ic, TRUE);
10118
10119
10120 }
10121
10122 /*-----------------------------------------------------------------*/
10123 /* genFarPointerSet - set value from far space                     */
10124 /*-----------------------------------------------------------------*/
10125 static void
10126 genFarPointerSet (operand * right,
10127                   operand * result, iCode * ic, iCode *pi)
10128 {
10129   int size, offset, dopi=1;
10130   sym_link *retype = getSpec (operandType (right));
10131   sym_link *letype = getSpec (operandType (result));
10132
10133   aopOp (result, ic, FALSE, FALSE);
10134
10135   /* if the operand is already in dptr
10136      then we do nothing else we move the value to dptr */
10137   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10138     {
10139       /* if this is remateriazable */
10140       if (AOP_TYPE (result) == AOP_IMMD)
10141         emitcode ("mov", "dptr,%s", 
10142                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10143       else
10144         {
10145           /* we need to get it byte by byte */
10146           _startLazyDPSEvaluation ();
10147           if (AOP_TYPE (result) != AOP_DPTR)
10148             {
10149               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10150               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10151               if (options.model == MODEL_FLAT24)
10152                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10153             }
10154           else
10155             {
10156               /* We need to generate a load to DPTR indirect through DPTR. */
10157               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10158                 
10159               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10160               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10161               if (options.model == MODEL_FLAT24)
10162                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10163               emitcode ("pop", "dph");
10164               emitcode ("pop", "dpl");
10165               dopi=0;
10166             }
10167           _endLazyDPSEvaluation ();
10168         }
10169     }
10170   /* so dptr know contains the address */
10171   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10172
10173   /* if bit then unpack */
10174   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10175       if (AOP_INDPTRn(result)) {
10176           genSetDPTR(AOP(result)->aopu.dptr);
10177       }
10178       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10179       if (AOP_INDPTRn(result)) {
10180           genSetDPTR(0);
10181       }
10182   } else {
10183       size = AOP_SIZE (right);
10184       offset = 0;
10185       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10186           while (size--) {
10187               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10188               
10189               genSetDPTR(AOP(result)->aopu.dptr);
10190               emitcode ("movx", "@dptr,a");
10191               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10192                   emitcode ("inc", "dptr");
10193               genSetDPTR (0);
10194           }
10195       } else {
10196           _startLazyDPSEvaluation ();
10197           while (size--) {
10198               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10199               
10200               if (AOP_INDPTRn(result)) {
10201                   genSetDPTR(AOP(result)->aopu.dptr);
10202               } else {
10203                   genSetDPTR (0);
10204               }
10205               _flushLazyDPS ();
10206               
10207               emitcode ("movx", "@dptr,a");
10208               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10209                   emitcode ("inc", "dptr");
10210           }
10211           _endLazyDPSEvaluation ();
10212       }
10213   }
10214   
10215   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10216       if (!AOP_INDPTRn(result)) {
10217           _startLazyDPSEvaluation ();
10218           
10219           aopPut (AOP(result),"dpl",0);
10220           aopPut (AOP(result),"dph",1);
10221           if (options.model == MODEL_FLAT24)
10222               aopPut (AOP(result),"dpx",2);
10223
10224           _endLazyDPSEvaluation ();
10225       }
10226       pi->generated=1;
10227   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10228              AOP_SIZE(right) > 1 &&
10229              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10230       
10231       size = AOP_SIZE (right) - 1;
10232       if (AOP_INDPTRn(result)) {
10233           genSetDPTR(AOP(result)->aopu.dptr);
10234       } 
10235       while (size--) emitcode ("lcall","__decdptr");
10236       if (AOP_INDPTRn(result)) {
10237           genSetDPTR(0);
10238       }
10239   }
10240   freeAsmop (result, NULL, ic, TRUE);
10241   freeAsmop (right, NULL, ic, TRUE);
10242 }
10243
10244 /*-----------------------------------------------------------------*/
10245 /* genGenPointerSet - set value from generic pointer space         */
10246 /*-----------------------------------------------------------------*/
10247 static void
10248 genGenPointerSet (operand * right,
10249                   operand * result, iCode * ic, iCode *pi)
10250 {
10251   int size, offset;
10252   sym_link *retype = getSpec (operandType (right));
10253   sym_link *letype = getSpec (operandType (result));
10254
10255   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10256
10257   /* if the operand is already in dptr
10258      then we do nothing else we move the value to dptr */
10259   if (AOP_TYPE (result) != AOP_STR)
10260     {
10261       _startLazyDPSEvaluation ();
10262       /* if this is remateriazable */
10263       if (AOP_TYPE (result) == AOP_IMMD)
10264         {
10265           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10266           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10267           {
10268               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10269           }
10270           else
10271           {
10272               emitcode ("mov", 
10273                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10274           }
10275         }
10276       else
10277         {                       /* we need to get it byte by byte */
10278           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10279           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10280           if (options.model == MODEL_FLAT24) {
10281             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10282             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10283           } else {
10284             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10285           }
10286         }
10287       _endLazyDPSEvaluation ();
10288     }
10289   /* so dptr + b now contains the address */
10290   _G.bInUse++;
10291   aopOp (right, ic, FALSE, TRUE);
10292   _G.bInUse--;
10293     
10294
10295   /* if bit then unpack */
10296   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10297     {
10298         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10299     }
10300   else
10301     {
10302         size = AOP_SIZE (right);
10303         offset = 0;
10304
10305         _startLazyDPSEvaluation ();
10306         while (size--)
10307         {
10308             if (size)
10309             {
10310                 // Set two bytes at a time, passed in _AP & A.
10311                 // dptr will be incremented ONCE by __gptrputWord.
10312                 //
10313                 // Note: any change here must be coordinated
10314                 // with the implementation of __gptrputWord
10315                 // in device/lib/_gptrput.c
10316                 emitcode("mov", "_ap, %s", 
10317                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10318                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10319                 
10320                 genSetDPTR (0);
10321                 _flushLazyDPS ();
10322                 emitcode ("lcall", "__gptrputWord");
10323                 size--;
10324             }
10325             else
10326             {
10327                 // Only one byte to put.
10328                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10329
10330                 genSetDPTR (0);
10331                 _flushLazyDPS ();               
10332                 emitcode ("lcall", "__gptrput");
10333             }
10334             
10335             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10336             {
10337                 emitcode ("inc", "dptr");
10338             }
10339         }
10340         _endLazyDPSEvaluation ();
10341     }
10342
10343   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10344       _startLazyDPSEvaluation ();
10345       
10346       aopPut (AOP(result),"dpl",0);
10347       aopPut (AOP(result),"dph",1);
10348       if (options.model == MODEL_FLAT24) {
10349           aopPut (AOP(result),"dpx",2);
10350           aopPut (AOP(result),"b",3);
10351       } else {
10352           aopPut (AOP(result),"b",2);
10353       }
10354       _endLazyDPSEvaluation ();
10355       
10356       pi->generated=1;
10357   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10358              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10359       
10360       size = AOP_SIZE (right) - 1;
10361       while (size--) emitcode ("lcall","__decdptr");
10362   }
10363   freeAsmop (result, NULL, ic, TRUE);
10364   freeAsmop (right, NULL, ic, TRUE);
10365 }
10366
10367 /*-----------------------------------------------------------------*/
10368 /* genPointerSet - stores the value into a pointer location        */
10369 /*-----------------------------------------------------------------*/
10370 static void
10371 genPointerSet (iCode * ic, iCode *pi)
10372 {
10373   operand *right, *result;
10374   sym_link *type, *etype;
10375   int p_type;
10376
10377   D (emitcode (";", "genPointerSet "););
10378
10379   right = IC_RIGHT (ic);
10380   result = IC_RESULT (ic);
10381
10382   /* depending on the type of pointer we need to
10383      move it to the correct pointer register */
10384   type = operandType (result);
10385   etype = getSpec (type);
10386   /* if left is of type of pointer then it is simple */
10387   if (IS_PTR (type) && !IS_FUNC (type->next))
10388     {
10389       p_type = DCL_TYPE (type);
10390     }
10391   else
10392     {
10393       /* we have to go by the storage class */
10394       p_type = PTR_TYPE (SPEC_OCLS (etype));
10395     }
10396   /* special case when cast remat */
10397   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10398       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10399           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10400           type = operandType (result);
10401           p_type = DCL_TYPE (type);
10402   }
10403
10404   /* now that we have the pointer type we assign
10405      the pointer values */
10406   switch (p_type)
10407     {
10408
10409     case POINTER:
10410     case IPOINTER:
10411       genNearPointerSet (right, result, ic, pi);
10412       break;
10413
10414     case PPOINTER:
10415       genPagedPointerSet (right, result, ic, pi);
10416       break;
10417
10418     case FPOINTER:
10419       genFarPointerSet (right, result, ic, pi);
10420       break;
10421
10422     case GPOINTER:
10423       genGenPointerSet (right, result, ic, pi);
10424       break;
10425
10426     default:
10427       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10428               "genPointerSet: illegal pointer type");
10429     }
10430
10431 }
10432
10433 /*-----------------------------------------------------------------*/
10434 /* genIfx - generate code for Ifx statement                        */
10435 /*-----------------------------------------------------------------*/
10436 static void
10437 genIfx (iCode * ic, iCode * popIc)
10438 {
10439   operand *cond = IC_COND (ic);
10440   int isbit = 0;
10441
10442   D (emitcode (";", "genIfx "););
10443
10444   aopOp (cond, ic, FALSE, FALSE);
10445
10446   /* get the value into acc */
10447   if (AOP_TYPE (cond) != AOP_CRY)
10448     {
10449         toBoolean (cond);
10450     }
10451   else
10452     {
10453         isbit = 1;
10454     }
10455     
10456   /* the result is now in the accumulator */
10457   freeAsmop (cond, NULL, ic, TRUE);
10458
10459   /* if there was something to be popped then do it */
10460   if (popIc)
10461     genIpop (popIc);
10462
10463   /* if the condition is  a bit variable */
10464   if (isbit && IS_ITEMP (cond) &&
10465       SPIL_LOC (cond))
10466     {
10467         genIfxJump (ic, SPIL_LOC (cond)->rname);
10468     }
10469   else if (isbit && !IS_ITEMP (cond))
10470     {
10471         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10472     }
10473   else
10474     {
10475         genIfxJump (ic, "a");
10476     }
10477
10478   ic->generated = 1;
10479 }
10480
10481 /*-----------------------------------------------------------------*/
10482 /* genAddrOf - generates code for address of                       */
10483 /*-----------------------------------------------------------------*/
10484 static void
10485 genAddrOf (iCode * ic)
10486 {
10487   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10488   int size, offset;
10489
10490   D (emitcode (";", "genAddrOf ");
10491     );
10492
10493   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10494
10495   /* if the operand is on the stack then we
10496      need to get the stack offset of this
10497      variable */
10498   if (sym->onStack) {
10499       
10500       /* if 10 bit stack */
10501       if (options.stack10bit) {
10502           char buff[10];
10503           int  offset;
10504           
10505           tsprintf(buff, sizeof(buff), 
10506                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10507           /* if it has an offset then we need to compute it */
10508 /*        emitcode ("subb", "a,#!constbyte", */
10509 /*                  -((sym->stack < 0) ? */
10510 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10511 /*                    ((short) sym->stack)) & 0xff); */
10512 /*        emitcode ("mov","b,a"); */
10513 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10514 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10515 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10516           if (sym->stack) {
10517               emitcode ("mov", "a,_bpx");
10518               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10519                                              ((char) (sym->stack - _G.nRegsSaved)) :
10520                                              ((char) sym->stack )) & 0xff);
10521               emitcode ("mov", "b,a");
10522               emitcode ("mov", "a,_bpx+1");
10523               
10524               offset = (((sym->stack < 0) ? 
10525                          ((short) (sym->stack - _G.nRegsSaved)) :
10526                          ((short) sym->stack )) >> 8) & 0xff;
10527           
10528               emitcode ("addc","a,#!constbyte", offset);
10529
10530               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10531               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10532               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10533           } else {
10534               /* we can just move _bp */
10535               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10536               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10537               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10538           }       
10539       } else {
10540           /* if it has an offset then we need to compute it */
10541           if (sym->stack) {
10542               emitcode ("mov", "a,_bp");
10543               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10544               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10545           } else {
10546               /* we can just move _bp */
10547               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10548           }
10549           /* fill the result with zero */
10550           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10551           
10552           
10553           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10554               fprintf (stderr,
10555                        "*** warning: pointer to stack var truncated.\n");
10556           }
10557
10558           offset = 1;
10559           while (size--) {
10560               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10561           }      
10562       }
10563       goto release;
10564   }
10565
10566   /* object not on stack then we need the name */
10567   size = AOP_SIZE (IC_RESULT (ic));
10568   offset = 0;
10569
10570   while (size--)
10571     {
10572       char s[SDCC_NAME_MAX];
10573       if (offset) {
10574           switch (offset) {
10575           case 1:
10576               tsprintf(s, sizeof(s), "#!his",sym->rname);
10577               break;
10578           case 2:
10579               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10580               break;
10581           case 3:
10582               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10583               break;
10584           default: /* should not need this (just in case) */
10585               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10586                        sym->rname,
10587                        offset * 8);
10588           }
10589       } 
10590       else
10591       {
10592           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10593       }
10594         
10595       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10596     }
10597
10598 release:
10599   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10600
10601 }
10602
10603 #if 0 // obsolete, and buggy for != xdata
10604 /*-----------------------------------------------------------------*/
10605 /* genArrayInit - generates code for address of                       */
10606 /*-----------------------------------------------------------------*/
10607 static void
10608 genArrayInit (iCode * ic)
10609 {
10610     literalList *iLoop;
10611     int         ix, count;
10612     int         elementSize = 0, eIndex;
10613     unsigned    val, lastVal;
10614     sym_link    *type;
10615     operand     *left=IC_LEFT(ic);
10616     
10617     D (emitcode (";", "genArrayInit "););
10618
10619     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10620     
10621     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10622     {
10623         // Load immediate value into DPTR.
10624         emitcode("mov", "dptr, %s",
10625              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10626     }
10627     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10628     {
10629 #if 0
10630       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10631               "Unexpected operand to genArrayInit.\n");
10632       exit(1);
10633 #else
10634       // a regression because of SDCCcse.c:1.52
10635       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10636       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10637       if (options.model == MODEL_FLAT24)
10638         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10639 #endif
10640     }
10641     
10642     type = operandType(IC_LEFT(ic));
10643     
10644     if (type && type->next)
10645     {
10646         elementSize = getSize(type->next);
10647     }
10648     else
10649     {
10650         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10651                                 "can't determine element size in genArrayInit.\n");
10652         exit(1);
10653     }
10654     
10655     iLoop = IC_ARRAYILIST(ic);
10656     lastVal = 0xffff;
10657     
10658     while (iLoop)
10659     {
10660         bool firstpass = TRUE;
10661         
10662         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10663                  iLoop->count, (int)iLoop->literalValue, elementSize);
10664         
10665         ix = iLoop->count;
10666         
10667         while (ix)
10668         {
10669             symbol *tlbl = NULL;
10670             
10671             count = ix > 256 ? 256 : ix;
10672             
10673             if (count > 1)
10674             {
10675                 tlbl = newiTempLabel (NULL);
10676                 if (firstpass || (count & 0xff))
10677                 {
10678                     emitcode("mov", "b, #!constbyte", count & 0xff);
10679                 }
10680                 
10681                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10682             }
10683             
10684             firstpass = FALSE;
10685                 
10686             for (eIndex = 0; eIndex < elementSize; eIndex++)
10687             {
10688                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10689                 if (val != lastVal)
10690                 {
10691                     emitcode("mov", "a, #!constbyte", val);
10692                     lastVal = val;
10693                 }
10694                 
10695                 emitcode("movx", "@dptr, a");
10696                 emitcode("inc", "dptr");
10697             }
10698             
10699             if (count > 1)
10700             {
10701                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10702             }
10703             
10704             ix -= count;
10705         }
10706         
10707         iLoop = iLoop->next;
10708     }
10709     
10710     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10711 }
10712 #endif
10713
10714 /*-----------------------------------------------------------------*/
10715 /* genFarFarAssign - assignment when both are in far space         */
10716 /*-----------------------------------------------------------------*/
10717 static void
10718 genFarFarAssign (operand * result, operand * right, iCode * ic)
10719 {
10720   int size = AOP_SIZE (right);
10721   int offset = 0;
10722   symbol *rSym = NULL;
10723
10724   if (size == 1)
10725   {
10726       /* quick & easy case. */
10727       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10728       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10729       freeAsmop (right, NULL, ic, FALSE);
10730       /* now assign DPTR to result */
10731       _G.accInUse++;
10732       aopOp(result, ic, FALSE, FALSE);
10733       _G.accInUse--;
10734       aopPut(AOP(result), "a", 0);
10735       freeAsmop(result, NULL, ic, FALSE);
10736       return;
10737   }
10738   
10739   /* See if we've got an underlying symbol to abuse. */
10740   if (IS_SYMOP(result) && OP_SYMBOL(result))
10741   {
10742       if (IS_TRUE_SYMOP(result))
10743       {
10744           rSym = OP_SYMBOL(result);
10745       }
10746       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10747       {
10748           rSym = OP_SYMBOL(result)->usl.spillLoc;
10749       }
10750   }
10751              
10752   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10753   {
10754       /* We can use the '390 auto-toggle feature to good effect here. */
10755       
10756       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10757       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10758       emitcode ("mov", "dptr,#%s", rSym->rname); 
10759       /* DP2 = result, DP1 = right, DP1 is current. */
10760       while (size)
10761       {
10762           emitcode("movx", "a,@dptr");
10763           emitcode("movx", "@dptr,a");
10764           if (--size)
10765           {
10766                emitcode("inc", "dptr");
10767                emitcode("inc", "dptr");
10768           }
10769       }
10770       emitcode("mov", "dps,#0");
10771       freeAsmop (right, NULL, ic, FALSE);
10772 #if 0
10773 some alternative code for processors without auto-toggle
10774 no time to test now, so later well put in...kpb
10775         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10776         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10777         emitcode ("mov", "dptr,#%s", rSym->rname); 
10778         /* DP2 = result, DP1 = right, DP1 is current. */
10779         while (size)
10780         {
10781           --size;
10782           emitcode("movx", "a,@dptr");
10783           if (size)
10784             emitcode("inc", "dptr");
10785           emitcode("inc", "dps");
10786           emitcode("movx", "@dptr,a");
10787           if (size)
10788             emitcode("inc", "dptr");
10789           emitcode("inc", "dps");
10790         }
10791         emitcode("mov", "dps,#0");
10792         freeAsmop (right, NULL, ic, FALSE);
10793 #endif
10794   }
10795   else
10796   {
10797       D (emitcode (";", "genFarFarAssign"););
10798       aopOp (result, ic, TRUE, TRUE);
10799
10800       _startLazyDPSEvaluation ();
10801       
10802       while (size--)
10803         {
10804           aopPut (AOP (result),
10805                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10806           offset++;
10807         }
10808       _endLazyDPSEvaluation ();
10809       freeAsmop (result, NULL, ic, FALSE);
10810       freeAsmop (right, NULL, ic, FALSE);
10811   }
10812 }
10813
10814 /*-----------------------------------------------------------------*/
10815 /* genAssign - generate code for assignment                        */
10816 /*-----------------------------------------------------------------*/
10817 static void
10818 genAssign (iCode * ic)
10819 {
10820   operand *result, *right;
10821   int size, offset;
10822   unsigned long lit = 0L;
10823
10824   D (emitcode (";", "genAssign ");
10825     );
10826
10827   result = IC_RESULT (ic);
10828   right = IC_RIGHT (ic);
10829
10830   /* if they are the same */
10831   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10832     return;
10833
10834   aopOp (right, ic, FALSE, FALSE);
10835
10836   emitcode (";", "genAssign: resultIsFar = %s",
10837             isOperandInFarSpace (result) ?
10838             "TRUE" : "FALSE");
10839
10840   /* special case both in far space */
10841   if ((AOP_TYPE (right) == AOP_DPTR ||
10842        AOP_TYPE (right) == AOP_DPTR2) &&
10843   /* IS_TRUE_SYMOP(result)       && */
10844       isOperandInFarSpace (result))
10845     {
10846       genFarFarAssign (result, right, ic);
10847       return;
10848     }
10849
10850   aopOp (result, ic, TRUE, FALSE);
10851
10852   /* if they are the same registers */
10853   if (sameRegs (AOP (right), AOP (result)))
10854     goto release;
10855
10856   /* if the result is a bit */
10857   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10858     {
10859       /* if the right size is a literal then
10860          we know what the value is */
10861       if (AOP_TYPE (right) == AOP_LIT)
10862         {
10863           if (((int) operandLitValue (right)))
10864             aopPut (AOP (result), one, 0);
10865           else
10866             aopPut (AOP (result), zero, 0);
10867           goto release;
10868         }
10869
10870       /* the right is also a bit variable */
10871       if (AOP_TYPE (right) == AOP_CRY)
10872         {
10873           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10874           aopPut (AOP (result), "c", 0);
10875           goto release;
10876         }
10877
10878       /* we need to or */
10879       toBoolean (right);
10880       aopPut (AOP (result), "a", 0);
10881       goto release;
10882     }
10883
10884   /* bit variables done */
10885   /* general case */
10886   size = AOP_SIZE (result);
10887   offset = 0;
10888   if (AOP_TYPE (right) == AOP_LIT)
10889     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10890
10891   if ((size > 1) &&
10892       (AOP_TYPE (result) != AOP_REG) &&
10893       (AOP_TYPE (right) == AOP_LIT) &&
10894       !IS_FLOAT (operandType (right)))
10895     {
10896       _startLazyDPSEvaluation ();
10897       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10898         {
10899           aopPut (AOP (result),
10900                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10901                   offset);
10902           offset++;
10903           size--;
10904         }
10905       /* And now fill the rest with zeros. */
10906       if (size)
10907         {
10908           emitcode ("clr", "a");
10909         }
10910       while (size--)
10911         {
10912           aopPut (AOP (result), "a", offset++);
10913         }
10914       _endLazyDPSEvaluation ();
10915     }
10916   else
10917     {
10918       _startLazyDPSEvaluation ();
10919       while (size--)
10920         {
10921           aopPut (AOP (result),
10922                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10923                   offset);
10924           offset++;
10925         }
10926       _endLazyDPSEvaluation ();
10927     }
10928
10929 release:
10930   freeAsmop (right, NULL, ic, FALSE);
10931   freeAsmop (result, NULL, ic, TRUE);
10932 }
10933
10934 /*-----------------------------------------------------------------*/
10935 /* genJumpTab - generates code for jump table                      */
10936 /*-----------------------------------------------------------------*/
10937 static void
10938 genJumpTab (iCode * ic)
10939 {
10940   symbol *jtab;
10941   char *l;
10942
10943   D (emitcode (";", "genJumpTab ");
10944     );
10945
10946   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10947   /* get the condition into accumulator */
10948   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10949   MOVA (l);
10950   /* multiply by four! */
10951   emitcode ("add", "a,acc");
10952   emitcode ("add", "a,acc");
10953   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10954
10955   jtab = newiTempLabel (NULL);
10956   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10957   emitcode ("jmp", "@a+dptr");
10958   emitcode ("", "!tlabeldef", jtab->key + 100);
10959   /* now generate the jump labels */
10960   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10961        jtab = setNextItem (IC_JTLABELS (ic)))
10962     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10963
10964 }
10965
10966 /*-----------------------------------------------------------------*/
10967 /* genCast - gen code for casting                                  */
10968 /*-----------------------------------------------------------------*/
10969 static void
10970 genCast (iCode * ic)
10971 {
10972   operand *result = IC_RESULT (ic);
10973   sym_link *ctype = operandType (IC_LEFT (ic));
10974   sym_link *rtype = operandType (IC_RIGHT (ic));
10975   operand *right = IC_RIGHT (ic);
10976   int size, offset;
10977
10978   D (emitcode (";", "genCast "););
10979
10980   /* if they are equivalent then do nothing */
10981   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10982     return;
10983
10984   aopOp (right, ic, FALSE, FALSE);
10985   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10986
10987   /* if the result is a bit */
10988   if (IS_BITVAR (OP_SYMBOL (result)->type)
10989       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10990     {
10991       /* if the right size is a literal then
10992          we know what the value is */
10993       if (AOP_TYPE (right) == AOP_LIT)
10994         {
10995           if (((int) operandLitValue (right)))
10996             aopPut (AOP (result), one, 0);
10997           else
10998             aopPut (AOP (result), zero, 0);
10999
11000           goto release;
11001         }
11002
11003       /* the right is also a bit variable */
11004       if (AOP_TYPE (right) == AOP_CRY)
11005         {
11006           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11007           aopPut (AOP (result), "c", 0);
11008           goto release;
11009         }
11010
11011       /* we need to or */
11012       toBoolean (right);
11013       aopPut (AOP (result), "a", 0);
11014       goto release;
11015     }
11016
11017   /* if they are the same size : or less */
11018   if (AOP_SIZE (result) <= AOP_SIZE (right))
11019     {
11020
11021       /* if they are in the same place */
11022       if (sameRegs (AOP (right), AOP (result)))
11023         goto release;
11024
11025       /* if they in different places then copy */
11026       size = AOP_SIZE (result);
11027       offset = 0;
11028       _startLazyDPSEvaluation ();
11029       while (size--)
11030         {
11031           aopPut (AOP (result),
11032                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11033                   offset);
11034           offset++;
11035         }
11036       _endLazyDPSEvaluation ();
11037       goto release;
11038     }
11039
11040
11041   /* if the result is of type pointer */
11042   if (IS_PTR (ctype))
11043     {
11044
11045       int p_type;
11046       sym_link *type = operandType (right);
11047
11048       /* pointer to generic pointer */
11049       if (IS_GENPTR (ctype))
11050         {
11051           if (IS_PTR (type))
11052             {
11053               p_type = DCL_TYPE (type);
11054             }
11055           else
11056             {
11057 #if OLD_CAST_BEHAVIOR
11058               /* KV: we are converting a non-pointer type to
11059                * a generic pointer. This (ifdef'd out) code
11060                * says that the resulting generic pointer
11061                * should have the same class as the storage
11062                * location of the non-pointer variable.
11063                *
11064                * For example, converting an int (which happens
11065                * to be stored in DATA space) to a pointer results
11066                * in a DATA generic pointer; if the original int
11067                * in XDATA space, so will be the resulting pointer.
11068                *
11069                * I don't like that behavior, and thus this change:
11070                * all such conversions will be forced to XDATA and
11071                * throw a warning. If you want some non-XDATA
11072                * type, or you want to suppress the warning, you
11073                * must go through an intermediate cast, like so:
11074                *
11075                * char _generic *gp = (char _xdata *)(intVar);
11076                */
11077               sym_link *etype = getSpec (type);
11078
11079               /* we have to go by the storage class */
11080               if (SPEC_OCLS (etype) != generic)
11081                 {
11082                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11083                 }
11084               else
11085 #endif
11086                 {
11087                   /* Converting unknown class (i.e. register variable)
11088                    * to generic pointer. This is not good, but
11089                    * we'll make a guess (and throw a warning).
11090                    */
11091                   p_type = FPOINTER;
11092                   werror (W_INT_TO_GEN_PTR_CAST);
11093                 }
11094             }
11095
11096           /* the first two bytes are known */
11097           size = GPTRSIZE - 1;
11098           offset = 0;
11099           _startLazyDPSEvaluation ();
11100           while (size--)
11101             {
11102               aopPut (AOP (result),
11103                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11104                       offset);
11105               offset++;
11106             }
11107           _endLazyDPSEvaluation ();
11108
11109           /* the last byte depending on type */
11110             {
11111                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11112                 char gpValStr[10];
11113             
11114                 if (gpVal == -1)
11115                 {
11116                     // pointerTypeToGPByte will have bitched.
11117                     exit(1);
11118                 }
11119             
11120                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11121                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11122             }
11123           goto release;
11124         }
11125
11126       /* just copy the pointers */
11127       size = AOP_SIZE (result);
11128       offset = 0;
11129       _startLazyDPSEvaluation ();
11130       while (size--)
11131         {
11132           aopPut (AOP (result),
11133                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11134                   offset);
11135           offset++;
11136         }
11137       _endLazyDPSEvaluation ();
11138       goto release;
11139     }
11140
11141   /* so we now know that the size of destination is greater
11142      than the size of the source */
11143   /* we move to result for the size of source */
11144   size = AOP_SIZE (right);
11145   offset = 0;
11146   _startLazyDPSEvaluation ();
11147   while (size--)
11148     {
11149       aopPut (AOP (result),
11150               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11151               offset);
11152       offset++;
11153     }
11154   _endLazyDPSEvaluation ();
11155
11156   /* now depending on the sign of the source && destination */
11157   size = AOP_SIZE (result) - AOP_SIZE (right);
11158   /* if unsigned or not an integral type */
11159   /* also, if the source is a bit, we don't need to sign extend, because
11160    * it can't possibly have set the sign bit.
11161    */
11162   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11163     {
11164       while (size--)
11165         {
11166           aopPut (AOP (result), zero, offset++);
11167         }
11168     }
11169   else
11170     {
11171       /* we need to extend the sign :{ */
11172       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11173                         FALSE, FALSE, NULL));
11174       emitcode ("rlc", "a");
11175       emitcode ("subb", "a,acc");
11176       while (size--)
11177         aopPut (AOP (result), "a", offset++);
11178     }
11179
11180   /* we are done hurray !!!! */
11181
11182 release:
11183   freeAsmop (right, NULL, ic, TRUE);
11184   freeAsmop (result, NULL, ic, TRUE);
11185
11186 }
11187
11188 /*-----------------------------------------------------------------*/
11189 /* genDjnz - generate decrement & jump if not zero instrucion      */
11190 /*-----------------------------------------------------------------*/
11191 static int
11192 genDjnz (iCode * ic, iCode * ifx)
11193 {
11194   symbol *lbl, *lbl1;
11195   if (!ifx)
11196     return 0;
11197
11198   /* if the if condition has a false label
11199      then we cannot save */
11200   if (IC_FALSE (ifx))
11201     return 0;
11202
11203   /* if the minus is not of the form
11204      a = a - 1 */
11205   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11206       !IS_OP_LITERAL (IC_RIGHT (ic)))
11207     return 0;
11208
11209   if (operandLitValue (IC_RIGHT (ic)) != 1)
11210     return 0;
11211
11212   /* if the size of this greater than one then no
11213      saving */
11214   if (getSize (operandType (IC_RESULT (ic))) > 1)
11215     return 0;
11216
11217   /* otherwise we can save BIG */
11218   D(emitcode(";", "genDjnz"););
11219
11220   lbl = newiTempLabel (NULL);
11221   lbl1 = newiTempLabel (NULL);
11222
11223   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11224
11225   if (AOP_NEEDSACC(IC_RESULT(ic)))
11226   {
11227       /* If the result is accessed indirectly via
11228        * the accumulator, we must explicitly write
11229        * it back after the decrement.
11230        */
11231       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11232       
11233       if (strcmp(rByte, "a"))
11234       {
11235            /* Something is hopelessly wrong */
11236            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11237                    __FILE__, __LINE__);
11238            /* We can just give up; the generated code will be inefficient,
11239             * but what the hey.
11240             */
11241            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11242            return 0;
11243       }
11244       emitcode ("dec", "%s", rByte);
11245       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11246       emitcode ("jnz", "!tlabel", lbl->key + 100);
11247   }
11248   else if (IS_AOP_PREG (IC_RESULT (ic)))
11249     {
11250       emitcode ("dec", "%s",
11251                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11252       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11253       emitcode ("jnz", "!tlabel", lbl->key + 100);
11254     }
11255   else
11256     {
11257       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11258                 lbl->key + 100);
11259     }
11260   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11261   emitcode ("", "!tlabeldef", lbl->key + 100);
11262   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11263   emitcode ("", "!tlabeldef", lbl1->key + 100);
11264
11265   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11266   ifx->generated = 1;
11267   return 1;
11268 }
11269
11270 /*-----------------------------------------------------------------*/
11271 /* genReceive - generate code for a receive iCode                  */
11272 /*-----------------------------------------------------------------*/
11273 static void
11274 genReceive (iCode * ic)
11275 {
11276     int size = getSize (operandType (IC_RESULT (ic)));
11277     int offset = 0;
11278     int rb1off ;
11279     
11280     D (emitcode (";", "genReceive "););
11281
11282     if (ic->argreg == 1) 
11283     {
11284         /* first parameter */
11285         if (AOP_IS_STR(IC_RESULT(ic)))
11286         {
11287             /* Nothing to do: it's already in the proper place. */
11288             return;
11289         }
11290         else
11291         {
11292             bool useDp2;
11293             
11294             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11295                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11296                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11297             
11298             _G.accInUse++;
11299             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11300             _G.accInUse--; 
11301             
11302             /* Sanity checking... */
11303             if (AOP_USESDPTR(IC_RESULT(ic)))
11304             {
11305                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11306                         "genReceive got unexpected DPTR.");
11307             }
11308             assignResultValue (IC_RESULT (ic));
11309         }
11310     } 
11311     else 
11312     { 
11313         /* second receive onwards */
11314         /* this gets a little tricky since unused recevies will be
11315          eliminated, we have saved the reg in the type field . and
11316          we use that to figure out which register to use */
11317         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11318         rb1off = ic->argreg;
11319         while (size--) 
11320         {
11321             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11322         }
11323     }
11324     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11325 }
11326
11327 /*-----------------------------------------------------------------*/
11328 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11329 /*-----------------------------------------------------------------*/
11330 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11331 {
11332     operand *from , *to , *count;
11333     symbol *lbl;
11334     bitVect *rsave;
11335     int i;
11336
11337     /* we know it has to be 3 parameters */
11338     assert (nparms == 3);
11339     
11340     rsave = newBitVect(16);
11341     /* save DPTR if it needs to be saved */
11342     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11343             if (bitVectBitValue(ic->rMask,i))
11344                     rsave = bitVectSetBit(rsave,i);
11345     }
11346     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11347                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11348     savermask(rsave);
11349     
11350     to = parms[0];
11351     from = parms[1];
11352     count = parms[2];
11353
11354     aopOp (from, ic->next, FALSE, FALSE);
11355
11356     /* get from into DPTR1 */
11357     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11358     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11359     if (options.model == MODEL_FLAT24) {
11360         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11361     }
11362
11363     freeAsmop (from, NULL, ic, FALSE);
11364     aopOp (to, ic, FALSE, FALSE);
11365     /* get "to" into DPTR */
11366     /* if the operand is already in dptr
11367        then we do nothing else we move the value to dptr */
11368     if (AOP_TYPE (to) != AOP_STR) {
11369         /* if already in DPTR then we need to push */
11370         if (AOP_TYPE(to) == AOP_DPTR) {
11371             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11372             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11373             if (options.model == MODEL_FLAT24)
11374                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11375             emitcode ("pop", "dph");
11376             emitcode ("pop", "dpl");        
11377         } else {
11378             _startLazyDPSEvaluation ();
11379             /* if this is remateriazable */
11380             if (AOP_TYPE (to) == AOP_IMMD) {
11381                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11382             } else {                    /* we need to get it byte by byte */
11383                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11384                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11385                 if (options.model == MODEL_FLAT24) {
11386                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11387                 }
11388             }
11389             _endLazyDPSEvaluation ();
11390         }
11391     }
11392     freeAsmop (to, NULL, ic, FALSE);
11393     _G.dptrInUse = _G.dptr1InUse = 1;
11394     aopOp (count, ic->next->next, FALSE,FALSE);
11395     lbl =newiTempLabel(NULL);
11396
11397     /* now for the actual copy */
11398     if (AOP_TYPE(count) == AOP_LIT && 
11399         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11400         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11401         if (fromc) {
11402             emitcode ("lcall","__bi_memcpyc2x_s");
11403         } else {
11404             emitcode ("lcall","__bi_memcpyx2x_s");
11405         }
11406         freeAsmop (count, NULL, ic, FALSE);
11407     } else {
11408         symbol *lbl1 = newiTempLabel(NULL);
11409         
11410         emitcode (";"," Auto increment but no djnz");
11411         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11412         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11413         freeAsmop (count, NULL, ic, FALSE);
11414         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11415         emitcode ("","!tlabeldef",lbl->key+100);
11416         if (fromc) {
11417             emitcode ("clr","a");
11418             emitcode ("movc", "a,@a+dptr");
11419         } else 
11420             emitcode ("movx", "a,@dptr");
11421         emitcode ("movx", "@dptr,a");
11422         emitcode ("inc", "dptr");
11423         emitcode ("inc", "dptr");
11424         emitcode ("mov","a,b");
11425         emitcode ("orl","a,_ap");
11426         emitcode ("jz","!tlabel",lbl1->key+100);
11427         emitcode ("mov","a,_ap");
11428         emitcode ("add","a,#!constbyte",0xFF);
11429         emitcode ("mov","_ap,a");
11430         emitcode ("mov","a,b");
11431         emitcode ("addc","a,#!constbyte",0xFF);
11432         emitcode ("mov","b,a");
11433         emitcode ("sjmp","!tlabel",lbl->key+100);
11434         emitcode ("","!tlabeldef",lbl1->key+100);
11435     }
11436     emitcode ("mov", "dps,#0"); 
11437     _G.dptrInUse = _G.dptr1InUse = 0;
11438     unsavermask(rsave);
11439
11440 }
11441
11442 /*-----------------------------------------------------------------*/
11443 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11444 /*-----------------------------------------------------------------*/
11445 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11446 {
11447     operand *from , *to , *count;
11448     symbol *lbl,*lbl2;
11449     bitVect *rsave;
11450     int i;
11451
11452     /* we know it has to be 3 parameters */
11453     assert (nparms == 3);
11454     
11455     rsave = newBitVect(16);
11456     /* save DPTR if it needs to be saved */
11457     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11458             if (bitVectBitValue(ic->rMask,i))
11459                     rsave = bitVectSetBit(rsave,i);
11460     }
11461     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11462                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11463     savermask(rsave);
11464     
11465     to = parms[0];
11466     from = parms[1];
11467     count = parms[2];
11468
11469     aopOp (from, ic->next, FALSE, FALSE);
11470
11471     /* get from into DPTR1 */
11472     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11473     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11474     if (options.model == MODEL_FLAT24) {
11475         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11476     }
11477
11478     freeAsmop (from, NULL, ic, FALSE);
11479     aopOp (to, ic, FALSE, FALSE);
11480     /* get "to" into DPTR */
11481     /* if the operand is already in dptr
11482        then we do nothing else we move the value to dptr */
11483     if (AOP_TYPE (to) != AOP_STR) {
11484         /* if already in DPTR then we need to push */
11485         if (AOP_TYPE(to) == AOP_DPTR) {
11486             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11487             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11488             if (options.model == MODEL_FLAT24)
11489                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11490             emitcode ("pop", "dph");
11491             emitcode ("pop", "dpl");        
11492         } else {
11493             _startLazyDPSEvaluation ();
11494             /* if this is remateriazable */
11495             if (AOP_TYPE (to) == AOP_IMMD) {
11496                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11497             } else {                    /* we need to get it byte by byte */
11498                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11499                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11500                 if (options.model == MODEL_FLAT24) {
11501                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11502                 }
11503             }
11504             _endLazyDPSEvaluation ();
11505         }
11506     }
11507     freeAsmop (to, NULL, ic, FALSE);
11508     _G.dptrInUse = _G.dptr1InUse = 1;
11509     aopOp (count, ic->next->next, FALSE,FALSE);
11510     lbl =newiTempLabel(NULL);
11511     lbl2 =newiTempLabel(NULL);
11512
11513     /* now for the actual compare */
11514     if (AOP_TYPE(count) == AOP_LIT && 
11515         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11516         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11517         if (fromc)
11518             emitcode("lcall","__bi_memcmpc2x_s");
11519         else
11520             emitcode("lcall","__bi_memcmpx2x_s");
11521         freeAsmop (count, NULL, ic, FALSE);
11522         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11523         aopPut(AOP(IC_RESULT(ic)),"a",0);
11524         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11525     } else {
11526         symbol *lbl1 = newiTempLabel(NULL);
11527
11528         emitcode("push","ar0");         
11529         emitcode (";"," Auto increment but no djnz");
11530         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11531         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11532         freeAsmop (count, NULL, ic, FALSE);
11533         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11534         emitcode ("","!tlabeldef",lbl->key+100);
11535         if (fromc) {
11536             emitcode ("clr","a");
11537             emitcode ("movc", "a,@a+dptr");
11538         } else 
11539             emitcode ("movx", "a,@dptr");
11540         emitcode ("mov","r0,a");
11541         emitcode ("movx", "a,@dptr");
11542         emitcode ("clr","c");
11543         emitcode ("subb","a,r0");
11544         emitcode ("jnz","!tlabel",lbl2->key+100);
11545         emitcode ("inc", "dptr");
11546         emitcode ("inc", "dptr");
11547         emitcode ("mov","a,b");
11548         emitcode ("orl","a,_ap");
11549         emitcode ("jz","!tlabel",lbl1->key+100);
11550         emitcode ("mov","a,_ap");
11551         emitcode ("add","a,#!constbyte",0xFF);
11552         emitcode ("mov","_ap,a");
11553         emitcode ("mov","a,b");
11554         emitcode ("addc","a,#!constbyte",0xFF);
11555         emitcode ("mov","b,a");
11556         emitcode ("sjmp","!tlabel",lbl->key+100);
11557         emitcode ("","!tlabeldef",lbl1->key+100);
11558         emitcode ("clr","a");
11559         emitcode ("","!tlabeldef",lbl2->key+100);
11560         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11561         aopPut(AOP(IC_RESULT(ic)),"a",0);
11562         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11563         emitcode("pop","ar0");
11564         emitcode ("mov", "dps,#0");      
11565     }
11566     _G.dptrInUse = _G.dptr1InUse = 0;
11567     unsavermask(rsave);
11568
11569 }
11570
11571 /*-----------------------------------------------------------------*/
11572 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11573 /* port, first parameter output area second parameter pointer to   */
11574 /* port third parameter count                                      */
11575 /*-----------------------------------------------------------------*/
11576 static void genInp( iCode *ic, int nparms, operand **parms)
11577 {
11578     operand *from , *to , *count;
11579     symbol *lbl;
11580     bitVect *rsave;
11581     int i;
11582
11583     /* we know it has to be 3 parameters */
11584     assert (nparms == 3);
11585     
11586     rsave = newBitVect(16);
11587     /* save DPTR if it needs to be saved */
11588     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11589             if (bitVectBitValue(ic->rMask,i))
11590                     rsave = bitVectSetBit(rsave,i);
11591     }
11592     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11593                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11594     savermask(rsave);
11595     
11596     to = parms[0];
11597     from = parms[1];
11598     count = parms[2];
11599
11600     aopOp (from, ic->next, FALSE, FALSE);
11601
11602     /* get from into DPTR1 */
11603     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11604     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11605     if (options.model == MODEL_FLAT24) {
11606         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11607     }
11608
11609     freeAsmop (from, NULL, ic, FALSE);
11610     aopOp (to, ic, FALSE, FALSE);
11611     /* get "to" into DPTR */
11612     /* if the operand is already in dptr
11613        then we do nothing else we move the value to dptr */
11614     if (AOP_TYPE (to) != AOP_STR) {
11615         /* if already in DPTR then we need to push */
11616         if (AOP_TYPE(to) == AOP_DPTR) {
11617             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11618             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11619             if (options.model == MODEL_FLAT24)
11620                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11621             emitcode ("pop", "dph");
11622             emitcode ("pop", "dpl");        
11623         } else {
11624             _startLazyDPSEvaluation ();
11625             /* if this is remateriazable */
11626             if (AOP_TYPE (to) == AOP_IMMD) {
11627                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11628             } else {                    /* we need to get it byte by byte */
11629                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11630                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11631                 if (options.model == MODEL_FLAT24) {
11632                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11633                 }
11634             }
11635             _endLazyDPSEvaluation ();
11636         }
11637     }
11638     freeAsmop (to, NULL, ic, FALSE);
11639
11640     _G.dptrInUse = _G.dptr1InUse = 1;
11641     aopOp (count, ic->next->next, FALSE,FALSE);
11642     lbl =newiTempLabel(NULL);
11643
11644     /* now for the actual copy */
11645     if (AOP_TYPE(count) == AOP_LIT && 
11646         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11647         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11648         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11649         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11650         freeAsmop (count, NULL, ic, FALSE);
11651         emitcode ("","!tlabeldef",lbl->key+100);
11652         emitcode ("movx", "a,@dptr");   /* read data from port */
11653         emitcode ("dec","dps");         /* switch to DPTR */
11654         emitcode ("movx", "@dptr,a");   /* save into location */
11655         emitcode ("inc", "dptr");       /* point to next area */
11656         emitcode ("inc","dps");         /* switch to DPTR2 */
11657         emitcode ("djnz","b,!tlabel",lbl->key+100);
11658     } else {
11659         symbol *lbl1 = newiTempLabel(NULL);
11660         
11661         emitcode (";"," Auto increment but no djnz");
11662         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11663         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11664         freeAsmop (count, NULL, ic, FALSE);
11665         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11666         emitcode ("","!tlabeldef",lbl->key+100);
11667         emitcode ("movx", "a,@dptr");
11668         emitcode ("dec","dps");         /* switch to DPTR */
11669         emitcode ("movx", "@dptr,a");
11670         emitcode ("inc", "dptr");
11671         emitcode ("inc","dps");         /* switch to DPTR2 */
11672 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11673 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11674         emitcode ("mov","a,b");
11675         emitcode ("orl","a,_ap");
11676         emitcode ("jz","!tlabel",lbl1->key+100);
11677         emitcode ("mov","a,_ap");
11678         emitcode ("add","a,#!constbyte",0xFF);
11679         emitcode ("mov","_ap,a");
11680         emitcode ("mov","a,b");
11681         emitcode ("addc","a,#!constbyte",0xFF);
11682         emitcode ("mov","b,a");
11683         emitcode ("sjmp","!tlabel",lbl->key+100);
11684         emitcode ("","!tlabeldef",lbl1->key+100);
11685     }
11686     emitcode ("mov", "dps,#0"); 
11687     _G.dptrInUse = _G.dptr1InUse = 0;
11688     unsavermask(rsave);
11689
11690 }
11691
11692 /*-----------------------------------------------------------------*/
11693 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11694 /* port, first parameter output area second parameter pointer to   */
11695 /* port third parameter count                                      */
11696 /*-----------------------------------------------------------------*/
11697 static void genOutp( iCode *ic, int nparms, operand **parms)
11698 {
11699     operand *from , *to , *count;
11700     symbol *lbl;
11701     bitVect *rsave;
11702     int i;
11703
11704     /* we know it has to be 3 parameters */
11705     assert (nparms == 3);
11706     
11707     rsave = newBitVect(16);
11708     /* save DPTR if it needs to be saved */
11709     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11710             if (bitVectBitValue(ic->rMask,i))
11711                     rsave = bitVectSetBit(rsave,i);
11712     }
11713     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11714                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11715     savermask(rsave);
11716     
11717     to = parms[0];
11718     from = parms[1];
11719     count = parms[2];
11720
11721     aopOp (from, ic->next, FALSE, FALSE);
11722
11723     /* get from into DPTR1 */
11724     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11725     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11726     if (options.model == MODEL_FLAT24) {
11727         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11728     }
11729
11730     freeAsmop (from, NULL, ic, FALSE);
11731     aopOp (to, ic, FALSE, FALSE);
11732     /* get "to" into DPTR */
11733     /* if the operand is already in dptr
11734        then we do nothing else we move the value to dptr */
11735     if (AOP_TYPE (to) != AOP_STR) {
11736         /* if already in DPTR then we need to push */
11737         if (AOP_TYPE(to) == AOP_DPTR) {
11738             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11739             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11740             if (options.model == MODEL_FLAT24)
11741                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11742             emitcode ("pop", "dph");
11743             emitcode ("pop", "dpl");        
11744         } else {
11745             _startLazyDPSEvaluation ();
11746             /* if this is remateriazable */
11747             if (AOP_TYPE (to) == AOP_IMMD) {
11748                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11749             } else {                    /* we need to get it byte by byte */
11750                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11751                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11752                 if (options.model == MODEL_FLAT24) {
11753                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11754                 }
11755             }
11756             _endLazyDPSEvaluation ();
11757         }
11758     }
11759     freeAsmop (to, NULL, ic, FALSE);
11760
11761     _G.dptrInUse = _G.dptr1InUse = 1;
11762     aopOp (count, ic->next->next, FALSE,FALSE);
11763     lbl =newiTempLabel(NULL);
11764
11765     /* now for the actual copy */
11766     if (AOP_TYPE(count) == AOP_LIT && 
11767         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11768         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11769         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11770         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11771         emitcode ("","!tlabeldef",lbl->key+100);
11772         emitcode ("movx", "a,@dptr");   /* read data from port */
11773         emitcode ("inc","dps");         /* switch to DPTR2 */
11774         emitcode ("movx", "@dptr,a");   /* save into location */
11775         emitcode ("inc", "dptr");       /* point to next area */
11776         emitcode ("dec","dps");         /* switch to DPTR */
11777         emitcode ("djnz","b,!tlabel",lbl->key+100);
11778         freeAsmop (count, NULL, ic, FALSE);
11779     } else {
11780         symbol *lbl1 = newiTempLabel(NULL);
11781         
11782         emitcode (";"," Auto increment but no djnz");
11783         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11784         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11785         freeAsmop (count, NULL, ic, FALSE);
11786         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11787         emitcode ("","!tlabeldef",lbl->key+100);
11788         emitcode ("movx", "a,@dptr");
11789         emitcode ("inc", "dptr");
11790         emitcode ("inc","dps");         /* switch to DPTR2 */
11791         emitcode ("movx", "@dptr,a");
11792         emitcode ("dec","dps");         /* switch to DPTR */
11793         emitcode ("mov","a,b");
11794         emitcode ("orl","a,_ap");
11795         emitcode ("jz","!tlabel",lbl1->key+100);
11796         emitcode ("mov","a,_ap");
11797         emitcode ("add","a,#!constbyte",0xFF);
11798         emitcode ("mov","_ap,a");
11799         emitcode ("mov","a,b");
11800         emitcode ("addc","a,#!constbyte",0xFF);
11801         emitcode ("mov","b,a");
11802         emitcode ("sjmp","!tlabel",lbl->key+100);
11803         emitcode ("","!tlabeldef",lbl1->key+100);
11804     }
11805     emitcode ("mov", "dps,#0"); 
11806     _G.dptrInUse = _G.dptr1InUse = 0;
11807     unsavermask(rsave);
11808
11809 }
11810
11811 /*-----------------------------------------------------------------*/
11812 /* genSwapW - swap lower & high order bytes                        */
11813 /*-----------------------------------------------------------------*/
11814 static void genSwapW(iCode *ic, int nparms, operand **parms)
11815 {
11816     operand *dest;
11817     operand *src;
11818     assert (nparms==1);
11819
11820     src = parms[0];
11821     dest=IC_RESULT(ic);
11822
11823     assert(getSize(operandType(src))==2);
11824
11825     aopOp (src, ic, FALSE, FALSE);
11826     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11827     _G.accInUse++;
11828     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11829     _G.accInUse--;
11830     freeAsmop (src, NULL, ic, FALSE);
11831     
11832     aopOp (dest,ic, FALSE, FALSE);
11833     aopPut(AOP(dest),"b",0);
11834     aopPut(AOP(dest),"a",1);
11835     freeAsmop (dest, NULL, ic, FALSE);    
11836 }
11837
11838 /*-----------------------------------------------------------------*/
11839 /* genMemsetX - gencode for memSetX data                           */
11840 /*-----------------------------------------------------------------*/
11841 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11842 {
11843     operand *to , *val , *count;
11844     symbol *lbl;
11845     char *l;
11846     int i;
11847     bitVect *rsave;
11848
11849     /* we know it has to be 3 parameters */
11850     assert (nparms == 3);
11851     
11852     to = parms[0];
11853     val = parms[1];
11854     count = parms[2];
11855         
11856     /* save DPTR if it needs to be saved */
11857     rsave = newBitVect(16);
11858     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11859             if (bitVectBitValue(ic->rMask,i))
11860                     rsave = bitVectSetBit(rsave,i);
11861     }
11862     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11863                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11864     savermask(rsave);
11865
11866     aopOp (to, ic, FALSE, FALSE);
11867     /* get "to" into DPTR */
11868     /* if the operand is already in dptr
11869        then we do nothing else we move the value to dptr */
11870     if (AOP_TYPE (to) != AOP_STR) {
11871         /* if already in DPTR then we need to push */
11872         if (AOP_TYPE(to) == AOP_DPTR) {
11873             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11874             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11875             if (options.model == MODEL_FLAT24)
11876                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11877             emitcode ("pop", "dph");
11878             emitcode ("pop", "dpl");        
11879         } else {
11880             _startLazyDPSEvaluation ();
11881             /* if this is remateriazable */
11882             if (AOP_TYPE (to) == AOP_IMMD) {
11883                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11884             } else {                    /* we need to get it byte by byte */
11885                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11886                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11887                 if (options.model == MODEL_FLAT24) {
11888                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11889                 }
11890             }
11891             _endLazyDPSEvaluation ();
11892         }
11893     }
11894     freeAsmop (to, NULL, ic, FALSE);
11895
11896     aopOp (val, ic->next->next, FALSE,FALSE);
11897     aopOp (count, ic->next->next, FALSE,FALSE);    
11898     lbl =newiTempLabel(NULL);
11899     /* now for the actual copy */
11900     if (AOP_TYPE(count) == AOP_LIT && 
11901         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11902         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11903         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11904         MOVA(l);
11905         emitcode ("","!tlabeldef",lbl->key+100);
11906         emitcode ("movx", "@dptr,a");
11907         emitcode ("inc", "dptr");
11908         emitcode ("djnz","b,!tlabel",lbl->key+100);
11909     } else {
11910         symbol *lbl1 = newiTempLabel(NULL);
11911         
11912         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11913         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11914         emitcode ("","!tlabeldef",lbl->key+100);
11915         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11916         emitcode ("movx", "@dptr,a");
11917         emitcode ("inc", "dptr");
11918         emitcode ("mov","a,b");
11919         emitcode ("orl","a,_ap");
11920         emitcode ("jz","!tlabel",lbl1->key+100);
11921         emitcode ("mov","a,_ap");
11922         emitcode ("add","a,#!constbyte",0xFF);
11923         emitcode ("mov","_ap,a");
11924         emitcode ("mov","a,b");
11925         emitcode ("addc","a,#!constbyte",0xFF);
11926         emitcode ("mov","b,a");
11927         emitcode ("sjmp","!tlabel",lbl->key+100);
11928         emitcode ("","!tlabeldef",lbl1->key+100);
11929     }
11930     freeAsmop (count, NULL, ic, FALSE);
11931     unsavermask(rsave);
11932 }
11933
11934 /*-----------------------------------------------------------------*/
11935 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11936 /*-----------------------------------------------------------------*/
11937 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11938 {
11939         bitVect *rsave ;
11940         operand *pnum, *result;
11941         int i;
11942     
11943         assert (nparms==1);
11944         /* save registers that need to be saved */
11945         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11946                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11947     
11948         pnum = parms[0]; 
11949         aopOp (pnum, ic, FALSE, FALSE);
11950         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11951         freeAsmop (pnum, NULL, ic, FALSE);
11952         emitcode ("lcall","NatLib_LoadPrimitive");
11953         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11954         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11955             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11956                 for (i = (size-1) ; i >= 0 ; i-- ) {
11957                         emitcode ("push","a%s",javaRet[i]);
11958                 }
11959                 for (i=0; i < size ; i++ ) {
11960                         emitcode ("pop","a%s",
11961                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11962                 }
11963         } else {
11964                 for (i = 0 ; i < size ; i++ ) {
11965                         aopPut(AOP(result),javaRet[i],i);
11966                 }
11967         }    
11968         freeAsmop (result, NULL, ic, FALSE);
11969         unsavermask(rsave);
11970 }
11971
11972 /*-----------------------------------------------------------------*/
11973 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11974 /*-----------------------------------------------------------------*/
11975 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11976 {
11977         bitVect *rsave ;
11978         operand *pnum, *result;
11979         int size = 3;
11980         int i;
11981     
11982         assert (nparms==1);
11983         /* save registers that need to be saved */
11984         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11985                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11986     
11987         pnum = parms[0]; 
11988         aopOp (pnum, ic, FALSE, FALSE);
11989         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11990         freeAsmop (pnum, NULL, ic, FALSE);
11991         emitcode ("lcall","NatLib_LoadPointer");
11992         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11993         if (AOP_TYPE(result)!=AOP_STR) {
11994                 for (i = 0 ; i < size ; i++ ) {
11995                         aopPut(AOP(result),fReturn[i],i);
11996                 }
11997         }    
11998         freeAsmop (result, NULL, ic, FALSE);
11999         unsavermask(rsave);
12000 }
12001
12002 /*-----------------------------------------------------------------*/
12003 /* genNatLibInstallStateBlock -                                    */
12004 /*-----------------------------------------------------------------*/
12005 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12006                                        operand **parms, const char *name)
12007 {
12008         bitVect *rsave ;
12009         operand *psb, *handle;
12010         assert (nparms==2);
12011
12012         /* save registers that need to be saved */
12013         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12014                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12015         psb = parms[0];
12016         handle = parms[1];
12017
12018         /* put pointer to state block into DPTR1 */
12019         aopOp (psb, ic, FALSE, FALSE);
12020         if (AOP_TYPE (psb) == AOP_IMMD) {
12021                 emitcode ("mov","dps,#1");
12022                 emitcode ("mov", "dptr,%s",
12023                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12024                 emitcode ("mov","dps,#0");
12025         } else {
12026                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12027                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12028                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12029         }
12030         freeAsmop (psb, NULL, ic, FALSE);
12031
12032         /* put libraryID into DPTR */
12033         emitcode ("mov","dptr,#LibraryID");
12034
12035         /* put handle into r3:r2 */
12036         aopOp (handle, ic, FALSE, FALSE);
12037         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12038                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12039                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12040                 emitcode ("pop","ar3");
12041                 emitcode ("pop","ar2");
12042         } else {        
12043                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12044                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12045         }
12046         freeAsmop (psb, NULL, ic, FALSE);
12047
12048         /* make the call */
12049         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12050
12051         /* put return value into place*/
12052         _G.accInUse++;
12053         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12054         _G.accInUse--;
12055         aopPut(AOP(IC_RESULT(ic)),"a",0);
12056         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12057         unsavermask(rsave);
12058 }
12059
12060 /*-----------------------------------------------------------------*/
12061 /* genNatLibRemoveStateBlock -                                     */
12062 /*-----------------------------------------------------------------*/
12063 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12064 {
12065         bitVect *rsave ;
12066
12067         assert(nparms==0);
12068
12069         /* save registers that need to be saved */
12070         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12071                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12072
12073         /* put libraryID into DPTR */
12074         emitcode ("mov","dptr,#LibraryID");
12075         /* make the call */
12076         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12077         unsavermask(rsave);
12078 }
12079
12080 /*-----------------------------------------------------------------*/
12081 /* genNatLibGetStateBlock -                                        */
12082 /*-----------------------------------------------------------------*/
12083 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12084                                    operand **parms,const char *name)
12085 {
12086         bitVect *rsave ;
12087         symbol *lbl = newiTempLabel(NULL);
12088         
12089         assert(nparms==0);
12090         /* save registers that need to be saved */
12091         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12092                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12093
12094         /* put libraryID into DPTR */
12095         emitcode ("mov","dptr,#LibraryID");
12096         /* make the call */
12097         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12098         emitcode ("jnz","!tlabel",lbl->key+100);
12099
12100         /* put return value into place */
12101         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12102         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12103                 emitcode ("push","ar3");
12104                 emitcode ("push","ar2");
12105                 emitcode ("pop","%s",
12106                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12107                 emitcode ("pop","%s",
12108                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12109         } else {
12110                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12111                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12112         }
12113         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12114         emitcode ("","!tlabeldef",lbl->key+100);
12115         unsavermask(rsave);
12116 }
12117
12118 /*-----------------------------------------------------------------*/
12119 /* genMMMalloc -                                                   */
12120 /*-----------------------------------------------------------------*/
12121 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12122                          int size, const char *name)
12123 {
12124         bitVect *rsave ;
12125         operand *bsize;
12126         symbol *rsym;
12127         symbol *lbl = newiTempLabel(NULL);
12128
12129         assert (nparms == 1);
12130         /* save registers that need to be saved */
12131         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12132                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12133         
12134         bsize=parms[0];
12135         aopOp (bsize,ic,FALSE,FALSE);
12136
12137         /* put the size in R4-R2 */
12138         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12139                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12140                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12141                 if (size==3) {
12142                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12143                         emitcode("pop","ar4");
12144                 }
12145                 emitcode("pop","ar3");
12146                 emitcode("pop","ar2");          
12147         } else {
12148                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12149                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12150                 if (size==3) {
12151                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12152                 }
12153         }
12154         freeAsmop (bsize, NULL, ic, FALSE);
12155
12156         /* make the call */
12157         emitcode ("lcall","MM_%s",name);
12158         emitcode ("jz","!tlabel",lbl->key+100);
12159         emitcode ("mov","r2,#!constbyte",0xff);
12160         emitcode ("mov","r3,#!constbyte",0xff);
12161         emitcode ("","!tlabeldef",lbl->key+100);
12162         /* we don't care about the pointer : we just save the handle */
12163         rsym = OP_SYMBOL(IC_RESULT(ic));
12164         if (rsym->liveFrom != rsym->liveTo) {
12165                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12166                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12167                         emitcode ("push","ar3");
12168                         emitcode ("push","ar2");
12169                         emitcode ("pop","%s",
12170                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12171                         emitcode ("pop","%s",
12172                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12173                 } else {
12174                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12175                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12176                 }
12177                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12178         }
12179         unsavermask(rsave);
12180 }
12181
12182 /*-----------------------------------------------------------------*/
12183 /* genMMDeref -                                                    */
12184 /*-----------------------------------------------------------------*/
12185 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12186 {
12187         bitVect *rsave ;
12188         operand *handle;
12189
12190         assert (nparms == 1);
12191         /* save registers that need to be saved */
12192         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12193                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12194         
12195         handle=parms[0];
12196         aopOp (handle,ic,FALSE,FALSE);
12197
12198         /* put the size in R4-R2 */
12199         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12200                 emitcode("push","%s",
12201                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12202                 emitcode("push","%s",
12203                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12204                 emitcode("pop","ar3");
12205                 emitcode("pop","ar2");          
12206         } else {
12207                 emitcode ("mov","r2,%s",
12208                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12209                 emitcode ("mov","r3,%s",
12210                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12211         }
12212         freeAsmop (handle, NULL, ic, FALSE);
12213
12214         /* make the call */
12215         emitcode ("lcall","MM_Deref");
12216         
12217         {
12218                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12219                 if (rsym->liveFrom != rsym->liveTo) {                   
12220                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12221                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12222                             _startLazyDPSEvaluation ();
12223                             
12224                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12225                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12226                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12227
12228                             _endLazyDPSEvaluation ();
12229                             
12230                         }
12231                 }
12232         }
12233         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12234         unsavermask(rsave);
12235 }
12236
12237 /*-----------------------------------------------------------------*/
12238 /* genMMUnrestrictedPersist -                                      */
12239 /*-----------------------------------------------------------------*/
12240 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12241 {
12242         bitVect *rsave ;
12243         operand *handle;
12244
12245         assert (nparms == 1);
12246         /* save registers that need to be saved */
12247         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12248                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12249         
12250         handle=parms[0];
12251         aopOp (handle,ic,FALSE,FALSE);
12252
12253         /* put the size in R3-R2 */
12254         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12255                 emitcode("push","%s",
12256                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12257                 emitcode("push","%s",
12258                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12259                 emitcode("pop","ar3");
12260                 emitcode("pop","ar2");          
12261         } else {
12262                 emitcode ("mov","r2,%s",
12263                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12264                 emitcode ("mov","r3,%s",
12265                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12266         }
12267         freeAsmop (handle, NULL, ic, FALSE);
12268
12269         /* make the call */
12270         emitcode ("lcall","MM_UnrestrictedPersist");
12271
12272         {
12273                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12274                 if (rsym->liveFrom != rsym->liveTo) {   
12275                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12276                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12277                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12278                 }
12279         }
12280         unsavermask(rsave);
12281 }
12282
12283 /*-----------------------------------------------------------------*/
12284 /* genSystemExecJavaProcess -                                      */
12285 /*-----------------------------------------------------------------*/
12286 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12287 {
12288         bitVect *rsave ;
12289         operand *handle, *pp;
12290
12291         assert (nparms==2);
12292         /* save registers that need to be saved */
12293         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12294                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12295         
12296         pp = parms[0];
12297         handle = parms[1];
12298         
12299         /* put the handle in R3-R2 */
12300         aopOp (handle,ic,FALSE,FALSE);
12301         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12302                 emitcode("push","%s",
12303                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12304                 emitcode("push","%s",
12305                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12306                 emitcode("pop","ar3");
12307                 emitcode("pop","ar2");          
12308         } else {
12309                 emitcode ("mov","r2,%s",
12310                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12311                 emitcode ("mov","r3,%s",
12312                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12313         }
12314         freeAsmop (handle, NULL, ic, FALSE);
12315         
12316         /* put pointer in DPTR */
12317         aopOp (pp,ic,FALSE,FALSE);
12318         if (AOP_TYPE(pp) == AOP_IMMD) {
12319                 emitcode ("mov", "dptr,%s",
12320                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12321         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12322                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12323                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12324                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12325         }
12326         freeAsmop (handle, NULL, ic, FALSE);
12327
12328         /* make the call */
12329         emitcode ("lcall","System_ExecJavaProcess");
12330         
12331         /* put result in place */
12332         {
12333                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12334                 if (rsym->liveFrom != rsym->liveTo) {   
12335                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12336                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12337                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12338                 }
12339         }
12340         
12341         unsavermask(rsave);
12342 }
12343
12344 /*-----------------------------------------------------------------*/
12345 /* genSystemRTCRegisters -                                         */
12346 /*-----------------------------------------------------------------*/
12347 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12348                                   char *name)
12349 {
12350         bitVect *rsave ;
12351         operand *pp;
12352
12353         assert (nparms==1);
12354         /* save registers that need to be saved */
12355         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12356                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12357         
12358         pp=parms[0];
12359         /* put pointer in DPTR */
12360         aopOp (pp,ic,FALSE,FALSE);
12361         if (AOP_TYPE (pp) == AOP_IMMD) {
12362                 emitcode ("mov","dps,#1");
12363                 emitcode ("mov", "dptr,%s", 
12364                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12365                 emitcode ("mov","dps,#0");
12366         } else {
12367                 emitcode ("mov","dpl1,%s",
12368                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12369                 emitcode ("mov","dph1,%s",
12370                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12371                 emitcode ("mov","dpx1,%s",
12372                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12373         }
12374         freeAsmop (pp, NULL, ic, FALSE);
12375
12376         /* make the call */
12377         emitcode ("lcall","System_%sRTCRegisters",name);
12378
12379         unsavermask(rsave);
12380 }
12381
12382 /*-----------------------------------------------------------------*/
12383 /* genSystemThreadSleep -                                          */
12384 /*-----------------------------------------------------------------*/
12385 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12386 {
12387         bitVect *rsave ;
12388         operand *to, *s;
12389
12390         assert (nparms==1);
12391         /* save registers that need to be saved */
12392         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12393                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12394
12395         to = parms[0];
12396         aopOp(to,ic,FALSE,FALSE);
12397         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12398             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12399                 emitcode ("push","%s",
12400                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12401                 emitcode ("push","%s",
12402                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12403                 emitcode ("push","%s",
12404                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12405                 emitcode ("push","%s",
12406                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12407                 emitcode ("pop","ar3");
12408                 emitcode ("pop","ar2");
12409                 emitcode ("pop","ar1");
12410                 emitcode ("pop","ar0");
12411         } else {
12412                 emitcode ("mov","r0,%s",
12413                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12414                 emitcode ("mov","r1,%s",
12415                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12416                 emitcode ("mov","r2,%s",
12417                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12418                 emitcode ("mov","r3,%s",
12419                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12420         }
12421         freeAsmop (to, NULL, ic, FALSE);
12422
12423         /* suspend in acc */
12424         s = parms[1];
12425         aopOp(s,ic,FALSE,FALSE);
12426         emitcode ("mov","a,%s",
12427                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12428         freeAsmop (s, NULL, ic, FALSE);
12429
12430         /* make the call */
12431         emitcode ("lcall","System_%s",name);
12432
12433         unsavermask(rsave);
12434 }
12435
12436 /*-----------------------------------------------------------------*/
12437 /* genSystemThreadResume -                                         */
12438 /*-----------------------------------------------------------------*/
12439 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12440 {
12441         bitVect *rsave ;
12442         operand *tid,*pid;
12443
12444         assert (nparms==2);
12445         /* save registers that need to be saved */
12446         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12447                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12448         
12449         tid = parms[0];
12450         pid = parms[1];
12451         
12452         /* PID in R0 */
12453         aopOp(pid,ic,FALSE,FALSE);
12454         emitcode ("mov","r0,%s",
12455                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12456         freeAsmop (pid, NULL, ic, FALSE);
12457         
12458         /* tid into ACC */
12459         aopOp(tid,ic,FALSE,FALSE);
12460         emitcode ("mov","a,%s",
12461                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12462         freeAsmop (tid, NULL, ic, FALSE);
12463         
12464         emitcode ("lcall","System_ThreadResume");
12465
12466         /* put result into place */
12467         {
12468                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12469                 if (rsym->liveFrom != rsym->liveTo) {   
12470                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12471                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12472                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12473                 }
12474         }
12475         unsavermask(rsave);
12476 }
12477
12478 /*-----------------------------------------------------------------*/
12479 /* genSystemProcessResume -                                        */
12480 /*-----------------------------------------------------------------*/
12481 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12482 {
12483         bitVect *rsave ;
12484         operand *pid;
12485
12486         assert (nparms==1);
12487         /* save registers that need to be saved */
12488         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12489                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12490         
12491         pid = parms[0];
12492         
12493         /* pid into ACC */
12494         aopOp(pid,ic,FALSE,FALSE);
12495         emitcode ("mov","a,%s",
12496                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12497         freeAsmop (pid, NULL, ic, FALSE);
12498         
12499         emitcode ("lcall","System_ProcessResume");
12500
12501         unsavermask(rsave);
12502 }
12503
12504 /*-----------------------------------------------------------------*/
12505 /* genSystem -                                                     */
12506 /*-----------------------------------------------------------------*/
12507 static void genSystem (iCode *ic,int nparms,char *name)
12508 {
12509         assert(nparms == 0);
12510
12511         emitcode ("lcall","System_%s",name);
12512 }
12513
12514 /*-----------------------------------------------------------------*/
12515 /* genSystemPoll -                                                  */
12516 /*-----------------------------------------------------------------*/
12517 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12518 {
12519         bitVect *rsave ;
12520         operand *fp;
12521
12522         assert (nparms==1);
12523         /* save registers that need to be saved */
12524         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12525                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12526
12527         fp = parms[0];
12528         aopOp (fp,ic,FALSE,FALSE);
12529         if (AOP_TYPE (fp) == AOP_IMMD) {
12530                 emitcode ("mov", "dptr,%s", 
12531                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12532         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12533                 emitcode ("mov","dpl,%s",
12534                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12535                 emitcode ("mov","dph,%s",
12536                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12537                 emitcode ("mov","dpx,%s",
12538                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12539         }
12540         freeAsmop (fp, NULL, ic, FALSE);
12541
12542         emitcode ("lcall","System_%sPoll",name);
12543
12544         /* put result into place */
12545         {
12546                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12547                 if (rsym->liveFrom != rsym->liveTo) {   
12548                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12549                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12550                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12551                 }
12552         }
12553         unsavermask(rsave);
12554 }
12555
12556 /*-----------------------------------------------------------------*/
12557 /* genSystemGetCurrentID -                                         */
12558 /*-----------------------------------------------------------------*/
12559 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12560 {
12561         assert (nparms==0);
12562
12563         emitcode ("lcall","System_GetCurrent%sId",name);
12564         /* put result into place */
12565         {
12566                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12567                 if (rsym->liveFrom != rsym->liveTo) {   
12568                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12569                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12570                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12571                 }
12572         }
12573 }
12574
12575 /*-----------------------------------------------------------------*/
12576 /* genDummyRead - generate code for dummy read of volatiles        */
12577 /*-----------------------------------------------------------------*/
12578 static void
12579 genDummyRead (iCode * ic)
12580 {
12581   operand *right;
12582   int size, offset;
12583
12584   D(emitcode(";     genDummyRead",""));
12585
12586   right = IC_RIGHT (ic);
12587
12588   aopOp (right, ic, FALSE, FALSE);
12589
12590   /* if the result is a bit */
12591   if (AOP_TYPE (right) == AOP_CRY)
12592     {
12593       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12594       goto release;
12595     }
12596
12597   /* bit variables done */
12598   /* general case */
12599   size = AOP_SIZE (right);
12600   offset = 0;
12601   while (size--)
12602     {
12603       emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12604       offset++;
12605     }
12606
12607 release:
12608   freeAsmop (right, NULL, ic, TRUE);
12609 }
12610
12611 /*-----------------------------------------------------------------*/
12612 /* genBuiltIn - calls the appropriate function to  generating code */
12613 /* for a built in function                                         */
12614 /*-----------------------------------------------------------------*/
12615 static void genBuiltIn (iCode *ic)
12616 {
12617         operand *bi_parms[MAX_BUILTIN_ARGS];
12618         int nbi_parms;
12619         iCode *bi_iCode;
12620         symbol *bif;
12621
12622         /* get all the arguments for a built in function */
12623         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12624
12625         /* which function is it */
12626         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12627         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12628                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12629         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12630                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12631         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12632                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12633         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12634                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12635         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12636                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12637         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12638                 genInp(bi_iCode,nbi_parms,bi_parms);
12639         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12640                 genOutp(bi_iCode,nbi_parms,bi_parms);
12641         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12642                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12643                 /* JavaNative builtIns */               
12644         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12645                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12646         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12647                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12648         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12649                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12650         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12651                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12652         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12653                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12654         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12655                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12656         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12657                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12658         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12659                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12660         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12661                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12662         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12663                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12664         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12665                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12666         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12667                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12668         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12669                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12670         } else if (strcmp(bif->name,"MM_Free")==0) {
12671                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12672         } else if (strcmp(bif->name,"MM_Deref")==0) {
12673                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12674         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12675                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12676         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12677                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12678         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12679                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12680         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12681                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12682         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12683                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12684         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12685                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12686         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12687                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12688         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12689                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12690         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12691                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12692         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12693                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12694         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12695                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12696         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12697                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12698         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12699                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12700         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12701                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12702         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12703                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12704         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12705                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12706         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12707                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12708         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12709                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12710         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12711                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12712         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12713                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12714         } else {
12715                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12716                 return ;
12717         }
12718         return ;    
12719 }
12720
12721 /*-----------------------------------------------------------------*/
12722 /* gen390Code - generate code for Dallas 390 based controllers     */
12723 /*-----------------------------------------------------------------*/
12724 void
12725 gen390Code (iCode * lic)
12726 {
12727   iCode *ic;
12728   int cln = 0;
12729
12730   lineHead = lineCurr = NULL;
12731   dptrn[1][0] = "dpl1";
12732   dptrn[1][1] = "dph1";
12733   dptrn[1][2] = "dpx1";
12734   
12735   if (options.model == MODEL_FLAT24) {
12736     fReturnSizeDS390 = 5;
12737     fReturn = fReturn24;
12738   } else {
12739     fReturnSizeDS390 = 4;
12740     fReturn = fReturn16;
12741     options.stack10bit=0;
12742   }
12743 #if 1
12744   /* print the allocation information */
12745   if (allocInfo && currFunc)
12746     printAllocInfo (currFunc, codeOutFile);
12747 #endif
12748   /* if debug information required */
12749   if (options.debug && currFunc)
12750     {
12751       debugFile->writeFunction(currFunc);
12752       _G.debugLine = 1;
12753       if (IS_STATIC (currFunc->etype))
12754         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12755       else
12756         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12757       _G.debugLine = 0;
12758     }
12759   /* stack pointer name */
12760   if (options.useXstack)
12761     spname = "_spx";
12762   else
12763     spname = "sp";
12764
12765
12766   for (ic = lic; ic; ic = ic->next)
12767     {
12768
12769       if (ic->lineno && cln != ic->lineno)
12770         {
12771           if (options.debug)
12772             {
12773               _G.debugLine = 1;
12774               emitcode ("", "C$%s$%d$%d$%d ==.",
12775                         FileBaseName (ic->filename), ic->lineno,
12776                         ic->level, ic->block);
12777               _G.debugLine = 0;
12778             }
12779           if (!options.noCcodeInAsm) {
12780             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12781                       printCLine(ic->filename, ic->lineno));
12782           }
12783           cln = ic->lineno;
12784         }
12785       if (options.iCodeInAsm) {
12786         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12787       }
12788       /* if the result is marked as
12789          spilt and rematerializable or code for
12790          this has already been generated then
12791          do nothing */
12792       if (resultRemat (ic) || ic->generated)
12793         continue;
12794
12795       /* depending on the operation */
12796       switch (ic->op)
12797         {
12798         case '!':
12799           genNot (ic);
12800           break;
12801
12802         case '~':
12803           genCpl (ic);
12804           break;
12805
12806         case UNARYMINUS:
12807           genUminus (ic);
12808           break;
12809
12810         case IPUSH:
12811           genIpush (ic);
12812           break;
12813
12814         case IPOP:
12815           /* IPOP happens only when trying to restore a
12816              spilt live range, if there is an ifx statement
12817              following this pop then the if statement might
12818              be using some of the registers being popped which
12819              would destory the contents of the register so
12820              we need to check for this condition and handle it */
12821           if (ic->next &&
12822               ic->next->op == IFX &&
12823               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12824             genIfx (ic->next, ic);
12825           else
12826             genIpop (ic);
12827           break;
12828
12829         case CALL:
12830           genCall (ic);
12831           break;
12832
12833         case PCALL:
12834           genPcall (ic);
12835           break;
12836
12837         case FUNCTION:
12838           genFunction (ic);
12839           break;
12840
12841         case ENDFUNCTION:
12842           genEndFunction (ic);
12843           break;
12844
12845         case RETURN:
12846           genRet (ic);
12847           break;
12848
12849         case LABEL:
12850           genLabel (ic);
12851           break;
12852
12853         case GOTO:
12854           genGoto (ic);
12855           break;
12856
12857         case '+':
12858           genPlus (ic);
12859           break;
12860
12861         case '-':
12862           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12863             genMinus (ic);
12864           break;
12865
12866         case '*':
12867           genMult (ic);
12868           break;
12869
12870         case '/':
12871           genDiv (ic);
12872           break;
12873
12874         case '%':
12875           genMod (ic);
12876           break;
12877
12878         case '>':
12879           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12880           break;
12881
12882         case '<':
12883           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12884           break;
12885
12886         case LE_OP:
12887         case GE_OP:
12888         case NE_OP:
12889
12890           /* note these two are xlated by algebraic equivalence
12891              during parsing SDCC.y */
12892           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12893                   "got '>=' or '<=' shouldn't have come here");
12894           break;
12895
12896         case EQ_OP:
12897           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12898           break;
12899
12900         case AND_OP:
12901           genAndOp (ic);
12902           break;
12903
12904         case OR_OP:
12905           genOrOp (ic);
12906           break;
12907
12908         case '^':
12909           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12910           break;
12911
12912         case '|':
12913           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12914           break;
12915
12916         case BITWISEAND:
12917           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12918           break;
12919
12920         case INLINEASM:
12921           genInline (ic);
12922           break;
12923
12924         case RRC:
12925           genRRC (ic);
12926           break;
12927
12928         case RLC:
12929           genRLC (ic);
12930           break;
12931
12932         case GETHBIT:
12933           genGetHbit (ic);
12934           break;
12935
12936         case LEFT_OP:
12937           genLeftShift (ic);
12938           break;
12939
12940         case RIGHT_OP:
12941           genRightShift (ic);
12942           break;
12943
12944         case GET_VALUE_AT_ADDRESS:
12945           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12946           break;
12947
12948         case '=':
12949           if (POINTER_SET (ic))
12950             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12951           else
12952             genAssign (ic);
12953           break;
12954
12955         case IFX:
12956           genIfx (ic, NULL);
12957           break;
12958
12959         case ADDRESS_OF:
12960           genAddrOf (ic);
12961           break;
12962
12963         case JUMPTABLE:
12964           genJumpTab (ic);
12965           break;
12966
12967         case CAST:
12968           genCast (ic);
12969           break;
12970
12971         case RECEIVE:
12972           genReceive (ic);
12973           break;
12974
12975         case SEND:
12976           if (ic->builtinSEND) genBuiltIn(ic);
12977           else addSet (&_G.sendSet, ic);
12978           break;
12979
12980         case DUMMY_READ_VOLATILE:
12981           genDummyRead (ic);
12982           break;
12983
12984 #if 0 // obsolete, and buggy for != xdata
12985         case ARRAYINIT:
12986             genArrayInit(ic);
12987             break;
12988 #endif
12989             
12990         default:
12991           ic = ic;
12992         }
12993     }
12994
12995
12996   /* now we are ready to call the
12997      peep hole optimizer */
12998   if (!options.nopeep)
12999     peepHole (&lineHead);
13000
13001   /* now do the actual printing */
13002   printLine (lineHead, codeOutFile);
13003   return;
13004 }