a6b6702454eb6b3c6a71e20069fda817e18e7113
[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   operand *op;
448   int size;
449   int accuseSize = 0;
450   int accuse = 0;
451   
452   if (!ic)
453     {
454       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
455               "null iCode pointer");
456       return 0;
457     }
458
459   if (ic->op == IFX)
460     {
461       op = IC_COND (ic);
462       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
463         {
464           accuse = 1;
465           size = getSize (OP_SYMBOL (op)->type);
466           if (size>accuseSize)
467             accuseSize = size;
468         }
469     }
470   else if (ic->op == JUMPTABLE)
471     {
472       op = IC_JTCOND (ic);
473       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
474         {
475           accuse = 1;
476           size = getSize (OP_SYMBOL (op)->type);
477           if (size>accuseSize)
478             accuseSize = size;
479         }
480     }
481   else
482     {
483       op = IC_LEFT (ic);
484       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
485         {
486           accuse = 1;
487           size = getSize (OP_SYMBOL (op)->type);
488           if (size>accuseSize)
489             accuseSize = size;
490         }
491       op = IC_RIGHT (ic);
492       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
493         {
494           accuse = 1;
495           size = getSize (OP_SYMBOL (op)->type);
496           if (size>accuseSize)
497             accuseSize = size;
498         }
499     }
500   
501   if (accuseSize)
502     return accuseSize;
503   else
504     return accuse;
505 }
506
507 /*-----------------------------------------------------------------*/
508 /* aopForSym - for a true symbol                                   */
509 /*-----------------------------------------------------------------*/
510 static asmop *
511 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
512 {
513   asmop *aop;
514   memmap *space = SPEC_OCLS (sym->etype);
515   int accuse = leftRightUseAcc (ic);
516
517   /* if already has one */
518   if (sym->aop)
519     return sym->aop;
520
521   /* assign depending on the storage class */
522   /* if it is on the stack or indirectly addressable */
523   /* space we need to assign either r0 or r1 to it   */
524   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
525     {
526       sym->aop = aop = newAsmop (0);
527       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
528       aop->size = getSize (sym->type);
529
530       /* now assign the address of the variable to
531          the pointer register */
532       if (aop->type != AOP_STK)
533         {
534
535           if (sym->onStack)
536             {
537               if (_G.accInUse || accuse)
538                 emitcode ("push", "acc");
539
540               if (_G.bInUse || (accuse>1))
541                 emitcode ("push", "b");
542
543               emitcode ("mov", "a,_bp");
544               emitcode ("add", "a,#!constbyte",
545                         ((sym->stack < 0) ?
546                          ((char) (sym->stack - _G.nRegsSaved)) :
547                          ((char) sym->stack)) & 0xff);
548               emitcode ("mov", "%s,a",
549                         aop->aopu.aop_ptr->name);
550
551               if (_G.bInUse || (accuse>1))
552                 emitcode ("pop", "b");
553
554               if (_G.accInUse || accuse)
555                 emitcode ("pop", "acc");
556             }
557           else
558             emitcode ("mov", "%s,#%s",
559                       aop->aopu.aop_ptr->name,
560                       sym->rname);
561           aop->paged = space->paged;
562         }
563       else
564         aop->aopu.aop_stk = sym->stack;
565       return aop;
566     }
567
568   if (sym->onStack && options.stack10bit)
569     {
570         short stack_val = -((sym->stack < 0) ?
571                             ((short) (sym->stack - _G.nRegsSaved)) :
572                             ((short) sym->stack)) ;
573         if (useDP2 && _G.dptr1InUse) {
574             emitcode ("push","dpl1");
575             emitcode ("push","dph1");
576             emitcode ("push","dpx1");
577         } else if (_G.dptrInUse ) {
578             emitcode ("push","dpl");
579             emitcode ("push","dph");
580             emitcode ("push","dpx");
581         }
582       /* It's on the 10 bit stack, which is located in
583        * far data space.
584        */           
585         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
586             if (useDP2) {
587                 if (options.model == MODEL_FLAT24)
588                 {
589                     emitcode ("mov", "dpx1,#!constbyte",
590                               (options.stack_loc >> 16) & 0xff);
591                 }
592                 emitcode ("mov", "dph1,_bpx+1");
593                 
594                 emitcode ("mov", "dpl1,_bpx");
595                 emitcode ("mov","dps,#1");
596             } else {
597                 if (options.model == MODEL_FLAT24)
598                 {
599                     emitcode ("mov", "dpx,#!constbyte",
600                               (options.stack_loc >> 16) & 0xff);
601                 }
602                 emitcode ("mov", "dph,_bpx+1");
603                 emitcode ("mov", "dpl,_bpx");
604             }
605             stack_val = -stack_val;
606             while (stack_val--) {
607                 emitcode ("inc","dptr");
608             }
609             if (useDP2) {
610                 emitcode("mov","dps,#0");
611             }
612         }  else {
613             if (_G.accInUse || accuse)
614                 emitcode ("push", "acc");
615             
616             if (_G.bInUse || (accuse>1))
617                 emitcode ("push", "b");
618         
619             emitcode ("mov", "a,_bpx");
620             emitcode ("clr","c");
621             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
622             emitcode ("mov","b,a");
623             emitcode ("mov","a,_bpx+1");
624             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
625             if (useDP2) {
626                 if (options.model == MODEL_FLAT24)
627                 {
628                     emitcode ("mov", "dpx1,#!constbyte",
629                               (options.stack_loc >> 16) & 0xff);
630                 }
631                 emitcode ("mov", "dph1,a");
632                 emitcode ("mov", "dpl1,b");
633             } else {
634                 if (options.model == MODEL_FLAT24)
635                 {
636                     emitcode ("mov", "dpx,#!constbyte",
637                               (options.stack_loc >> 16) & 0xff);
638                 }
639                 emitcode ("mov", "dph,a");
640                 emitcode ("mov", "dpl,b");
641             }
642             
643             if (_G.bInUse || (accuse>1))
644                 emitcode ("pop", "b");
645             
646             if (_G.accInUse || accuse)
647                 emitcode ("pop", "acc");
648         }
649         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
650         aop->size = getSize (sym->type);
651         return aop;
652     }
653
654   /* if in bit space */
655   if (IN_BITSPACE (space))
656     {
657       sym->aop = aop = newAsmop (AOP_CRY);
658       aop->aopu.aop_dir = sym->rname;
659       aop->size = getSize (sym->type);
660       return aop;
661     }
662   /* if it is in direct space */
663   if (IN_DIRSPACE (space))
664     {
665       sym->aop = aop = newAsmop (AOP_DIR);
666       aop->aopu.aop_dir = sym->rname;
667       aop->size = getSize (sym->type);
668       return aop;
669     }
670
671   /* special case for a function */
672   if (IS_FUNC (sym->type) && !(sym->isitmp))
673     {
674       sym->aop = aop = newAsmop (AOP_IMMD);
675       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
676       aop->size = FPTRSIZE;
677       return aop;
678     }
679
680   /* only remaining is far space */
681   /* in which case DPTR gets the address */
682   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
683   if (useDP2)
684     {
685       genSetDPTR (1);
686       _flushLazyDPS ();
687       emitcode ("mov", "dptr,#%s", sym->rname);
688       genSetDPTR (0);
689     }
690   else
691     {
692       emitcode ("mov", "dptr,#%s", sym->rname);
693     }
694   aop->size = getSize (sym->type);
695
696   /* if it is in code space */
697   if (IN_CODESPACE (space))
698     aop->code = 1;
699
700   return aop;
701 }
702
703 /*-----------------------------------------------------------------*/
704 /* aopForRemat - rematerialzes an object                           */
705 /*-----------------------------------------------------------------*/
706 static asmop *
707 aopForRemat (symbol * sym)
708 {
709   iCode *ic = sym->rematiCode;
710   asmop *aop = newAsmop (AOP_IMMD);
711   int ptr_type =0;
712   int val = 0;
713
714   for (;;)
715     {
716       if (ic->op == '+')
717         val += (int) operandLitValue (IC_RIGHT (ic));
718       else if (ic->op == '-')
719         val -= (int) operandLitValue (IC_RIGHT (ic));
720       else if (IS_CAST_ICODE(ic)) {
721               sym_link *from_type = operandType(IC_RIGHT(ic));
722               aop->aopu.aop_immd.from_cast_remat = 1;
723               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
724               ptr_type = DCL_TYPE(from_type);
725               if (ptr_type == IPOINTER) {
726                 // bug #481053
727                 ptr_type = POINTER;
728               }
729               continue ;
730       } else break;
731       
732       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
733     }
734
735   if (val)
736   {
737       SNPRINTF (buffer, sizeof(buffer),
738                 "(%s %c 0x%04x)",
739                 OP_SYMBOL (IC_LEFT (ic))->rname,
740                 val >= 0 ? '+' : '-',
741                 abs (val) & 0xffffff);
742   }
743   else 
744   {
745       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
746       {
747           SNPRINTF(buffer, sizeof(buffer), 
748                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
749       }
750       else
751       {
752           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
753       }
754   }
755
756   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
757   /* set immd2 field if required */
758   if (aop->aopu.aop_immd.from_cast_remat) 
759   {
760       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
761       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
762   }
763
764   return aop;
765 }
766
767 /*-----------------------------------------------------------------*/
768 /* aopHasRegs - returns true if aop has regs between from-to       */
769 /*-----------------------------------------------------------------*/
770 static int aopHasRegs(asmop *aop, int from, int to)
771 {
772     int size =0;
773
774     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
775
776     for (; size < aop->size ; size++) {
777         int reg;
778         for (reg = from ; reg <= to ; reg++)
779             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
780     }
781     return 0;
782 }
783
784 /*-----------------------------------------------------------------*/
785 /* regsInCommon - two operands have some registers in common       */
786 /*-----------------------------------------------------------------*/
787 static bool
788 regsInCommon (operand * op1, operand * op2)
789 {
790   symbol *sym1, *sym2;
791   int i;
792
793   /* if they have registers in common */
794   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
795     return FALSE;
796
797   sym1 = OP_SYMBOL (op1);
798   sym2 = OP_SYMBOL (op2);
799
800   if (sym1->nRegs == 0 || sym2->nRegs == 0)
801     return FALSE;
802
803   for (i = 0; i < sym1->nRegs; i++)
804     {
805       int j;
806       if (!sym1->regs[i])
807         continue;
808
809       for (j = 0; j < sym2->nRegs; j++)
810         {
811           if (!sym2->regs[j])
812             continue;
813
814           if (sym2->regs[j] == sym1->regs[i])
815             return TRUE;
816         }
817     }
818
819   return FALSE;
820 }
821
822 /*-----------------------------------------------------------------*/
823 /* operandsEqu - equivalent                                        */
824 /*-----------------------------------------------------------------*/
825 static bool
826 operandsEqu (operand * op1, operand * op2)
827 {
828   symbol *sym1, *sym2;
829
830   /* if they not symbols */
831   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
832     return FALSE;
833
834   sym1 = OP_SYMBOL (op1);
835   sym2 = OP_SYMBOL (op2);
836
837   /* if both are itemps & one is spilt
838      and the other is not then false */
839   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
840       sym1->isspilt != sym2->isspilt)
841     return FALSE;
842
843   /* if they are the same */
844   if (sym1 == sym2)
845     return TRUE;
846
847   if (strcmp (sym1->rname, sym2->rname) == 0)
848     return TRUE;
849
850
851   /* if left is a tmp & right is not */
852   if (IS_ITEMP (op1) &&
853       !IS_ITEMP (op2) &&
854       sym1->isspilt &&
855       (sym1->usl.spillLoc == sym2))
856     return TRUE;
857
858   if (IS_ITEMP (op2) &&
859       !IS_ITEMP (op1) &&
860       sym2->isspilt &&
861       sym1->level > 0 &&
862       (sym2->usl.spillLoc == sym1))
863     return TRUE;
864
865   return FALSE;
866 }
867
868 /*-----------------------------------------------------------------*/
869 /* sameRegs - two asmops have the same registers                   */
870 /*-----------------------------------------------------------------*/
871 static bool
872 sameRegs (asmop * aop1, asmop * aop2)
873 {
874   int i;
875
876   if (aop1 == aop2)
877     {
878       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
879         {
880           return FALSE;
881         }
882       return TRUE;
883     }
884
885   if (aop1->type != AOP_REG ||
886       aop2->type != AOP_REG)
887     return FALSE;
888
889   if (aop1->size != aop2->size)
890     return FALSE;
891
892   for (i = 0; i < aop1->size; i++)
893     if (aop1->aopu.aop_reg[i] !=
894         aop2->aopu.aop_reg[i])
895       return FALSE;
896
897   return TRUE;
898 }
899
900 /*-----------------------------------------------------------------*/
901 /* aopOp - allocates an asmop for an operand  :                    */
902 /*-----------------------------------------------------------------*/
903 static void
904 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
905 {
906   asmop *aop;
907   symbol *sym;
908   int i;
909
910   if (!op)
911     return;
912
913   /* if this a literal */
914   if (IS_OP_LITERAL (op))
915     {
916       op->aop = aop = newAsmop (AOP_LIT);
917       aop->aopu.aop_lit = op->operand.valOperand;
918       aop->size = getSize (operandType (op));
919       return;
920     }
921
922   /* if already has a asmop then continue */
923   if (op->aop)
924     return;
925
926   /* if the underlying symbol has a aop */
927   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
928     {
929       op->aop = OP_SYMBOL (op)->aop;
930       return;
931     }
932
933   /* if this is a true symbol */
934   if (IS_TRUE_SYMOP (op))
935     {
936       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
937       return;
938     }
939
940   /* this is a temporary : this has
941      only four choices :
942      a) register
943      b) spillocation
944      c) rematerialize
945      d) conditional
946      e) can be a return use only */
947
948   sym = OP_SYMBOL (op);
949
950
951   /* if the type is a conditional */
952   if (sym->regType == REG_CND)
953     {
954       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
955       aop->size = 0;
956       return;
957     }
958
959   /* if it is spilt then two situations
960      a) is rematerialize
961      b) has a spill location */
962   if (sym->isspilt || sym->nRegs == 0)
963     {
964
965       /* rematerialize it NOW */
966       if (sym->remat)
967         {
968           sym->aop = op->aop = aop =
969             aopForRemat (sym);
970           aop->size = getSize (sym->type);
971           return;
972         }
973
974       if (sym->accuse)
975         {
976           int i;
977           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
978           aop->size = getSize (sym->type);
979           for (i = 0; i < 2; i++)
980             aop->aopu.aop_str[i] = accUse[i];
981           return;
982         }
983
984       if (sym->ruonly)
985         {
986           int i;
987
988           if (useDP2)
989             {
990               /* a AOP_STR uses DPTR, but DPTR is already in use;
991                * we're just hosed.
992                */
993                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
994             }
995
996           aop = op->aop = sym->aop = newAsmop (AOP_STR);
997           aop->size = getSize (sym->type);
998           for (i = 0; i < (int) fReturnSizeDS390; i++)
999             aop->aopu.aop_str[i] = fReturn[i];
1000           return;
1001         }
1002       
1003       if (sym->dptr) { /* has been allocated to a DPTRn */
1004           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1005           aop->size = getSize (sym->type);
1006           aop->aopu.dptr = sym->dptr;
1007           return ;
1008       }
1009       
1010       if (sym->usl.spillLoc)
1011         {
1012           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1013             {
1014               /* force a new aop if sizes differ */
1015               sym->usl.spillLoc->aop = NULL;
1016             }
1017           sym->aop = op->aop = aop =
1018                      aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1019           aop->size = getSize (sym->type);
1020           return;
1021         }
1022       
1023       /* else must be a dummy iTemp */
1024       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1025       aop->size = getSize (sym->type);
1026       return;
1027     }
1028
1029   /* must be in a register */
1030   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1031   aop->size = sym->nRegs;
1032   for (i = 0; i < sym->nRegs; i++)
1033     aop->aopu.aop_reg[i] = sym->regs[i];
1034 }
1035
1036 /*-----------------------------------------------------------------*/
1037 /* freeAsmop - free up the asmop given to an operand               */
1038 /*----------------------------------------------------------------*/
1039 static void
1040 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1041 {
1042   asmop *aop;
1043
1044   if (!op)
1045     aop = aaop;
1046   else
1047     aop = op->aop;
1048
1049   if (!aop)
1050     return;
1051
1052   if (aop->freed)
1053     goto dealloc;
1054
1055   aop->freed = 1;
1056
1057   /* depending on the asmop type only three cases need work AOP_RO
1058      , AOP_R1 && AOP_STK */
1059   switch (aop->type)
1060     {
1061     case AOP_R0:
1062       if (_G.r0Pushed)
1063         {
1064           if (pop)
1065             {
1066               emitcode ("pop", "ar0");
1067               _G.r0Pushed--;
1068             }
1069         }
1070       bitVectUnSetBit (ic->rUsed, R0_IDX);
1071       break;
1072
1073     case AOP_R1:
1074       if (_G.r1Pushed)
1075         {
1076           if (pop)
1077             {
1078               emitcode ("pop", "ar1");
1079               _G.r1Pushed--;
1080             }
1081         }
1082       bitVectUnSetBit (ic->rUsed, R1_IDX);
1083       break;
1084
1085     case AOP_STK:
1086       {
1087         int sz = aop->size;
1088         int stk = aop->aopu.aop_stk + aop->size;
1089         bitVectUnSetBit (ic->rUsed, R0_IDX);
1090         bitVectUnSetBit (ic->rUsed, R1_IDX);
1091
1092         getFreePtr (ic, &aop, FALSE);
1093
1094         if (options.stack10bit)
1095           {
1096             /* I'm not sure what to do here yet... */
1097             /* #STUB */
1098             fprintf (stderr,
1099                      "*** Warning: probably generating bad code for "
1100                      "10 bit stack mode.\n");
1101           }
1102
1103         if (stk)
1104           {
1105             emitcode ("mov", "a,_bp");
1106             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1107             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1108           }
1109         else
1110           {
1111             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1112           }
1113
1114         while (sz--)
1115           {
1116             emitcode ("pop", "acc");
1117             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1118             if (!sz)
1119               break;
1120             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1121           }
1122         op->aop = aop;
1123         freeAsmop (op, NULL, ic, TRUE);
1124         if (_G.r0Pushed)
1125           {
1126             emitcode ("pop", "ar0");
1127             _G.r0Pushed--;
1128           }
1129
1130         if (_G.r1Pushed)
1131           {
1132             emitcode ("pop", "ar1");
1133             _G.r1Pushed--;
1134           }
1135       }
1136     case AOP_DPTR2:
1137         if (_G.dptr1InUse) {
1138             emitcode ("pop","dpx1");
1139             emitcode ("pop","dph1");
1140             emitcode ("pop","dpl1");
1141         }
1142         break;
1143     case AOP_DPTR:
1144         if (_G.dptrInUse) {
1145             emitcode ("pop","dpx");
1146             emitcode ("pop","dph");
1147             emitcode ("pop","dpl");
1148         }
1149         break;
1150     }
1151 dealloc:
1152   /* all other cases just dealloc */
1153   if (op)
1154     {
1155       op->aop = NULL;
1156       if (IS_SYMOP (op))
1157         {
1158           OP_SYMBOL (op)->aop = NULL;
1159           /* if the symbol has a spill */
1160           if (SPIL_LOC (op))
1161             SPIL_LOC (op)->aop = NULL;
1162         }
1163     }
1164 }
1165
1166 #define DEFAULT_ACC_WARNING 0
1167 static int saveAccWarn = DEFAULT_ACC_WARNING;
1168
1169 /*-------------------------------------------------------------------*/
1170 /* aopGet - for fetching value of the aop                            */
1171 /*                                                                   */
1172 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1173 /* in the accumulator. Set it to the name of a free register         */
1174 /* if acc must be preserved; the register will be used to preserve   */
1175 /* acc temporarily and to return the result byte.                    */
1176 /*-------------------------------------------------------------------*/
1177
1178 static char *
1179 aopGet (asmop *aop,
1180         int   offset,
1181         bool  bit16,
1182         bool  dname,
1183         char  *saveAcc)
1184 {
1185   /* offset is greater than
1186      size then zero */
1187   if (offset > (aop->size - 1) &&
1188       aop->type != AOP_LIT)
1189     return zero;
1190
1191   /* depending on type */
1192   switch (aop->type)
1193     {
1194     case AOP_DUMMY:
1195       return zero;
1196
1197     case AOP_R0:
1198     case AOP_R1:
1199       /* if we need to increment it */
1200       while (offset > aop->coff)
1201         {
1202           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1203           aop->coff++;
1204         }
1205
1206       while (offset < aop->coff)
1207         {
1208           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1209           aop->coff--;
1210         }
1211
1212       aop->coff = offset;
1213       if (aop->paged)
1214         {
1215           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1216           return (dname ? "acc" : "a");
1217         }
1218       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1219       return Safe_strdup(buffer);       
1220
1221     case AOP_DPTRn:
1222         assert(offset <= 3);
1223         return dptrn[aop->aopu.dptr][offset];
1224
1225     case AOP_DPTR:
1226     case AOP_DPTR2:
1227
1228       if (aop->type == AOP_DPTR2)
1229         {
1230           genSetDPTR (1);
1231         }
1232         
1233       if (saveAcc)
1234         {
1235             TR_AP("#1");
1236 //          if (aop->type != AOP_DPTR2)
1237 //          {
1238 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1239 //              emitcode(";", "spanky: saveAcc for DPTR");
1240 //          }
1241             
1242             emitcode ("xch", "a, %s", saveAcc);
1243         }
1244
1245       _flushLazyDPS ();
1246
1247       while (offset > aop->coff)
1248         {
1249           emitcode ("inc", "dptr");
1250           aop->coff++;
1251         }
1252
1253       while (offset < aop->coff)
1254         {
1255           emitcode ("lcall", "__decdptr");
1256           aop->coff--;
1257         }
1258
1259       aop->coff = offset;
1260       if (aop->code)
1261         {
1262           emitcode ("clr", "a");
1263           emitcode ("movc", "a,@a+dptr");
1264         }
1265       else
1266         {
1267           emitcode ("movx", "a,@dptr");
1268         }
1269
1270       if (aop->type == AOP_DPTR2)
1271         {
1272           genSetDPTR (0);
1273         }
1274         
1275         if (saveAcc)
1276         {
1277        TR_AP("#2");
1278               emitcode ("xch", "a, %s", saveAcc);
1279 //            if (strcmp(saveAcc, "_ap"))
1280 //            {
1281 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1282 //            }
1283                   
1284               return saveAcc;
1285         }
1286       return (dname ? "acc" : "a");
1287
1288     case AOP_IMMD:
1289       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1290       {
1291           SNPRINTF(buffer, sizeof(buffer), 
1292                    "%s",aop->aopu.aop_immd.aop_immd2);
1293       } 
1294       else if (bit16)
1295       {
1296          SNPRINTF(buffer, sizeof(buffer), 
1297                   "#%s", aop->aopu.aop_immd.aop_immd1);
1298       }
1299       else if (offset) 
1300       {
1301           switch (offset) {
1302           case 1:
1303               tsprintf(buffer, sizeof(buffer),
1304                        "#!his",aop->aopu.aop_immd.aop_immd1);
1305               break;
1306           case 2:
1307               tsprintf(buffer, sizeof(buffer), 
1308                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1309               break;
1310           case 3:
1311               tsprintf(buffer, sizeof(buffer),
1312                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1313               break;
1314           default: /* should not need this (just in case) */
1315               SNPRINTF (buffer, sizeof(buffer), 
1316                         "#(%s >> %d)",
1317                        aop->aopu.aop_immd.aop_immd1,
1318                        offset * 8);
1319           }
1320       }
1321       else
1322       {
1323         SNPRINTF (buffer, sizeof(buffer), 
1324                   "#%s", aop->aopu.aop_immd.aop_immd1);
1325       }
1326       return Safe_strdup(buffer);       
1327
1328     case AOP_DIR:
1329       if (offset)
1330       {
1331         SNPRINTF (buffer, sizeof(buffer),
1332                   "(%s + %d)",
1333                  aop->aopu.aop_dir,
1334                  offset);
1335       }
1336       else
1337       {
1338         SNPRINTF(buffer, sizeof(buffer), 
1339                  "%s", aop->aopu.aop_dir);
1340       }
1341
1342       return Safe_strdup(buffer);
1343
1344     case AOP_REG:
1345       if (dname)
1346         return aop->aopu.aop_reg[offset]->dname;
1347       else
1348         return aop->aopu.aop_reg[offset]->name;
1349
1350     case AOP_CRY:
1351       emitcode ("clr", "a");
1352       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1353       emitcode ("rlc", "a");
1354       return (dname ? "acc" : "a");
1355
1356     case AOP_ACC:
1357       if (!offset && dname)
1358         return "acc";
1359       return aop->aopu.aop_str[offset];
1360
1361     case AOP_LIT:
1362       return aopLiteral (aop->aopu.aop_lit, offset);
1363
1364     case AOP_STR:
1365       aop->coff = offset;
1366       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1367           dname)
1368         return "acc";
1369
1370       return aop->aopu.aop_str[offset];
1371
1372     }
1373
1374   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1375           "aopget got unsupported aop->type");
1376   exit (1);
1377     
1378   return NULL;  // not reached, but makes compiler happy.
1379 }
1380 /*-----------------------------------------------------------------*/
1381 /* aopPut - puts a string for a aop                                */
1382 /*-----------------------------------------------------------------*/
1383 static void
1384 aopPut (asmop * aop, char *s, int offset)
1385 {
1386   if (aop->size && offset > (aop->size - 1))
1387     {
1388       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1389               "aopPut got offset > aop->size");
1390       exit (1);
1391     }
1392
1393   /* will assign value to value */
1394   /* depending on where it is ofcourse */
1395   switch (aop->type)
1396     {
1397     case AOP_DUMMY:
1398       MOVA (s);         /* read s in case it was volatile */
1399       break;
1400       
1401     case AOP_DIR:
1402         if (offset)
1403         {
1404             SNPRINTF (buffer, sizeof(buffer),
1405                       "(%s + %d)",
1406                       aop->aopu.aop_dir, offset);
1407         }
1408         else
1409         {
1410             SNPRINTF (buffer, sizeof(buffer), 
1411                      "%s", aop->aopu.aop_dir);
1412         }
1413         
1414
1415         if (strcmp (buffer, s))
1416         {
1417             emitcode ("mov", "%s,%s", buffer, s);
1418         }
1419       break;
1420
1421     case AOP_REG:
1422       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1423           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1424         {
1425           if (*s == '@' ||
1426               strcmp (s, "r0") == 0 ||
1427               strcmp (s, "r1") == 0 ||
1428               strcmp (s, "r2") == 0 ||
1429               strcmp (s, "r3") == 0 ||
1430               strcmp (s, "r4") == 0 ||
1431               strcmp (s, "r5") == 0 ||
1432               strcmp (s, "r6") == 0 ||
1433               strcmp (s, "r7") == 0)
1434             {
1435                 emitcode ("mov", "%s,%s",
1436                           aop->aopu.aop_reg[offset]->dname, s);
1437             }
1438             else
1439             {
1440                 emitcode ("mov", "%s,%s",
1441                           aop->aopu.aop_reg[offset]->name, s);
1442             }
1443         }
1444       break;
1445
1446     case AOP_DPTRn:
1447         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1448         break;
1449
1450     case AOP_DPTR:
1451     case AOP_DPTR2:
1452
1453       if (aop->type == AOP_DPTR2)
1454         {
1455           genSetDPTR (1);
1456         }
1457       _flushLazyDPS ();
1458
1459       if (aop->code)
1460         {
1461           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1462                   "aopPut writting to code space");
1463           exit (1);
1464         }
1465
1466       while (offset > aop->coff)
1467         {
1468           aop->coff++;
1469           emitcode ("inc", "dptr");
1470         }
1471
1472       while (offset < aop->coff)
1473         {
1474           aop->coff--;
1475           emitcode ("lcall", "__decdptr");
1476         }
1477
1478       aop->coff = offset;
1479
1480       /* if not in accumulater */
1481       MOVA (s);
1482
1483       emitcode ("movx", "@dptr,a");
1484
1485       if (aop->type == AOP_DPTR2)
1486         {
1487           genSetDPTR (0);
1488         }
1489       break;
1490
1491     case AOP_R0:
1492     case AOP_R1:
1493       while (offset > aop->coff)
1494         {
1495           aop->coff++;
1496           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1497         }
1498       while (offset < aop->coff)
1499         {
1500           aop->coff--;
1501           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1502         }
1503       aop->coff = offset;
1504
1505       if (aop->paged)
1506         {
1507           MOVA (s);
1508           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1509
1510         }
1511       else if (*s == '@')
1512         {
1513           MOVA (s);
1514           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1515         }
1516       else if (strcmp (s, "r0") == 0 ||
1517                strcmp (s, "r1") == 0 ||
1518                strcmp (s, "r2") == 0 ||
1519                strcmp (s, "r3") == 0 ||
1520                strcmp (s, "r4") == 0 ||
1521                strcmp (s, "r5") == 0 ||
1522                strcmp (s, "r6") == 0 ||
1523                strcmp (s, "r7") == 0)
1524         {
1525           char buff[10];
1526           SNPRINTF(buff, sizeof(buff), 
1527                    "a%s", s);
1528           emitcode ("mov", "@%s,%s",
1529                     aop->aopu.aop_ptr->name, buff);
1530         }
1531         else
1532         {
1533             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1534         }
1535       break;
1536
1537     case AOP_STK:
1538       if (strcmp (s, "a") == 0)
1539         emitcode ("push", "acc");
1540       else
1541         if (*s=='@') {
1542           MOVA(s);
1543           emitcode ("push", "acc");
1544         } else {
1545           emitcode ("push", s);
1546         }
1547
1548       break;
1549
1550     case AOP_CRY:
1551       /* if bit variable */
1552       if (!aop->aopu.aop_dir)
1553         {
1554           emitcode ("clr", "a");
1555           emitcode ("rlc", "a");
1556         }
1557       else
1558         {
1559           if (s == zero)
1560             emitcode ("clr", "%s", aop->aopu.aop_dir);
1561           else if (s == one)
1562             emitcode ("setb", "%s", aop->aopu.aop_dir);
1563           else if (!strcmp (s, "c"))
1564             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1565           else
1566             {
1567               if (strcmp (s, "a"))
1568                 {
1569                   MOVA (s);
1570                 }
1571               {
1572                 /* set C, if a >= 1 */
1573                 emitcode ("add", "a,#!constbyte",0xff);
1574                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1575               }
1576             }
1577         }
1578       break;
1579
1580     case AOP_STR:
1581       aop->coff = offset;
1582       if (strcmp (aop->aopu.aop_str[offset], s))
1583         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1584       break;
1585
1586     case AOP_ACC:
1587       aop->coff = offset;
1588       if (!offset && (strcmp (s, "acc") == 0))
1589         break;
1590
1591       if (strcmp (aop->aopu.aop_str[offset], s))
1592         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1593       break;
1594
1595     default:
1596       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1597               "aopPut got unsupported aop->type");
1598       exit (1);
1599     }
1600
1601 }
1602
1603
1604 /*--------------------------------------------------------------------*/
1605 /* reAdjustPreg - points a register back to where it should (coff==0) */
1606 /*--------------------------------------------------------------------*/
1607 static void
1608 reAdjustPreg (asmop * aop)
1609 {
1610   if ((aop->coff==0) || (aop->size <= 1)) {
1611     return;
1612   }
1613
1614   switch (aop->type)
1615     {
1616     case AOP_R0:
1617     case AOP_R1:
1618       while (aop->coff--)
1619         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1620       break;
1621     case AOP_DPTR:
1622     case AOP_DPTR2:
1623       if (aop->type == AOP_DPTR2)
1624         {
1625           genSetDPTR (1);
1626           _flushLazyDPS ();
1627         }
1628       while (aop->coff--)
1629         {
1630           emitcode ("lcall", "__decdptr");
1631         }
1632
1633       if (aop->type == AOP_DPTR2)
1634         {
1635           genSetDPTR (0);
1636         }
1637       break;
1638
1639     }
1640   aop->coff=0;
1641 }
1642
1643 #define AOP(op) op->aop
1644 #define AOP_TYPE(op) AOP(op)->type
1645 #define AOP_SIZE(op) AOP(op)->size
1646 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1647                        AOP_TYPE(x) == AOP_R0))
1648
1649 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1650                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1651                          AOP(x)->paged))
1652
1653 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1654                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1655                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1656 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1657 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1658 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1659
1660 // The following two macros can be used even if the aop has not yet been aopOp'd.
1661 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1662 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1663
1664 /* Workaround for DS80C390 bug: div ab may return bogus results
1665  * if A is accessed in instruction immediately before the div.
1666  *
1667  * Will be fixed in B4 rev of processor, Dallas claims.
1668  */
1669
1670 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1671     if (!AOP_NEEDSACC(RIGHT))         \
1672     {               \
1673       /* We can load A first, then B, since     \
1674        * B (the RIGHT operand) won't clobber A,   \
1675        * thus avoiding touching A right before the div. \
1676        */             \
1677       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1678       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1679       MOVA(L);            \
1680       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1681       MOVB(L); \
1682     }               \
1683     else              \
1684     {               \
1685       /* Just stuff in a nop after loading A. */    \
1686       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1687       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1688       MOVA(L);            \
1689       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1690     }
1691
1692
1693 /*-----------------------------------------------------------------*/
1694 /* opIsGptr: returns non-zero if the passed operand is       */
1695 /* a generic pointer type.             */
1696 /*-----------------------------------------------------------------*/
1697 static int
1698 opIsGptr (operand * op)
1699 {
1700   sym_link *type = operandType (op);
1701
1702   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1703     {
1704       return 1;
1705     }
1706   return 0;
1707 }
1708
1709 /*-----------------------------------------------------------------*/
1710 /* getDataSize - get the operand data size                         */
1711 /*-----------------------------------------------------------------*/
1712 static int
1713 getDataSize (operand * op)
1714 {
1715   int size;
1716   size = AOP_SIZE (op);
1717   if (size == GPTRSIZE)
1718     {
1719       sym_link *type = operandType (op);
1720       if (IS_GENPTR (type))
1721         {
1722           /* generic pointer; arithmetic operations
1723            * should ignore the high byte (pointer type).
1724            */
1725           size--;
1726         }
1727     }
1728   return size;
1729 }
1730
1731 /*-----------------------------------------------------------------*/
1732 /* outAcc - output Acc                                             */
1733 /*-----------------------------------------------------------------*/
1734 static void
1735 outAcc (operand * result)
1736 {
1737   int size, offset;
1738   size = getDataSize (result);
1739   if (size)
1740     {
1741       aopPut (AOP (result), "a", 0);
1742       size--;
1743       offset = 1;
1744       /* unsigned or positive */
1745       while (size--)
1746         {
1747           aopPut (AOP (result), zero, offset++);
1748         }
1749     }
1750 }
1751
1752 /*-----------------------------------------------------------------*/
1753 /* outBitC - output a bit C                                        */
1754 /*-----------------------------------------------------------------*/
1755 static void
1756 outBitC (operand * result)
1757 {
1758   /* if the result is bit */
1759   if (AOP_TYPE (result) == AOP_CRY)
1760     {
1761       aopPut (AOP (result), "c", 0);
1762     }
1763   else
1764     {
1765       emitcode ("clr", "a");
1766       emitcode ("rlc", "a");
1767       outAcc (result);
1768     }
1769 }
1770
1771 /*-----------------------------------------------------------------*/
1772 /* toBoolean - emit code for orl a,operator(sizeop)                */
1773 /*-----------------------------------------------------------------*/
1774 static void
1775 toBoolean (operand * oper)
1776 {
1777   int   size = AOP_SIZE (oper) - 1;
1778   int   offset = 1;
1779   bool usedB = FALSE;
1780
1781   /* The generic part of a generic pointer should
1782    * not participate in it's truth value.
1783    *
1784    * i.e. 0x10000000 is zero.
1785    */
1786   if (opIsGptr (oper))
1787     {
1788       D (emitcode (";", "toBoolean: generic ptr special case."););
1789       size--;
1790     }
1791
1792   _startLazyDPSEvaluation ();
1793   if (AOP_NEEDSACC (oper) && size)
1794     {
1795       usedB = TRUE;
1796       if (_G.bInUse)
1797       {
1798           emitcode ("push", "b");
1799       }
1800       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1801     }
1802   else
1803     {
1804       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1805     }
1806     
1807   while (size--)
1808     {
1809       if (usedB)
1810         {
1811           emitcode ("orl", "b,%s",
1812                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1813         }
1814       else
1815         {
1816           emitcode ("orl", "a,%s",
1817                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1818         }
1819     }
1820   _endLazyDPSEvaluation ();
1821
1822   if (usedB)
1823     {
1824       emitcode ("mov", "a,b");
1825       if (_G.bInUse)
1826       {
1827           emitcode ("pop", "b");
1828       }
1829         
1830     }
1831 }
1832
1833
1834 /*-----------------------------------------------------------------*/
1835 /* genNot - generate code for ! operation                          */
1836 /*-----------------------------------------------------------------*/
1837 static void
1838 genNot (iCode * ic)
1839 {
1840   symbol *tlbl;
1841
1842   D (emitcode (";", "genNot "););
1843
1844   /* assign asmOps to operand & result */
1845   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1846   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1847
1848   /* if in bit space then a special case */
1849   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1850     {
1851       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1852       emitcode ("cpl", "c");
1853       outBitC (IC_RESULT (ic));
1854       goto release;
1855     }
1856
1857   toBoolean (IC_LEFT (ic));
1858
1859   tlbl = newiTempLabel (NULL);
1860   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1861   emitcode ("", "!tlabeldef", tlbl->key + 100);
1862   outBitC (IC_RESULT (ic));
1863
1864 release:
1865   /* release the aops */
1866   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1867   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1868 }
1869
1870
1871 /*-----------------------------------------------------------------*/
1872 /* genCpl - generate code for complement                           */
1873 /*-----------------------------------------------------------------*/
1874 static void
1875 genCpl (iCode * ic)
1876 {
1877   int offset = 0;
1878   int size;
1879   symbol *tlbl;
1880
1881   D (emitcode (";", "genCpl "););
1882
1883
1884   /* assign asmOps to operand & result */
1885   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1886   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1887
1888   /* special case if in bit space */
1889   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1890     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1891       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1892       emitcode ("cpl", "c");
1893       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1894       goto release;
1895     }
1896     tlbl=newiTempLabel(NULL);
1897     emitcode ("cjne", "%s,#0x01,%05d$", 
1898               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1899     emitcode ("", "%05d$:", tlbl->key+100);
1900     outBitC (IC_RESULT(ic));
1901     goto release;
1902   }
1903
1904   size = AOP_SIZE (IC_RESULT (ic));
1905   _startLazyDPSEvaluation ();
1906   while (size--)
1907     {
1908       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1909       emitcode ("cpl", "a");
1910       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1911     }
1912   _endLazyDPSEvaluation ();
1913
1914
1915 release:
1916   /* release the aops */
1917   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1918   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1919 }
1920
1921 /*-----------------------------------------------------------------*/
1922 /* genUminusFloat - unary minus for floating points                */
1923 /*-----------------------------------------------------------------*/
1924 static void
1925 genUminusFloat (operand * op, operand * result)
1926 {
1927   int size, offset = 0;
1928     
1929   D(emitcode (";", "genUminusFloat"););
1930   
1931   /* for this we just copy and then flip the bit */
1932     
1933   _startLazyDPSEvaluation ();
1934   size = AOP_SIZE (op) - 1;
1935
1936   while (size--)
1937   {
1938       aopPut (AOP (result),
1939               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1940               offset);
1941       offset++;
1942     }
1943   
1944   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1945
1946   emitcode ("cpl", "acc.7");
1947   aopPut (AOP (result), "a", offset);    
1948   _endLazyDPSEvaluation ();
1949 }
1950
1951 /*-----------------------------------------------------------------*/
1952 /* genUminus - unary minus code generation                         */
1953 /*-----------------------------------------------------------------*/
1954 static void
1955 genUminus (iCode * ic)
1956 {
1957   int offset, size;
1958   sym_link *optype;
1959
1960   D (emitcode (";", "genUminus "););
1961
1962   /* assign asmops */
1963   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1964   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1965
1966   /* if both in bit space then special
1967      case */
1968   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1969       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1970     {
1971
1972       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1973       emitcode ("cpl", "c");
1974       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1975       goto release;
1976     }
1977
1978   optype = operandType (IC_LEFT (ic));
1979
1980   /* if float then do float stuff */
1981   if (IS_FLOAT (optype))
1982     {
1983       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1984       goto release;
1985     }
1986
1987   /* otherwise subtract from zero */
1988   size = AOP_SIZE (IC_LEFT (ic));
1989   offset = 0;
1990   _startLazyDPSEvaluation ();
1991   while (size--)
1992     {
1993       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1994       if (!strcmp (l, "a"))
1995         {
1996           if (offset == 0)
1997             SETC;
1998           emitcode ("cpl", "a");
1999           emitcode ("addc", "a,#0");
2000         }
2001       else
2002         {
2003           if (offset == 0)
2004             CLRC;
2005           emitcode ("clr", "a");
2006           emitcode ("subb", "a,%s", l);
2007         }
2008       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2009     }
2010   _endLazyDPSEvaluation ();
2011
2012   /* if any remaining bytes in the result */
2013   /* we just need to propagate the sign   */
2014   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2015     {
2016       emitcode ("rlc", "a");
2017       emitcode ("subb", "a,acc");
2018       while (size--)
2019         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2020     }
2021
2022 release:
2023   /* release the aops */
2024   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2025   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2026 }
2027
2028 /*-----------------------------------------------------------------*/
2029 /* savermask - saves registers in the mask                         */
2030 /*-----------------------------------------------------------------*/
2031 static void savermask(bitVect *rs_mask)
2032 {
2033     int i;
2034     if (options.useXstack) {
2035         if (bitVectBitValue (rs_mask, R0_IDX))
2036             emitcode ("mov", "b,r0");
2037         emitcode ("mov", "r0,%s", spname);
2038         for (i = 0; i < ds390_nRegs; i++) {
2039             if (bitVectBitValue (rs_mask, i)) {
2040                 if (i == R0_IDX)
2041                     emitcode ("mov", "a,b");
2042                 else
2043                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2044                 emitcode ("movx", "@r0,a");
2045                 emitcode ("inc", "r0");
2046             }
2047         }
2048         emitcode ("mov", "%s,r0", spname);
2049         if (bitVectBitValue (rs_mask, R0_IDX))
2050             emitcode ("mov", "r0,b");
2051     } else {
2052         for (i = 0; i < ds390_nRegs; i++) {
2053             if (bitVectBitValue (rs_mask, i))
2054                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2055         }
2056     }
2057 }
2058
2059 /*-----------------------------------------------------------------*/
2060 /* saveRegisters - will look for a call and save the registers     */
2061 /*-----------------------------------------------------------------*/
2062 static void
2063 saveRegisters (iCode * lic)
2064 {
2065   iCode *ic;
2066   bitVect *rsave;
2067
2068   /* look for call */
2069   for (ic = lic; ic; ic = ic->next)
2070     if (ic->op == CALL || ic->op == PCALL)
2071       break;
2072
2073   if (!ic)
2074     {
2075       fprintf (stderr, "found parameter push with no function call\n");
2076       return;
2077     }
2078
2079   /* if the registers have been saved already then
2080      do nothing */
2081   if (ic->regsSaved 
2082       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2083     return ;
2084
2085   /* special case if DPTR alive across a function call then must save it 
2086      even though callee saves */
2087   if (IS_SYMOP(IC_LEFT(ic)) &&
2088       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2089       int i;
2090       rsave = newBitVect(ic->rMask->size);
2091       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2092           if (bitVectBitValue(ic->rMask,i))
2093               rsave = bitVectSetBit(rsave,i);
2094       }
2095       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2096   } else {
2097     /* safe the registers in use at this time but skip the
2098        ones for the result */
2099     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2100                            ds390_rUmaskForOp (IC_RESULT(ic)));
2101   }
2102   ic->regsSaved = 1;
2103   savermask(rsave);
2104 }
2105
2106 /*-----------------------------------------------------------------*/
2107 /* usavermask - restore registers with mask                        */
2108 /*-----------------------------------------------------------------*/
2109 static void unsavermask(bitVect *rs_mask)
2110 {
2111     int i;
2112     if (options.useXstack) {
2113         emitcode ("mov", "r0,%s", spname);
2114         for (i = ds390_nRegs; i >= 0; i--) {
2115             if (bitVectBitValue (rs_mask, i)) {
2116                 emitcode ("dec", "r0");
2117                 emitcode ("movx", "a,@r0");
2118                 if (i == R0_IDX)
2119                     emitcode ("mov", "b,a");
2120                 else
2121                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2122             }       
2123         }
2124         emitcode ("mov", "%s,r0", spname);
2125         if (bitVectBitValue (rs_mask, R0_IDX))
2126             emitcode ("mov", "r0,b");
2127     } else {
2128         for (i = ds390_nRegs; i >= 0; i--) {
2129             if (bitVectBitValue (rs_mask, i))
2130                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2131         }
2132     }
2133 }
2134
2135 /*-----------------------------------------------------------------*/
2136 /* unsaveRegisters - pop the pushed registers                      */
2137 /*-----------------------------------------------------------------*/
2138 static void
2139 unsaveRegisters (iCode * ic)
2140 {
2141   bitVect *rsave;
2142
2143   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2144       int i;
2145       rsave = newBitVect(ic->rMask->size);
2146       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2147           if (bitVectBitValue(ic->rMask,i))
2148               rsave = bitVectSetBit(rsave,i);
2149       }
2150       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2151   } else {
2152     /* restore the registers in use at this time but skip the
2153        ones for the result */
2154     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2155                            ds390_rUmaskForOp (IC_RESULT(ic)));
2156   }
2157   unsavermask(rsave);
2158 }
2159
2160
2161 /*-----------------------------------------------------------------*/
2162 /* pushSide -                */
2163 /*-----------------------------------------------------------------*/
2164 static void
2165 pushSide (operand * oper, int size)
2166 {
2167   int offset = 0;
2168   _startLazyDPSEvaluation ();
2169   while (size--)
2170     {
2171       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2172       if (AOP_TYPE (oper) != AOP_REG &&
2173           AOP_TYPE (oper) != AOP_DIR &&
2174           strcmp (l, "a"))
2175         {
2176           emitcode ("mov", "a,%s", l);
2177           emitcode ("push", "acc");
2178         }
2179       else
2180         emitcode ("push", "%s", l);
2181     }
2182   _endLazyDPSEvaluation ();
2183 }
2184
2185 /*-----------------------------------------------------------------*/
2186 /* assignResultValue -               */
2187 /*-----------------------------------------------------------------*/
2188 static void
2189 assignResultValue (operand * oper)
2190 {
2191   int offset = 0;
2192   int size = AOP_SIZE (oper);
2193   bool pushedAcc = FALSE;
2194
2195   if (size == fReturnSizeDS390)
2196   {
2197       /* I don't think this case can ever happen... */
2198       /* ACC is the last part of this. If writing the result
2199        * uses AC, we must preserve it.
2200        */
2201       if (AOP_NEEDSACC(oper))
2202       {
2203           emitcode(";", "assignResultValue special case for ACC.");
2204           emitcode("push", "acc");
2205           pushedAcc = TRUE;
2206           size--;
2207       }
2208   }
2209     
2210     
2211   _startLazyDPSEvaluation ();
2212   while (size--)
2213     {
2214       aopPut (AOP (oper), fReturn[offset], offset);
2215       offset++;
2216     }
2217   _endLazyDPSEvaluation ();
2218     
2219   if (pushedAcc)
2220     {
2221         emitcode("pop", "acc");
2222         aopPut(AOP(oper), "a", offset);
2223     }
2224 }
2225
2226
2227 /*-----------------------------------------------------------------*/
2228 /* genXpush - pushes onto the external stack                       */
2229 /*-----------------------------------------------------------------*/
2230 static void
2231 genXpush (iCode * ic)
2232 {
2233   asmop *aop = newAsmop (0);
2234   regs *r;
2235   int size, offset = 0;
2236
2237   D (emitcode (";", "genXpush ");
2238     );
2239
2240   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2241   r = getFreePtr (ic, &aop, FALSE);
2242
2243
2244   emitcode ("mov", "%s,_spx", r->name);
2245
2246   size = AOP_SIZE (IC_LEFT (ic));
2247   _startLazyDPSEvaluation ();
2248   while (size--)
2249     {
2250
2251       MOVA (aopGet (AOP (IC_LEFT (ic)),
2252                         offset++, FALSE, FALSE, NULL));
2253       emitcode ("movx", "@%s,a", r->name);
2254       emitcode ("inc", "%s", r->name);
2255
2256     }
2257   _endLazyDPSEvaluation ();
2258
2259
2260   emitcode ("mov", "_spx,%s", r->name);
2261
2262   freeAsmop (NULL, aop, ic, TRUE);
2263   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2264 }
2265
2266 /*-----------------------------------------------------------------*/
2267 /* genIpush - generate code for pushing this gets a little complex  */
2268 /*-----------------------------------------------------------------*/
2269 static void
2270 genIpush (iCode * ic)
2271 {
2272   int size, offset = 0;
2273   char *l;
2274
2275   D (emitcode (";", "genIpush ");
2276     );
2277
2278   /* if this is not a parm push : ie. it is spill push
2279      and spill push is always done on the local stack */
2280   if (!ic->parmPush)
2281     {
2282
2283       /* and the item is spilt then do nothing */
2284       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2285         return;
2286
2287       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2288       size = AOP_SIZE (IC_LEFT (ic));
2289       /* push it on the stack */
2290       _startLazyDPSEvaluation ();
2291       while (size--)
2292         {
2293           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2294           if (*l == '#')
2295             {
2296               MOVA (l);
2297               l = "acc";
2298             }
2299           emitcode ("push", "%s", l);
2300         }
2301       _endLazyDPSEvaluation ();
2302       return;
2303     }
2304
2305   /* this is a paramter push: in this case we call
2306      the routine to find the call and save those
2307      registers that need to be saved */
2308   saveRegisters (ic);
2309
2310   /* if use external stack then call the external
2311      stack pushing routine */
2312   if (options.useXstack)
2313     {
2314       genXpush (ic);
2315       return;
2316     }
2317
2318   /* then do the push */
2319   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2320
2321   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2322   size = AOP_SIZE (IC_LEFT (ic));
2323
2324   _startLazyDPSEvaluation ();
2325   while (size--)
2326     {
2327       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2328       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2329           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2330           strcmp (l, "acc"))
2331         {
2332           emitcode ("mov", "a,%s", l);
2333           emitcode ("push", "acc");
2334         }
2335       else
2336         {
2337             emitcode ("push", "%s", l);
2338         }
2339     }
2340   _endLazyDPSEvaluation ();
2341
2342   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2343 }
2344
2345 /*-----------------------------------------------------------------*/
2346 /* genIpop - recover the registers: can happen only for spilling   */
2347 /*-----------------------------------------------------------------*/
2348 static void
2349 genIpop (iCode * ic)
2350 {
2351   int size, offset;
2352
2353   D (emitcode (";", "genIpop ");
2354     );
2355
2356
2357   /* if the temp was not pushed then */
2358   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2359     return;
2360
2361   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2362   size = AOP_SIZE (IC_LEFT (ic));
2363   offset = (size - 1);
2364   _startLazyDPSEvaluation ();
2365   while (size--)
2366     {
2367       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2368                                      FALSE, TRUE, NULL));
2369     }
2370   _endLazyDPSEvaluation ();
2371
2372   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2373 }
2374
2375 /*-----------------------------------------------------------------*/
2376 /* unsaveRBank - restores the resgister bank from stack            */
2377 /*-----------------------------------------------------------------*/
2378 static void
2379 unsaveRBank (int bank, iCode * ic, bool popPsw)
2380 {
2381   int i;
2382   asmop *aop = NULL;
2383   regs *r = NULL;
2384
2385   if (options.useXstack)
2386   {
2387       if (!ic)
2388       {
2389           /* Assume r0 is available for use. */
2390           r = ds390_regWithIdx (R0_IDX);;          
2391       } 
2392       else
2393       {
2394           aop = newAsmop (0);
2395           r = getFreePtr (ic, &aop, FALSE);
2396       }
2397       emitcode ("mov", "%s,_spx", r->name);      
2398   }
2399   
2400   if (popPsw)
2401     {
2402       if (options.useXstack)
2403       {
2404           emitcode ("movx", "a,@%s", r->name);
2405           emitcode ("mov", "psw,a");
2406           emitcode ("dec", "%s", r->name);
2407         }
2408       else
2409       {
2410         emitcode ("pop", "psw");
2411       }
2412     }
2413
2414   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2415     {
2416       if (options.useXstack)
2417         {
2418           emitcode ("movx", "a,@%s", r->name);
2419           emitcode ("mov", "(%s+%d),a",
2420                     regs390[i].base, 8 * bank + regs390[i].offset);
2421           emitcode ("dec", "%s", r->name);
2422
2423         }
2424       else
2425         emitcode ("pop", "(%s+%d)",
2426                   regs390[i].base, 8 * bank + regs390[i].offset);
2427     }
2428
2429   if (options.useXstack)
2430     {
2431       emitcode ("mov", "_spx,%s", r->name);
2432     }
2433     
2434   if (aop)
2435   {
2436       freeAsmop (NULL, aop, ic, TRUE);  
2437   }    
2438 }
2439
2440 /*-----------------------------------------------------------------*/
2441 /* saveRBank - saves an entire register bank on the stack          */
2442 /*-----------------------------------------------------------------*/
2443 static void
2444 saveRBank (int bank, iCode * ic, bool pushPsw)
2445 {
2446   int i;
2447   asmop *aop = NULL;
2448   regs *r = NULL;
2449
2450   if (options.useXstack)
2451     {
2452         if (!ic)
2453         {
2454           /* Assume r0 is available for use. */
2455                   r = ds390_regWithIdx (R0_IDX);;
2456         }
2457         else
2458         {
2459           aop = newAsmop (0);
2460           r = getFreePtr (ic, &aop, FALSE);
2461         }
2462         emitcode ("mov", "%s,_spx", r->name);    
2463     }
2464
2465   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2466     {
2467       if (options.useXstack)
2468         {
2469           emitcode ("inc", "%s", r->name);
2470           emitcode ("mov", "a,(%s+%d)",
2471                     regs390[i].base, 8 * bank + regs390[i].offset);
2472           emitcode ("movx", "@%s,a", r->name);
2473         }
2474       else
2475         emitcode ("push", "(%s+%d)",
2476                   regs390[i].base, 8 * bank + regs390[i].offset);
2477     }
2478
2479   if (pushPsw)
2480     {
2481       if (options.useXstack)
2482         {
2483           emitcode ("mov", "a,psw");
2484           emitcode ("movx", "@%s,a", r->name);
2485           emitcode ("inc", "%s", r->name);
2486           emitcode ("mov", "_spx,%s", r->name);
2487         }
2488       else
2489       {
2490         emitcode ("push", "psw");
2491       }
2492
2493       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2494     }
2495   
2496   if (aop)
2497   {
2498        freeAsmop (NULL, aop, ic, TRUE);
2499   }    
2500     
2501   if (ic)
2502   {  
2503       ic->bankSaved = 1;
2504   }
2505 }
2506
2507 /*-----------------------------------------------------------------*/
2508 /* genSend - gen code for SEND                                     */
2509 /*-----------------------------------------------------------------*/
2510 static void genSend(set *sendSet)
2511 {
2512     iCode *sic;
2513     int sendCount = 0 ;
2514     static int rb1_count = 0;
2515
2516     for (sic = setFirstItem (sendSet); sic;
2517          sic = setNextItem (sendSet)) {     
2518         int size, offset = 0;
2519         
2520         size=getSize(operandType(IC_LEFT(sic)));
2521         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2522         if (sendCount == 0) { /* first parameter */
2523             // we know that dpl(hxb) is the result, so
2524             rb1_count = 0 ;
2525             _startLazyDPSEvaluation ();
2526             if (size>1) {
2527                 aopOp (IC_LEFT (sic), sic, FALSE, 
2528                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2529             } else {
2530                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2531             }
2532             while (size--) {
2533                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2534                                   FALSE, FALSE, NULL);
2535                 if (strcmp (l, fReturn[offset])) {
2536                     emitcode ("mov", "%s,%s",
2537                               fReturn[offset],
2538                               l);
2539                 }
2540                 offset++;
2541             }
2542             _endLazyDPSEvaluation ();
2543             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2544             rb1_count =0;
2545         } else { /* if more parameter in registers */
2546             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2547             while (size--) {
2548                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2549                                                                 FALSE, FALSE, NULL));
2550             }
2551             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2552         }
2553         sendCount++;
2554     }
2555 }
2556
2557 static void
2558 adjustEsp(const char *reg)
2559 {
2560     emitcode ("anl","%s,#3", reg);
2561     if (TARGET_IS_DS400)
2562     {
2563         emitcode ("orl","%s,#!constbyte",
2564                   reg,
2565                   (options.stack_loc >> 8) & 0xff);
2566     }
2567 }
2568
2569 /*-----------------------------------------------------------------*/
2570 /* genCall - generates a call statement                            */
2571 /*-----------------------------------------------------------------*/
2572 static void
2573 genCall (iCode * ic)
2574 {
2575   sym_link *dtype;
2576   bool restoreBank = FALSE;
2577   bool swapBanks = FALSE;
2578
2579   D (emitcode (";", "genCall "););
2580
2581   /* if we are calling a not _naked function that is not using
2582      the same register bank then we need to save the
2583      destination registers on the stack */
2584   dtype = operandType (IC_LEFT (ic));
2585   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2586       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2587       IFFUNC_ISISR (currFunc->type))
2588   {
2589       if (!ic->bankSaved) 
2590       {
2591            /* This is unexpected; the bank should have been saved in
2592             * genFunction.
2593             */
2594            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2595            restoreBank = TRUE;
2596       }
2597       swapBanks = TRUE;
2598   }
2599   
2600     /* if caller saves & we have not saved then */
2601     if (!ic->regsSaved)
2602       saveRegisters (ic);
2603   
2604   /* if send set is not empty the assign */
2605   /* We've saved all the registers we care about;
2606   * therefore, we may clobber any register not used
2607   * in the calling convention (i.e. anything not in
2608   * fReturn.
2609   */
2610   if (_G.sendSet)
2611     {
2612         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2613             genSend(reverseSet(_G.sendSet));
2614         } else {
2615             genSend(_G.sendSet);
2616         }
2617       _G.sendSet = NULL;
2618     }  
2619     
2620   if (swapBanks)
2621   {
2622         emitcode ("mov", "psw,#!constbyte", 
2623            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2624   }
2625
2626   /* make the call */
2627   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2628                             OP_SYMBOL (IC_LEFT (ic))->rname :
2629                             OP_SYMBOL (IC_LEFT (ic))->name));
2630
2631   if (swapBanks)
2632   {
2633        emitcode ("mov", "psw,#!constbyte", 
2634           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2635   }
2636
2637   /* if we need assign a result value */
2638   if ((IS_ITEMP (IC_RESULT (ic)) &&
2639        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2640         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2641         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2642       IS_TRUE_SYMOP (IC_RESULT (ic)))
2643     {
2644       if (isOperandInFarSpace (IC_RESULT (ic))
2645           && getSize (operandType (IC_RESULT (ic))) <= 2)
2646         {
2647           int size = getSize (operandType (IC_RESULT (ic)));
2648
2649           /* Special case for 1 or 2 byte return in far space. */
2650           MOVA (fReturn[0]);
2651           if (size > 1)
2652             {
2653               emitcode ("mov", "b,%s", fReturn[1]);
2654             }
2655
2656           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2657           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2658
2659           if (size > 1)
2660             {
2661               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2662             }
2663           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2664         }
2665       else
2666         {
2667           _G.accInUse++;
2668           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2669           _G.accInUse--;
2670
2671           assignResultValue (IC_RESULT (ic));
2672
2673           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2674         }
2675     }
2676
2677   /* adjust the stack for parameters if
2678      required */
2679   if (ic->parmBytes) {
2680       int i;
2681       if (options.stack10bit) {
2682           if (ic->parmBytes <= 10) {
2683               emitcode(";","stack adjustment for parms");
2684               for (i=0; i < ic->parmBytes ; i++) {
2685                   emitcode("pop","acc");
2686               }
2687           } else {            
2688               PROTECT_SP;
2689               emitcode ("clr","c");
2690               emitcode ("mov","a,sp");
2691               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2692               emitcode ("mov","sp,a");
2693               emitcode ("mov","a,esp");
2694               adjustEsp("a");
2695               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2696               emitcode ("mov","esp,a");   
2697               UNPROTECT_SP;
2698           }
2699       } else {
2700           if (ic->parmBytes > 3) {
2701               emitcode ("mov", "a,%s", spname);
2702               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2703               emitcode ("mov", "%s,a", spname);
2704           } else
2705               for (i = 0; i < ic->parmBytes; i++)
2706                   emitcode ("dec", "%s", spname);
2707       }
2708   }
2709
2710   /* if we hade saved some registers then unsave them */
2711   if (ic->regsSaved)
2712     unsaveRegisters (ic);
2713
2714   /* if register bank was saved then pop them */
2715   if (restoreBank)
2716     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2717 }
2718
2719 /*-----------------------------------------------------------------*/
2720 /* genPcall - generates a call by pointer statement                */
2721 /*-----------------------------------------------------------------*/
2722 static void
2723 genPcall (iCode * ic)
2724 {
2725   sym_link *dtype;
2726   symbol *rlbl = newiTempLabel (NULL);
2727   bool restoreBank=FALSE;
2728
2729   D (emitcode (";", "genPcall ");
2730     );
2731
2732
2733   /* if caller saves & we have not saved then */
2734   if (!ic->regsSaved)
2735     saveRegisters (ic);
2736
2737   /* if we are calling a function that is not using
2738      the same register bank then we need to save the
2739      destination registers on the stack */
2740   dtype = operandType (IC_LEFT (ic));
2741   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2742       IFFUNC_ISISR (currFunc->type) &&
2743       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2744     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2745     restoreBank=TRUE;
2746   }
2747
2748   /* push the return address on to the stack */
2749   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2750   emitcode ("push", "acc");
2751   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2752   emitcode ("push", "acc");
2753
2754   if (options.model == MODEL_FLAT24)
2755     {
2756       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2757       emitcode ("push", "acc");
2758     }
2759
2760   /* now push the calling address */
2761   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2762
2763   pushSide (IC_LEFT (ic), FPTRSIZE);
2764
2765   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2766
2767   /* if send set is not empty the assign */
2768   if (_G.sendSet)
2769     {
2770         genSend(reverseSet(_G.sendSet));
2771         _G.sendSet = NULL;
2772     }
2773
2774   emitcode ("ret", "");
2775   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2776
2777
2778   /* if we need assign a result value */
2779   if ((IS_ITEMP (IC_RESULT (ic)) &&
2780        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2781         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2782       IS_TRUE_SYMOP (IC_RESULT (ic)))
2783     {
2784
2785       _G.accInUse++;
2786       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2787       _G.accInUse--;
2788
2789       assignResultValue (IC_RESULT (ic));
2790
2791       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2792     }
2793
2794   /* adjust the stack for parameters if
2795      required */
2796   if (ic->parmBytes)
2797     {
2798       int i;
2799       if (options.stack10bit) {
2800           if (ic->parmBytes <= 10) {
2801               emitcode(";","stack adjustment for parms");
2802               for (i=0; i < ic->parmBytes ; i++) {
2803                   emitcode("pop","acc");
2804               }
2805           } else {            
2806               PROTECT_SP;
2807               emitcode ("clr","c");
2808               emitcode ("mov","a,sp");
2809               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2810               emitcode ("mov","sp,a");
2811               emitcode ("mov","a,esp");
2812               adjustEsp("a");
2813               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2814               emitcode ("mov","esp,a");   
2815               UNPROTECT_SP;
2816           }
2817       } else {
2818           if (ic->parmBytes > 3) {
2819               emitcode ("mov", "a,%s", spname);
2820               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2821               emitcode ("mov", "%s,a", spname);
2822           }
2823           else
2824               for (i = 0; i < ic->parmBytes; i++)
2825                   emitcode ("dec", "%s", spname);
2826           
2827       }
2828     }
2829   /* if register bank was saved then unsave them */
2830   if (restoreBank)
2831     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2832   
2833   /* if we hade saved some registers then
2834      unsave them */
2835   if (ic->regsSaved)
2836     unsaveRegisters (ic);
2837
2838 }
2839
2840 /*-----------------------------------------------------------------*/
2841 /* resultRemat - result  is rematerializable                       */
2842 /*-----------------------------------------------------------------*/
2843 static int
2844 resultRemat (iCode * ic)
2845 {
2846   if (SKIP_IC (ic) || ic->op == IFX)
2847     return 0;
2848
2849   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2850     {
2851       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2852       if (sym->remat && !POINTER_SET (ic))
2853         return 1;
2854     }
2855
2856   return 0;
2857 }
2858
2859 #if defined(__BORLANDC__) || defined(_MSC_VER)
2860 #define STRCASECMP stricmp
2861 #else
2862 #define STRCASECMP strcasecmp
2863 #endif
2864
2865 /*-----------------------------------------------------------------*/
2866 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2867 /*-----------------------------------------------------------------*/
2868 static int
2869 regsCmp(void *p1, void *p2)
2870 {
2871   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2872 }
2873
2874 static bool
2875 inExcludeList (char *s)
2876 {
2877   const char *p = setFirstItem(options.excludeRegsSet);
2878
2879   if (p == NULL || STRCASECMP(p, "none") == 0)
2880     return FALSE;
2881
2882
2883   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2884 }
2885
2886 /*-----------------------------------------------------------------*/
2887 /* genFunction - generated code for function entry                 */
2888 /*-----------------------------------------------------------------*/
2889 static void
2890 genFunction (iCode * ic)
2891 {
2892   symbol *sym;
2893   sym_link *ftype;
2894   bool   switchedPSW = FALSE;
2895
2896   D (emitcode (";", "genFunction "););
2897
2898   _G.nRegsSaved = 0;
2899   /* create the function header */
2900   emitcode (";", "-----------------------------------------");
2901   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2902   emitcode (";", "-----------------------------------------");
2903
2904   emitcode ("", "%s:", sym->rname);
2905   ftype = operandType (IC_LEFT (ic));
2906
2907   if (IFFUNC_ISNAKED(ftype))
2908   {
2909       emitcode(";", "naked function: no prologue.");
2910       return;
2911   }
2912   
2913   if (options.stack_probe) 
2914       emitcode ("lcall","__stack_probe");
2915
2916   /* here we need to generate the equates for the
2917      register bank if required */
2918   if (FUNC_REGBANK (ftype) != rbank)
2919     {
2920       int i;
2921
2922       rbank = FUNC_REGBANK (ftype);
2923       for (i = 0; i < ds390_nRegs; i++)
2924         {
2925           if (regs390[i].print) {
2926               if (strcmp (regs390[i].base, "0") == 0)
2927                   emitcode ("", "%s !equ !constbyte",
2928                             regs390[i].dname,
2929                             8 * rbank + regs390[i].offset);
2930               else
2931                   emitcode ("", "%s !equ %s + !constbyte",
2932                             regs390[i].dname,
2933                             regs390[i].base,
2934                             8 * rbank + regs390[i].offset);
2935           }
2936         }
2937     }
2938
2939   /* if this is an interrupt service routine then
2940      save acc, b, dpl, dph  */
2941   if (IFFUNC_ISISR (sym->type))
2942       { /* is ISR */
2943       if (!inExcludeList ("acc"))
2944         emitcode ("push", "acc");
2945       if (!inExcludeList ("b"))
2946         emitcode ("push", "b");
2947       if (!inExcludeList ("dpl"))
2948         emitcode ("push", "dpl");
2949       if (!inExcludeList ("dph"))
2950         emitcode ("push", "dph");
2951       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2952         {
2953           emitcode ("push", "dpx");
2954           /* Make sure we're using standard DPTR */
2955           emitcode ("push", "dps");
2956           emitcode ("mov", "dps,#0");
2957           if (options.stack10bit)
2958             {
2959               /* This ISR could conceivably use DPTR2. Better save it. */
2960               emitcode ("push", "dpl1");
2961               emitcode ("push", "dph1");
2962               emitcode ("push", "dpx1");
2963               emitcode ("push",  DP2_RESULT_REG);
2964             }
2965         }
2966       /* if this isr has no bank i.e. is going to
2967          run with bank 0 , then we need to save more
2968          registers :-) */
2969       if (!FUNC_REGBANK (sym->type))
2970         {
2971             int i;
2972
2973           /* if this function does not call any other
2974              function then we can be economical and
2975              save only those registers that are used */
2976           if (!IFFUNC_HASFCALL(sym->type))
2977             {
2978
2979               /* if any registers used */
2980               if (sym->regsUsed)
2981                 {
2982                   /* save the registers used */
2983                   for (i = 0; i < sym->regsUsed->size; i++)
2984                     {
2985                       if (bitVectBitValue (sym->regsUsed, i) ||
2986                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2987                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2988                     }
2989                 }
2990
2991             }
2992           else
2993             {
2994               /* this function has  a function call cannot
2995                  determines register usage so we will have to push the
2996                  entire bank */
2997               saveRBank (0, ic, FALSE);
2998               if (options.parms_in_bank1) {
2999                   for (i=0; i < 8 ; i++ ) {
3000                       emitcode ("push","%s",rb1regs[i]);
3001                   }
3002               }
3003             }
3004         }
3005         else
3006         {
3007             /* This ISR uses a non-zero bank.
3008              *
3009              * We assume that the bank is available for our
3010              * exclusive use.
3011              *
3012              * However, if this ISR calls a function which uses some
3013              * other bank, we must save that bank entirely.
3014              */
3015             unsigned long banksToSave = 0;
3016             
3017             if (IFFUNC_HASFCALL(sym->type))
3018             {
3019
3020 #define MAX_REGISTER_BANKS 4
3021
3022                 iCode *i;
3023                 int ix;
3024
3025                 for (i = ic; i; i = i->next)
3026                 {
3027                     if (i->op == ENDFUNCTION)
3028                     {
3029                         /* we got to the end OK. */
3030                         break;
3031                     }
3032                     
3033                     if (i->op == CALL)
3034                     {
3035                         sym_link *dtype;
3036                         
3037                         dtype = operandType (IC_LEFT(i));
3038                         if (dtype 
3039                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3040                         {
3041                              /* Mark this bank for saving. */
3042                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3043                              {
3044                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3045                              }
3046                              else
3047                              {
3048                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3049                              }
3050                              
3051                              /* And note that we don't need to do it in 
3052                               * genCall.
3053                               */
3054                              i->bankSaved = 1;
3055                         }
3056                     }
3057                     if (i->op == PCALL)
3058                     {
3059                         /* This is a mess; we have no idea what
3060                          * register bank the called function might
3061                          * use.
3062                          *
3063                          * The only thing I can think of to do is
3064                          * throw a warning and hope.
3065                          */
3066                         werror(W_FUNCPTR_IN_USING_ISR);   
3067                     }
3068                 }
3069
3070                 if (banksToSave && options.useXstack)
3071                 {
3072                     /* Since we aren't passing it an ic, 
3073                      * saveRBank will assume r0 is available to abuse.
3074                      *
3075                      * So switch to our (trashable) bank now, so
3076                      * the caller's R0 isn't trashed.
3077                      */
3078                     emitcode ("push", "psw");
3079                     emitcode ("mov", "psw,#!constbyte", 
3080                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3081                     switchedPSW = TRUE;
3082                 }
3083                 
3084                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3085                 {
3086                      if (banksToSave & (1 << ix))
3087                      {
3088                          saveRBank(ix, NULL, FALSE);
3089                      }
3090                 }
3091             }
3092             // TODO: this needs a closer look
3093             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3094         }
3095     }
3096   else
3097     {
3098       /* if callee-save to be used for this function
3099          then save the registers being used in this function */
3100       if (IFFUNC_CALLEESAVES(sym->type))
3101         {
3102           int i;
3103
3104           /* if any registers used */
3105           if (sym->regsUsed)
3106             {
3107               /* save the registers used */
3108               for (i = 0; i < sym->regsUsed->size; i++)
3109                 {
3110                   if (bitVectBitValue (sym->regsUsed, i) ||
3111                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3112                     {
3113                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3114                       _G.nRegsSaved++;
3115                     }
3116                 }
3117             }
3118         }
3119     }
3120
3121   /* set the register bank to the desired value */
3122   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3123    && !switchedPSW)
3124     {
3125       emitcode ("push", "psw");
3126       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3127     }
3128
3129   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3130        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3131       if (options.stack10bit) {
3132           emitcode ("push","_bpx");
3133           emitcode ("push","_bpx+1");
3134           emitcode ("mov","_bpx,%s",spname);
3135           emitcode ("mov","_bpx+1,esp");
3136           adjustEsp("_bpx+1");
3137       } else {
3138           if (options.useXstack) {
3139               emitcode ("mov", "r0,%s", spname);
3140               emitcode ("mov", "a,_bp");
3141               emitcode ("movx", "@r0,a");
3142               emitcode ("inc", "%s", spname);
3143           } else {
3144               /* set up the stack */
3145               emitcode ("push", "_bp"); /* save the callers stack  */
3146           }
3147           emitcode ("mov", "_bp,%s", spname);
3148       }
3149   }
3150
3151   /* adjust the stack for the function */
3152   if (sym->stack) {
3153       int i = sym->stack;
3154       if (options.stack10bit) {
3155           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3156           assert (sym->recvSize <= 4);
3157           if (sym->stack <= 8) {
3158               while (i--) emitcode ("push","acc");
3159           } else {
3160               PROTECT_SP;
3161               emitcode ("mov","a,sp");
3162               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3163               emitcode ("mov","sp,a");
3164               emitcode ("mov","a,esp");
3165               adjustEsp("a");
3166               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3167               emitcode ("mov","esp,a");
3168               UNPROTECT_SP;
3169           }
3170       } else {
3171           if (i > 256)
3172               werror (W_STACK_OVERFLOW, sym->name);
3173           
3174           if (i > 3 && sym->recvSize < 4) {
3175               
3176               emitcode ("mov", "a,sp");
3177               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3178               emitcode ("mov", "sp,a");
3179               
3180           } else
3181               while (i--)
3182                   emitcode ("inc", "sp");
3183       }
3184   }
3185
3186   if (sym->xstack)
3187     {
3188
3189       emitcode ("mov", "a,_spx");
3190       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3191       emitcode ("mov", "_spx,a");
3192     }
3193   
3194   /* if critical function then turn interrupts off */
3195   if (IFFUNC_ISCRITICAL (ftype))
3196     {
3197       symbol *tlbl = newiTempLabel (NULL);
3198       emitcode ("setb", "c");
3199       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3200       emitcode ("clr", "c");
3201       emitcode ("", "%05d$:", (tlbl->key + 100));
3202       emitcode ("push", "psw"); /* save old ea via c in psw */
3203     }
3204
3205 }
3206
3207 /*-----------------------------------------------------------------*/
3208 /* genEndFunction - generates epilogue for functions               */
3209 /*-----------------------------------------------------------------*/
3210 static void
3211 genEndFunction (iCode * ic)
3212 {
3213   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3214
3215   D (emitcode (";", "genEndFunction "););
3216
3217   if (IFFUNC_ISNAKED(sym->type))
3218   {
3219       emitcode(";", "naked function: no epilogue.");
3220       return;
3221   }
3222
3223   if (IFFUNC_ISCRITICAL (sym->type))
3224     {
3225       emitcode ("pop", "psw"); /* restore ea via c in psw */
3226       emitcode ("mov", "ea,c");
3227     }
3228   
3229   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3230        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3231
3232       if (options.stack10bit) {
3233           PROTECT_SP;     
3234           emitcode ("mov", "sp,_bpx", spname);
3235           emitcode ("mov", "esp,_bpx+1", spname);
3236           UNPROTECT_SP;
3237       } else {
3238           emitcode ("mov", "%s,_bp", spname);
3239       }
3240   }
3241
3242   /* if use external stack but some variables were
3243      added to the local stack then decrement the
3244      local stack */
3245   if (options.useXstack && sym->stack) {
3246       emitcode ("mov", "a,sp");
3247       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3248       emitcode ("mov", "sp,a");
3249   }
3250
3251
3252   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3253        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3254
3255       if (options.useXstack) {
3256           emitcode ("mov", "r0,%s", spname);
3257           emitcode ("movx", "a,@r0");
3258           emitcode ("mov", "_bp,a");
3259           emitcode ("dec", "%s", spname);
3260       } else {
3261           if (options.stack10bit) {
3262               emitcode ("pop", "_bpx+1");
3263               emitcode ("pop", "_bpx");
3264           } else {
3265               emitcode ("pop", "_bp");
3266           }
3267       }
3268   }
3269
3270   /* restore the register bank  */
3271   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3272   {
3273     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3274      || !options.useXstack)
3275     {
3276         /* Special case of ISR using non-zero bank with useXstack
3277          * is handled below.
3278          */
3279         emitcode ("pop", "psw");
3280     }
3281   } 
3282
3283   if (IFFUNC_ISISR (sym->type))
3284       { /* is ISR */  
3285
3286       /* now we need to restore the registers */
3287       /* if this isr has no bank i.e. is going to
3288          run with bank 0 , then we need to save more
3289          registers :-) */
3290       if (!FUNC_REGBANK (sym->type))
3291         {
3292             int i;
3293           /* if this function does not call any other
3294              function then we can be economical and
3295              save only those registers that are used */
3296           if (!IFFUNC_HASFCALL(sym->type))
3297             {
3298
3299               /* if any registers used */
3300               if (sym->regsUsed)
3301                 {
3302                   /* save the registers used */
3303                   for (i = sym->regsUsed->size; i >= 0; i--)
3304                     {
3305                       if (bitVectBitValue (sym->regsUsed, i) ||
3306                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3307                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3308                     }
3309                 }
3310
3311             }
3312           else
3313             {
3314               /* this function has  a function call cannot
3315                  determines register usage so we will have to pop the
3316                  entire bank */
3317               if (options.parms_in_bank1) {
3318                   for (i = 7 ; i >= 0 ; i-- ) {
3319                       emitcode ("pop","%s",rb1regs[i]);
3320                   }
3321               }
3322               unsaveRBank (0, ic, FALSE);
3323             }
3324         }
3325         else
3326         {
3327             /* This ISR uses a non-zero bank.
3328              *
3329              * Restore any register banks saved by genFunction
3330              * in reverse order.
3331              */
3332             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3333             int ix;
3334           
3335             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3336             {
3337                 if (savedBanks & (1 << ix))
3338                 {
3339                     unsaveRBank(ix, NULL, FALSE);
3340                 }
3341             }
3342             
3343             if (options.useXstack)
3344             {
3345                 /* Restore bank AFTER calling unsaveRBank,
3346                  * since it can trash r0.
3347                  */
3348                 emitcode ("pop", "psw");
3349             }
3350         }
3351
3352       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3353         {
3354           if (options.stack10bit)
3355             {
3356               emitcode ("pop", DP2_RESULT_REG);
3357               emitcode ("pop", "dpx1");
3358               emitcode ("pop", "dph1");
3359               emitcode ("pop", "dpl1");
3360             }
3361           emitcode ("pop", "dps");
3362           emitcode ("pop", "dpx");
3363         }
3364       if (!inExcludeList ("dph"))
3365         emitcode ("pop", "dph");
3366       if (!inExcludeList ("dpl"))
3367         emitcode ("pop", "dpl");
3368       if (!inExcludeList ("b"))
3369         emitcode ("pop", "b");
3370       if (!inExcludeList ("acc"))
3371         emitcode ("pop", "acc");
3372
3373       /* if debug then send end of function */
3374       if (options.debug && currFunc) {
3375           _G.debugLine = 1;
3376           emitcode ("", "C$%s$%d$%d$%d ==.",
3377                     FileBaseName (ic->filename), currFunc->lastLine,
3378                     ic->level, ic->block);
3379           if (IS_STATIC (currFunc->etype))
3380             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3381           else
3382             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3383           _G.debugLine = 0;
3384         }
3385
3386       emitcode ("reti", "");
3387     }
3388   else
3389     {
3390       if (IFFUNC_CALLEESAVES(sym->type))
3391         {
3392           int i;
3393
3394           /* if any registers used */
3395           if (sym->regsUsed)
3396             {
3397               /* save the registers used */
3398               for (i = sym->regsUsed->size; i >= 0; i--)
3399                 {
3400                   if (bitVectBitValue (sym->regsUsed, i) ||
3401                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3402                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3403                 }
3404             }
3405
3406         }
3407
3408       /* if debug then send end of function */
3409       if (options.debug && currFunc)
3410         {
3411           _G.debugLine = 1;
3412           emitcode ("", "C$%s$%d$%d$%d ==.",
3413                     FileBaseName (ic->filename), currFunc->lastLine,
3414                     ic->level, ic->block);
3415           if (IS_STATIC (currFunc->etype))
3416             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3417           else
3418             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3419           _G.debugLine = 0;
3420         }
3421
3422       emitcode ("ret", "");
3423     }
3424
3425 }
3426
3427 /*-----------------------------------------------------------------*/
3428 /* genJavaNativeRet - generate code for return JavaNative          */
3429 /*-----------------------------------------------------------------*/
3430 static void genJavaNativeRet(iCode *ic)
3431 {
3432     int i, size;
3433
3434     aopOp (IC_LEFT (ic), ic, FALSE, 
3435            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3436     size = AOP_SIZE (IC_LEFT (ic));
3437
3438     assert (size <= 4);
3439
3440     /* it is assigned to GPR0-R3 then push them */
3441     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3442         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3443         for (i = 0 ; i < size ; i++ ) {
3444             emitcode ("push","%s",
3445                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3446         }
3447         for (i = (size-1) ; i >= 0 ; i--) {
3448             emitcode ("pop","a%s",javaRet[i]);
3449         }
3450     } else {
3451         for (i = 0 ; i < size ; i++) 
3452             emitcode ("mov","%s,%s",javaRet[i],
3453                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3454     }
3455     for (i = size ; i < 4 ; i++ )
3456             emitcode ("mov","%s,#0",javaRet[i]);
3457     return;
3458 }
3459
3460 /*-----------------------------------------------------------------*/
3461 /* genRet - generate code for return statement                     */
3462 /*-----------------------------------------------------------------*/
3463 static void
3464 genRet (iCode * ic)
3465 {
3466   int size, offset = 0, pushed = 0;
3467
3468   D (emitcode (";", "genRet "););
3469
3470   /* if we have no return value then
3471      just generate the "ret" */
3472   if (!IC_LEFT (ic))
3473     goto jumpret;
3474
3475   /* if this is a JavaNative function then return 
3476      value in different register */
3477   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3478       genJavaNativeRet(ic);
3479       goto jumpret;
3480   }
3481   /* we have something to return then
3482      move the return value into place */
3483   aopOp (IC_LEFT (ic), ic, FALSE, 
3484          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3485   size = AOP_SIZE (IC_LEFT (ic));
3486
3487   _startLazyDPSEvaluation ();
3488   while (size--)
3489     {
3490       char *l;
3491       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3492         {
3493           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3494                       FALSE, TRUE, NULL);
3495           emitcode ("push", "%s", l);
3496           pushed++;
3497         }
3498       else
3499         {
3500           /* Since A is the last element of fReturn,
3501            * is is OK to clobber it in the aopGet.
3502            */
3503           l = aopGet (AOP (IC_LEFT (ic)), offset,
3504                       FALSE, FALSE, NULL);
3505           if (strcmp (fReturn[offset], l))
3506             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3507         }
3508     }
3509   _endLazyDPSEvaluation ();
3510
3511   if (pushed)
3512     {
3513       while (pushed)
3514         {
3515           pushed--;
3516           if (strcmp (fReturn[pushed], "a"))
3517             emitcode ("pop", fReturn[pushed]);
3518           else
3519             emitcode ("pop", "acc");
3520         }
3521     }
3522   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3523
3524 jumpret:
3525   /* generate a jump to the return label
3526      if the next is not the return statement */
3527   if (!(ic->next && ic->next->op == LABEL &&
3528         IC_LABEL (ic->next) == returnLabel))
3529
3530     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3531
3532 }
3533
3534 /*-----------------------------------------------------------------*/
3535 /* genLabel - generates a label                                    */
3536 /*-----------------------------------------------------------------*/
3537 static void
3538 genLabel (iCode * ic)
3539 {
3540   /* special case never generate */
3541   if (IC_LABEL (ic) == entryLabel)
3542     return;
3543
3544   D (emitcode (";", "genLabel ");
3545     );
3546
3547   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3548 }
3549
3550 /*-----------------------------------------------------------------*/
3551 /* genGoto - generates a ljmp                                      */
3552 /*-----------------------------------------------------------------*/
3553 static void
3554 genGoto (iCode * ic)
3555 {
3556   D (emitcode (";", "genGoto ");
3557     );
3558   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3559 }
3560
3561 /*-----------------------------------------------------------------*/
3562 /* findLabelBackwards: walks back through the iCode chain looking  */
3563 /* for the given label. Returns number of iCode instructions     */
3564 /* between that label and given ic.          */
3565 /* Returns zero if label not found.          */
3566 /*-----------------------------------------------------------------*/
3567 static int
3568 findLabelBackwards (iCode * ic, int key)
3569 {
3570   int count = 0;
3571
3572   while (ic->prev)
3573     {
3574       ic = ic->prev;
3575       count++;
3576
3577       /* If we have any pushes or pops, we cannot predict the distance.
3578          I don't like this at all, this should be dealt with in the 
3579          back-end */
3580       if (ic->op == IPUSH || ic->op == IPOP) {
3581         return 0;
3582       }
3583
3584       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3585         {
3586           /* printf("findLabelBackwards = %d\n", count); */
3587           return count;
3588         }
3589     }
3590
3591   return 0;
3592 }
3593
3594 /*-----------------------------------------------------------------*/
3595 /* genPlusIncr :- does addition with increment if possible         */
3596 /*-----------------------------------------------------------------*/
3597 static bool
3598 genPlusIncr (iCode * ic)
3599 {
3600   unsigned int icount;
3601   unsigned int size = getDataSize (IC_RESULT (ic));
3602
3603   /* will try to generate an increment */
3604   /* if the right side is not a literal
3605      we cannot */
3606   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3607     return FALSE;
3608
3609   /* if the literal value of the right hand side
3610      is greater than 4 then it is not worth it */
3611   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3612     return FALSE;
3613
3614   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3615       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3616       while (icount--) {
3617           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3618       }
3619       return TRUE;
3620   }
3621   /* if increment 16 bits in register */
3622   if (
3623        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3624        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3625        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3626        (size > 1) &&
3627        (icount == 1))
3628     {
3629       symbol  *tlbl;
3630       int     emitTlbl;
3631       int     labelRange;
3632       char    *l;
3633
3634       /* If the next instruction is a goto and the goto target
3635        * is <= 5 instructions previous to this, we can generate
3636        * jumps straight to that target.
3637        */
3638       if (ic->next && ic->next->op == GOTO
3639           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3640           && labelRange <= 5)
3641         {
3642           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3643           tlbl = IC_LABEL (ic->next);
3644           emitTlbl = 0;
3645         }
3646       else
3647         {
3648           tlbl = newiTempLabel (NULL);
3649           emitTlbl = 1;
3650         }
3651         
3652       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3653       emitcode ("inc", "%s", l);
3654       
3655       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3656           IS_AOP_PREG (IC_RESULT (ic)))
3657       {   
3658         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3659       }
3660       else
3661       {
3662           emitcode ("clr", "a");
3663           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3664       }
3665
3666       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3667       emitcode ("inc", "%s", l);
3668       if (size > 2)
3669         {
3670             if (!strcmp(l, "acc"))
3671             {
3672                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3673             }
3674             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3675                      IS_AOP_PREG (IC_RESULT (ic)))
3676             {
3677                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3678             }
3679             else
3680             {
3681                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3682             }
3683
3684             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3685             emitcode ("inc", "%s", l);
3686         }
3687       if (size > 3)
3688         {
3689             if (!strcmp(l, "acc"))
3690             {
3691                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3692             }
3693             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3694                      IS_AOP_PREG (IC_RESULT (ic)))
3695             {
3696                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3697             }
3698             else
3699             {
3700                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3701             }
3702
3703             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3704             emitcode ("inc", "%s", l);  }
3705
3706       if (emitTlbl)
3707         {
3708           emitcode ("", "!tlabeldef", tlbl->key + 100);
3709         }
3710       return TRUE;
3711     }
3712
3713   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3714       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3715       options.model == MODEL_FLAT24 ) {
3716
3717       switch (size) {
3718       case 3:
3719           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3720       case 2:
3721           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3722       case 1:
3723           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3724           break;
3725       }
3726       while (icount--) emitcode ("inc","dptr");      
3727       return TRUE;
3728   }
3729
3730   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3731       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3732       icount <= 5 ) {
3733       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3734       while (icount--) emitcode ("inc","dptr");
3735       emitcode ("mov","dps,#0");
3736       return TRUE;
3737   }
3738
3739   /* if the sizes are greater than 1 then we cannot */
3740   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3741       AOP_SIZE (IC_LEFT (ic)) > 1)
3742     return FALSE;
3743
3744   /* we can if the aops of the left & result match or
3745      if they are in registers and the registers are the
3746      same */
3747   if (
3748        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3749        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3750        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3751     {
3752
3753       if (icount > 3)
3754         {
3755           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3756           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3757           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3758         }
3759       else
3760         {
3761
3762           _startLazyDPSEvaluation ();
3763           while (icount--)
3764             {
3765               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3766             }
3767           _endLazyDPSEvaluation ();
3768         }
3769
3770       return TRUE;
3771     }
3772
3773   return FALSE;
3774 }
3775
3776 /*-----------------------------------------------------------------*/
3777 /* outBitAcc - output a bit in acc                                 */
3778 /*-----------------------------------------------------------------*/
3779 static void
3780 outBitAcc (operand * result)
3781 {
3782   symbol *tlbl = newiTempLabel (NULL);
3783   /* if the result is a bit */
3784   if (AOP_TYPE (result) == AOP_CRY)
3785     {
3786       aopPut (AOP (result), "a", 0);
3787     }
3788   else
3789     {
3790       emitcode ("jz", "!tlabel", tlbl->key + 100);
3791       emitcode ("mov", "a,%s", one);
3792       emitcode ("", "!tlabeldef", tlbl->key + 100);
3793       outAcc (result);
3794     }
3795 }
3796
3797 /*-----------------------------------------------------------------*/
3798 /* genPlusBits - generates code for addition of two bits           */
3799 /*-----------------------------------------------------------------*/
3800 static void
3801 genPlusBits (iCode * ic)
3802 {
3803   D (emitcode (";", "genPlusBits "););
3804     
3805   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3806     {
3807       symbol *lbl = newiTempLabel (NULL);
3808       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3809       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3810       emitcode ("cpl", "c");
3811       emitcode ("", "!tlabeldef", (lbl->key + 100));
3812       outBitC (IC_RESULT (ic));
3813     }
3814   else
3815     {
3816       emitcode ("clr", "a");
3817       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3818       emitcode ("rlc", "a");
3819       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3820       emitcode ("addc", "a,#0");
3821       outAcc (IC_RESULT (ic));
3822     }
3823 }
3824
3825 static void
3826 adjustArithmeticResult (iCode * ic)
3827 {
3828   if (opIsGptr (IC_RESULT (ic)) &&
3829       opIsGptr (IC_LEFT (ic)) &&
3830       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3831     {
3832       aopPut (AOP (IC_RESULT (ic)),
3833               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3834               GPTRSIZE - 1);
3835     }
3836
3837   if (opIsGptr (IC_RESULT (ic)) &&
3838       opIsGptr (IC_RIGHT (ic)) &&
3839       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3840     {
3841       aopPut (AOP (IC_RESULT (ic)),
3842             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3843               GPTRSIZE - 1);
3844     }
3845
3846   if (opIsGptr (IC_RESULT (ic)) &&
3847       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3848       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3849       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3850       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3851     {
3852       char buff[5];
3853       SNPRINTF (buff, sizeof(buff), 
3854                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3855       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3856     }
3857 }
3858
3859 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3860 // generates the result if possible. If result is generated, returns TRUE; otherwise
3861 // returns false and caller must deal with fact that result isn't aopOp'd.
3862 bool aopOp3(iCode * ic)
3863 {
3864     bool dp1InUse, dp2InUse;
3865     bool useDp2;
3866     
3867     // First, generate the right opcode. DPTR may be used if neither left nor result are
3868     // of type AOP_STR.
3869     
3870 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3871 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3872 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3873 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3874 //      );
3875 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3876 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3877 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3878 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3879 //      );
3880     
3881     // Right uses DPTR unless left or result is an AOP_STR; however,
3882     // if right is an AOP_STR, it must use DPTR regardless.
3883     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3884      && !AOP_IS_STR(IC_RIGHT(ic)))
3885     {
3886         useDp2 = TRUE;
3887     }
3888     else
3889     {
3890         useDp2 = FALSE;
3891     }
3892         
3893     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3894     
3895     // if the right used DPTR, left MUST use DPTR2.
3896     // if the right used DPTR2, left MUST use DPTR.
3897     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3898     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3899     // enabling us to assign DPTR to result.
3900      
3901     if (AOP_USESDPTR(IC_RIGHT(ic)))
3902     {
3903         useDp2 = TRUE;
3904     }
3905     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3906     {
3907         useDp2 = FALSE;
3908     }
3909     else
3910     {
3911         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3912         {
3913             useDp2 = TRUE;
3914         }
3915         else
3916         {
3917             useDp2 = FALSE;
3918         }
3919     }
3920
3921     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3922     
3923     // We've op'd the left & right. So, if left or right are the same operand as result, 
3924     // we know aopOp will succeed, and we can just do it & bail.
3925     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3926         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3927     {
3928 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3929         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3930         return TRUE;
3931     }
3932     
3933     // Note which dptrs are currently in use.
3934     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3935     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3936     
3937     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3938     // generate it.
3939     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3940     {
3941         return FALSE;
3942     }
3943     
3944     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3945     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3946     {
3947         return FALSE;
3948     }
3949     
3950     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3951     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3952     {
3953         return FALSE;
3954     }
3955
3956     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3957
3958     // Some sanity checking...
3959     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3960     {
3961         fprintf(stderr,
3962                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3963                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3964         emitcode(";", ">>> unexpected DPTR here.");
3965     }
3966     
3967     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3968     {
3969         fprintf(stderr,
3970                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3971                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3972         emitcode(";", ">>> unexpected DPTR2 here.");
3973     }    
3974     
3975     return TRUE;
3976 }
3977
3978 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3979 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3980 // will be set TRUE. The caller must then handle the case specially, noting
3981 // that the IC_RESULT operand is not aopOp'd.
3982 // 
3983 #define AOP_OP_3_NOFATAL(ic, rc) \
3984             do { rc = !aopOp3(ic); } while (0)
3985
3986 // aopOp the left & right operands of an ic.
3987 #define AOP_OP_2(ic) \
3988     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3989     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3990
3991 // convienience macro.
3992 #define AOP_SET_LOCALS(ic) \
3993     left = IC_LEFT(ic); \
3994     right = IC_RIGHT(ic); \
3995     result = IC_RESULT(ic);
3996
3997
3998 // Given an integer value of pushedSize bytes on the stack,
3999 // adjust it to be resultSize bytes, either by discarding
4000 // the most significant bytes or by zero-padding.
4001 //
4002 // On exit from this macro, pushedSize will have been adjusted to
4003 // equal resultSize, and ACC may be trashed.
4004 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4005       /* If the pushed data is bigger than the result,          \
4006        * simply discard unused bytes. Icky, but works.          \
4007        */                                                       \
4008       while (pushedSize > resultSize)                           \
4009       {                                                         \
4010           D (emitcode (";", "discarding unused result byte."););\
4011           emitcode ("pop", "acc");                              \
4012           pushedSize--;                                         \
4013       }                                                         \
4014       if (pushedSize < resultSize)                              \
4015       {                                                         \
4016           emitcode ("clr", "a");                                \
4017           /* Conversly, we haven't pushed enough here.          \
4018            * just zero-pad, and all is well.                    \
4019            */                                                   \
4020           while (pushedSize < resultSize)                       \
4021           {                                                     \
4022               emitcode("push", "acc");                          \
4023               pushedSize++;                                     \
4024           }                                                     \
4025       }                                                         \
4026       assert(pushedSize == resultSize);
4027
4028 /*-----------------------------------------------------------------*/
4029 /* genPlus - generates code for addition                           */
4030 /*-----------------------------------------------------------------*/
4031 static void
4032 genPlus (iCode * ic)
4033 {
4034   int size, offset = 0;
4035   bool pushResult;
4036   int rSize;
4037
4038   D (emitcode (";", "genPlus "););
4039
4040   /* special cases :- */
4041   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4042       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4043       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4044       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4045       if (size <= 9) {
4046           while (size--) emitcode ("inc","dptr");
4047       } else {
4048           emitcode ("mov","a,dpl");
4049           emitcode ("add","a,#!constbyte",size & 0xff);
4050           emitcode ("mov","dpl,a");
4051           emitcode ("mov","a,dph");
4052           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4053           emitcode ("mov","dph,a");
4054           emitcode ("mov","a,dpx");
4055           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4056           emitcode ("mov","dpx,a");
4057       }
4058       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4059       return ;
4060   }
4061   if ( IS_SYMOP(IC_LEFT(ic)) && 
4062        OP_SYMBOL(IC_LEFT(ic))->remat &&
4063        isOperandInFarSpace(IC_RIGHT(ic))) {
4064       operand *op = IC_RIGHT(ic);
4065       IC_RIGHT(ic) = IC_LEFT(ic);
4066       IC_LEFT(ic) = op;
4067   }
4068                 
4069   AOP_OP_3_NOFATAL (ic, pushResult);
4070     
4071   if (pushResult)
4072     {
4073       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4074     }
4075
4076   if (!pushResult)
4077     {
4078       /* if literal, literal on the right or
4079          if left requires ACC or right is already
4080          in ACC */
4081       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4082        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4083           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4084         {
4085           operand *t = IC_RIGHT (ic);
4086           IC_RIGHT (ic) = IC_LEFT (ic);
4087           IC_LEFT (ic) = t;
4088           emitcode (";", "Swapped plus args.");
4089         }
4090
4091       /* if both left & right are in bit
4092          space */
4093       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4094           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4095         {
4096           genPlusBits (ic);
4097           goto release;
4098         }
4099
4100       /* if left in bit space & right literal */
4101       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4102           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4103         {
4104           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4105           /* if result in bit space */
4106           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4107             {
4108               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4109                 emitcode ("cpl", "c");
4110               outBitC (IC_RESULT (ic));
4111             }
4112           else
4113             {
4114               size = getDataSize (IC_RESULT (ic));
4115               _startLazyDPSEvaluation ();
4116               while (size--)
4117                 {
4118                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4119                   emitcode ("addc", "a,#0");
4120                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4121                 }
4122               _endLazyDPSEvaluation ();
4123             }
4124           goto release;
4125         }
4126
4127       /* if I can do an increment instead
4128          of add then GOOD for ME */
4129       if (genPlusIncr (ic) == TRUE)
4130         {
4131           emitcode (";", "did genPlusIncr");
4132           goto release;
4133         }
4134
4135     }
4136   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4137
4138   _startLazyDPSEvaluation ();
4139   while (size--)
4140     {
4141       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4142         {
4143           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4144           if (offset == 0)
4145             emitcode ("add", "a,%s",
4146                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4147           else
4148             emitcode ("addc", "a,%s",
4149                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4150         }
4151       else
4152         {
4153           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4154           {
4155               /* right is going to use ACC or we would have taken the
4156                * above branch.
4157                */
4158               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4159        TR_AP("#3");
4160               D(emitcode(";", "+ AOP_ACC special case."););
4161               emitcode("xch", "a, %s", DP2_RESULT_REG);
4162           }
4163           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4164           if (offset == 0)
4165           {
4166             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4167             {
4168          TR_AP("#4");
4169                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4170             }
4171             else
4172             {
4173                 emitcode ("add", "a,%s",
4174                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4175                                   DP2_RESULT_REG));
4176             }
4177           }
4178           else
4179           {
4180             emitcode ("addc", "a,%s",
4181                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4182                           DP2_RESULT_REG));
4183           }
4184         }
4185       if (!pushResult)
4186         {
4187           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4188         }
4189       else
4190         {
4191           emitcode ("push", "acc");
4192         }
4193       offset++;
4194     }
4195   _endLazyDPSEvaluation ();
4196
4197   if (pushResult)
4198     {
4199       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4200
4201       size = getDataSize (IC_LEFT (ic));
4202       rSize = getDataSize (IC_RESULT (ic));
4203
4204       ADJUST_PUSHED_RESULT(size, rSize);
4205
4206       _startLazyDPSEvaluation ();
4207       while (size--)
4208         {
4209           emitcode ("pop", "acc");
4210           aopPut (AOP (IC_RESULT (ic)), "a", size);
4211         }
4212       _endLazyDPSEvaluation ();
4213     }
4214
4215   adjustArithmeticResult (ic);
4216
4217 release:
4218   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4219   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4220   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4221 }
4222
4223 /*-----------------------------------------------------------------*/
4224 /* genMinusDec :- does subtraction with deccrement if possible     */
4225 /*-----------------------------------------------------------------*/
4226 static bool
4227 genMinusDec (iCode * ic)
4228 {
4229   unsigned int icount;
4230   unsigned int size = getDataSize (IC_RESULT (ic));
4231
4232   /* will try to generate an increment */
4233   /* if the right side is not a literal
4234      we cannot */
4235   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4236     return FALSE;
4237
4238   /* if the literal value of the right hand side
4239      is greater than 4 then it is not worth it */
4240   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4241     return FALSE;
4242
4243   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4244       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4245       while (icount--) {
4246           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4247       }
4248       return TRUE;
4249   }
4250   /* if decrement 16 bits in register */
4251   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4252       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4253       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4254       (size > 1) &&
4255       (icount == 1))
4256     {
4257       symbol *tlbl;
4258       int    emitTlbl;
4259       int    labelRange;
4260       char   *l;
4261
4262       /* If the next instruction is a goto and the goto target
4263          * is <= 5 instructions previous to this, we can generate
4264          * jumps straight to that target.
4265        */
4266       if (ic->next && ic->next->op == GOTO
4267           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4268           && labelRange <= 5)
4269         {
4270           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4271           tlbl = IC_LABEL (ic->next);
4272           emitTlbl = 0;
4273         }
4274       else
4275         {
4276           tlbl = newiTempLabel (NULL);
4277           emitTlbl = 1;
4278         }
4279
4280       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4281       emitcode ("dec", "%s", l);
4282  
4283       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4284           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4285           IS_AOP_PREG (IC_RESULT (ic)))
4286       {     
4287           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4288       }
4289       else
4290       {
4291           emitcode ("mov", "a,#!constbyte",0xff);
4292           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4293       }
4294       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4295       emitcode ("dec", "%s", l);
4296       if (size > 2)
4297         {
4298             if (!strcmp(l, "acc"))
4299             {
4300                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4301             }
4302             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4303                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4304                      IS_AOP_PREG (IC_RESULT (ic)))
4305             {       
4306                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4307             }
4308             else
4309             {
4310                 emitcode ("mov", "a,#!constbyte",0xff);
4311                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4312             }
4313             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4314             emitcode ("dec", "%s", l);
4315         }
4316       if (size > 3)
4317         {
4318             if (!strcmp(l, "acc"))
4319             {
4320                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4321             }
4322             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4323                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4324                      IS_AOP_PREG (IC_RESULT (ic)))
4325             {       
4326                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4327             }
4328             else
4329             {
4330                 emitcode ("mov", "a,#!constbyte",0xff);
4331                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4332             }       
4333             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4334             emitcode ("dec", "%s", l);
4335         }
4336       if (emitTlbl)
4337         {
4338           emitcode ("", "!tlabeldef", tlbl->key + 100);
4339         }
4340       return TRUE;
4341     }
4342
4343   /* if the sizes are greater than 1 then we cannot */
4344   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4345       AOP_SIZE (IC_LEFT (ic)) > 1)
4346     return FALSE;
4347
4348   /* we can if the aops of the left & result match or
4349      if they are in registers and the registers are the
4350      same */
4351   if (
4352        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4353        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4354        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4355     {
4356
4357       _startLazyDPSEvaluation ();
4358       while (icount--)
4359         {
4360           emitcode ("dec", "%s",
4361                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4362         }
4363       _endLazyDPSEvaluation ();
4364
4365       return TRUE;
4366     }
4367
4368   return FALSE;
4369 }
4370
4371 /*-----------------------------------------------------------------*/
4372 /* addSign - complete with sign                                    */
4373 /*-----------------------------------------------------------------*/
4374 static void
4375 addSign (operand * result, int offset, int sign)
4376 {
4377   int size = (getDataSize (result) - offset);
4378   if (size > 0)
4379     {
4380       _startLazyDPSEvaluation();
4381       if (sign)
4382         {
4383           emitcode ("rlc", "a");
4384           emitcode ("subb", "a,acc");
4385           while (size--)
4386           {
4387             aopPut (AOP (result), "a", offset++);
4388           }
4389         }
4390       else
4391       {
4392         while (size--)
4393         {
4394           aopPut (AOP (result), zero, offset++);
4395         }
4396       }
4397       _endLazyDPSEvaluation();
4398     }
4399 }
4400
4401 /*-----------------------------------------------------------------*/
4402 /* genMinusBits - generates code for subtraction  of two bits      */
4403 /*-----------------------------------------------------------------*/
4404 static void
4405 genMinusBits (iCode * ic)
4406 {
4407   symbol *lbl = newiTempLabel (NULL);
4408
4409   D (emitcode (";", "genMinusBits "););
4410
4411   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4412     {
4413       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4414       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4415       emitcode ("cpl", "c");
4416       emitcode ("", "!tlabeldef", (lbl->key + 100));
4417       outBitC (IC_RESULT (ic));
4418     }
4419   else
4420     {
4421       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4422       emitcode ("subb", "a,acc");
4423       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4424       emitcode ("inc", "a");
4425       emitcode ("", "!tlabeldef", (lbl->key + 100));
4426       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4427       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4428     }
4429 }
4430
4431 /*-----------------------------------------------------------------*/
4432 /* genMinus - generates code for subtraction                       */
4433 /*-----------------------------------------------------------------*/
4434 static void
4435 genMinus (iCode * ic)
4436 {
4437     int size, offset = 0;
4438     int rSize;
4439     long lit = 0L;
4440     bool pushResult;
4441
4442     D (emitcode (";", "genMinus "););
4443
4444     AOP_OP_3_NOFATAL(ic, pushResult);   
4445
4446     if (!pushResult)
4447     {
4448       /* special cases :- */
4449       /* if both left & right are in bit space */
4450       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4451           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4452         {
4453           genMinusBits (ic);
4454           goto release;
4455         }
4456
4457       /* if I can do an decrement instead
4458          of subtract then GOOD for ME */
4459       if (genMinusDec (ic) == TRUE)
4460         goto release;
4461
4462     }
4463
4464   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4465
4466   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4467     {
4468       CLRC;
4469     }
4470   else
4471     {
4472       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4473       lit = -lit;
4474     }
4475
4476
4477   /* if literal, add a,#-lit, else normal subb */
4478   _startLazyDPSEvaluation ();
4479   while (size--) {
4480       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4481           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4482               emitcode ("mov","b,%s",
4483                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4484               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4485               emitcode ("subb","a,b");
4486           } else {
4487               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4488               emitcode ("subb", "a,%s",
4489                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4490                                 DP2_RESULT_REG));
4491           }
4492       } else {
4493           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4494           /* first add without previous c */
4495           if (!offset) {
4496               if (!size && lit==-1) {
4497                   emitcode ("dec", "a");
4498               } else {
4499                   emitcode ("add", "a,#!constbyte",
4500                             (unsigned int) (lit & 0x0FFL));
4501               }
4502           } else {
4503               emitcode ("addc", "a,#!constbyte",
4504                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4505           }
4506       }
4507       
4508       if (pushResult) {
4509           emitcode ("push", "acc");
4510       } else {
4511           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4512       }
4513       offset++;
4514   }
4515   _endLazyDPSEvaluation ();
4516   
4517   if (pushResult)
4518     {
4519       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4520
4521       size = getDataSize (IC_LEFT (ic));
4522       rSize = getDataSize (IC_RESULT (ic));
4523
4524       ADJUST_PUSHED_RESULT(size, rSize);
4525
4526       _startLazyDPSEvaluation ();
4527       while (size--)
4528         {
4529           emitcode ("pop", "acc");
4530           aopPut (AOP (IC_RESULT (ic)), "a", size);
4531         }
4532       _endLazyDPSEvaluation ();
4533     }
4534
4535   adjustArithmeticResult (ic);
4536
4537 release:
4538   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4539   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4540   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4541 }
4542
4543
4544 /*-----------------------------------------------------------------*/
4545 /* genMultbits :- multiplication of bits                           */
4546 /*-----------------------------------------------------------------*/
4547 static void
4548 genMultbits (operand * left,
4549              operand * right,
4550              operand * result,
4551              iCode   * ic)
4552 {
4553   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4554   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4555   aopOp(result, ic, TRUE, FALSE);
4556   outBitC (result);
4557 }
4558
4559
4560 /*-----------------------------------------------------------------*/
4561 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4562 /*-----------------------------------------------------------------*/
4563 static void
4564 genMultOneByte (operand * left,
4565                 operand * right,
4566                 operand * result,
4567                 iCode   * ic)
4568 {
4569   sym_link *opetype = operandType (result);
4570   symbol *lbl;
4571
4572
4573   /* (if two literals: the value is computed before) */
4574   /* if one literal, literal on the right */
4575   if (AOP_TYPE (left) == AOP_LIT)
4576     {
4577       operand *t = right;
4578       right = left;
4579       left = t;
4580       emitcode (";", "swapped left and right");
4581     }
4582
4583   if (SPEC_USIGN(opetype)
4584       // ignore the sign of left and right, what else can we do?
4585       || (SPEC_USIGN(operandType(left)) && 
4586           SPEC_USIGN(operandType(right)))) {
4587     // just an unsigned 8*8=8/16 multiply
4588     //emitcode (";","unsigned");
4589     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4590     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4591     emitcode ("mul", "ab");
4592    
4593     _G.accInUse++; _G.bInUse++;
4594     aopOp(result, ic, TRUE, FALSE);
4595       
4596       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4597       {
4598           // this should never happen
4599           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4600                    AOP_SIZE(result), __FILE__, lineno);
4601           exit (1);
4602       }      
4603       
4604     aopPut (AOP (result), "a", 0);
4605     _G.accInUse--; _G.bInUse--;
4606     if (AOP_SIZE(result)==2) 
4607     {
4608       aopPut (AOP (result), "b", 1);
4609     }
4610     return;
4611   }
4612
4613   // we have to do a signed multiply
4614
4615   emitcode (";", "signed");
4616   emitcode ("clr", "F0"); // reset sign flag
4617   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4618
4619   lbl=newiTempLabel(NULL);
4620   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4621   // left side is negative, 8-bit two's complement, this fails for -128
4622   emitcode ("setb", "F0"); // set sign flag
4623   emitcode ("cpl", "a");
4624   emitcode ("inc", "a");
4625
4626   emitcode ("", "!tlabeldef", lbl->key+100);
4627
4628   /* if literal */
4629   if (AOP_TYPE(right)==AOP_LIT) {
4630     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4631     /* AND literal negative */
4632     if ((int) val < 0) {
4633       emitcode ("cpl", "F0"); // complement sign flag
4634       emitcode ("mov", "b,#!constbyte", -val);
4635     } else {
4636       emitcode ("mov", "b,#!constbyte", val);
4637     }
4638   } else {
4639     lbl=newiTempLabel(NULL);
4640     emitcode ("mov", "b,a");
4641     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4642     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4643     // right side is negative, 8-bit two's complement
4644     emitcode ("cpl", "F0"); // complement sign flag
4645     emitcode ("cpl", "a");
4646     emitcode ("inc", "a");
4647     emitcode ("", "!tlabeldef", lbl->key+100);
4648   }
4649   emitcode ("mul", "ab");
4650     
4651   _G.accInUse++;_G.bInUse++;
4652   aopOp(result, ic, TRUE, FALSE);
4653     
4654   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4655   {
4656     // this should never happen
4657       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4658                AOP_SIZE(result), __FILE__, lineno);
4659       exit (1);
4660   }    
4661     
4662   lbl=newiTempLabel(NULL);
4663   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4664   // only ONE op was negative, we have to do a 8/16-bit two's complement
4665   emitcode ("cpl", "a"); // lsb
4666   if (AOP_SIZE(result)==1) {
4667     emitcode ("inc", "a");
4668   } else {
4669     emitcode ("add", "a,#1");
4670     emitcode ("xch", "a,b");
4671     emitcode ("cpl", "a"); // msb
4672     emitcode ("addc", "a,#0");
4673     emitcode ("xch", "a,b");
4674   }
4675
4676   emitcode ("", "!tlabeldef", lbl->key+100);
4677   aopPut (AOP (result), "a", 0);
4678   _G.accInUse--;_G.bInUse--;
4679   if (AOP_SIZE(result)==2) {
4680     aopPut (AOP (result), "b", 1);
4681   }
4682 }
4683
4684 /*-----------------------------------------------------------------*/
4685 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4686 /*-----------------------------------------------------------------*/
4687 static void genMultTwoByte (operand *left, operand *right, 
4688                             operand *result, iCode *ic)
4689 {
4690         sym_link *retype = getSpec(operandType(right));
4691         sym_link *letype = getSpec(operandType(left));
4692         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4693         symbol *lbl;
4694
4695         if (AOP_TYPE (left) == AOP_LIT) {
4696                 operand *t = right;
4697                 right = left;
4698                 left = t;
4699         }
4700         /* save EA bit in F1 */
4701         lbl = newiTempLabel(NULL);
4702         emitcode ("setb","F1");
4703         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4704         emitcode ("clr","F1");
4705         emitcode("","!tlabeldef",lbl->key+100);
4706
4707         /* load up MB with right */
4708         if (!umult) {
4709                 emitcode("clr","F0");
4710                 if (AOP_TYPE(right) == AOP_LIT) {
4711                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4712                         if (val < 0) {
4713                                 emitcode("setb","F0");
4714                                 val = -val;
4715                         }
4716                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4717                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4718                 } else {
4719                         lbl = newiTempLabel(NULL);
4720                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4721                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4722                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4723                         emitcode ("xch", "a,b");
4724                         emitcode ("cpl","a");
4725                         emitcode ("add", "a,#1");
4726                         emitcode ("xch", "a,b");
4727                         emitcode ("cpl", "a"); // msb
4728                         emitcode ("addc", "a,#0");
4729                         emitcode ("setb","F0");
4730                         emitcode ("","!tlabeldef",lbl->key+100);
4731                         emitcode ("mov","mb,b");
4732                         emitcode ("mov","mb,a");
4733                 }
4734         } else {
4735                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4736                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4737         }
4738         /* load up MA with left */
4739         if (!umult) {
4740                 lbl = newiTempLabel(NULL);
4741                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4742                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4743                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4744                 emitcode ("xch", "a,b");
4745                 emitcode ("cpl","a");
4746                 emitcode ("add", "a,#1");
4747                 emitcode ("xch", "a,b");
4748                 emitcode ("cpl", "a"); // msb
4749                 emitcode ("addc","a,#0");
4750                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4751                 emitcode ("setb","F0");
4752                 emitcode ("","!tlabeldef",lbl->key+100);
4753                 emitcode ("mov","ma,b");
4754                 emitcode ("mov","ma,a");
4755         } else {
4756                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4757                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4758         }
4759         /* wait for multiplication to finish */
4760         lbl = newiTempLabel(NULL);
4761         emitcode("","!tlabeldef", lbl->key+100);
4762         emitcode("mov","a,mcnt1");
4763         emitcode("anl","a,#!constbyte",0x80);
4764         emitcode("jnz","!tlabel",lbl->key+100);
4765         
4766         freeAsmop (left, NULL, ic, TRUE);
4767         freeAsmop (right, NULL, ic,TRUE);
4768         aopOp(result, ic, TRUE, FALSE);
4769
4770         /* if unsigned then simple */   
4771         if (umult) {
4772                 emitcode ("mov","a,ma");
4773                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4774                 emitcode ("mov","a,ma");
4775                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4776                 aopPut(AOP(result),"ma",1);
4777                 aopPut(AOP(result),"ma",0);
4778         } else {
4779                 emitcode("push","ma");
4780                 emitcode("push","ma");
4781                 emitcode("push","ma");
4782                 MOVA("ma");
4783                 /* negate result if needed */
4784                 lbl = newiTempLabel(NULL);      
4785                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4786                 emitcode("cpl","a");
4787                 emitcode("add","a,#1");
4788                 emitcode("","!tlabeldef", lbl->key+100);
4789                 if (AOP_TYPE(result) == AOP_ACC)
4790                 {
4791                     D(emitcode(";", "ACC special case."););
4792                     /* We know result is the only live aop, and 
4793                      * it's obviously not a DPTR2, so AP is available.
4794                      */
4795                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4796                 }
4797                 else
4798                 {
4799                     aopPut(AOP(result),"a",0);
4800                 }
4801             
4802                 emitcode("pop","acc");
4803                 lbl = newiTempLabel(NULL);      
4804                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4805                 emitcode("cpl","a");
4806                 emitcode("addc","a,#0");
4807                 emitcode("","!tlabeldef", lbl->key+100);
4808                 aopPut(AOP(result),"a",1);
4809                 emitcode("pop","acc");
4810                 if (AOP_SIZE(result) >= 3) {
4811                         lbl = newiTempLabel(NULL);      
4812                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4813                         emitcode("cpl","a");
4814                         emitcode("addc","a,#0");                        
4815                         emitcode("","!tlabeldef", lbl->key+100);
4816                         aopPut(AOP(result),"a",2);
4817                 }
4818                 emitcode("pop","acc");
4819                 if (AOP_SIZE(result) >= 4) {
4820                         lbl = newiTempLabel(NULL);      
4821                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4822                         emitcode("cpl","a");
4823                         emitcode("addc","a,#0");                        
4824                         emitcode("","!tlabeldef", lbl->key+100);
4825                         aopPut(AOP(result),"a",3);
4826                 }
4827                 if (AOP_TYPE(result) == AOP_ACC)
4828                 {
4829                     /* We stashed the result away above. */
4830                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4831                 }           
4832                 
4833         }
4834         freeAsmop (result, NULL, ic, TRUE);
4835
4836         /* restore EA bit in F1 */
4837         lbl = newiTempLabel(NULL);
4838         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4839         emitcode ("setb","EA");
4840         emitcode("","!tlabeldef",lbl->key+100);
4841         return ;
4842 }
4843
4844 /*-----------------------------------------------------------------*/
4845 /* genMult - generates code for multiplication                     */
4846 /*-----------------------------------------------------------------*/
4847 static void
4848 genMult (iCode * ic)
4849 {
4850   operand *left = IC_LEFT (ic);
4851   operand *right = IC_RIGHT (ic);
4852   operand *result = IC_RESULT (ic);
4853
4854   D (emitcode (";", "genMult "););
4855
4856   /* assign the amsops */
4857   AOP_OP_2 (ic);
4858
4859   /* special cases first */
4860   /* both are bits */
4861   if (AOP_TYPE (left) == AOP_CRY &&
4862       AOP_TYPE (right) == AOP_CRY)
4863     {
4864       genMultbits (left, right, result, ic);
4865       goto release;
4866     }
4867
4868   /* if both are of size == 1 */
4869   if (AOP_SIZE (left) == 1 &&
4870       AOP_SIZE (right) == 1)
4871     {
4872       genMultOneByte (left, right, result, ic);
4873       goto release;
4874     }
4875
4876   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4877           /* use the ds390 ARITHMETIC accel UNIT */
4878           genMultTwoByte (left, right, result, ic);
4879           return ;
4880   }
4881   /* should have been converted to function call */
4882   assert (0);
4883
4884 release:
4885   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4886   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4887   freeAsmop (result, NULL, ic, TRUE);
4888 }
4889
4890 /*-----------------------------------------------------------------*/
4891 /* genDivbits :- division of bits                                  */
4892 /*-----------------------------------------------------------------*/
4893 static void
4894 genDivbits (operand * left,
4895             operand * right,
4896             operand * result,
4897             iCode   * ic)
4898 {
4899
4900   char *l;
4901
4902   /* the result must be bit */
4903   LOAD_AB_FOR_DIV (left, right, l);
4904   emitcode ("div", "ab");
4905   emitcode ("rrc", "a");
4906   aopOp(result, ic, TRUE, FALSE);
4907     
4908   aopPut (AOP (result), "c", 0);
4909 }
4910
4911 /*-----------------------------------------------------------------*/
4912 /* genDivOneByte : 8 bit division                                  */
4913 /*-----------------------------------------------------------------*/
4914 static void
4915 genDivOneByte (operand * left,
4916                operand * right,
4917                operand * result,
4918                iCode   * ic)
4919 {
4920   sym_link *opetype = operandType (result);
4921   char *l;
4922   symbol *lbl;
4923   int size, offset;
4924
4925   offset = 1;
4926   /* signed or unsigned */
4927   if (SPEC_USIGN (opetype))
4928     {
4929         /* unsigned is easy */
4930         LOAD_AB_FOR_DIV (left, right, l);
4931         emitcode ("div", "ab");
4932
4933         _G.accInUse++;
4934         aopOp(result, ic, TRUE, FALSE);
4935         aopPut (AOP (result), "a", 0);
4936         _G.accInUse--;
4937
4938         size = AOP_SIZE (result) - 1;
4939         
4940         while (size--)
4941         {
4942             aopPut (AOP (result), zero, offset++);
4943         }
4944       return;
4945     }
4946
4947   /* signed is a little bit more difficult */
4948
4949   /* save the signs of the operands */
4950   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4951   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4952   emitcode ("push", "acc");     /* save it on the stack */
4953
4954   /* now sign adjust for both left & right */
4955   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4956   lbl = newiTempLabel (NULL);
4957   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4958   emitcode ("cpl", "a");
4959   emitcode ("inc", "a");
4960   emitcode ("", "!tlabeldef", (lbl->key + 100));
4961   emitcode ("mov", "b,a");
4962
4963   /* sign adjust left side */
4964   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4965
4966   lbl = newiTempLabel (NULL);
4967   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4968   emitcode ("cpl", "a");
4969   emitcode ("inc", "a");
4970   emitcode ("", "!tlabeldef", (lbl->key + 100));
4971
4972   /* now the division */
4973   emitcode ("nop", "; workaround for DS80C390 div bug.");
4974   emitcode ("div", "ab");
4975   /* we are interested in the lower order
4976      only */
4977   emitcode ("mov", "b,a");
4978   lbl = newiTempLabel (NULL);
4979   emitcode ("pop", "acc");
4980   /* if there was an over flow we don't
4981      adjust the sign of the result */
4982   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4983   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4984   CLRC;
4985   emitcode ("clr", "a");
4986   emitcode ("subb", "a,b");
4987   emitcode ("mov", "b,a");
4988   emitcode ("", "!tlabeldef", (lbl->key + 100));
4989
4990   /* now we are done */
4991   _G.accInUse++;     _G.bInUse++;
4992     aopOp(result, ic, TRUE, FALSE);
4993     
4994     aopPut (AOP (result), "b", 0);
4995     
4996     size = AOP_SIZE (result) - 1;
4997     
4998     if (size > 0)
4999     {
5000       emitcode ("mov", "c,b.7");
5001       emitcode ("subb", "a,acc");
5002     }
5003     while (size--)
5004     {
5005         aopPut (AOP (result), "a", offset++);
5006     }
5007     _G.accInUse--;     _G.bInUse--;
5008
5009 }
5010
5011 /*-----------------------------------------------------------------*/
5012 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5013 /*-----------------------------------------------------------------*/
5014 static void genDivTwoByte (operand *left, operand *right, 
5015                             operand *result, iCode *ic)
5016 {
5017         sym_link *retype = getSpec(operandType(right));
5018         sym_link *letype = getSpec(operandType(left));
5019         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5020         symbol *lbl;
5021
5022         /* save EA bit in F1 */
5023         lbl = newiTempLabel(NULL);
5024         emitcode ("setb","F1");
5025         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5026         emitcode ("clr","F1");
5027         emitcode("","!tlabeldef",lbl->key+100);
5028
5029         /* load up MA with left */
5030         if (!umult) {
5031                 emitcode("clr","F0");
5032                 lbl = newiTempLabel(NULL);
5033                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5034                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5035                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5036                 emitcode ("xch", "a,b");
5037                 emitcode ("cpl","a");
5038                 emitcode ("add", "a,#1");
5039                 emitcode ("xch", "a,b");
5040                 emitcode ("cpl", "a"); // msb
5041                 emitcode ("addc","a,#0");
5042                 emitcode ("setb","F0");
5043                 emitcode ("","!tlabeldef",lbl->key+100);
5044                 emitcode ("mov","ma,b");
5045                 emitcode ("mov","ma,a");
5046         } else {
5047                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5048                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5049         }
5050
5051         /* load up MB with right */
5052         if (!umult) {
5053                 if (AOP_TYPE(right) == AOP_LIT) {
5054                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5055                         if (val < 0) {
5056                                 lbl = newiTempLabel(NULL);
5057                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5058                                 emitcode("setb","F0");
5059                                 emitcode ("","!tlabeldef",lbl->key+100);
5060                                 val = -val;
5061                         } 
5062                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5063                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5064                 } else {
5065                         lbl = newiTempLabel(NULL);
5066                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5067                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5068                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5069                         emitcode ("xch", "a,b");
5070                         emitcode ("cpl","a");
5071                         emitcode ("add", "a,#1");
5072                         emitcode ("xch", "a,b");
5073                         emitcode ("cpl", "a"); // msb
5074                         emitcode ("addc", "a,#0");
5075                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5076                         emitcode ("setb","F0");
5077                         emitcode ("","!tlabeldef",lbl->key+100);
5078                         emitcode ("mov","mb,b");
5079                         emitcode ("mov","mb,a");
5080                 }
5081         } else {
5082                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5083                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5084         }
5085
5086         /* wait for multiplication to finish */
5087         lbl = newiTempLabel(NULL);
5088         emitcode("","!tlabeldef", lbl->key+100);
5089         emitcode("mov","a,mcnt1");
5090         emitcode("anl","a,#!constbyte",0x80);
5091         emitcode("jnz","!tlabel",lbl->key+100);
5092         
5093         freeAsmop (left, NULL, ic, TRUE);
5094         freeAsmop (right, NULL, ic,TRUE);
5095         aopOp(result, ic, TRUE, FALSE);
5096
5097         /* if unsigned then simple */   
5098         if (umult) {
5099                 aopPut(AOP(result),"ma",1);
5100                 aopPut(AOP(result),"ma",0);
5101         } else {
5102                 emitcode("push","ma");
5103                 MOVA("ma");
5104                 /* negate result if needed */
5105                 lbl = newiTempLabel(NULL);      
5106                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5107                 emitcode("cpl","a");
5108                 emitcode("add","a,#1");
5109                 emitcode("","!tlabeldef", lbl->key+100);
5110                 aopPut(AOP(result),"a",0);
5111                 emitcode("pop","acc");
5112                 lbl = newiTempLabel(NULL);      
5113                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5114                 emitcode("cpl","a");
5115                 emitcode("addc","a,#0");
5116                 emitcode("","!tlabeldef", lbl->key+100);
5117                 aopPut(AOP(result),"a",1);
5118         }
5119         freeAsmop (result, NULL, ic, TRUE);
5120         /* restore EA bit in F1 */
5121         lbl = newiTempLabel(NULL);
5122         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5123         emitcode ("setb","EA");
5124         emitcode("","!tlabeldef",lbl->key+100);
5125         return ;
5126 }
5127
5128 /*-----------------------------------------------------------------*/
5129 /* genDiv - generates code for division                            */
5130 /*-----------------------------------------------------------------*/
5131 static void
5132 genDiv (iCode * ic)
5133 {
5134   operand *left = IC_LEFT (ic);
5135   operand *right = IC_RIGHT (ic);
5136   operand *result = IC_RESULT (ic);
5137
5138   D (emitcode (";", "genDiv "););
5139
5140   /* assign the amsops */
5141   AOP_OP_2 (ic);
5142
5143   /* special cases first */
5144   /* both are bits */
5145   if (AOP_TYPE (left) == AOP_CRY &&
5146       AOP_TYPE (right) == AOP_CRY)
5147     {
5148       genDivbits (left, right, result, ic);
5149       goto release;
5150     }
5151
5152   /* if both are of size == 1 */
5153   if (AOP_SIZE (left) == 1 &&
5154       AOP_SIZE (right) == 1)
5155     {
5156       genDivOneByte (left, right, result, ic);
5157       goto release;
5158     }
5159
5160   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5161           /* use the ds390 ARITHMETIC accel UNIT */
5162           genDivTwoByte (left, right, result, ic);
5163           return ;
5164   }
5165   /* should have been converted to function call */
5166   assert (0);
5167 release:
5168   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5169   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5170   freeAsmop (result, NULL, ic, TRUE);
5171 }
5172
5173 /*-----------------------------------------------------------------*/
5174 /* genModbits :- modulus of bits                                   */
5175 /*-----------------------------------------------------------------*/
5176 static void
5177 genModbits (operand * left,
5178             operand * right,
5179             operand * result,
5180             iCode   * ic)
5181 {
5182
5183   char *l;
5184
5185   /* the result must be bit */
5186   LOAD_AB_FOR_DIV (left, right, l);
5187   emitcode ("div", "ab");
5188   emitcode ("mov", "a,b");
5189   emitcode ("rrc", "a");
5190   aopOp(result, ic, TRUE, FALSE);
5191   aopPut (AOP (result), "c", 0);
5192 }
5193
5194 /*-----------------------------------------------------------------*/
5195 /* genModOneByte : 8 bit modulus                                   */
5196 /*-----------------------------------------------------------------*/
5197 static void
5198 genModOneByte (operand * left,
5199                operand * right,
5200                operand * result,
5201                iCode   * ic)
5202 {
5203   sym_link *opetype = operandType (result);
5204   char *l;
5205   symbol *lbl;
5206
5207   /* signed or unsigned */
5208   if (SPEC_USIGN (opetype))
5209     {
5210       /* unsigned is easy */
5211       LOAD_AB_FOR_DIV (left, right, l);
5212       emitcode ("div", "ab");
5213       aopOp(result, ic, TRUE, FALSE);   
5214       aopPut (AOP (result), "b", 0);
5215       return;
5216     }
5217
5218   /* signed is a little bit more difficult */
5219
5220   /* save the signs of the operands */
5221   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5222
5223   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5224   emitcode ("push", "acc");     /* save it on the stack */
5225
5226   /* now sign adjust for both left & right */
5227   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5228
5229   lbl = newiTempLabel (NULL);
5230   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5231   emitcode ("cpl", "a");
5232   emitcode ("inc", "a");
5233   emitcode ("", "!tlabeldef", (lbl->key + 100));
5234   emitcode ("mov", "b,a");
5235
5236   /* sign adjust left side */
5237   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5238
5239   lbl = newiTempLabel (NULL);
5240   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5241   emitcode ("cpl", "a");
5242   emitcode ("inc", "a");
5243   emitcode ("", "!tlabeldef", (lbl->key + 100));
5244
5245   /* now the multiplication */
5246   emitcode ("nop", "; workaround for DS80C390 div bug.");
5247   emitcode ("div", "ab");
5248   /* we are interested in the lower order
5249      only */
5250   lbl = newiTempLabel (NULL);
5251   emitcode ("pop", "acc");
5252   /* if there was an over flow we don't
5253      adjust the sign of the result */
5254   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5255   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5256   CLRC;
5257   emitcode ("clr", "a");
5258   emitcode ("subb", "a,b");
5259   emitcode ("mov", "b,a");
5260   emitcode ("", "!tlabeldef", (lbl->key + 100));
5261   
5262   _G.bInUse++;
5263   /* now we are done */
5264   aopOp(result, ic, TRUE, FALSE);    
5265   aopPut (AOP (result), "b", 0);
5266   _G.bInUse--;
5267
5268 }
5269
5270 /*-----------------------------------------------------------------*/
5271 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5272 /*-----------------------------------------------------------------*/
5273 static void genModTwoByte (operand *left, operand *right, 
5274                             operand *result, iCode *ic)
5275 {
5276         sym_link *retype = getSpec(operandType(right));
5277         sym_link *letype = getSpec(operandType(left));
5278         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5279         symbol *lbl;
5280
5281         /* load up MA with left */
5282         /* save EA bit in F1 */
5283         lbl = newiTempLabel(NULL);
5284         emitcode ("setb","F1");
5285         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5286         emitcode ("clr","F1");
5287         emitcode("","!tlabeldef",lbl->key+100);
5288
5289         if (!umult) {
5290                 lbl = newiTempLabel(NULL);
5291                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5292                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5293                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5294                 emitcode ("xch", "a,b");
5295                 emitcode ("cpl","a");
5296                 emitcode ("add", "a,#1");
5297                 emitcode ("xch", "a,b");
5298                 emitcode ("cpl", "a"); // msb
5299                 emitcode ("addc","a,#0");
5300                 emitcode ("","!tlabeldef",lbl->key+100);
5301                 emitcode ("mov","ma,b");
5302                 emitcode ("mov","ma,a");
5303         } else {
5304                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5305                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5306         }
5307
5308         /* load up MB with right */
5309         if (!umult) {
5310                 if (AOP_TYPE(right) == AOP_LIT) {
5311                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5312                         if (val < 0) {
5313                                 val = -val;
5314                         } 
5315                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5316                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5317                 } else {
5318                         lbl = newiTempLabel(NULL);
5319                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5320                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5321                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5322                         emitcode ("xch", "a,b");
5323                         emitcode ("cpl","a");
5324                         emitcode ("add", "a,#1");
5325                         emitcode ("xch", "a,b");
5326                         emitcode ("cpl", "a"); // msb
5327                         emitcode ("addc", "a,#0");
5328                         emitcode ("","!tlabeldef",lbl->key+100);
5329                         emitcode ("mov","mb,b");
5330                         emitcode ("mov","mb,a");
5331                 }
5332         } else {
5333                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5334                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5335         }
5336
5337         /* wait for multiplication to finish */
5338         lbl = newiTempLabel(NULL);
5339         emitcode("","!tlabeldef", lbl->key+100);
5340         emitcode("mov","a,mcnt1");
5341         emitcode("anl","a,#!constbyte",0x80);
5342         emitcode("jnz","!tlabel",lbl->key+100);
5343         
5344         freeAsmop (left, NULL, ic, TRUE);
5345         freeAsmop (right, NULL, ic,TRUE);
5346         aopOp(result, ic, TRUE, FALSE);
5347
5348         aopPut(AOP(result),"mb",1);
5349         aopPut(AOP(result),"mb",0);
5350         freeAsmop (result, NULL, ic, TRUE);
5351
5352         /* restore EA bit in F1 */
5353         lbl = newiTempLabel(NULL);
5354         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5355         emitcode ("setb","EA");
5356         emitcode("","!tlabeldef",lbl->key+100);
5357         return ;
5358 }
5359
5360 /*-----------------------------------------------------------------*/
5361 /* genMod - generates code for division                            */
5362 /*-----------------------------------------------------------------*/
5363 static void
5364 genMod (iCode * ic)
5365 {
5366   operand *left = IC_LEFT (ic);
5367   operand *right = IC_RIGHT (ic);
5368   operand *result = IC_RESULT (ic);
5369
5370   D (emitcode (";", "genMod "); );
5371
5372   /* assign the amsops */
5373   AOP_OP_2 (ic);
5374
5375   /* special cases first */
5376   /* both are bits */
5377   if (AOP_TYPE (left) == AOP_CRY &&
5378       AOP_TYPE (right) == AOP_CRY)
5379     {
5380       genModbits (left, right, result, ic);
5381       goto release;
5382     }
5383
5384   /* if both are of size == 1 */
5385   if (AOP_SIZE (left) == 1 &&
5386       AOP_SIZE (right) == 1)
5387     {
5388       genModOneByte (left, right, result, ic);
5389       goto release;
5390     }
5391
5392   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5393           /* use the ds390 ARITHMETIC accel UNIT */
5394           genModTwoByte (left, right, result, ic);
5395           return ;
5396   }
5397
5398   /* should have been converted to function call */
5399   assert (0);
5400
5401 release:
5402   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5403   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5404   freeAsmop (result, NULL, ic, TRUE);
5405 }
5406
5407 /*-----------------------------------------------------------------*/
5408 /* genIfxJump :- will create a jump depending on the ifx           */
5409 /*-----------------------------------------------------------------*/
5410 static void
5411 genIfxJump (iCode * ic, char *jval)
5412 {
5413   symbol *jlbl;
5414   symbol *tlbl = newiTempLabel (NULL);
5415   char *inst;
5416
5417   D (emitcode (";", "genIfxJump"););
5418
5419   /* if true label then we jump if condition
5420      supplied is true */
5421   if (IC_TRUE (ic))
5422     {
5423       jlbl = IC_TRUE (ic);
5424       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5425                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5426     }
5427   else
5428     {
5429       /* false label is present */
5430       jlbl = IC_FALSE (ic);
5431       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5432                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5433     }
5434   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5435     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5436   else
5437     emitcode (inst, "!tlabel", tlbl->key + 100);
5438   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5439   emitcode ("", "!tlabeldef", tlbl->key + 100);
5440
5441   /* mark the icode as generated */
5442   ic->generated = 1;
5443 }
5444
5445 /*-----------------------------------------------------------------*/
5446 /* genCmp :- greater or less than comparison                       */
5447 /*-----------------------------------------------------------------*/
5448 static void
5449 genCmp (operand * left, operand * right,
5450         iCode * ic, iCode * ifx, int sign)
5451 {
5452   int size, offset = 0;
5453   unsigned long lit = 0L;
5454   operand *result;
5455
5456   D (emitcode (";", "genCmp"););
5457
5458   result = IC_RESULT (ic);
5459
5460   /* if left & right are bit variables */
5461   if (AOP_TYPE (left) == AOP_CRY &&
5462       AOP_TYPE (right) == AOP_CRY)
5463     {
5464       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5465       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5466     }
5467   else
5468     {
5469       /* subtract right from left if at the
5470          end the carry flag is set then we know that
5471          left is greater than right */
5472       size = max (AOP_SIZE (left), AOP_SIZE (right));
5473
5474       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5475       if ((size == 1) && !sign 
5476           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5477         {
5478           symbol *lbl = newiTempLabel (NULL);
5479           emitcode ("cjne", "%s,%s,!tlabel",
5480                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5481                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5482                     lbl->key + 100);
5483           emitcode ("", "!tlabeldef", lbl->key + 100);
5484         }
5485       else
5486         {
5487           if (AOP_TYPE (right) == AOP_LIT)
5488             {
5489               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5490               /* optimize if(x < 0) or if(x >= 0) */
5491               if (lit == 0L)
5492                 {
5493                   if (!sign)
5494                     {
5495                       CLRC;
5496                     }
5497                   else
5498                     {
5499                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5500
5501                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5502                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5503
5504                       aopOp (result, ic, FALSE, FALSE);
5505
5506                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5507                         {
5508                           freeAsmop (result, NULL, ic, TRUE);
5509                           genIfxJump (ifx, "acc.7");
5510                           return;
5511                         }
5512                       else
5513                         {
5514                           emitcode ("rlc", "a");
5515                         }
5516                       goto release_freedLR;
5517                     }
5518                   goto release;
5519                 }
5520             }
5521           CLRC;
5522           while (size--)
5523             {
5524               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5525               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5526               // emitcode (";", "genCmp #2");
5527               if (sign && (size == 0))
5528                 {
5529                   // emitcode (";", "genCmp #3");
5530                   emitcode ("xrl", "a,#!constbyte",0x80);
5531                   if (AOP_TYPE (right) == AOP_LIT)
5532                     {
5533                       unsigned long lit = (unsigned long)
5534                       floatFromVal (AOP (right)->aopu.aop_lit);
5535                       // emitcode (";", "genCmp #3.1");
5536                       emitcode ("subb", "a,#!constbyte",
5537                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5538                     }
5539                   else
5540                     {
5541                       // emitcode (";", "genCmp #3.2");
5542                       saveAccWarn = 0;  
5543                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5544                       saveAccWarn = DEFAULT_ACC_WARNING;
5545                       emitcode ("xrl", "b,#!constbyte",0x80);
5546                       emitcode ("subb", "a,b");
5547                     }
5548                 }
5549               else
5550                 {
5551                   const char *s;
5552
5553                   // emitcode (";", "genCmp #4");
5554                   saveAccWarn = 0;
5555                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5556                   saveAccWarn = DEFAULT_ACC_WARNING;
5557
5558                   emitcode ("subb", "a,%s", s);
5559                 }
5560             }
5561         }
5562     }
5563
5564 release:
5565 /* Don't need the left & right operands any more; do need the result. */
5566   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5567   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5568
5569   aopOp (result, ic, FALSE, FALSE);
5570
5571 release_freedLR:
5572
5573   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5574     {
5575       outBitC (result);
5576     }
5577   else
5578     {
5579       /* if the result is used in the next
5580          ifx conditional branch then generate
5581          code a little differently */
5582       if (ifx)
5583         {
5584           genIfxJump (ifx, "c");
5585         }
5586       else
5587         {
5588           outBitC (result);
5589         }
5590       /* leave the result in acc */
5591     }
5592   freeAsmop (result, NULL, ic, TRUE);
5593 }
5594
5595 /*-----------------------------------------------------------------*/
5596 /* genCmpGt :- greater than comparison                             */
5597 /*-----------------------------------------------------------------*/
5598 static void
5599 genCmpGt (iCode * ic, iCode * ifx)
5600 {
5601   operand *left, *right;
5602   sym_link *letype, *retype;
5603   int sign;
5604
5605   D (emitcode (";", "genCmpGt ");
5606     );
5607
5608   left = IC_LEFT (ic);
5609   right = IC_RIGHT (ic);
5610
5611   letype = getSpec (operandType (left));
5612   retype = getSpec (operandType (right));
5613   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5614
5615   /* assign the left & right amsops */
5616   AOP_OP_2 (ic);
5617
5618   genCmp (right, left, ic, ifx, sign);
5619 }
5620
5621 /*-----------------------------------------------------------------*/
5622 /* genCmpLt - less than comparisons                                */
5623 /*-----------------------------------------------------------------*/
5624 static void
5625 genCmpLt (iCode * ic, iCode * ifx)
5626 {
5627   operand *left, *right;
5628   sym_link *letype, *retype;
5629   int sign;
5630
5631   D (emitcode (";", "genCmpLt "););
5632
5633   left = IC_LEFT (ic);
5634   right = IC_RIGHT (ic);
5635
5636   letype = getSpec (operandType (left));
5637   retype = getSpec (operandType (right));
5638   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5639
5640   /* assign the left & right amsops */
5641   AOP_OP_2 (ic);
5642
5643   genCmp (left, right, ic, ifx, sign);
5644 }
5645
5646 /*-----------------------------------------------------------------*/
5647 /* gencjneshort - compare and jump if not equal                    */
5648 /*-----------------------------------------------------------------*/
5649 static void
5650 gencjneshort (operand * left, operand * right, symbol * lbl)
5651 {
5652   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5653   int offset = 0;
5654   unsigned long lit = 0L;
5655
5656   D (emitcode (";", "gencjneshort");
5657     );
5658
5659   /* if the left side is a literal or
5660      if the right is in a pointer register and left
5661      is not */
5662   if ((AOP_TYPE (left) == AOP_LIT) ||
5663       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5664     {
5665       operand *t = right;
5666       right = left;
5667       left = t;
5668     }
5669
5670   if (AOP_TYPE (right) == AOP_LIT)
5671     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5672
5673   if (opIsGptr (left) || opIsGptr (right))
5674     {
5675       /* We are comparing a generic pointer to something.
5676        * Exclude the generic type byte from the comparison.
5677        */
5678       size--;
5679       D (emitcode (";", "cjneshort: generic ptr special case."););
5680     }
5681
5682
5683   /* if the right side is a literal then anything goes */
5684   if (AOP_TYPE (right) == AOP_LIT &&
5685       AOP_TYPE (left) != AOP_DIR)
5686     {
5687       while (size--)
5688         {
5689           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5690           emitcode ("cjne", "a,%s,!tlabel",
5691                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5692                     lbl->key + 100);
5693           offset++;
5694         }
5695     }
5696
5697   /* if the right side is in a register or in direct space or
5698      if the left is a pointer register & right is not */
5699   else if (AOP_TYPE (right) == AOP_REG ||
5700            AOP_TYPE (right) == AOP_DIR ||
5701            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5702            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5703     {
5704       while (size--)
5705         {
5706           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5707           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5708               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5709             emitcode ("jnz", "!tlabel", lbl->key + 100);
5710           else
5711             emitcode ("cjne", "a,%s,!tlabel",
5712                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5713                       lbl->key + 100);
5714           offset++;
5715         }
5716     }
5717   else
5718     {
5719       /* right is a pointer reg need both a & b */
5720       while (size--)
5721         {
5722           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5723           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5724           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5725           offset++;
5726         }
5727     }
5728 }
5729
5730 /*-----------------------------------------------------------------*/
5731 /* gencjne - compare and jump if not equal                         */
5732 /*-----------------------------------------------------------------*/
5733 static void
5734 gencjne (operand * left, operand * right, symbol * lbl)
5735 {
5736   symbol *tlbl = newiTempLabel (NULL);
5737
5738   D (emitcode (";", "gencjne");
5739     );
5740
5741   gencjneshort (left, right, lbl);
5742
5743   emitcode ("mov", "a,%s", one);
5744   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5745   emitcode ("", "!tlabeldef", lbl->key + 100);
5746   emitcode ("clr", "a");
5747   emitcode ("", "!tlabeldef", tlbl->key + 100);
5748 }
5749
5750 /*-----------------------------------------------------------------*/
5751 /* genCmpEq - generates code for equal to                          */
5752 /*-----------------------------------------------------------------*/
5753 static void
5754 genCmpEq (iCode * ic, iCode * ifx)
5755 {
5756   operand *left, *right, *result;
5757
5758   D (emitcode (";", "genCmpEq ");
5759     );
5760
5761   AOP_OP_2 (ic);
5762   AOP_SET_LOCALS (ic);
5763
5764   /* if literal, literal on the right or
5765      if the right is in a pointer register and left
5766      is not */
5767   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5768       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5769     {
5770       operand *t = IC_RIGHT (ic);
5771       IC_RIGHT (ic) = IC_LEFT (ic);
5772       IC_LEFT (ic) = t;
5773     }
5774
5775   if (ifx &&                    /* !AOP_SIZE(result) */
5776       OP_SYMBOL (result) &&
5777       OP_SYMBOL (result)->regType == REG_CND)
5778     {
5779       symbol *tlbl;
5780       /* if they are both bit variables */
5781       if (AOP_TYPE (left) == AOP_CRY &&
5782           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5783         {
5784           if (AOP_TYPE (right) == AOP_LIT)
5785             {
5786               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5787               if (lit == 0L)
5788                 {
5789                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5790                   emitcode ("cpl", "c");
5791                 }
5792               else if (lit == 1L)
5793                 {
5794                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5795                 }
5796               else
5797                 {
5798                   emitcode ("clr", "c");
5799                 }
5800               /* AOP_TYPE(right) == AOP_CRY */
5801             }
5802           else
5803             {
5804               symbol *lbl = newiTempLabel (NULL);
5805               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5806               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5807               emitcode ("cpl", "c");
5808               emitcode ("", "!tlabeldef", (lbl->key + 100));
5809             }
5810           /* if true label then we jump if condition
5811              supplied is true */
5812           tlbl = newiTempLabel (NULL);
5813           if (IC_TRUE (ifx))
5814             {
5815               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5816               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5817             }
5818           else
5819             {
5820               emitcode ("jc", "!tlabel", tlbl->key + 100);
5821               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5822             }
5823           emitcode ("", "!tlabeldef", tlbl->key + 100);
5824         }
5825       else
5826         {
5827           tlbl = newiTempLabel (NULL);
5828           gencjneshort (left, right, tlbl);
5829           if (IC_TRUE (ifx))
5830             {
5831               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5832               emitcode ("", "!tlabeldef", tlbl->key + 100);
5833             }
5834           else
5835             {
5836               symbol *lbl = newiTempLabel (NULL);
5837               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5838               emitcode ("", "!tlabeldef", tlbl->key + 100);
5839               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5840               emitcode ("", "!tlabeldef", lbl->key + 100);
5841             }
5842         }
5843       /* mark the icode as generated */
5844       ifx->generated = 1;
5845
5846       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5847       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5848       return;
5849     }
5850
5851   /* if they are both bit variables */
5852   if (AOP_TYPE (left) == AOP_CRY &&
5853       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5854     {
5855       if (AOP_TYPE (right) == AOP_LIT)
5856         {
5857           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5858           if (lit == 0L)
5859             {
5860               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5861               emitcode ("cpl", "c");
5862             }
5863           else if (lit == 1L)
5864             {
5865               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5866             }
5867           else
5868             {
5869               emitcode ("clr", "c");
5870             }
5871           /* AOP_TYPE(right) == AOP_CRY */
5872         }
5873       else
5874         {
5875           symbol *lbl = newiTempLabel (NULL);
5876           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5877           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5878           emitcode ("cpl", "c");
5879           emitcode ("", "!tlabeldef", (lbl->key + 100));
5880         }
5881
5882       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5883       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5884
5885       aopOp (result, ic, TRUE, FALSE);
5886
5887       /* c = 1 if egal */
5888       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5889         {
5890           outBitC (result);
5891           goto release;
5892         }
5893       if (ifx)
5894         {
5895           genIfxJump (ifx, "c");
5896           goto release;
5897         }
5898       /* if the result is used in an arithmetic operation
5899          then put the result in place */
5900       outBitC (result);
5901     }
5902   else
5903     {
5904       gencjne (left, right, newiTempLabel (NULL));
5905
5906       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5907       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5908
5909       aopOp (result, ic, TRUE, FALSE);
5910
5911       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5912         {
5913           aopPut (AOP (result), "a", 0);
5914           goto release;
5915         }
5916       if (ifx)
5917         {
5918           genIfxJump (ifx, "a");
5919           goto release;
5920         }
5921       /* if the result is used in an arithmetic operation
5922          then put the result in place */
5923       if (AOP_TYPE (result) != AOP_CRY)
5924         outAcc (result);
5925       /* leave the result in acc */
5926     }
5927
5928 release:
5929   freeAsmop (result, NULL, ic, TRUE);
5930 }
5931
5932 /*-----------------------------------------------------------------*/
5933 /* ifxForOp - returns the icode containing the ifx for operand     */
5934 /*-----------------------------------------------------------------*/
5935 static iCode *
5936 ifxForOp (operand * op, iCode * ic)
5937 {
5938   /* if true symbol then needs to be assigned */
5939   if (IS_TRUE_SYMOP (op))
5940     return NULL;
5941
5942   /* if this has register type condition and
5943      the next instruction is ifx with the same operand
5944      and live to of the operand is upto the ifx only then */
5945   if (ic->next &&
5946       ic->next->op == IFX &&
5947       IC_COND (ic->next)->key == op->key &&
5948       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5949     return ic->next;
5950
5951   return NULL;
5952 }
5953 /*-----------------------------------------------------------------*/
5954 /* hasInc - operand is incremented before any other use            */
5955 /*-----------------------------------------------------------------*/
5956 static iCode *
5957 hasInc (operand *op, iCode *ic, int osize)
5958 {
5959   sym_link *type = operandType(op);
5960   sym_link *retype = getSpec (type);
5961   iCode *lic = ic->next;
5962   int isize ;
5963   
5964   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5965   if (!IS_SYMOP(op)) return NULL;
5966
5967   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5968   if (IS_AGGREGATE(type->next)) return NULL;
5969   if (osize != (isize = getSize(type->next))) return NULL;
5970
5971   while (lic) {
5972       /* if operand of the form op = op + <sizeof *op> */
5973       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5974           isOperandEqual(IC_RESULT(lic),op) && 
5975           isOperandLiteral(IC_RIGHT(lic)) &&
5976           operandLitValue(IC_RIGHT(lic)) == isize) {
5977           return lic;
5978       }
5979       /* if the operand used or deffed */
5980       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5981           return NULL;
5982       }
5983       /* if GOTO or IFX */
5984       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5985       lic = lic->next;
5986   }
5987   return NULL;
5988 }
5989
5990 /*-----------------------------------------------------------------*/
5991 /* genAndOp - for && operation                                     */
5992 /*-----------------------------------------------------------------*/
5993 static void
5994 genAndOp (iCode * ic)
5995 {
5996   operand *left, *right, *result;
5997   symbol *tlbl;
5998
5999   D (emitcode (";", "genAndOp "););
6000
6001   /* note here that && operations that are in an
6002      if statement are taken away by backPatchLabels
6003      only those used in arthmetic operations remain */
6004   AOP_OP_2 (ic);
6005   AOP_SET_LOCALS (ic);
6006
6007   /* if both are bit variables */
6008   if (AOP_TYPE (left) == AOP_CRY &&
6009       AOP_TYPE (right) == AOP_CRY)
6010     {
6011       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6012       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6013       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6014       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6015   
6016       aopOp (result,ic,FALSE, FALSE);
6017       outBitC (result);
6018     }
6019   else
6020     {
6021       tlbl = newiTempLabel (NULL);
6022       toBoolean (left);
6023       emitcode ("jz", "!tlabel", tlbl->key + 100);
6024       toBoolean (right);
6025       emitcode ("", "!tlabeldef", tlbl->key + 100);
6026       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6027       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6028   
6029       aopOp (result,ic,FALSE, FALSE);
6030       outBitAcc (result);
6031     }
6032     freeAsmop (result, NULL, ic, TRUE);
6033 }
6034
6035
6036 /*-----------------------------------------------------------------*/
6037 /* genOrOp - for || operation                                      */
6038 /*-----------------------------------------------------------------*/
6039 static void
6040 genOrOp (iCode * ic)
6041 {
6042   operand *left, *right, *result;
6043   symbol *tlbl;
6044
6045   D (emitcode (";", "genOrOp "););
6046
6047   /* note here that || operations that are in an
6048      if statement are taken away by backPatchLabels
6049      only those used in arthmetic operations remain */
6050   AOP_OP_2 (ic);
6051   AOP_SET_LOCALS (ic);
6052
6053   /* if both are bit variables */
6054   if (AOP_TYPE (left) == AOP_CRY &&
6055       AOP_TYPE (right) == AOP_CRY)
6056     {
6057       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6058       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6059       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6060       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6061   
6062       aopOp (result,ic,FALSE, FALSE);
6063       
6064       outBitC (result);
6065     }
6066   else
6067     {
6068       tlbl = newiTempLabel (NULL);
6069       toBoolean (left);
6070       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6071       toBoolean (right);
6072       emitcode ("", "!tlabeldef", tlbl->key + 100);
6073       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6074       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6075   
6076       aopOp (result,ic,FALSE, FALSE);
6077       
6078       outBitAcc (result);
6079     }
6080
6081   freeAsmop (result, NULL, ic, TRUE);
6082 }
6083
6084 /*-----------------------------------------------------------------*/
6085 /* isLiteralBit - test if lit == 2^n                               */
6086 /*-----------------------------------------------------------------*/
6087 static int
6088 isLiteralBit (unsigned long lit)
6089 {
6090   unsigned long pw[32] =
6091   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6092    0x100L, 0x200L, 0x400L, 0x800L,
6093    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6094    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6095    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6096    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6097    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6098   int idx;
6099
6100   for (idx = 0; idx < 32; idx++)
6101     if (lit == pw[idx])
6102       return idx + 1;
6103   return 0;
6104 }
6105
6106 /*-----------------------------------------------------------------*/
6107 /* continueIfTrue -                                                */
6108 /*-----------------------------------------------------------------*/
6109 static void
6110 continueIfTrue (iCode * ic)
6111 {
6112   if (IC_TRUE (ic))
6113     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6114   ic->generated = 1;
6115 }
6116
6117 /*-----------------------------------------------------------------*/
6118 /* jmpIfTrue -                                                     */
6119 /*-----------------------------------------------------------------*/
6120 static void
6121 jumpIfTrue (iCode * ic)
6122 {
6123   if (!IC_TRUE (ic))
6124     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6125   ic->generated = 1;
6126 }
6127
6128 /*-----------------------------------------------------------------*/
6129 /* jmpTrueOrFalse -                                                */
6130 /*-----------------------------------------------------------------*/
6131 static void
6132 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6133 {
6134   // ugly but optimized by peephole
6135   if (IC_TRUE (ic))
6136     {
6137       symbol *nlbl = newiTempLabel (NULL);
6138       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6139       emitcode ("", "!tlabeldef", tlbl->key + 100);
6140       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6141       emitcode ("", "!tlabeldef", nlbl->key + 100);
6142     }
6143   else
6144     {
6145       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6146       emitcode ("", "!tlabeldef", tlbl->key + 100);
6147     }
6148   ic->generated = 1;
6149 }
6150
6151 // Generate code to perform a bit-wise logic operation
6152 // on two operands in far space (assumed to already have been 
6153 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6154 // in far space. This requires pushing the result on the stack
6155 // then popping it into the result.
6156 static void
6157 genFarFarLogicOp(iCode *ic, char *logicOp)
6158 {
6159       int size, resultSize, compSize;
6160       int offset = 0;
6161       
6162       TR_AP("#5");
6163       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6164       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6165                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6166       
6167       _startLazyDPSEvaluation();
6168       for (size = compSize; (size--); offset++)
6169       {
6170           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6171           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6172           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6173           
6174           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6175           emitcode ("push", "acc");
6176       }
6177       _endLazyDPSEvaluation();
6178      
6179       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6180       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6181       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6182      
6183       resultSize = AOP_SIZE(IC_RESULT(ic));
6184
6185       ADJUST_PUSHED_RESULT(compSize, resultSize);
6186
6187       _startLazyDPSEvaluation();
6188       while (compSize--)
6189       {
6190           emitcode ("pop", "acc");
6191           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6192       }
6193       _endLazyDPSEvaluation();
6194       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6195 }
6196
6197
6198 /*-----------------------------------------------------------------*/
6199 /* genAnd  - code for and                                          */
6200 /*-----------------------------------------------------------------*/
6201 static void
6202 genAnd (iCode * ic, iCode * ifx)
6203 {
6204   operand *left, *right, *result;
6205   int size, offset = 0;
6206   unsigned long lit = 0L;
6207   int bytelit;
6208   char buff[10];
6209   bool pushResult;
6210
6211   D (emitcode (";", "genAnd "););
6212
6213   AOP_OP_3_NOFATAL (ic, pushResult);
6214   AOP_SET_LOCALS (ic);
6215
6216   if (pushResult)
6217   {
6218       genFarFarLogicOp(ic, "anl");
6219       return;
6220   }  
6221
6222 #ifdef DEBUG_TYPE
6223   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6224             AOP_TYPE (result),
6225             AOP_TYPE (left), AOP_TYPE (right));
6226   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6227             AOP_SIZE (result),
6228             AOP_SIZE (left), AOP_SIZE (right));
6229 #endif
6230
6231   /* if left is a literal & right is not then exchange them */
6232   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6233 #ifdef LOGIC_OPS_BROKEN      
6234     ||  AOP_NEEDSACC (left)
6235 #endif
6236     )
6237     {
6238       operand *tmp = right;
6239       right = left;
6240       left = tmp;
6241     }
6242
6243   /* if result = right then exchange them */
6244   if (sameRegs (AOP (result), AOP (right)))
6245     {
6246       operand *tmp = right;
6247       right = left;
6248       left = tmp;
6249     }
6250
6251   /* if right is bit then exchange them */
6252   if (AOP_TYPE (right) == AOP_CRY &&
6253       AOP_TYPE (left) != AOP_CRY)
6254     {
6255       operand *tmp = right;
6256       right = left;
6257       left = tmp;
6258     }
6259   if (AOP_TYPE (right) == AOP_LIT)
6260     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6261
6262   size = AOP_SIZE (result);
6263
6264   // if(bit & yy)
6265   // result = bit & yy;
6266   if (AOP_TYPE (left) == AOP_CRY)
6267     {
6268       // c = bit & literal;
6269       if (AOP_TYPE (right) == AOP_LIT)
6270         {
6271           if (lit & 1)
6272             {
6273               if (size && sameRegs (AOP (result), AOP (left)))
6274                 // no change
6275                 goto release;
6276               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6277             }
6278           else
6279             {
6280               // bit(result) = 0;
6281               if (size && (AOP_TYPE (result) == AOP_CRY))
6282                 {
6283                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6284                   goto release;
6285                 }
6286               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6287                 {
6288                   jumpIfTrue (ifx);
6289                   goto release;
6290                 }
6291               emitcode ("clr", "c");
6292             }
6293         }
6294       else
6295         {
6296           if (AOP_TYPE (right) == AOP_CRY)
6297             {
6298               // c = bit & bit;
6299               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6300               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6301             }
6302           else
6303             {
6304               // c = bit & val;
6305               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6306               // c = lsb
6307               emitcode ("rrc", "a");
6308               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6309             }
6310         }
6311       // bit = c
6312       // val = c
6313       if (size)
6314         outBitC (result);
6315       // if(bit & ...)
6316       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6317         genIfxJump (ifx, "c");
6318       goto release;
6319     }
6320
6321   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6322   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6323   if ((AOP_TYPE (right) == AOP_LIT) &&
6324       (AOP_TYPE (result) == AOP_CRY) &&
6325       (AOP_TYPE (left) != AOP_CRY))
6326     {
6327       int posbit = isLiteralBit (lit);
6328       /* left &  2^n */
6329       if (posbit)
6330         {
6331           posbit--;
6332           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6333           // bit = left & 2^n
6334           if (size)
6335             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6336           // if(left &  2^n)
6337           else
6338             {
6339               if (ifx)
6340                 {
6341                   SNPRINTF (buff, sizeof(buff), 
6342                             "acc.%d", posbit & 0x07);
6343                   genIfxJump (ifx, buff);
6344                 }
6345               else 
6346                   {
6347                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6348                   }
6349               goto release;
6350             }
6351         }
6352       else
6353         {
6354           symbol *tlbl = newiTempLabel (NULL);
6355           int sizel = AOP_SIZE (left);
6356           if (size)
6357             emitcode ("setb", "c");
6358           while (sizel--)
6359             {
6360               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6361                 {
6362                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6363                   // byte ==  2^n ?
6364                   if ((posbit = isLiteralBit (bytelit)) != 0)
6365                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6366                   else
6367                     {
6368                       if (bytelit != 0x0FFL)
6369                         emitcode ("anl", "a,%s",
6370                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6371                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6372                     }
6373                 }
6374               offset++;
6375             }
6376           // bit = left & literal
6377           if (size)
6378             {
6379               emitcode ("clr", "c");
6380               emitcode ("", "!tlabeldef", tlbl->key + 100);
6381             }
6382           // if(left & literal)
6383           else
6384             {
6385               if (ifx)
6386                 jmpTrueOrFalse (ifx, tlbl);
6387               goto release;
6388             }
6389         }
6390       outBitC (result);
6391       goto release;
6392     }
6393
6394   /* if left is same as result */
6395   if (sameRegs (AOP (result), AOP (left)))
6396     {
6397       for (; size--; offset++)
6398         {
6399           if (AOP_TYPE (right) == AOP_LIT)
6400             {
6401               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6402                 continue;
6403               else if (bytelit == 0)
6404                 aopPut (AOP (result), zero, offset);
6405               else if (IS_AOP_PREG (result))
6406                 {
6407                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6408                   emitcode ("anl", "a,%s",
6409                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6410                   aopPut (AOP (result), "a", offset);
6411                 }
6412               else
6413                 emitcode ("anl", "%s,%s",
6414                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6415                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6416             }
6417           else
6418             {
6419               if (AOP_TYPE (left) == AOP_ACC)
6420                 emitcode ("anl", "a,%s",
6421                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6422               else
6423                 {
6424                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6425                   if (IS_AOP_PREG (result))
6426                     {
6427                       emitcode ("anl", "a,%s",
6428                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6429                       aopPut (AOP (result), "a", offset);
6430                     }
6431                   else
6432                     emitcode ("anl", "%s,a",
6433                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6434                 }
6435             }
6436         }
6437     }
6438   else
6439     {
6440       // left & result in different registers
6441       if (AOP_TYPE (result) == AOP_CRY)
6442         {
6443           // result = bit
6444           // if(size), result in bit
6445           // if(!size && ifx), conditional oper: if(left & right)
6446           symbol *tlbl = newiTempLabel (NULL);
6447           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6448           if (size)
6449             emitcode ("setb", "c");
6450           while (sizer--)
6451             {
6452               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6453                 emitcode ("anl", "a,%s",
6454                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6455               } else {
6456                 if (AOP_TYPE(left)==AOP_ACC) {
6457                   emitcode("mov", "b,a");
6458                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6459                   emitcode("anl", "a,b");
6460                 }else {
6461                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6462                   emitcode ("anl", "a,%s",
6463                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6464                 }
6465               }
6466               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6467               offset++;
6468             }
6469           if (size)
6470             {
6471               CLRC;
6472               emitcode ("", "!tlabeldef", tlbl->key + 100);
6473               outBitC (result);
6474             }
6475           else if (ifx)
6476             jmpTrueOrFalse (ifx, tlbl);
6477         }
6478       else
6479         {
6480           for (; (size--); offset++)
6481             {
6482               // normal case
6483               // result = left & right
6484               if (AOP_TYPE (right) == AOP_LIT)
6485                 {
6486                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6487                     {
6488                       aopPut (AOP (result),
6489                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6490                               offset);
6491                       continue;
6492                     }
6493                   else if (bytelit == 0)
6494                     {
6495                       aopPut (AOP (result), zero, offset);
6496                       continue;
6497                     }
6498                   D (emitcode (";", "better literal AND."););
6499                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6500                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6501                                                     FALSE, FALSE, DP2_RESULT_REG));
6502
6503                 }
6504               else
6505                 {
6506                   // faster than result <- left, anl result,right
6507                   // and better if result is SFR
6508                   if (AOP_TYPE (left) == AOP_ACC)
6509                     {
6510                       emitcode ("anl", "a,%s", 
6511                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6512                     }
6513                   else
6514                     {
6515                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6516                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6517                       {
6518                           emitcode("mov", "b,a");
6519                           rOp = "b";
6520                       }
6521                         
6522                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6523                       emitcode ("anl", "a,%s", rOp);
6524                     }                   
6525                 }
6526               aopPut (AOP (result), "a", offset);
6527             }
6528         }
6529     }
6530
6531 release:
6532   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6533   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6534   freeAsmop (result, NULL, ic, TRUE);
6535 }
6536
6537
6538 /*-----------------------------------------------------------------*/
6539 /* genOr  - code for or                                            */
6540 /*-----------------------------------------------------------------*/
6541 static void
6542 genOr (iCode * ic, iCode * ifx)
6543 {
6544   operand *left, *right, *result;
6545   int size, offset = 0;
6546   unsigned long lit = 0L;
6547   bool     pushResult;
6548
6549   D (emitcode (";", "genOr "););
6550
6551   AOP_OP_3_NOFATAL (ic, pushResult);
6552   AOP_SET_LOCALS (ic);
6553
6554   if (pushResult)
6555   {
6556       genFarFarLogicOp(ic, "orl");
6557       return;
6558   }
6559
6560
6561 #ifdef DEBUG_TYPE
6562   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6563             AOP_TYPE (result),
6564             AOP_TYPE (left), AOP_TYPE (right));
6565   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6566             AOP_SIZE (result),
6567             AOP_SIZE (left), AOP_SIZE (right));
6568 #endif
6569
6570   /* if left is a literal & right is not then exchange them */
6571   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6572 #ifdef LOGIC_OPS_BROKEN
6573    || AOP_NEEDSACC (left) // I think this is a net loss now.
6574 #endif      
6575       )
6576     {
6577       operand *tmp = right;
6578       right = left;
6579       left = tmp;
6580     }
6581
6582   /* if result = right then exchange them */
6583   if (sameRegs (AOP (result), AOP (right)))
6584     {
6585       operand *tmp = right;
6586       right = left;
6587       left = tmp;
6588     }
6589
6590   /* if right is bit then exchange them */
6591   if (AOP_TYPE (right) == AOP_CRY &&
6592       AOP_TYPE (left) != AOP_CRY)
6593     {
6594       operand *tmp = right;
6595       right = left;
6596       left = tmp;
6597     }
6598   if (AOP_TYPE (right) == AOP_LIT)
6599     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6600
6601   size = AOP_SIZE (result);
6602
6603   // if(bit | yy)
6604   // xx = bit | yy;
6605   if (AOP_TYPE (left) == AOP_CRY)
6606     {
6607       if (AOP_TYPE (right) == AOP_LIT)
6608         {
6609           // c = bit & literal;
6610           if (lit)
6611             {
6612               // lit != 0 => result = 1
6613               if (AOP_TYPE (result) == AOP_CRY)
6614                 {
6615                   if (size)
6616                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6617                   else if (ifx)
6618                     continueIfTrue (ifx);
6619                   goto release;
6620                 }
6621               emitcode ("setb", "c");
6622             }
6623           else
6624             {
6625               // lit == 0 => result = left
6626               if (size && sameRegs (AOP (result), AOP (left)))
6627                 goto release;
6628               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6629             }
6630         }
6631       else
6632         {
6633           if (AOP_TYPE (right) == AOP_CRY)
6634             {
6635               // c = bit | bit;
6636               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6637               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6638             }
6639           else
6640             {
6641               // c = bit | val;
6642               symbol *tlbl = newiTempLabel (NULL);
6643               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6644                 emitcode ("setb", "c");
6645               emitcode ("jb", "%s,!tlabel",
6646                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6647               toBoolean (right);
6648               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6649               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6650                 {
6651                   jmpTrueOrFalse (ifx, tlbl);
6652                   goto release;
6653                 }
6654               else
6655                 {
6656                   CLRC;
6657                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6658                 }
6659             }
6660         }
6661       // bit = c
6662       // val = c
6663       if (size)
6664         outBitC (result);
6665       // if(bit | ...)
6666       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6667            genIfxJump (ifx, "c");
6668       goto release;
6669     }
6670
6671   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6672   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6673   if ((AOP_TYPE (right) == AOP_LIT) &&
6674       (AOP_TYPE (result) == AOP_CRY) &&
6675       (AOP_TYPE (left) != AOP_CRY))
6676     {
6677       if (lit)
6678         {
6679           // result = 1
6680           if (size)
6681             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6682           else
6683             continueIfTrue (ifx);
6684           goto release;
6685         }
6686       else
6687         {
6688           // lit = 0, result = boolean(left)
6689           if (size)
6690             emitcode ("setb", "c");
6691           toBoolean (right);
6692           if (size)
6693             {
6694               symbol *tlbl = newiTempLabel (NULL);
6695               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6696               CLRC;
6697               emitcode ("", "!tlabeldef", tlbl->key + 100);
6698             }
6699           else
6700             {
6701               genIfxJump (ifx, "a");
6702               goto release;
6703             }
6704         }
6705       outBitC (result);
6706       goto release;
6707     }
6708
6709   /* if left is same as result */
6710   if (sameRegs (AOP (result), AOP (left)))
6711     {
6712       for (; size--; offset++)
6713         {
6714           if (AOP_TYPE (right) == AOP_LIT)
6715             {
6716               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6717                 {
6718                   continue;
6719                 }
6720               else
6721                 {
6722                   if (IS_AOP_PREG (left))
6723                     {
6724                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6725                       emitcode ("orl", "a,%s",
6726                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6727                       aopPut (AOP (result), "a", offset);
6728                     }
6729                   else
6730                     {
6731                       emitcode ("orl", "%s,%s",
6732                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6733                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6734                     }
6735                 }
6736             }
6737           else
6738             {
6739               if (AOP_TYPE (left) == AOP_ACC)
6740                 {
6741                   emitcode ("orl", "a,%s",
6742                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6743                 }
6744               else
6745                 {
6746                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6747                   if (IS_AOP_PREG (left))
6748                     {
6749                       emitcode ("orl", "a,%s", 
6750                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6751                       aopPut (AOP (result), "a", offset);
6752                     }
6753                   else
6754                     {
6755                       emitcode ("orl", "%s,a",
6756                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6757                     }
6758                 }
6759             }
6760         }
6761     }
6762   else
6763     {
6764       // left & result in different registers
6765       if (AOP_TYPE (result) == AOP_CRY)
6766         {
6767           // result = bit
6768           // if(size), result in bit
6769           // if(!size && ifx), conditional oper: if(left | right)
6770           symbol *tlbl = newiTempLabel (NULL);
6771           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6772           if (size)
6773             emitcode ("setb", "c");
6774           while (sizer--)
6775             {
6776               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6777                 emitcode ("orl", "a,%s",
6778                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6779               } else {
6780                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6781                 emitcode ("orl", "a,%s",
6782                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6783               }
6784               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6785               offset++;
6786             }
6787           if (size)
6788             {
6789               CLRC;
6790               emitcode ("", "!tlabeldef", tlbl->key + 100);
6791               outBitC (result);
6792             }
6793           else if (ifx)
6794             jmpTrueOrFalse (ifx, tlbl);
6795         }
6796       else
6797         {
6798             _startLazyDPSEvaluation();
6799           for (; (size--); offset++)
6800             {
6801               // normal case
6802               // result = left & right
6803               if (AOP_TYPE (right) == AOP_LIT)
6804                 {
6805                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6806                     {
6807                       aopPut (AOP (result),
6808                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6809                               offset);
6810                       continue;
6811                     }
6812                   D (emitcode (";", "better literal OR."););
6813                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6814                   emitcode ("orl", "a, %s",
6815                             aopGet (AOP (right), offset,
6816                                     FALSE, FALSE, DP2_RESULT_REG));
6817
6818                 }
6819               else
6820                 {
6821                   // faster than result <- left, anl result,right
6822                   // and better if result is SFR
6823                   if (AOP_TYPE (left) == AOP_ACC)
6824                     {
6825                       emitcode ("orl", "a,%s",
6826                                 aopGet (AOP (right), offset,
6827                                         FALSE, FALSE, DP2_RESULT_REG));
6828                     }
6829                   else
6830                     {
6831                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6832                         
6833                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6834                       {
6835                           emitcode("mov", "b,a");
6836                           rOp = "b";
6837                       }
6838                         
6839                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6840                       emitcode ("orl", "a,%s", rOp);
6841                     }
6842                 }
6843               aopPut (AOP (result), "a", offset);
6844             }
6845             _endLazyDPSEvaluation();
6846         }
6847     }
6848
6849 release:
6850   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6851   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6852   freeAsmop (result, NULL, ic, TRUE);
6853 }
6854
6855 /*-----------------------------------------------------------------*/
6856 /* genXor - code for xclusive or                                   */
6857 /*-----------------------------------------------------------------*/
6858 static void
6859 genXor (iCode * ic, iCode * ifx)
6860 {
6861   operand *left, *right, *result;
6862   int size, offset = 0;
6863   unsigned long lit = 0L;
6864   bool pushResult;
6865
6866   D (emitcode (";", "genXor "););
6867
6868   AOP_OP_3_NOFATAL (ic, pushResult);
6869   AOP_SET_LOCALS (ic);
6870
6871   if (pushResult)
6872   {
6873       genFarFarLogicOp(ic, "xrl");
6874       return;
6875   }  
6876
6877 #ifdef DEBUG_TYPE
6878   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6879             AOP_TYPE (result),
6880             AOP_TYPE (left), AOP_TYPE (right));
6881   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6882             AOP_SIZE (result),
6883             AOP_SIZE (left), AOP_SIZE (right));
6884 #endif
6885
6886   /* if left is a literal & right is not ||
6887      if left needs acc & right does not */
6888   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6889 #ifdef LOGIC_OPS_BROKEN      
6890       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6891 #endif
6892      )
6893     {
6894       operand *tmp = right;
6895       right = left;
6896       left = tmp;
6897     }
6898
6899   /* if result = right then exchange them */
6900   if (sameRegs (AOP (result), AOP (right)))
6901     {
6902       operand *tmp = right;
6903       right = left;
6904       left = tmp;
6905     }
6906
6907   /* if right is bit then exchange them */
6908   if (AOP_TYPE (right) == AOP_CRY &&
6909       AOP_TYPE (left) != AOP_CRY)
6910     {
6911       operand *tmp = right;
6912       right = left;
6913       left = tmp;
6914     }
6915   if (AOP_TYPE (right) == AOP_LIT)
6916     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6917
6918   size = AOP_SIZE (result);
6919
6920   // if(bit ^ yy)
6921   // xx = bit ^ yy;
6922   if (AOP_TYPE (left) == AOP_CRY)
6923     {
6924       if (AOP_TYPE (right) == AOP_LIT)
6925         {
6926           // c = bit & literal;
6927           if (lit >> 1)
6928             {
6929               // lit>>1  != 0 => result = 1
6930               if (AOP_TYPE (result) == AOP_CRY)
6931                 {
6932                   if (size)
6933                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6934                   else if (ifx)
6935                     continueIfTrue (ifx);
6936                   goto release;
6937                 }
6938               emitcode ("setb", "c");
6939             }
6940           else
6941             {
6942               // lit == (0 or 1)
6943               if (lit == 0)
6944                 {
6945                   // lit == 0, result = left
6946                   if (size && sameRegs (AOP (result), AOP (left)))
6947                     goto release;
6948                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6949                 }
6950               else
6951                 {
6952                   // lit == 1, result = not(left)
6953                   if (size && sameRegs (AOP (result), AOP (left)))
6954                     {
6955                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6956                       goto release;
6957                     }
6958                   else
6959                     {
6960                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6961                       emitcode ("cpl", "c");
6962                     }
6963                 }
6964             }
6965
6966         }
6967       else
6968         {
6969           // right != literal
6970           symbol *tlbl = newiTempLabel (NULL);
6971           if (AOP_TYPE (right) == AOP_CRY)
6972             {
6973               // c = bit ^ bit;
6974               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6975             }
6976           else
6977             {
6978               int sizer = AOP_SIZE (right);
6979               // c = bit ^ val
6980               // if val>>1 != 0, result = 1
6981               emitcode ("setb", "c");
6982               while (sizer)
6983                 {
6984                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6985                   if (sizer == 1)
6986                     // test the msb of the lsb
6987                     emitcode ("anl", "a,#!constbyte",0xfe);
6988                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6989                   sizer--;
6990                 }
6991               // val = (0,1)
6992               emitcode ("rrc", "a");
6993             }
6994           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6995           emitcode ("cpl", "c");
6996           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6997         }
6998       // bit = c
6999       // val = c
7000       if (size)
7001         outBitC (result);
7002       // if(bit | ...)
7003       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7004         genIfxJump (ifx, "c");
7005       goto release;
7006     }
7007
7008   if (sameRegs (AOP (result), AOP (left)))
7009     {
7010       /* if left is same as result */
7011       for (; size--; offset++)
7012         {
7013           if (AOP_TYPE (right) == AOP_LIT)
7014             {
7015               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7016                 continue;
7017               else if (IS_AOP_PREG (left))
7018                 {
7019                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7020                   emitcode ("xrl", "a,%s",
7021                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7022                   aopPut (AOP (result), "a", offset);
7023                 }
7024               else
7025                 emitcode ("xrl", "%s,%s",
7026                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7027                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7028             }
7029           else
7030             {
7031               if (AOP_TYPE (left) == AOP_ACC)
7032                 emitcode ("xrl", "a,%s",
7033                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7034               else
7035                 {
7036                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7037                   if (IS_AOP_PREG (left))
7038                     {
7039                       emitcode ("xrl", "a,%s",
7040                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7041                       aopPut (AOP (result), "a", offset);
7042                     }
7043                   else
7044                     emitcode ("xrl", "%s,a",
7045                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7046                 }
7047             }
7048         }
7049     }
7050   else
7051     {
7052       // left & result in different registers
7053       if (AOP_TYPE (result) == AOP_CRY)
7054         {
7055           // result = bit
7056           // if(size), result in bit
7057           // if(!size && ifx), conditional oper: if(left ^ right)
7058           symbol *tlbl = newiTempLabel (NULL);
7059           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7060                   
7061           if (size)
7062             emitcode ("setb", "c");
7063           while (sizer--)
7064             {
7065               if ((AOP_TYPE (right) == AOP_LIT) &&
7066                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7067                 {
7068                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7069                 }
7070               else
7071                 {
7072                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7073                     emitcode ("xrl", "a,%s",
7074                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7075                   } else {
7076                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7077                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7078                       {
7079                           emitcode("mov", "b,a");
7080                           rOp = "b";
7081                       }
7082                         
7083                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7084                       emitcode ("xrl", "a,%s", rOp);                  
7085                   }
7086                 }
7087               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7088               offset++;
7089             }
7090           if (size)
7091             {
7092               CLRC;
7093               emitcode ("", "!tlabeldef", tlbl->key + 100);
7094               outBitC (result);
7095             }
7096           else if (ifx)
7097             jmpTrueOrFalse (ifx, tlbl);
7098         }
7099       else
7100         {
7101         for (; (size--); offset++)
7102           {
7103             // normal case
7104             // result = left & right
7105             if (AOP_TYPE (right) == AOP_LIT)
7106               {
7107                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7108                   {
7109                     aopPut (AOP (result),
7110                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7111                             offset);
7112                     continue;
7113                   }
7114                 D (emitcode (";", "better literal XOR."););
7115                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7116                 emitcode ("xrl", "a, %s",
7117                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7118               }
7119             else
7120               {
7121                 // faster than result <- left, anl result,right
7122                 // and better if result is SFR
7123                 if (AOP_TYPE (left) == AOP_ACC)
7124                   {
7125                     emitcode ("xrl", "a,%s",
7126                               aopGet (AOP (right), offset,
7127                                       FALSE, FALSE, DP2_RESULT_REG));
7128                   }
7129                 else
7130                   {
7131                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7132                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7133                       {
7134                           emitcode("mov", "b,a");
7135                           rOp = "b";
7136                       }
7137                         
7138                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7139                       emitcode ("xrl", "a,%s", rOp);
7140                   }
7141               }
7142             aopPut (AOP (result), "a", offset);
7143           }
7144         }
7145         
7146     }
7147
7148 release:
7149   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7150   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7151   freeAsmop (result, NULL, ic, TRUE);
7152 }
7153
7154 /*-----------------------------------------------------------------*/
7155 /* genInline - write the inline code out                           */
7156 /*-----------------------------------------------------------------*/
7157 static void
7158 genInline (iCode * ic)
7159 {
7160   char *buffer, *bp, *bp1;
7161
7162   D (emitcode (";", "genInline "); );
7163
7164   _G.inLine += (!options.asmpeep);
7165
7166   buffer = Safe_strdup(IC_INLINE(ic));
7167   bp = buffer;
7168   bp1 = buffer;
7169
7170   /* emit each line as a code */
7171   while (*bp)
7172     {
7173       if (*bp == '\n')
7174         {
7175           *bp++ = '\0';
7176           emitcode (bp1, "");
7177           bp1 = bp;
7178         }
7179       else
7180         {
7181           if (*bp == ':')
7182             {
7183               bp++;
7184               *bp = '\0';
7185               bp++;
7186               emitcode (bp1, "");
7187               bp1 = bp;
7188             }
7189           else
7190             bp++;
7191         }
7192     }
7193   if (bp1 != bp)
7194     emitcode (bp1, "");
7195   /*     emitcode("",buffer); */
7196   _G.inLine -= (!options.asmpeep);
7197 }
7198
7199 /*-----------------------------------------------------------------*/
7200 /* genRRC - rotate right with carry                                */
7201 /*-----------------------------------------------------------------*/
7202 static void
7203 genRRC (iCode * ic)
7204 {
7205   operand *left, *result;
7206   int     size, offset;
7207
7208   D (emitcode (";", "genRRC "););
7209
7210   /* rotate right with carry */
7211   left = IC_LEFT (ic);
7212   result = IC_RESULT (ic);
7213   aopOp (left, ic, FALSE, FALSE);
7214   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7215
7216   /* move it to the result */
7217   size = AOP_SIZE (result);
7218   offset = size - 1;
7219   CLRC;
7220
7221   _startLazyDPSEvaluation ();
7222   while (size--)
7223     {
7224       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7225       emitcode ("rrc", "a");
7226       if (AOP_SIZE (result) > 1)
7227         aopPut (AOP (result), "a", offset--);
7228     }
7229   _endLazyDPSEvaluation ();
7230
7231   /* now we need to put the carry into the
7232      highest order byte of the result */
7233   if (AOP_SIZE (result) > 1)
7234     {
7235       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7236     }
7237   emitcode ("mov", "acc.7,c");
7238   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7239   freeAsmop (left, NULL, ic, TRUE);
7240   freeAsmop (result, NULL, ic, TRUE);
7241 }
7242
7243 /*-----------------------------------------------------------------*/
7244 /* genRLC - generate code for rotate left with carry               */
7245 /*-----------------------------------------------------------------*/
7246 static void
7247 genRLC (iCode * ic)
7248 {
7249   operand *left, *result;
7250   int size, offset;
7251   char *l;
7252
7253   D (emitcode (";", "genRLC "););
7254
7255   /* rotate right with carry */
7256   left = IC_LEFT (ic);
7257   result = IC_RESULT (ic);
7258   aopOp (left, ic, FALSE, FALSE);
7259   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7260
7261   /* move it to the result */
7262   size = AOP_SIZE (result);
7263   offset = 0;
7264   if (size--)
7265     {
7266       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7267       MOVA (l);
7268       emitcode ("add", "a,acc");
7269       if (AOP_SIZE (result) > 1)
7270         {
7271           aopPut (AOP (result), "a", offset++);
7272         }
7273
7274       _startLazyDPSEvaluation ();
7275       while (size--)
7276         {
7277           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7278           MOVA (l);
7279           emitcode ("rlc", "a");
7280           if (AOP_SIZE (result) > 1)
7281             aopPut (AOP (result), "a", offset++);
7282         }
7283       _endLazyDPSEvaluation ();
7284     }
7285   /* now we need to put the carry into the
7286      highest order byte of the result */
7287   if (AOP_SIZE (result) > 1)
7288     {
7289       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7290       MOVA (l);
7291     }
7292   emitcode ("mov", "acc.0,c");
7293   aopPut (AOP (result), "a", 0);
7294   freeAsmop (left, NULL, ic, TRUE);
7295   freeAsmop (result, NULL, ic, TRUE);
7296 }
7297
7298 /*-----------------------------------------------------------------*/
7299 /* genGetHbit - generates code get highest order bit               */
7300 /*-----------------------------------------------------------------*/
7301 static void
7302 genGetHbit (iCode * ic)
7303 {
7304   operand *left, *result;
7305   left = IC_LEFT (ic);
7306   result = IC_RESULT (ic);
7307   aopOp (left, ic, FALSE, FALSE);
7308   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7309
7310   D (emitcode (";", "genGetHbit "););
7311
7312   /* get the highest order byte into a */
7313   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7314   if (AOP_TYPE (result) == AOP_CRY)
7315     {
7316       emitcode ("rlc", "a");
7317       outBitC (result);
7318     }
7319   else
7320     {
7321       emitcode ("rl", "a");
7322       emitcode ("anl", "a,#1");
7323       outAcc (result);
7324     }
7325
7326
7327   freeAsmop (left, NULL, ic, TRUE);
7328   freeAsmop (result, NULL, ic, TRUE);
7329 }
7330
7331 /*-----------------------------------------------------------------*/
7332 /* AccRol - rotate left accumulator by known count                 */
7333 /*-----------------------------------------------------------------*/
7334 static void
7335 AccRol (int shCount)
7336 {
7337   shCount &= 0x0007;            // shCount : 0..7
7338
7339   switch (shCount)
7340     {
7341     case 0:
7342       break;
7343     case 1:
7344       emitcode ("rl", "a");
7345       break;
7346     case 2:
7347       emitcode ("rl", "a");
7348       emitcode ("rl", "a");
7349       break;
7350     case 3:
7351       emitcode ("swap", "a");
7352       emitcode ("rr", "a");
7353       break;
7354     case 4:
7355       emitcode ("swap", "a");
7356       break;
7357     case 5:
7358       emitcode ("swap", "a");
7359       emitcode ("rl", "a");
7360       break;
7361     case 6:
7362       emitcode ("rr", "a");
7363       emitcode ("rr", "a");
7364       break;
7365     case 7:
7366       emitcode ("rr", "a");
7367       break;
7368     }
7369 }
7370
7371 /*-----------------------------------------------------------------*/
7372 /* AccLsh - left shift accumulator by known count                  */
7373 /*-----------------------------------------------------------------*/
7374 static void
7375 AccLsh (int shCount)
7376 {
7377   if (shCount != 0)
7378     {
7379       if (shCount == 1)
7380         emitcode ("add", "a,acc");
7381       else if (shCount == 2)
7382         {
7383           emitcode ("add", "a,acc");
7384           emitcode ("add", "a,acc");
7385         }
7386       else
7387         {
7388           /* rotate left accumulator */
7389           AccRol (shCount);
7390           /* and kill the lower order bits */
7391           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7392         }
7393     }
7394 }
7395
7396 /*-----------------------------------------------------------------*/
7397 /* AccRsh - right shift accumulator by known count                 */
7398 /*-----------------------------------------------------------------*/
7399 static void
7400 AccRsh (int shCount)
7401 {
7402   if (shCount != 0)
7403     {
7404       if (shCount == 1)
7405         {
7406           CLRC;
7407           emitcode ("rrc", "a");
7408         }
7409       else
7410         {
7411           /* rotate right accumulator */
7412           AccRol (8 - shCount);
7413           /* and kill the higher order bits */
7414           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7415         }
7416     }
7417 }
7418
7419 #ifdef BETTER_LITERAL_SHIFT
7420 /*-----------------------------------------------------------------*/
7421 /* AccSRsh - signed right shift accumulator by known count                 */
7422 /*-----------------------------------------------------------------*/
7423 static void
7424 AccSRsh (int shCount)
7425 {
7426   symbol *tlbl;
7427   if (shCount != 0)
7428     {
7429       if (shCount == 1)
7430         {
7431           emitcode ("mov", "c,acc.7");
7432           emitcode ("rrc", "a");
7433         }
7434       else if (shCount == 2)
7435         {
7436           emitcode ("mov", "c,acc.7");
7437           emitcode ("rrc", "a");
7438           emitcode ("mov", "c,acc.7");
7439           emitcode ("rrc", "a");
7440         }
7441       else
7442         {
7443           tlbl = newiTempLabel (NULL);
7444           /* rotate right accumulator */
7445           AccRol (8 - shCount);
7446           /* and kill the higher order bits */
7447           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7448           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7449           emitcode ("orl", "a,#!constbyte",
7450                     (unsigned char) ~SRMask[shCount]);
7451           emitcode ("", "!tlabeldef", tlbl->key + 100);
7452         }
7453     }
7454 }
7455 #endif
7456
7457 #ifdef BETTER_LITERAL_SHIFT
7458 /*-----------------------------------------------------------------*/
7459 /* shiftR1Left2Result - shift right one byte from left to result   */
7460 /*-----------------------------------------------------------------*/
7461 static void
7462 shiftR1Left2Result (operand * left, int offl,
7463                     operand * result, int offr,
7464                     int shCount, int sign)
7465 {
7466   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7467   /* shift right accumulator */
7468   if (sign)
7469     AccSRsh (shCount);
7470   else
7471     AccRsh (shCount);
7472   aopPut (AOP (result), "a", offr);
7473 }
7474 #endif
7475
7476 #ifdef BETTER_LITERAL_SHIFT
7477 /*-----------------------------------------------------------------*/
7478 /* shiftL1Left2Result - shift left one byte from left to result    */
7479 /*-----------------------------------------------------------------*/
7480 static void
7481 shiftL1Left2Result (operand * left, int offl,
7482                     operand * result, int offr, int shCount)
7483 {
7484   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7485   /* shift left accumulator */
7486   AccLsh (shCount);
7487   aopPut (AOP (result), "a", offr);
7488 }
7489 #endif
7490
7491 #ifdef BETTER_LITERAL_SHIFT
7492 /*-----------------------------------------------------------------*/
7493 /* movLeft2Result - move byte from left to result                  */
7494 /*-----------------------------------------------------------------*/
7495 static void
7496 movLeft2Result (operand * left, int offl,
7497                 operand * result, int offr, int sign)
7498 {
7499   char *l;
7500   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7501   {
7502       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7503
7504       if (*l == '@' && (IS_AOP_PREG (result)))
7505       {
7506           emitcode ("mov", "a,%s", l);
7507           aopPut (AOP (result), "a", offr);
7508       }
7509       else
7510       {
7511           if (!sign)
7512           {
7513             aopPut (AOP (result), l, offr);
7514           }
7515           else
7516             {
7517               /* MSB sign in acc.7 ! */
7518               if (getDataSize (left) == offl + 1)
7519                 {
7520                   emitcode ("mov", "a,%s", l);
7521                   aopPut (AOP (result), "a", offr);
7522                 }
7523             }
7524       }
7525   }
7526 }
7527 #endif
7528
7529 #ifdef BETTER_LITERAL_SHIFT
7530 /*-----------------------------------------------------------------*/
7531 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7532 /*-----------------------------------------------------------------*/
7533 static void
7534 AccAXRrl1 (char *x)
7535 {
7536   emitcode ("rrc", "a");
7537   emitcode ("xch", "a,%s", x);
7538   emitcode ("rrc", "a");
7539   emitcode ("xch", "a,%s", x);
7540 }
7541 #endif
7542
7543 #ifdef BETTER_LITERAL_SHIFT
7544 //REMOVE ME!!!
7545 /*-----------------------------------------------------------------*/
7546 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7547 /*-----------------------------------------------------------------*/
7548 static void
7549 AccAXLrl1 (char *x)
7550 {
7551   emitcode ("xch", "a,%s", x);
7552   emitcode ("rlc", "a");
7553   emitcode ("xch", "a,%s", x);
7554   emitcode ("rlc", "a");
7555 }
7556 #endif
7557
7558 #ifdef BETTER_LITERAL_SHIFT
7559 /*-----------------------------------------------------------------*/
7560 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7561 /*-----------------------------------------------------------------*/
7562 static void
7563 AccAXLsh1 (char *x)
7564 {
7565   emitcode ("xch", "a,%s", x);
7566   emitcode ("add", "a,acc");
7567   emitcode ("xch", "a,%s", x);
7568   emitcode ("rlc", "a");
7569 }
7570 #endif
7571
7572 #ifdef BETTER_LITERAL_SHIFT
7573 /*-----------------------------------------------------------------*/
7574 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7575 /*-----------------------------------------------------------------*/
7576 static void
7577 AccAXLsh (char *x, int shCount)
7578 {
7579   switch (shCount)
7580     {
7581     case 0:
7582       break;
7583     case 1:
7584       AccAXLsh1 (x);
7585       break;
7586     case 2:
7587       AccAXLsh1 (x);
7588       AccAXLsh1 (x);
7589       break;
7590     case 3:
7591     case 4:
7592     case 5:                     // AAAAABBB:CCCCCDDD
7593
7594       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7595
7596       emitcode ("anl", "a,#!constbyte",
7597                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7598
7599       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7600
7601       AccRol (shCount);         // DDDCCCCC:BBB00000
7602
7603       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7604
7605       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7606
7607       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7608
7609       emitcode ("anl", "a,#!constbyte",
7610                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7611
7612       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7613
7614       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7615
7616       break;
7617     case 6:                     // AAAAAABB:CCCCCCDD
7618       emitcode ("anl", "a,#!constbyte",
7619                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7620       emitcode ("mov", "c,acc.0");      // c = B
7621       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7622 #if 0
7623       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7624       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7625 #else
7626       emitcode("rrc","a"); 
7627       emitcode("xch","a,%s", x); 
7628       emitcode("rrc","a"); 
7629       emitcode("mov","c,acc.0"); //<< get correct bit 
7630       emitcode("xch","a,%s", x); 
7631
7632       emitcode("rrc","a"); 
7633       emitcode("xch","a,%s", x); 
7634       emitcode("rrc","a"); 
7635       emitcode("xch","a,%s", x); 
7636 #endif
7637       break;
7638     case 7:                     // a:x <<= 7
7639
7640       emitcode ("anl", "a,#!constbyte",
7641                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7642
7643       emitcode ("mov", "c,acc.0");      // c = B
7644
7645       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7646
7647       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7648
7649       break;
7650     default:
7651       break;
7652     }
7653 }
7654 #endif
7655
7656 #ifdef BETTER_LITERAL_SHIFT
7657 //REMOVE ME!!!
7658 /*-----------------------------------------------------------------*/
7659 /* AccAXRsh - right shift a:x known count (0..7)                   */
7660 /*-----------------------------------------------------------------*/
7661 static void
7662 AccAXRsh (char *x, int shCount)
7663 {
7664   switch (shCount)
7665     {
7666     case 0:
7667       break;
7668     case 1:
7669       CLRC;
7670       AccAXRrl1 (x);            // 0->a:x
7671
7672       break;
7673     case 2:
7674       CLRC;
7675       AccAXRrl1 (x);            // 0->a:x
7676
7677       CLRC;
7678       AccAXRrl1 (x);            // 0->a:x
7679
7680       break;
7681     case 3:
7682     case 4:
7683     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7684
7685       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7686
7687       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7688
7689       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7690
7691       emitcode ("anl", "a,#!constbyte",
7692                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7693
7694       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7695
7696       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7697
7698       emitcode ("anl", "a,#!constbyte",
7699                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7700
7701       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7702
7703       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7704
7705       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7706
7707       break;
7708     case 6:                     // AABBBBBB:CCDDDDDD
7709
7710       emitcode ("mov", "c,acc.7");
7711       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7712
7713       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7714
7715       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7716
7717       emitcode ("anl", "a,#!constbyte",
7718                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7719
7720       break;
7721     case 7:                     // ABBBBBBB:CDDDDDDD
7722
7723       emitcode ("mov", "c,acc.7");      // c = A
7724
7725       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7726
7727       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7728
7729       emitcode ("anl", "a,#!constbyte",
7730                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7731
7732       break;
7733     default:
7734       break;
7735     }
7736 }
7737 #endif
7738
7739 #ifdef BETTER_LITERAL_SHIFT
7740 /*-----------------------------------------------------------------*/
7741 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7742 /*-----------------------------------------------------------------*/
7743 static void
7744 AccAXRshS (char *x, int shCount)
7745 {
7746   symbol *tlbl;
7747   switch (shCount)
7748     {
7749     case 0:
7750       break;
7751     case 1:
7752       emitcode ("mov", "c,acc.7");
7753       AccAXRrl1 (x);            // s->a:x
7754
7755       break;
7756     case 2:
7757       emitcode ("mov", "c,acc.7");
7758       AccAXRrl1 (x);            // s->a:x
7759
7760       emitcode ("mov", "c,acc.7");
7761       AccAXRrl1 (x);            // s->a:x
7762
7763       break;
7764     case 3:
7765     case 4:
7766     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7767
7768       tlbl = newiTempLabel (NULL);
7769       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7770
7771       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7772
7773       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7774
7775       emitcode ("anl", "a,#!constbyte",
7776                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7777
7778       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7779
7780       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7781
7782       emitcode ("anl", "a,#!constbyte",
7783                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7784
7785       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7786
7787       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7788
7789       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7790
7791       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7792       emitcode ("orl", "a,#!constbyte",
7793                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7794
7795       emitcode ("", "!tlabeldef", tlbl->key + 100);
7796       break;                    // SSSSAAAA:BBBCCCCC
7797
7798     case 6:                     // AABBBBBB:CCDDDDDD
7799
7800       tlbl = newiTempLabel (NULL);
7801       emitcode ("mov", "c,acc.7");
7802       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7803
7804       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7805
7806       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7807
7808       emitcode ("anl", "a,#!constbyte",
7809                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7810
7811       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7812       emitcode ("orl", "a,#!constbyte",
7813                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7814
7815       emitcode ("", "!tlabeldef", tlbl->key + 100);
7816       break;
7817     case 7:                     // ABBBBBBB:CDDDDDDD
7818
7819       tlbl = newiTempLabel (NULL);
7820       emitcode ("mov", "c,acc.7");      // c = A
7821
7822       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7823
7824       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7825
7826       emitcode ("anl", "a,#!constbyte",
7827                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7828
7829       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7830       emitcode ("orl", "a,#!constbyte",
7831                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7832
7833       emitcode ("", "!tlabeldef", tlbl->key + 100);
7834       break;
7835     default:
7836       break;
7837     }
7838 }
7839 #endif
7840
7841 #ifdef BETTER_LITERAL_SHIFT
7842 static void
7843 _loadLeftIntoAx(char    **lsb, 
7844                 operand *left, 
7845                 operand *result,
7846                 int     offl,
7847                 int     offr)
7848 {
7849   // Get the initial value from left into a pair of registers.
7850   // MSB must be in A, LSB can be any register.
7851   //
7852   // If the result is held in registers, it is an optimization
7853   // if the LSB can be held in the register which will hold the,
7854   // result LSB since this saves us from having to copy it into
7855   // the result following AccAXLsh.
7856   //
7857   // If the result is addressed indirectly, this is not a gain.
7858   if (AOP_NEEDSACC(result))
7859   {
7860        char *leftByte;
7861        
7862        _startLazyDPSEvaluation();
7863       if (AOP_TYPE(left) == AOP_DPTR2)
7864        {
7865            // Get MSB in A.
7866            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7867            // get LSB in DP2_RESULT_REG.
7868            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7869            assert(!strcmp(leftByte, DP2_RESULT_REG));
7870        }
7871        else
7872        {
7873            // get LSB into DP2_RESULT_REG
7874            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7875            if (strcmp(leftByte, DP2_RESULT_REG))
7876            {
7877                TR_AP("#7");
7878                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7879            }
7880            // And MSB in A.
7881            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7882            assert(strcmp(leftByte, DP2_RESULT_REG));
7883            MOVA(leftByte);
7884        }
7885        _endLazyDPSEvaluation();
7886        *lsb = DP2_RESULT_REG;
7887   }
7888   else
7889   {
7890       if (sameRegs (AOP (result), AOP (left)) &&
7891         ((offl + MSB16) == offr))
7892       {
7893           /* don't crash result[offr] */
7894           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7895           emitcode ("xch", "a,%s", 
7896                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7897       }
7898       else
7899       {
7900           movLeft2Result (left, offl, result, offr, 0);
7901           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7902       }
7903       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7904       assert(strcmp(*lsb,"a"));      
7905   }
7906 }
7907
7908 static void
7909 _storeAxResults(char    *lsb,
7910                 operand *result,
7911                 int     offr)
7912 {
7913   _startLazyDPSEvaluation();
7914   if (AOP_NEEDSACC(result))
7915   {
7916       /* We have to explicitly update the result LSB.
7917        */
7918       emitcode("xch","a,%s", lsb);
7919       aopPut(AOP(result), "a", offr);
7920       emitcode("mov","a,%s", lsb);
7921   }
7922   if (getDataSize (result) > 1)
7923   {
7924       aopPut (AOP (result), "a", offr + MSB16);
7925   }
7926   _endLazyDPSEvaluation();
7927 }
7928
7929 /*-----------------------------------------------------------------*/
7930 /* shiftL2Left2Result - shift left two bytes from left to result   */
7931 /*-----------------------------------------------------------------*/
7932 static void
7933 shiftL2Left2Result (operand * left, int offl,
7934                     operand * result, int offr, int shCount)
7935 {
7936   char *lsb;
7937
7938   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7939   
7940   AccAXLsh (lsb, shCount);
7941   
7942   _storeAxResults(lsb, result, offr);
7943 }
7944 #endif
7945
7946 #ifdef BETTER_LITERAL_SHIFT
7947 /*-----------------------------------------------------------------*/
7948 /* shiftR2Left2Result - shift right two bytes from left to result  */
7949 /*-----------------------------------------------------------------*/
7950 static void
7951 shiftR2Left2Result (operand * left, int offl,
7952                     operand * result, int offr,
7953                     int shCount, int sign)
7954 {
7955   char *lsb;
7956   
7957   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7958   
7959   /* a:x >> shCount (x = lsb(result)) */
7960   if (sign)
7961   {
7962      AccAXRshS(lsb, shCount);
7963   }
7964   else
7965   {
7966     AccAXRsh(lsb, shCount);
7967   }
7968   
7969   _storeAxResults(lsb, result, offr);
7970 }
7971 #endif
7972
7973 /*-----------------------------------------------------------------*/
7974 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7975 /*-----------------------------------------------------------------*/
7976 static void
7977 shiftLLeftOrResult (operand * left, int offl,
7978                     operand * result, int offr, int shCount)
7979 {
7980   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7981   /* shift left accumulator */
7982   AccLsh (shCount);
7983   /* or with result */
7984   emitcode ("orl", "a,%s",
7985             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7986   /* back to result */
7987   aopPut (AOP (result), "a", offr);
7988 }
7989
7990 #if 0
7991 //REMOVE ME!!!
7992 /*-----------------------------------------------------------------*/
7993 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7994 /*-----------------------------------------------------------------*/
7995 static void
7996 shiftRLeftOrResult (operand * left, int offl,
7997                     operand * result, int offr, int shCount)
7998 {
7999   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8000   /* shift right accumulator */
8001   AccRsh (shCount);
8002   /* or with result */
8003   emitcode ("orl", "a,%s",
8004             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8005   /* back to result */
8006   aopPut (AOP (result), "a", offr);
8007 }
8008 #endif
8009
8010 #ifdef BETTER_LITERAL_SHIFT
8011 /*-----------------------------------------------------------------*/
8012 /* genlshOne - left shift a one byte quantity by known count       */
8013 /*-----------------------------------------------------------------*/
8014 static void
8015 genlshOne (operand * result, operand * left, int shCount)
8016 {
8017   D (emitcode (";", "genlshOne "););
8018   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8019 }
8020 #endif
8021
8022 #ifdef BETTER_LITERAL_SHIFT
8023 /*-----------------------------------------------------------------*/
8024 /* genlshTwo - left shift two bytes by known amount != 0           */
8025 /*-----------------------------------------------------------------*/
8026 static void
8027 genlshTwo (operand * result, operand * left, int shCount)
8028 {
8029   int size;
8030
8031   D (emitcode (";", "genlshTwo "););
8032
8033   size = getDataSize (result);
8034
8035   /* if shCount >= 8 */
8036   if (shCount >= 8)
8037   {
8038       shCount -= 8;
8039
8040       _startLazyDPSEvaluation();
8041
8042       if (size > 1)
8043         {
8044           if (shCount)
8045           {
8046             _endLazyDPSEvaluation();
8047             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8048             aopPut (AOP (result), zero, LSB);       
8049           }
8050           else
8051           {
8052             movLeft2Result (left, LSB, result, MSB16, 0);
8053             aopPut (AOP (result), zero, LSB);
8054             _endLazyDPSEvaluation();
8055           }
8056         }
8057         else
8058         {
8059           aopPut (AOP (result), zero, LSB);
8060           _endLazyDPSEvaluation();
8061         }
8062   }
8063
8064   /*  1 <= shCount <= 7 */
8065   else
8066     {
8067       if (size == 1)
8068       {
8069         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8070       }
8071       else
8072       {
8073         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8074       }
8075     }
8076 }
8077 #endif
8078
8079 #if 0
8080 //REMOVE ME!!!
8081 /*-----------------------------------------------------------------*/
8082 /* shiftLLong - shift left one long from left to result            */
8083 /* offl = LSB or MSB16                                             */
8084 /*-----------------------------------------------------------------*/
8085 static void
8086 shiftLLong (operand * left, operand * result, int offr)
8087 {
8088   char *l;
8089   int size = AOP_SIZE (result);
8090
8091   if (size >= LSB + offr)
8092     {
8093       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8094       MOVA (l);
8095       emitcode ("add", "a,acc");
8096       if (sameRegs (AOP (left), AOP (result)) &&
8097           size >= MSB16 + offr && offr != LSB)
8098         emitcode ("xch", "a,%s",
8099                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8100       else
8101         aopPut (AOP (result), "a", LSB + offr);
8102     }
8103
8104   if (size >= MSB16 + offr)
8105     {
8106       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8107         {
8108           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8109         }
8110       emitcode ("rlc", "a");
8111       if (sameRegs (AOP (left), AOP (result)) &&
8112           size >= MSB24 + offr && offr != LSB)
8113         emitcode ("xch", "a,%s",
8114                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8115       else
8116         aopPut (AOP (result), "a", MSB16 + offr);
8117     }
8118
8119   if (size >= MSB24 + offr)
8120     {
8121       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8122         {
8123           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8124         }
8125       emitcode ("rlc", "a");
8126       if (sameRegs (AOP (left), AOP (result)) &&
8127           size >= MSB32 + offr && offr != LSB)
8128         emitcode ("xch", "a,%s",
8129                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8130       else
8131         aopPut (AOP (result), "a", MSB24 + offr);
8132     }
8133
8134   if (size > MSB32 + offr)
8135     {
8136       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8137         {
8138           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8139         }
8140       emitcode ("rlc", "a");
8141       aopPut (AOP (result), "a", MSB32 + offr);
8142     }
8143   if (offr != LSB)
8144     aopPut (AOP (result), zero, LSB);
8145 }
8146 #endif
8147
8148 #if 0
8149 //REMOVE ME!!!
8150 /*-----------------------------------------------------------------*/
8151 /* genlshFour - shift four byte by a known amount != 0             */
8152 /*-----------------------------------------------------------------*/
8153 static void
8154 genlshFour (operand * result, operand * left, int shCount)
8155 {
8156   int size;
8157
8158   D (emitcode (";", "genlshFour ");
8159     );
8160
8161   size = AOP_SIZE (result);
8162
8163   /* if shifting more that 3 bytes */
8164   if (shCount >= 24)
8165     {
8166       shCount -= 24;
8167       if (shCount)
8168         /* lowest order of left goes to the highest
8169            order of the destination */
8170         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8171       else
8172         movLeft2Result (left, LSB, result, MSB32, 0);
8173       aopPut (AOP (result), zero, LSB);
8174       aopPut (AOP (result), zero, MSB16);
8175       aopPut (AOP (result), zero, MSB24);
8176       return;
8177     }
8178
8179   /* more than two bytes */
8180   else if (shCount >= 16)
8181     {
8182       /* lower order two bytes goes to higher order two bytes */
8183       shCount -= 16;
8184       /* if some more remaining */
8185       if (shCount)
8186         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8187       else
8188         {
8189           movLeft2Result (left, MSB16, result, MSB32, 0);
8190           movLeft2Result (left, LSB, result, MSB24, 0);
8191         }
8192       aopPut (AOP (result), zero, MSB16);
8193       aopPut (AOP (result), zero, LSB);
8194       return;
8195     }
8196
8197   /* if more than 1 byte */
8198   else if (shCount >= 8)
8199     {
8200       /* lower order three bytes goes to higher order  three bytes */
8201       shCount -= 8;
8202       if (size == 2)
8203         {
8204           if (shCount)
8205             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8206           else
8207             movLeft2Result (left, LSB, result, MSB16, 0);
8208         }
8209       else
8210         {                       /* size = 4 */
8211           if (shCount == 0)
8212             {
8213               movLeft2Result (left, MSB24, result, MSB32, 0);
8214               movLeft2Result (left, MSB16, result, MSB24, 0);
8215               movLeft2Result (left, LSB, result, MSB16, 0);
8216               aopPut (AOP (result), zero, LSB);
8217             }
8218           else if (shCount == 1)
8219             shiftLLong (left, result, MSB16);
8220           else
8221             {
8222               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8223               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8224               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8225               aopPut (AOP (result), zero, LSB);
8226             }
8227         }
8228     }
8229
8230   /* 1 <= shCount <= 7 */
8231   else if (shCount <= 2)
8232     {
8233       shiftLLong (left, result, LSB);
8234       if (shCount == 2)
8235         shiftLLong (result, result, LSB);
8236     }
8237   /* 3 <= shCount <= 7, optimize */
8238   else
8239     {
8240       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8241       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8242       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8243     }
8244 }
8245 #endif
8246
8247 #ifdef BETTER_LITERAL_SHIFT
8248 /*-----------------------------------------------------------------*/
8249 /* genLeftShiftLiteral - left shifting by known count              */
8250 /*-----------------------------------------------------------------*/
8251 static bool
8252 genLeftShiftLiteral (operand * left,
8253                      operand * right,
8254                      operand * result,
8255                      iCode * ic)
8256 {
8257   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8258   int size;
8259
8260   size = getSize (operandType (result));
8261
8262   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8263
8264   /* We only handle certain easy cases so far. */
8265   if ((shCount != 0)
8266    && (shCount < (size * 8))
8267    && (size != 1)
8268    && (size != 2))
8269   {
8270       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8271       return FALSE;
8272   }
8273
8274   freeAsmop (right, NULL, ic, TRUE);
8275
8276   aopOp(left, ic, FALSE, FALSE);
8277   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8278
8279 #if 0 // debug spew
8280   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8281   {
8282         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8283         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8284         {
8285            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8286         }
8287   }
8288   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8289   {
8290         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8291         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8292         {
8293            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8294         }       
8295   }  
8296 #endif
8297   
8298 #if VIEW_SIZE
8299   emitcode ("; shift left ", "result %d, left %d", size,
8300             AOP_SIZE (left));
8301 #endif
8302
8303   /* I suppose that the left size >= result size */
8304   if (shCount == 0)
8305   {
8306         _startLazyDPSEvaluation();
8307         while (size--)
8308         {
8309           movLeft2Result (left, size, result, size, 0);
8310         }
8311         _endLazyDPSEvaluation();
8312   }
8313   else if (shCount >= (size * 8))
8314   {
8315     _startLazyDPSEvaluation();
8316     while (size--)
8317     {
8318       aopPut (AOP (result), zero, size);
8319     }
8320     _endLazyDPSEvaluation();
8321   }
8322   else
8323   {
8324       switch (size)
8325         {
8326         case 1:
8327           genlshOne (result, left, shCount);
8328           break;
8329
8330         case 2:
8331           genlshTwo (result, left, shCount);
8332           break;
8333 #if 0
8334         case 4:
8335           genlshFour (result, left, shCount);
8336           break;
8337 #endif
8338         default:
8339           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8340           break;
8341         }
8342     }
8343   freeAsmop (left, NULL, ic, TRUE);
8344   freeAsmop (result, NULL, ic, TRUE);
8345   return TRUE;
8346 }
8347 #endif
8348
8349 /*-----------------------------------------------------------------*/
8350 /* genLeftShift - generates code for left shifting                 */
8351 /*-----------------------------------------------------------------*/
8352 static void
8353 genLeftShift (iCode * ic)
8354 {
8355   operand *left, *right, *result;
8356   int size, offset;
8357   char *l;
8358   symbol *tlbl, *tlbl1;
8359
8360   D (emitcode (";", "genLeftShift "););
8361
8362   right = IC_RIGHT (ic);
8363   left = IC_LEFT (ic);
8364   result = IC_RESULT (ic);
8365
8366   aopOp (right, ic, FALSE, FALSE);
8367
8368
8369 #ifdef BETTER_LITERAL_SHIFT
8370   /* if the shift count is known then do it
8371      as efficiently as possible */
8372   if (AOP_TYPE (right) == AOP_LIT)
8373     {
8374       if (genLeftShiftLiteral (left, right, result, ic))
8375       {
8376         return;
8377       }
8378     }
8379 #endif
8380
8381   /* shift count is unknown then we have to form
8382      a loop get the loop count in B : Note: we take
8383      only the lower order byte since shifting
8384      more that 32 bits make no sense anyway, ( the
8385      largest size of an object can be only 32 bits ) */
8386
8387   if (AOP_TYPE (right) == AOP_LIT)
8388   {
8389       /* Really should be handled by genLeftShiftLiteral,
8390        * but since I'm too lazy to fix that today, at least we can make
8391        * some small improvement.
8392        */
8393        emitcode("mov", "b,#!constbyte",
8394                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8395   }
8396   else
8397   {
8398       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8399       emitcode ("inc", "b");
8400   }
8401   freeAsmop (right, NULL, ic, TRUE);
8402   aopOp (left, ic, FALSE, FALSE);
8403   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8404
8405   /* now move the left to the result if they are not the
8406      same */
8407   if (!sameRegs (AOP (left), AOP (result)) &&
8408       AOP_SIZE (result) > 1)
8409     {
8410
8411       size = AOP_SIZE (result);
8412       offset = 0;
8413       _startLazyDPSEvaluation ();
8414       while (size--)
8415         {
8416           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8417           if (*l == '@' && (IS_AOP_PREG (result)))
8418             {
8419
8420               emitcode ("mov", "a,%s", l);
8421               aopPut (AOP (result), "a", offset);
8422             }
8423           else
8424             aopPut (AOP (result), l, offset);
8425           offset++;
8426         }
8427       _endLazyDPSEvaluation ();
8428     }
8429
8430   tlbl = newiTempLabel (NULL);
8431   size = AOP_SIZE (result);
8432   offset = 0;
8433   tlbl1 = newiTempLabel (NULL);
8434
8435   /* if it is only one byte then */
8436   if (size == 1)
8437     {
8438       symbol *tlbl1 = newiTempLabel (NULL);
8439
8440       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8441       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8442       emitcode ("", "!tlabeldef", tlbl->key + 100);
8443       emitcode ("add", "a,acc");
8444       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8445       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8446       aopPut (AOP (result), "a", 0);
8447       goto release;
8448     }
8449
8450   reAdjustPreg (AOP (result));
8451
8452   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8453   emitcode ("", "!tlabeldef", tlbl->key + 100);
8454   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8455   emitcode ("add", "a,acc");
8456   aopPut (AOP (result), "a", offset++);
8457   _startLazyDPSEvaluation ();
8458   while (--size)
8459     {
8460       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8461       emitcode ("rlc", "a");
8462       aopPut (AOP (result), "a", offset++);
8463     }
8464   _endLazyDPSEvaluation ();
8465   reAdjustPreg (AOP (result));
8466
8467   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8468   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8469 release:
8470   freeAsmop (left, NULL, ic, TRUE);
8471   freeAsmop (result, NULL, ic, TRUE);
8472 }
8473
8474 #ifdef BETTER_LITERAL_SHIFT
8475 /*-----------------------------------------------------------------*/
8476 /* genrshOne - right shift a one byte quantity by known count      */
8477 /*-----------------------------------------------------------------*/
8478 static void
8479 genrshOne (operand * result, operand * left,
8480            int shCount, int sign)
8481 {
8482   D (emitcode (";", "genrshOne"););
8483   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8484 }
8485 #endif
8486
8487 #ifdef BETTER_LITERAL_SHIFT
8488 /*-----------------------------------------------------------------*/
8489 /* genrshTwo - right shift two bytes by known amount != 0          */
8490 /*-----------------------------------------------------------------*/
8491 static void
8492 genrshTwo (operand * result, operand * left,
8493            int shCount, int sign)
8494 {
8495   D (emitcode (";", "genrshTwo"););
8496
8497   /* if shCount >= 8 */
8498   if (shCount >= 8)
8499     {
8500       shCount -= 8;
8501       _startLazyDPSEvaluation();
8502       if (shCount)
8503       {
8504         shiftR1Left2Result (left, MSB16, result, LSB,
8505                             shCount, sign);
8506       }                     
8507       else
8508       {
8509         movLeft2Result (left, MSB16, result, LSB, sign);
8510       }
8511       addSign (result, MSB16, sign);
8512       _endLazyDPSEvaluation();
8513     }
8514
8515   /*  1 <= shCount <= 7 */
8516   else
8517   {
8518     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8519   }
8520 }
8521 #endif
8522
8523 /*-----------------------------------------------------------------*/
8524 /* shiftRLong - shift right one long from left to result           */
8525 /* offl = LSB or MSB16                                             */
8526 /*-----------------------------------------------------------------*/
8527 static void
8528 shiftRLong (operand * left, int offl,
8529             operand * result, int sign)
8530 {
8531   int isSameRegs=sameRegs(AOP(left),AOP(result));
8532
8533   if (isSameRegs && offl>1) {
8534     // we are in big trouble, but this shouldn't happen
8535     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8536   }
8537
8538   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8539   
8540   if (offl==MSB16) {
8541     // shift is > 8
8542     if (sign) {
8543       emitcode ("rlc", "a");
8544       emitcode ("subb", "a,acc");
8545       emitcode ("xch", "a,%s",
8546                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8547     } else {
8548       aopPut (AOP(result), zero, MSB32);
8549     }
8550   }
8551
8552   if (!sign) {
8553     emitcode ("clr", "c");
8554   } else {
8555     emitcode ("mov", "c,acc.7");
8556   }
8557
8558   emitcode ("rrc", "a");
8559
8560   if (isSameRegs && offl==MSB16) {
8561     emitcode ("xch",
8562               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8563   } else {
8564     aopPut (AOP (result), "a", MSB32);
8565     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8566   }
8567
8568   emitcode ("rrc", "a");
8569   if (isSameRegs && offl==1) {
8570     emitcode ("xch", "a,%s",
8571               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8572   } else {
8573     aopPut (AOP (result), "a", MSB24);
8574     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8575   }
8576   emitcode ("rrc", "a");
8577   aopPut (AOP (result), "a", MSB16 - offl);
8578
8579   if (offl == LSB)
8580     {
8581       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8582       emitcode ("rrc", "a");
8583       aopPut (AOP (result), "a", LSB);
8584     }
8585 }
8586
8587 /*-----------------------------------------------------------------*/
8588 /* genrshFour - shift four byte by a known amount != 0             */
8589 /*-----------------------------------------------------------------*/
8590 static void
8591 genrshFour (operand * result, operand * left,
8592             int shCount, int sign)
8593 {
8594   D (emitcode (";", "genrshFour"););
8595
8596   /* if shifting more that 3 bytes */
8597   if (shCount >= 24)
8598     {
8599       shCount -= 24;
8600       _startLazyDPSEvaluation();
8601       if (shCount)
8602         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8603       else
8604         movLeft2Result (left, MSB32, result, LSB, sign);
8605       addSign (result, MSB16, sign);
8606       _endLazyDPSEvaluation();
8607     }
8608   else if (shCount >= 16)
8609     {
8610       shCount -= 16;
8611       _startLazyDPSEvaluation();
8612       if (shCount)
8613         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8614       else
8615         {
8616           movLeft2Result (left, MSB24, result, LSB, 0);
8617           movLeft2Result (left, MSB32, result, MSB16, sign);
8618         }
8619       addSign (result, MSB24, sign);
8620       _endLazyDPSEvaluation();
8621     }
8622   else if (shCount >= 8)
8623     {
8624       shCount -= 8;
8625       _startLazyDPSEvaluation();
8626       if (shCount == 1)
8627         {
8628             shiftRLong (left, MSB16, result, sign);
8629         }
8630       else if (shCount == 0)
8631         {
8632           movLeft2Result (left, MSB16, result, LSB, 0);
8633           movLeft2Result (left, MSB24, result, MSB16, 0);
8634           movLeft2Result (left, MSB32, result, MSB24, sign);
8635           addSign (result, MSB32, sign);
8636         }
8637       else
8638         {
8639           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8640           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8641           /* the last shift is signed */
8642           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8643           addSign (result, MSB32, sign);
8644         }
8645         _endLazyDPSEvaluation();
8646     }
8647   else
8648     {   
8649         /* 1 <= shCount <= 7 */
8650       if (shCount <= 2)
8651         {
8652           shiftRLong (left, LSB, result, sign);
8653           if (shCount == 2)
8654             shiftRLong (result, LSB, result, sign);
8655         }
8656       else
8657         {
8658           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8659           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8660           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8661         }
8662     }
8663 }
8664
8665 #ifdef BETTER_LITERAL_SHIFT
8666 /*-----------------------------------------------------------------*/
8667 /* genRightShiftLiteral - right shifting by known count            */
8668 /*-----------------------------------------------------------------*/
8669 static bool
8670 genRightShiftLiteral (operand * left,
8671                       operand * right,
8672                       operand * result,
8673                       iCode * ic,
8674                       int sign)
8675 {
8676   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8677   int size;
8678
8679   size = getSize (operandType (result));
8680
8681   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8682
8683   /* We only handle certain easy cases so far. */
8684   if ((shCount != 0)
8685    && (shCount < (size * 8))
8686    && (size != 1)
8687    && (size != 2)
8688    && (size != 4))
8689   {
8690       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8691       return FALSE;
8692   }
8693
8694   freeAsmop (right, NULL, ic, TRUE);
8695
8696   aopOp (left, ic, FALSE, FALSE);
8697   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8698
8699 #if VIEW_SIZE
8700   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8701             AOP_SIZE (left));
8702 #endif
8703
8704   /* test the LEFT size !!! */
8705
8706   /* I suppose that the left size >= result size */
8707   if (shCount == 0)
8708   {
8709       size = getDataSize (result);
8710       _startLazyDPSEvaluation();
8711       while (size--)
8712       {
8713         movLeft2Result (left, size, result, size, 0);
8714       }
8715       _endLazyDPSEvaluation();
8716   }
8717   else if (shCount >= (size * 8))
8718     {
8719       if (sign)
8720       {
8721         /* get sign in acc.7 */
8722         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8723       }
8724       addSign (result, LSB, sign);
8725     }
8726   else
8727     {
8728       switch (size)
8729         {
8730         case 1:
8731           genrshOne (result, left, shCount, sign);
8732           break;
8733
8734         case 2:
8735           genrshTwo (result, left, shCount, sign);
8736           break;
8737 #if 1
8738         case 4:
8739           genrshFour (result, left, shCount, sign);
8740           break;
8741 #endif    
8742         default:
8743           break;
8744         }
8745     }
8746   freeAsmop (left, NULL, ic, TRUE);
8747   freeAsmop (result, NULL, ic, TRUE);
8748   
8749   return TRUE;
8750 }
8751 #endif
8752
8753 /*-----------------------------------------------------------------*/
8754 /* genSignedRightShift - right shift of signed number              */
8755 /*-----------------------------------------------------------------*/
8756 static void
8757 genSignedRightShift (iCode * ic)
8758 {
8759   operand *right, *left, *result;
8760   int size, offset;
8761   char *l;
8762   symbol *tlbl, *tlbl1;
8763
8764   D (emitcode (";", "genSignedRightShift "););
8765
8766   /* we do it the hard way put the shift count in b
8767      and loop thru preserving the sign */
8768
8769   right = IC_RIGHT (ic);
8770   left = IC_LEFT (ic);
8771   result = IC_RESULT (ic);
8772
8773   aopOp (right, ic, FALSE, FALSE);
8774
8775 #ifdef BETTER_LITERAL_SHIFT
8776   if (AOP_TYPE (right) == AOP_LIT)
8777     {
8778       if (genRightShiftLiteral (left, right, result, ic, 1))
8779       {
8780         return;
8781       }
8782     }
8783 #endif
8784   /* shift count is unknown then we have to form
8785      a loop get the loop count in B : Note: we take
8786      only the lower order byte since shifting
8787      more that 32 bits make no sense anyway, ( the
8788      largest size of an object can be only 32 bits ) */
8789
8790   if (AOP_TYPE (right) == AOP_LIT)
8791   {
8792       /* Really should be handled by genRightShiftLiteral,
8793        * but since I'm too lazy to fix that today, at least we can make
8794        * some small improvement.
8795        */
8796        emitcode("mov", "b,#!constbyte",
8797                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8798   }
8799   else
8800   {
8801         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8802         emitcode ("inc", "b");
8803   }
8804   freeAsmop (right, NULL, ic, TRUE);
8805   aopOp (left, ic, FALSE, FALSE);
8806   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8807
8808   /* now move the left to the result if they are not the
8809      same */
8810   if (!sameRegs (AOP (left), AOP (result)) &&
8811       AOP_SIZE (result) > 1)
8812     {
8813
8814       size = AOP_SIZE (result);
8815       offset = 0;
8816       _startLazyDPSEvaluation ();
8817       while (size--)
8818         {
8819           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8820           if (*l == '@' && IS_AOP_PREG (result))
8821             {
8822
8823               emitcode ("mov", "a,%s", l);
8824               aopPut (AOP (result), "a", offset);
8825             }
8826           else
8827             aopPut (AOP (result), l, offset);
8828           offset++;
8829         }
8830       _endLazyDPSEvaluation ();
8831     }
8832
8833   /* mov the highest order bit to OVR */
8834   tlbl = newiTempLabel (NULL);
8835   tlbl1 = newiTempLabel (NULL);
8836
8837   size = AOP_SIZE (result);
8838   offset = size - 1;
8839   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8840   emitcode ("rlc", "a");
8841   emitcode ("mov", "ov,c");
8842   /* if it is only one byte then */
8843   if (size == 1)
8844     {
8845       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8846       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8847       emitcode ("", "!tlabeldef", tlbl->key + 100);
8848       emitcode ("mov", "c,ov");
8849       emitcode ("rrc", "a");
8850       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8851       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8852       aopPut (AOP (result), "a", 0);
8853       goto release;
8854     }
8855
8856   reAdjustPreg (AOP (result));
8857   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8858   emitcode ("", "!tlabeldef", tlbl->key + 100);
8859   emitcode ("mov", "c,ov");
8860   _startLazyDPSEvaluation ();
8861   while (size--)
8862     {
8863       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8864       emitcode ("rrc", "a");
8865       aopPut (AOP (result), "a", offset--);
8866     }
8867   _endLazyDPSEvaluation ();
8868   reAdjustPreg (AOP (result));
8869   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8870   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8871
8872 release:
8873   freeAsmop (left, NULL, ic, TRUE);
8874   freeAsmop (result, NULL, ic, TRUE);
8875 }
8876
8877 /*-----------------------------------------------------------------*/
8878 /* genRightShift - generate code for right shifting                */
8879 /*-----------------------------------------------------------------*/
8880 static void
8881 genRightShift (iCode * ic)
8882 {
8883   operand *right, *left, *result;
8884   sym_link *retype;
8885   int size, offset;
8886   char *l;
8887   symbol *tlbl, *tlbl1;
8888
8889   D (emitcode (";", "genRightShift "););
8890
8891   /* if signed then we do it the hard way preserve the
8892      sign bit moving it inwards */
8893   retype = getSpec (operandType (IC_RESULT (ic)));
8894
8895   if (!SPEC_USIGN (retype))
8896     {
8897       genSignedRightShift (ic);
8898       return;
8899     }
8900
8901   /* signed & unsigned types are treated the same : i.e. the
8902      signed is NOT propagated inwards : quoting from the
8903      ANSI - standard : "for E1 >> E2, is equivalent to division
8904      by 2**E2 if unsigned or if it has a non-negative value,
8905      otherwise the result is implementation defined ", MY definition
8906      is that the sign does not get propagated */
8907
8908   right = IC_RIGHT (ic);
8909   left = IC_LEFT (ic);
8910   result = IC_RESULT (ic);
8911
8912   aopOp (right, ic, FALSE, FALSE);
8913
8914 #ifdef BETTER_LITERAL_SHIFT
8915   /* if the shift count is known then do it
8916      as efficiently as possible */
8917   if (AOP_TYPE (right) == AOP_LIT)
8918     {
8919       if (genRightShiftLiteral (left, right, result, ic, 0))
8920       {
8921         return;
8922       }
8923     }
8924 #endif
8925
8926   /* shift count is unknown then we have to form
8927      a loop get the loop count in B : Note: we take
8928      only the lower order byte since shifting
8929      more that 32 bits make no sense anyway, ( the
8930      largest size of an object can be only 32 bits ) */
8931   
8932   if (AOP_TYPE (right) == AOP_LIT)
8933   {
8934       /* Really should be handled by genRightShiftLiteral,
8935        * but since I'm too lazy to fix that today, at least we can make
8936        * some small improvement.
8937        */
8938        emitcode("mov", "b,#!constbyte",
8939                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8940   }
8941   else
8942   {
8943       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8944       emitcode ("inc", "b");
8945   }
8946   freeAsmop (right, NULL, ic, TRUE);
8947   aopOp (left, ic, FALSE, FALSE);
8948   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8949
8950   /* now move the left to the result if they are not the
8951      same */
8952   if (!sameRegs (AOP (left), AOP (result)) &&
8953       AOP_SIZE (result) > 1)
8954     {
8955
8956       size = AOP_SIZE (result);
8957       offset = 0;
8958       _startLazyDPSEvaluation ();
8959       while (size--)
8960         {
8961           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8962           if (*l == '@' && IS_AOP_PREG (result))
8963             {
8964
8965               emitcode ("mov", "a,%s", l);
8966               aopPut (AOP (result), "a", offset);
8967             }
8968           else
8969             aopPut (AOP (result), l, offset);
8970           offset++;
8971         }
8972       _endLazyDPSEvaluation ();
8973     }
8974
8975   tlbl = newiTempLabel (NULL);
8976   tlbl1 = newiTempLabel (NULL);
8977   size = AOP_SIZE (result);
8978   offset = size - 1;
8979
8980   /* if it is only one byte then */
8981   if (size == 1)
8982     {
8983       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8984       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8985       emitcode ("", "!tlabeldef", tlbl->key + 100);
8986       CLRC;
8987       emitcode ("rrc", "a");
8988       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8989       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8990       aopPut (AOP (result), "a", 0);
8991       goto release;
8992     }
8993
8994   reAdjustPreg (AOP (result));
8995   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8996   emitcode ("", "!tlabeldef", tlbl->key + 100);
8997   CLRC;
8998   _startLazyDPSEvaluation ();
8999   while (size--)
9000     {
9001       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9002       emitcode ("rrc", "a");
9003       aopPut (AOP (result), "a", offset--);
9004     }
9005   _endLazyDPSEvaluation ();
9006   reAdjustPreg (AOP (result));
9007
9008   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9009   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9010
9011 release:
9012   freeAsmop (left, NULL, ic, TRUE);
9013   freeAsmop (result, NULL, ic, TRUE);
9014 }
9015
9016
9017 /*-----------------------------------------------------------------*/
9018 /* emitPtrByteGet - emits code to get a byte into A through a      */
9019 /*                  pointer register (R0, R1, or DPTR). The        */
9020 /*                  original value of A can be preserved in B.     */
9021 /*-----------------------------------------------------------------*/
9022 static void
9023 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9024 {
9025   switch (p_type)
9026     {
9027     case IPOINTER:
9028     case POINTER:
9029       if (preserveAinB)
9030         emitcode ("mov", "b,a");
9031       emitcode ("mov", "a,@%s", rname);
9032       break;
9033
9034     case PPOINTER:
9035       if (preserveAinB)
9036         emitcode ("mov", "b,a");
9037       emitcode ("movx", "a,@%s", rname);
9038       break;
9039       
9040     case FPOINTER:
9041       if (preserveAinB)
9042         emitcode ("mov", "b,a");
9043       emitcode ("movx", "a,@dptr");
9044       break;
9045
9046     case CPOINTER:
9047       if (preserveAinB)
9048         emitcode ("mov", "b,a");
9049       emitcode ("clr", "a");
9050       emitcode ("movc", "a,@a+dptr");
9051       break;
9052
9053     case GPOINTER:
9054       if (preserveAinB)
9055         {
9056           emitcode ("push", "b");
9057           emitcode ("push", "acc");
9058         }
9059       emitcode ("lcall", "__gptrget");
9060       if (preserveAinB)
9061         emitcode ("pop", "b");
9062       break;
9063     }
9064 }
9065
9066 /*-----------------------------------------------------------------*/
9067 /* emitPtrByteSet - emits code to set a byte from src through a    */
9068 /*                  pointer register (R0, R1, or DPTR).            */
9069 /*-----------------------------------------------------------------*/
9070 static void
9071 emitPtrByteSet (char *rname, int p_type, char *src)
9072 {
9073   switch (p_type)
9074     {
9075     case IPOINTER:
9076     case POINTER:
9077       if (*src=='@')
9078         {
9079           MOVA (src);
9080           emitcode ("mov", "@%s,a", rname);
9081         }
9082       else
9083         emitcode ("mov", "@%s,%s", rname, src);
9084       break;
9085
9086     case PPOINTER:
9087       MOVA (src);
9088       emitcode ("movx", "@%s,a", rname);
9089       break;
9090       
9091     case FPOINTER:
9092       MOVA (src);
9093       emitcode ("movx", "@dptr,a");
9094       break;
9095
9096     case GPOINTER:
9097       MOVA (src);
9098       emitcode ("lcall", "__gptrput");
9099       break;
9100     }
9101 }
9102
9103 /*-----------------------------------------------------------------*/
9104 /* genUnpackBits - generates code for unpacking bits               */
9105 /*-----------------------------------------------------------------*/
9106 static void
9107 genUnpackBits (operand * result, char *rname, int ptype)
9108 {
9109   int offset = 0;       /* result byte offset */
9110   int rsize;            /* result size */
9111   int rlen = 0;         /* remaining bitfield length */
9112   sym_link *etype;      /* bitfield type information */
9113   int blen;             /* bitfield length */
9114   int bstr;             /* bitfield starting bit within byte */
9115
9116   D(emitcode (";     genUnpackBits",""));
9117
9118   etype = getSpec (operandType (result));
9119   rsize = getSize (operandType (result));
9120   blen = SPEC_BLEN (etype);
9121   bstr = SPEC_BSTR (etype);
9122
9123   /* If the bitfield length is less than a byte */
9124   if (blen < 8)
9125     {
9126       emitPtrByteGet (rname, ptype, FALSE);
9127       AccRsh (bstr);
9128       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9129       aopPut (AOP (result), "a", offset++);
9130       goto finish;
9131     }
9132
9133   /* Bit field did not fit in a byte. Copy all
9134      but the partial byte at the end.  */
9135   for (rlen=blen;rlen>=8;rlen-=8)
9136     {
9137       emitPtrByteGet (rname, ptype, FALSE);
9138       aopPut (AOP (result), "a", offset++);
9139       if (rlen>8)
9140         emitcode ("inc", "%s", rname);
9141     }
9142
9143   /* Handle the partial byte at the end */
9144   if (rlen)
9145     {
9146       emitPtrByteGet (rname, ptype, FALSE);
9147       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9148       aopPut (AOP (result), "a", offset++);
9149     }
9150
9151 finish:
9152   if (offset < rsize)
9153     {
9154       rsize -= offset;
9155       while (rsize--)
9156         aopPut (AOP (result), zero, offset++);
9157     }
9158 }
9159
9160
9161 /*-----------------------------------------------------------------*/
9162 /* genDataPointerGet - generates code when ptr offset is known     */
9163 /*-----------------------------------------------------------------*/
9164 static void
9165 genDataPointerGet (operand * left,
9166                    operand * result,
9167                    iCode * ic)
9168 {
9169   char *l;
9170   char buff[256];
9171   int size, offset = 0;
9172   aopOp (result, ic, TRUE, FALSE);
9173
9174   /* get the string representation of the name */
9175   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9176   size = AOP_SIZE (result);
9177   _startLazyDPSEvaluation ();
9178   while (size--)
9179     {
9180         if (offset)
9181         {
9182             SNPRINTF (buff, sizeof(buff), 
9183                       "(%s + %d)", l + 1, offset);
9184         }
9185         else
9186         {
9187             SNPRINTF (buff, sizeof(buff), 
9188                       "%s", l + 1);
9189         }
9190       aopPut (AOP (result), buff, offset++);
9191     }
9192   _endLazyDPSEvaluation ();
9193
9194   freeAsmop (left, NULL, ic, TRUE);
9195   freeAsmop (result, NULL, ic, TRUE);
9196 }
9197
9198 /*-----------------------------------------------------------------*/
9199 /* genNearPointerGet - emitcode for near pointer fetch             */
9200 /*-----------------------------------------------------------------*/
9201 static void
9202 genNearPointerGet (operand * left,
9203                    operand * result,
9204                    iCode * ic,
9205                    iCode *pi)
9206 {
9207   asmop *aop = NULL;
9208   regs *preg;
9209   char *rname;
9210   sym_link *rtype, *retype, *letype;
9211   sym_link *ltype = operandType (left);
9212   char buff[80];
9213
9214   rtype = operandType (result);
9215   retype = getSpec (rtype);
9216   letype = getSpec (ltype);
9217
9218   aopOp (left, ic, FALSE, FALSE);
9219
9220   /* if left is rematerialisable and
9221      result is not bit variable type and
9222      the left is pointer to data space i.e
9223      lower 128 bytes of space */
9224   if (AOP_TYPE (left) == AOP_IMMD &&
9225       !IS_BITVAR (retype) &&
9226       !IS_BITVAR (letype) &&
9227       DCL_TYPE (ltype) == POINTER)
9228     {
9229       genDataPointerGet (left, result, ic);
9230       return;
9231     }
9232
9233   /* if the value is already in a pointer register
9234      then don't need anything more */
9235   if (!AOP_INPREG (AOP (left)))
9236     {
9237       /* otherwise get a free pointer register */
9238       aop = newAsmop (0);
9239       preg = getFreePtr (ic, &aop, FALSE);
9240       emitcode ("mov", "%s,%s",
9241                 preg->name,
9242                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9243       rname = preg->name;
9244     }
9245   else
9246     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9247
9248   freeAsmop (left, NULL, ic, TRUE);
9249   aopOp (result, ic, FALSE, FALSE);
9250
9251   /* if bitfield then unpack the bits */
9252   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9253     genUnpackBits (result, rname, POINTER);
9254   else
9255     {
9256       /* we have can just get the values */
9257       int size = AOP_SIZE (result);
9258       int offset = 0;
9259
9260       while (size--)
9261         {
9262           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9263             {
9264
9265               emitcode ("mov", "a,@%s", rname);
9266               aopPut (AOP (result), "a", offset);
9267             }
9268           else
9269             {
9270               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9271               aopPut (AOP (result), buff, offset);
9272             }
9273           offset++;
9274           if (size || pi)
9275             {
9276                 emitcode ("inc", "%s", rname);
9277             }
9278         }
9279     }
9280
9281   /* now some housekeeping stuff */
9282   if (aop)
9283     {
9284       /* we had to allocate for this iCode */
9285       if (pi) { /* post increment present */
9286         aopPut(AOP ( left ),rname,0);
9287       }
9288       freeAsmop (NULL, aop, ic, TRUE);
9289     }
9290   else
9291     {
9292       /* we did not allocate which means left
9293          already in a pointer register, then
9294          if size > 0 && this could be used again
9295          we have to point it back to where it
9296          belongs */
9297       if (AOP_SIZE (result) > 1 &&
9298           !OP_SYMBOL (left)->remat &&
9299           (OP_SYMBOL (left)->liveTo > ic->seq ||
9300            ic->depth) &&
9301           !pi)
9302         {
9303           int size = AOP_SIZE (result) - 1;
9304           while (size--)
9305             emitcode ("dec", "%s", rname);
9306         }
9307     }
9308
9309   /* done */
9310   freeAsmop (result, NULL, ic, TRUE);
9311   if (pi) pi->generated = 1;
9312 }
9313
9314 /*-----------------------------------------------------------------*/
9315 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9316 /*-----------------------------------------------------------------*/
9317 static void
9318 genPagedPointerGet (operand * left,
9319                     operand * result,
9320                     iCode * ic,
9321                     iCode * pi)
9322 {
9323   asmop *aop = NULL;
9324   regs *preg;
9325   char *rname;
9326   sym_link *rtype, *retype, *letype;
9327
9328   rtype = operandType (result);
9329   retype = getSpec (rtype);
9330   letype = getSpec (operandType (left));
9331   aopOp (left, ic, FALSE, FALSE);
9332
9333   /* if the value is already in a pointer register
9334      then don't need anything more */
9335   if (!AOP_INPREG (AOP (left)))
9336     {
9337       /* otherwise get a free pointer register */
9338       aop = newAsmop (0);
9339       preg = getFreePtr (ic, &aop, FALSE);
9340       emitcode ("mov", "%s,%s",
9341                 preg->name,
9342                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9343       rname = preg->name;
9344     }
9345   else
9346     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9347
9348   freeAsmop (left, NULL, ic, TRUE);
9349   aopOp (result, ic, FALSE, FALSE);
9350
9351   /* if bitfield then unpack the bits */
9352   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9353     genUnpackBits (result, rname, PPOINTER);
9354   else
9355     {
9356       /* we have can just get the values */
9357       int size = AOP_SIZE (result);
9358       int offset = 0;
9359
9360       while (size--)
9361         {
9362
9363           emitcode ("movx", "a,@%s", rname);
9364           aopPut (AOP (result), "a", offset);
9365
9366           offset++;
9367
9368           if (size || pi)
9369             emitcode ("inc", "%s", rname);
9370         }
9371     }
9372
9373   /* now some housekeeping stuff */
9374   if (aop)
9375     {
9376       /* we had to allocate for this iCode */
9377       if (pi) aopPut ( AOP (left), rname, 0);
9378       freeAsmop (NULL, aop, ic, TRUE);
9379     }
9380   else
9381     {
9382       /* we did not allocate which means left
9383          already in a pointer register, then
9384          if size > 0 && this could be used again
9385          we have to point it back to where it
9386          belongs */
9387       if (AOP_SIZE (result) > 1 &&
9388           !OP_SYMBOL (left)->remat &&
9389           (OP_SYMBOL (left)->liveTo > ic->seq ||
9390            ic->depth) &&
9391           !pi)
9392         {
9393           int size = AOP_SIZE (result) - 1;
9394           while (size--)
9395             emitcode ("dec", "%s", rname);
9396         }
9397     }
9398
9399   /* done */
9400   freeAsmop (result, NULL, ic, TRUE);
9401   if (pi) pi->generated = 1;
9402 }
9403
9404 /*-----------------------------------------------------------------*/
9405 /* genFarPointerGet - gget value from far space                    */
9406 /*-----------------------------------------------------------------*/
9407 static void
9408 genFarPointerGet (operand * left,
9409                   operand * result, iCode * ic, iCode *pi)
9410 {
9411     int size, offset, dopi=1;
9412   sym_link *retype = getSpec (operandType (result));
9413   sym_link *letype = getSpec (operandType (left));
9414   D (emitcode (";", "genFarPointerGet"););
9415
9416   aopOp (left, ic, FALSE, FALSE);
9417
9418   /* if the operand is already in dptr
9419      then we do nothing else we move the value to dptr */
9420   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9421     {
9422       /* if this is remateriazable */
9423       if (AOP_TYPE (left) == AOP_IMMD)
9424         {
9425           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9426         }
9427       else
9428         {
9429           /* we need to get it byte by byte */
9430           _startLazyDPSEvaluation ();
9431           if (AOP_TYPE (left) != AOP_DPTR)
9432             {
9433               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9434               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9435               if (options.model == MODEL_FLAT24)
9436                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9437             }
9438           else
9439             {
9440               /* We need to generate a load to DPTR indirect through DPTR. */
9441               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9442               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9443               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9444               if (options.model == MODEL_FLAT24)
9445                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9446               emitcode ("pop", "dph");
9447               emitcode ("pop", "dpl");
9448               dopi =0;
9449             }
9450           _endLazyDPSEvaluation ();
9451         }
9452     }
9453   /* so dptr know contains the address */
9454   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9455
9456   /* if bit then unpack */
9457   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9458       if (AOP_INDPTRn(left)) {
9459           genSetDPTR(AOP(left)->aopu.dptr);
9460       }
9461       genUnpackBits (result, "dptr", FPOINTER);
9462       if (AOP_INDPTRn(left)) {
9463           genSetDPTR(0);
9464       }
9465   } else
9466     {
9467       size = AOP_SIZE (result);
9468       offset = 0;
9469
9470       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9471           while (size--) {
9472               genSetDPTR(AOP(left)->aopu.dptr);
9473               emitcode ("movx", "a,@dptr");
9474               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9475                   emitcode ("inc", "dptr");
9476               genSetDPTR (0);
9477               aopPut (AOP (result), "a", offset++);
9478           }
9479       } else {
9480           _startLazyDPSEvaluation ();
9481           while (size--) {
9482               if (AOP_INDPTRn(left)) {
9483                   genSetDPTR(AOP(left)->aopu.dptr);
9484               } else {
9485                   genSetDPTR (0);
9486               }
9487               _flushLazyDPS ();
9488               
9489               emitcode ("movx", "a,@dptr");
9490               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9491                   emitcode ("inc", "dptr");
9492               
9493               aopPut (AOP (result), "a", offset++);
9494           }
9495           _endLazyDPSEvaluation ();
9496       }
9497     }
9498   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9499       if (!AOP_INDPTRn(left)) {
9500           _startLazyDPSEvaluation ();
9501           aopPut ( AOP (left), "dpl", 0);
9502           aopPut ( AOP (left), "dph", 1);
9503           if (options.model == MODEL_FLAT24)
9504               aopPut ( AOP (left), "dpx", 2);
9505           _endLazyDPSEvaluation ();
9506       }
9507     pi->generated = 1;
9508   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9509              AOP_SIZE(result) > 1 &&
9510              IS_SYMOP(left) &&
9511              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9512       
9513       size = AOP_SIZE (result) - 1;
9514       if (AOP_INDPTRn(left)) {
9515           genSetDPTR(AOP(left)->aopu.dptr);
9516       }
9517       while (size--) emitcode ("lcall","__decdptr");
9518       if (AOP_INDPTRn(left)) {
9519           genSetDPTR(0);
9520       }
9521   }
9522
9523   freeAsmop (left, NULL, ic, TRUE);
9524   freeAsmop (result, NULL, ic, TRUE);
9525 }
9526
9527 /*-----------------------------------------------------------------*/
9528 /* genCodePointerGet - get value from code space                  */
9529 /*-----------------------------------------------------------------*/
9530 static void
9531 genCodePointerGet (operand * left,
9532                     operand * result, iCode * ic, iCode *pi)
9533 {
9534   int size, offset, dopi=1;
9535   sym_link *retype = getSpec (operandType (result));
9536
9537   aopOp (left, ic, FALSE, FALSE);
9538
9539   /* if the operand is already in dptr
9540      then we do nothing else we move the value to dptr */
9541   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9542     {
9543       /* if this is remateriazable */
9544       if (AOP_TYPE (left) == AOP_IMMD)
9545         {
9546           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9547         }
9548       else
9549         {                       /* we need to get it byte by byte */
9550           _startLazyDPSEvaluation ();
9551           if (AOP_TYPE (left) != AOP_DPTR)
9552             {
9553               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9554               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9555               if (options.model == MODEL_FLAT24)
9556                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9557             }
9558           else
9559             {
9560               /* We need to generate a load to DPTR indirect through DPTR. */
9561               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9562               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9563               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9564               if (options.model == MODEL_FLAT24)
9565                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9566               emitcode ("pop", "dph");
9567               emitcode ("pop", "dpl");
9568               dopi=0;
9569             }
9570           _endLazyDPSEvaluation ();
9571         }
9572     }
9573   /* so dptr know contains the address */
9574   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9575
9576   /* if bit then unpack */
9577   if (IS_BITVAR (retype)) {
9578       if (AOP_INDPTRn(left)) {
9579           genSetDPTR(AOP(left)->aopu.dptr);
9580       }
9581       genUnpackBits (result, "dptr", CPOINTER);
9582       if (AOP_INDPTRn(left)) {
9583           genSetDPTR(0);
9584       }
9585   } else
9586     {
9587       size = AOP_SIZE (result);
9588       offset = 0;
9589       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9590           while (size--) {
9591               genSetDPTR(AOP(left)->aopu.dptr);
9592               emitcode ("clr", "a");
9593               emitcode ("movc", "a,@a+dptr");
9594               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9595                   emitcode ("inc", "dptr");
9596               genSetDPTR (0);
9597               aopPut (AOP (result), "a", offset++);
9598           }
9599       } else {
9600           _startLazyDPSEvaluation ();
9601           while (size--)
9602               {
9603                   if (AOP_INDPTRn(left)) {
9604                       genSetDPTR(AOP(left)->aopu.dptr);
9605                   } else {
9606                       genSetDPTR (0);
9607                   }
9608                   _flushLazyDPS ();
9609                   
9610                   emitcode ("clr", "a");
9611                   emitcode ("movc", "a,@a+dptr");
9612                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9613                       emitcode ("inc", "dptr");
9614                   aopPut (AOP (result), "a", offset++);
9615               }
9616           _endLazyDPSEvaluation ();
9617       }
9618     }
9619   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9620       if (!AOP_INDPTRn(left)) {
9621           _startLazyDPSEvaluation ();
9622           
9623           aopPut ( AOP (left), "dpl", 0);
9624           aopPut ( AOP (left), "dph", 1);
9625           if (options.model == MODEL_FLAT24)
9626               aopPut ( AOP (left), "dpx", 2);
9627
9628           _endLazyDPSEvaluation ();
9629       }
9630       pi->generated = 1;
9631   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9632              AOP_SIZE(result) > 1 &&
9633              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9634       
9635       size = AOP_SIZE (result) - 1;
9636       if (AOP_INDPTRn(left)) {
9637           genSetDPTR(AOP(left)->aopu.dptr);
9638       }
9639       while (size--) emitcode ("lcall","__decdptr");
9640       if (AOP_INDPTRn(left)) {
9641           genSetDPTR(0);
9642       }
9643   }
9644   
9645   freeAsmop (left, NULL, ic, TRUE);
9646   freeAsmop (result, NULL, ic, TRUE);
9647 }
9648
9649 /*-----------------------------------------------------------------*/
9650 /* genGenPointerGet - gget value from generic pointer space        */
9651 /*-----------------------------------------------------------------*/
9652 static void
9653 genGenPointerGet (operand * left,
9654                   operand * result, iCode * ic, iCode * pi)
9655 {
9656   int size, offset;
9657   sym_link *retype = getSpec (operandType (result));
9658   sym_link *letype = getSpec (operandType (left));
9659
9660   D (emitcode (";", "genGenPointerGet "); );
9661
9662   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9663
9664   /* if the operand is already in dptr
9665      then we do nothing else we move the value to dptr */
9666   if (AOP_TYPE (left) != AOP_STR)
9667     {
9668       /* if this is remateriazable */
9669       if (AOP_TYPE (left) == AOP_IMMD)
9670         {
9671           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9672           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9673             {
9674                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9675             }
9676             else
9677             {
9678                 emitcode ("mov", "b,#%d", pointerCode (retype));
9679             }
9680         }
9681       else
9682         {                       /* we need to get it byte by byte */
9683             _startLazyDPSEvaluation ();
9684             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9685             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9686             if (options.model == MODEL_FLAT24) {
9687                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9688                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9689             } else {
9690                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9691             }
9692             _endLazyDPSEvaluation ();
9693         }
9694     }
9695
9696   /* so dptr-b now contains the address */
9697   _G.bInUse++;
9698   aopOp (result, ic, FALSE, TRUE);
9699   _G.bInUse--;
9700
9701   /* if bit then unpack */
9702   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9703   {
9704     genUnpackBits (result, "dptr", GPOINTER);
9705   }
9706   else
9707     {
9708         size = AOP_SIZE (result);
9709         offset = 0;
9710
9711         while (size--)
9712         {
9713             if (size)
9714             {
9715                 // Get two bytes at a time, results in _AP & A.
9716                 // dptr will be incremented ONCE by __gptrgetWord.
9717                 //
9718                 // Note: any change here must be coordinated
9719                 // with the implementation of __gptrgetWord
9720                 // in device/lib/_gptrget.c
9721                 emitcode ("lcall", "__gptrgetWord");
9722                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9723                 aopPut (AOP (result), "a", offset++);
9724                 size--;
9725             }
9726             else
9727             {
9728                 // Only one byte to get.
9729                 emitcode ("lcall", "__gptrget");
9730                 aopPut (AOP (result), "a", offset++);
9731             }
9732             
9733             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9734             {
9735                 emitcode ("inc", "dptr");
9736             }
9737         }
9738     }
9739
9740   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9741     _startLazyDPSEvaluation ();
9742       
9743     aopPut ( AOP (left), "dpl", 0);
9744     aopPut ( AOP (left), "dph", 1);
9745     if (options.model == MODEL_FLAT24) {
9746         aopPut ( AOP (left), "dpx", 2);
9747         aopPut ( AOP (left), "b", 3);   
9748     } else  aopPut ( AOP (left), "b", 2);       
9749     
9750     _endLazyDPSEvaluation ();
9751       
9752     pi->generated = 1;
9753   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9754              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9755       
9756       size = AOP_SIZE (result) - 1;
9757       while (size--) emitcode ("lcall","__decdptr");
9758   }
9759
9760   freeAsmop (left, NULL, ic, TRUE);
9761   freeAsmop (result, NULL, ic, TRUE);
9762 }
9763
9764 /*-----------------------------------------------------------------*/
9765 /* genPointerGet - generate code for pointer get                   */
9766 /*-----------------------------------------------------------------*/
9767 static void
9768 genPointerGet (iCode * ic, iCode *pi)
9769 {
9770   operand *left, *result;
9771   sym_link *type, *etype;
9772   int p_type;
9773
9774   D (emitcode (";", "genPointerGet ");
9775     );
9776
9777   left = IC_LEFT (ic);
9778   result = IC_RESULT (ic);
9779
9780   /* depending on the type of pointer we need to
9781      move it to the correct pointer register */
9782   type = operandType (left);
9783   etype = getSpec (type);
9784   /* if left is of type of pointer then it is simple */
9785   if (IS_PTR (type) && !IS_FUNC (type->next))
9786     p_type = DCL_TYPE (type);
9787   else
9788     {
9789       /* we have to go by the storage class */
9790       p_type = PTR_TYPE (SPEC_OCLS (etype));
9791     }
9792   /* special case when cast remat */
9793   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9794       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9795           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9796           type = operandType (left);
9797           p_type = DCL_TYPE (type);
9798   }
9799   /* now that we have the pointer type we assign
9800      the pointer values */
9801   switch (p_type)
9802     {
9803
9804     case POINTER:
9805     case IPOINTER:
9806       genNearPointerGet (left, result, ic, pi);
9807       break;
9808
9809     case PPOINTER:
9810       genPagedPointerGet (left, result, ic, pi);
9811       break;
9812
9813     case FPOINTER:
9814       genFarPointerGet (left, result, ic, pi);
9815       break;
9816
9817     case CPOINTER:
9818       genCodePointerGet (left, result, ic, pi);
9819       break;
9820
9821     case GPOINTER:
9822       genGenPointerGet (left, result, ic, pi);
9823       break;
9824     }
9825
9826 }
9827
9828 /*-----------------------------------------------------------------*/
9829 /* genPackBits - generates code for packed bit storage             */
9830 /*-----------------------------------------------------------------*/
9831 static void
9832 genPackBits (sym_link * etype,
9833              operand * right,
9834              char *rname, int p_type)
9835 {
9836   int offset = 0;       /* source byte offset */
9837   int rlen = 0;         /* remaining bitfield length */
9838   int blen;             /* bitfield length */
9839   int bstr;             /* bitfield starting bit within byte */
9840   int litval;           /* source literal value (if AOP_LIT) */
9841   unsigned char mask;   /* bitmask within current byte */
9842
9843   D(emitcode (";     genPackBits",""));
9844
9845   blen = SPEC_BLEN (etype);
9846   bstr = SPEC_BSTR (etype);
9847
9848   /* If the bitfield length is less than a byte */
9849   if (blen < 8)
9850     {
9851       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9852               (unsigned char) (0xFF >> (8 - bstr)));
9853
9854       if (AOP_TYPE (right) == AOP_LIT)
9855         {
9856           /* Case with a bitfield length <8 and literal source
9857           */
9858           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9859           litval <<= bstr;
9860           litval &= (~mask) & 0xff;
9861           emitPtrByteGet (rname, p_type, FALSE);
9862           if ((mask|litval)!=0xff)
9863             emitcode ("anl","a,#!constbyte", mask);
9864           if (litval)
9865             emitcode ("orl","a,#!constbyte", litval);
9866         }
9867       else
9868         {
9869           if ((blen==1) && (p_type!=GPOINTER))
9870             {
9871               /* Case with a bitfield length == 1 and no generic pointer
9872               */
9873               if (AOP_TYPE (right) == AOP_CRY)
9874                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9875               else
9876                 {
9877                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9878                   emitcode ("rrc","a");
9879                 }
9880               emitPtrByteGet (rname, p_type, FALSE);
9881               emitcode ("mov","acc.%d,c",bstr);
9882             }
9883           else
9884             {
9885               /* Case with a bitfield length < 8 and arbitrary source
9886               */
9887               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9888               /* shift and mask source value */
9889               AccLsh (bstr);
9890               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9891
9892               /* transfer A to B and get next byte */
9893               emitPtrByteGet (rname, p_type, TRUE);
9894
9895               emitcode ("anl", "a,#!constbyte", mask);
9896               emitcode ("orl", "a,b");
9897               if (p_type == GPOINTER)
9898                 emitcode ("pop", "b");
9899            }
9900         }
9901
9902       emitPtrByteSet (rname, p_type, "a");
9903       return;
9904     }
9905
9906   /* Bit length is greater than 7 bits. In this case, copy  */
9907   /* all except the partial byte at the end                 */
9908   for (rlen=blen;rlen>=8;rlen-=8)
9909     {
9910       emitPtrByteSet (rname, p_type, 
9911                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9912       if (rlen>8)
9913         emitcode ("inc", "%s", rname);
9914     }
9915
9916   /* If there was a partial byte at the end */
9917   if (rlen)
9918     {
9919       mask = (((unsigned char) -1 << rlen) & 0xff);
9920       
9921       if (AOP_TYPE (right) == AOP_LIT)
9922         {
9923           /* Case with partial byte and literal source
9924           */
9925           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9926           litval >>= (blen-rlen);
9927           litval &= (~mask) & 0xff;
9928           emitPtrByteGet (rname, p_type, FALSE);
9929           if ((mask|litval)!=0xff)
9930             emitcode ("anl","a,#!constbyte", mask);
9931           if (litval)
9932             emitcode ("orl","a,#!constbyte", litval);
9933         }
9934       else
9935         {
9936           /* Case with partial byte and arbitrary source
9937           */
9938           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9939           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9940
9941           /* transfer A to B and get next byte */
9942           emitPtrByteGet (rname, p_type, TRUE);
9943
9944           emitcode ("anl", "a,#!constbyte", mask);
9945           emitcode ("orl", "a,b");
9946           if (p_type == GPOINTER)
9947             emitcode ("pop", "b");
9948         }
9949       emitPtrByteSet (rname, p_type, "a");
9950     }
9951
9952 }
9953
9954
9955 /*-----------------------------------------------------------------*/
9956 /* genDataPointerSet - remat pointer to data space                 */
9957 /*-----------------------------------------------------------------*/
9958 static void
9959 genDataPointerSet (operand * right,
9960                    operand * result,
9961                    iCode * ic)
9962 {
9963   int size, offset = 0;
9964   char *l, buff[256];
9965
9966   aopOp (right, ic, FALSE, FALSE);
9967
9968   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9969   size = AOP_SIZE (right);
9970   while (size--)
9971     {
9972       if (offset)
9973         {
9974             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9975         }
9976       else
9977         {
9978             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9979         }
9980         
9981       emitcode ("mov", "%s,%s", buff,
9982                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9983     }
9984
9985   freeAsmop (right, NULL, ic, TRUE);
9986   freeAsmop (result, NULL, ic, TRUE);
9987 }
9988
9989 /*-----------------------------------------------------------------*/
9990 /* genNearPointerSet - emitcode for near pointer put                */
9991 /*-----------------------------------------------------------------*/
9992 static void
9993 genNearPointerSet (operand * right,
9994                    operand * result,
9995                    iCode * ic,
9996                    iCode * pi)
9997 {
9998   asmop *aop = NULL;
9999   char *rname, *l;
10000   sym_link *retype, *letype;
10001   sym_link *ptype = operandType (result);
10002
10003   retype = getSpec (operandType (right));
10004   letype = getSpec (ptype);
10005
10006   aopOp (result, ic, FALSE, FALSE);
10007
10008   /* if the result is rematerializable &
10009      in data space & not a bit variable */
10010   if (AOP_TYPE (result) == AOP_IMMD &&
10011       DCL_TYPE (ptype) == POINTER &&
10012       !IS_BITVAR (retype) &&
10013       !IS_BITVAR (letype))
10014     {
10015       genDataPointerSet (right, result, ic);
10016       return;
10017     }
10018
10019   /* if the value is already in a pointer register
10020      then don't need anything more */
10021   if (!AOP_INPREG (AOP (result)))
10022     {
10023       /* otherwise get a free pointer register */
10024       regs *preg;
10025         
10026       aop = newAsmop (0);
10027       preg = getFreePtr (ic, &aop, FALSE);
10028       emitcode ("mov", "%s,%s",
10029                 preg->name,
10030                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10031       rname = preg->name;
10032     }
10033   else
10034     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10035
10036   aopOp (right, ic, FALSE, FALSE);
10037
10038   /* if bitfield then unpack the bits */
10039   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10040     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10041   else
10042     {
10043       /* we have can just get the values */
10044       int size = AOP_SIZE (right);
10045       int offset = 0;
10046
10047       while (size--)
10048         {
10049           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10050           if (*l == '@')
10051             {
10052               MOVA (l);
10053               emitcode ("mov", "@%s,a", rname);
10054             }
10055           else
10056             emitcode ("mov", "@%s,%s", rname, l);
10057           if (size || pi)
10058             emitcode ("inc", "%s", rname);
10059           offset++;
10060         }
10061     }
10062
10063   /* now some housekeeping stuff */
10064   if (aop)
10065     {
10066       /* we had to allocate for this iCode */
10067       if (pi) aopPut (AOP (result),rname,0);
10068       freeAsmop (NULL, aop, ic, TRUE);
10069     }
10070   else
10071     {
10072       /* we did not allocate which means left
10073          already in a pointer register, then
10074          if size > 0 && this could be used again
10075          we have to point it back to where it
10076          belongs */
10077       if (AOP_SIZE (right) > 1 &&
10078           !OP_SYMBOL (result)->remat &&
10079           (OP_SYMBOL (result)->liveTo > ic->seq ||
10080            ic->depth) &&
10081           !pi)
10082         {
10083           int size = AOP_SIZE (right) - 1;
10084           while (size--)
10085             emitcode ("dec", "%s", rname);
10086         }
10087     }
10088
10089   /* done */
10090   if (pi) pi->generated = 1;
10091   freeAsmop (result, NULL, ic, TRUE);
10092   freeAsmop (right, NULL, ic, TRUE);
10093
10094
10095 }
10096
10097 /*-----------------------------------------------------------------*/
10098 /* genPagedPointerSet - emitcode for Paged pointer put             */
10099 /*-----------------------------------------------------------------*/
10100 static void
10101 genPagedPointerSet (operand * right,
10102                     operand * result,
10103                     iCode * ic,
10104                     iCode *pi)
10105 {
10106   asmop *aop = NULL;
10107   char *rname;
10108   sym_link *retype, *letype;
10109
10110   retype = getSpec (operandType (right));
10111   letype = getSpec (operandType (result));
10112
10113   aopOp (result, ic, FALSE, FALSE);
10114
10115   /* if the value is already in a pointer register
10116      then don't need anything more */
10117   if (!AOP_INPREG (AOP (result)))
10118     {
10119       /* otherwise get a free pointer register */
10120       regs *preg;
10121         
10122       aop = newAsmop (0);
10123       preg = getFreePtr (ic, &aop, FALSE);
10124       emitcode ("mov", "%s,%s",
10125                 preg->name,
10126                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10127       rname = preg->name;
10128     }
10129   else
10130     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10131
10132   aopOp (right, ic, FALSE, FALSE);
10133
10134   /* if bitfield then unpack the bits */
10135   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10136     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10137   else
10138     {
10139       /* we have can just get the values */
10140       int size = AOP_SIZE (right);
10141       int offset = 0;
10142
10143       while (size--)
10144         {
10145           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10146
10147           emitcode ("movx", "@%s,a", rname);
10148
10149           if (size || pi)
10150             emitcode ("inc", "%s", rname);
10151
10152           offset++;
10153         }
10154     }
10155
10156   /* now some housekeeping stuff */
10157   if (aop)
10158     {
10159       if (pi) aopPut (AOP (result),rname,0);
10160       /* we had to allocate for this iCode */
10161       freeAsmop (NULL, aop, ic, TRUE);
10162     }
10163   else
10164     {
10165       /* we did not allocate which means left
10166          already in a pointer register, then
10167          if size > 0 && this could be used again
10168          we have to point it back to where it
10169          belongs */
10170       if (AOP_SIZE (right) > 1 &&
10171           !OP_SYMBOL (result)->remat &&
10172           (OP_SYMBOL (result)->liveTo > ic->seq ||
10173            ic->depth) &&
10174           !pi)
10175         {
10176           int size = AOP_SIZE (right) - 1;
10177           while (size--)
10178             emitcode ("dec", "%s", rname);
10179         }
10180     }
10181
10182   /* done */
10183   if (pi) pi->generated = 1;
10184   freeAsmop (result, NULL, ic, TRUE);
10185   freeAsmop (right, NULL, ic, TRUE);
10186
10187
10188 }
10189
10190 /*-----------------------------------------------------------------*/
10191 /* genFarPointerSet - set value from far space                     */
10192 /*-----------------------------------------------------------------*/
10193 static void
10194 genFarPointerSet (operand * right,
10195                   operand * result, iCode * ic, iCode *pi)
10196 {
10197   int size, offset, dopi=1;
10198   sym_link *retype = getSpec (operandType (right));
10199   sym_link *letype = getSpec (operandType (result));
10200
10201   aopOp (result, ic, FALSE, FALSE);
10202
10203   /* if the operand is already in dptr
10204      then we do nothing else we move the value to dptr */
10205   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10206     {
10207       /* if this is remateriazable */
10208       if (AOP_TYPE (result) == AOP_IMMD)
10209         emitcode ("mov", "dptr,%s", 
10210                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10211       else
10212         {
10213           /* we need to get it byte by byte */
10214           _startLazyDPSEvaluation ();
10215           if (AOP_TYPE (result) != AOP_DPTR)
10216             {
10217               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10218               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10219               if (options.model == MODEL_FLAT24)
10220                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10221             }
10222           else
10223             {
10224               /* We need to generate a load to DPTR indirect through DPTR. */
10225               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10226                 
10227               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10228               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10229               if (options.model == MODEL_FLAT24)
10230                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10231               emitcode ("pop", "dph");
10232               emitcode ("pop", "dpl");
10233               dopi=0;
10234             }
10235           _endLazyDPSEvaluation ();
10236         }
10237     }
10238   /* so dptr know contains the address */
10239   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10240
10241   /* if bit then unpack */
10242   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10243       if (AOP_INDPTRn(result)) {
10244           genSetDPTR(AOP(result)->aopu.dptr);
10245       }
10246       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10247       if (AOP_INDPTRn(result)) {
10248           genSetDPTR(0);
10249       }
10250   } else {
10251       size = AOP_SIZE (right);
10252       offset = 0;
10253       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10254           while (size--) {
10255               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10256               
10257               genSetDPTR(AOP(result)->aopu.dptr);
10258               emitcode ("movx", "@dptr,a");
10259               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10260                   emitcode ("inc", "dptr");
10261               genSetDPTR (0);
10262           }
10263       } else {
10264           _startLazyDPSEvaluation ();
10265           while (size--) {
10266               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10267               
10268               if (AOP_INDPTRn(result)) {
10269                   genSetDPTR(AOP(result)->aopu.dptr);
10270               } else {
10271                   genSetDPTR (0);
10272               }
10273               _flushLazyDPS ();
10274               
10275               emitcode ("movx", "@dptr,a");
10276               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10277                   emitcode ("inc", "dptr");
10278           }
10279           _endLazyDPSEvaluation ();
10280       }
10281   }
10282   
10283   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10284       if (!AOP_INDPTRn(result)) {
10285           _startLazyDPSEvaluation ();
10286           
10287           aopPut (AOP(result),"dpl",0);
10288           aopPut (AOP(result),"dph",1);
10289           if (options.model == MODEL_FLAT24)
10290               aopPut (AOP(result),"dpx",2);
10291
10292           _endLazyDPSEvaluation ();
10293       }
10294       pi->generated=1;
10295   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10296              AOP_SIZE(right) > 1 &&
10297              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10298       
10299       size = AOP_SIZE (right) - 1;
10300       if (AOP_INDPTRn(result)) {
10301           genSetDPTR(AOP(result)->aopu.dptr);
10302       } 
10303       while (size--) emitcode ("lcall","__decdptr");
10304       if (AOP_INDPTRn(result)) {
10305           genSetDPTR(0);
10306       }
10307   }
10308   freeAsmop (result, NULL, ic, TRUE);
10309   freeAsmop (right, NULL, ic, TRUE);
10310 }
10311
10312 /*-----------------------------------------------------------------*/
10313 /* genGenPointerSet - set value from generic pointer space         */
10314 /*-----------------------------------------------------------------*/
10315 static void
10316 genGenPointerSet (operand * right,
10317                   operand * result, iCode * ic, iCode *pi)
10318 {
10319   int size, offset;
10320   sym_link *retype = getSpec (operandType (right));
10321   sym_link *letype = getSpec (operandType (result));
10322
10323   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10324
10325   /* if the operand is already in dptr
10326      then we do nothing else we move the value to dptr */
10327   if (AOP_TYPE (result) != AOP_STR)
10328     {
10329       _startLazyDPSEvaluation ();
10330       /* if this is remateriazable */
10331       if (AOP_TYPE (result) == AOP_IMMD)
10332         {
10333           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10334           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10335           {
10336               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10337           }
10338           else
10339           {
10340               emitcode ("mov", 
10341                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10342           }
10343         }
10344       else
10345         {                       /* we need to get it byte by byte */
10346           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10347           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10348           if (options.model == MODEL_FLAT24) {
10349             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10350             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10351           } else {
10352             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10353           }
10354         }
10355       _endLazyDPSEvaluation ();
10356     }
10357   /* so dptr + b now contains the address */
10358   _G.bInUse++;
10359   aopOp (right, ic, FALSE, TRUE);
10360   _G.bInUse--;
10361     
10362
10363   /* if bit then unpack */
10364   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10365     {
10366         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10367     }
10368   else
10369     {
10370         size = AOP_SIZE (right);
10371         offset = 0;
10372
10373         _startLazyDPSEvaluation ();
10374         while (size--)
10375         {
10376             if (size)
10377             {
10378                 // Set two bytes at a time, passed in _AP & A.
10379                 // dptr will be incremented ONCE by __gptrputWord.
10380                 //
10381                 // Note: any change here must be coordinated
10382                 // with the implementation of __gptrputWord
10383                 // in device/lib/_gptrput.c
10384                 emitcode("mov", "_ap, %s", 
10385                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10386                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10387                 
10388                 genSetDPTR (0);
10389                 _flushLazyDPS ();
10390                 emitcode ("lcall", "__gptrputWord");
10391                 size--;
10392             }
10393             else
10394             {
10395                 // Only one byte to put.
10396                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10397
10398                 genSetDPTR (0);
10399                 _flushLazyDPS ();               
10400                 emitcode ("lcall", "__gptrput");
10401             }
10402             
10403             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10404             {
10405                 emitcode ("inc", "dptr");
10406             }
10407         }
10408         _endLazyDPSEvaluation ();
10409     }
10410
10411   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10412       _startLazyDPSEvaluation ();
10413       
10414       aopPut (AOP(result),"dpl",0);
10415       aopPut (AOP(result),"dph",1);
10416       if (options.model == MODEL_FLAT24) {
10417           aopPut (AOP(result),"dpx",2);
10418           aopPut (AOP(result),"b",3);
10419       } else {
10420           aopPut (AOP(result),"b",2);
10421       }
10422       _endLazyDPSEvaluation ();
10423       
10424       pi->generated=1;
10425   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10426              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10427       
10428       size = AOP_SIZE (right) - 1;
10429       while (size--) emitcode ("lcall","__decdptr");
10430   }
10431   freeAsmop (result, NULL, ic, TRUE);
10432   freeAsmop (right, NULL, ic, TRUE);
10433 }
10434
10435 /*-----------------------------------------------------------------*/
10436 /* genPointerSet - stores the value into a pointer location        */
10437 /*-----------------------------------------------------------------*/
10438 static void
10439 genPointerSet (iCode * ic, iCode *pi)
10440 {
10441   operand *right, *result;
10442   sym_link *type, *etype;
10443   int p_type;
10444
10445   D (emitcode (";", "genPointerSet "););
10446
10447   right = IC_RIGHT (ic);
10448   result = IC_RESULT (ic);
10449
10450   /* depending on the type of pointer we need to
10451      move it to the correct pointer register */
10452   type = operandType (result);
10453   etype = getSpec (type);
10454   /* if left is of type of pointer then it is simple */
10455   if (IS_PTR (type) && !IS_FUNC (type->next))
10456     {
10457       p_type = DCL_TYPE (type);
10458     }
10459   else
10460     {
10461       /* we have to go by the storage class */
10462       p_type = PTR_TYPE (SPEC_OCLS (etype));
10463     }
10464   /* special case when cast remat */
10465   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10466       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10467           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10468           type = operandType (result);
10469           p_type = DCL_TYPE (type);
10470   }
10471
10472   /* now that we have the pointer type we assign
10473      the pointer values */
10474   switch (p_type)
10475     {
10476
10477     case POINTER:
10478     case IPOINTER:
10479       genNearPointerSet (right, result, ic, pi);
10480       break;
10481
10482     case PPOINTER:
10483       genPagedPointerSet (right, result, ic, pi);
10484       break;
10485
10486     case FPOINTER:
10487       genFarPointerSet (right, result, ic, pi);
10488       break;
10489
10490     case GPOINTER:
10491       genGenPointerSet (right, result, ic, pi);
10492       break;
10493
10494     default:
10495       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10496               "genPointerSet: illegal pointer type");
10497     }
10498
10499 }
10500
10501 /*-----------------------------------------------------------------*/
10502 /* genIfx - generate code for Ifx statement                        */
10503 /*-----------------------------------------------------------------*/
10504 static void
10505 genIfx (iCode * ic, iCode * popIc)
10506 {
10507   operand *cond = IC_COND (ic);
10508   int isbit = 0;
10509
10510   D (emitcode (";", "genIfx "););
10511
10512   aopOp (cond, ic, FALSE, FALSE);
10513
10514   /* get the value into acc */
10515   if (AOP_TYPE (cond) != AOP_CRY)
10516     {
10517         toBoolean (cond);
10518     }
10519   else
10520     {
10521         isbit = 1;
10522     }
10523     
10524   /* the result is now in the accumulator */
10525   freeAsmop (cond, NULL, ic, TRUE);
10526
10527   /* if there was something to be popped then do it */
10528   if (popIc)
10529     genIpop (popIc);
10530
10531   /* if the condition is  a bit variable */
10532   if (isbit && IS_ITEMP (cond) &&
10533       SPIL_LOC (cond))
10534     {
10535         genIfxJump (ic, SPIL_LOC (cond)->rname);
10536     }
10537   else if (isbit && !IS_ITEMP (cond))
10538     {
10539         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10540     }
10541   else
10542     {
10543         genIfxJump (ic, "a");
10544     }
10545
10546   ic->generated = 1;
10547 }
10548
10549 /*-----------------------------------------------------------------*/
10550 /* genAddrOf - generates code for address of                       */
10551 /*-----------------------------------------------------------------*/
10552 static void
10553 genAddrOf (iCode * ic)
10554 {
10555   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10556   int size, offset;
10557
10558   D (emitcode (";", "genAddrOf ");
10559     );
10560
10561   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10562
10563   /* if the operand is on the stack then we
10564      need to get the stack offset of this
10565      variable */
10566   if (sym->onStack) {
10567       
10568       /* if 10 bit stack */
10569       if (options.stack10bit) {
10570           char buff[10];
10571           int  offset;
10572           
10573           tsprintf(buff, sizeof(buff), 
10574                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10575           /* if it has an offset then we need to compute it */
10576 /*        emitcode ("subb", "a,#!constbyte", */
10577 /*                  -((sym->stack < 0) ? */
10578 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10579 /*                    ((short) sym->stack)) & 0xff); */
10580 /*        emitcode ("mov","b,a"); */
10581 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10582 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10583 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10584           if (sym->stack) {
10585               emitcode ("mov", "a,_bpx");
10586               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10587                                              ((char) (sym->stack - _G.nRegsSaved)) :
10588                                              ((char) sym->stack )) & 0xff);
10589               emitcode ("mov", "b,a");
10590               emitcode ("mov", "a,_bpx+1");
10591               
10592               offset = (((sym->stack < 0) ? 
10593                          ((short) (sym->stack - _G.nRegsSaved)) :
10594                          ((short) sym->stack )) >> 8) & 0xff;
10595           
10596               emitcode ("addc","a,#!constbyte", offset);
10597
10598               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10599               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10600               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10601           } else {
10602               /* we can just move _bp */
10603               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10604               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10605               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10606           }       
10607       } else {
10608           /* if it has an offset then we need to compute it */
10609           if (sym->stack) {
10610               emitcode ("mov", "a,_bp");
10611               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10612               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10613           } else {
10614               /* we can just move _bp */
10615               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10616           }
10617           /* fill the result with zero */
10618           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10619           
10620           
10621           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10622               fprintf (stderr,
10623                        "*** warning: pointer to stack var truncated.\n");
10624           }
10625
10626           offset = 1;
10627           while (size--) {
10628               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10629           }      
10630       }
10631       goto release;
10632   }
10633
10634   /* object not on stack then we need the name */
10635   size = AOP_SIZE (IC_RESULT (ic));
10636   offset = 0;
10637
10638   while (size--)
10639     {
10640       char s[SDCC_NAME_MAX];
10641       if (offset) {
10642           switch (offset) {
10643           case 1:
10644               tsprintf(s, sizeof(s), "#!his",sym->rname);
10645               break;
10646           case 2:
10647               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10648               break;
10649           case 3:
10650               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10651               break;
10652           default: /* should not need this (just in case) */
10653               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10654                        sym->rname,
10655                        offset * 8);
10656           }
10657       } 
10658       else
10659       {
10660           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10661       }
10662         
10663       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10664     }
10665
10666 release:
10667   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10668
10669 }
10670
10671 #if 0 // obsolete, and buggy for != xdata
10672 /*-----------------------------------------------------------------*/
10673 /* genArrayInit - generates code for address of                       */
10674 /*-----------------------------------------------------------------*/
10675 static void
10676 genArrayInit (iCode * ic)
10677 {
10678     literalList *iLoop;
10679     int         ix, count;
10680     int         elementSize = 0, eIndex;
10681     unsigned    val, lastVal;
10682     sym_link    *type;
10683     operand     *left=IC_LEFT(ic);
10684     
10685     D (emitcode (";", "genArrayInit "););
10686
10687     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10688     
10689     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10690     {
10691         // Load immediate value into DPTR.
10692         emitcode("mov", "dptr, %s",
10693              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10694     }
10695     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10696     {
10697 #if 0
10698       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10699               "Unexpected operand to genArrayInit.\n");
10700       exit(1);
10701 #else
10702       // a regression because of SDCCcse.c:1.52
10703       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10704       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10705       if (options.model == MODEL_FLAT24)
10706         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10707 #endif
10708     }
10709     
10710     type = operandType(IC_LEFT(ic));
10711     
10712     if (type && type->next)
10713     {
10714         elementSize = getSize(type->next);
10715     }
10716     else
10717     {
10718         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10719                                 "can't determine element size in genArrayInit.\n");
10720         exit(1);
10721     }
10722     
10723     iLoop = IC_ARRAYILIST(ic);
10724     lastVal = 0xffff;
10725     
10726     while (iLoop)
10727     {
10728         bool firstpass = TRUE;
10729         
10730         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10731                  iLoop->count, (int)iLoop->literalValue, elementSize);
10732         
10733         ix = iLoop->count;
10734         
10735         while (ix)
10736         {
10737             symbol *tlbl = NULL;
10738             
10739             count = ix > 256 ? 256 : ix;
10740             
10741             if (count > 1)
10742             {
10743                 tlbl = newiTempLabel (NULL);
10744                 if (firstpass || (count & 0xff))
10745                 {
10746                     emitcode("mov", "b, #!constbyte", count & 0xff);
10747                 }
10748                 
10749                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10750             }
10751             
10752             firstpass = FALSE;
10753                 
10754             for (eIndex = 0; eIndex < elementSize; eIndex++)
10755             {
10756                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10757                 if (val != lastVal)
10758                 {
10759                     emitcode("mov", "a, #!constbyte", val);
10760                     lastVal = val;
10761                 }
10762                 
10763                 emitcode("movx", "@dptr, a");
10764                 emitcode("inc", "dptr");
10765             }
10766             
10767             if (count > 1)
10768             {
10769                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10770             }
10771             
10772             ix -= count;
10773         }
10774         
10775         iLoop = iLoop->next;
10776     }
10777     
10778     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10779 }
10780 #endif
10781
10782 /*-----------------------------------------------------------------*/
10783 /* genFarFarAssign - assignment when both are in far space         */
10784 /*-----------------------------------------------------------------*/
10785 static void
10786 genFarFarAssign (operand * result, operand * right, iCode * ic)
10787 {
10788   int size = AOP_SIZE (right);
10789   int offset = 0;
10790   symbol *rSym = NULL;
10791
10792   if (size == 1)
10793   {
10794       /* quick & easy case. */
10795       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10796       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10797       freeAsmop (right, NULL, ic, FALSE);
10798       /* now assign DPTR to result */
10799       _G.accInUse++;
10800       aopOp(result, ic, FALSE, FALSE);
10801       _G.accInUse--;
10802       aopPut(AOP(result), "a", 0);
10803       freeAsmop(result, NULL, ic, FALSE);
10804       return;
10805   }
10806   
10807   /* See if we've got an underlying symbol to abuse. */
10808   if (IS_SYMOP(result) && OP_SYMBOL(result))
10809   {
10810       if (IS_TRUE_SYMOP(result))
10811       {
10812           rSym = OP_SYMBOL(result);
10813       }
10814       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10815       {
10816           rSym = OP_SYMBOL(result)->usl.spillLoc;
10817       }
10818   }
10819              
10820   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10821   {
10822       /* We can use the '390 auto-toggle feature to good effect here. */
10823       
10824       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10825       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10826       emitcode ("mov", "dptr,#%s", rSym->rname); 
10827       /* DP2 = result, DP1 = right, DP1 is current. */
10828       while (size)
10829       {
10830           emitcode("movx", "a,@dptr");
10831           emitcode("movx", "@dptr,a");
10832           if (--size)
10833           {
10834                emitcode("inc", "dptr");
10835                emitcode("inc", "dptr");
10836           }
10837       }
10838       emitcode("mov", "dps,#0");
10839       freeAsmop (right, NULL, ic, FALSE);
10840 #if 0
10841 some alternative code for processors without auto-toggle
10842 no time to test now, so later well put in...kpb
10843         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10844         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10845         emitcode ("mov", "dptr,#%s", rSym->rname); 
10846         /* DP2 = result, DP1 = right, DP1 is current. */
10847         while (size)
10848         {
10849           --size;
10850           emitcode("movx", "a,@dptr");
10851           if (size)
10852             emitcode("inc", "dptr");
10853           emitcode("inc", "dps");
10854           emitcode("movx", "@dptr,a");
10855           if (size)
10856             emitcode("inc", "dptr");
10857           emitcode("inc", "dps");
10858         }
10859         emitcode("mov", "dps,#0");
10860         freeAsmop (right, NULL, ic, FALSE);
10861 #endif
10862   }
10863   else
10864   {
10865       D (emitcode (";", "genFarFarAssign"););
10866       aopOp (result, ic, TRUE, TRUE);
10867
10868       _startLazyDPSEvaluation ();
10869       
10870       while (size--)
10871         {
10872           aopPut (AOP (result),
10873                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10874           offset++;
10875         }
10876       _endLazyDPSEvaluation ();
10877       freeAsmop (result, NULL, ic, FALSE);
10878       freeAsmop (right, NULL, ic, FALSE);
10879   }
10880 }
10881
10882 /*-----------------------------------------------------------------*/
10883 /* genAssign - generate code for assignment                        */
10884 /*-----------------------------------------------------------------*/
10885 static void
10886 genAssign (iCode * ic)
10887 {
10888   operand *result, *right;
10889   int size, offset;
10890   unsigned long lit = 0L;
10891
10892   D (emitcode (";", "genAssign ");
10893     );
10894
10895   result = IC_RESULT (ic);
10896   right = IC_RIGHT (ic);
10897
10898   /* if they are the same */
10899   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10900     return;
10901
10902   aopOp (right, ic, FALSE, FALSE);
10903
10904   emitcode (";", "genAssign: resultIsFar = %s",
10905             isOperandInFarSpace (result) ?
10906             "TRUE" : "FALSE");
10907
10908   /* special case both in far space */
10909   if ((AOP_TYPE (right) == AOP_DPTR ||
10910        AOP_TYPE (right) == AOP_DPTR2) &&
10911   /* IS_TRUE_SYMOP(result)       && */
10912       isOperandInFarSpace (result))
10913     {
10914       genFarFarAssign (result, right, ic);
10915       return;
10916     }
10917
10918   aopOp (result, ic, TRUE, FALSE);
10919
10920   /* if they are the same registers */
10921   if (sameRegs (AOP (right), AOP (result)))
10922     goto release;
10923
10924   /* if the result is a bit */
10925   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10926     {
10927       /* if the right size is a literal then
10928          we know what the value is */
10929       if (AOP_TYPE (right) == AOP_LIT)
10930         {
10931           if (((int) operandLitValue (right)))
10932             aopPut (AOP (result), one, 0);
10933           else
10934             aopPut (AOP (result), zero, 0);
10935           goto release;
10936         }
10937
10938       /* the right is also a bit variable */
10939       if (AOP_TYPE (right) == AOP_CRY)
10940         {
10941           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10942           aopPut (AOP (result), "c", 0);
10943           goto release;
10944         }
10945
10946       /* we need to or */
10947       toBoolean (right);
10948       aopPut (AOP (result), "a", 0);
10949       goto release;
10950     }
10951
10952   /* bit variables done */
10953   /* general case */
10954   size = AOP_SIZE (result);
10955   offset = 0;
10956   if (AOP_TYPE (right) == AOP_LIT)
10957     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10958
10959   if ((size > 1) &&
10960       (AOP_TYPE (result) != AOP_REG) &&
10961       (AOP_TYPE (right) == AOP_LIT) &&
10962       !IS_FLOAT (operandType (right)))
10963     {
10964       _startLazyDPSEvaluation ();
10965       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10966         {
10967           aopPut (AOP (result),
10968                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10969                   offset);
10970           offset++;
10971           size--;
10972         }
10973       /* And now fill the rest with zeros. */
10974       if (size)
10975         {
10976           emitcode ("clr", "a");
10977         }
10978       while (size--)
10979         {
10980           aopPut (AOP (result), "a", offset++);
10981         }
10982       _endLazyDPSEvaluation ();
10983     }
10984   else
10985     {
10986       _startLazyDPSEvaluation ();
10987       while (size--)
10988         {
10989           aopPut (AOP (result),
10990                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10991                   offset);
10992           offset++;
10993         }
10994       _endLazyDPSEvaluation ();
10995     }
10996
10997 release:
10998   freeAsmop (right, NULL, ic, FALSE);
10999   freeAsmop (result, NULL, ic, TRUE);
11000 }
11001
11002 /*-----------------------------------------------------------------*/
11003 /* genJumpTab - generates code for jump table                      */
11004 /*-----------------------------------------------------------------*/
11005 static void
11006 genJumpTab (iCode * ic)
11007 {
11008   symbol *jtab;
11009   char *l;
11010
11011   D (emitcode (";", "genJumpTab ");
11012     );
11013
11014   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11015   /* get the condition into accumulator */
11016   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11017   MOVA (l);
11018   /* multiply by four! */
11019   emitcode ("add", "a,acc");
11020   emitcode ("add", "a,acc");
11021   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11022
11023   jtab = newiTempLabel (NULL);
11024   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11025   emitcode ("jmp", "@a+dptr");
11026   emitcode ("", "!tlabeldef", jtab->key + 100);
11027   /* now generate the jump labels */
11028   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11029        jtab = setNextItem (IC_JTLABELS (ic)))
11030     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11031
11032 }
11033
11034 /*-----------------------------------------------------------------*/
11035 /* genCast - gen code for casting                                  */
11036 /*-----------------------------------------------------------------*/
11037 static void
11038 genCast (iCode * ic)
11039 {
11040   operand *result = IC_RESULT (ic);
11041   sym_link *ctype = operandType (IC_LEFT (ic));
11042   sym_link *rtype = operandType (IC_RIGHT (ic));
11043   operand *right = IC_RIGHT (ic);
11044   int size, offset;
11045
11046   D (emitcode (";", "genCast "););
11047
11048   /* if they are equivalent then do nothing */
11049   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11050     return;
11051
11052   aopOp (right, ic, FALSE, FALSE);
11053   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11054
11055   /* if the result is a bit */
11056   if (IS_BITVAR (OP_SYMBOL (result)->type)
11057       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11058     {
11059       /* if the right size is a literal then
11060          we know what the value is */
11061       if (AOP_TYPE (right) == AOP_LIT)
11062         {
11063           if (((int) operandLitValue (right)))
11064             aopPut (AOP (result), one, 0);
11065           else
11066             aopPut (AOP (result), zero, 0);
11067
11068           goto release;
11069         }
11070
11071       /* the right is also a bit variable */
11072       if (AOP_TYPE (right) == AOP_CRY)
11073         {
11074           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11075           aopPut (AOP (result), "c", 0);
11076           goto release;
11077         }
11078
11079       /* we need to or */
11080       toBoolean (right);
11081       aopPut (AOP (result), "a", 0);
11082       goto release;
11083     }
11084
11085   /* if they are the same size : or less */
11086   if (AOP_SIZE (result) <= AOP_SIZE (right))
11087     {
11088
11089       /* if they are in the same place */
11090       if (sameRegs (AOP (right), AOP (result)))
11091         goto release;
11092
11093       /* if they in different places then copy */
11094       size = AOP_SIZE (result);
11095       offset = 0;
11096       _startLazyDPSEvaluation ();
11097       while (size--)
11098         {
11099           aopPut (AOP (result),
11100                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11101                   offset);
11102           offset++;
11103         }
11104       _endLazyDPSEvaluation ();
11105       goto release;
11106     }
11107
11108
11109   /* if the result is of type pointer */
11110   if (IS_PTR (ctype))
11111     {
11112
11113       int p_type;
11114       sym_link *type = operandType (right);
11115
11116       /* pointer to generic pointer */
11117       if (IS_GENPTR (ctype))
11118         {
11119           if (IS_PTR (type))
11120             {
11121               p_type = DCL_TYPE (type);
11122             }
11123           else
11124             {
11125 #if OLD_CAST_BEHAVIOR
11126               /* KV: we are converting a non-pointer type to
11127                * a generic pointer. This (ifdef'd out) code
11128                * says that the resulting generic pointer
11129                * should have the same class as the storage
11130                * location of the non-pointer variable.
11131                *
11132                * For example, converting an int (which happens
11133                * to be stored in DATA space) to a pointer results
11134                * in a DATA generic pointer; if the original int
11135                * in XDATA space, so will be the resulting pointer.
11136                *
11137                * I don't like that behavior, and thus this change:
11138                * all such conversions will be forced to XDATA and
11139                * throw a warning. If you want some non-XDATA
11140                * type, or you want to suppress the warning, you
11141                * must go through an intermediate cast, like so:
11142                *
11143                * char _generic *gp = (char _xdata *)(intVar);
11144                */
11145               sym_link *etype = getSpec (type);
11146
11147               /* we have to go by the storage class */
11148               if (SPEC_OCLS (etype) != generic)
11149                 {
11150                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11151                 }
11152               else
11153 #endif
11154                 {
11155                   /* Converting unknown class (i.e. register variable)
11156                    * to generic pointer. This is not good, but
11157                    * we'll make a guess (and throw a warning).
11158                    */
11159                   p_type = FPOINTER;
11160                   werror (W_INT_TO_GEN_PTR_CAST);
11161                 }
11162             }
11163
11164           /* the first two bytes are known */
11165           size = GPTRSIZE - 1;
11166           offset = 0;
11167           _startLazyDPSEvaluation ();
11168           while (size--)
11169             {
11170               aopPut (AOP (result),
11171                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11172                       offset);
11173               offset++;
11174             }
11175           _endLazyDPSEvaluation ();
11176
11177           /* the last byte depending on type */
11178             {
11179                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11180                 char gpValStr[10];
11181             
11182                 if (gpVal == -1)
11183                 {
11184                     // pointerTypeToGPByte will have bitched.
11185                     exit(1);
11186                 }
11187             
11188                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11189                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11190             }
11191           goto release;
11192         }
11193
11194       /* just copy the pointers */
11195       size = AOP_SIZE (result);
11196       offset = 0;
11197       _startLazyDPSEvaluation ();
11198       while (size--)
11199         {
11200           aopPut (AOP (result),
11201                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11202                   offset);
11203           offset++;
11204         }
11205       _endLazyDPSEvaluation ();
11206       goto release;
11207     }
11208
11209   /* so we now know that the size of destination is greater
11210      than the size of the source */
11211   /* we move to result for the size of source */
11212   size = AOP_SIZE (right);
11213   offset = 0;
11214   _startLazyDPSEvaluation ();
11215   while (size--)
11216     {
11217       aopPut (AOP (result),
11218               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11219               offset);
11220       offset++;
11221     }
11222   _endLazyDPSEvaluation ();
11223
11224   /* now depending on the sign of the source && destination */
11225   size = AOP_SIZE (result) - AOP_SIZE (right);
11226   /* if unsigned or not an integral type */
11227   /* also, if the source is a bit, we don't need to sign extend, because
11228    * it can't possibly have set the sign bit.
11229    */
11230   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11231     {
11232       while (size--)
11233         {
11234           aopPut (AOP (result), zero, offset++);
11235         }
11236     }
11237   else
11238     {
11239       /* we need to extend the sign :{ */
11240       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11241                         FALSE, FALSE, NULL));
11242       emitcode ("rlc", "a");
11243       emitcode ("subb", "a,acc");
11244       while (size--)
11245         aopPut (AOP (result), "a", offset++);
11246     }
11247
11248   /* we are done hurray !!!! */
11249
11250 release:
11251   freeAsmop (right, NULL, ic, TRUE);
11252   freeAsmop (result, NULL, ic, TRUE);
11253
11254 }
11255
11256 /*-----------------------------------------------------------------*/
11257 /* genDjnz - generate decrement & jump if not zero instrucion      */
11258 /*-----------------------------------------------------------------*/
11259 static int
11260 genDjnz (iCode * ic, iCode * ifx)
11261 {
11262   symbol *lbl, *lbl1;
11263   if (!ifx)
11264     return 0;
11265
11266   /* if the if condition has a false label
11267      then we cannot save */
11268   if (IC_FALSE (ifx))
11269     return 0;
11270
11271   /* if the minus is not of the form
11272      a = a - 1 */
11273   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11274       !IS_OP_LITERAL (IC_RIGHT (ic)))
11275     return 0;
11276
11277   if (operandLitValue (IC_RIGHT (ic)) != 1)
11278     return 0;
11279
11280   /* if the size of this greater than one then no
11281      saving */
11282   if (getSize (operandType (IC_RESULT (ic))) > 1)
11283     return 0;
11284
11285   /* otherwise we can save BIG */
11286   D(emitcode(";", "genDjnz"););
11287
11288   lbl = newiTempLabel (NULL);
11289   lbl1 = newiTempLabel (NULL);
11290
11291   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11292
11293   if (AOP_NEEDSACC(IC_RESULT(ic)))
11294   {
11295       /* If the result is accessed indirectly via
11296        * the accumulator, we must explicitly write
11297        * it back after the decrement.
11298        */
11299       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11300       
11301       if (strcmp(rByte, "a"))
11302       {
11303            /* Something is hopelessly wrong */
11304            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11305                    __FILE__, __LINE__);
11306            /* We can just give up; the generated code will be inefficient,
11307             * but what the hey.
11308             */
11309            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11310            return 0;
11311       }
11312       emitcode ("dec", "%s", rByte);
11313       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11314       emitcode ("jnz", "!tlabel", lbl->key + 100);
11315   }
11316   else if (IS_AOP_PREG (IC_RESULT (ic)))
11317     {
11318       emitcode ("dec", "%s",
11319                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11320       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11321       emitcode ("jnz", "!tlabel", lbl->key + 100);
11322     }
11323   else
11324     {
11325       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11326                 lbl->key + 100);
11327     }
11328   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11329   emitcode ("", "!tlabeldef", lbl->key + 100);
11330   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11331   emitcode ("", "!tlabeldef", lbl1->key + 100);
11332
11333   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11334   ifx->generated = 1;
11335   return 1;
11336 }
11337
11338 /*-----------------------------------------------------------------*/
11339 /* genReceive - generate code for a receive iCode                  */
11340 /*-----------------------------------------------------------------*/
11341 static void
11342 genReceive (iCode * ic)
11343 {
11344     int size = getSize (operandType (IC_RESULT (ic)));
11345     int offset = 0;
11346     int rb1off ;
11347     
11348     D (emitcode (";", "genReceive "););
11349
11350     if (ic->argreg == 1) 
11351     {
11352         /* first parameter */
11353         if (AOP_IS_STR(IC_RESULT(ic)))
11354         {
11355             /* Nothing to do: it's already in the proper place. */
11356             return;
11357         }
11358         else
11359         {
11360             bool useDp2;
11361             
11362             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11363                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11364                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11365             
11366             _G.accInUse++;
11367             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11368             _G.accInUse--; 
11369             
11370             /* Sanity checking... */
11371             if (AOP_USESDPTR(IC_RESULT(ic)))
11372             {
11373                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11374                         "genReceive got unexpected DPTR.");
11375             }
11376             assignResultValue (IC_RESULT (ic));
11377         }
11378     } 
11379     else 
11380     { 
11381         /* second receive onwards */
11382         /* this gets a little tricky since unused recevies will be
11383          eliminated, we have saved the reg in the type field . and
11384          we use that to figure out which register to use */
11385         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11386         rb1off = ic->argreg;
11387         while (size--) 
11388         {
11389             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11390         }
11391     }
11392     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11393 }
11394
11395 /*-----------------------------------------------------------------*/
11396 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11397 /*-----------------------------------------------------------------*/
11398 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11399 {
11400     operand *from , *to , *count;
11401     symbol *lbl;
11402     bitVect *rsave;
11403     int i;
11404
11405     /* we know it has to be 3 parameters */
11406     assert (nparms == 3);
11407     
11408     rsave = newBitVect(16);
11409     /* save DPTR if it needs to be saved */
11410     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11411             if (bitVectBitValue(ic->rMask,i))
11412                     rsave = bitVectSetBit(rsave,i);
11413     }
11414     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11415                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11416     savermask(rsave);
11417     
11418     to = parms[0];
11419     from = parms[1];
11420     count = parms[2];
11421
11422     aopOp (from, ic->next, FALSE, FALSE);
11423
11424     /* get from into DPTR1 */
11425     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11426     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11427     if (options.model == MODEL_FLAT24) {
11428         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11429     }
11430
11431     freeAsmop (from, NULL, ic, FALSE);
11432     aopOp (to, ic, FALSE, FALSE);
11433     /* get "to" into DPTR */
11434     /* if the operand is already in dptr
11435        then we do nothing else we move the value to dptr */
11436     if (AOP_TYPE (to) != AOP_STR) {
11437         /* if already in DPTR then we need to push */
11438         if (AOP_TYPE(to) == AOP_DPTR) {
11439             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11440             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11441             if (options.model == MODEL_FLAT24)
11442                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11443             emitcode ("pop", "dph");
11444             emitcode ("pop", "dpl");        
11445         } else {
11446             _startLazyDPSEvaluation ();
11447             /* if this is remateriazable */
11448             if (AOP_TYPE (to) == AOP_IMMD) {
11449                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11450             } else {                    /* we need to get it byte by byte */
11451                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11452                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11453                 if (options.model == MODEL_FLAT24) {
11454                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11455                 }
11456             }
11457             _endLazyDPSEvaluation ();
11458         }
11459     }
11460     freeAsmop (to, NULL, ic, FALSE);
11461     _G.dptrInUse = _G.dptr1InUse = 1;
11462     aopOp (count, ic->next->next, FALSE,FALSE);
11463     lbl =newiTempLabel(NULL);
11464
11465     /* now for the actual copy */
11466     if (AOP_TYPE(count) == AOP_LIT && 
11467         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11468         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11469         if (fromc) {
11470             emitcode ("lcall","__bi_memcpyc2x_s");
11471         } else {
11472             emitcode ("lcall","__bi_memcpyx2x_s");
11473         }
11474         freeAsmop (count, NULL, ic, FALSE);
11475     } else {
11476         symbol *lbl1 = newiTempLabel(NULL);
11477         
11478         emitcode (";"," Auto increment but no djnz");
11479         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11480         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11481         freeAsmop (count, NULL, ic, FALSE);
11482         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11483         emitcode ("","!tlabeldef",lbl->key+100);
11484         if (fromc) {
11485             emitcode ("clr","a");
11486             emitcode ("movc", "a,@a+dptr");
11487         } else 
11488             emitcode ("movx", "a,@dptr");
11489         emitcode ("movx", "@dptr,a");
11490         emitcode ("inc", "dptr");
11491         emitcode ("inc", "dptr");
11492         emitcode ("mov","a,b");
11493         emitcode ("orl","a,_ap");
11494         emitcode ("jz","!tlabel",lbl1->key+100);
11495         emitcode ("mov","a,_ap");
11496         emitcode ("add","a,#!constbyte",0xFF);
11497         emitcode ("mov","_ap,a");
11498         emitcode ("mov","a,b");
11499         emitcode ("addc","a,#!constbyte",0xFF);
11500         emitcode ("mov","b,a");
11501         emitcode ("sjmp","!tlabel",lbl->key+100);
11502         emitcode ("","!tlabeldef",lbl1->key+100);
11503     }
11504     emitcode ("mov", "dps,#0"); 
11505     _G.dptrInUse = _G.dptr1InUse = 0;
11506     unsavermask(rsave);
11507
11508 }
11509
11510 /*-----------------------------------------------------------------*/
11511 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11512 /*-----------------------------------------------------------------*/
11513 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11514 {
11515     operand *from , *to , *count;
11516     symbol *lbl,*lbl2;
11517     bitVect *rsave;
11518     int i;
11519
11520     /* we know it has to be 3 parameters */
11521     assert (nparms == 3);
11522     
11523     rsave = newBitVect(16);
11524     /* save DPTR if it needs to be saved */
11525     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11526             if (bitVectBitValue(ic->rMask,i))
11527                     rsave = bitVectSetBit(rsave,i);
11528     }
11529     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11530                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11531     savermask(rsave);
11532     
11533     to = parms[0];
11534     from = parms[1];
11535     count = parms[2];
11536
11537     aopOp (from, ic->next, FALSE, FALSE);
11538
11539     /* get from into DPTR1 */
11540     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11541     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11542     if (options.model == MODEL_FLAT24) {
11543         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11544     }
11545
11546     freeAsmop (from, NULL, ic, FALSE);
11547     aopOp (to, ic, FALSE, FALSE);
11548     /* get "to" into DPTR */
11549     /* if the operand is already in dptr
11550        then we do nothing else we move the value to dptr */
11551     if (AOP_TYPE (to) != AOP_STR) {
11552         /* if already in DPTR then we need to push */
11553         if (AOP_TYPE(to) == AOP_DPTR) {
11554             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11555             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11556             if (options.model == MODEL_FLAT24)
11557                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11558             emitcode ("pop", "dph");
11559             emitcode ("pop", "dpl");        
11560         } else {
11561             _startLazyDPSEvaluation ();
11562             /* if this is remateriazable */
11563             if (AOP_TYPE (to) == AOP_IMMD) {
11564                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11565             } else {                    /* we need to get it byte by byte */
11566                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11567                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11568                 if (options.model == MODEL_FLAT24) {
11569                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11570                 }
11571             }
11572             _endLazyDPSEvaluation ();
11573         }
11574     }
11575     freeAsmop (to, NULL, ic, FALSE);
11576     _G.dptrInUse = _G.dptr1InUse = 1;
11577     aopOp (count, ic->next->next, FALSE,FALSE);
11578     lbl =newiTempLabel(NULL);
11579     lbl2 =newiTempLabel(NULL);
11580
11581     /* now for the actual compare */
11582     if (AOP_TYPE(count) == AOP_LIT && 
11583         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11584         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11585         if (fromc)
11586             emitcode("lcall","__bi_memcmpc2x_s");
11587         else
11588             emitcode("lcall","__bi_memcmpx2x_s");
11589         freeAsmop (count, NULL, ic, FALSE);
11590         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11591         aopPut(AOP(IC_RESULT(ic)),"a",0);
11592         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11593     } else {
11594         symbol *lbl1 = newiTempLabel(NULL);
11595
11596         emitcode("push","ar0");         
11597         emitcode (";"," Auto increment but no djnz");
11598         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11599         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11600         freeAsmop (count, NULL, ic, FALSE);
11601         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11602         emitcode ("","!tlabeldef",lbl->key+100);
11603         if (fromc) {
11604             emitcode ("clr","a");
11605             emitcode ("movc", "a,@a+dptr");
11606         } else 
11607             emitcode ("movx", "a,@dptr");
11608         emitcode ("mov","r0,a");
11609         emitcode ("movx", "a,@dptr");
11610         emitcode ("clr","c");
11611         emitcode ("subb","a,r0");
11612         emitcode ("jnz","!tlabel",lbl2->key+100);
11613         emitcode ("inc", "dptr");
11614         emitcode ("inc", "dptr");
11615         emitcode ("mov","a,b");
11616         emitcode ("orl","a,_ap");
11617         emitcode ("jz","!tlabel",lbl1->key+100);
11618         emitcode ("mov","a,_ap");
11619         emitcode ("add","a,#!constbyte",0xFF);
11620         emitcode ("mov","_ap,a");
11621         emitcode ("mov","a,b");
11622         emitcode ("addc","a,#!constbyte",0xFF);
11623         emitcode ("mov","b,a");
11624         emitcode ("sjmp","!tlabel",lbl->key+100);
11625         emitcode ("","!tlabeldef",lbl1->key+100);
11626         emitcode ("clr","a");
11627         emitcode ("","!tlabeldef",lbl2->key+100);
11628         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11629         aopPut(AOP(IC_RESULT(ic)),"a",0);
11630         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11631         emitcode("pop","ar0");
11632         emitcode ("mov", "dps,#0");      
11633     }
11634     _G.dptrInUse = _G.dptr1InUse = 0;
11635     unsavermask(rsave);
11636
11637 }
11638
11639 /*-----------------------------------------------------------------*/
11640 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11641 /* port, first parameter output area second parameter pointer to   */
11642 /* port third parameter count                                      */
11643 /*-----------------------------------------------------------------*/
11644 static void genInp( iCode *ic, int nparms, operand **parms)
11645 {
11646     operand *from , *to , *count;
11647     symbol *lbl;
11648     bitVect *rsave;
11649     int i;
11650
11651     /* we know it has to be 3 parameters */
11652     assert (nparms == 3);
11653     
11654     rsave = newBitVect(16);
11655     /* save DPTR if it needs to be saved */
11656     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11657             if (bitVectBitValue(ic->rMask,i))
11658                     rsave = bitVectSetBit(rsave,i);
11659     }
11660     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11661                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11662     savermask(rsave);
11663     
11664     to = parms[0];
11665     from = parms[1];
11666     count = parms[2];
11667
11668     aopOp (from, ic->next, FALSE, FALSE);
11669
11670     /* get from into DPTR1 */
11671     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11672     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11673     if (options.model == MODEL_FLAT24) {
11674         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11675     }
11676
11677     freeAsmop (from, NULL, ic, FALSE);
11678     aopOp (to, ic, FALSE, FALSE);
11679     /* get "to" into DPTR */
11680     /* if the operand is already in dptr
11681        then we do nothing else we move the value to dptr */
11682     if (AOP_TYPE (to) != AOP_STR) {
11683         /* if already in DPTR then we need to push */
11684         if (AOP_TYPE(to) == AOP_DPTR) {
11685             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11686             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11687             if (options.model == MODEL_FLAT24)
11688                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11689             emitcode ("pop", "dph");
11690             emitcode ("pop", "dpl");        
11691         } else {
11692             _startLazyDPSEvaluation ();
11693             /* if this is remateriazable */
11694             if (AOP_TYPE (to) == AOP_IMMD) {
11695                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11696             } else {                    /* we need to get it byte by byte */
11697                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11698                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11699                 if (options.model == MODEL_FLAT24) {
11700                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11701                 }
11702             }
11703             _endLazyDPSEvaluation ();
11704         }
11705     }
11706     freeAsmop (to, NULL, ic, FALSE);
11707
11708     _G.dptrInUse = _G.dptr1InUse = 1;
11709     aopOp (count, ic->next->next, FALSE,FALSE);
11710     lbl =newiTempLabel(NULL);
11711
11712     /* now for the actual copy */
11713     if (AOP_TYPE(count) == AOP_LIT && 
11714         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11715         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11716         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11717         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11718         freeAsmop (count, NULL, ic, FALSE);
11719         emitcode ("","!tlabeldef",lbl->key+100);
11720         emitcode ("movx", "a,@dptr");   /* read data from port */
11721         emitcode ("dec","dps");         /* switch to DPTR */
11722         emitcode ("movx", "@dptr,a");   /* save into location */
11723         emitcode ("inc", "dptr");       /* point to next area */
11724         emitcode ("inc","dps");         /* switch to DPTR2 */
11725         emitcode ("djnz","b,!tlabel",lbl->key+100);
11726     } else {
11727         symbol *lbl1 = newiTempLabel(NULL);
11728         
11729         emitcode (";"," Auto increment but no djnz");
11730         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11731         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11732         freeAsmop (count, NULL, ic, FALSE);
11733         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11734         emitcode ("","!tlabeldef",lbl->key+100);
11735         emitcode ("movx", "a,@dptr");
11736         emitcode ("dec","dps");         /* switch to DPTR */
11737         emitcode ("movx", "@dptr,a");
11738         emitcode ("inc", "dptr");
11739         emitcode ("inc","dps");         /* switch to DPTR2 */
11740 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11741 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11742         emitcode ("mov","a,b");
11743         emitcode ("orl","a,_ap");
11744         emitcode ("jz","!tlabel",lbl1->key+100);
11745         emitcode ("mov","a,_ap");
11746         emitcode ("add","a,#!constbyte",0xFF);
11747         emitcode ("mov","_ap,a");
11748         emitcode ("mov","a,b");
11749         emitcode ("addc","a,#!constbyte",0xFF);
11750         emitcode ("mov","b,a");
11751         emitcode ("sjmp","!tlabel",lbl->key+100);
11752         emitcode ("","!tlabeldef",lbl1->key+100);
11753     }
11754     emitcode ("mov", "dps,#0"); 
11755     _G.dptrInUse = _G.dptr1InUse = 0;
11756     unsavermask(rsave);
11757
11758 }
11759
11760 /*-----------------------------------------------------------------*/
11761 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11762 /* port, first parameter output area second parameter pointer to   */
11763 /* port third parameter count                                      */
11764 /*-----------------------------------------------------------------*/
11765 static void genOutp( iCode *ic, int nparms, operand **parms)
11766 {
11767     operand *from , *to , *count;
11768     symbol *lbl;
11769     bitVect *rsave;
11770     int i;
11771
11772     /* we know it has to be 3 parameters */
11773     assert (nparms == 3);
11774     
11775     rsave = newBitVect(16);
11776     /* save DPTR if it needs to be saved */
11777     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11778             if (bitVectBitValue(ic->rMask,i))
11779                     rsave = bitVectSetBit(rsave,i);
11780     }
11781     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11782                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11783     savermask(rsave);
11784     
11785     to = parms[0];
11786     from = parms[1];
11787     count = parms[2];
11788
11789     aopOp (from, ic->next, FALSE, FALSE);
11790
11791     /* get from into DPTR1 */
11792     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11793     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11794     if (options.model == MODEL_FLAT24) {
11795         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11796     }
11797
11798     freeAsmop (from, NULL, ic, FALSE);
11799     aopOp (to, ic, FALSE, FALSE);
11800     /* get "to" into DPTR */
11801     /* if the operand is already in dptr
11802        then we do nothing else we move the value to dptr */
11803     if (AOP_TYPE (to) != AOP_STR) {
11804         /* if already in DPTR then we need to push */
11805         if (AOP_TYPE(to) == AOP_DPTR) {
11806             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11807             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11808             if (options.model == MODEL_FLAT24)
11809                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11810             emitcode ("pop", "dph");
11811             emitcode ("pop", "dpl");        
11812         } else {
11813             _startLazyDPSEvaluation ();
11814             /* if this is remateriazable */
11815             if (AOP_TYPE (to) == AOP_IMMD) {
11816                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11817             } else {                    /* we need to get it byte by byte */
11818                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11819                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11820                 if (options.model == MODEL_FLAT24) {
11821                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11822                 }
11823             }
11824             _endLazyDPSEvaluation ();
11825         }
11826     }
11827     freeAsmop (to, NULL, ic, FALSE);
11828
11829     _G.dptrInUse = _G.dptr1InUse = 1;
11830     aopOp (count, ic->next->next, FALSE,FALSE);
11831     lbl =newiTempLabel(NULL);
11832
11833     /* now for the actual copy */
11834     if (AOP_TYPE(count) == AOP_LIT && 
11835         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11836         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11837         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11838         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11839         emitcode ("","!tlabeldef",lbl->key+100);
11840         emitcode ("movx", "a,@dptr");   /* read data from port */
11841         emitcode ("inc","dps");         /* switch to DPTR2 */
11842         emitcode ("movx", "@dptr,a");   /* save into location */
11843         emitcode ("inc", "dptr");       /* point to next area */
11844         emitcode ("dec","dps");         /* switch to DPTR */
11845         emitcode ("djnz","b,!tlabel",lbl->key+100);
11846         freeAsmop (count, NULL, ic, FALSE);
11847     } else {
11848         symbol *lbl1 = newiTempLabel(NULL);
11849         
11850         emitcode (";"," Auto increment but no djnz");
11851         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11852         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11853         freeAsmop (count, NULL, ic, FALSE);
11854         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11855         emitcode ("","!tlabeldef",lbl->key+100);
11856         emitcode ("movx", "a,@dptr");
11857         emitcode ("inc", "dptr");
11858         emitcode ("inc","dps");         /* switch to DPTR2 */
11859         emitcode ("movx", "@dptr,a");
11860         emitcode ("dec","dps");         /* switch to DPTR */
11861         emitcode ("mov","a,b");
11862         emitcode ("orl","a,_ap");
11863         emitcode ("jz","!tlabel",lbl1->key+100);
11864         emitcode ("mov","a,_ap");
11865         emitcode ("add","a,#!constbyte",0xFF);
11866         emitcode ("mov","_ap,a");
11867         emitcode ("mov","a,b");
11868         emitcode ("addc","a,#!constbyte",0xFF);
11869         emitcode ("mov","b,a");
11870         emitcode ("sjmp","!tlabel",lbl->key+100);
11871         emitcode ("","!tlabeldef",lbl1->key+100);
11872     }
11873     emitcode ("mov", "dps,#0"); 
11874     _G.dptrInUse = _G.dptr1InUse = 0;
11875     unsavermask(rsave);
11876
11877 }
11878
11879 /*-----------------------------------------------------------------*/
11880 /* genSwapW - swap lower & high order bytes                        */
11881 /*-----------------------------------------------------------------*/
11882 static void genSwapW(iCode *ic, int nparms, operand **parms)
11883 {
11884     operand *dest;
11885     operand *src;
11886     assert (nparms==1);
11887
11888     src = parms[0];
11889     dest=IC_RESULT(ic);
11890
11891     assert(getSize(operandType(src))==2);
11892
11893     aopOp (src, ic, FALSE, FALSE);
11894     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11895     _G.accInUse++;
11896     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11897     _G.accInUse--;
11898     freeAsmop (src, NULL, ic, FALSE);
11899     
11900     aopOp (dest,ic, FALSE, FALSE);
11901     aopPut(AOP(dest),"b",0);
11902     aopPut(AOP(dest),"a",1);
11903     freeAsmop (dest, NULL, ic, FALSE);    
11904 }
11905
11906 /*-----------------------------------------------------------------*/
11907 /* genMemsetX - gencode for memSetX data                           */
11908 /*-----------------------------------------------------------------*/
11909 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11910 {
11911     operand *to , *val , *count;
11912     symbol *lbl;
11913     char *l;
11914     int i;
11915     bitVect *rsave;
11916
11917     /* we know it has to be 3 parameters */
11918     assert (nparms == 3);
11919     
11920     to = parms[0];
11921     val = parms[1];
11922     count = parms[2];
11923         
11924     /* save DPTR if it needs to be saved */
11925     rsave = newBitVect(16);
11926     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11927             if (bitVectBitValue(ic->rMask,i))
11928                     rsave = bitVectSetBit(rsave,i);
11929     }
11930     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11931                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11932     savermask(rsave);
11933
11934     aopOp (to, ic, FALSE, FALSE);
11935     /* get "to" into DPTR */
11936     /* if the operand is already in dptr
11937        then we do nothing else we move the value to dptr */
11938     if (AOP_TYPE (to) != AOP_STR) {
11939         /* if already in DPTR then we need to push */
11940         if (AOP_TYPE(to) == AOP_DPTR) {
11941             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11942             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11943             if (options.model == MODEL_FLAT24)
11944                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11945             emitcode ("pop", "dph");
11946             emitcode ("pop", "dpl");        
11947         } else {
11948             _startLazyDPSEvaluation ();
11949             /* if this is remateriazable */
11950             if (AOP_TYPE (to) == AOP_IMMD) {
11951                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11952             } else {                    /* we need to get it byte by byte */
11953                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11954                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11955                 if (options.model == MODEL_FLAT24) {
11956                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11957                 }
11958             }
11959             _endLazyDPSEvaluation ();
11960         }
11961     }
11962     freeAsmop (to, NULL, ic, FALSE);
11963
11964     aopOp (val, ic->next->next, FALSE,FALSE);
11965     aopOp (count, ic->next->next, FALSE,FALSE);    
11966     lbl =newiTempLabel(NULL);
11967     /* now for the actual copy */
11968     if (AOP_TYPE(count) == AOP_LIT && 
11969         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11970         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11971         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11972         MOVA(l);
11973         emitcode ("","!tlabeldef",lbl->key+100);
11974         emitcode ("movx", "@dptr,a");
11975         emitcode ("inc", "dptr");
11976         emitcode ("djnz","b,!tlabel",lbl->key+100);
11977     } else {
11978         symbol *lbl1 = newiTempLabel(NULL);
11979         
11980         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11981         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11982         emitcode ("","!tlabeldef",lbl->key+100);
11983         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11984         emitcode ("movx", "@dptr,a");
11985         emitcode ("inc", "dptr");
11986         emitcode ("mov","a,b");
11987         emitcode ("orl","a,_ap");
11988         emitcode ("jz","!tlabel",lbl1->key+100);
11989         emitcode ("mov","a,_ap");
11990         emitcode ("add","a,#!constbyte",0xFF);
11991         emitcode ("mov","_ap,a");
11992         emitcode ("mov","a,b");
11993         emitcode ("addc","a,#!constbyte",0xFF);
11994         emitcode ("mov","b,a");
11995         emitcode ("sjmp","!tlabel",lbl->key+100);
11996         emitcode ("","!tlabeldef",lbl1->key+100);
11997     }
11998     freeAsmop (count, NULL, ic, FALSE);
11999     unsavermask(rsave);
12000 }
12001
12002 /*-----------------------------------------------------------------*/
12003 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12004 /*-----------------------------------------------------------------*/
12005 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12006 {
12007         bitVect *rsave ;
12008         operand *pnum, *result;
12009         int i;
12010     
12011         assert (nparms==1);
12012         /* save registers that need to be saved */
12013         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12014                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12015     
12016         pnum = parms[0]; 
12017         aopOp (pnum, ic, FALSE, FALSE);
12018         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12019         freeAsmop (pnum, NULL, ic, FALSE);
12020         emitcode ("lcall","NatLib_LoadPrimitive");
12021         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12022         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12023             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12024                 for (i = (size-1) ; i >= 0 ; i-- ) {
12025                         emitcode ("push","a%s",javaRet[i]);
12026                 }
12027                 for (i=0; i < size ; i++ ) {
12028                         emitcode ("pop","a%s",
12029                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12030                 }
12031         } else {
12032                 for (i = 0 ; i < size ; i++ ) {
12033                         aopPut(AOP(result),javaRet[i],i);
12034                 }
12035         }    
12036         freeAsmop (result, NULL, ic, FALSE);
12037         unsavermask(rsave);
12038 }
12039
12040 /*-----------------------------------------------------------------*/
12041 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12042 /*-----------------------------------------------------------------*/
12043 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12044 {
12045         bitVect *rsave ;
12046         operand *pnum, *result;
12047         int size = 3;
12048         int i;
12049     
12050         assert (nparms==1);
12051         /* save registers that need to be saved */
12052         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12053                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12054     
12055         pnum = parms[0]; 
12056         aopOp (pnum, ic, FALSE, FALSE);
12057         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12058         freeAsmop (pnum, NULL, ic, FALSE);
12059         emitcode ("lcall","NatLib_LoadPointer");
12060         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12061         if (AOP_TYPE(result)!=AOP_STR) {
12062                 for (i = 0 ; i < size ; i++ ) {
12063                         aopPut(AOP(result),fReturn[i],i);
12064                 }
12065         }    
12066         freeAsmop (result, NULL, ic, FALSE);
12067         unsavermask(rsave);
12068 }
12069
12070 /*-----------------------------------------------------------------*/
12071 /* genNatLibInstallStateBlock -                                    */
12072 /*-----------------------------------------------------------------*/
12073 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12074                                        operand **parms, const char *name)
12075 {
12076         bitVect *rsave ;
12077         operand *psb, *handle;
12078         assert (nparms==2);
12079
12080         /* save registers that need to be saved */
12081         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12082                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12083         psb = parms[0];
12084         handle = parms[1];
12085
12086         /* put pointer to state block into DPTR1 */
12087         aopOp (psb, ic, FALSE, FALSE);
12088         if (AOP_TYPE (psb) == AOP_IMMD) {
12089                 emitcode ("mov","dps,#1");
12090                 emitcode ("mov", "dptr,%s",
12091                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12092                 emitcode ("mov","dps,#0");
12093         } else {
12094                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12095                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12096                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12097         }
12098         freeAsmop (psb, NULL, ic, FALSE);
12099
12100         /* put libraryID into DPTR */
12101         emitcode ("mov","dptr,#LibraryID");
12102
12103         /* put handle into r3:r2 */
12104         aopOp (handle, ic, FALSE, FALSE);
12105         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12106                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12107                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12108                 emitcode ("pop","ar3");
12109                 emitcode ("pop","ar2");
12110         } else {        
12111                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12112                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12113         }
12114         freeAsmop (psb, NULL, ic, FALSE);
12115
12116         /* make the call */
12117         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12118
12119         /* put return value into place*/
12120         _G.accInUse++;
12121         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12122         _G.accInUse--;
12123         aopPut(AOP(IC_RESULT(ic)),"a",0);
12124         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12125         unsavermask(rsave);
12126 }
12127
12128 /*-----------------------------------------------------------------*/
12129 /* genNatLibRemoveStateBlock -                                     */
12130 /*-----------------------------------------------------------------*/
12131 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12132 {
12133         bitVect *rsave ;
12134
12135         assert(nparms==0);
12136
12137         /* save registers that need to be saved */
12138         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12139                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12140
12141         /* put libraryID into DPTR */
12142         emitcode ("mov","dptr,#LibraryID");
12143         /* make the call */
12144         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12145         unsavermask(rsave);
12146 }
12147
12148 /*-----------------------------------------------------------------*/
12149 /* genNatLibGetStateBlock -                                        */
12150 /*-----------------------------------------------------------------*/
12151 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12152                                    operand **parms,const char *name)
12153 {
12154         bitVect *rsave ;
12155         symbol *lbl = newiTempLabel(NULL);
12156         
12157         assert(nparms==0);
12158         /* save registers that need to be saved */
12159         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12160                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12161
12162         /* put libraryID into DPTR */
12163         emitcode ("mov","dptr,#LibraryID");
12164         /* make the call */
12165         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12166         emitcode ("jnz","!tlabel",lbl->key+100);
12167
12168         /* put return value into place */
12169         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12170         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12171                 emitcode ("push","ar3");
12172                 emitcode ("push","ar2");
12173                 emitcode ("pop","%s",
12174                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12175                 emitcode ("pop","%s",
12176                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12177         } else {
12178                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12179                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12180         }
12181         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12182         emitcode ("","!tlabeldef",lbl->key+100);
12183         unsavermask(rsave);
12184 }
12185
12186 /*-----------------------------------------------------------------*/
12187 /* genMMMalloc -                                                   */
12188 /*-----------------------------------------------------------------*/
12189 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12190                          int size, const char *name)
12191 {
12192         bitVect *rsave ;
12193         operand *bsize;
12194         symbol *rsym;
12195         symbol *lbl = newiTempLabel(NULL);
12196
12197         assert (nparms == 1);
12198         /* save registers that need to be saved */
12199         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12200                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12201         
12202         bsize=parms[0];
12203         aopOp (bsize,ic,FALSE,FALSE);
12204
12205         /* put the size in R4-R2 */
12206         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12207                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12208                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12209                 if (size==3) {
12210                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12211                         emitcode("pop","ar4");
12212                 }
12213                 emitcode("pop","ar3");
12214                 emitcode("pop","ar2");          
12215         } else {
12216                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12217                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12218                 if (size==3) {
12219                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12220                 }
12221         }
12222         freeAsmop (bsize, NULL, ic, FALSE);
12223
12224         /* make the call */
12225         emitcode ("lcall","MM_%s",name);
12226         emitcode ("jz","!tlabel",lbl->key+100);
12227         emitcode ("mov","r2,#!constbyte",0xff);
12228         emitcode ("mov","r3,#!constbyte",0xff);
12229         emitcode ("","!tlabeldef",lbl->key+100);
12230         /* we don't care about the pointer : we just save the handle */
12231         rsym = OP_SYMBOL(IC_RESULT(ic));
12232         if (rsym->liveFrom != rsym->liveTo) {
12233                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12234                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12235                         emitcode ("push","ar3");
12236                         emitcode ("push","ar2");
12237                         emitcode ("pop","%s",
12238                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12239                         emitcode ("pop","%s",
12240                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12241                 } else {
12242                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12243                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12244                 }
12245                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12246         }
12247         unsavermask(rsave);
12248 }
12249
12250 /*-----------------------------------------------------------------*/
12251 /* genMMDeref -                                                    */
12252 /*-----------------------------------------------------------------*/
12253 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12254 {
12255         bitVect *rsave ;
12256         operand *handle;
12257
12258         assert (nparms == 1);
12259         /* save registers that need to be saved */
12260         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12261                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12262         
12263         handle=parms[0];
12264         aopOp (handle,ic,FALSE,FALSE);
12265
12266         /* put the size in R4-R2 */
12267         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12268                 emitcode("push","%s",
12269                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12270                 emitcode("push","%s",
12271                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12272                 emitcode("pop","ar3");
12273                 emitcode("pop","ar2");          
12274         } else {
12275                 emitcode ("mov","r2,%s",
12276                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12277                 emitcode ("mov","r3,%s",
12278                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12279         }
12280         freeAsmop (handle, NULL, ic, FALSE);
12281
12282         /* make the call */
12283         emitcode ("lcall","MM_Deref");
12284         
12285         {
12286                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12287                 if (rsym->liveFrom != rsym->liveTo) {                   
12288                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12289                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12290                             _startLazyDPSEvaluation ();
12291                             
12292                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12293                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12294                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12295
12296                             _endLazyDPSEvaluation ();
12297                             
12298                         }
12299                 }
12300         }
12301         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12302         unsavermask(rsave);
12303 }
12304
12305 /*-----------------------------------------------------------------*/
12306 /* genMMUnrestrictedPersist -                                      */
12307 /*-----------------------------------------------------------------*/
12308 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12309 {
12310         bitVect *rsave ;
12311         operand *handle;
12312
12313         assert (nparms == 1);
12314         /* save registers that need to be saved */
12315         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12316                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12317         
12318         handle=parms[0];
12319         aopOp (handle,ic,FALSE,FALSE);
12320
12321         /* put the size in R3-R2 */
12322         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12323                 emitcode("push","%s",
12324                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12325                 emitcode("push","%s",
12326                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12327                 emitcode("pop","ar3");
12328                 emitcode("pop","ar2");          
12329         } else {
12330                 emitcode ("mov","r2,%s",
12331                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12332                 emitcode ("mov","r3,%s",
12333                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12334         }
12335         freeAsmop (handle, NULL, ic, FALSE);
12336
12337         /* make the call */
12338         emitcode ("lcall","MM_UnrestrictedPersist");
12339
12340         {
12341                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12342                 if (rsym->liveFrom != rsym->liveTo) {   
12343                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12344                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12345                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12346                 }
12347         }
12348         unsavermask(rsave);
12349 }
12350
12351 /*-----------------------------------------------------------------*/
12352 /* genSystemExecJavaProcess -                                      */
12353 /*-----------------------------------------------------------------*/
12354 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12355 {
12356         bitVect *rsave ;
12357         operand *handle, *pp;
12358
12359         assert (nparms==2);
12360         /* save registers that need to be saved */
12361         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12362                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12363         
12364         pp = parms[0];
12365         handle = parms[1];
12366         
12367         /* put the handle in R3-R2 */
12368         aopOp (handle,ic,FALSE,FALSE);
12369         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12370                 emitcode("push","%s",
12371                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12372                 emitcode("push","%s",
12373                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12374                 emitcode("pop","ar3");
12375                 emitcode("pop","ar2");          
12376         } else {
12377                 emitcode ("mov","r2,%s",
12378                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12379                 emitcode ("mov","r3,%s",
12380                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12381         }
12382         freeAsmop (handle, NULL, ic, FALSE);
12383         
12384         /* put pointer in DPTR */
12385         aopOp (pp,ic,FALSE,FALSE);
12386         if (AOP_TYPE(pp) == AOP_IMMD) {
12387                 emitcode ("mov", "dptr,%s",
12388                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12389         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12390                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12391                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12392                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12393         }
12394         freeAsmop (handle, NULL, ic, FALSE);
12395
12396         /* make the call */
12397         emitcode ("lcall","System_ExecJavaProcess");
12398         
12399         /* put result in place */
12400         {
12401                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12402                 if (rsym->liveFrom != rsym->liveTo) {   
12403                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12404                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12405                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12406                 }
12407         }
12408         
12409         unsavermask(rsave);
12410 }
12411
12412 /*-----------------------------------------------------------------*/
12413 /* genSystemRTCRegisters -                                         */
12414 /*-----------------------------------------------------------------*/
12415 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12416                                   char *name)
12417 {
12418         bitVect *rsave ;
12419         operand *pp;
12420
12421         assert (nparms==1);
12422         /* save registers that need to be saved */
12423         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12424                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12425         
12426         pp=parms[0];
12427         /* put pointer in DPTR */
12428         aopOp (pp,ic,FALSE,FALSE);
12429         if (AOP_TYPE (pp) == AOP_IMMD) {
12430                 emitcode ("mov","dps,#1");
12431                 emitcode ("mov", "dptr,%s", 
12432                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12433                 emitcode ("mov","dps,#0");
12434         } else {
12435                 emitcode ("mov","dpl1,%s",
12436                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12437                 emitcode ("mov","dph1,%s",
12438                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12439                 emitcode ("mov","dpx1,%s",
12440                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12441         }
12442         freeAsmop (pp, NULL, ic, FALSE);
12443
12444         /* make the call */
12445         emitcode ("lcall","System_%sRTCRegisters",name);
12446
12447         unsavermask(rsave);
12448 }
12449
12450 /*-----------------------------------------------------------------*/
12451 /* genSystemThreadSleep -                                          */
12452 /*-----------------------------------------------------------------*/
12453 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12454 {
12455         bitVect *rsave ;
12456         operand *to, *s;
12457
12458         assert (nparms==1);
12459         /* save registers that need to be saved */
12460         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12461                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12462
12463         to = parms[0];
12464         aopOp(to,ic,FALSE,FALSE);
12465         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12466             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12467                 emitcode ("push","%s",
12468                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12469                 emitcode ("push","%s",
12470                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12471                 emitcode ("push","%s",
12472                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12473                 emitcode ("push","%s",
12474                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12475                 emitcode ("pop","ar3");
12476                 emitcode ("pop","ar2");
12477                 emitcode ("pop","ar1");
12478                 emitcode ("pop","ar0");
12479         } else {
12480                 emitcode ("mov","r0,%s",
12481                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12482                 emitcode ("mov","r1,%s",
12483                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12484                 emitcode ("mov","r2,%s",
12485                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12486                 emitcode ("mov","r3,%s",
12487                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12488         }
12489         freeAsmop (to, NULL, ic, FALSE);
12490
12491         /* suspend in acc */
12492         s = parms[1];
12493         aopOp(s,ic,FALSE,FALSE);
12494         emitcode ("mov","a,%s",
12495                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12496         freeAsmop (s, NULL, ic, FALSE);
12497
12498         /* make the call */
12499         emitcode ("lcall","System_%s",name);
12500
12501         unsavermask(rsave);
12502 }
12503
12504 /*-----------------------------------------------------------------*/
12505 /* genSystemThreadResume -                                         */
12506 /*-----------------------------------------------------------------*/
12507 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12508 {
12509         bitVect *rsave ;
12510         operand *tid,*pid;
12511
12512         assert (nparms==2);
12513         /* save registers that need to be saved */
12514         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12515                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12516         
12517         tid = parms[0];
12518         pid = parms[1];
12519         
12520         /* PID in R0 */
12521         aopOp(pid,ic,FALSE,FALSE);
12522         emitcode ("mov","r0,%s",
12523                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12524         freeAsmop (pid, NULL, ic, FALSE);
12525         
12526         /* tid into ACC */
12527         aopOp(tid,ic,FALSE,FALSE);
12528         emitcode ("mov","a,%s",
12529                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12530         freeAsmop (tid, NULL, ic, FALSE);
12531         
12532         emitcode ("lcall","System_ThreadResume");
12533
12534         /* put result into place */
12535         {
12536                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12537                 if (rsym->liveFrom != rsym->liveTo) {   
12538                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12539                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12540                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12541                 }
12542         }
12543         unsavermask(rsave);
12544 }
12545
12546 /*-----------------------------------------------------------------*/
12547 /* genSystemProcessResume -                                        */
12548 /*-----------------------------------------------------------------*/
12549 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12550 {
12551         bitVect *rsave ;
12552         operand *pid;
12553
12554         assert (nparms==1);
12555         /* save registers that need to be saved */
12556         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12557                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12558         
12559         pid = parms[0];
12560         
12561         /* pid into ACC */
12562         aopOp(pid,ic,FALSE,FALSE);
12563         emitcode ("mov","a,%s",
12564                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12565         freeAsmop (pid, NULL, ic, FALSE);
12566         
12567         emitcode ("lcall","System_ProcessResume");
12568
12569         unsavermask(rsave);
12570 }
12571
12572 /*-----------------------------------------------------------------*/
12573 /* genSystem -                                                     */
12574 /*-----------------------------------------------------------------*/
12575 static void genSystem (iCode *ic,int nparms,char *name)
12576 {
12577         assert(nparms == 0);
12578
12579         emitcode ("lcall","System_%s",name);
12580 }
12581
12582 /*-----------------------------------------------------------------*/
12583 /* genSystemPoll -                                                  */
12584 /*-----------------------------------------------------------------*/
12585 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12586 {
12587         bitVect *rsave ;
12588         operand *fp;
12589
12590         assert (nparms==1);
12591         /* save registers that need to be saved */
12592         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12593                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12594
12595         fp = parms[0];
12596         aopOp (fp,ic,FALSE,FALSE);
12597         if (AOP_TYPE (fp) == AOP_IMMD) {
12598                 emitcode ("mov", "dptr,%s", 
12599                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12600         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12601                 emitcode ("mov","dpl,%s",
12602                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12603                 emitcode ("mov","dph,%s",
12604                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12605                 emitcode ("mov","dpx,%s",
12606                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12607         }
12608         freeAsmop (fp, NULL, ic, FALSE);
12609
12610         emitcode ("lcall","System_%sPoll",name);
12611
12612         /* put result into place */
12613         {
12614                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12615                 if (rsym->liveFrom != rsym->liveTo) {   
12616                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12617                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12618                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12619                 }
12620         }
12621         unsavermask(rsave);
12622 }
12623
12624 /*-----------------------------------------------------------------*/
12625 /* genSystemGetCurrentID -                                         */
12626 /*-----------------------------------------------------------------*/
12627 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12628 {
12629         assert (nparms==0);
12630
12631         emitcode ("lcall","System_GetCurrent%sId",name);
12632         /* put result into place */
12633         {
12634                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12635                 if (rsym->liveFrom != rsym->liveTo) {   
12636                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12637                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12638                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12639                 }
12640         }
12641 }
12642
12643 /*-----------------------------------------------------------------*/
12644 /* genDummyRead - generate code for dummy read of volatiles        */
12645 /*-----------------------------------------------------------------*/
12646 static void
12647 genDummyRead (iCode * ic)
12648 {
12649   operand *right;
12650   int size, offset;
12651
12652   D(emitcode(";     genDummyRead",""));
12653
12654   right = IC_RIGHT (ic);
12655
12656   aopOp (right, ic, FALSE, FALSE);
12657
12658   /* if the result is a bit */
12659   if (AOP_TYPE (right) == AOP_CRY)
12660     {
12661       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12662       goto release;
12663     }
12664
12665   /* bit variables done */
12666   /* general case */
12667   size = AOP_SIZE (right);
12668   offset = 0;
12669   while (size--)
12670     {
12671       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12672       offset++;
12673     }
12674
12675 release:
12676   freeAsmop (right, NULL, ic, TRUE);
12677 }
12678
12679 /*-----------------------------------------------------------------*/
12680 /* genCritical - generate code for start of a critical sequence    */
12681 /*-----------------------------------------------------------------*/
12682 static void
12683 genCritical (iCode *ic)
12684 {
12685   symbol *tlbl = newiTempLabel (NULL);
12686
12687   D(emitcode(";     genCritical",""));
12688   
12689   if (IC_RESULT (ic))
12690     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12691
12692   emitcode ("setb", "c");
12693   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12694   emitcode ("clr", "c");
12695   emitcode ("", "%05d$:", (tlbl->key + 100));
12696
12697   if (IC_RESULT (ic))
12698     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12699   else
12700     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12701
12702   if (IC_RESULT (ic))
12703     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12704 }
12705
12706 /*-----------------------------------------------------------------*/
12707 /* genEndCritical - generate code for end of a critical sequence   */
12708 /*-----------------------------------------------------------------*/
12709 static void
12710 genEndCritical (iCode *ic)
12711 {
12712   D(emitcode(";     genEndCritical",""));
12713   
12714   if (IC_RIGHT (ic))
12715     {
12716       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12717       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12718         {
12719           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12720           emitcode ("mov", "ea,c");
12721         }
12722       else
12723         {
12724           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12725           emitcode ("rrc", "a");
12726           emitcode ("mov", "ea,c");
12727         }
12728       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12729     }
12730   else
12731     {
12732       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12733       emitcode ("mov", "ea,c");
12734     }
12735 }
12736
12737
12738
12739 /*-----------------------------------------------------------------*/
12740 /* genBuiltIn - calls the appropriate function to  generating code */
12741 /* for a built in function                                         */
12742 /*-----------------------------------------------------------------*/
12743 static void genBuiltIn (iCode *ic)
12744 {
12745         operand *bi_parms[MAX_BUILTIN_ARGS];
12746         int nbi_parms;
12747         iCode *bi_iCode;
12748         symbol *bif;
12749
12750         /* get all the arguments for a built in function */
12751         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12752
12753         /* which function is it */
12754         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12755         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12756                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12757         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12758                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12759         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12760                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12761         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12762                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12763         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12764                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12765         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12766                 genInp(bi_iCode,nbi_parms,bi_parms);
12767         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12768                 genOutp(bi_iCode,nbi_parms,bi_parms);
12769         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12770                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12771                 /* JavaNative builtIns */               
12772         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12773                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12774         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12775                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12776         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12777                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12778         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12779                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12780         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12781                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12782         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12783                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12784         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12785                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12786         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12787                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12788         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12789                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12790         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12791                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12792         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12793                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12794         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12795                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12796         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12797                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12798         } else if (strcmp(bif->name,"MM_Free")==0) {
12799                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12800         } else if (strcmp(bif->name,"MM_Deref")==0) {
12801                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12802         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12803                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12804         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12805                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12806         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12807                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12808         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12809                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12810         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12811                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12812         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12813                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12814         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12815                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12816         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12817                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12818         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12819                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12820         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12821                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12822         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12823                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12824         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12825                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12826         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12827                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12828         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12829                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12830         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12831                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12832         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12833                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12834         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12835                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12836         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12837                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12838         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12839                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12840         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12841                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12842         } else {
12843                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12844                 return ;
12845         }
12846         return ;    
12847 }
12848
12849 /*-----------------------------------------------------------------*/
12850 /* gen390Code - generate code for Dallas 390 based controllers     */
12851 /*-----------------------------------------------------------------*/
12852 void
12853 gen390Code (iCode * lic)
12854 {
12855   iCode *ic;
12856   int cln = 0;
12857
12858   lineHead = lineCurr = NULL;
12859   dptrn[1][0] = "dpl1";
12860   dptrn[1][1] = "dph1";
12861   dptrn[1][2] = "dpx1";
12862   
12863   if (options.model == MODEL_FLAT24) {
12864     fReturnSizeDS390 = 5;
12865     fReturn = fReturn24;
12866   } else {
12867     fReturnSizeDS390 = 4;
12868     fReturn = fReturn16;
12869     options.stack10bit=0;
12870   }
12871 #if 1
12872   /* print the allocation information */
12873   if (allocInfo && currFunc)
12874     printAllocInfo (currFunc, codeOutFile);
12875 #endif
12876   /* if debug information required */
12877   if (options.debug && currFunc)
12878     {
12879       debugFile->writeFunction(currFunc);
12880       _G.debugLine = 1;
12881       if (IS_STATIC (currFunc->etype))
12882         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12883       else
12884         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12885       _G.debugLine = 0;
12886     }
12887   /* stack pointer name */
12888   if (options.useXstack)
12889     spname = "_spx";
12890   else
12891     spname = "sp";
12892
12893
12894   for (ic = lic; ic; ic = ic->next)
12895     {
12896
12897       if (ic->lineno && cln != ic->lineno)
12898         {
12899           if (options.debug)
12900             {
12901               _G.debugLine = 1;
12902               emitcode ("", "C$%s$%d$%d$%d ==.",
12903                         FileBaseName (ic->filename), ic->lineno,
12904                         ic->level, ic->block);
12905               _G.debugLine = 0;
12906             }
12907           if (!options.noCcodeInAsm) {
12908             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12909                       printCLine(ic->filename, ic->lineno));
12910           }
12911           cln = ic->lineno;
12912         }
12913       if (options.iCodeInAsm) {
12914         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12915       }
12916       /* if the result is marked as
12917          spilt and rematerializable or code for
12918          this has already been generated then
12919          do nothing */
12920       if (resultRemat (ic) || ic->generated)
12921         continue;
12922
12923       /* depending on the operation */
12924       switch (ic->op)
12925         {
12926         case '!':
12927           genNot (ic);
12928           break;
12929
12930         case '~':
12931           genCpl (ic);
12932           break;
12933
12934         case UNARYMINUS:
12935           genUminus (ic);
12936           break;
12937
12938         case IPUSH:
12939           genIpush (ic);
12940           break;
12941
12942         case IPOP:
12943           /* IPOP happens only when trying to restore a
12944              spilt live range, if there is an ifx statement
12945              following this pop then the if statement might
12946              be using some of the registers being popped which
12947              would destory the contents of the register so
12948              we need to check for this condition and handle it */
12949           if (ic->next &&
12950               ic->next->op == IFX &&
12951               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12952             genIfx (ic->next, ic);
12953           else
12954             genIpop (ic);
12955           break;
12956
12957         case CALL:
12958           genCall (ic);
12959           break;
12960
12961         case PCALL:
12962           genPcall (ic);
12963           break;
12964
12965         case FUNCTION:
12966           genFunction (ic);
12967           break;
12968
12969         case ENDFUNCTION:
12970           genEndFunction (ic);
12971           break;
12972
12973         case RETURN:
12974           genRet (ic);
12975           break;
12976
12977         case LABEL:
12978           genLabel (ic);
12979           break;
12980
12981         case GOTO:
12982           genGoto (ic);
12983           break;
12984
12985         case '+':
12986           genPlus (ic);
12987           break;
12988
12989         case '-':
12990           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12991             genMinus (ic);
12992           break;
12993
12994         case '*':
12995           genMult (ic);
12996           break;
12997
12998         case '/':
12999           genDiv (ic);
13000           break;
13001
13002         case '%':
13003           genMod (ic);
13004           break;
13005
13006         case '>':
13007           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13008           break;
13009
13010         case '<':
13011           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13012           break;
13013
13014         case LE_OP:
13015         case GE_OP:
13016         case NE_OP:
13017
13018           /* note these two are xlated by algebraic equivalence
13019              during parsing SDCC.y */
13020           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13021                   "got '>=' or '<=' shouldn't have come here");
13022           break;
13023
13024         case EQ_OP:
13025           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13026           break;
13027
13028         case AND_OP:
13029           genAndOp (ic);
13030           break;
13031
13032         case OR_OP:
13033           genOrOp (ic);
13034           break;
13035
13036         case '^':
13037           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13038           break;
13039
13040         case '|':
13041           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13042           break;
13043
13044         case BITWISEAND:
13045           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13046           break;
13047
13048         case INLINEASM:
13049           genInline (ic);
13050           break;
13051
13052         case RRC:
13053           genRRC (ic);
13054           break;
13055
13056         case RLC:
13057           genRLC (ic);
13058           break;
13059
13060         case GETHBIT:
13061           genGetHbit (ic);
13062           break;
13063
13064         case LEFT_OP:
13065           genLeftShift (ic);
13066           break;
13067
13068         case RIGHT_OP:
13069           genRightShift (ic);
13070           break;
13071
13072         case GET_VALUE_AT_ADDRESS:
13073           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13074           break;
13075
13076         case '=':
13077           if (POINTER_SET (ic))
13078             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13079           else
13080             genAssign (ic);
13081           break;
13082
13083         case IFX:
13084           genIfx (ic, NULL);
13085           break;
13086
13087         case ADDRESS_OF:
13088           genAddrOf (ic);
13089           break;
13090
13091         case JUMPTABLE:
13092           genJumpTab (ic);
13093           break;
13094
13095         case CAST:
13096           genCast (ic);
13097           break;
13098
13099         case RECEIVE:
13100           genReceive (ic);
13101           break;
13102
13103         case SEND:
13104           if (ic->builtinSEND) genBuiltIn(ic);
13105           else addSet (&_G.sendSet, ic);
13106           break;
13107
13108         case DUMMY_READ_VOLATILE:
13109           genDummyRead (ic);
13110           break;
13111
13112         case CRITICAL:
13113           genCritical (ic);
13114           break;
13115
13116         case ENDCRITICAL:
13117           genEndCritical (ic);
13118           break;
13119           
13120 #if 0 // obsolete, and buggy for != xdata
13121         case ARRAYINIT:
13122             genArrayInit(ic);
13123             break;
13124 #endif
13125             
13126         default:
13127           ic = ic;
13128         }
13129     }
13130
13131
13132   /* now we are ready to call the
13133      peep hole optimizer */
13134   if (!options.nopeep)
13135     peepHole (&lineHead);
13136
13137   /* now do the actual printing */
13138   printLine (lineHead, codeOutFile);
13139   return;
13140 }