]> git.gag.com Git - fw/sdcc/blob - src/ds390/gen.c
* configure,
[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 "main.h"
35 #include "ralloc.h"
36 #include "gen.h"
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #define BETTER_LITERAL_SHIFT
41
42 char *aopLiteral (value * val, int offset);
43 extern int allocInfo;
44
45 /* this is the down and dirty file with all kinds of
46    kludgy & hacky stuff. This is what it is all about
47    CODE GENERATION for a specific MCU . some of the
48    routines may be reusable, will have to see */
49
50 static char *zero = "#0";
51 static char *one = "#1";
52 static char *spname;
53
54 #define D(x) x
55
56 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
57 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
58
59 short fReturnSizeDS390 = 5;
60 static char *fReturn24[] =
61 {"dpl", "dph", "dpx", "b", "a"};
62 static char *fReturn16[] =
63 {"dpl", "dph", "b", "a"};
64 static char **fReturn = fReturn24;
65 static char *accUse[] =
66 {"a", "b"};
67 static char *dptrn[2][3];
68 static char *javaRet[] = { "r0","r1","r2","r3"};
69 static short rbank = -1;
70
71 static struct
72   {
73     short r0Pushed;
74     short r1Pushed;
75     short accInUse;
76     short bInUse;
77     short inLine;
78     short debugLine;
79     short nRegsSaved;
80     short dptrInUse;
81     short dptr1InUse;
82     set *sendSet;
83     iCode *current_iCode;
84   }
85 _G;
86
87 static char *rb1regs[] = {
88     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
89 };
90
91 static void saveRBank (int, iCode *, bool);
92
93 #define RESULTONSTACK(x) \
94                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
95                          IC_RESULT(x)->aop->type == AOP_STK )
96
97 #define MOVA(x) _movA(x)
98 #define MOVB(x) _movB(x)
99
100 #define CLRC    emitcode("clr","c")
101 #define SETC    emitcode("setb","c")
102
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG  "_ap"
106
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
109
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112  0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115  0x07, 0x03, 0x01, 0x00};
116
117 #define LSB     0
118 #define MSB16   1
119 #define MSB24   2
120 #define MSB32   3
121 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
122                                 symbol *lbl = newiTempLabel(NULL);              \
123                                 emitcode ("setb","F1");                         \
124                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
125                                 emitcode ("clr","F1");                          \
126                                 emitcode ("","!tlabeldef",lbl->key+100);        \
127                         }}
128 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
129                                 symbol *lbl = newiTempLabel(NULL);              \
130                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
131                                 emitcode ("setb","EA");                         \
132                                 emitcode ("","!tlabeldef",lbl->key+100);        \
133                         }}
134
135 static int _currentDPS;         /* Current processor DPS. */
136 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
137 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
138
139 /*-----------------------------------------------------------------*/
140 /* emitcode - writes the code into a file : for now it is simple    */
141 /*-----------------------------------------------------------------*/
142 static void
143 emitcode (char *inst, const char *fmt,...)
144 {
145   va_list ap;
146   char lb[INITIAL_INLINEASM];
147   char *lbp = lb;
148
149   va_start (ap, fmt);
150
151   if (inst && *inst)
152     {
153       if (fmt && *fmt)
154         {
155           SNPRINTF (lb, sizeof(lb), "%s\t", inst);
156         }
157       else
158         {
159           SNPRINTF (lb, sizeof(lb), "%s", inst);
160         }
161
162       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
163     }
164   else
165     {
166       tvsprintf (lb, sizeof(lb), fmt, ap);
167     }
168
169   while (isspace ((unsigned char)*lbp))
170     {
171       lbp++;
172     }
173
174   if (lbp && *lbp)
175     {
176       lineCurr = (lineCurr ?
177                   connectLine (lineCurr, newLineNode (lb)) :
178                   (lineHead = newLineNode (lb)));
179     }
180
181   lineCurr->isInline = _G.inLine;
182   lineCurr->isDebug = _G.debugLine;
183   lineCurr->ic = _G.current_iCode;
184   lineCurr->aln = ds390newAsmLineNode(_currentDPS);
185   va_end (ap);
186 }
187
188 /*-----------------------------------------------------------------*/
189 /* ds390_emitDebuggerSymbol - associate the current code location  */
190 /*   with a debugger symbol                                        */
191 /*-----------------------------------------------------------------*/
192 void
193 ds390_emitDebuggerSymbol (char * debugSym)
194 {
195   _G.debugLine = 1;
196   emitcode ("", "%s ==.", debugSym);
197   _G.debugLine = 0;
198 }
199
200 //
201 // Move the passed value into A unless it is already there.
202 //
203 static void
204 _movA(const char *s)
205 {
206     if (strcmp(s,"a") && strcmp(s,"acc"))
207     {
208         emitcode("mov","a,%s",s);
209     }
210 }
211
212 //
213 // Move the passed value into B unless it is already there.
214 //
215 static void
216 _movB(const char *s)
217 {
218     if (strcmp(s,"b"))
219     {
220         emitcode("mov","b,%s",s);
221     }
222 }
223
224 /*-----------------------------------------------------------------*/
225 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
226 /*-----------------------------------------------------------------*/
227 static regs *
228 getFreePtr (iCode * ic, asmop ** aopp, bool result)
229 {
230   bool r0iu, r1iu;
231   bool r0ou, r1ou;
232
233   /* the logic: if r0 & r1 used in the instruction
234      then we are in trouble otherwise */
235
236   /* first check if r0 & r1 are used by this
237      instruction, in which case we are in trouble */
238   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
239   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
240   if (r0iu && r1iu) {
241       goto endOfWorld;
242     }
243
244   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
245   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
246
247   /* if no usage of r0 then return it */
248   if (!r0iu && !r0ou)
249     {
250       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
251       (*aopp)->type = AOP_R0;
252
253       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
254     }
255
256   /* if no usage of r1 then return it */
257   if (!r1iu && !r1ou)
258     {
259       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
260       (*aopp)->type = AOP_R1;
261
262       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
263     }
264
265   /* now we know they both have usage */
266   /* if r0 not used in this instruction */
267   if (!r0iu)
268     {
269       /* push it if not already pushed */
270       if (!_G.r0Pushed)
271         {
272           emitcode ("push", "%s",
273                     ds390_regWithIdx (R0_IDX)->dname);
274           _G.r0Pushed++;
275         }
276
277       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
278       (*aopp)->type = AOP_R0;
279
280       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
281     }
282
283   /* if r1 not used then */
284
285   if (!r1iu)
286     {
287       /* push it if not already pushed */
288       if (!_G.r1Pushed)
289         {
290           emitcode ("push", "%s",
291                     ds390_regWithIdx (R1_IDX)->dname);
292           _G.r1Pushed++;
293         }
294
295       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
296       (*aopp)->type = AOP_R1;
297       return ds390_regWithIdx (R1_IDX);
298     }
299
300 endOfWorld:
301   /* I said end of world but not quite end of world yet */
302   /* if this is a result then we can push it on the stack */
303   if (result)
304     {
305       (*aopp)->type = AOP_STK;
306       return NULL;
307     }
308
309   /* other wise this is true end of the world */
310   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
311           "getFreePtr should never reach here");
312   exit (1);
313
314   return NULL; // notreached, but makes compiler happy.
315 }
316
317 /*-----------------------------------------------------------------*/
318 /* newAsmop - creates a new asmOp                                  */
319 /*-----------------------------------------------------------------*/
320 static asmop *
321 newAsmop (short type)
322 {
323   asmop *aop;
324
325   aop = Safe_calloc (1, sizeof (asmop));
326   aop->type = type;
327   return aop;
328 }
329
330
331 /*-----------------------------------------------------------------*/
332 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
333 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
334 /* alternate DPTR (DPL1/DPH1/DPX1).          */
335 /*-----------------------------------------------------------------*/
336 static void
337 genSetDPTR (int n)
338 {
339
340   /* If we are doing lazy evaluation, simply note the desired
341    * change, but don't emit any code yet.
342    */
343   if (_lazyDPS)
344     {
345       _desiredDPS = n;
346       return;
347     }
348
349   if (!n)
350     {
351       emitcode ("mov", "dps,#0");
352     }
353   else
354     {
355       TR_DPTR("#1");
356       emitcode ("mov", "dps,#1");
357     }
358 }
359
360 /*-----------------------------------------------------------------*/
361 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
362 /*                   */
363 /* Any code that operates on DPTR (NB: not on the individual     */
364 /* components, like DPH) *must* call _flushLazyDPS() before using  */
365 /* DPTR within a lazy DPS evaluation block.        */
366 /*                   */
367 /* Note that aopPut and aopGet already contain the proper calls to */
368 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
369 /* DPS evaluation block.             */
370 /*                   */
371 /* Also, _flushLazyDPS must be called before any flow control      */
372 /* operations that could potentially branch out of the block.    */
373 /*                         */
374 /* Lazy DPS evaluation is simply an optimization (though an      */
375 /* important one), so if in doubt, leave it out.       */
376 /*-----------------------------------------------------------------*/
377 static void
378 _startLazyDPSEvaluation (void)
379 {
380   _currentDPS = 0;
381   _desiredDPS = 0;
382 #ifdef BETTER_LITERAL_SHIFT
383   _lazyDPS++;
384 #else
385   _lazyDPS = 1;
386 #endif
387 }
388
389 /*-----------------------------------------------------------------*/
390 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
391 /* desired one. Call before using DPTR within a lazy DPS evaluation */
392 /* block.                */
393 /*-----------------------------------------------------------------*/
394 static void
395 _flushLazyDPS (void)
396 {
397   if (!_lazyDPS)
398     {
399       /* nothing to do. */
400       return;
401     }
402
403   if (_desiredDPS != _currentDPS)
404     {
405       if (_desiredDPS)
406         {
407           emitcode ("inc", "dps");
408         }
409       else
410         {
411           emitcode ("dec", "dps");
412         }
413       _currentDPS = _desiredDPS;
414     }
415 }
416
417 /*-----------------------------------------------------------------*/
418 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
419 /*                   */
420 /* Forces us back to the safe state (standard DPTR selected).    */
421 /*-----------------------------------------------------------------*/
422 static void
423 _endLazyDPSEvaluation (void)
424 {
425 #ifdef BETTER_LITERAL_SHIFT
426   _lazyDPS--;
427 #else
428   _lazyDPS = 0;
429 #endif
430   if (!_lazyDPS)
431   {
432     if (_currentDPS)
433     {
434       genSetDPTR (0);
435       _flushLazyDPS ();
436     }
437     _currentDPS = 0;
438     _desiredDPS = 0;
439   }
440 }
441
442
443
444 /*-----------------------------------------------------------------*/
445 /* pointerCode - returns the code for a pointer type               */
446 /*-----------------------------------------------------------------*/
447 static int
448 pointerCode (sym_link * etype)
449 {
450
451   return PTR_TYPE (SPEC_OCLS (etype));
452
453 }
454
455 /*-----------------------------------------------------------------*/
456 /* leftRightUseAcc - returns size of accumulator use by operands   */
457 /*-----------------------------------------------------------------*/
458 static int
459 leftRightUseAcc(iCode *ic)
460 {
461   operand *op;
462   int size;
463   int accuseSize = 0;
464   int accuse = 0;
465
466   if (!ic)
467     {
468       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
469               "null iCode pointer");
470       return 0;
471     }
472
473   if (ic->op == IFX)
474     {
475       op = IC_COND (ic);
476       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
477         {
478           accuse = 1;
479           size = getSize (OP_SYMBOL (op)->type);
480           if (size>accuseSize)
481             accuseSize = size;
482         }
483     }
484   else if (ic->op == JUMPTABLE)
485     {
486       op = IC_JTCOND (ic);
487       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
488         {
489           accuse = 1;
490           size = getSize (OP_SYMBOL (op)->type);
491           if (size>accuseSize)
492             accuseSize = size;
493         }
494     }
495   else
496     {
497       op = IC_LEFT (ic);
498       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
499         {
500           accuse = 1;
501           size = getSize (OP_SYMBOL (op)->type);
502           if (size>accuseSize)
503             accuseSize = size;
504         }
505       op = IC_RIGHT (ic);
506       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
507         {
508           accuse = 1;
509           size = getSize (OP_SYMBOL (op)->type);
510           if (size>accuseSize)
511             accuseSize = size;
512         }
513     }
514
515   if (accuseSize)
516     return accuseSize;
517   else
518     return accuse;
519 }
520
521 /*-----------------------------------------------------------------*/
522 /* aopForSym - for a true symbol                                   */
523 /*-----------------------------------------------------------------*/
524 static asmop *
525 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
526 {
527   asmop *aop;
528   memmap *space = SPEC_OCLS (sym->etype);
529   int accuse = leftRightUseAcc (ic);
530
531   /* if already has one */
532   if (sym->aop)
533     {
534       if ((sym->aop->type == AOP_DPTR && useDP2)
535           || (sym->aop->type == AOP_DPTR2 && !useDP2))
536         sym->aop = NULL;
537       else
538         return sym->aop;
539     }
540
541   /* assign depending on the storage class */
542   /* if it is on the stack or indirectly addressable */
543   /* space we need to assign either r0 or r1 to it   */
544   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
545     {
546       sym->aop = aop = newAsmop (0);
547       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
548       aop->size = getSize (sym->type);
549
550       /* now assign the address of the variable to
551          the pointer register */
552       if (aop->type != AOP_STK)
553         {
554
555           if (sym->onStack)
556             {
557               if (_G.accInUse || accuse)
558                 emitcode ("push", "acc");
559
560               if (_G.bInUse || (accuse>1))
561                 emitcode ("push", "b");
562
563               emitcode ("mov", "a,_bp");
564               emitcode ("add", "a,#!constbyte",
565                         ((sym->stack < 0) ?
566                          ((char) (sym->stack - _G.nRegsSaved)) :
567                          ((char) sym->stack)) & 0xff);
568               emitcode ("mov", "%s,a",
569                         aop->aopu.aop_ptr->name);
570
571               if (_G.bInUse || (accuse>1))
572                 emitcode ("pop", "b");
573
574               if (_G.accInUse || accuse)
575                 emitcode ("pop", "acc");
576             }
577           else
578             emitcode ("mov", "%s,#%s",
579                       aop->aopu.aop_ptr->name,
580                       sym->rname);
581           aop->paged = space->paged;
582         }
583       else
584         aop->aopu.aop_stk = sym->stack;
585       return aop;
586     }
587
588   if (sym->onStack && options.stack10bit)
589     {
590         short stack_val = -((sym->stack < 0) ?
591                             ((short) (sym->stack - _G.nRegsSaved)) :
592                             ((short) sym->stack)) ;
593         if (useDP2 && _G.dptr1InUse) {
594             emitcode ("push","dpl1");
595             emitcode ("push","dph1");
596             emitcode ("push","dpx1");
597         } else if (_G.dptrInUse ) {
598             emitcode ("push","dpl");
599             emitcode ("push","dph");
600             emitcode ("push","dpx");
601         }
602       /* It's on the 10 bit stack, which is located in
603        * far data space.
604        */
605         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
606             if (useDP2) {
607                 if (options.model == MODEL_FLAT24)
608                 {
609                     emitcode ("mov", "dpx1,#!constbyte",
610                               (options.stack_loc >> 16) & 0xff);
611                 }
612                 emitcode ("mov", "dph1,_bpx+1");
613
614                 emitcode ("mov", "dpl1,_bpx");
615                 emitcode ("mov","dps,#1");
616             } else {
617                 if (options.model == MODEL_FLAT24)
618                 {
619                     emitcode ("mov", "dpx,#!constbyte",
620                               (options.stack_loc >> 16) & 0xff);
621                 }
622                 emitcode ("mov", "dph,_bpx+1");
623                 emitcode ("mov", "dpl,_bpx");
624             }
625             stack_val = -stack_val;
626             while (stack_val--) {
627                 emitcode ("inc","dptr");
628             }
629             if (useDP2) {
630                 emitcode("mov","dps,#0");
631             }
632         }  else {
633             if (_G.accInUse || accuse)
634                 emitcode ("push", "acc");
635
636             if (_G.bInUse || (accuse>1))
637                 emitcode ("push", "b");
638
639             emitcode ("mov", "a,_bpx");
640             emitcode ("clr","c");
641             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
642             emitcode ("mov","b,a");
643             emitcode ("mov","a,_bpx+1");
644             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
645             if (useDP2) {
646                 if (options.model == MODEL_FLAT24)
647                 {
648                     emitcode ("mov", "dpx1,#!constbyte",
649                               (options.stack_loc >> 16) & 0xff);
650                 }
651                 emitcode ("mov", "dph1,a");
652                 emitcode ("mov", "dpl1,b");
653             } else {
654                 if (options.model == MODEL_FLAT24)
655                 {
656                     emitcode ("mov", "dpx,#!constbyte",
657                               (options.stack_loc >> 16) & 0xff);
658                 }
659                 emitcode ("mov", "dph,a");
660                 emitcode ("mov", "dpl,b");
661             }
662
663             if (_G.bInUse || (accuse>1))
664                 emitcode ("pop", "b");
665
666             if (_G.accInUse || accuse)
667                 emitcode ("pop", "acc");
668         }
669         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
670         aop->size = getSize (sym->type);
671         return aop;
672     }
673
674   /* if in bit space */
675   if (IN_BITSPACE (space))
676     {
677       sym->aop = aop = newAsmop (AOP_CRY);
678       aop->aopu.aop_dir = sym->rname;
679       aop->size = getSize (sym->type);
680       return aop;
681     }
682   /* if it is in direct space */
683   if (IN_DIRSPACE (space))
684     {
685       sym->aop = aop = newAsmop (AOP_DIR);
686       aop->aopu.aop_dir = sym->rname;
687       aop->size = getSize (sym->type);
688       return aop;
689     }
690
691   /* special case for a function */
692   if (IS_FUNC (sym->type) && !(sym->isitmp))
693     {
694       sym->aop = aop = newAsmop (AOP_IMMD);
695       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696       aop->size = FPTRSIZE;
697       return aop;
698     }
699
700   /* only remaining is far space */
701   /* in which case DPTR gets the address */
702   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
703   if (useDP2)
704     {
705       genSetDPTR (1);
706       _flushLazyDPS ();
707       emitcode ("mov", "dptr,#%s", sym->rname);
708       genSetDPTR (0);
709     }
710   else
711     {
712       emitcode ("mov", "dptr,#%s", sym->rname);
713     }
714   aop->size = getSize (sym->type);
715
716   /* if it is in code space */
717   if (IN_CODESPACE (space))
718     aop->code = 1;
719
720   return aop;
721 }
722
723 /*-----------------------------------------------------------------*/
724 /* aopForRemat - rematerialzes an object                           */
725 /*-----------------------------------------------------------------*/
726 static asmop *
727 aopForRemat (symbol * sym)
728 {
729   iCode *ic = sym->rematiCode;
730   asmop *aop = newAsmop (AOP_IMMD);
731   int ptr_type = 0;
732   int val = 0;
733
734   for (;;)
735     {
736       if (ic->op == '+')
737         val += (int) operandLitValue (IC_RIGHT (ic));
738       else if (ic->op == '-')
739         val -= (int) operandLitValue (IC_RIGHT (ic));
740       else if (IS_CAST_ICODE(ic)) {
741               sym_link *from_type = operandType(IC_RIGHT(ic));
742               aop->aopu.aop_immd.from_cast_remat = 1;
743               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
744               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
745               continue;
746       } else break;
747
748       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
749     }
750
751   if (val)
752   {
753       SNPRINTF (buffer, sizeof(buffer),
754                 "(%s %c 0x%04x)",
755                 OP_SYMBOL (IC_LEFT (ic))->rname,
756                 val >= 0 ? '+' : '-',
757                 abs (val) & 0xffffff);
758   }
759   else
760   {
761       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
762       {
763           SNPRINTF(buffer, sizeof(buffer),
764                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
765       }
766       else
767       {
768           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
769       }
770   }
771
772   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
773   /* set immd2 field if required */
774   if (aop->aopu.aop_immd.from_cast_remat)
775   {
776       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
777       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
778   }
779
780   return aop;
781 }
782
783 /*-----------------------------------------------------------------*/
784 /* aopHasRegs - returns true if aop has regs between from-to       */
785 /*-----------------------------------------------------------------*/
786 static int aopHasRegs(asmop *aop, int from, int to)
787 {
788     int size =0;
789
790     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
791
792     for (; size < aop->size ; size++) {
793         int reg;
794         for (reg = from ; reg <= to ; reg++)
795             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
796     }
797     return 0;
798 }
799
800 /*-----------------------------------------------------------------*/
801 /* regsInCommon - two operands have some registers in common       */
802 /*-----------------------------------------------------------------*/
803 static bool
804 regsInCommon (operand * op1, operand * op2)
805 {
806   symbol *sym1, *sym2;
807   int i;
808
809   /* if they have registers in common */
810   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
811     return FALSE;
812
813   sym1 = OP_SYMBOL (op1);
814   sym2 = OP_SYMBOL (op2);
815
816   if (sym1->nRegs == 0 || sym2->nRegs == 0)
817     return FALSE;
818
819   for (i = 0; i < sym1->nRegs; i++)
820     {
821       int j;
822       if (!sym1->regs[i])
823         continue;
824
825       for (j = 0; j < sym2->nRegs; j++)
826         {
827           if (!sym2->regs[j])
828             continue;
829
830           if (sym2->regs[j] == sym1->regs[i])
831             return TRUE;
832         }
833     }
834
835   return FALSE;
836 }
837
838 /*-----------------------------------------------------------------*/
839 /* operandsEqu - equivalent                                        */
840 /*-----------------------------------------------------------------*/
841 static bool
842 operandsEqu (operand * op1, operand * op2)
843 {
844   symbol *sym1, *sym2;
845
846   /* if they not symbols */
847   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
848     return FALSE;
849
850   sym1 = OP_SYMBOL (op1);
851   sym2 = OP_SYMBOL (op2);
852
853   /* if both are itemps & one is spilt
854      and the other is not then false */
855   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
856       sym1->isspilt != sym2->isspilt)
857     return FALSE;
858
859   /* if they are the same */
860   if (sym1 == sym2)
861     return TRUE;
862
863   if (sym1->rname[0] && sym2->rname[0]
864       && strcmp (sym1->rname, sym2->rname) == 0)
865     return TRUE;
866
867   /* if left is a tmp & right is not */
868   if (IS_ITEMP (op1) &&
869       !IS_ITEMP (op2) &&
870       sym1->isspilt &&
871       (sym1->usl.spillLoc == sym2))
872     return TRUE;
873
874   if (IS_ITEMP (op2) &&
875       !IS_ITEMP (op1) &&
876       sym2->isspilt &&
877       sym1->level > 0 &&
878       (sym2->usl.spillLoc == sym1))
879     return TRUE;
880
881   /* are they spilt to the same location */
882   if (IS_ITEMP (op2) &&
883       IS_ITEMP (op1) &&
884       sym2->isspilt &&
885       sym1->isspilt &&
886       (sym1->usl.spillLoc == sym2->usl.spillLoc))
887     return TRUE;
888
889   return FALSE;
890 }
891
892 /*-----------------------------------------------------------------*/
893 /* sameRegs - two asmops have the same registers                   */
894 /*-----------------------------------------------------------------*/
895 static bool
896 sameRegs (asmop * aop1, asmop * aop2)
897 {
898   int i;
899
900   if (aop1 == aop2)
901     {
902       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
903         {
904           return FALSE;
905         }
906       return TRUE;
907     }
908
909   if (aop1->type != AOP_REG ||
910       aop2->type != AOP_REG)
911     return FALSE;
912
913   if (aop1->size != aop2->size)
914     return FALSE;
915
916   for (i = 0; i < aop1->size; i++)
917     if (aop1->aopu.aop_reg[i] !=
918         aop2->aopu.aop_reg[i])
919       return FALSE;
920
921   return TRUE;
922 }
923
924 /*-----------------------------------------------------------------*/
925 /* aopOp - allocates an asmop for an operand  :                    */
926 /*-----------------------------------------------------------------*/
927 static void
928 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
929 {
930   asmop *aop;
931   symbol *sym;
932   int i;
933
934   if (!op)
935     return;
936
937   /* if this a literal */
938   if (IS_OP_LITERAL (op))
939     {
940       op->aop = aop = newAsmop (AOP_LIT);
941       aop->aopu.aop_lit = op->operand.valOperand;
942       aop->size = getSize (operandType (op));
943       return;
944     }
945
946   /* if already has a asmop then continue */
947   if (op->aop)
948     {
949       if ((op->aop->type == AOP_DPTR && useDP2)
950           || (op->aop->type == AOP_DPTR2 && !useDP2))
951         op->aop = NULL;
952       else
953         return;
954     }
955
956   /* if the underlying symbol has a aop */
957   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
958     {
959       op->aop = OP_SYMBOL (op)->aop;
960       if ((op->aop->type == AOP_DPTR && useDP2)
961           || (op->aop->type == AOP_DPTR2 && !useDP2))
962         op->aop = NULL;
963       else
964         return;
965     }
966
967   /* if this is a true symbol */
968   if (IS_TRUE_SYMOP (op))
969     {
970       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
971       return;
972     }
973
974   /* this is a temporary : this has
975      only four choices :
976      a) register
977      b) spillocation
978      c) rematerialize
979      d) conditional
980      e) can be a return use only */
981
982   sym = OP_SYMBOL (op);
983
984   /* if the type is a conditional */
985   if (sym->regType == REG_CND)
986     {
987       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
988       aop->size = 0;
989       return;
990     }
991
992   /* if it is spilt then two situations
993      a) is rematerialize
994      b) has a spill location */
995   if (sym->isspilt || sym->nRegs == 0)
996     {
997
998       /* rematerialize it NOW */
999       if (sym->remat)
1000         {
1001           sym->aop = op->aop = aop =
1002             aopForRemat (sym);
1003           aop->size = getSize (sym->type);
1004           return;
1005         }
1006
1007       if (sym->accuse)
1008         {
1009           int i;
1010           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1011           aop->size = getSize (sym->type);
1012           for (i = 0; i < 2; i++)
1013             aop->aopu.aop_str[i] = accUse[i];
1014           return;
1015         }
1016
1017       if (sym->ruonly)
1018         {
1019           int i;
1020
1021           if (useDP2)
1022             {
1023               /* a AOP_STR uses DPTR, but DPTR is already in use;
1024                * we're just hosed.
1025                */
1026                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1027             }
1028
1029           aop = op->aop = sym->aop = newAsmop (AOP_STR);
1030           aop->size = getSize (sym->type);
1031           for (i = 0; i < fReturnSizeDS390; i++)
1032             aop->aopu.aop_str[i] = fReturn[i];
1033           return;
1034         }
1035
1036       if (sym->dptr) { /* has been allocated to a DPTRn */
1037           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1038           aop->size = getSize (sym->type);
1039           aop->aopu.dptr = sym->dptr;
1040           return ;
1041       }
1042
1043       if (sym->usl.spillLoc)
1044         {
1045           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1046             {
1047               /* force a new aop if sizes differ */
1048               sym->usl.spillLoc->aop = NULL;
1049             }
1050           sym->aop = op->aop = aop =
1051                      aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1052           aop->size = getSize (sym->type);
1053           return;
1054         }
1055
1056       /* else must be a dummy iTemp */
1057       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1058       aop->size = getSize (sym->type);
1059       return;
1060     }
1061
1062   /* must be in a register */
1063   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1064   aop->size = sym->nRegs;
1065   for (i = 0; i < sym->nRegs; i++)
1066     aop->aopu.aop_reg[i] = sym->regs[i];
1067 }
1068
1069 /*-----------------------------------------------------------------*/
1070 /* freeAsmop - free up the asmop given to an operand               */
1071 /*----------------------------------------------------------------*/
1072 static void
1073 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1074 {
1075   asmop *aop;
1076
1077   if (!op)
1078     aop = aaop;
1079   else
1080     aop = op->aop;
1081
1082   if (!aop)
1083     return;
1084
1085   if (aop->freed)
1086     goto dealloc;
1087
1088   aop->freed = 1;
1089
1090   /* depending on the asmop type only three cases need work AOP_RO
1091      , AOP_R1 && AOP_STK */
1092   switch (aop->type)
1093     {
1094     case AOP_R0:
1095       if (_G.r0Pushed)
1096         {
1097           if (pop)
1098             {
1099               emitcode ("pop", "ar0");
1100               _G.r0Pushed--;
1101             }
1102         }
1103       bitVectUnSetBit (ic->rUsed, R0_IDX);
1104       break;
1105
1106     case AOP_R1:
1107       if (_G.r1Pushed)
1108         {
1109           if (pop)
1110             {
1111               emitcode ("pop", "ar1");
1112               _G.r1Pushed--;
1113             }
1114         }
1115       bitVectUnSetBit (ic->rUsed, R1_IDX);
1116       break;
1117
1118     case AOP_STK:
1119       {
1120         int sz = aop->size;
1121         int stk = aop->aopu.aop_stk + aop->size;
1122         bitVectUnSetBit (ic->rUsed, R0_IDX);
1123         bitVectUnSetBit (ic->rUsed, R1_IDX);
1124
1125         getFreePtr (ic, &aop, FALSE);
1126
1127         if (options.stack10bit)
1128           {
1129             /* I'm not sure what to do here yet... */
1130             /* #STUB */
1131             fprintf (stderr,
1132                      "*** Warning: probably generating bad code for "
1133                      "10 bit stack mode.\n");
1134           }
1135
1136         if (stk)
1137           {
1138             emitcode ("mov", "a,_bp");
1139             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1140             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1141           }
1142         else
1143           {
1144             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1145           }
1146
1147         while (sz--)
1148           {
1149             emitcode ("pop", "acc");
1150             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1151             if (!sz)
1152               break;
1153             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1154           }
1155         op->aop = aop;
1156         freeAsmop (op, NULL, ic, TRUE);
1157         if (_G.r0Pushed)
1158           {
1159             emitcode ("pop", "ar0");
1160             _G.r0Pushed--;
1161           }
1162
1163         if (_G.r1Pushed)
1164           {
1165             emitcode ("pop", "ar1");
1166             _G.r1Pushed--;
1167           }
1168       }
1169     case AOP_DPTR2:
1170         if (_G.dptr1InUse) {
1171             emitcode ("pop","dpx1");
1172             emitcode ("pop","dph1");
1173             emitcode ("pop","dpl1");
1174         }
1175         break;
1176     case AOP_DPTR:
1177         if (_G.dptrInUse) {
1178             emitcode ("pop","dpx");
1179             emitcode ("pop","dph");
1180             emitcode ("pop","dpl");
1181         }
1182         break;
1183     }
1184 dealloc:
1185   /* all other cases just dealloc */
1186   if (op)
1187     {
1188       op->aop = NULL;
1189       if (IS_SYMOP (op))
1190         {
1191           OP_SYMBOL (op)->aop = NULL;
1192           /* if the symbol has a spill */
1193           if (SPIL_LOC (op))
1194             SPIL_LOC (op)->aop = NULL;
1195         }
1196     }
1197 }
1198
1199 #define DEFAULT_ACC_WARNING 0
1200 static int saveAccWarn = DEFAULT_ACC_WARNING;
1201
1202 /*-------------------------------------------------------------------*/
1203 /* aopGet - for fetching value of the aop                            */
1204 /*                                                                   */
1205 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1206 /* in the accumulator. Set it to the name of a free register         */
1207 /* if acc must be preserved; the register will be used to preserve   */
1208 /* acc temporarily and to return the result byte.                    */
1209 /*-------------------------------------------------------------------*/
1210
1211 static char *
1212 aopGet (asmop *aop,
1213         int   offset,
1214         bool  bit16,
1215         bool  dname,
1216         char  *saveAcc)
1217 {
1218   /* offset is greater than
1219      size then zero */
1220   if (offset > (aop->size - 1) &&
1221       aop->type != AOP_LIT)
1222     return zero;
1223
1224   /* depending on type */
1225   switch (aop->type)
1226     {
1227     case AOP_DUMMY:
1228       return zero;
1229
1230     case AOP_R0:
1231     case AOP_R1:
1232       /* if we need to increment it */
1233       while (offset > aop->coff)
1234         {
1235           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1236           aop->coff++;
1237         }
1238
1239       while (offset < aop->coff)
1240         {
1241           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1242           aop->coff--;
1243         }
1244
1245       aop->coff = offset;
1246       if (aop->paged)
1247         {
1248           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1249           return (dname ? "acc" : "a");
1250         }
1251       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1252       return Safe_strdup(buffer);
1253
1254     case AOP_DPTRn:
1255         assert(offset <= 3);
1256         return dptrn[aop->aopu.dptr][offset];
1257
1258     case AOP_DPTR:
1259     case AOP_DPTR2:
1260
1261       if (aop->type == AOP_DPTR2)
1262         {
1263           genSetDPTR (1);
1264         }
1265
1266       if (saveAcc)
1267         {
1268             TR_AP("#1");
1269 //          if (aop->type != AOP_DPTR2)
1270 //          {
1271 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1272 //              emitcode(";", "spanky: saveAcc for DPTR");
1273 //          }
1274
1275             emitcode ("xch", "a, %s", saveAcc);
1276         }
1277
1278       _flushLazyDPS ();
1279
1280       while (offset > aop->coff)
1281         {
1282           emitcode ("inc", "dptr");
1283           aop->coff++;
1284         }
1285
1286       while (offset < aop->coff)
1287         {
1288           emitcode ("lcall", "__decdptr");
1289           aop->coff--;
1290         }
1291
1292       aop->coff = offset;
1293       if (aop->code)
1294         {
1295           emitcode ("clr", "a");
1296           emitcode ("movc", "a,@a+dptr");
1297         }
1298       else
1299         {
1300           emitcode ("movx", "a,@dptr");
1301         }
1302
1303       if (aop->type == AOP_DPTR2)
1304         {
1305           genSetDPTR (0);
1306         }
1307
1308         if (saveAcc)
1309         {
1310        TR_AP("#2");
1311               emitcode ("xch", "a, %s", saveAcc);
1312 //            if (strcmp(saveAcc, "_ap"))
1313 //            {
1314 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1315 //            }
1316
1317               return saveAcc;
1318         }
1319       return (dname ? "acc" : "a");
1320
1321     case AOP_IMMD:
1322       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1323       {
1324           SNPRINTF(buffer, sizeof(buffer),
1325                    "%s",aop->aopu.aop_immd.aop_immd2);
1326       }
1327       else if (bit16)
1328       {
1329          SNPRINTF(buffer, sizeof(buffer),
1330                   "#%s", aop->aopu.aop_immd.aop_immd1);
1331       }
1332       else if (offset)
1333       {
1334           switch (offset) {
1335           case 1:
1336               tsprintf(buffer, sizeof(buffer),
1337                        "#!his",aop->aopu.aop_immd.aop_immd1);
1338               break;
1339           case 2:
1340               tsprintf(buffer, sizeof(buffer),
1341                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1342               break;
1343           case 3:
1344               tsprintf(buffer, sizeof(buffer),
1345                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1346               break;
1347           default: /* should not need this (just in case) */
1348               SNPRINTF (buffer, sizeof(buffer),
1349                         "#(%s >> %d)",
1350                        aop->aopu.aop_immd.aop_immd1,
1351                        offset * 8);
1352           }
1353       }
1354       else
1355       {
1356         SNPRINTF (buffer, sizeof(buffer),
1357                   "#%s", aop->aopu.aop_immd.aop_immd1);
1358       }
1359       return Safe_strdup(buffer);
1360
1361     case AOP_DIR:
1362       if (offset)
1363       {
1364         SNPRINTF (buffer, sizeof(buffer),
1365                   "(%s + %d)",
1366                  aop->aopu.aop_dir,
1367                  offset);
1368       }
1369       else
1370       {
1371         SNPRINTF(buffer, sizeof(buffer),
1372                  "%s", aop->aopu.aop_dir);
1373       }
1374
1375       return Safe_strdup(buffer);
1376
1377     case AOP_REG:
1378       if (dname)
1379         return aop->aopu.aop_reg[offset]->dname;
1380       else
1381         return aop->aopu.aop_reg[offset]->name;
1382
1383     case AOP_CRY:
1384       emitcode ("clr", "a");
1385       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1386       emitcode ("rlc", "a");
1387       return (dname ? "acc" : "a");
1388
1389     case AOP_ACC:
1390       if (!offset && dname)
1391         return "acc";
1392       return aop->aopu.aop_str[offset];
1393
1394     case AOP_LIT:
1395       return aopLiteral (aop->aopu.aop_lit, offset);
1396
1397     case AOP_STR:
1398       aop->coff = offset;
1399       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1400           dname)
1401         return "acc";
1402
1403       return aop->aopu.aop_str[offset];
1404
1405     }
1406
1407   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1408           "aopget got unsupported aop->type");
1409   exit (1);
1410
1411   return NULL;  // not reached, but makes compiler happy.
1412 }
1413 /*-----------------------------------------------------------------*/
1414 /* aopPut - puts a string for a aop                                */
1415 /*-----------------------------------------------------------------*/
1416 static void
1417 aopPut (asmop * aop, char *s, int offset)
1418 {
1419   if (aop->size && offset > (aop->size - 1))
1420     {
1421       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1422               "aopPut got offset > aop->size");
1423       exit (1);
1424     }
1425
1426   /* will assign value to value */
1427   /* depending on where it is ofcourse */
1428   switch (aop->type)
1429     {
1430     case AOP_DUMMY:
1431       MOVA (s);         /* read s in case it was volatile */
1432       break;
1433
1434     case AOP_DIR:
1435         if (offset)
1436         {
1437             SNPRINTF (buffer, sizeof(buffer),
1438                       "(%s + %d)",
1439                       aop->aopu.aop_dir, offset);
1440         }
1441         else
1442         {
1443             SNPRINTF (buffer, sizeof(buffer),
1444                      "%s", aop->aopu.aop_dir);
1445         }
1446
1447
1448         if (strcmp (buffer, s))
1449         {
1450             emitcode ("mov", "%s,%s", buffer, s);
1451         }
1452       break;
1453
1454     case AOP_REG:
1455       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1456           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1457         {
1458           if (*s == '@' ||
1459               strcmp (s, "r0") == 0 ||
1460               strcmp (s, "r1") == 0 ||
1461               strcmp (s, "r2") == 0 ||
1462               strcmp (s, "r3") == 0 ||
1463               strcmp (s, "r4") == 0 ||
1464               strcmp (s, "r5") == 0 ||
1465               strcmp (s, "r6") == 0 ||
1466               strcmp (s, "r7") == 0)
1467             {
1468                 emitcode ("mov", "%s,%s",
1469                           aop->aopu.aop_reg[offset]->dname, s);
1470             }
1471             else
1472             {
1473                 emitcode ("mov", "%s,%s",
1474                           aop->aopu.aop_reg[offset]->name, s);
1475             }
1476         }
1477       break;
1478
1479     case AOP_DPTRn:
1480         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1481         break;
1482
1483     case AOP_DPTR:
1484     case AOP_DPTR2:
1485
1486       if (aop->type == AOP_DPTR2)
1487         {
1488           genSetDPTR (1);
1489         }
1490       _flushLazyDPS ();
1491
1492       if (aop->code)
1493         {
1494           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1495                   "aopPut writting to code space");
1496           exit (1);
1497         }
1498
1499       while (offset > aop->coff)
1500         {
1501           aop->coff++;
1502           emitcode ("inc", "dptr");
1503         }
1504
1505       while (offset < aop->coff)
1506         {
1507           aop->coff--;
1508           emitcode ("lcall", "__decdptr");
1509         }
1510
1511       aop->coff = offset;
1512
1513       /* if not in accumulater */
1514       MOVA (s);
1515
1516       emitcode ("movx", "@dptr,a");
1517
1518       if (aop->type == AOP_DPTR2)
1519         {
1520           genSetDPTR (0);
1521         }
1522       break;
1523
1524     case AOP_R0:
1525     case AOP_R1:
1526       while (offset > aop->coff)
1527         {
1528           aop->coff++;
1529           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1530         }
1531       while (offset < aop->coff)
1532         {
1533           aop->coff--;
1534           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1535         }
1536       aop->coff = offset;
1537
1538       if (aop->paged)
1539         {
1540           MOVA (s);
1541           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1542
1543         }
1544       else if (*s == '@')
1545         {
1546           MOVA (s);
1547           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1548         }
1549       else if (strcmp (s, "r0") == 0 ||
1550                strcmp (s, "r1") == 0 ||
1551                strcmp (s, "r2") == 0 ||
1552                strcmp (s, "r3") == 0 ||
1553                strcmp (s, "r4") == 0 ||
1554                strcmp (s, "r5") == 0 ||
1555                strcmp (s, "r6") == 0 ||
1556                strcmp (s, "r7") == 0)
1557         {
1558           char buff[10];
1559           SNPRINTF(buff, sizeof(buff),
1560                    "a%s", s);
1561           emitcode ("mov", "@%s,%s",
1562                     aop->aopu.aop_ptr->name, buff);
1563         }
1564         else
1565         {
1566             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1567         }
1568       break;
1569
1570     case AOP_STK:
1571       if (strcmp (s, "a") == 0)
1572         emitcode ("push", "acc");
1573       else
1574         if (*s=='@') {
1575           MOVA(s);
1576           emitcode ("push", "acc");
1577         } else {
1578           emitcode ("push", s);
1579         }
1580
1581       break;
1582
1583     case AOP_CRY:
1584       /* if bit variable */
1585       if (!aop->aopu.aop_dir)
1586         {
1587           emitcode ("clr", "a");
1588           emitcode ("rlc", "a");
1589         }
1590       else
1591         {
1592           if (s == zero)
1593             emitcode ("clr", "%s", aop->aopu.aop_dir);
1594           else if (s == one)
1595             emitcode ("setb", "%s", aop->aopu.aop_dir);
1596           else if (!strcmp (s, "c"))
1597             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1598           else
1599             {
1600               if (strcmp (s, "a"))
1601                 {
1602                   MOVA (s);
1603                 }
1604               {
1605                 /* set C, if a >= 1 */
1606                 emitcode ("add", "a,#!constbyte",0xff);
1607                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1608               }
1609             }
1610         }
1611       break;
1612
1613     case AOP_STR:
1614       aop->coff = offset;
1615       if (strcmp (aop->aopu.aop_str[offset], s))
1616         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1617       break;
1618
1619     case AOP_ACC:
1620       aop->coff = offset;
1621       if (!offset && (strcmp (s, "acc") == 0))
1622         break;
1623
1624       if (strcmp (aop->aopu.aop_str[offset], s))
1625         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1626       break;
1627
1628     default:
1629       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1630               "aopPut got unsupported aop->type");
1631       exit (1);
1632     }
1633
1634 }
1635
1636
1637 /*--------------------------------------------------------------------*/
1638 /* reAdjustPreg - points a register back to where it should (coff==0) */
1639 /*--------------------------------------------------------------------*/
1640 static void
1641 reAdjustPreg (asmop * aop)
1642 {
1643   if ((aop->coff==0) || (aop->size <= 1)) {
1644     return;
1645   }
1646
1647   switch (aop->type)
1648     {
1649     case AOP_R0:
1650     case AOP_R1:
1651       while (aop->coff--)
1652         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1653       break;
1654     case AOP_DPTR:
1655     case AOP_DPTR2:
1656       if (aop->type == AOP_DPTR2)
1657         {
1658           genSetDPTR (1);
1659           _flushLazyDPS ();
1660         }
1661       while (aop->coff--)
1662         {
1663           emitcode ("lcall", "__decdptr");
1664         }
1665
1666       if (aop->type == AOP_DPTR2)
1667         {
1668           genSetDPTR (0);
1669         }
1670       break;
1671
1672     }
1673   aop->coff=0;
1674 }
1675
1676 #define AOP(op) op->aop
1677 #define AOP_TYPE(op) AOP(op)->type
1678 #define AOP_SIZE(op) AOP(op)->size
1679 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1680                        AOP_TYPE(x) == AOP_R0))
1681
1682 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1683                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1684                          AOP(x)->paged))
1685
1686 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1687                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1688                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1689 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1690 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1691 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1692
1693 // The following two macros can be used even if the aop has not yet been aopOp'd.
1694 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1695 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1696
1697 /* Workaround for DS80C390 bug: div ab may return bogus results
1698  * if A is accessed in instruction immediately before the div.
1699  *
1700  * Will be fixed in B4 rev of processor, Dallas claims.
1701  */
1702
1703 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1704     if (!AOP_NEEDSACC(RIGHT))         \
1705     {               \
1706       /* We can load A first, then B, since     \
1707        * B (the RIGHT operand) won't clobber A,   \
1708        * thus avoiding touching A right before the div. \
1709        */             \
1710       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1711       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1712       MOVA(L);            \
1713       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1714       MOVB(L); \
1715     }               \
1716     else              \
1717     {               \
1718       /* Just stuff in a nop after loading A. */    \
1719       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1720       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1721       MOVA(L);            \
1722       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1723     }
1724
1725
1726 /*-----------------------------------------------------------------*/
1727 /* opIsGptr: returns non-zero if the passed operand is       */
1728 /* a generic pointer type.             */
1729 /*-----------------------------------------------------------------*/
1730 static int
1731 opIsGptr (operand * op)
1732 {
1733   sym_link *type = operandType (op);
1734
1735   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1736     {
1737       return 1;
1738     }
1739   return 0;
1740 }
1741
1742 /*-----------------------------------------------------------------*/
1743 /* getDataSize - get the operand data size                         */
1744 /*-----------------------------------------------------------------*/
1745 static int
1746 getDataSize (operand * op)
1747 {
1748   int size;
1749   size = AOP_SIZE (op);
1750   if (size == GPTRSIZE)
1751     {
1752       sym_link *type = operandType (op);
1753       if (IS_GENPTR (type))
1754         {
1755           /* generic pointer; arithmetic operations
1756            * should ignore the high byte (pointer type).
1757            */
1758           size--;
1759         }
1760     }
1761   return size;
1762 }
1763
1764 /*-----------------------------------------------------------------*/
1765 /* outAcc - output Acc                                             */
1766 /*-----------------------------------------------------------------*/
1767 static void
1768 outAcc (operand * result)
1769 {
1770   int size, offset;
1771   size = getDataSize (result);
1772   if (size)
1773     {
1774       aopPut (AOP (result), "a", 0);
1775       size--;
1776       offset = 1;
1777       /* unsigned or positive */
1778       while (size--)
1779         {
1780           aopPut (AOP (result), zero, offset++);
1781         }
1782     }
1783 }
1784
1785 /*-----------------------------------------------------------------*/
1786 /* outBitC - output a bit C                                        */
1787 /*-----------------------------------------------------------------*/
1788 static void
1789 outBitC (operand * result)
1790 {
1791   /* if the result is bit */
1792   if (AOP_TYPE (result) == AOP_CRY)
1793     {
1794       aopPut (AOP (result), "c", 0);
1795     }
1796   else
1797     {
1798       emitcode ("clr", "a");
1799       emitcode ("rlc", "a");
1800       outAcc (result);
1801     }
1802 }
1803
1804 /*-----------------------------------------------------------------*/
1805 /* toBoolean - emit code for orl a,operator(sizeop)                */
1806 /*-----------------------------------------------------------------*/
1807 static void
1808 toBoolean (operand * oper)
1809 {
1810   int   size = AOP_SIZE (oper) - 1;
1811   int   offset = 1;
1812   bool usedB = FALSE;
1813
1814   /* The generic part of a generic pointer should
1815    * not participate in it's truth value.
1816    *
1817    * i.e. 0x10000000 is zero.
1818    */
1819   if (opIsGptr (oper))
1820     {
1821       D (emitcode (";", "toBoolean: generic ptr special case."););
1822       size--;
1823     }
1824
1825   _startLazyDPSEvaluation ();
1826   if (AOP_NEEDSACC (oper) && size)
1827     {
1828       usedB = TRUE;
1829       if (_G.bInUse)
1830       {
1831           emitcode ("push", "b");
1832       }
1833       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1834     }
1835   else
1836     {
1837       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1838     }
1839
1840   while (size--)
1841     {
1842       if (usedB)
1843         {
1844           emitcode ("orl", "b,%s",
1845                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1846         }
1847       else
1848         {
1849           emitcode ("orl", "a,%s",
1850                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1851         }
1852     }
1853   _endLazyDPSEvaluation ();
1854
1855   if (usedB)
1856     {
1857       emitcode ("mov", "a,b");
1858       if (_G.bInUse)
1859       {
1860           emitcode ("pop", "b");
1861       }
1862
1863     }
1864 }
1865
1866
1867 /*-----------------------------------------------------------------*/
1868 /* genNot - generate code for ! operation                          */
1869 /*-----------------------------------------------------------------*/
1870 static void
1871 genNot (iCode * ic)
1872 {
1873   symbol *tlbl;
1874
1875   D (emitcode (";", "genNot "););
1876
1877   /* assign asmOps to operand & result */
1878   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1879   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1880
1881   /* if in bit space then a special case */
1882   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1883     {
1884       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1885       emitcode ("cpl", "c");
1886       outBitC (IC_RESULT (ic));
1887       goto release;
1888     }
1889
1890   toBoolean (IC_LEFT (ic));
1891
1892   tlbl = newiTempLabel (NULL);
1893   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1894   emitcode ("", "!tlabeldef", tlbl->key + 100);
1895   outBitC (IC_RESULT (ic));
1896
1897 release:
1898   /* release the aops */
1899   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1900   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1901 }
1902
1903
1904 /*-----------------------------------------------------------------*/
1905 /* genCpl - generate code for complement                           */
1906 /*-----------------------------------------------------------------*/
1907 static void
1908 genCpl (iCode * ic)
1909 {
1910   int offset = 0;
1911   int size;
1912   symbol *tlbl;
1913   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1914
1915   D(emitcode (";", "genCpl"));
1916
1917   /* assign asmOps to operand & result */
1918   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1919   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1920
1921   /* special case if in bit space */
1922   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1923     {
1924       char *l;
1925
1926       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1927           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1928         {
1929           /* promotion rules are responsible for this strange result:
1930              bit -> int -> ~int -> bit
1931              uchar -> int -> ~int -> bit
1932           */
1933           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1934           goto release;
1935         }
1936       tlbl=newiTempLabel(NULL);
1937       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE, NULL);
1938       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1939           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1940           IS_AOP_PREG (IC_LEFT (ic)))
1941         {
1942           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1943         }
1944       else
1945         {
1946           MOVA (l);
1947           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1948         }
1949       emitcode ("", "%05d$:", tlbl->key+100);
1950       outBitC (IC_RESULT(ic));
1951       goto release;
1952     }
1953
1954   size = AOP_SIZE (IC_RESULT (ic));
1955   _startLazyDPSEvaluation ();
1956   while (size--)
1957     {
1958       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1959       emitcode ("cpl", "a");
1960       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1961     }
1962   _endLazyDPSEvaluation ();
1963
1964
1965 release:
1966   /* release the aops */
1967   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1968   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1969 }
1970
1971 /*-----------------------------------------------------------------*/
1972 /* genUminusFloat - unary minus for floating points                */
1973 /*-----------------------------------------------------------------*/
1974 static void
1975 genUminusFloat (operand * op, operand * result)
1976 {
1977   int size, offset = 0;
1978
1979   D(emitcode (";", "genUminusFloat"););
1980
1981   /* for this we just copy and then flip the bit */
1982
1983   _startLazyDPSEvaluation ();
1984   size = AOP_SIZE (op) - 1;
1985
1986   while (size--)
1987     {
1988       aopPut (AOP (result),
1989               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1990               offset);
1991       offset++;
1992     }
1993
1994   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1995
1996   emitcode ("cpl", "acc.7");
1997   aopPut (AOP (result), "a", offset);
1998   _endLazyDPSEvaluation ();
1999 }
2000
2001 /*-----------------------------------------------------------------*/
2002 /* genUminus - unary minus code generation                         */
2003 /*-----------------------------------------------------------------*/
2004 static void
2005 genUminus (iCode * ic)
2006 {
2007   int offset, size;
2008   sym_link *optype;
2009
2010   D (emitcode (";", "genUminus "););
2011
2012   /* assign asmops */
2013   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2014   aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2015
2016   /* if both in bit space then special
2017      case */
2018   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2019       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2020     {
2021
2022       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2023       emitcode ("cpl", "c");
2024       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2025       goto release;
2026     }
2027
2028   optype = operandType (IC_LEFT (ic));
2029
2030   /* if float then do float stuff */
2031   if (IS_FLOAT (optype))
2032     {
2033       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2034       goto release;
2035     }
2036
2037   /* otherwise subtract from zero */
2038   size = AOP_SIZE (IC_LEFT (ic));
2039   offset = 0;
2040   _startLazyDPSEvaluation ();
2041   while (size--)
2042     {
2043       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2044       if (!strcmp (l, "a"))
2045         {
2046           if (offset == 0)
2047             SETC;
2048           emitcode ("cpl", "a");
2049           emitcode ("addc", "a,#0");
2050         }
2051       else
2052         {
2053           if (offset == 0)
2054             CLRC;
2055           emitcode ("clr", "a");
2056           emitcode ("subb", "a,%s", l);
2057         }
2058       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2059     }
2060   _endLazyDPSEvaluation ();
2061
2062   /* if any remaining bytes in the result */
2063   /* we just need to propagate the sign   */
2064   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2065     {
2066       emitcode ("rlc", "a");
2067       emitcode ("subb", "a,acc");
2068       while (size--)
2069         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2070     }
2071
2072 release:
2073   /* release the aops */
2074   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2075   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2076 }
2077
2078 /*-----------------------------------------------------------------*/
2079 /* savermask - saves registers in the mask                         */
2080 /*-----------------------------------------------------------------*/
2081 static void savermask(bitVect *rs_mask)
2082 {
2083     int i;
2084     if (options.useXstack) {
2085         if (bitVectBitValue (rs_mask, R0_IDX))
2086             emitcode ("mov", "b,r0");
2087         emitcode ("mov", "r0,%s", spname);
2088         for (i = 0; i < ds390_nRegs; i++) {
2089             if (bitVectBitValue (rs_mask, i)) {
2090                 if (i == R0_IDX)
2091                     emitcode ("mov", "a,b");
2092                 else
2093                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2094                 emitcode ("movx", "@r0,a");
2095                 emitcode ("inc", "r0");
2096             }
2097         }
2098         emitcode ("mov", "%s,r0", spname);
2099         if (bitVectBitValue (rs_mask, R0_IDX))
2100             emitcode ("mov", "r0,b");
2101     } else {
2102         for (i = 0; i < ds390_nRegs; i++) {
2103             if (bitVectBitValue (rs_mask, i))
2104                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2105         }
2106     }
2107 }
2108
2109 /*-----------------------------------------------------------------*/
2110 /* saveRegisters - will look for a call and save the registers     */
2111 /*-----------------------------------------------------------------*/
2112 static void
2113 saveRegisters (iCode * lic)
2114 {
2115   iCode *ic;
2116   bitVect *rsave;
2117
2118   /* look for call */
2119   for (ic = lic; ic; ic = ic->next)
2120     if (ic->op == CALL || ic->op == PCALL)
2121       break;
2122
2123   if (!ic)
2124     {
2125       fprintf (stderr, "found parameter push with no function call\n");
2126       return;
2127     }
2128
2129   /* if the registers have been saved already then
2130      do nothing */
2131   if (ic->regsSaved
2132       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2133     return ;
2134
2135   /* special case if DPTR alive across a function call then must save it
2136      even though callee saves */
2137   if (IS_SYMOP(IC_LEFT(ic)) &&
2138       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2139       int i;
2140       rsave = newBitVect(ic->rMask->size);
2141       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2142           if (bitVectBitValue(ic->rMask,i))
2143               rsave = bitVectSetBit(rsave,i);
2144       }
2145       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2146   } else {
2147     /* safe the registers in use at this time but skip the
2148        ones for the result */
2149     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2150                            ds390_rUmaskForOp (IC_RESULT(ic)));
2151   }
2152   ic->regsSaved = 1;
2153   savermask(rsave);
2154 }
2155
2156 /*-----------------------------------------------------------------*/
2157 /* usavermask - restore registers with mask                        */
2158 /*-----------------------------------------------------------------*/
2159 static void unsavermask(bitVect *rs_mask)
2160 {
2161     int i;
2162     if (options.useXstack) {
2163         emitcode ("mov", "r0,%s", spname);
2164         for (i = ds390_nRegs; i >= 0; i--) {
2165             if (bitVectBitValue (rs_mask, i)) {
2166                 emitcode ("dec", "r0");
2167                 emitcode ("movx", "a,@r0");
2168                 if (i == R0_IDX)
2169                     emitcode ("mov", "b,a");
2170                 else
2171                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2172             }
2173         }
2174         emitcode ("mov", "%s,r0", spname);
2175         if (bitVectBitValue (rs_mask, R0_IDX))
2176             emitcode ("mov", "r0,b");
2177     } else {
2178         for (i = ds390_nRegs; i >= 0; i--) {
2179             if (bitVectBitValue (rs_mask, i))
2180                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2181         }
2182     }
2183 }
2184
2185 /*-----------------------------------------------------------------*/
2186 /* unsaveRegisters - pop the pushed registers                      */
2187 /*-----------------------------------------------------------------*/
2188 static void
2189 unsaveRegisters (iCode * ic)
2190 {
2191   bitVect *rsave;
2192
2193   if (IS_SYMOP(IC_LEFT (ic)) &&
2194       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2195       int i;
2196       rsave = newBitVect(ic->rMask->size);
2197       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2198           if (bitVectBitValue(ic->rMask,i))
2199               rsave = bitVectSetBit(rsave,i);
2200       }
2201       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2202   } else {
2203     /* restore the registers in use at this time but skip the
2204        ones for the result */
2205     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2206                            ds390_rUmaskForOp (IC_RESULT(ic)));
2207   }
2208   unsavermask(rsave);
2209 }
2210
2211
2212 /*-----------------------------------------------------------------*/
2213 /* pushSide -                */
2214 /*-----------------------------------------------------------------*/
2215 static void
2216 pushSide (operand * oper, int size)
2217 {
2218   int offset = 0;
2219   _startLazyDPSEvaluation ();
2220   while (size--)
2221     {
2222       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2223       if (AOP_TYPE (oper) != AOP_REG &&
2224           AOP_TYPE (oper) != AOP_DIR &&
2225           strcmp (l, "a"))
2226         {
2227           emitcode ("mov", "a,%s", l);
2228           emitcode ("push", "acc");
2229         }
2230       else
2231         emitcode ("push", "%s", l);
2232     }
2233   _endLazyDPSEvaluation ();
2234 }
2235
2236 /*-----------------------------------------------------------------*/
2237 /* assignResultValue -               */
2238 /*-----------------------------------------------------------------*/
2239 static void
2240 assignResultValue (operand * oper)
2241 {
2242   int offset = 0;
2243   int size = AOP_SIZE (oper);
2244   bool pushedAcc = FALSE;
2245
2246   if (size == fReturnSizeDS390)
2247   {
2248       /* I don't think this case can ever happen... */
2249       /* ACC is the last part of this. If writing the result
2250        * uses AC, we must preserve it.
2251        */
2252       if (AOP_NEEDSACC(oper))
2253       {
2254           emitcode(";", "assignResultValue special case for ACC.");
2255           emitcode("push", "acc");
2256           pushedAcc = TRUE;
2257           size--;
2258       }
2259   }
2260
2261
2262   _startLazyDPSEvaluation ();
2263   while (size--)
2264     {
2265       aopPut (AOP (oper), fReturn[offset], offset);
2266       offset++;
2267     }
2268   _endLazyDPSEvaluation ();
2269
2270   if (pushedAcc)
2271     {
2272         emitcode("pop", "acc");
2273         aopPut(AOP(oper), "a", offset);
2274     }
2275 }
2276
2277
2278 /*-----------------------------------------------------------------*/
2279 /* genXpush - pushes onto the external stack                       */
2280 /*-----------------------------------------------------------------*/
2281 static void
2282 genXpush (iCode * ic)
2283 {
2284   asmop *aop = newAsmop (0);
2285   regs *r;
2286   int size, offset = 0;
2287
2288   D (emitcode (";", "genXpush ");
2289     );
2290
2291   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2292   r = getFreePtr (ic, &aop, FALSE);
2293
2294
2295   emitcode ("mov", "%s,_spx", r->name);
2296
2297   size = AOP_SIZE (IC_LEFT (ic));
2298   _startLazyDPSEvaluation ();
2299   while (size--)
2300     {
2301
2302       MOVA (aopGet (AOP (IC_LEFT (ic)),
2303                         offset++, FALSE, FALSE, NULL));
2304       emitcode ("movx", "@%s,a", r->name);
2305       emitcode ("inc", "%s", r->name);
2306
2307     }
2308   _endLazyDPSEvaluation ();
2309
2310
2311   emitcode ("mov", "_spx,%s", r->name);
2312
2313   freeAsmop (NULL, aop, ic, TRUE);
2314   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2315 }
2316
2317 /*-----------------------------------------------------------------*/
2318 /* genIpush - generate code for pushing this gets a little complex  */
2319 /*-----------------------------------------------------------------*/
2320 static void
2321 genIpush (iCode * ic)
2322 {
2323   int size, offset = 0;
2324   char *l;
2325
2326   D (emitcode (";", "genIpush ");
2327     );
2328
2329   /* if this is not a parm push : ie. it is spill push
2330      and spill push is always done on the local stack */
2331   if (!ic->parmPush)
2332     {
2333
2334       /* and the item is spilt then do nothing */
2335       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2336         return;
2337
2338       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2339       size = AOP_SIZE (IC_LEFT (ic));
2340       /* push it on the stack */
2341       _startLazyDPSEvaluation ();
2342       while (size--)
2343         {
2344           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2345           if (*l == '#')
2346             {
2347               MOVA (l);
2348               l = "acc";
2349             }
2350           emitcode ("push", "%s", l);
2351         }
2352       _endLazyDPSEvaluation ();
2353       return;
2354     }
2355
2356   /* this is a paramter push: in this case we call
2357      the routine to find the call and save those
2358      registers that need to be saved */
2359   saveRegisters (ic);
2360
2361   /* if use external stack then call the external
2362      stack pushing routine */
2363   if (options.useXstack)
2364     {
2365       genXpush (ic);
2366       return;
2367     }
2368
2369   /* then do the push */
2370   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2371
2372   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2373   size = AOP_SIZE (IC_LEFT (ic));
2374
2375   _startLazyDPSEvaluation ();
2376   while (size--)
2377     {
2378       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2379       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2380           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2381           strcmp (l, "acc"))
2382         {
2383           emitcode ("mov", "a,%s", l);
2384           emitcode ("push", "acc");
2385         }
2386       else
2387         {
2388             emitcode ("push", "%s", l);
2389         }
2390     }
2391   _endLazyDPSEvaluation ();
2392
2393   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2394 }
2395
2396 /*-----------------------------------------------------------------*/
2397 /* genIpop - recover the registers: can happen only for spilling   */
2398 /*-----------------------------------------------------------------*/
2399 static void
2400 genIpop (iCode * ic)
2401 {
2402   int size, offset;
2403
2404   D (emitcode (";", "genIpop ");
2405     );
2406
2407
2408   /* if the temp was not pushed then */
2409   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2410     return;
2411
2412   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2413   size = AOP_SIZE (IC_LEFT (ic));
2414   offset = (size - 1);
2415   _startLazyDPSEvaluation ();
2416   while (size--)
2417     {
2418       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2419                                      FALSE, TRUE, NULL));
2420     }
2421   _endLazyDPSEvaluation ();
2422
2423   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2424 }
2425
2426 /*-----------------------------------------------------------------*/
2427 /* unsaveRBank - restores the resgister bank from stack            */
2428 /*-----------------------------------------------------------------*/
2429 static void
2430 unsaveRBank (int bank, iCode * ic, bool popPsw)
2431 {
2432   int i;
2433   asmop *aop = NULL;
2434   regs *r = NULL;
2435
2436   if (options.useXstack)
2437   {
2438       if (!ic)
2439       {
2440           /* Assume r0 is available for use. */
2441           r = ds390_regWithIdx (R0_IDX);;
2442       }
2443       else
2444       {
2445           aop = newAsmop (0);
2446           r = getFreePtr (ic, &aop, FALSE);
2447       }
2448       emitcode ("mov", "%s,_spx", r->name);
2449   }
2450
2451   if (popPsw)
2452     {
2453       if (options.useXstack)
2454       {
2455           emitcode ("movx", "a,@%s", r->name);
2456           emitcode ("mov", "psw,a");
2457           emitcode ("dec", "%s", r->name);
2458         }
2459       else
2460       {
2461         emitcode ("pop", "psw");
2462       }
2463     }
2464
2465   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2466     {
2467       if (options.useXstack)
2468         {
2469           emitcode ("movx", "a,@%s", r->name);
2470           emitcode ("mov", "(%s+%d),a",
2471                     regs390[i].base, 8 * bank + regs390[i].offset);
2472           emitcode ("dec", "%s", r->name);
2473
2474         }
2475       else
2476         emitcode ("pop", "(%s+%d)",
2477                   regs390[i].base, 8 * bank + regs390[i].offset);
2478     }
2479
2480   if (options.useXstack)
2481     {
2482       emitcode ("mov", "_spx,%s", r->name);
2483     }
2484
2485   if (aop)
2486   {
2487       freeAsmop (NULL, aop, ic, TRUE);
2488   }
2489 }
2490
2491 /*-----------------------------------------------------------------*/
2492 /* saveRBank - saves an entire register bank on the stack          */
2493 /*-----------------------------------------------------------------*/
2494 static void
2495 saveRBank (int bank, iCode * ic, bool pushPsw)
2496 {
2497   int i;
2498   asmop *aop = NULL;
2499   regs *r = NULL;
2500
2501   if (options.useXstack)
2502     {
2503         if (!ic)
2504         {
2505           /* Assume r0 is available for use. */
2506                   r = ds390_regWithIdx (R0_IDX);;
2507         }
2508         else
2509         {
2510           aop = newAsmop (0);
2511           r = getFreePtr (ic, &aop, FALSE);
2512         }
2513         emitcode ("mov", "%s,_spx", r->name);
2514     }
2515
2516   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2517     {
2518       if (options.useXstack)
2519         {
2520           emitcode ("inc", "%s", r->name);
2521           emitcode ("mov", "a,(%s+%d)",
2522                     regs390[i].base, 8 * bank + regs390[i].offset);
2523           emitcode ("movx", "@%s,a", r->name);
2524         }
2525       else
2526         emitcode ("push", "(%s+%d)",
2527                   regs390[i].base, 8 * bank + regs390[i].offset);
2528     }
2529
2530   if (pushPsw)
2531     {
2532       if (options.useXstack)
2533         {
2534           emitcode ("mov", "a,psw");
2535           emitcode ("movx", "@%s,a", r->name);
2536           emitcode ("inc", "%s", r->name);
2537           emitcode ("mov", "_spx,%s", r->name);
2538         }
2539       else
2540       {
2541         emitcode ("push", "psw");
2542       }
2543
2544       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2545     }
2546
2547   if (aop)
2548   {
2549     freeAsmop (NULL, aop, ic, TRUE);
2550   }
2551
2552   if (ic)
2553   {
2554     ic->bankSaved = 1;
2555   }
2556 }
2557
2558 /*-----------------------------------------------------------------*/
2559 /* genSend - gen code for SEND                                     */
2560 /*-----------------------------------------------------------------*/
2561 static void genSend(set *sendSet)
2562 {
2563     iCode *sic;
2564     int sendCount = 0 ;
2565     static int rb1_count = 0;
2566
2567     for (sic = setFirstItem (sendSet); sic;
2568          sic = setNextItem (sendSet)) {
2569         int size, offset = 0;
2570
2571         size=getSize(operandType(IC_LEFT(sic)));
2572         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2573         if (sendCount == 0) { /* first parameter */
2574             // we know that dpl(hxb) is the result, so
2575             rb1_count = 0 ;
2576             _startLazyDPSEvaluation ();
2577             if (size>1) {
2578                 aopOp (IC_LEFT (sic), sic, FALSE,
2579                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2580             } else {
2581                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2582             }
2583             while (size--) {
2584                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2585                                   FALSE, FALSE, NULL);
2586                 if (strcmp (l, fReturn[offset])) {
2587                     emitcode ("mov", "%s,%s",
2588                               fReturn[offset],
2589                               l);
2590                 }
2591                 offset++;
2592             }
2593             _endLazyDPSEvaluation ();
2594             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2595             rb1_count =0;
2596         } else { /* if more parameter in registers */
2597             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2598             while (size--) {
2599                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2600                                                                 FALSE, FALSE, NULL));
2601             }
2602             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2603         }
2604         sendCount++;
2605     }
2606 }
2607
2608 static void
2609 adjustEsp(const char *reg)
2610 {
2611     emitcode ("anl","%s,#3", reg);
2612     if (TARGET_IS_DS400)
2613     {
2614         emitcode ("orl","%s,#!constbyte",
2615                   reg,
2616                   (options.stack_loc >> 8) & 0xff);
2617     }
2618 }
2619
2620 /*-----------------------------------------------------------------*/
2621 /* genCall - generates a call statement                            */
2622 /*-----------------------------------------------------------------*/
2623 static void
2624 genCall (iCode * ic)
2625 {
2626   sym_link *dtype;
2627   bool restoreBank = FALSE;
2628   bool swapBanks = FALSE;
2629
2630   D (emitcode (";", "genCall "););
2631
2632   /* if we are calling a not _naked function that is not using
2633      the same register bank then we need to save the
2634      destination registers on the stack */
2635   dtype = operandType (IC_LEFT (ic));
2636   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2637       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2638       IFFUNC_ISISR (currFunc->type))
2639   {
2640       if (!ic->bankSaved)
2641       {
2642            /* This is unexpected; the bank should have been saved in
2643             * genFunction.
2644             */
2645            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2646            restoreBank = TRUE;
2647       }
2648       swapBanks = TRUE;
2649   }
2650
2651     /* if caller saves & we have not saved then */
2652     if (!ic->regsSaved)
2653       saveRegisters (ic);
2654
2655   /* if send set is not empty then assign */
2656   /* We've saved all the registers we care about;
2657   * therefore, we may clobber any register not used
2658   * in the calling convention (i.e. anything not in
2659   * fReturn.
2660   */
2661   if (_G.sendSet)
2662     {
2663         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2664             genSend(reverseSet(_G.sendSet));
2665         } else {
2666             genSend(_G.sendSet);
2667         }
2668       _G.sendSet = NULL;
2669     }
2670
2671   if (swapBanks)
2672   {
2673         emitcode ("mov", "psw,#!constbyte",
2674            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2675   }
2676
2677   /* make the call */
2678   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2679                             OP_SYMBOL (IC_LEFT (ic))->rname :
2680                             OP_SYMBOL (IC_LEFT (ic))->name));
2681
2682   if (swapBanks)
2683   {
2684        emitcode ("mov", "psw,#!constbyte",
2685           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2686   }
2687
2688   /* if we need assign a result value */
2689   if ((IS_ITEMP (IC_RESULT (ic)) &&
2690        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2691         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2692         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2693       IS_TRUE_SYMOP (IC_RESULT (ic)))
2694     {
2695       if (isOperandInFarSpace (IC_RESULT (ic))
2696           && getSize (operandType (IC_RESULT (ic))) <= 2)
2697         {
2698           int size = getSize (operandType (IC_RESULT (ic)));
2699
2700           /* Special case for 1 or 2 byte return in far space. */
2701           MOVA (fReturn[0]);
2702           if (size > 1)
2703             {
2704               emitcode ("mov", "b,%s", fReturn[1]);
2705               _G.bInUse++;
2706             }
2707
2708           _G.accInUse++;
2709           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2710           _G.accInUse--;
2711
2712           if (size > 1)
2713             _G.bInUse--;
2714
2715           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2716
2717           if (size > 1)
2718             {
2719               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2720             }
2721           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2722         }
2723       else
2724         {
2725           _G.bInUse++;
2726           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2727           _G.bInUse--;
2728
2729           assignResultValue (IC_RESULT (ic));
2730
2731           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2732         }
2733     }
2734
2735   /* adjust the stack for parameters if
2736      required */
2737   if (ic->parmBytes) {
2738       int i;
2739       if (options.stack10bit) {
2740           if (ic->parmBytes <= 10) {
2741               emitcode(";","stack adjustment for parms");
2742               for (i=0; i < ic->parmBytes ; i++) {
2743                   emitcode("pop","acc");
2744               }
2745           } else {
2746               PROTECT_SP;
2747               emitcode ("clr","c");
2748               emitcode ("mov","a,sp");
2749               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2750               emitcode ("mov","sp,a");
2751               emitcode ("mov","a,esp");
2752               adjustEsp("a");
2753               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2754               emitcode ("mov","esp,a");
2755               UNPROTECT_SP;
2756           }
2757       } else {
2758           if (ic->parmBytes > 3) {
2759               emitcode ("mov", "a,%s", spname);
2760               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2761               emitcode ("mov", "%s,a", spname);
2762           } else
2763               for (i = 0; i < ic->parmBytes; i++)
2764                   emitcode ("dec", "%s", spname);
2765       }
2766   }
2767
2768   /* if we hade saved some registers then unsave them */
2769   if (ic->regsSaved)
2770     unsaveRegisters (ic);
2771
2772   /* if register bank was saved then pop them */
2773   if (restoreBank)
2774     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2775 }
2776
2777 /*-----------------------------------------------------------------*/
2778 /* genPcall - generates a call by pointer statement                */
2779 /*-----------------------------------------------------------------*/
2780 static void
2781 genPcall (iCode * ic)
2782 {
2783   sym_link *dtype;
2784   symbol *rlbl = newiTempLabel (NULL);
2785   bool restoreBank=FALSE;
2786
2787   D (emitcode (";", "genPcall ");
2788     );
2789
2790
2791   /* if caller saves & we have not saved then */
2792   if (!ic->regsSaved)
2793     saveRegisters (ic);
2794
2795   /* if we are calling a function that is not using
2796      the same register bank then we need to save the
2797      destination registers on the stack */
2798   dtype = operandType (IC_LEFT (ic));
2799   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2800       IFFUNC_ISISR (currFunc->type) &&
2801       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2802     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2803     restoreBank=TRUE;
2804   }
2805
2806   /* push the return address on to the stack */
2807   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2808   emitcode ("push", "acc");
2809   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2810   emitcode ("push", "acc");
2811
2812   if (options.model == MODEL_FLAT24)
2813     {
2814       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2815       emitcode ("push", "acc");
2816     }
2817
2818   /* now push the calling address */
2819   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2820
2821   pushSide (IC_LEFT (ic), FPTRSIZE);
2822
2823   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2824
2825   /* if send set is not empty the assign */
2826   if (_G.sendSet)
2827     {
2828         genSend(reverseSet(_G.sendSet));
2829         _G.sendSet = NULL;
2830     }
2831
2832   emitcode ("ret", "");
2833   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2834
2835
2836   /* if we need assign a result value */
2837   if ((IS_ITEMP (IC_RESULT (ic)) &&
2838        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2839         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2840       IS_TRUE_SYMOP (IC_RESULT (ic)))
2841     {
2842
2843       _G.accInUse++;
2844       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2845       _G.accInUse--;
2846
2847       assignResultValue (IC_RESULT (ic));
2848
2849       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2850     }
2851
2852   /* adjust the stack for parameters if
2853      required */
2854   if (ic->parmBytes)
2855     {
2856       int i;
2857       if (options.stack10bit) {
2858           if (ic->parmBytes <= 10) {
2859               emitcode(";","stack adjustment for parms");
2860               for (i=0; i < ic->parmBytes ; i++) {
2861                   emitcode("pop","acc");
2862               }
2863           } else {
2864               PROTECT_SP;
2865               emitcode ("clr","c");
2866               emitcode ("mov","a,sp");
2867               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2868               emitcode ("mov","sp,a");
2869               emitcode ("mov","a,esp");
2870               adjustEsp("a");
2871               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2872               emitcode ("mov","esp,a");
2873               UNPROTECT_SP;
2874           }
2875       } else {
2876           if (ic->parmBytes > 3) {
2877               emitcode ("mov", "a,%s", spname);
2878               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2879               emitcode ("mov", "%s,a", spname);
2880           }
2881           else
2882               for (i = 0; i < ic->parmBytes; i++)
2883                   emitcode ("dec", "%s", spname);
2884
2885       }
2886     }
2887   /* if register bank was saved then unsave them */
2888   if (restoreBank)
2889     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2890
2891   /* if we hade saved some registers then
2892      unsave them */
2893   if (ic->regsSaved)
2894     unsaveRegisters (ic);
2895
2896 }
2897
2898 /*-----------------------------------------------------------------*/
2899 /* resultRemat - result  is rematerializable                       */
2900 /*-----------------------------------------------------------------*/
2901 static int
2902 resultRemat (iCode * ic)
2903 {
2904   if (SKIP_IC (ic) || ic->op == IFX)
2905     return 0;
2906
2907   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2908     {
2909       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2910       if (sym->remat && !POINTER_SET (ic))
2911         return 1;
2912     }
2913
2914   return 0;
2915 }
2916
2917 #if defined(__BORLANDC__) || defined(_MSC_VER)
2918 #define STRCASECMP stricmp
2919 #else
2920 #define STRCASECMP strcasecmp
2921 #endif
2922
2923 /*-----------------------------------------------------------------*/
2924 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2925 /*-----------------------------------------------------------------*/
2926 static int
2927 regsCmp(void *p1, void *p2)
2928 {
2929   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2930 }
2931
2932 static bool
2933 inExcludeList (char *s)
2934 {
2935   const char *p = setFirstItem(options.excludeRegsSet);
2936
2937   if (p == NULL || STRCASECMP(p, "none") == 0)
2938     return FALSE;
2939
2940
2941   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2942 }
2943
2944 /*-----------------------------------------------------------------*/
2945 /* genFunction - generated code for function entry                 */
2946 /*-----------------------------------------------------------------*/
2947 static void
2948 genFunction (iCode * ic)
2949 {
2950   symbol *sym;
2951   sym_link *ftype;
2952   bool   switchedPSW = FALSE;
2953
2954   D (emitcode (";", "genFunction "););
2955
2956   _G.nRegsSaved = 0;
2957   /* create the function header */
2958   emitcode (";", "-----------------------------------------");
2959   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2960   emitcode (";", "-----------------------------------------");
2961
2962   emitcode ("", "%s:", sym->rname);
2963   ftype = operandType (IC_LEFT (ic));
2964
2965   if (IFFUNC_ISNAKED(ftype))
2966   {
2967       emitcode(";", "naked function: no prologue.");
2968       return;
2969   }
2970
2971   if (options.stack_probe)
2972       emitcode ("lcall","__stack_probe");
2973
2974   /* here we need to generate the equates for the
2975      register bank if required */
2976   if (FUNC_REGBANK (ftype) != rbank)
2977     {
2978       int i;
2979
2980       rbank = FUNC_REGBANK (ftype);
2981       for (i = 0; i < ds390_nRegs; i++)
2982         {
2983           if (regs390[i].print) {
2984               if (strcmp (regs390[i].base, "0") == 0)
2985                   emitcode ("", "%s !equ !constbyte",
2986                             regs390[i].dname,
2987                             8 * rbank + regs390[i].offset);
2988               else
2989                   emitcode ("", "%s !equ %s + !constbyte",
2990                             regs390[i].dname,
2991                             regs390[i].base,
2992                             8 * rbank + regs390[i].offset);
2993           }
2994         }
2995     }
2996
2997   /* if this is an interrupt service routine then
2998      save acc, b, dpl, dph  */
2999   if (IFFUNC_ISISR (sym->type))
3000       { /* is ISR */
3001       if (!inExcludeList ("acc"))
3002         emitcode ("push", "acc");
3003       if (!inExcludeList ("b"))
3004         emitcode ("push", "b");
3005       if (!inExcludeList ("dpl"))
3006         emitcode ("push", "dpl");
3007       if (!inExcludeList ("dph"))
3008         emitcode ("push", "dph");
3009       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3010         {
3011           emitcode ("push", "dpx");
3012           /* Make sure we're using standard DPTR */
3013           emitcode ("push", "dps");
3014           emitcode ("mov", "dps,#0");
3015           if (options.stack10bit)
3016             {
3017               /* This ISR could conceivably use DPTR2. Better save it. */
3018               emitcode ("push", "dpl1");
3019               emitcode ("push", "dph1");
3020               emitcode ("push", "dpx1");
3021               emitcode ("push",  DP2_RESULT_REG);
3022             }
3023         }
3024       /* if this isr has no bank i.e. is going to
3025          run with bank 0 , then we need to save more
3026          registers :-) */
3027       if (!FUNC_REGBANK (sym->type))
3028         {
3029             int i;
3030
3031           /* if this function does not call any other
3032              function then we can be economical and
3033              save only those registers that are used */
3034           if (!IFFUNC_HASFCALL(sym->type))
3035             {
3036
3037               /* if any registers used */
3038               if (sym->regsUsed)
3039                 {
3040                   /* save the registers used */
3041                   for (i = 0; i < sym->regsUsed->size; i++)
3042                     {
3043                       if (bitVectBitValue (sym->regsUsed, i))
3044                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3045                     }
3046                 }
3047             }
3048           else
3049             {
3050               /* this function has  a function call cannot
3051                  determines register usage so we will have to push the
3052                  entire bank */
3053               saveRBank (0, ic, FALSE);
3054               if (options.parms_in_bank1) {
3055                   for (i=0; i < 8 ; i++ ) {
3056                       emitcode ("push","%s",rb1regs[i]);
3057                   }
3058               }
3059             }
3060         }
3061         else
3062         {
3063             /* This ISR uses a non-zero bank.
3064              *
3065              * We assume that the bank is available for our
3066              * exclusive use.
3067              *
3068              * However, if this ISR calls a function which uses some
3069              * other bank, we must save that bank entirely.
3070              */
3071             unsigned long banksToSave = 0;
3072
3073             if (IFFUNC_HASFCALL(sym->type))
3074             {
3075
3076 #define MAX_REGISTER_BANKS 4
3077
3078                 iCode *i;
3079                 int ix;
3080
3081                 for (i = ic; i; i = i->next)
3082                 {
3083                     if (i->op == ENDFUNCTION)
3084                     {
3085                         /* we got to the end OK. */
3086                         break;
3087                     }
3088
3089                     if (i->op == CALL)
3090                     {
3091                         sym_link *dtype;
3092
3093                         dtype = operandType (IC_LEFT(i));
3094                         if (dtype
3095                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3096                         {
3097                              /* Mark this bank for saving. */
3098                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3099                              {
3100                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3101                              }
3102                              else
3103                              {
3104                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3105                              }
3106
3107                              /* And note that we don't need to do it in
3108                               * genCall.
3109                               */
3110                              i->bankSaved = 1;
3111                         }
3112                     }
3113                     if (i->op == PCALL)
3114                     {
3115                         /* This is a mess; we have no idea what
3116                          * register bank the called function might
3117                          * use.
3118                          *
3119                          * The only thing I can think of to do is
3120                          * throw a warning and hope.
3121                          */
3122                         werror(W_FUNCPTR_IN_USING_ISR);
3123                     }
3124                 }
3125
3126                 if (banksToSave && options.useXstack)
3127                 {
3128                     /* Since we aren't passing it an ic,
3129                      * saveRBank will assume r0 is available to abuse.
3130                      *
3131                      * So switch to our (trashable) bank now, so
3132                      * the caller's R0 isn't trashed.
3133                      */
3134                     emitcode ("push", "psw");
3135                     emitcode ("mov", "psw,#!constbyte",
3136                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3137                     switchedPSW = TRUE;
3138                 }
3139
3140                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3141                 {
3142                      if (banksToSave & (1 << ix))
3143                      {
3144                          saveRBank(ix, NULL, FALSE);
3145                      }
3146                 }
3147             }
3148             // TODO: this needs a closer look
3149             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3150         }
3151     }
3152   else
3153     {
3154       /* if callee-save to be used for this function
3155          then save the registers being used in this function */
3156       if (IFFUNC_CALLEESAVES(sym->type))
3157         {
3158           int i;
3159
3160           /* if any registers used */
3161           if (sym->regsUsed)
3162             {
3163               /* save the registers used */
3164               for (i = 0; i < sym->regsUsed->size; i++)
3165                 {
3166                   if (bitVectBitValue (sym->regsUsed, i))
3167                     {
3168                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3169                       _G.nRegsSaved++;
3170                     }
3171                 }
3172             }
3173         }
3174     }
3175
3176   /* set the register bank to the desired value */
3177   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3178    && !switchedPSW)
3179     {
3180       emitcode ("push", "psw");
3181       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3182     }
3183
3184   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3185        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3186       if (options.stack10bit) {
3187           emitcode ("push","_bpx");
3188           emitcode ("push","_bpx+1");
3189           emitcode ("mov","_bpx,%s",spname);
3190           emitcode ("mov","_bpx+1,esp");
3191           adjustEsp("_bpx+1");
3192       } else {
3193           if (options.useXstack) {
3194               emitcode ("mov", "r0,%s", spname);
3195               emitcode ("mov", "a,_bp");
3196               emitcode ("movx", "@r0,a");
3197               emitcode ("inc", "%s", spname);
3198           } else {
3199               /* set up the stack */
3200               emitcode ("push", "_bp"); /* save the callers stack  */
3201           }
3202           emitcode ("mov", "_bp,%s", spname);
3203       }
3204   }
3205
3206   /* adjust the stack for the function */
3207   if (sym->stack) {
3208       int i = sym->stack;
3209       if (options.stack10bit) {
3210           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3211           assert (sym->recvSize <= 4);
3212           if (sym->stack <= 8) {
3213               while (i--) emitcode ("push","acc");
3214           } else {
3215               PROTECT_SP;
3216               emitcode ("mov","a,sp");
3217               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3218               emitcode ("mov","sp,a");
3219               emitcode ("mov","a,esp");
3220               adjustEsp("a");
3221               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3222               emitcode ("mov","esp,a");
3223               UNPROTECT_SP;
3224           }
3225       } else {
3226           if (i > 256)
3227               werror (W_STACK_OVERFLOW, sym->name);
3228
3229           if (i > 3 && sym->recvSize < 4) {
3230
3231               emitcode ("mov", "a,sp");
3232               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3233               emitcode ("mov", "sp,a");
3234
3235           } else
3236               while (i--)
3237                   emitcode ("inc", "sp");
3238       }
3239   }
3240
3241   if (sym->xstack)
3242     {
3243
3244       emitcode ("mov", "a,_spx");
3245       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3246       emitcode ("mov", "_spx,a");
3247     }
3248
3249   /* if critical function then turn interrupts off */
3250   if (IFFUNC_ISCRITICAL (ftype))
3251     {
3252       symbol *tlbl = newiTempLabel (NULL);
3253       emitcode ("setb", "c");
3254       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3255       emitcode ("clr", "c");
3256       emitcode ("", "%05d$:", (tlbl->key + 100));
3257       emitcode ("push", "psw"); /* save old ea via c in psw */
3258     }
3259
3260 }
3261
3262 /*-----------------------------------------------------------------*/
3263 /* genEndFunction - generates epilogue for functions               */
3264 /*-----------------------------------------------------------------*/
3265 static void
3266 genEndFunction (iCode * ic)
3267 {
3268   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3269   lineNode *lnp = lineCurr;
3270   bitVect *regsUsed;
3271   bitVect *regsUsedPrologue;
3272   bitVect *regsUnneeded;
3273   int idx;
3274
3275   D (emitcode (";", "genEndFunction "););
3276
3277   if (IFFUNC_ISNAKED(sym->type))
3278   {
3279       emitcode(";", "naked function: no epilogue.");
3280       if (options.debug && currFunc)
3281         debugFile->writeEndFunction (currFunc, ic, 0);
3282       return;
3283   }
3284
3285   if (IFFUNC_ISCRITICAL (sym->type))
3286     {
3287       emitcode ("pop", "psw"); /* restore ea via c in psw */
3288       emitcode ("mov", "ea,c");
3289     }
3290
3291   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3292        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3293
3294       if (options.stack10bit) {
3295           PROTECT_SP;
3296           emitcode ("mov", "sp,_bpx", spname);
3297           emitcode ("mov", "esp,_bpx+1", spname);
3298           UNPROTECT_SP;
3299       } else {
3300           emitcode ("mov", "%s,_bp", spname);
3301       }
3302   }
3303
3304   /* if use external stack but some variables were
3305      added to the local stack then decrement the
3306      local stack */
3307   if (options.useXstack && sym->stack) {
3308       emitcode ("mov", "a,sp");
3309       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3310       emitcode ("mov", "sp,a");
3311   }
3312
3313
3314   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3315        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3316
3317       if (options.useXstack) {
3318           emitcode ("mov", "r0,%s", spname);
3319           emitcode ("movx", "a,@r0");
3320           emitcode ("mov", "_bp,a");
3321           emitcode ("dec", "%s", spname);
3322       } else {
3323           if (options.stack10bit) {
3324               emitcode ("pop", "_bpx+1");
3325               emitcode ("pop", "_bpx");
3326           } else {
3327               emitcode ("pop", "_bp");
3328           }
3329       }
3330   }
3331
3332   /* restore the register bank  */
3333   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3334   {
3335     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3336      || !options.useXstack)
3337     {
3338         /* Special case of ISR using non-zero bank with useXstack
3339          * is handled below.
3340          */
3341         emitcode ("pop", "psw");
3342     }
3343   }
3344
3345   if (IFFUNC_ISISR (sym->type))
3346       { /* is ISR */
3347
3348       /* now we need to restore the registers */
3349       /* if this isr has no bank i.e. is going to
3350          run with bank 0 , then we need to save more
3351          registers :-) */
3352       if (!FUNC_REGBANK (sym->type))
3353         {
3354             int i;
3355           /* if this function does not call any other
3356              function then we can be economical and
3357              save only those registers that are used */
3358           if (!IFFUNC_HASFCALL(sym->type))
3359             {
3360
3361               /* if any registers used */
3362               if (sym->regsUsed)
3363                 {
3364                   /* save the registers used */
3365                   for (i = sym->regsUsed->size; i >= 0; i--)
3366                     {
3367                       if (bitVectBitValue (sym->regsUsed, i))
3368                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3369                     }
3370                 }
3371             }
3372           else
3373             {
3374               /* this function has  a function call cannot
3375                  determines register usage so we will have to pop the
3376                  entire bank */
3377               if (options.parms_in_bank1) {
3378                   for (i = 7 ; i >= 0 ; i-- ) {
3379                       emitcode ("pop","%s",rb1regs[i]);
3380                   }
3381               }
3382               unsaveRBank (0, ic, FALSE);
3383             }
3384         }
3385         else
3386         {
3387             /* This ISR uses a non-zero bank.
3388              *
3389              * Restore any register banks saved by genFunction
3390              * in reverse order.
3391              */
3392             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3393             int ix;
3394
3395             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3396             {
3397                 if (savedBanks & (1 << ix))
3398                 {
3399                     unsaveRBank(ix, NULL, FALSE);
3400                 }
3401             }
3402
3403             if (options.useXstack)
3404             {
3405                 /* Restore bank AFTER calling unsaveRBank,
3406                  * since it can trash r0.
3407                  */
3408                 emitcode ("pop", "psw");
3409             }
3410         }
3411
3412       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3413         {
3414           if (options.stack10bit)
3415             {
3416               emitcode ("pop", DP2_RESULT_REG);
3417               emitcode ("pop", "dpx1");
3418               emitcode ("pop", "dph1");
3419               emitcode ("pop", "dpl1");
3420             }
3421           emitcode ("pop", "dps");
3422           emitcode ("pop", "dpx");
3423         }
3424       if (!inExcludeList ("dph"))
3425         emitcode ("pop", "dph");
3426       if (!inExcludeList ("dpl"))
3427         emitcode ("pop", "dpl");
3428       if (!inExcludeList ("b"))
3429         emitcode ("pop", "b");
3430       if (!inExcludeList ("acc"))
3431         emitcode ("pop", "acc");
3432
3433       /* if debug then send end of function */
3434       if (options.debug && currFunc) {
3435           debugFile->writeEndFunction (currFunc, ic, 1);
3436         }
3437
3438       emitcode ("reti", "");
3439     }
3440   else
3441     {
3442       if (IFFUNC_CALLEESAVES(sym->type))
3443         {
3444           int i;
3445
3446           /* if any registers used */
3447           if (sym->regsUsed)
3448             {
3449               /* save the registers used */
3450               for (i = sym->regsUsed->size; i >= 0; i--)
3451                 {
3452                   if (bitVectBitValue (sym->regsUsed, i))
3453                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3454                 }
3455             }
3456         }
3457
3458       /* if debug then send end of function */
3459       if (options.debug && currFunc)
3460         {
3461           debugFile->writeEndFunction (currFunc, ic, 1);
3462         }
3463
3464       emitcode ("ret", "");
3465     }
3466
3467   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3468     return;
3469
3470   /* If this was an interrupt handler using bank 0 that called another */
3471   /* function, then all registers must be saved; nothing to optimized. */
3472   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3473       && !FUNC_REGBANK(sym->type))
3474     return;
3475
3476   /* There are no push/pops to optimize if not callee-saves or ISR */
3477   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3478     return;
3479
3480   /* If there were stack parameters, we cannot optimize without also    */
3481   /* fixing all of the stack offsets; this is too dificult to consider. */
3482   if (FUNC_HASSTACKPARM(sym->type))
3483     return;
3484
3485   /* Compute the registers actually used */
3486   regsUsed = newBitVect (ds390_nRegs);
3487   regsUsedPrologue = newBitVect (ds390_nRegs);
3488   while (lnp)
3489     {
3490       if (lnp->ic && lnp->ic->op == FUNCTION)
3491         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3492       else
3493         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3494
3495       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3496           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3497         break;
3498       if (!lnp->prev)
3499         break;
3500       lnp = lnp->prev;
3501     }
3502
3503   if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3504       && !bitVectBitValue (regsUsed, DPS_IDX))
3505     {
3506       bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3507     }
3508
3509   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3510       && !bitVectBitValue (regsUsed, CND_IDX))
3511     {
3512       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3513       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3514           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3515         bitVectUnSetBit (regsUsed, CND_IDX);
3516     }
3517   else
3518     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3519
3520   /* If this was an interrupt handler that called another function */
3521   /* function, then assume working registers may be modified by it. */
3522   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3523     {
3524       regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3525       regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3526       regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3527       regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3528       regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3529       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3530       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3531       regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3532       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3533       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3534       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3535     }
3536
3537   /* Remove the unneeded push/pops */
3538   regsUnneeded = newBitVect (ds390_nRegs);
3539   while (lnp)
3540     {
3541       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3542         {
3543           if (!strncmp(lnp->line, "push", 4))
3544             {
3545               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3546               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3547                 {
3548                   connectLine (lnp->prev, lnp->next);
3549                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3550                 }
3551             }
3552           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3553             {
3554               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3555               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3556                 {
3557                   connectLine (lnp->prev, lnp->next);
3558                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3559                 }
3560             }
3561         }
3562       lnp = lnp->next;
3563     }
3564
3565   for (idx = 0; idx < regsUnneeded->size; idx++)
3566     if (bitVectBitValue (regsUnneeded, idx))
3567       emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3568
3569   freeBitVect (regsUnneeded);
3570   freeBitVect (regsUsed);
3571   freeBitVect (regsUsedPrologue);
3572 }
3573
3574 /*-----------------------------------------------------------------*/
3575 /* genJavaNativeRet - generate code for return JavaNative          */
3576 /*-----------------------------------------------------------------*/
3577 static void genJavaNativeRet(iCode *ic)
3578 {
3579     int i, size;
3580
3581     aopOp (IC_LEFT (ic), ic, FALSE,
3582            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3583     size = AOP_SIZE (IC_LEFT (ic));
3584
3585     assert (size <= 4);
3586
3587     /* it is assigned to GPR0-R3 then push them */
3588     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3589         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3590         for (i = 0 ; i < size ; i++ ) {
3591             emitcode ("push","%s",
3592                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3593         }
3594         for (i = (size-1) ; i >= 0 ; i--) {
3595             emitcode ("pop","a%s",javaRet[i]);
3596         }
3597     } else {
3598         for (i = 0 ; i < size ; i++)
3599             emitcode ("mov","%s,%s",javaRet[i],
3600                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3601     }
3602     for (i = size ; i < 4 ; i++ )
3603             emitcode ("mov","%s,#0",javaRet[i]);
3604     return;
3605 }
3606
3607 /*-----------------------------------------------------------------*/
3608 /* genRet - generate code for return statement                     */
3609 /*-----------------------------------------------------------------*/
3610 static void
3611 genRet (iCode * ic)
3612 {
3613   int size, offset = 0, pushed = 0;
3614
3615   D (emitcode (";", "genRet "););
3616
3617   /* if we have no return value then
3618      just generate the "ret" */
3619   if (!IC_LEFT (ic))
3620     goto jumpret;
3621
3622   /* if this is a JavaNative function then return
3623      value in different register */
3624   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3625       genJavaNativeRet(ic);
3626       goto jumpret;
3627   }
3628   /* we have something to return then
3629      move the return value into place */
3630   aopOp (IC_LEFT (ic), ic, FALSE,
3631          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3632   size = AOP_SIZE (IC_LEFT (ic));
3633
3634   _startLazyDPSEvaluation ();
3635   while (size--)
3636     {
3637       char *l;
3638       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3639         {
3640           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3641                       FALSE, TRUE, NULL);
3642           emitcode ("push", "%s", l);
3643           pushed++;
3644         }
3645       else
3646         {
3647           /* Since A is the last element of fReturn,
3648            * is is OK to clobber it in the aopGet.
3649            */
3650           l = aopGet (AOP (IC_LEFT (ic)), offset,
3651                       FALSE, FALSE, NULL);
3652           if (strcmp (fReturn[offset], l))
3653             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3654         }
3655     }
3656   _endLazyDPSEvaluation ();
3657
3658   if (pushed)
3659     {
3660       while (pushed)
3661         {
3662           pushed--;
3663           if (strcmp (fReturn[pushed], "a"))
3664             emitcode ("pop", fReturn[pushed]);
3665           else
3666             emitcode ("pop", "acc");
3667         }
3668     }
3669   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3670
3671 jumpret:
3672   /* generate a jump to the return label
3673      if the next is not the return statement */
3674   if (!(ic->next && ic->next->op == LABEL &&
3675         IC_LABEL (ic->next) == returnLabel))
3676
3677     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3678
3679 }
3680
3681 /*-----------------------------------------------------------------*/
3682 /* genLabel - generates a label                                    */
3683 /*-----------------------------------------------------------------*/
3684 static void
3685 genLabel (iCode * ic)
3686 {
3687   /* special case never generate */
3688   if (IC_LABEL (ic) == entryLabel)
3689     return;
3690
3691   D (emitcode (";", "genLabel ");
3692     );
3693
3694   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3695 }
3696
3697 /*-----------------------------------------------------------------*/
3698 /* genGoto - generates a ljmp                                      */
3699 /*-----------------------------------------------------------------*/
3700 static void
3701 genGoto (iCode * ic)
3702 {
3703   D (emitcode (";", "genGoto ");
3704     );
3705   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3706 }
3707
3708 /*-----------------------------------------------------------------*/
3709 /* findLabelBackwards: walks back through the iCode chain looking  */
3710 /* for the given label. Returns number of iCode instructions     */
3711 /* between that label and given ic.          */
3712 /* Returns zero if label not found.          */
3713 /*-----------------------------------------------------------------*/
3714 static int
3715 findLabelBackwards (iCode * ic, int key)
3716 {
3717   int count = 0;
3718
3719   while (ic->prev)
3720     {
3721       ic = ic->prev;
3722       count++;
3723
3724       /* If we have any pushes or pops, we cannot predict the distance.
3725          I don't like this at all, this should be dealt with in the
3726          back-end */
3727       if (ic->op == IPUSH || ic->op == IPOP) {
3728         return 0;
3729       }
3730
3731       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3732         {
3733           /* printf("findLabelBackwards = %d\n", count); */
3734           return count;
3735         }
3736     }
3737
3738   return 0;
3739 }
3740
3741 /*-----------------------------------------------------------------*/
3742 /* genPlusIncr :- does addition with increment if possible         */
3743 /*-----------------------------------------------------------------*/
3744 static bool
3745 genPlusIncr (iCode * ic)
3746 {
3747   unsigned int icount;
3748   unsigned int size = getDataSize (IC_RESULT (ic));
3749
3750   /* will try to generate an increment */
3751   /* if the right side is not a literal
3752      we cannot */
3753   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3754     return FALSE;
3755
3756   /* if the literal value of the right hand side
3757      is greater than 4 then it is not worth it */
3758   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3759     return FALSE;
3760
3761   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3762       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3763       while (icount--) {
3764           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3765       }
3766       return TRUE;
3767   }
3768   /* if increment 16 bits in register */
3769   if (
3770        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3771        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3772        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3773        (size > 1) &&
3774        (icount == 1))
3775     {
3776       symbol  *tlbl;
3777       int     emitTlbl;
3778       int     labelRange;
3779       char    *l;
3780
3781       /* If the next instruction is a goto and the goto target
3782        * is <= 5 instructions previous to this, we can generate
3783        * jumps straight to that target.
3784        */
3785       if (ic->next && ic->next->op == GOTO
3786           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3787           && labelRange <= 5)
3788         {
3789           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3790           tlbl = IC_LABEL (ic->next);
3791           emitTlbl = 0;
3792         }
3793       else
3794         {
3795           tlbl = newiTempLabel (NULL);
3796           emitTlbl = 1;
3797         }
3798
3799       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3800       emitcode ("inc", "%s", l);
3801
3802       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3803           IS_AOP_PREG (IC_RESULT (ic)))
3804         {
3805           emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3806         }
3807       else
3808         {
3809           emitcode ("clr", "a");
3810           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3811         }
3812
3813       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3814       emitcode ("inc", "%s", l);
3815       if (size > 2)
3816         {
3817           if (!strcmp(l, "acc"))
3818             {
3819                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3820             }
3821           else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3822                    IS_AOP_PREG (IC_RESULT (ic)))
3823             {
3824                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3825             }
3826           else
3827             {
3828                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3829             }
3830
3831           l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3832           emitcode ("inc", "%s", l);
3833         }
3834       if (size > 3)
3835         {
3836           if (!strcmp(l, "acc"))
3837             {
3838                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3839             }
3840           else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3841                    IS_AOP_PREG (IC_RESULT (ic)))
3842             {
3843                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3844             }
3845           else
3846             {
3847                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3848             }
3849
3850           l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3851           emitcode ("inc", "%s", l);
3852         }
3853
3854       if (emitTlbl)
3855         {
3856           emitcode ("", "!tlabeldef", tlbl->key + 100);
3857         }
3858       return TRUE;
3859     }
3860
3861   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3862       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3863       options.model == MODEL_FLAT24 )
3864     {
3865       if (IC_RESULT(ic)->isGptr)
3866         {
3867           emitcode ("mov","b,%s",aopGet(AOP (IC_LEFT (ic)), 3, FALSE, FALSE, NULL));
3868         }
3869       switch (size) {
3870       case 3:
3871           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3872       case 2:
3873           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3874       case 1:
3875           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3876           break;
3877       }
3878       while (icount--) emitcode ("inc","dptr");
3879       return TRUE;
3880   }
3881
3882   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3883       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3884       icount <= 5 ) {
3885       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3886       while (icount--) emitcode ("inc","dptr");
3887       emitcode ("mov","dps,#0");
3888       return TRUE;
3889   }
3890
3891   /* if the sizes are greater than 1 then we cannot */
3892   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3893       AOP_SIZE (IC_LEFT (ic)) > 1)
3894     return FALSE;
3895
3896   /* we can if the aops of the left & result match or
3897      if they are in registers and the registers are the
3898      same */
3899   if (
3900        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3901        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3902        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3903     {
3904
3905       if (icount > 3)
3906         {
3907           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3908           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3909           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3910         }
3911       else
3912         {
3913
3914           _startLazyDPSEvaluation ();
3915           while (icount--)
3916             {
3917               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3918             }
3919           _endLazyDPSEvaluation ();
3920         }
3921
3922       return TRUE;
3923     }
3924
3925   return FALSE;
3926 }
3927
3928 /*-----------------------------------------------------------------*/
3929 /* outBitAcc - output a bit in acc                                 */
3930 /*-----------------------------------------------------------------*/
3931 static void
3932 outBitAcc (operand * result)
3933 {
3934   symbol *tlbl = newiTempLabel (NULL);
3935   /* if the result is a bit */
3936   if (AOP_TYPE (result) == AOP_CRY)
3937     {
3938       aopPut (AOP (result), "a", 0);
3939     }
3940   else
3941     {
3942       emitcode ("jz", "!tlabel", tlbl->key + 100);
3943       emitcode ("mov", "a,%s", one);
3944       emitcode ("", "!tlabeldef", tlbl->key + 100);
3945       outAcc (result);
3946     }
3947 }
3948
3949 /*-----------------------------------------------------------------*/
3950 /* genPlusBits - generates code for addition of two bits           */
3951 /*-----------------------------------------------------------------*/
3952 static void
3953 genPlusBits (iCode * ic)
3954 {
3955   D (emitcode (";", "genPlusBits "););
3956
3957   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3958     {
3959       symbol *lbl = newiTempLabel (NULL);
3960       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3961       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3962       emitcode ("cpl", "c");
3963       emitcode ("", "!tlabeldef", (lbl->key + 100));
3964       outBitC (IC_RESULT (ic));
3965     }
3966   else
3967     {
3968       emitcode ("clr", "a");
3969       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3970       emitcode ("rlc", "a");
3971       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3972       emitcode ("addc", "a,#0");
3973       outAcc (IC_RESULT (ic));
3974     }
3975 }
3976
3977 static void
3978 adjustArithmeticResult (iCode * ic)
3979 {
3980   if (opIsGptr (IC_RESULT (ic)) &&
3981       opIsGptr (IC_LEFT (ic)) &&
3982       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3983     {
3984       aopPut (AOP (IC_RESULT (ic)),
3985               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3986               GPTRSIZE - 1);
3987     }
3988
3989   if (opIsGptr (IC_RESULT (ic)) &&
3990       opIsGptr (IC_RIGHT (ic)) &&
3991       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3992     {
3993       aopPut (AOP (IC_RESULT (ic)),
3994             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3995               GPTRSIZE - 1);
3996     }
3997
3998   if (opIsGptr (IC_RESULT (ic)) &&
3999       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4000       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4001       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4002       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4003     {
4004       char buff[5];
4005       SNPRINTF (buff, sizeof(buff),
4006                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4007       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
4008     }
4009 }
4010
4011 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4012 // generates the result if possible. If result is generated, returns TRUE; otherwise
4013 // returns false and caller must deal with fact that result isn't aopOp'd.
4014 bool aopOp3(iCode * ic)
4015 {
4016     bool dp1InUse, dp2InUse;
4017     bool useDp2;
4018
4019     // First, generate the right opcode. DPTR may be used if neither left nor result are
4020     // of type AOP_STR.
4021
4022 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4023 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4024 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4025 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4026 //      );
4027 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4028 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4029 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4030 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4031 //      );
4032
4033     // Right uses DPTR unless left or result is an AOP_STR; however,
4034     // if right is an AOP_STR, it must use DPTR regardless.
4035     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4036      && !AOP_IS_STR(IC_RIGHT(ic)))
4037     {
4038         useDp2 = TRUE;
4039     }
4040     else
4041     {
4042         useDp2 = FALSE;
4043     }
4044
4045     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4046
4047     // if the right used DPTR, left MUST use DPTR2.
4048     // if the right used DPTR2, left MUST use DPTR.
4049     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4050     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4051     // enabling us to assign DPTR to result.
4052
4053     if (AOP_USESDPTR(IC_RIGHT(ic)))
4054     {
4055         useDp2 = TRUE;
4056     }
4057     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4058     {
4059         useDp2 = FALSE;
4060     }
4061     else
4062     {
4063         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4064         {
4065             useDp2 = TRUE;
4066         }
4067         else
4068         {
4069             useDp2 = FALSE;
4070         }
4071     }
4072
4073     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4074
4075
4076     // We've op'd the left & right. So, if left or right are the same operand as result,
4077     // we know aopOp will succeed, and we can just do it & bail.
4078     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4079       {
4080         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4081         return TRUE;
4082       }
4083     if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4084       {
4085 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
4086         aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4087         return TRUE;
4088       }
4089
4090     // Operands may be equivalent (but not equal) if they share a spill location. If
4091     // so, use the same DPTR or DPTR2.
4092     if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4093       {
4094         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4095         return TRUE;
4096       }
4097     if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4098       {
4099         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4100         return TRUE;
4101       }
4102
4103     // Note which dptrs are currently in use.
4104     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4105     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4106
4107     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4108     // generate it.
4109     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4110     {
4111         return FALSE;
4112     }
4113
4114     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4115     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4116     {
4117         return FALSE;
4118     }
4119
4120     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4121     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4122     {
4123         return FALSE;
4124     }
4125
4126     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4127
4128     // Some sanity checking...
4129     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4130     {
4131         fprintf(stderr,
4132                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4133                 __FILE__, __LINE__, ic->filename, ic->lineno);
4134         emitcode(";", ">>> unexpected DPTR here.");
4135     }
4136
4137     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4138     {
4139         fprintf(stderr,
4140                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4141                 __FILE__, __LINE__, ic->filename, ic->lineno);
4142         emitcode(";", ">>> unexpected DPTR2 here.");
4143     }
4144
4145     return TRUE;
4146 }
4147
4148 // Macro to aopOp all three operands of an ic. If this cannot be done,
4149 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4150 // will be set TRUE. The caller must then handle the case specially, noting
4151 // that the IC_RESULT operand is not aopOp'd.
4152 //
4153 #define AOP_OP_3_NOFATAL(ic, rc) \
4154             do { rc = !aopOp3(ic); } while (0)
4155
4156 // aopOp the left & right operands of an ic.
4157 #define AOP_OP_2(ic) \
4158     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4159     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4160
4161 // convienience macro.
4162 #define AOP_SET_LOCALS(ic) \
4163     left = IC_LEFT(ic); \
4164     right = IC_RIGHT(ic); \
4165     result = IC_RESULT(ic);
4166
4167
4168 // Given an integer value of pushedSize bytes on the stack,
4169 // adjust it to be resultSize bytes, either by discarding
4170 // the most significant bytes or by zero-padding.
4171 //
4172 // On exit from this macro, pushedSize will have been adjusted to
4173 // equal resultSize, and ACC may be trashed.
4174 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4175       /* If the pushed data is bigger than the result,          \
4176        * simply discard unused bytes. Icky, but works.          \
4177        */                                                       \
4178       while (pushedSize > resultSize)                           \
4179       {                                                         \
4180           D (emitcode (";", "discarding unused result byte."););\
4181           emitcode ("pop", "acc");                              \
4182           pushedSize--;                                         \
4183       }                                                         \
4184       if (pushedSize < resultSize)                              \
4185       {                                                         \
4186           emitcode ("clr", "a");                                \
4187           /* Conversly, we haven't pushed enough here.          \
4188            * just zero-pad, and all is well.                    \
4189            */                                                   \
4190           while (pushedSize < resultSize)                       \
4191           {                                                     \
4192               emitcode("push", "acc");                          \
4193               pushedSize++;                                     \
4194           }                                                     \
4195       }                                                         \
4196       assert(pushedSize == resultSize);
4197
4198 /*-----------------------------------------------------------------*/
4199 /* genPlus - generates code for addition                           */
4200 /*-----------------------------------------------------------------*/
4201 static void
4202 genPlus (iCode * ic)
4203 {
4204   int size, offset = 0;
4205   bool pushResult;
4206   int rSize;
4207
4208   D (emitcode (";", "genPlus "););
4209
4210   /* special cases :- */
4211   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4212       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4213       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4214       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4215       if (size <= 9) {
4216           while (size--) emitcode ("inc","dptr");
4217       } else {
4218           emitcode ("mov","a,dpl");
4219           emitcode ("add","a,#!constbyte",size & 0xff);
4220           emitcode ("mov","dpl,a");
4221           emitcode ("mov","a,dph");
4222           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4223           emitcode ("mov","dph,a");
4224           emitcode ("mov","a,dpx");
4225           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4226           emitcode ("mov","dpx,a");
4227       }
4228       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4229       return ;
4230   }
4231   if ( IS_SYMOP(IC_LEFT(ic)) &&
4232        OP_SYMBOL(IC_LEFT(ic))->remat &&
4233        isOperandInFarSpace(IC_RIGHT(ic))) {
4234       operand *op = IC_RIGHT(ic);
4235       IC_RIGHT(ic) = IC_LEFT(ic);
4236       IC_LEFT(ic) = op;
4237   }
4238
4239   AOP_OP_3_NOFATAL (ic, pushResult);
4240
4241   if (pushResult)
4242     {
4243       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4244     }
4245
4246   if (!pushResult)
4247     {
4248       /* if literal, literal on the right or
4249          if left requires ACC or right is already
4250          in ACC */
4251       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4252        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4253           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4254         {
4255           operand *t = IC_RIGHT (ic);
4256           IC_RIGHT (ic) = IC_LEFT (ic);
4257           IC_LEFT (ic) = t;
4258           emitcode (";", "Swapped plus args.");
4259         }
4260
4261       /* if both left & right are in bit
4262          space */
4263       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4264           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4265         {
4266           genPlusBits (ic);
4267           goto release;
4268         }
4269
4270       /* if left in bit space & right literal */
4271       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4272           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4273         {
4274           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4275           /* if result in bit space */
4276           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4277             {
4278               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4279                 emitcode ("cpl", "c");
4280               outBitC (IC_RESULT (ic));
4281             }
4282           else
4283             {
4284               size = getDataSize (IC_RESULT (ic));
4285               _startLazyDPSEvaluation ();
4286               while (size--)
4287                 {
4288                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4289                   emitcode ("addc", "a,#0");
4290                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4291                 }
4292               _endLazyDPSEvaluation ();
4293             }
4294           goto release;
4295         }
4296
4297       /* if I can do an increment instead
4298          of add then GOOD for ME */
4299       if (genPlusIncr (ic) == TRUE)
4300         {
4301           emitcode (";", "did genPlusIncr");
4302           goto release;
4303         }
4304
4305     }
4306   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4307
4308   _startLazyDPSEvaluation ();
4309   while (size--)
4310     {
4311       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4312         {
4313           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4314           if (offset == 0)
4315             emitcode ("add", "a,%s",
4316                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4317           else
4318             emitcode ("addc", "a,%s",
4319                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4320         }
4321       else
4322         {
4323           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4324           {
4325               /* right is going to use ACC or we would have taken the
4326                * above branch.
4327                */
4328               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4329        TR_AP("#3");
4330               D(emitcode(";", "+ AOP_ACC special case."););
4331               emitcode("xch", "a, %s", DP2_RESULT_REG);
4332           }
4333           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4334           if (offset == 0)
4335           {
4336             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4337             {
4338          TR_AP("#4");
4339                 emitcode("add", "a, %s", DP2_RESULT_REG);
4340             }
4341             else
4342             {
4343                 emitcode ("add", "a,%s",
4344                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4345                                   DP2_RESULT_REG));
4346             }
4347           }
4348           else
4349           {
4350             emitcode ("addc", "a,%s",
4351                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4352                           DP2_RESULT_REG));
4353           }
4354         }
4355       if (!pushResult)
4356         {
4357           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4358         }
4359       else
4360         {
4361           emitcode ("push", "acc");
4362         }
4363       offset++;
4364     }
4365   _endLazyDPSEvaluation ();
4366
4367   if (pushResult)
4368     {
4369       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4370
4371       size = getDataSize (IC_LEFT (ic));
4372       rSize = getDataSize (IC_RESULT (ic));
4373
4374       ADJUST_PUSHED_RESULT(size, rSize);
4375
4376       _startLazyDPSEvaluation ();
4377       while (size--)
4378         {
4379           emitcode ("pop", "acc");
4380           aopPut (AOP (IC_RESULT (ic)), "a", size);
4381         }
4382       _endLazyDPSEvaluation ();
4383     }
4384
4385   adjustArithmeticResult (ic);
4386
4387 release:
4388   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4389   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4390   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4391 }
4392
4393 /*-----------------------------------------------------------------*/
4394 /* genMinusDec :- does subtraction with deccrement if possible     */
4395 /*-----------------------------------------------------------------*/
4396 static bool
4397 genMinusDec (iCode * ic)
4398 {
4399   unsigned int icount;
4400   unsigned int size = getDataSize (IC_RESULT (ic));
4401
4402   /* will try to generate an increment */
4403   /* if the right side is not a literal
4404      we cannot */
4405   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4406     return FALSE;
4407
4408   /* if the literal value of the right hand side
4409      is greater than 4 then it is not worth it */
4410   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4411     return FALSE;
4412
4413   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4414       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4415       while (icount--) {
4416           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4417       }
4418       return TRUE;
4419   }
4420   /* if decrement 16 bits in register */
4421   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4422       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4423       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4424       (size > 1) &&
4425       (icount == 1))
4426     {
4427       symbol *tlbl;
4428       int    emitTlbl;
4429       int    labelRange;
4430       char   *l;
4431
4432       /* If the next instruction is a goto and the goto target
4433          * is <= 5 instructions previous to this, we can generate
4434          * jumps straight to that target.
4435        */
4436       if (ic->next && ic->next->op == GOTO
4437           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4438           && labelRange <= 5)
4439         {
4440           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4441           tlbl = IC_LABEL (ic->next);
4442           emitTlbl = 0;
4443         }
4444       else
4445         {
4446           tlbl = newiTempLabel (NULL);
4447           emitTlbl = 1;
4448         }
4449
4450       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4451       emitcode ("dec", "%s", l);
4452
4453       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4454           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4455           IS_AOP_PREG (IC_RESULT (ic)))
4456       {
4457           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4458       }
4459       else
4460       {
4461           emitcode ("mov", "a,#!constbyte",0xff);
4462           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4463       }
4464       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4465       emitcode ("dec", "%s", l);
4466       if (size > 2)
4467         {
4468             if (!strcmp(l, "acc"))
4469             {
4470                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4471             }
4472             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4473                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4474                      IS_AOP_PREG (IC_RESULT (ic)))
4475             {
4476                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4477             }
4478             else
4479             {
4480                 emitcode ("mov", "a,#!constbyte",0xff);
4481                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4482             }
4483             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4484             emitcode ("dec", "%s", l);
4485         }
4486       if (size > 3)
4487         {
4488             if (!strcmp(l, "acc"))
4489             {
4490                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4491             }
4492             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4493                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4494                      IS_AOP_PREG (IC_RESULT (ic)))
4495             {
4496                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4497             }
4498             else
4499             {
4500                 emitcode ("mov", "a,#!constbyte",0xff);
4501                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4502             }
4503             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4504             emitcode ("dec", "%s", l);
4505         }
4506       if (emitTlbl)
4507         {
4508           emitcode ("", "!tlabeldef", tlbl->key + 100);
4509         }
4510       return TRUE;
4511     }
4512
4513   /* if the sizes are greater than 1 then we cannot */
4514   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4515       AOP_SIZE (IC_LEFT (ic)) > 1)
4516     return FALSE;
4517
4518   /* we can if the aops of the left & result match or
4519      if they are in registers and the registers are the
4520      same */
4521   if (
4522        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4523        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4524        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4525     {
4526
4527       _startLazyDPSEvaluation ();
4528       while (icount--)
4529         {
4530           emitcode ("dec", "%s",
4531                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4532         }
4533       _endLazyDPSEvaluation ();
4534
4535       return TRUE;
4536     }
4537
4538   return FALSE;
4539 }
4540
4541 /*-----------------------------------------------------------------*/
4542 /* addSign - complete with sign                                    */
4543 /*-----------------------------------------------------------------*/
4544 static void
4545 addSign (operand * result, int offset, int sign)
4546 {
4547   int size = (getDataSize (result) - offset);
4548   if (size > 0)
4549     {
4550       _startLazyDPSEvaluation();
4551       if (sign)
4552         {
4553           emitcode ("rlc", "a");
4554           emitcode ("subb", "a,acc");
4555           while (size--)
4556           {
4557             aopPut (AOP (result), "a", offset++);
4558           }
4559         }
4560       else
4561       {
4562         while (size--)
4563         {
4564           aopPut (AOP (result), zero, offset++);
4565         }
4566       }
4567       _endLazyDPSEvaluation();
4568     }
4569 }
4570
4571 /*-----------------------------------------------------------------*/
4572 /* genMinusBits - generates code for subtraction  of two bits      */
4573 /*-----------------------------------------------------------------*/
4574 static void
4575 genMinusBits (iCode * ic)
4576 {
4577   symbol *lbl = newiTempLabel (NULL);
4578
4579   D (emitcode (";", "genMinusBits "););
4580
4581   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4582     {
4583       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4584       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4585       emitcode ("cpl", "c");
4586       emitcode ("", "!tlabeldef", (lbl->key + 100));
4587       outBitC (IC_RESULT (ic));
4588     }
4589   else
4590     {
4591       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4592       emitcode ("subb", "a,acc");
4593       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4594       emitcode ("inc", "a");
4595       emitcode ("", "!tlabeldef", (lbl->key + 100));
4596       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4597       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4598     }
4599 }
4600
4601 /*-----------------------------------------------------------------*/
4602 /* genMinus - generates code for subtraction                       */
4603 /*-----------------------------------------------------------------*/
4604 static void
4605 genMinus (iCode * ic)
4606 {
4607     int size, offset = 0;
4608     int rSize;
4609     long lit = 0L;
4610     bool pushResult;
4611
4612     D (emitcode (";", "genMinus "););
4613
4614     AOP_OP_3_NOFATAL(ic, pushResult);
4615
4616     if (!pushResult)
4617     {
4618       /* special cases :- */
4619       /* if both left & right are in bit space */
4620       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4621           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4622         {
4623           genMinusBits (ic);
4624           goto release;
4625         }
4626
4627       /* if I can do an decrement instead
4628          of subtract then GOOD for ME */
4629       if (genMinusDec (ic) == TRUE)
4630         goto release;
4631
4632     }
4633
4634   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4635
4636   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4637     {
4638       CLRC;
4639     }
4640   else
4641     {
4642       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4643       lit = -lit;
4644     }
4645
4646
4647   /* if literal, add a,#-lit, else normal subb */
4648   _startLazyDPSEvaluation ();
4649   while (size--) {
4650       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4651           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4652               emitcode ("mov","b,%s",
4653                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4654               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4655               emitcode ("subb","a,b");
4656           } else {
4657               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4658               emitcode ("subb", "a,%s",
4659                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4660                                 DP2_RESULT_REG));
4661           }
4662       } else {
4663           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4664           /* first add without previous c */
4665           if (!offset) {
4666               if (!size && lit==-1) {
4667                   emitcode ("dec", "a");
4668               } else {
4669                   emitcode ("add", "a,#!constbyte",
4670                             (unsigned int) (lit & 0x0FFL));
4671               }
4672           } else {
4673               emitcode ("addc", "a,#!constbyte",
4674                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4675           }
4676       }
4677
4678       if (pushResult) {
4679           emitcode ("push", "acc");
4680       } else {
4681           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4682       }
4683       offset++;
4684   }
4685   _endLazyDPSEvaluation ();
4686
4687   if (pushResult)
4688     {
4689       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4690
4691       size = getDataSize (IC_LEFT (ic));
4692       rSize = getDataSize (IC_RESULT (ic));
4693
4694       ADJUST_PUSHED_RESULT(size, rSize);
4695
4696       _startLazyDPSEvaluation ();
4697       while (size--)
4698         {
4699           emitcode ("pop", "acc");
4700           aopPut (AOP (IC_RESULT (ic)), "a", size);
4701         }
4702       _endLazyDPSEvaluation ();
4703     }
4704
4705   adjustArithmeticResult (ic);
4706
4707 release:
4708   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4709   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4710   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4711 }
4712
4713
4714 /*-----------------------------------------------------------------*/
4715 /* genMultbits :- multiplication of bits                           */
4716 /*-----------------------------------------------------------------*/
4717 static void
4718 genMultbits (operand * left,
4719              operand * right,
4720              operand * result,
4721              iCode   * ic)
4722 {
4723   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4724   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4725   aopOp(result, ic, TRUE, FALSE);
4726   outBitC (result);
4727 }
4728
4729
4730 /*-----------------------------------------------------------------*/
4731 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4732 /*-----------------------------------------------------------------*/
4733 static void
4734 genMultOneByte (operand * left,
4735                 operand * right,
4736                 operand * result,
4737                 iCode   * ic)
4738 {
4739   int size;
4740   symbol *lbl;
4741   bool runtimeSign, compiletimeSign;
4742   bool lUnsigned, rUnsigned;
4743
4744
4745   /* (if two literals: the value is computed before) */
4746   /* if one literal, literal on the right */
4747   if (AOP_TYPE (left) == AOP_LIT)
4748     {
4749       operand *t = right;
4750       right = left;
4751       left = t;
4752       emitcode (";", "swapped left and right");
4753     }
4754
4755   /* (if two literals: the value is computed before) */
4756   /* if one literal, literal on the right */
4757   if (AOP_TYPE (left) == AOP_LIT)
4758     {
4759       operand *t = right;
4760       right = left;
4761       left = t;
4762       /* emitcode (";", "swapped left and right"); */
4763     }
4764   /* if no literal, unsigned on the right: shorter code */
4765   if (   AOP_TYPE (right) != AOP_LIT
4766       && SPEC_USIGN (getSpec (operandType (left))))
4767     {
4768       operand *t = right;
4769       right = left;
4770       left = t;
4771     }
4772
4773   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4774   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4775
4776   if ((lUnsigned && rUnsigned)
4777 /* sorry, I don't know how to get size
4778    without calling aopOp (result,...);
4779    see Feature Request  */
4780       /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4781                    no need to take care about the signedness! */
4782     {
4783       /* just an unsigned 8 * 8 = 8 multiply
4784          or 8u * 8u = 16u */
4785       /* emitcode (";","unsigned"); */
4786       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4787       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4788       emitcode ("mul", "ab");
4789
4790       _G.accInUse++; _G.bInUse++;
4791       aopOp (result, ic, TRUE, FALSE);
4792       size = AOP_SIZE (result);
4793
4794       if (size < 1 || size > 2)
4795         {
4796           /* this should never happen */
4797           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4798                    size, __FILE__, lineno);
4799           exit (1);
4800         }
4801
4802       aopPut (AOP (result), "a", 0);
4803       _G.accInUse--; _G.bInUse--;
4804       if (size == 2)
4805         aopPut (AOP (result), "b", 1);
4806       return;
4807     }
4808
4809   /* we have to do a signed multiply */
4810   /* emitcode (";", "signed"); */
4811
4812   /* now sign adjust for both left & right */
4813
4814   /* let's see what's needed: */
4815   /* apply negative sign during runtime */
4816   runtimeSign = FALSE;
4817   /* negative sign from literals */
4818   compiletimeSign = FALSE;
4819
4820   if (!lUnsigned)
4821     {
4822       if (AOP_TYPE(left) == AOP_LIT)
4823         {
4824           /* signed literal */
4825           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4826           if (val < 0)
4827             compiletimeSign = TRUE;
4828         }
4829       else
4830         /* signed but not literal */
4831         runtimeSign = TRUE;
4832     }
4833
4834   if (!rUnsigned)
4835     {
4836       if (AOP_TYPE(right) == AOP_LIT)
4837         {
4838           /* signed literal */
4839           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4840           if (val < 0)
4841             compiletimeSign ^= TRUE;
4842         }
4843       else
4844         /* signed but not literal */
4845         runtimeSign = TRUE;
4846     }
4847
4848   /* initialize F0, which stores the runtime sign */
4849   if (runtimeSign)
4850     {
4851       if (compiletimeSign)
4852         emitcode ("setb", "F0"); /* set sign flag */
4853       else
4854         emitcode ("clr", "F0"); /* reset sign flag */
4855     }
4856
4857   /* save the signs of the operands */
4858   if (AOP_TYPE(right) == AOP_LIT)
4859     {
4860       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4861
4862       if (!rUnsigned && val < 0)
4863         emitcode ("mov", "b,#!constbyte", -val);
4864       else
4865         emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4866     }
4867   else /* ! literal */
4868     {
4869       if (rUnsigned)  /* emitcode (";", "signed"); */
4870         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4871       else
4872         {
4873           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4874           lbl = newiTempLabel (NULL);
4875           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4876           emitcode ("cpl", "F0"); /* complement sign flag */
4877           emitcode ("cpl", "a");  /* 2's complement */
4878           emitcode ("inc", "a");
4879           emitcode ("", "!tlabeldef", lbl->key + 100);
4880           emitcode ("mov", "b,a");
4881         }
4882     }
4883
4884   if (AOP_TYPE(left) == AOP_LIT)
4885     {
4886       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4887
4888       if (!lUnsigned && val < 0)
4889         emitcode ("mov", "a,#!constbyte", -val);
4890       else
4891         emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4892     }
4893   else /* ! literal */
4894     {
4895       if (lUnsigned)  /* emitcode (";", "signed"); */
4896
4897         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4898       else
4899         {
4900           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4901           lbl = newiTempLabel (NULL);
4902           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4903           emitcode ("cpl", "F0"); /* complement sign flag */
4904           emitcode ("cpl", "a");  /* 2's complement */
4905           emitcode ("inc", "a");
4906           emitcode ("", "!tlabeldef", lbl->key + 100);
4907         }
4908     }
4909
4910   /* now the multiplication */
4911   emitcode ("mul", "ab");
4912   _G.accInUse++;_G.bInUse++;
4913   aopOp(result, ic, TRUE, FALSE);
4914   size = AOP_SIZE (result);
4915
4916   if (size < 1 || size > 2)
4917     {
4918       /* this should never happen */
4919       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4920                size, __FILE__, lineno);
4921       exit (1);
4922     }
4923
4924   if (runtimeSign || compiletimeSign)
4925     {
4926       lbl = newiTempLabel (NULL);
4927       if (runtimeSign)
4928         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4929       emitcode ("cpl", "a"); /* lsb 2's complement */
4930       if (size != 2)
4931         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4932       else
4933         {
4934           emitcode ("add", "a,#1"); /* this sets carry flag */
4935           emitcode ("xch", "a,b");
4936           emitcode ("cpl", "a"); /* msb 2's complement */
4937           emitcode ("addc", "a,#0");
4938           emitcode ("xch", "a,b");
4939         }
4940       emitcode ("", "!tlabeldef", lbl->key + 100);
4941     }
4942   aopPut (AOP (result), "a", 0);
4943   _G.accInUse--;_G.bInUse--;
4944   if (size == 2)
4945     aopPut (AOP (result), "b", 1);
4946 }
4947
4948 /*-----------------------------------------------------------------*/
4949 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4950 /*-----------------------------------------------------------------*/
4951 static void genMultTwoByte (operand *left, operand *right,
4952                             operand *result, iCode *ic)
4953 {
4954         sym_link *retype = getSpec(operandType(right));
4955         sym_link *letype = getSpec(operandType(left));
4956         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4957         symbol *lbl;
4958
4959         if (AOP_TYPE (left) == AOP_LIT) {
4960                 operand *t = right;
4961                 right = left;
4962                 left = t;
4963         }
4964         /* save EA bit in F1 */
4965         lbl = newiTempLabel(NULL);
4966         emitcode ("setb","F1");
4967         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4968         emitcode ("clr","F1");
4969         emitcode("","!tlabeldef",lbl->key+100);
4970
4971         /* load up MB with right */
4972         if (!umult) {
4973                 emitcode("clr","F0");
4974                 if (AOP_TYPE(right) == AOP_LIT) {
4975                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4976                         if (val < 0) {
4977                                 emitcode("setb","F0");
4978                                 val = -val;
4979                         }
4980                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4981                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4982                 } else {
4983                         lbl = newiTempLabel(NULL);
4984                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4985                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4986                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4987                         emitcode ("xch", "a,b");
4988                         emitcode ("cpl","a");
4989                         emitcode ("add", "a,#1");
4990                         emitcode ("xch", "a,b");
4991                         emitcode ("cpl", "a"); // msb
4992                         emitcode ("addc", "a,#0");
4993                         emitcode ("setb","F0");
4994                         emitcode ("","!tlabeldef",lbl->key+100);
4995                         emitcode ("mov","mb,b");
4996                         emitcode ("mov","mb,a");
4997                 }
4998         } else {
4999                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5000                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5001         }
5002         /* load up MA with left */
5003         if (!umult) {
5004                 lbl = newiTempLabel(NULL);
5005                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5006                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5007                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5008                 emitcode ("xch", "a,b");
5009                 emitcode ("cpl","a");
5010                 emitcode ("add", "a,#1");
5011                 emitcode ("xch", "a,b");
5012                 emitcode ("cpl", "a"); // msb
5013                 emitcode ("addc","a,#0");
5014                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5015                 emitcode ("setb","F0");
5016                 emitcode ("","!tlabeldef",lbl->key+100);
5017                 emitcode ("mov","ma,b");
5018                 emitcode ("mov","ma,a");
5019         } else {
5020                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5021                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5022         }
5023         /* wait for multiplication to finish */
5024         lbl = newiTempLabel(NULL);
5025         emitcode("","!tlabeldef", lbl->key+100);
5026         emitcode("mov","a,mcnt1");
5027         emitcode("anl","a,#!constbyte",0x80);
5028         emitcode("jnz","!tlabel",lbl->key+100);
5029
5030         freeAsmop (left, NULL, ic, TRUE);
5031         freeAsmop (right, NULL, ic,TRUE);
5032         aopOp(result, ic, TRUE, FALSE);
5033
5034         /* if unsigned then simple */
5035         if (umult) {
5036                 emitcode ("mov","a,ma");
5037                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5038                 emitcode ("mov","a,ma");
5039                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5040                 aopPut(AOP(result),"ma",1);
5041                 aopPut(AOP(result),"ma",0);
5042         } else {
5043                 emitcode("push","ma");
5044                 emitcode("push","ma");
5045                 emitcode("push","ma");
5046                 MOVA("ma");
5047                 /* negate result if needed */
5048                 lbl = newiTempLabel(NULL);
5049                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5050                 emitcode("cpl","a");
5051                 emitcode("add","a,#1");
5052                 emitcode("","!tlabeldef", lbl->key+100);
5053                 if (AOP_TYPE(result) == AOP_ACC)
5054                 {
5055                     D(emitcode(";", "ACC special case."););
5056                     /* We know result is the only live aop, and
5057                      * it's obviously not a DPTR2, so AP is available.
5058                      */
5059                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
5060                 }
5061                 else
5062                 {
5063                     aopPut(AOP(result),"a",0);
5064                 }
5065
5066                 emitcode("pop","acc");
5067                 lbl = newiTempLabel(NULL);
5068                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5069                 emitcode("cpl","a");
5070                 emitcode("addc","a,#0");
5071                 emitcode("","!tlabeldef", lbl->key+100);
5072                 aopPut(AOP(result),"a",1);
5073                 emitcode("pop","acc");
5074                 if (AOP_SIZE(result) >= 3) {
5075                         lbl = newiTempLabel(NULL);
5076                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5077                         emitcode("cpl","a");
5078                         emitcode("addc","a,#0");
5079                         emitcode("","!tlabeldef", lbl->key+100);
5080                         aopPut(AOP(result),"a",2);
5081                 }
5082                 emitcode("pop","acc");
5083                 if (AOP_SIZE(result) >= 4) {
5084                         lbl = newiTempLabel(NULL);
5085                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5086                         emitcode("cpl","a");
5087                         emitcode("addc","a,#0");
5088                         emitcode("","!tlabeldef", lbl->key+100);
5089                         aopPut(AOP(result),"a",3);
5090                 }
5091                 if (AOP_TYPE(result) == AOP_ACC)
5092                 {
5093                     /* We stashed the result away above. */
5094                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
5095                 }
5096
5097         }
5098         freeAsmop (result, NULL, ic, TRUE);
5099
5100         /* restore EA bit in F1 */
5101         lbl = newiTempLabel(NULL);
5102         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5103         emitcode ("setb","EA");
5104         emitcode("","!tlabeldef",lbl->key+100);
5105         return ;
5106 }
5107
5108 /*-----------------------------------------------------------------*/
5109 /* genMult - generates code for multiplication                     */
5110 /*-----------------------------------------------------------------*/
5111 static void
5112 genMult (iCode * ic)
5113 {
5114   operand *left = IC_LEFT (ic);
5115   operand *right = IC_RIGHT (ic);
5116   operand *result = IC_RESULT (ic);
5117
5118   D (emitcode (";", "genMult "););
5119
5120   /* assign the amsops */
5121   AOP_OP_2 (ic);
5122
5123   /* special cases first */
5124   /* both are bits */
5125   if (AOP_TYPE (left) == AOP_CRY &&
5126       AOP_TYPE (right) == AOP_CRY)
5127     {
5128       genMultbits (left, right, result, ic);
5129       goto release;
5130     }
5131
5132   /* if both are of size == 1 */
5133   if (AOP_SIZE (left) == 1 &&
5134       AOP_SIZE (right) == 1)
5135     {
5136       genMultOneByte (left, right, result, ic);
5137       goto release;
5138     }
5139
5140   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5141           /* use the ds390 ARITHMETIC accel UNIT */
5142           genMultTwoByte (left, right, result, ic);
5143           return ;
5144   }
5145   /* should have been converted to function call */
5146   assert (0);
5147
5148 release:
5149   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5150   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5151   freeAsmop (result, NULL, ic, TRUE);
5152 }
5153
5154 /*-----------------------------------------------------------------*/
5155 /* genDivbits :- division of bits                                  */
5156 /*-----------------------------------------------------------------*/
5157 static void
5158 genDivbits (operand * left,
5159             operand * right,
5160             operand * result,
5161             iCode   * ic)
5162 {
5163
5164   char *l;
5165
5166   /* the result must be bit */
5167   LOAD_AB_FOR_DIV (left, right, l);
5168   emitcode ("div", "ab");
5169   emitcode ("rrc", "a");
5170   aopOp(result, ic, TRUE, FALSE);
5171
5172   aopPut (AOP (result), "c", 0);
5173 }
5174
5175 /*-----------------------------------------------------------------*/
5176 /* genDivOneByte : 8 bit division                                  */
5177 /*-----------------------------------------------------------------*/
5178 static void
5179 genDivOneByte (operand * left,
5180                operand * right,
5181                operand * result,
5182                iCode   * ic)
5183 {
5184   bool lUnsigned, rUnsigned;
5185   bool runtimeSign, compiletimeSign;
5186   char *l;
5187   symbol *lbl;
5188   int size, offset;
5189
5190   offset = 1;
5191   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5192   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5193
5194   /* signed or unsigned */
5195   if (lUnsigned && rUnsigned)
5196     {
5197       /* unsigned is easy */
5198       LOAD_AB_FOR_DIV (left, right, l);
5199       emitcode ("div", "ab");
5200
5201       _G.accInUse++;
5202       aopOp (result, ic, TRUE, FALSE);
5203       aopPut (AOP (result), "a", 0);
5204       _G.accInUse--;
5205
5206       size = AOP_SIZE (result) - 1;
5207
5208       while (size--)
5209         aopPut (AOP (result), zero, offset++);
5210       return;
5211     }
5212
5213   /* signed is a little bit more difficult */
5214
5215   /* now sign adjust for both left & right */
5216
5217   /* let's see what's needed: */
5218   /* apply negative sign during runtime */
5219   runtimeSign = FALSE;
5220   /* negative sign from literals */
5221   compiletimeSign = FALSE;
5222
5223   if (!lUnsigned)
5224     {
5225       if (AOP_TYPE(left) == AOP_LIT)
5226         {
5227           /* signed literal */
5228           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5229           if (val < 0)
5230             compiletimeSign = TRUE;
5231         }
5232       else
5233         /* signed but not literal */
5234         runtimeSign = TRUE;
5235     }
5236
5237   if (!rUnsigned)
5238     {
5239       if (AOP_TYPE(right) == AOP_LIT)
5240         {
5241           /* signed literal */
5242           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5243           if (val < 0)
5244             compiletimeSign ^= TRUE;
5245         }
5246       else
5247         /* signed but not literal */
5248         runtimeSign = TRUE;
5249     }
5250
5251   /* initialize F0, which stores the runtime sign */
5252   if (runtimeSign)
5253     {
5254       if (compiletimeSign)
5255         emitcode ("setb", "F0"); /* set sign flag */
5256       else
5257         emitcode ("clr", "F0"); /* reset sign flag */
5258     }
5259
5260   /* save the signs of the operands */
5261   if (AOP_TYPE(right) == AOP_LIT)
5262     {
5263       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5264
5265       if (!rUnsigned && val < 0)
5266         emitcode ("mov", "b,#0x%02x", -val);
5267       else
5268         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5269     }
5270   else /* ! literal */
5271     {
5272       if (rUnsigned)
5273         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5274       else
5275         {
5276           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5277           lbl = newiTempLabel (NULL);
5278           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5279           emitcode ("cpl", "F0"); /* complement sign flag */
5280           emitcode ("cpl", "a");  /* 2's complement */
5281           emitcode ("inc", "a");
5282           emitcode ("", "!tlabeldef", lbl->key + 100);
5283           emitcode ("mov", "b,a");
5284         }
5285     }
5286
5287   if (AOP_TYPE(left) == AOP_LIT)
5288     {
5289       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5290
5291       if (!lUnsigned && val < 0)
5292         emitcode ("mov", "a,#0x%02x", -val);
5293       else
5294         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5295     }
5296   else /* ! literal */
5297     {
5298       if (lUnsigned)
5299         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5300       else
5301         {
5302           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5303           lbl = newiTempLabel (NULL);
5304           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5305           emitcode ("cpl", "F0"); /* complement sign flag */
5306           emitcode ("cpl", "a");  /* 2's complement */
5307           emitcode ("inc", "a");
5308           emitcode ("", "!tlabeldef", lbl->key + 100);
5309         }
5310     }
5311
5312   /* now the division */
5313   emitcode ("nop", "; workaround for DS80C390 div bug.");
5314   emitcode ("div", "ab");
5315
5316   if (runtimeSign || compiletimeSign)
5317     {
5318       lbl = newiTempLabel (NULL);
5319       if (runtimeSign)
5320         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5321       emitcode ("cpl", "a"); /* lsb 2's complement */
5322       emitcode ("inc", "a");
5323       emitcode ("", "!tlabeldef", lbl->key + 100);
5324
5325       _G.accInUse++;     _G.bInUse++;
5326       aopOp (result, ic, TRUE, FALSE);
5327       size = AOP_SIZE (result) - 1;
5328
5329       if (size > 0)
5330         {
5331           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5332              then the result will be in b, a */
5333           emitcode ("mov", "b,a"); /* 1 */
5334           /* msb is 0x00 or 0xff depending on the sign */
5335           if (runtimeSign)
5336             {
5337               emitcode ("mov",  "c,F0");
5338               emitcode ("subb", "a,acc");
5339               emitcode ("xch",  "a,b"); /* 2 */
5340               while (size--)
5341                 aopPut (AOP (result), "b", offset++); /* write msb's */
5342             }
5343           else /* compiletimeSign */
5344             while (size--)
5345               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5346         }
5347       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5348     }
5349   else
5350     {
5351       _G.accInUse++;     _G.bInUse++;
5352       aopOp(result, ic, TRUE, FALSE);
5353       size = AOP_SIZE (result) - 1;
5354
5355       aopPut (AOP (result), "a", 0);
5356       while (size--)
5357         aopPut (AOP (result), zero, offset++);
5358     }
5359   _G.accInUse--;     _G.bInUse--;
5360
5361 }
5362
5363 /*-----------------------------------------------------------------*/
5364 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5365 /*-----------------------------------------------------------------*/
5366 static void genDivTwoByte (operand *left, operand *right,
5367                             operand *result, iCode *ic)
5368 {
5369         sym_link *retype = getSpec(operandType(right));
5370         sym_link *letype = getSpec(operandType(left));
5371         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5372         symbol *lbl;
5373
5374         /* save EA bit in F1 */
5375         lbl = newiTempLabel(NULL);
5376         emitcode ("setb","F1");
5377         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5378         emitcode ("clr","F1");
5379         emitcode("","!tlabeldef",lbl->key+100);
5380
5381         /* load up MA with left */
5382         if (!umult) {
5383                 emitcode("clr","F0");
5384                 lbl = newiTempLabel(NULL);
5385                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5386                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5387                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5388                 emitcode ("xch", "a,b");
5389                 emitcode ("cpl","a");
5390                 emitcode ("add", "a,#1");
5391                 emitcode ("xch", "a,b");
5392                 emitcode ("cpl", "a"); // msb
5393                 emitcode ("addc","a,#0");
5394                 emitcode ("setb","F0");
5395                 emitcode ("","!tlabeldef",lbl->key+100);
5396                 emitcode ("mov","ma,b");
5397                 emitcode ("mov","ma,a");
5398         } else {
5399                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5400                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5401         }
5402
5403         /* load up MB with right */
5404         if (!umult) {
5405                 if (AOP_TYPE(right) == AOP_LIT) {
5406                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5407                         if (val < 0) {
5408                                 lbl = newiTempLabel(NULL);
5409                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5410                                 emitcode("setb","F0");
5411                                 emitcode ("","!tlabeldef",lbl->key+100);
5412                                 val = -val;
5413                         }
5414                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5415                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5416                 } else {
5417                         lbl = newiTempLabel(NULL);
5418                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5419                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5420                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5421                         emitcode ("xch", "a,b");
5422                         emitcode ("cpl","a");
5423                         emitcode ("add", "a,#1");
5424                         emitcode ("xch", "a,b");
5425                         emitcode ("cpl", "a"); // msb
5426                         emitcode ("addc", "a,#0");
5427                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5428                         emitcode ("setb","F0");
5429                         emitcode ("","!tlabeldef",lbl->key+100);
5430                         emitcode ("mov","mb,b");
5431                         emitcode ("mov","mb,a");
5432                 }
5433         } else {
5434                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5435                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5436         }
5437
5438         /* wait for multiplication to finish */
5439         lbl = newiTempLabel(NULL);
5440         emitcode("","!tlabeldef", lbl->key+100);
5441         emitcode("mov","a,mcnt1");
5442         emitcode("anl","a,#!constbyte",0x80);
5443         emitcode("jnz","!tlabel",lbl->key+100);
5444
5445         freeAsmop (left, NULL, ic, TRUE);
5446         freeAsmop (right, NULL, ic,TRUE);
5447         aopOp(result, ic, TRUE, FALSE);
5448
5449         /* if unsigned then simple */
5450         if (umult) {
5451                 aopPut(AOP(result),"ma",1);
5452                 aopPut(AOP(result),"ma",0);
5453         } else {
5454                 emitcode("push","ma");
5455                 MOVA("ma");
5456                 /* negate result if needed */
5457                 lbl = newiTempLabel(NULL);
5458                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5459                 emitcode("cpl","a");
5460                 emitcode("add","a,#1");
5461                 emitcode("","!tlabeldef", lbl->key+100);
5462                 aopPut(AOP(result),"a",0);
5463                 emitcode("pop","acc");
5464                 lbl = newiTempLabel(NULL);
5465                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5466                 emitcode("cpl","a");
5467                 emitcode("addc","a,#0");
5468                 emitcode("","!tlabeldef", lbl->key+100);
5469                 aopPut(AOP(result),"a",1);
5470         }
5471         freeAsmop (result, NULL, ic, TRUE);
5472         /* restore EA bit in F1 */
5473         lbl = newiTempLabel(NULL);
5474         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5475         emitcode ("setb","EA");
5476         emitcode("","!tlabeldef",lbl->key+100);
5477         return ;
5478 }
5479
5480 /*-----------------------------------------------------------------*/
5481 /* genDiv - generates code for division                            */
5482 /*-----------------------------------------------------------------*/
5483 static void
5484 genDiv (iCode * ic)
5485 {
5486   operand *left = IC_LEFT (ic);
5487   operand *right = IC_RIGHT (ic);
5488   operand *result = IC_RESULT (ic);
5489
5490   D (emitcode (";", "genDiv "););
5491
5492   /* assign the amsops */
5493   AOP_OP_2 (ic);
5494
5495   /* special cases first */
5496   /* both are bits */
5497   if (AOP_TYPE (left) == AOP_CRY &&
5498       AOP_TYPE (right) == AOP_CRY)
5499     {
5500       genDivbits (left, right, result, ic);
5501       goto release;
5502     }
5503
5504   /* if both are of size == 1 */
5505   if (AOP_SIZE (left) == 1 &&
5506       AOP_SIZE (right) == 1)
5507     {
5508       genDivOneByte (left, right, result, ic);
5509       goto release;
5510     }
5511
5512   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5513           /* use the ds390 ARITHMETIC accel UNIT */
5514           genDivTwoByte (left, right, result, ic);
5515           return ;
5516   }
5517   /* should have been converted to function call */
5518   assert (0);
5519 release:
5520   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5521   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5522   freeAsmop (result, NULL, ic, TRUE);
5523 }
5524
5525 /*-----------------------------------------------------------------*/
5526 /* genModbits :- modulus of bits                                   */
5527 /*-----------------------------------------------------------------*/
5528 static void
5529 genModbits (operand * left,
5530             operand * right,
5531             operand * result,
5532             iCode   * ic)
5533 {
5534
5535   char *l;
5536
5537   /* the result must be bit */
5538   LOAD_AB_FOR_DIV (left, right, l);
5539   emitcode ("div", "ab");
5540   emitcode ("mov", "a,b");
5541   emitcode ("rrc", "a");
5542   aopOp(result, ic, TRUE, FALSE);
5543   aopPut (AOP (result), "c", 0);
5544 }
5545
5546 /*-----------------------------------------------------------------*/
5547 /* genModOneByte : 8 bit modulus                                   */
5548 /*-----------------------------------------------------------------*/
5549 static void
5550 genModOneByte (operand * left,
5551                operand * right,
5552                operand * result,
5553                iCode   * ic)
5554 {
5555   bool lUnsigned, rUnsigned;
5556   bool runtimeSign, compiletimeSign;
5557   char *l;
5558   symbol *lbl;
5559   int size, offset;
5560
5561   offset = 1;
5562   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5563   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5564
5565   /* signed or unsigned */
5566   if (lUnsigned && rUnsigned)
5567     {
5568       /* unsigned is easy */
5569       LOAD_AB_FOR_DIV (left, right, l);
5570       emitcode ("div", "ab");
5571       aopOp (result, ic, TRUE, FALSE);
5572       aopPut (AOP (result), "b", 0);
5573
5574       for (size = AOP_SIZE (result) - 1; size--;)
5575         aopPut (AOP (result), zero, offset++);
5576       return;
5577     }
5578
5579   /* signed is a little bit more difficult */
5580
5581   /* now sign adjust for both left & right */
5582
5583   /* modulus: sign of the right operand has no influence on the result! */
5584   if (AOP_TYPE(right) == AOP_LIT)
5585     {
5586       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5587
5588       if (!rUnsigned && val < 0)
5589         emitcode ("mov", "b,#0x%02x", -val);
5590       else
5591         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5592     }
5593   else /* ! literal */
5594     {
5595       if (rUnsigned)
5596         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5597       else
5598         {
5599           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5600           lbl = newiTempLabel (NULL);
5601           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5602           emitcode ("cpl", "a");  /* 2's complement */
5603           emitcode ("inc", "a");
5604           emitcode ("", "!tlabeldef", lbl->key + 100);
5605           emitcode ("mov", "b,a");
5606         }
5607     }
5608
5609   /* let's see what's needed: */
5610   /* apply negative sign during runtime */
5611   runtimeSign = FALSE;
5612   /* negative sign from literals */
5613   compiletimeSign = FALSE;
5614
5615   /* sign adjust left side */
5616   if (AOP_TYPE(left) == AOP_LIT)
5617     {
5618       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5619
5620       if (!lUnsigned && val < 0)
5621         {
5622           compiletimeSign = TRUE; /* set sign flag */
5623           emitcode ("mov", "a,#0x%02x", -val);
5624         }
5625       else
5626         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5627     }
5628   else /* ! literal */
5629     {
5630       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5631
5632       if (!lUnsigned)
5633         {
5634           runtimeSign = TRUE;
5635           emitcode ("clr", "F0"); /* clear sign flag */
5636
5637           lbl = newiTempLabel (NULL);
5638           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5639           emitcode ("setb", "F0"); /* set sign flag */
5640           emitcode ("cpl", "a");   /* 2's complement */
5641           emitcode ("inc", "a");
5642           emitcode ("", "!tlabeldef", lbl->key + 100);
5643         }
5644     }
5645
5646   /* now the modulus */
5647   emitcode ("nop", "; workaround for DS80C390 div bug.");
5648   emitcode ("div", "ab");
5649
5650   if (runtimeSign || compiletimeSign)
5651     {
5652       emitcode ("mov", "a,b");
5653       lbl = newiTempLabel (NULL);
5654       if (runtimeSign)
5655         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5656       emitcode ("cpl", "a"); /* lsb 2's complement */
5657       emitcode ("inc", "a");
5658       emitcode ("", "!tlabeldef", lbl->key + 100);
5659
5660       _G.accInUse++;     _G.bInUse++;
5661       aopOp (result, ic, TRUE, FALSE);
5662       size = AOP_SIZE (result) - 1;
5663
5664       if (size > 0)
5665         {
5666           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5667              then the result will be in b, a */
5668           emitcode ("mov", "b,a"); /* 1 */
5669           /* msb is 0x00 or 0xff depending on the sign */
5670           if (runtimeSign)
5671             {
5672               emitcode ("mov",  "c,F0");
5673               emitcode ("subb", "a,acc");
5674               emitcode ("xch",  "a,b"); /* 2 */
5675               while (size--)
5676                 aopPut (AOP (result), "b", offset++); /* write msb's */
5677             }
5678           else /* compiletimeSign */
5679             while (size--)
5680               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5681         }
5682       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5683     }
5684   else
5685     {
5686       _G.accInUse++;     _G.bInUse++;
5687       aopOp(result, ic, TRUE, FALSE);
5688       size = AOP_SIZE (result) - 1;
5689
5690       aopPut (AOP (result), "b", 0);
5691       while (size--)
5692         aopPut (AOP (result), zero, offset++);
5693     }
5694   _G.accInUse--;     _G.bInUse--;
5695
5696 }
5697
5698 /*-----------------------------------------------------------------*/
5699 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5700 /*-----------------------------------------------------------------*/
5701 static void genModTwoByte (operand *left, operand *right,
5702                             operand *result, iCode *ic)
5703 {
5704         sym_link *retype = getSpec(operandType(right));
5705         sym_link *letype = getSpec(operandType(left));
5706         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5707         symbol *lbl;
5708
5709         /* load up MA with left */
5710         /* save EA bit in F1 */
5711         lbl = newiTempLabel(NULL);
5712         emitcode ("setb","F1");
5713         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5714         emitcode ("clr","F1");
5715         emitcode("","!tlabeldef",lbl->key+100);
5716
5717         if (!umult) {
5718                 lbl = newiTempLabel(NULL);
5719                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5720                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5721                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5722                 emitcode ("xch", "a,b");
5723                 emitcode ("cpl","a");
5724                 emitcode ("add", "a,#1");
5725                 emitcode ("xch", "a,b");
5726                 emitcode ("cpl", "a"); // msb
5727                 emitcode ("addc","a,#0");
5728                 emitcode ("","!tlabeldef",lbl->key+100);
5729                 emitcode ("mov","ma,b");
5730                 emitcode ("mov","ma,a");
5731         } else {
5732                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5733                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5734         }
5735
5736         /* load up MB with right */
5737         if (!umult) {
5738                 if (AOP_TYPE(right) == AOP_LIT) {
5739                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5740                         if (val < 0) {
5741                                 val = -val;
5742                         }
5743                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5744                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5745                 } else {
5746                         lbl = newiTempLabel(NULL);
5747                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5748                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5749                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5750                         emitcode ("xch", "a,b");
5751                         emitcode ("cpl","a");
5752                         emitcode ("add", "a,#1");
5753                         emitcode ("xch", "a,b");
5754                         emitcode ("cpl", "a"); // msb
5755                         emitcode ("addc", "a,#0");
5756                         emitcode ("","!tlabeldef",lbl->key+100);
5757                         emitcode ("mov","mb,b");
5758                         emitcode ("mov","mb,a");
5759                 }
5760         } else {
5761                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5762                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5763         }
5764
5765         /* wait for multiplication to finish */
5766         lbl = newiTempLabel(NULL);
5767         emitcode("","!tlabeldef", lbl->key+100);
5768         emitcode("mov","a,mcnt1");
5769         emitcode("anl","a,#!constbyte",0x80);
5770         emitcode("jnz","!tlabel",lbl->key+100);
5771
5772         freeAsmop (left, NULL, ic, TRUE);
5773         freeAsmop (right, NULL, ic,TRUE);
5774         aopOp(result, ic, TRUE, FALSE);
5775
5776         aopPut(AOP(result),"mb",1);
5777         aopPut(AOP(result),"mb",0);
5778         freeAsmop (result, NULL, ic, TRUE);
5779
5780         /* restore EA bit in F1 */
5781         lbl = newiTempLabel(NULL);
5782         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5783         emitcode ("setb","EA");
5784         emitcode("","!tlabeldef",lbl->key+100);
5785         return ;
5786 }
5787
5788 /*-----------------------------------------------------------------*/
5789 /* genMod - generates code for division                            */
5790 /*-----------------------------------------------------------------*/
5791 static void
5792 genMod (iCode * ic)
5793 {
5794   operand *left = IC_LEFT (ic);
5795   operand *right = IC_RIGHT (ic);
5796   operand *result = IC_RESULT (ic);
5797
5798   D (emitcode (";", "genMod "); );
5799
5800   /* assign the amsops */
5801   AOP_OP_2 (ic);
5802
5803   /* special cases first */
5804   /* both are bits */
5805   if (AOP_TYPE (left) == AOP_CRY &&
5806       AOP_TYPE (right) == AOP_CRY)
5807     {
5808       genModbits (left, right, result, ic);
5809       goto release;
5810     }
5811
5812   /* if both are of size == 1 */
5813   if (AOP_SIZE (left) == 1 &&
5814       AOP_SIZE (right) == 1)
5815     {
5816       genModOneByte (left, right, result, ic);
5817       goto release;
5818     }
5819
5820   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5821           /* use the ds390 ARITHMETIC accel UNIT */
5822           genModTwoByte (left, right, result, ic);
5823           return ;
5824   }
5825
5826   /* should have been converted to function call */
5827   assert (0);
5828
5829 release:
5830   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5831   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5832   freeAsmop (result, NULL, ic, TRUE);
5833 }
5834
5835 /*-----------------------------------------------------------------*/
5836 /* genIfxJump :- will create a jump depending on the ifx           */
5837 /*-----------------------------------------------------------------*/
5838 static void
5839 genIfxJump (iCode * ic, char *jval)
5840 {
5841   symbol *jlbl;
5842   symbol *tlbl = newiTempLabel (NULL);
5843   char *inst;
5844
5845   D (emitcode (";", "genIfxJump"););
5846
5847   /* if true label then we jump if condition
5848      supplied is true */
5849   if (IC_TRUE (ic))
5850     {
5851       jlbl = IC_TRUE (ic);
5852       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5853                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5854     }
5855   else
5856     {
5857       /* false label is present */
5858       jlbl = IC_FALSE (ic);
5859       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5860                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5861     }
5862   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5863     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5864   else
5865     emitcode (inst, "!tlabel", tlbl->key + 100);
5866   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5867   emitcode ("", "!tlabeldef", tlbl->key + 100);
5868
5869   /* mark the icode as generated */
5870   ic->generated = 1;
5871 }
5872
5873 /*-----------------------------------------------------------------*/
5874 /* genCmp :- greater or less than comparison                       */
5875 /*-----------------------------------------------------------------*/
5876 static void
5877 genCmp (operand * left, operand * right,
5878         iCode * ic, iCode * ifx, int sign)
5879 {
5880   int size, offset = 0;
5881   unsigned long lit = 0L;
5882   operand *result;
5883
5884   D (emitcode (";", "genCmp"););
5885
5886   result = IC_RESULT (ic);
5887
5888   /* if left & right are bit variables */
5889   if (AOP_TYPE (left) == AOP_CRY &&
5890       AOP_TYPE (right) == AOP_CRY)
5891     {
5892       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5893       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5894     }
5895   else
5896     {
5897       /* subtract right from left if at the
5898          end the carry flag is set then we know that
5899          left is greater than right */
5900       size = max (AOP_SIZE (left), AOP_SIZE (right));
5901
5902       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5903       if ((size == 1) && !sign
5904           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5905         {
5906           symbol *lbl = newiTempLabel (NULL);
5907           emitcode ("cjne", "%s,%s,!tlabel",
5908                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5909                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5910                     lbl->key + 100);
5911           emitcode ("", "!tlabeldef", lbl->key + 100);
5912         }
5913       else
5914         {
5915           if (AOP_TYPE (right) == AOP_LIT)
5916             {
5917               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5918               /* optimize if(x < 0) or if(x >= 0) */
5919               if (lit == 0L)
5920                 {
5921                   if (!sign)
5922                     {
5923                       CLRC;
5924                     }
5925                   else
5926                     {
5927                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5928
5929                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5930                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5931
5932                       aopOp (result, ic, FALSE, FALSE);
5933
5934                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5935                         {
5936                           freeAsmop (result, NULL, ic, TRUE);
5937                           genIfxJump (ifx, "acc.7");
5938                           return;
5939                         }
5940                       else
5941                         {
5942                           emitcode ("rlc", "a");
5943                         }
5944                       goto release_freedLR;
5945                     }
5946                   goto release;
5947                 }
5948             }
5949           CLRC;
5950           while (size--)
5951             {
5952               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5953               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5954               // emitcode (";", "genCmp #2");
5955               if (sign && (size == 0))
5956                 {
5957                   // emitcode (";", "genCmp #3");
5958                   emitcode ("xrl", "a,#!constbyte",0x80);
5959                   if (AOP_TYPE (right) == AOP_LIT)
5960                     {
5961                       unsigned long lit = (unsigned long)
5962                       floatFromVal (AOP (right)->aopu.aop_lit);
5963                       // emitcode (";", "genCmp #3.1");
5964                       emitcode ("subb", "a,#!constbyte",
5965                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5966                     }
5967                   else
5968                     {
5969                       // emitcode (";", "genCmp #3.2");
5970                       saveAccWarn = 0;
5971                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5972                       saveAccWarn = DEFAULT_ACC_WARNING;
5973                       emitcode ("xrl", "b,#!constbyte",0x80);
5974                       emitcode ("subb", "a,b");
5975                     }
5976                 }
5977               else
5978                 {
5979                   const char *s;
5980
5981                   // emitcode (";", "genCmp #4");
5982                   saveAccWarn = 0;
5983                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5984                   saveAccWarn = DEFAULT_ACC_WARNING;
5985
5986                   emitcode ("subb", "a,%s", s);
5987                 }
5988             }
5989         }
5990     }
5991
5992 release:
5993 /* Don't need the left & right operands any more; do need the result. */
5994   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5995   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5996
5997   aopOp (result, ic, FALSE, FALSE);
5998
5999 release_freedLR:
6000
6001   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6002     {
6003       outBitC (result);
6004     }
6005   else
6006     {
6007       /* if the result is used in the next
6008          ifx conditional branch then generate
6009          code a little differently */
6010       if (ifx)
6011         {
6012           genIfxJump (ifx, "c");
6013         }
6014       else
6015         {
6016           outBitC (result);
6017         }
6018       /* leave the result in acc */
6019     }
6020   freeAsmop (result, NULL, ic, TRUE);
6021 }
6022
6023 /*-----------------------------------------------------------------*/
6024 /* genCmpGt :- greater than comparison                             */
6025 /*-----------------------------------------------------------------*/
6026 static void
6027 genCmpGt (iCode * ic, iCode * ifx)
6028 {
6029   operand *left, *right;
6030   sym_link *letype, *retype;
6031   int sign;
6032
6033   D (emitcode (";", "genCmpGt ");
6034     );
6035
6036   left = IC_LEFT (ic);
6037   right = IC_RIGHT (ic);
6038
6039   letype = getSpec (operandType (left));
6040   retype = getSpec (operandType (right));
6041   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6042
6043   /* assign the left & right amsops */
6044   AOP_OP_2 (ic);
6045
6046   genCmp (right, left, ic, ifx, sign);
6047 }
6048
6049 /*-----------------------------------------------------------------*/
6050 /* genCmpLt - less than comparisons                                */
6051 /*-----------------------------------------------------------------*/
6052 static void
6053 genCmpLt (iCode * ic, iCode * ifx)
6054 {
6055   operand *left, *right;
6056   sym_link *letype, *retype;
6057   int sign;
6058
6059   D (emitcode (";", "genCmpLt "););
6060
6061   left = IC_LEFT (ic);
6062   right = IC_RIGHT (ic);
6063
6064   letype = getSpec (operandType (left));
6065   retype = getSpec (operandType (right));
6066   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6067
6068   /* assign the left & right amsops */
6069   AOP_OP_2 (ic);
6070
6071   genCmp (left, right, ic, ifx, sign);
6072 }
6073
6074 /*-----------------------------------------------------------------*/
6075 /* gencjneshort - compare and jump if not equal                    */
6076 /*-----------------------------------------------------------------*/
6077 static void
6078 gencjneshort (operand * left, operand * right, symbol * lbl)
6079 {
6080   int size = max (AOP_SIZE (left), AOP_SIZE (right));
6081   int offset = 0;
6082   unsigned long lit = 0L;
6083
6084   D (emitcode (";", "gencjneshort");
6085     );
6086
6087   /* if the left side is a literal or
6088      if the right is in a pointer register and left
6089      is not */
6090   if ((AOP_TYPE (left) == AOP_LIT) ||
6091       (AOP_TYPE (left) == AOP_IMMD) ||
6092       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6093     {
6094       operand *t = right;
6095       right = left;
6096       left = t;
6097     }
6098
6099   if (AOP_TYPE (right) == AOP_LIT)
6100     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6101
6102   if (opIsGptr (left) || opIsGptr (right))
6103     {
6104       /* We are comparing a generic pointer to something.
6105        * Exclude the generic type byte from the comparison.
6106        */
6107       size--;
6108       D (emitcode (";", "cjneshort: generic ptr special case."););
6109     }
6110
6111
6112   /* if the right side is a literal then anything goes */
6113   if (AOP_TYPE (right) == AOP_LIT &&
6114       AOP_TYPE (left) != AOP_DIR)
6115     {
6116       while (size--)
6117         {
6118           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6119           emitcode ("cjne", "a,%s,!tlabel",
6120                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6121                     lbl->key + 100);
6122           offset++;
6123         }
6124     }
6125
6126   /* if the right side is in a register or in direct space or
6127      if the left is a pointer register & right is not */
6128   else if (AOP_TYPE (right) == AOP_REG ||
6129            AOP_TYPE (right) == AOP_DIR ||
6130            AOP_TYPE (right) == AOP_LIT ||
6131            AOP_TYPE (right) == AOP_IMMD ||
6132            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6133            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6134     {
6135       while (size--)
6136         {
6137           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6138           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6139               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6140             emitcode ("jnz", "!tlabel", lbl->key + 100);
6141           else
6142             emitcode ("cjne", "a,%s,!tlabel",
6143                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6144                       lbl->key + 100);
6145           offset++;
6146         }
6147     }
6148   else
6149     {
6150       /* right is a pointer reg need both a & b */
6151       while (size--)
6152         {
6153           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6154           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6155           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6156           offset++;
6157         }
6158     }
6159 }
6160
6161 /*-----------------------------------------------------------------*/
6162 /* gencjne - compare and jump if not equal                         */
6163 /*-----------------------------------------------------------------*/
6164 static void
6165 gencjne (operand * left, operand * right, symbol * lbl)
6166 {
6167   symbol *tlbl = newiTempLabel (NULL);
6168
6169   D (emitcode (";", "gencjne");
6170     );
6171
6172   gencjneshort (left, right, lbl);
6173
6174   emitcode ("mov", "a,%s", one);
6175   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6176   emitcode ("", "!tlabeldef", lbl->key + 100);
6177   emitcode ("clr", "a");
6178   emitcode ("", "!tlabeldef", tlbl->key + 100);
6179 }
6180
6181 /*-----------------------------------------------------------------*/
6182 /* genCmpEq - generates code for equal to                          */
6183 /*-----------------------------------------------------------------*/
6184 static void
6185 genCmpEq (iCode * ic, iCode * ifx)
6186 {
6187   operand *left, *right, *result;
6188
6189   D (emitcode (";", "genCmpEq ");
6190     );
6191
6192   AOP_OP_2 (ic);
6193   AOP_SET_LOCALS (ic);
6194
6195   /* if literal, literal on the right or
6196      if the right is in a pointer register and left
6197      is not */
6198   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6199       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6200     {
6201       operand *t = IC_RIGHT (ic);
6202       IC_RIGHT (ic) = IC_LEFT (ic);
6203       IC_LEFT (ic) = t;
6204     }
6205
6206   if (ifx &&                    /* !AOP_SIZE(result) */
6207       OP_SYMBOL (result) &&
6208       OP_SYMBOL (result)->regType == REG_CND)
6209     {
6210       symbol *tlbl;
6211       /* if they are both bit variables */
6212       if (AOP_TYPE (left) == AOP_CRY &&
6213           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6214         {
6215           if (AOP_TYPE (right) == AOP_LIT)
6216             {
6217               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6218               if (lit == 0L)
6219                 {
6220                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6221                   emitcode ("cpl", "c");
6222                 }
6223               else if (lit == 1L)
6224                 {
6225                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6226                 }
6227               else
6228                 {
6229                   emitcode ("clr", "c");
6230                 }
6231               /* AOP_TYPE(right) == AOP_CRY */
6232             }
6233           else
6234             {
6235               symbol *lbl = newiTempLabel (NULL);
6236               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6237               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6238               emitcode ("cpl", "c");
6239               emitcode ("", "!tlabeldef", (lbl->key + 100));
6240             }
6241           /* if true label then we jump if condition
6242              supplied is true */
6243           tlbl = newiTempLabel (NULL);
6244           if (IC_TRUE (ifx))
6245             {
6246               emitcode ("jnc", "!tlabel", tlbl->key + 100);
6247               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6248             }
6249           else
6250             {
6251               emitcode ("jc", "!tlabel", tlbl->key + 100);
6252               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6253             }
6254           emitcode ("", "!tlabeldef", tlbl->key + 100);
6255         }
6256       else
6257         {
6258           tlbl = newiTempLabel (NULL);
6259           gencjneshort (left, right, tlbl);
6260           if (IC_TRUE (ifx))
6261             {
6262               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6263               emitcode ("", "!tlabeldef", tlbl->key + 100);
6264             }
6265           else
6266             {
6267               symbol *lbl = newiTempLabel (NULL);
6268               emitcode ("sjmp", "!tlabel", lbl->key + 100);
6269               emitcode ("", "!tlabeldef", tlbl->key + 100);
6270               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6271               emitcode ("", "!tlabeldef", lbl->key + 100);
6272             }
6273         }
6274       /* mark the icode as generated */
6275       ifx->generated = 1;
6276
6277       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6278       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6279       return;
6280     }
6281
6282   /* if they are both bit variables */
6283   if (AOP_TYPE (left) == AOP_CRY &&
6284       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6285     {
6286       if (AOP_TYPE (right) == AOP_LIT)
6287         {
6288           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6289           if (lit == 0L)
6290             {
6291               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6292               emitcode ("cpl", "c");
6293             }
6294           else if (lit == 1L)
6295             {
6296               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6297             }
6298           else
6299             {
6300               emitcode ("clr", "c");
6301             }
6302           /* AOP_TYPE(right) == AOP_CRY */
6303         }
6304       else
6305         {
6306           symbol *lbl = newiTempLabel (NULL);
6307           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6308           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6309           emitcode ("cpl", "c");
6310           emitcode ("", "!tlabeldef", (lbl->key + 100));
6311         }
6312
6313       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6314       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6315
6316       aopOp (result, ic, TRUE, FALSE);
6317
6318       /* c = 1 if egal */
6319       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6320         {
6321           outBitC (result);
6322           goto release;
6323         }
6324       if (ifx)
6325         {
6326           genIfxJump (ifx, "c");
6327           goto release;
6328         }
6329       /* if the result is used in an arithmetic operation
6330          then put the result in place */
6331       outBitC (result);
6332     }
6333   else
6334     {
6335       gencjne (left, right, newiTempLabel (NULL));
6336
6337       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6338       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6339
6340       aopOp (result, ic, TRUE, FALSE);
6341
6342       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6343         {
6344           aopPut (AOP (result), "a", 0);
6345           goto release;
6346         }
6347       if (ifx)
6348         {
6349           genIfxJump (ifx, "a");
6350           goto release;
6351         }
6352       /* if the result is used in an arithmetic operation
6353          then put the result in place */
6354       if (AOP_TYPE (result) != AOP_CRY)
6355         outAcc (result);
6356       /* leave the result in acc */
6357     }
6358
6359 release:
6360   freeAsmop (result, NULL, ic, TRUE);
6361 }
6362
6363 /*-----------------------------------------------------------------*/
6364 /* ifxForOp - returns the icode containing the ifx for operand     */
6365 /*-----------------------------------------------------------------*/
6366 static iCode *
6367 ifxForOp (operand * op, iCode * ic)
6368 {
6369   /* if true symbol then needs to be assigned */
6370   if (IS_TRUE_SYMOP (op))
6371     return NULL;
6372
6373   /* if this has register type condition and
6374      the next instruction is ifx with the same operand
6375      and live to of the operand is upto the ifx only then */
6376   if (ic->next &&
6377       ic->next->op == IFX &&
6378       IC_COND (ic->next)->key == op->key &&
6379       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6380     return ic->next;
6381
6382   return NULL;
6383 }
6384 /*-----------------------------------------------------------------*/
6385 /* hasInc - operand is incremented before any other use            */
6386 /*-----------------------------------------------------------------*/
6387 static iCode *
6388 hasInc (operand *op, iCode *ic, int osize)
6389 {
6390   sym_link *type = operandType(op);
6391   sym_link *retype = getSpec (type);
6392   iCode *lic = ic->next;
6393   int isize ;
6394
6395   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6396   if (!IS_SYMOP(op)) return NULL;
6397
6398   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6399   if (IS_AGGREGATE(type->next)) return NULL;
6400   if (osize != (isize = getSize(type->next))) return NULL;
6401
6402   while (lic) {
6403       /* if operand of the form op = op + <sizeof *op> */
6404       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6405           isOperandEqual(IC_RESULT(lic),op) &&
6406           isOperandLiteral(IC_RIGHT(lic)) &&
6407           operandLitValue(IC_RIGHT(lic)) == isize) {
6408           return lic;
6409       }
6410       /* if the operand used or deffed */
6411       if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6412           return NULL;
6413       }
6414       /* if GOTO or IFX */
6415       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6416       lic = lic->next;
6417   }
6418   return NULL;
6419 }
6420
6421 /*-----------------------------------------------------------------*/
6422 /* genAndOp - for && operation                                     */
6423 /*-----------------------------------------------------------------*/
6424 static void
6425 genAndOp (iCode * ic)
6426 {
6427   operand *left, *right, *result;
6428   symbol *tlbl;
6429
6430   D (emitcode (";", "genAndOp "););
6431
6432   /* note here that && operations that are in an
6433      if statement are taken away by backPatchLabels
6434      only those used in arthmetic operations remain */
6435   AOP_OP_2 (ic);
6436   AOP_SET_LOCALS (ic);
6437
6438   /* if both are bit variables */
6439   if (AOP_TYPE (left) == AOP_CRY &&
6440       AOP_TYPE (right) == AOP_CRY)
6441     {
6442       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6443       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6444       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6445       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6446
6447       aopOp (result,ic,FALSE, FALSE);
6448       outBitC (result);
6449     }
6450   else
6451     {
6452       tlbl = newiTempLabel (NULL);
6453       toBoolean (left);
6454       emitcode ("jz", "!tlabel", tlbl->key + 100);
6455       toBoolean (right);
6456       emitcode ("", "!tlabeldef", tlbl->key + 100);
6457       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6458       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6459
6460       aopOp (result,ic,FALSE, FALSE);
6461       outBitAcc (result);
6462     }
6463     freeAsmop (result, NULL, ic, TRUE);
6464 }
6465
6466
6467 /*-----------------------------------------------------------------*/
6468 /* genOrOp - for || operation                                      */
6469 /*-----------------------------------------------------------------*/
6470 static void
6471 genOrOp (iCode * ic)
6472 {
6473   operand *left, *right, *result;
6474   symbol *tlbl;
6475
6476   D (emitcode (";", "genOrOp "););
6477
6478   /* note here that || operations that are in an
6479      if statement are taken away by backPatchLabels
6480      only those used in arthmetic operations remain */
6481   AOP_OP_2 (ic);
6482   AOP_SET_LOCALS (ic);
6483
6484   /* if both are bit variables */
6485   if (AOP_TYPE (left) == AOP_CRY &&
6486       AOP_TYPE (right) == AOP_CRY)
6487     {
6488       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6489       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6490       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6491       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6492
6493       aopOp (result,ic,FALSE, FALSE);
6494
6495       outBitC (result);
6496     }
6497   else
6498     {
6499       tlbl = newiTempLabel (NULL);
6500       toBoolean (left);
6501       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6502       toBoolean (right);
6503       emitcode ("", "!tlabeldef", tlbl->key + 100);
6504       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6505       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6506
6507       aopOp (result,ic,FALSE, FALSE);
6508
6509       outBitAcc (result);
6510     }
6511
6512   freeAsmop (result, NULL, ic, TRUE);
6513 }
6514
6515 /*-----------------------------------------------------------------*/
6516 /* isLiteralBit - test if lit == 2^n                               */
6517 /*-----------------------------------------------------------------*/
6518 static int
6519 isLiteralBit (unsigned long lit)
6520 {
6521   unsigned long pw[32] =
6522   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6523    0x100L, 0x200L, 0x400L, 0x800L,
6524    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6525    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6526    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6527    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6528    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6529   int idx;
6530
6531   for (idx = 0; idx < 32; idx++)
6532     if (lit == pw[idx])
6533       return idx + 1;
6534   return 0;
6535 }
6536
6537 /*-----------------------------------------------------------------*/
6538 /* continueIfTrue -                                                */
6539 /*-----------------------------------------------------------------*/
6540 static void
6541 continueIfTrue (iCode * ic)
6542 {
6543   if (IC_TRUE (ic))
6544     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6545   ic->generated = 1;
6546 }
6547
6548 /*-----------------------------------------------------------------*/
6549 /* jmpIfTrue -                                                     */
6550 /*-----------------------------------------------------------------*/
6551 static void
6552 jumpIfTrue (iCode * ic)
6553 {
6554   if (!IC_TRUE (ic))
6555     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6556   ic->generated = 1;
6557 }
6558
6559 /*-----------------------------------------------------------------*/
6560 /* jmpTrueOrFalse -                                                */
6561 /*-----------------------------------------------------------------*/
6562 static void
6563 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6564 {
6565   // ugly but optimized by peephole
6566   if (IC_TRUE (ic))
6567     {
6568       symbol *nlbl = newiTempLabel (NULL);
6569       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6570       emitcode ("", "!tlabeldef", tlbl->key + 100);
6571       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6572       emitcode ("", "!tlabeldef", nlbl->key + 100);
6573     }
6574   else
6575     {
6576       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6577       emitcode ("", "!tlabeldef", tlbl->key + 100);
6578     }
6579   ic->generated = 1;
6580 }
6581
6582 // Generate code to perform a bit-wise logic operation
6583 // on two operands in far space (assumed to already have been
6584 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6585 // in far space. This requires pushing the result on the stack
6586 // then popping it into the result.
6587 static void
6588 genFarFarLogicOp(iCode *ic, char *logicOp)
6589 {
6590       int size, resultSize, compSize;
6591       int offset = 0;
6592
6593       TR_AP("#5");
6594       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6595       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6596                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6597
6598       _startLazyDPSEvaluation();
6599       for (size = compSize; (size--); offset++)
6600       {
6601           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6602           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6603           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6604
6605           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6606           emitcode ("push", "acc");
6607       }
6608       _endLazyDPSEvaluation();
6609
6610       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6611       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6612       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6613
6614       resultSize = AOP_SIZE(IC_RESULT(ic));
6615
6616       ADJUST_PUSHED_RESULT(compSize, resultSize);
6617
6618       _startLazyDPSEvaluation();
6619       while (compSize--)
6620       {
6621           emitcode ("pop", "acc");
6622           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6623       }
6624       _endLazyDPSEvaluation();
6625       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6626 }
6627
6628
6629 /*-----------------------------------------------------------------*/
6630 /* genAnd  - code for and                                          */
6631 /*-----------------------------------------------------------------*/
6632 static void
6633 genAnd (iCode * ic, iCode * ifx)
6634 {
6635   operand *left, *right, *result;
6636   int size, offset = 0;
6637   unsigned long lit = 0L;
6638   int bytelit;
6639   char buff[10];
6640   bool pushResult;
6641
6642   D (emitcode (";", "genAnd "););
6643
6644   AOP_OP_3_NOFATAL (ic, pushResult);
6645   AOP_SET_LOCALS (ic);
6646
6647   if (pushResult)
6648   {
6649       genFarFarLogicOp(ic, "anl");
6650       return;
6651   }
6652
6653 #ifdef DEBUG_TYPE
6654   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6655             AOP_TYPE (result),
6656             AOP_TYPE (left), AOP_TYPE (right));
6657   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6658             AOP_SIZE (result),
6659             AOP_SIZE (left), AOP_SIZE (right));
6660 #endif
6661
6662   /* if left is a literal & right is not then exchange them */
6663   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6664 #ifdef LOGIC_OPS_BROKEN
6665     ||  AOP_NEEDSACC (left)
6666 #endif
6667     )
6668     {
6669       operand *tmp = right;
6670       right = left;
6671       left = tmp;
6672     }
6673
6674   /* if result = right then exchange left and right */
6675   if (sameRegs (AOP (result), AOP (right)))
6676     {
6677       operand *tmp = right;
6678       right = left;
6679       left = tmp;
6680     }
6681
6682   /* if right is bit then exchange them */
6683   if (AOP_TYPE (right) == AOP_CRY &&
6684       AOP_TYPE (left) != AOP_CRY)
6685     {
6686       operand *tmp = right;
6687       right = left;
6688       left = tmp;
6689     }
6690   if (AOP_TYPE (right) == AOP_LIT)
6691     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6692
6693   size = AOP_SIZE (result);
6694
6695   // if(bit & yy)
6696   // result = bit & yy;
6697   if (AOP_TYPE (left) == AOP_CRY)
6698     {
6699       // c = bit & literal;
6700       if (AOP_TYPE (right) == AOP_LIT)
6701         {
6702           if (lit & 1)
6703             {
6704               if (size && sameRegs (AOP (result), AOP (left)))
6705                 // no change
6706                 goto release;
6707               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6708             }
6709           else
6710             {
6711               // bit(result) = 0;
6712               if (size && (AOP_TYPE (result) == AOP_CRY))
6713                 {
6714                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6715                   goto release;
6716                 }
6717               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6718                 {
6719                   jumpIfTrue (ifx);
6720                   goto release;
6721                 }
6722               emitcode ("clr", "c");
6723             }
6724         }
6725       else
6726         {
6727           if (AOP_TYPE (right) == AOP_CRY)
6728             {
6729               // c = bit & bit;
6730               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6731               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6732             }
6733           else
6734             {
6735               // c = bit & val;
6736               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6737               // c = lsb
6738               emitcode ("rrc", "a");
6739               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6740             }
6741         }
6742       // bit = c
6743       // val = c
6744       if (size)
6745         outBitC (result);
6746       // if(bit & ...)
6747       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6748         genIfxJump (ifx, "c");
6749       goto release;
6750     }
6751
6752   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6753   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6754   if ((AOP_TYPE (right) == AOP_LIT) &&
6755       (AOP_TYPE (result) == AOP_CRY) &&
6756       (AOP_TYPE (left) != AOP_CRY))
6757     {
6758       int posbit = isLiteralBit (lit);
6759       /* left &  2^n */
6760       if (posbit)
6761         {
6762           posbit--;
6763           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6764           // bit = left & 2^n
6765           if (size)
6766             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6767           // if(left &  2^n)
6768           else
6769             {
6770               if (ifx)
6771                 {
6772                   SNPRINTF (buff, sizeof(buff),
6773                             "acc.%d", posbit & 0x07);
6774                   genIfxJump (ifx, buff);
6775                 }
6776               else
6777                   {
6778                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6779                   }
6780               goto release;
6781             }
6782         }
6783       else
6784         {
6785           symbol *tlbl = newiTempLabel (NULL);
6786           int sizel = AOP_SIZE (left);
6787           if (size)
6788             emitcode ("setb", "c");
6789           while (sizel--)
6790             {
6791               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6792                 {
6793                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6794                   // byte ==  2^n ?
6795                   if ((posbit = isLiteralBit (bytelit)) != 0)
6796                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6797                   else
6798                     {
6799                       if (bytelit != 0x0FFL)
6800                         emitcode ("anl", "a,%s",
6801                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6802                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6803                     }
6804                 }
6805               offset++;
6806             }
6807           // bit = left & literal
6808           if (size)
6809             {
6810               emitcode ("clr", "c");
6811               emitcode ("", "!tlabeldef", tlbl->key + 100);
6812             }
6813           // if(left & literal)
6814           else
6815             {
6816               if (ifx)
6817                 jmpTrueOrFalse (ifx, tlbl);
6818               else
6819                 emitcode ("", "!tlabeldef", tlbl->key + 100);
6820               goto release;
6821             }
6822         }
6823       outBitC (result);
6824       goto release;
6825     }
6826
6827   /* if left is same as result */
6828   if (sameRegs (AOP (result), AOP (left)))
6829     {
6830       for (; size--; offset++)
6831         {
6832           if (AOP_TYPE (right) == AOP_LIT)
6833             {
6834               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6835               if (bytelit == 0x0FF)
6836                 {
6837                   /* dummy read of volatile operand */
6838                   if (isOperandVolatile (left, FALSE))
6839                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6840                   else
6841                     continue;
6842                 }
6843               else if (bytelit == 0)
6844                 {
6845                   aopPut (AOP (result), zero, offset);
6846                 }
6847               else if (IS_AOP_PREG (result))
6848                 {
6849                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6850                   emitcode ("anl", "a,%s",
6851                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6852                   aopPut (AOP (result), "a", offset);
6853                 }
6854               else
6855                 emitcode ("anl", "%s,%s",
6856                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6857                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6858             }
6859           else
6860             {
6861               if (AOP_TYPE (left) == AOP_ACC)
6862                 emitcode ("anl", "a,%s",
6863                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6864               else
6865                 {
6866                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6867                   if (IS_AOP_PREG (result))
6868                     {
6869                       emitcode ("anl", "a,%s",
6870                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6871                       aopPut (AOP (result), "a", offset);
6872                     }
6873                   else
6874                     emitcode ("anl", "%s,a",
6875                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6876                 }
6877             }
6878         }
6879     }
6880   else
6881     {
6882       // left & result in different registers
6883       if (AOP_TYPE (result) == AOP_CRY)
6884         {
6885           // result = bit
6886           // if(size), result in bit
6887           // if(!size && ifx), conditional oper: if(left & right)
6888           symbol *tlbl = newiTempLabel (NULL);
6889           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6890           if (size)
6891             emitcode ("setb", "c");
6892           while (sizer--)
6893             {
6894               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6895                 emitcode ("anl", "a,%s",
6896                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6897               } else {
6898                 if (AOP_TYPE(left)==AOP_ACC) {
6899                   emitcode("mov", "b,a");
6900                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6901                   emitcode("anl", "a,b");
6902                 }else {
6903                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6904                   emitcode ("anl", "a,%s",
6905                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6906                 }
6907               }
6908               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6909               offset++;
6910             }
6911           if (size)
6912             {
6913               CLRC;
6914               emitcode ("", "!tlabeldef", tlbl->key + 100);
6915               outBitC (result);
6916             }
6917           else if (ifx)
6918             jmpTrueOrFalse (ifx, tlbl);
6919           else
6920             emitcode ("", "!tlabeldef", tlbl->key + 100);
6921         }
6922       else
6923         {
6924           for (; (size--); offset++)
6925             {
6926               // normal case
6927               // result = left & right
6928               if (AOP_TYPE (right) == AOP_LIT)
6929                 {
6930                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6931                   if (bytelit == 0x0FF)
6932                     {
6933                       aopPut (AOP (result),
6934                               aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6935                               offset);
6936                       continue;
6937                     }
6938                   else if (bytelit == 0)
6939                     {
6940                       /* dummy read of volatile operand */
6941                       if (isOperandVolatile (left, FALSE))
6942                         MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6943                       aopPut (AOP (result), zero, offset);
6944                       continue;
6945                     }
6946                   D (emitcode (";", "better literal AND."););
6947                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6948                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6949                                                     FALSE, FALSE, DP2_RESULT_REG));
6950
6951                 }
6952               else
6953                 {
6954                   // faster than result <- left, anl result,right
6955                   // and better if result is SFR
6956                   if (AOP_TYPE (left) == AOP_ACC)
6957                     {
6958                       emitcode ("anl", "a,%s",
6959                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6960                     }
6961                   else
6962                     {
6963                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6964                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6965                       {
6966                           emitcode("mov", "b,a");
6967                           rOp = "b";
6968                       }
6969
6970                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6971                       emitcode ("anl", "a,%s", rOp);
6972                     }
6973                 }
6974               aopPut (AOP (result), "a", offset);
6975             }
6976         }
6977     }
6978
6979 release:
6980   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6981   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6982   freeAsmop (result, NULL, ic, TRUE);
6983 }
6984
6985
6986 /*-----------------------------------------------------------------*/
6987 /* genOr  - code for or                                            */
6988 /*-----------------------------------------------------------------*/
6989 static void
6990 genOr (iCode * ic, iCode * ifx)
6991 {
6992   operand *left, *right, *result;
6993   int size, offset = 0;
6994   unsigned long lit = 0L;
6995   int bytelit = 0;
6996   bool     pushResult;
6997
6998   D (emitcode (";", "genOr "););
6999
7000   AOP_OP_3_NOFATAL (ic, pushResult);
7001   AOP_SET_LOCALS (ic);
7002
7003   if (pushResult)
7004   {
7005       genFarFarLogicOp(ic, "orl");
7006       return;
7007   }
7008
7009
7010 #ifdef DEBUG_TYPE
7011   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7012             AOP_TYPE (result),
7013             AOP_TYPE (left), AOP_TYPE (right));
7014   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7015             AOP_SIZE (result),
7016             AOP_SIZE (left), AOP_SIZE (right));
7017 #endif
7018
7019   /* if left is a literal & right is not then exchange them */
7020   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7021 #ifdef LOGIC_OPS_BROKEN
7022    || AOP_NEEDSACC (left) // I think this is a net loss now.
7023 #endif
7024       )
7025     {
7026       operand *tmp = right;
7027       right = left;
7028       left = tmp;
7029     }
7030
7031   /* if result = right then exchange them */
7032   if (sameRegs (AOP (result), AOP (right)))
7033     {
7034       operand *tmp = right;
7035       right = left;
7036       left = tmp;
7037     }
7038
7039   /* if right is bit then exchange them */
7040   if (AOP_TYPE (right) == AOP_CRY &&
7041       AOP_TYPE (left) != AOP_CRY)
7042     {
7043       operand *tmp = right;
7044       right = left;
7045       left = tmp;
7046     }
7047   if (AOP_TYPE (right) == AOP_LIT)
7048     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7049
7050   size = AOP_SIZE (result);
7051
7052   // if(bit | yy)
7053   // xx = bit | yy;
7054   if (AOP_TYPE (left) == AOP_CRY)
7055     {
7056       if (AOP_TYPE (right) == AOP_LIT)
7057         {
7058           // c = bit & literal;
7059           if (lit)
7060             {
7061               // lit != 0 => result = 1
7062               if (AOP_TYPE (result) == AOP_CRY)
7063                 {
7064                   if (size)
7065                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7066                   else if (ifx)
7067                     continueIfTrue (ifx);
7068                   goto release;
7069                 }
7070               emitcode ("setb", "c");
7071             }
7072           else
7073             {
7074               // lit == 0 => result = left
7075               if (size && sameRegs (AOP (result), AOP (left)))
7076                 goto release;
7077               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7078             }
7079         }
7080       else
7081         {
7082           if (AOP_TYPE (right) == AOP_CRY)
7083             {
7084               // c = bit | bit;
7085               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7086               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7087             }
7088           else
7089             {
7090               // c = bit | val;
7091               symbol *tlbl = newiTempLabel (NULL);
7092               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7093                 emitcode ("setb", "c");
7094               emitcode ("jb", "%s,!tlabel",
7095                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
7096               toBoolean (right);
7097               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7098               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7099                 {
7100                   jmpTrueOrFalse (ifx, tlbl);
7101                   goto release;
7102                 }
7103               else
7104                 {
7105                   CLRC;
7106                   emitcode ("", "!tlabeldef", tlbl->key + 100);
7107                 }
7108             }
7109         }
7110       // bit = c
7111       // val = c
7112       if (size)
7113         outBitC (result);
7114       // if(bit | ...)
7115       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7116            genIfxJump (ifx, "c");
7117       goto release;
7118     }
7119
7120   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7121   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7122   if ((AOP_TYPE (right) == AOP_LIT) &&
7123       (AOP_TYPE (result) == AOP_CRY) &&
7124       (AOP_TYPE (left) != AOP_CRY))
7125     {
7126       if (lit)
7127         {
7128           // result = 1
7129           if (size)
7130             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7131           else
7132             continueIfTrue (ifx);
7133           goto release;
7134         }
7135       else
7136         {
7137           // lit = 0, result = boolean(left)
7138           if (size)
7139             emitcode ("setb", "c");
7140           toBoolean (right);
7141           if (size)
7142             {
7143               symbol *tlbl = newiTempLabel (NULL);
7144               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7145               CLRC;
7146               emitcode ("", "!tlabeldef", tlbl->key + 100);
7147             }
7148           else
7149             {
7150               genIfxJump (ifx, "a");
7151               goto release;
7152             }
7153         }
7154       outBitC (result);
7155       goto release;
7156     }
7157
7158   /* if left is same as result */
7159   if (sameRegs (AOP (result), AOP (left)))
7160     {
7161       for (; size--; offset++)
7162         {
7163           if (AOP_TYPE (right) == AOP_LIT)
7164             {
7165               bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7166               if (bytelit == 0x00L)
7167                 {
7168                   /* dummy read of volatile operand */
7169                   if (isOperandVolatile (left, FALSE))
7170                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7171                   else
7172                     continue;
7173                 }
7174               else if (bytelit == 0x0FF)
7175                 {
7176                   aopPut (AOP (result), "#0xFF", offset);
7177                 }
7178               else if (IS_AOP_PREG (left))
7179                 {
7180                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7181                   emitcode ("orl", "a,%s",
7182                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7183                   aopPut (AOP (result), "a", offset);
7184                 }
7185               else
7186                 {
7187                   emitcode ("orl", "%s,%s",
7188                             aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7189                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7190                 }
7191             }
7192           else
7193             {
7194               if (AOP_TYPE (left) == AOP_ACC)
7195                 {
7196                   emitcode ("orl", "a,%s",
7197                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7198                 }
7199               else
7200                 {
7201                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7202                   if (IS_AOP_PREG (left))
7203                     {
7204                       emitcode ("orl", "a,%s",
7205                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7206                       aopPut (AOP (result), "a", offset);
7207                     }
7208                   else
7209                     {
7210                       emitcode ("orl", "%s,a",
7211                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7212                     }
7213                 }
7214             }
7215         }
7216     }
7217   else
7218     {
7219       // left & result in different registers
7220       if (AOP_TYPE (result) == AOP_CRY)
7221         {
7222           // result = bit
7223           // if(size), result in bit
7224           // if(!size && ifx), conditional oper: if(left | right)
7225           symbol *tlbl = newiTempLabel (NULL);
7226           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7227           if (size)
7228             emitcode ("setb", "c");
7229           while (sizer--)
7230             {
7231               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7232                 emitcode ("orl", "a,%s",
7233                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7234               } else {
7235                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7236                 emitcode ("orl", "a,%s",
7237                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7238               }
7239               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7240               offset++;
7241             }
7242           if (size)
7243             {
7244               CLRC;
7245               emitcode ("", "!tlabeldef", tlbl->key + 100);
7246               outBitC (result);
7247             }
7248           else if (ifx)
7249             jmpTrueOrFalse (ifx, tlbl);
7250           else
7251             emitcode ("", "!tlabeldef", tlbl->key + 100);
7252         }
7253       else
7254         {
7255             _startLazyDPSEvaluation();
7256           for (; (size--); offset++)
7257             {
7258               // normal case
7259               // result = left & right
7260               if (AOP_TYPE (right) == AOP_LIT)
7261                 {
7262                   bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7263                   if (bytelit == 0x00L)
7264                     {
7265                       aopPut (AOP (result),
7266                               aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7267                               offset);
7268                       continue;
7269                     }
7270                   else if (bytelit == 0x0FF)
7271                     {
7272                       /* dummy read of volatile operand */
7273                       if (isOperandVolatile (left, FALSE))
7274                         MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7275                       aopPut (AOP (result), "#0xFF", offset);
7276                       continue;
7277                     }
7278                   D (emitcode (";", "better literal OR."););
7279                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7280                   emitcode ("orl", "a, %s",
7281                             aopGet (AOP (right), offset,
7282                                     FALSE, FALSE, DP2_RESULT_REG));
7283
7284                 }
7285               else
7286                 {
7287                   // faster than result <- left, anl result,right
7288                   // and better if result is SFR
7289                   if (AOP_TYPE (left) == AOP_ACC)
7290                     {
7291                       emitcode ("orl", "a,%s",
7292                                 aopGet (AOP (right), offset,
7293                                         FALSE, FALSE, DP2_RESULT_REG));
7294                     }
7295                   else
7296                     {
7297                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7298
7299                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7300                       {
7301                           emitcode("mov", "b,a");
7302                           rOp = "b";
7303                       }
7304
7305                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7306                       emitcode ("orl", "a,%s", rOp);
7307                     }
7308                 }
7309               aopPut (AOP (result), "a", offset);
7310             }
7311             _endLazyDPSEvaluation();
7312         }
7313     }
7314
7315 release:
7316   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7317   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7318   freeAsmop (result, NULL, ic, TRUE);
7319 }
7320
7321 /*-----------------------------------------------------------------*/
7322 /* genXor - code for xclusive or                                   */
7323 /*-----------------------------------------------------------------*/
7324 static void
7325 genXor (iCode * ic, iCode * ifx)
7326 {
7327   operand *left, *right, *result;
7328   int size, offset = 0;
7329   unsigned long lit = 0L;
7330   int bytelit = 0;
7331   bool pushResult;
7332
7333   D (emitcode (";", "genXor "););
7334
7335   AOP_OP_3_NOFATAL (ic, pushResult);
7336   AOP_SET_LOCALS (ic);
7337
7338   if (pushResult)
7339   {
7340       genFarFarLogicOp(ic, "xrl");
7341       return;
7342   }
7343
7344 #ifdef DEBUG_TYPE
7345   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7346             AOP_TYPE (result),
7347             AOP_TYPE (left), AOP_TYPE (right));
7348   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7349             AOP_SIZE (result),
7350             AOP_SIZE (left), AOP_SIZE (right));
7351 #endif
7352
7353   /* if left is a literal & right is not ||
7354      if left needs acc & right does not */
7355   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7356 #ifdef LOGIC_OPS_BROKEN
7357       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7358 #endif
7359      )
7360     {
7361       operand *tmp = right;
7362       right = left;
7363       left = tmp;
7364     }
7365
7366   /* if result = right then exchange them */
7367   if (sameRegs (AOP (result), AOP (right)))
7368     {
7369       operand *tmp = right;
7370       right = left;
7371       left = tmp;
7372     }
7373
7374   /* if right is bit then exchange them */
7375   if (AOP_TYPE (right) == AOP_CRY &&
7376       AOP_TYPE (left) != AOP_CRY)
7377     {
7378       operand *tmp = right;
7379       right = left;
7380       left = tmp;
7381     }
7382   if (AOP_TYPE (right) == AOP_LIT)
7383     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7384
7385   size = AOP_SIZE (result);
7386
7387   // if(bit ^ yy)
7388   // xx = bit ^ yy;
7389   if (AOP_TYPE (left) == AOP_CRY)
7390     {
7391       if (AOP_TYPE (right) == AOP_LIT)
7392         {
7393           // c = bit & literal;
7394           if (lit >> 1)
7395             {
7396               // lit>>1  != 0 => result = 1
7397               if (AOP_TYPE (result) == AOP_CRY)
7398                 {
7399                   if (size)
7400                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7401                   else if (ifx)
7402                     continueIfTrue (ifx);
7403                   goto release;
7404                 }
7405               emitcode ("setb", "c");
7406             }
7407           else
7408             {
7409               // lit == (0 or 1)
7410               if (lit == 0)
7411                 {
7412                   // lit == 0, result = left
7413                   if (size && sameRegs (AOP (result), AOP (left)))
7414                     goto release;
7415                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7416                 }
7417               else
7418                 {
7419                   // lit == 1, result = not(left)
7420                   if (size && sameRegs (AOP (result), AOP (left)))
7421                     {
7422                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7423                       goto release;
7424                     }
7425                   else
7426                     {
7427                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7428                       emitcode ("cpl", "c");
7429                     }
7430                 }
7431             }
7432
7433         }
7434       else
7435         {
7436           // right != literal
7437           symbol *tlbl = newiTempLabel (NULL);
7438           if (AOP_TYPE (right) == AOP_CRY)
7439             {
7440               // c = bit ^ bit;
7441               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7442             }
7443           else
7444             {
7445               int sizer = AOP_SIZE (right);
7446               // c = bit ^ val
7447               // if val>>1 != 0, result = 1
7448               emitcode ("setb", "c");
7449               while (sizer)
7450                 {
7451                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7452                   if (sizer == 1)
7453                     // test the msb of the lsb
7454                     emitcode ("anl", "a,#!constbyte",0xfe);
7455                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
7456                   sizer--;
7457                 }
7458               // val = (0,1)
7459               emitcode ("rrc", "a");
7460             }
7461           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7462           emitcode ("cpl", "c");
7463           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7464         }
7465       // bit = c
7466       // val = c
7467       if (size)
7468         outBitC (result);
7469       // if(bit | ...)
7470       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7471         genIfxJump (ifx, "c");
7472       goto release;
7473     }
7474
7475   /* if left is same as result */
7476   if (sameRegs (AOP (result), AOP (left)))
7477     {
7478       for (; size--; offset++)
7479         {
7480           if (AOP_TYPE (right) == AOP_LIT)
7481             {
7482               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7483               if (bytelit == 0x00L)
7484                 {
7485                   /* dummy read of volatile operand */
7486                   if (isOperandVolatile (left, FALSE))
7487                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7488                   else
7489                     continue;
7490                 }
7491               else if (IS_AOP_PREG (left))
7492                 {
7493                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7494                   emitcode ("xrl", "a,%s",
7495                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7496                   aopPut (AOP (result), "a", offset);
7497                 }
7498               else
7499                 {
7500                   emitcode ("xrl", "%s,%s",
7501                             aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7502                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7503                 }
7504             }
7505           else
7506             {
7507               if (AOP_TYPE (left) == AOP_ACC)
7508                 emitcode ("xrl", "a,%s",
7509                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7510               else
7511                 {
7512                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7513                   if (IS_AOP_PREG (left))
7514                     {
7515                       emitcode ("xrl", "a,%s",
7516                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7517                       aopPut (AOP (result), "a", offset);
7518                     }
7519                   else
7520                     emitcode ("xrl", "%s,a",
7521                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7522                 }
7523             }
7524         }
7525     }
7526   else
7527     {
7528       // left & result in different registers
7529       if (AOP_TYPE (result) == AOP_CRY)
7530         {
7531           // result = bit
7532           // if(size), result in bit
7533           // if(!size && ifx), conditional oper: if(left ^ right)
7534           symbol *tlbl = newiTempLabel (NULL);
7535           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7536
7537           if (size)
7538             emitcode ("setb", "c");
7539           while (sizer--)
7540             {
7541               if ((AOP_TYPE (right) == AOP_LIT) &&
7542                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7543                 {
7544                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7545                 }
7546               else
7547                 {
7548                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7549                     emitcode ("xrl", "a,%s",
7550                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7551                   } else {
7552                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7553                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7554                       {
7555                           emitcode("mov", "b,a");
7556                           rOp = "b";
7557                       }
7558
7559                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7560                       emitcode ("xrl", "a,%s", rOp);
7561                   }
7562                 }
7563               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7564               offset++;
7565             }
7566           if (size)
7567             {
7568               CLRC;
7569               emitcode ("", "!tlabeldef", tlbl->key + 100);
7570               outBitC (result);
7571             }
7572           else if (ifx)
7573             jmpTrueOrFalse (ifx, tlbl);
7574         }
7575       else
7576         {
7577         for (; (size--); offset++)
7578           {
7579             // normal case
7580             // result = left & right
7581             if (AOP_TYPE (right) == AOP_LIT)
7582               {
7583                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7584                   {
7585                     aopPut (AOP (result),
7586                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7587                             offset);
7588                     continue;
7589                   }
7590                 D (emitcode (";", "better literal XOR."););
7591                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7592                 emitcode ("xrl", "a, %s",
7593                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7594               }
7595             else
7596               {
7597                 // faster than result <- left, anl result,right
7598                 // and better if result is SFR
7599                 if (AOP_TYPE (left) == AOP_ACC)
7600                   {
7601                     emitcode ("xrl", "a,%s",
7602                               aopGet (AOP (right), offset,
7603                                       FALSE, FALSE, DP2_RESULT_REG));
7604                   }
7605                 else
7606                   {
7607                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7608                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7609                       {
7610                           emitcode("mov", "b,a");
7611                           rOp = "b";
7612                       }
7613
7614                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7615                       emitcode ("xrl", "a,%s", rOp);
7616                   }
7617               }
7618             aopPut (AOP (result), "a", offset);
7619           }
7620         }
7621
7622     }
7623
7624 release:
7625   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7626   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7627   freeAsmop (result, NULL, ic, TRUE);
7628 }
7629
7630 /*-----------------------------------------------------------------*/
7631 /* genInline - write the inline code out                           */
7632 /*-----------------------------------------------------------------*/
7633 static void
7634 genInline (iCode * ic)
7635 {
7636   char *buffer, *bp, *bp1;
7637
7638   D (emitcode (";", "genInline "); );
7639
7640   _G.inLine += (!options.asmpeep);
7641
7642   buffer = Safe_strdup(IC_INLINE(ic));
7643   bp = buffer;
7644   bp1 = buffer;
7645
7646   /* emit each line as a code */
7647   while (*bp)
7648     {
7649       if (*bp == '\n')
7650         {
7651           *bp++ = '\0';
7652           emitcode (bp1, "");
7653           bp1 = bp;
7654         }
7655       else
7656         {
7657           if (*bp == ':')
7658             {
7659               bp++;
7660               *bp = '\0';
7661               bp++;
7662               emitcode (bp1, "");
7663               bp1 = bp;
7664             }
7665           else
7666             bp++;
7667         }
7668     }
7669   if (bp1 != bp)
7670     emitcode (bp1, "");
7671   /*     emitcode("",buffer); */
7672   _G.inLine -= (!options.asmpeep);
7673 }
7674
7675 /*-----------------------------------------------------------------*/
7676 /* genRRC - rotate right with carry                                */
7677 /*-----------------------------------------------------------------*/
7678 static void
7679 genRRC (iCode * ic)
7680 {
7681   operand *left, *result;
7682   int     size, offset;
7683
7684   D (emitcode (";", "genRRC "););
7685
7686   /* rotate right with carry */
7687   left = IC_LEFT (ic);
7688   result = IC_RESULT (ic);
7689   aopOp (left, ic, FALSE, FALSE);
7690   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7691
7692   /* move it to the result */
7693   size = AOP_SIZE (result);
7694   offset = size - 1;
7695   CLRC;
7696
7697   _startLazyDPSEvaluation ();
7698   while (size--)
7699     {
7700       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7701       emitcode ("rrc", "a");
7702       if (AOP_SIZE (result) > 1)
7703         aopPut (AOP (result), "a", offset--);
7704     }
7705   _endLazyDPSEvaluation ();
7706
7707   /* now we need to put the carry into the
7708      highest order byte of the result */
7709   if (AOP_SIZE (result) > 1)
7710     {
7711       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7712     }
7713   emitcode ("mov", "acc.7,c");
7714   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7715   freeAsmop (left, NULL, ic, TRUE);
7716   freeAsmop (result, NULL, ic, TRUE);
7717 }
7718
7719 /*-----------------------------------------------------------------*/
7720 /* genRLC - generate code for rotate left with carry               */
7721 /*-----------------------------------------------------------------*/
7722 static void
7723 genRLC (iCode * ic)
7724 {
7725   operand *left, *result;
7726   int size, offset;
7727   char *l;
7728
7729   D (emitcode (";", "genRLC "););
7730
7731   /* rotate right with carry */
7732   left = IC_LEFT (ic);
7733   result = IC_RESULT (ic);
7734   aopOp (left, ic, FALSE, FALSE);
7735   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7736
7737   /* move it to the result */
7738   size = AOP_SIZE (result);
7739   offset = 0;
7740   if (size--)
7741     {
7742       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7743       MOVA (l);
7744       emitcode ("add", "a,acc");
7745       if (AOP_SIZE (result) > 1)
7746         {
7747           aopPut (AOP (result), "a", offset++);
7748         }
7749
7750       _startLazyDPSEvaluation ();
7751       while (size--)
7752         {
7753           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7754           MOVA (l);
7755           emitcode ("rlc", "a");
7756           if (AOP_SIZE (result) > 1)
7757             aopPut (AOP (result), "a", offset++);
7758         }
7759       _endLazyDPSEvaluation ();
7760     }
7761   /* now we need to put the carry into the
7762      highest order byte of the result */
7763   if (AOP_SIZE (result) > 1)
7764     {
7765       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7766       MOVA (l);
7767     }
7768   emitcode ("mov", "acc.0,c");
7769   aopPut (AOP (result), "a", 0);
7770   freeAsmop (left, NULL, ic, TRUE);
7771   freeAsmop (result, NULL, ic, TRUE);
7772 }
7773
7774 /*-----------------------------------------------------------------*/
7775 /* genGetHbit - generates code get highest order bit               */
7776 /*-----------------------------------------------------------------*/
7777 static void
7778 genGetHbit (iCode * ic)
7779 {
7780   operand *left, *result;
7781   left = IC_LEFT (ic);
7782   result = IC_RESULT (ic);
7783   aopOp (left, ic, FALSE, FALSE);
7784   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7785
7786   D (emitcode (";", "genGetHbit "););
7787
7788   /* get the highest order byte into a */
7789   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7790   if (AOP_TYPE (result) == AOP_CRY)
7791     {
7792       emitcode ("rlc", "a");
7793       outBitC (result);
7794     }
7795   else
7796     {
7797       emitcode ("rl", "a");
7798       emitcode ("anl", "a,#1");
7799       outAcc (result);
7800     }
7801
7802
7803   freeAsmop (left, NULL, ic, TRUE);
7804   freeAsmop (result, NULL, ic, TRUE);
7805 }
7806
7807 /*-----------------------------------------------------------------*/
7808 /* genSwap - generates code to swap nibbles or bytes               */
7809 /*-----------------------------------------------------------------*/
7810 static void
7811 genSwap (iCode * ic)
7812 {
7813   operand *left, *result;
7814
7815   D(emitcode (";     genSwap",""));
7816
7817   left = IC_LEFT (ic);
7818   result = IC_RESULT (ic);
7819   aopOp (left, ic, FALSE, FALSE);
7820   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7821
7822   _startLazyDPSEvaluation ();
7823   switch (AOP_SIZE (left))
7824     {
7825     case 1: /* swap nibbles in byte */
7826       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7827       emitcode ("swap", "a");
7828       aopPut (AOP (result), "a", 0);
7829       break;
7830     case 2: /* swap bytes in word */
7831       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7832         {
7833           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7834           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7835           aopPut (AOP (result), "a", 1);
7836         }
7837       else if (operandsEqu (left, result))
7838         {
7839           char * reg = "a";
7840           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7841           if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7842             {
7843               emitcode ("mov", "b,a");
7844               reg = "b";
7845               _G.bInUse=1;
7846             }
7847           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7848           aopPut (AOP (result), reg, 1);
7849           _G.bInUse=0;
7850         }
7851       else
7852         {
7853           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7854           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7855         }
7856       break;
7857     default:
7858       wassertl(FALSE, "unsupported SWAP operand size");
7859     }
7860   _endLazyDPSEvaluation ();
7861
7862   freeAsmop (left, NULL, ic, TRUE);
7863   freeAsmop (result, NULL, ic, TRUE);
7864 }
7865
7866 /*-----------------------------------------------------------------*/
7867 /* AccRol - rotate left accumulator by known count                 */
7868 /*-----------------------------------------------------------------*/
7869 static void
7870 AccRol (int shCount)
7871 {
7872   shCount &= 0x0007;            // shCount : 0..7
7873
7874   switch (shCount)
7875     {
7876     case 0:
7877       break;
7878     case 1:
7879       emitcode ("rl", "a");
7880       break;
7881     case 2:
7882       emitcode ("rl", "a");
7883       emitcode ("rl", "a");
7884       break;
7885     case 3:
7886       emitcode ("swap", "a");
7887       emitcode ("rr", "a");
7888       break;
7889     case 4:
7890       emitcode ("swap", "a");
7891       break;
7892     case 5:
7893       emitcode ("swap", "a");
7894       emitcode ("rl", "a");
7895       break;
7896     case 6:
7897       emitcode ("rr", "a");
7898       emitcode ("rr", "a");
7899       break;
7900     case 7:
7901       emitcode ("rr", "a");
7902       break;
7903     }
7904 }
7905
7906 /*-----------------------------------------------------------------*/
7907 /* AccLsh - left shift accumulator by known count                  */
7908 /*-----------------------------------------------------------------*/
7909 static void
7910 AccLsh (int shCount)
7911 {
7912   if (shCount != 0)
7913     {
7914       if (shCount == 1)
7915         emitcode ("add", "a,acc");
7916       else if (shCount == 2)
7917         {
7918           emitcode ("add", "a,acc");
7919           emitcode ("add", "a,acc");
7920         }
7921       else
7922         {
7923           /* rotate left accumulator */
7924           AccRol (shCount);
7925           /* and kill the lower order bits */
7926           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7927         }
7928     }
7929 }
7930
7931 /*-----------------------------------------------------------------*/
7932 /* AccRsh - right shift accumulator by known count                 */
7933 /*-----------------------------------------------------------------*/
7934 static void
7935 AccRsh (int shCount)
7936 {
7937   if (shCount != 0)
7938     {
7939       if (shCount == 1)
7940         {
7941           CLRC;
7942           emitcode ("rrc", "a");
7943         }
7944       else
7945         {
7946           /* rotate right accumulator */
7947           AccRol (8 - shCount);
7948           /* and kill the higher order bits */
7949           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7950         }
7951     }
7952 }
7953
7954 #ifdef BETTER_LITERAL_SHIFT
7955 /*-----------------------------------------------------------------*/
7956 /* AccSRsh - signed right shift accumulator by known count                 */
7957 /*-----------------------------------------------------------------*/
7958 static void
7959 AccSRsh (int shCount)
7960 {
7961   symbol *tlbl;
7962   if (shCount != 0)
7963     {
7964       if (shCount == 1)
7965         {
7966           emitcode ("mov", "c,acc.7");
7967           emitcode ("rrc", "a");
7968         }
7969       else if (shCount == 2)
7970         {
7971           emitcode ("mov", "c,acc.7");
7972           emitcode ("rrc", "a");
7973           emitcode ("mov", "c,acc.7");
7974           emitcode ("rrc", "a");
7975         }
7976       else
7977         {
7978           tlbl = newiTempLabel (NULL);
7979           /* rotate right accumulator */
7980           AccRol (8 - shCount);
7981           /* and kill the higher order bits */
7982           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7983           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7984           emitcode ("orl", "a,#!constbyte",
7985                     (unsigned char) ~SRMask[shCount]);
7986           emitcode ("", "!tlabeldef", tlbl->key + 100);
7987         }
7988     }
7989 }
7990 #endif
7991
7992 #ifdef BETTER_LITERAL_SHIFT
7993 /*-----------------------------------------------------------------*/
7994 /* shiftR1Left2Result - shift right one byte from left to result   */
7995 /*-----------------------------------------------------------------*/
7996 static void
7997 shiftR1Left2Result (operand * left, int offl,
7998                     operand * result, int offr,
7999                     int shCount, int sign)
8000 {
8001   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8002   /* shift right accumulator */
8003   if (sign)
8004     AccSRsh (shCount);
8005   else
8006     AccRsh (shCount);
8007   aopPut (AOP (result), "a", offr);
8008 }
8009 #endif
8010
8011 #ifdef BETTER_LITERAL_SHIFT
8012 /*-----------------------------------------------------------------*/
8013 /* shiftL1Left2Result - shift left one byte from left to result    */
8014 /*-----------------------------------------------------------------*/
8015 static void
8016 shiftL1Left2Result (operand * left, int offl,
8017                     operand * result, int offr, int shCount)
8018 {
8019   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8020   /* shift left accumulator */
8021   AccLsh (shCount);
8022   aopPut (AOP (result), "a", offr);
8023 }
8024 #endif
8025
8026 #ifdef BETTER_LITERAL_SHIFT
8027 /*-----------------------------------------------------------------*/
8028 /* movLeft2Result - move byte from left to result                  */
8029 /*-----------------------------------------------------------------*/
8030 static void
8031 movLeft2Result (operand * left, int offl,
8032                 operand * result, int offr, int sign)
8033 {
8034   char *l;
8035   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8036   {
8037       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
8038
8039       if (*l == '@' && (IS_AOP_PREG (result)))
8040       {
8041           emitcode ("mov", "a,%s", l);
8042           aopPut (AOP (result), "a", offr);
8043       }
8044       else
8045       {
8046           if (!sign)
8047           {
8048             aopPut (AOP (result), l, offr);
8049           }
8050           else
8051             {
8052               /* MSB sign in acc.7 ! */
8053               if (getDataSize (left) == offl + 1)
8054                 {
8055                   emitcode ("mov", "a,%s", l);
8056                   aopPut (AOP (result), "a", offr);
8057                 }
8058             }
8059       }
8060   }
8061 }
8062 #endif
8063
8064 #ifdef BETTER_LITERAL_SHIFT
8065 /*-----------------------------------------------------------------*/
8066 /* AccAXRrl1 - right rotate a:x by 1                               */
8067 /*-----------------------------------------------------------------*/
8068 static void
8069 AccAXRrl1 (char *x)
8070 {
8071   emitcode ("mov", "c,acc.0");
8072   emitcode ("xch", "a,%s", x);
8073   emitcode ("rrc", "a");
8074   emitcode ("xch", "a,%s", x);
8075   emitcode ("rrc", "a");
8076 }
8077 #endif
8078
8079 #ifdef BETTER_LITERAL_SHIFT
8080 //REMOVE ME!!!
8081 /*-----------------------------------------------------------------*/
8082 /* AccAXLrl1 - left rotate a:x by 1                                */
8083 /*-----------------------------------------------------------------*/
8084 static void
8085 AccAXLrl1 (char *x)
8086 {
8087   emitcode ("mov", "c,acc.7");
8088   emitcode ("xch", "a,%s", x);
8089   emitcode ("rlc", "a");
8090   emitcode ("xch", "a,%s", x);
8091   emitcode ("rlc", "a");
8092 }
8093 #endif
8094
8095 #ifdef BETTER_LITERAL_SHIFT
8096 /*-----------------------------------------------------------------*/
8097 /* AccAXRsh1 - right shift c->a:x->c by 1                          */
8098 /*-----------------------------------------------------------------*/
8099 static void
8100 AccAXRsh1 (char *x)
8101 {
8102   emitcode ("rrc", "a");
8103   emitcode ("xch", "a,%s", x);
8104   emitcode ("rrc", "a");
8105   emitcode ("xch", "a,%s", x);
8106 }
8107 #endif
8108
8109 #ifdef BETTER_LITERAL_SHIFT
8110 /*-----------------------------------------------------------------*/
8111 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8112 /*-----------------------------------------------------------------*/
8113 static void
8114 AccAXLsh1 (char *x)
8115 {
8116   emitcode ("xch", "a,%s", x);
8117   emitcode ("add", "a,acc");
8118   emitcode ("xch", "a,%s", x);
8119   emitcode ("rlc", "a");
8120 }
8121 #endif
8122
8123 #ifdef BETTER_LITERAL_SHIFT
8124 /*-----------------------------------------------------------------*/
8125 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8126 /*-----------------------------------------------------------------*/
8127 static void
8128 AccAXLsh (char *x, int shCount)
8129 {
8130   switch (shCount)
8131     {
8132     case 0:
8133       break;
8134     case 1:
8135       AccAXLsh1 (x);
8136       break;
8137     case 2:
8138       AccAXLsh1 (x);
8139       AccAXLsh1 (x);
8140       break;
8141     case 3:
8142     case 4:
8143     case 5:                             // AAAAABBB:CCCCCDDD
8144
8145       AccRol (shCount);                 // BBBAAAAA:CCCCCDDD
8146
8147       emitcode ("anl", "a,#!constbyte",
8148                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8149
8150       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8151
8152       AccRol (shCount);                 // DDDCCCCC:BBB00000
8153
8154       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8155
8156       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8157
8158       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8159
8160       emitcode ("anl", "a,#!constbyte",
8161                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8162
8163       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8164
8165       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8166
8167       break;
8168     case 6:                             // AAAAAABB:CCCCCCDD
8169       emitcode ("anl", "a,#!constbyte",
8170                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8171 #if 1
8172       AccAXRrl1 (x);                    // D000000B:BCCCCCCD
8173       AccAXRrl1 (x);                    // DD000000:BBCCCCCC
8174       emitcode ("xch", "a,%s", x);      // BBCCCCCC:DD000000
8175 #else
8176       emitcode ("mov", "c,acc.0");      // c = B
8177       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8178       emitcode("rrc","a");
8179       emitcode("xch","a,%s", x);
8180       emitcode("rrc","a");
8181       emitcode("mov","c,acc.0"); //<< get correct bit
8182       emitcode("xch","a,%s", x);
8183
8184       emitcode("rrc","a");
8185       emitcode("xch","a,%s", x);
8186       emitcode("rrc","a");
8187       emitcode("xch","a,%s", x);
8188 #endif
8189       break;
8190     case 7:                             // a:x <<= 7
8191
8192       emitcode ("anl", "a,#!constbyte",
8193                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8194
8195       AccAXRrl1 (x);                    // D0000000:BCCCCCCC
8196
8197       emitcode ("xch", "a,%s", x);      // BCCCCCCC:D0000000
8198
8199       break;
8200     default:
8201       break;
8202     }
8203 }
8204 #endif
8205
8206 #ifdef BETTER_LITERAL_SHIFT
8207 //REMOVE ME!!!
8208 /*-----------------------------------------------------------------*/
8209 /* AccAXRsh - right shift a:x known count (0..7)                   */
8210 /*-----------------------------------------------------------------*/
8211 static void
8212 AccAXRsh (char *x, int shCount)
8213 {
8214   switch (shCount)
8215     {
8216     case 0:
8217       break;
8218     case 1:
8219       CLRC;
8220       AccAXRsh1 (x);                    // 0->a:x
8221
8222       break;
8223     case 2:
8224       CLRC;
8225       AccAXRsh1 (x);                    // 0->a:x
8226
8227       CLRC;
8228       AccAXRsh1 (x);                    // 0->a:x
8229
8230       break;
8231     case 3:
8232     case 4:
8233     case 5:                             // AAAAABBB:CCCCCDDD = a:x
8234
8235       AccRol (8 - shCount);             // BBBAAAAA:DDDCCCCC
8236
8237       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8238
8239       AccRol (8 - shCount);             // DDDCCCCC:BBBAAAAA
8240
8241       emitcode ("anl", "a,#!constbyte",
8242                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8243
8244       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8245
8246       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8247
8248       emitcode ("anl", "a,#!constbyte",
8249                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8250
8251       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8252
8253       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8254
8255       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8256
8257       break;
8258     case 6:                             // AABBBBBB:CCDDDDDD
8259
8260       AccAXLrl1 (x);                    // ABBBBBBC:CDDDDDDE
8261       AccAXLrl1 (x);                    // BBBBBBCC:DDDDDDAA
8262
8263       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8264
8265       emitcode ("anl", "a,#!constbyte",
8266                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8267
8268       break;
8269     case 7:                             // ABBBBBBB:CDDDDDDD
8270
8271       AccAXLrl1 (x);                    // BBBBBBBC:DDDDDDDA
8272
8273       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8274
8275       emitcode ("anl", "a,#!constbyte",
8276                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8277
8278       break;
8279     default:
8280       break;
8281     }
8282 }
8283 #endif
8284
8285 #ifdef BETTER_LITERAL_SHIFT
8286 /*-----------------------------------------------------------------*/
8287 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8288 /*-----------------------------------------------------------------*/
8289 static void
8290 AccAXRshS (char *x, int shCount)
8291 {
8292   symbol *tlbl;
8293   switch (shCount)
8294     {
8295     case 0:
8296       break;
8297     case 1:
8298       emitcode ("mov", "c,acc.7");
8299       AccAXRsh1 (x);                    // s->a:x
8300
8301       break;
8302     case 2:
8303       emitcode ("mov", "c,acc.7");
8304       AccAXRsh1 (x);                    // s->a:x
8305
8306       emitcode ("mov", "c,acc.7");
8307       AccAXRsh1 (x);                    // s->a:x
8308
8309       break;
8310     case 3:
8311     case 4:
8312     case 5:                             // AAAAABBB:CCCCCDDD = a:x
8313
8314       tlbl = newiTempLabel (NULL);
8315       AccRol (8 - shCount);             // BBBAAAAA:CCCCCDDD
8316
8317       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8318
8319       AccRol (8 - shCount);             // DDDCCCCC:BBBAAAAA
8320
8321       emitcode ("anl", "a,#!constbyte",
8322                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8323
8324       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8325
8326       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8327
8328       emitcode ("anl", "a,#!constbyte",
8329                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8330
8331       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8332
8333       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8334
8335       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8336
8337       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8338       emitcode ("orl", "a,#!constbyte",
8339                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8340
8341       emitcode ("", "!tlabeldef", tlbl->key + 100);
8342       break;                            // SSSSAAAA:BBBCCCCC
8343
8344     case 6:                             // AABBBBBB:CCDDDDDD
8345
8346       tlbl = newiTempLabel (NULL);
8347
8348       AccAXLrl1 (x);                    // ABBBBBBC:CDDDDDDA
8349       AccAXLrl1 (x);                    // BBBBBBCC:DDDDDDAA
8350
8351       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8352
8353       emitcode ("anl", "a,#!constbyte",
8354                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8355
8356       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8357       emitcode ("orl", "a,#!constbyte",
8358                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8359
8360       emitcode ("", "!tlabeldef", tlbl->key + 100);
8361       break;
8362     case 7:                             // ABBBBBBB:CDDDDDDD
8363
8364       tlbl = newiTempLabel (NULL);
8365
8366       AccAXLrl1 (x);                    // BBBBBBBC:DDDDDDDA
8367
8368       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8369
8370       emitcode ("anl", "a,#!constbyte",
8371                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8372
8373       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8374       emitcode ("orl", "a,#!constbyte",
8375                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8376
8377       emitcode ("", "!tlabeldef", tlbl->key + 100);
8378       break;
8379     default:
8380       break;
8381     }
8382 }
8383 #endif
8384
8385 #ifdef BETTER_LITERAL_SHIFT
8386 static void
8387 _loadLeftIntoAx(char    **lsb,
8388                 operand *left,
8389                 operand *result,
8390                 int     offl,
8391                 int     offr)
8392 {
8393   // Get the initial value from left into a pair of registers.
8394   // MSB must be in A, LSB can be any register.
8395   //
8396   // If the result is held in registers, it is an optimization
8397   // if the LSB can be held in the register which will hold the,
8398   // result LSB since this saves us from having to copy it into
8399   // the result following AccAXLsh.
8400   //
8401   // If the result is addressed indirectly, this is not a gain.
8402   if (AOP_NEEDSACC(result))
8403   {
8404        char *leftByte;
8405
8406        _startLazyDPSEvaluation();
8407       if (AOP_TYPE(left) == AOP_DPTR2)
8408        {
8409            // Get MSB in A.
8410            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8411            // get LSB in DP2_RESULT_REG.
8412            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8413            assert(!strcmp(leftByte, DP2_RESULT_REG));
8414        }
8415        else
8416        {
8417            // get LSB into DP2_RESULT_REG
8418            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8419            if (strcmp(leftByte, DP2_RESULT_REG))
8420            {
8421                TR_AP("#7");
8422                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8423            }
8424            // And MSB in A.
8425            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8426            assert(strcmp(leftByte, DP2_RESULT_REG));
8427            MOVA(leftByte);
8428        }
8429        _endLazyDPSEvaluation();
8430        *lsb = DP2_RESULT_REG;
8431   }
8432   else
8433   {
8434       if (sameRegs (AOP (result), AOP (left)) &&
8435         ((offl + MSB16) == offr))
8436       {
8437           /* don't crash result[offr] */
8438           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8439           emitcode ("xch", "a,%s",
8440                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8441       }
8442       else
8443       {
8444           movLeft2Result (left, offl, result, offr, 0);
8445           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8446       }
8447       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8448       assert(strcmp(*lsb,"a"));
8449   }
8450 }
8451
8452 static void
8453 _storeAxResults(char    *lsb,
8454                 operand *result,
8455                 int     offr)
8456 {
8457   _startLazyDPSEvaluation();
8458   if (AOP_NEEDSACC(result))
8459   {
8460       /* We have to explicitly update the result LSB.
8461        */
8462       emitcode("xch","a,%s", lsb);
8463       aopPut(AOP(result), "a", offr);
8464       emitcode("mov","a,%s", lsb);
8465   }
8466   if (getDataSize (result) > 1)
8467   {
8468       aopPut (AOP (result), "a", offr + MSB16);
8469   }
8470   _endLazyDPSEvaluation();
8471 }
8472
8473 /*-----------------------------------------------------------------*/
8474 /* shiftL2Left2Result - shift left two bytes from left to result   */
8475 /*-----------------------------------------------------------------*/
8476 static void
8477 shiftL2Left2Result (operand * left, int offl,
8478                     operand * result, int offr, int shCount)
8479 {
8480   char *lsb;
8481
8482   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8483
8484   AccAXLsh (lsb, shCount);
8485
8486   _storeAxResults(lsb, result, offr);
8487 }
8488 #endif
8489
8490 #ifdef BETTER_LITERAL_SHIFT
8491 /*-----------------------------------------------------------------*/
8492 /* shiftR2Left2Result - shift right two bytes from left to result  */
8493 /*-----------------------------------------------------------------*/
8494 static void
8495 shiftR2Left2Result (operand * left, int offl,
8496                     operand * result, int offr,
8497                     int shCount, int sign)
8498 {
8499   char *lsb;
8500
8501   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8502
8503   /* a:x >> shCount (x = lsb(result)) */
8504   if (sign)
8505   {
8506      AccAXRshS(lsb, shCount);
8507   }
8508   else
8509   {
8510     AccAXRsh(lsb, shCount);
8511   }
8512
8513   _storeAxResults(lsb, result, offr);
8514 }
8515 #endif
8516
8517 /*-----------------------------------------------------------------*/
8518 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8519 /*-----------------------------------------------------------------*/
8520 static void
8521 shiftLLeftOrResult (operand * left, int offl,
8522                     operand * result, int offr, int shCount)
8523 {
8524   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8525   /* shift left accumulator */
8526   AccLsh (shCount);
8527   /* or with result */
8528   emitcode ("orl", "a,%s",
8529             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8530   /* back to result */
8531   aopPut (AOP (result), "a", offr);
8532 }
8533
8534 #if 0
8535 //REMOVE ME!!!
8536 /*-----------------------------------------------------------------*/
8537 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8538 /*-----------------------------------------------------------------*/
8539 static void
8540 shiftRLeftOrResult (operand * left, int offl,
8541                     operand * result, int offr, int shCount)
8542 {
8543   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8544   /* shift right accumulator */
8545   AccRsh (shCount);
8546   /* or with result */
8547   emitcode ("orl", "a,%s",
8548             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8549   /* back to result */
8550   aopPut (AOP (result), "a", offr);
8551 }
8552 #endif
8553
8554 #ifdef BETTER_LITERAL_SHIFT
8555 /*-----------------------------------------------------------------*/
8556 /* genlshOne - left shift a one byte quantity by known count       */
8557 /*-----------------------------------------------------------------*/
8558 static void
8559 genlshOne (operand * result, operand * left, int shCount)
8560 {
8561   D (emitcode (";", "genlshOne "););
8562   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8563 }
8564 #endif
8565
8566 #ifdef BETTER_LITERAL_SHIFT
8567 /*-----------------------------------------------------------------*/
8568 /* genlshTwo - left shift two bytes by known amount != 0           */
8569 /*-----------------------------------------------------------------*/
8570 static void
8571 genlshTwo (operand * result, operand * left, int shCount)
8572 {
8573   int size;
8574
8575   D (emitcode (";", "genlshTwo "););
8576
8577   size = getDataSize (result);
8578
8579   /* if shCount >= 8 */
8580   if (shCount >= 8)
8581   {
8582       shCount -= 8;
8583
8584       _startLazyDPSEvaluation();
8585
8586       if (size > 1)
8587         {
8588           if (shCount)
8589           {
8590             _endLazyDPSEvaluation();
8591             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8592             aopPut (AOP (result), zero, LSB);
8593           }
8594           else
8595           {
8596             movLeft2Result (left, LSB, result, MSB16, 0);
8597             aopPut (AOP (result), zero, LSB);
8598             _endLazyDPSEvaluation();
8599           }
8600         }
8601         else
8602         {
8603           aopPut (AOP (result), zero, LSB);
8604           _endLazyDPSEvaluation();
8605         }
8606   }
8607
8608   /*  1 <= shCount <= 7 */
8609   else
8610     {
8611       if (size == 1)
8612       {
8613         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8614       }
8615       else
8616       {
8617         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8618       }
8619     }
8620 }
8621 #endif
8622
8623 #if 0
8624 //REMOVE ME!!!
8625 /*-----------------------------------------------------------------*/
8626 /* shiftLLong - shift left one long from left to result            */
8627 /* offl = LSB or MSB16                                             */
8628 /*-----------------------------------------------------------------*/
8629 static void
8630 shiftLLong (operand * left, operand * result, int offr)
8631 {
8632   char *l;
8633   int size = AOP_SIZE (result);
8634
8635   if (size >= LSB + offr)
8636     {
8637       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8638       MOVA (l);
8639       emitcode ("add", "a,acc");
8640       if (sameRegs (AOP (left), AOP (result)) &&
8641           size >= MSB16 + offr && offr != LSB)
8642         emitcode ("xch", "a,%s",
8643                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8644       else
8645         aopPut (AOP (result), "a", LSB + offr);
8646     }
8647
8648   if (size >= MSB16 + offr)
8649     {
8650       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8651         {
8652           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8653         }
8654       emitcode ("rlc", "a");
8655       if (sameRegs (AOP (left), AOP (result)) &&
8656           size >= MSB24 + offr && offr != LSB)
8657         emitcode ("xch", "a,%s",
8658                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8659       else
8660         aopPut (AOP (result), "a", MSB16 + offr);
8661     }
8662
8663   if (size >= MSB24 + offr)
8664     {
8665       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8666         {
8667           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8668         }
8669       emitcode ("rlc", "a");
8670       if (sameRegs (AOP (left), AOP (result)) &&
8671           size >= MSB32 + offr && offr != LSB)
8672         emitcode ("xch", "a,%s",
8673                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8674       else
8675         aopPut (AOP (result), "a", MSB24 + offr);
8676     }
8677
8678   if (size > MSB32 + offr)
8679     {
8680       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8681         {
8682           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8683         }
8684       emitcode ("rlc", "a");
8685       aopPut (AOP (result), "a", MSB32 + offr);
8686     }
8687   if (offr != LSB)
8688     aopPut (AOP (result), zero, LSB);
8689 }
8690 #endif
8691
8692 #if 0
8693 //REMOVE ME!!!
8694 /*-----------------------------------------------------------------*/
8695 /* genlshFour - shift four byte by a known amount != 0             */
8696 /*-----------------------------------------------------------------*/
8697 static void
8698 genlshFour (operand * result, operand * left, int shCount)
8699 {
8700   int size;
8701
8702   D (emitcode (";", "genlshFour ");
8703     );
8704
8705   size = AOP_SIZE (result);
8706
8707   /* if shifting more that 3 bytes */
8708   if (shCount >= 24)
8709     {
8710       shCount -= 24;
8711       if (shCount)
8712         /* lowest order of left goes to the highest
8713            order of the destination */
8714         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8715       else
8716         movLeft2Result (left, LSB, result, MSB32, 0);
8717       aopPut (AOP (result), zero, LSB);
8718       aopPut (AOP (result), zero, MSB16);
8719       aopPut (AOP (result), zero, MSB24);
8720       return;
8721     }
8722
8723   /* more than two bytes */
8724   else if (shCount >= 16)
8725     {
8726       /* lower order two bytes goes to higher order two bytes */
8727       shCount -= 16;
8728       /* if some more remaining */
8729       if (shCount)
8730         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8731       else
8732         {
8733           movLeft2Result (left, MSB16, result, MSB32, 0);
8734           movLeft2Result (left, LSB, result, MSB24, 0);
8735         }
8736       aopPut (AOP (result), zero, MSB16);
8737       aopPut (AOP (result), zero, LSB);
8738       return;
8739     }
8740
8741   /* if more than 1 byte */
8742   else if (shCount >= 8)
8743     {
8744       /* lower order three bytes goes to higher order  three bytes */
8745       shCount -= 8;
8746       if (size == 2)
8747         {
8748           if (shCount)
8749             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8750           else
8751             movLeft2Result (left, LSB, result, MSB16, 0);
8752         }
8753       else
8754         {                       /* size = 4 */
8755           if (shCount == 0)
8756             {
8757               movLeft2Result (left, MSB24, result, MSB32, 0);
8758               movLeft2Result (left, MSB16, result, MSB24, 0);
8759               movLeft2Result (left, LSB, result, MSB16, 0);
8760               aopPut (AOP (result), zero, LSB);
8761             }
8762           else if (shCount == 1)
8763             shiftLLong (left, result, MSB16);
8764           else
8765             {
8766               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8767               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8768               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8769               aopPut (AOP (result), zero, LSB);
8770             }
8771         }
8772     }
8773
8774   /* 1 <= shCount <= 7 */
8775   else if (shCount <= 2)
8776     {
8777       shiftLLong (left, result, LSB);
8778       if (shCount == 2)
8779         shiftLLong (result, result, LSB);
8780     }
8781   /* 3 <= shCount <= 7, optimize */
8782   else
8783     {
8784       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8785       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8786       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8787     }
8788 }
8789 #endif
8790
8791 #ifdef BETTER_LITERAL_SHIFT
8792 /*-----------------------------------------------------------------*/
8793 /* genLeftShiftLiteral - left shifting by known count              */
8794 /*-----------------------------------------------------------------*/
8795 static bool
8796 genLeftShiftLiteral (operand * left,
8797                      operand * right,
8798                      operand * result,
8799                      iCode * ic)
8800 {
8801   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8802   int size;
8803
8804   size = getSize (operandType (result));
8805
8806   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8807
8808   /* We only handle certain easy cases so far. */
8809   if ((shCount != 0)
8810    && (shCount < (size * 8))
8811    && (size != 1)
8812    && (size != 2))
8813   {
8814       D(emitcode (";", "genLeftShiftLiteral wimping out"););
8815       return FALSE;
8816   }
8817
8818   freeAsmop (right, NULL, ic, TRUE);
8819
8820   aopOp(left, ic, FALSE, FALSE);
8821   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8822
8823 #if 0 // debug spew
8824   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8825   {
8826         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8827         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8828         {
8829            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8830         }
8831   }
8832   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8833   {
8834         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8835         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8836         {
8837            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8838         }
8839   }
8840 #endif
8841
8842 #if VIEW_SIZE
8843   emitcode ("; shift left ", "result %d, left %d", size,
8844             AOP_SIZE (left));
8845 #endif
8846
8847   /* I suppose that the left size >= result size */
8848   if (shCount == 0)
8849   {
8850         _startLazyDPSEvaluation();
8851         while (size--)
8852         {
8853           movLeft2Result (left, size, result, size, 0);
8854         }
8855         _endLazyDPSEvaluation();
8856   }
8857   else if (shCount >= (size * 8))
8858   {
8859     _startLazyDPSEvaluation();
8860     while (size--)
8861     {
8862       aopPut (AOP (result), zero, size);
8863     }
8864     _endLazyDPSEvaluation();
8865   }
8866   else
8867   {
8868       switch (size)
8869         {
8870         case 1:
8871           genlshOne (result, left, shCount);
8872           break;
8873
8874         case 2:
8875           genlshTwo (result, left, shCount);
8876           break;
8877 #if 0
8878         case 4:
8879           genlshFour (result, left, shCount);
8880           break;
8881 #endif
8882         default:
8883           fprintf(stderr, "*** ack! mystery literal shift!\n");
8884           break;
8885         }
8886     }
8887   freeAsmop (left, NULL, ic, TRUE);
8888   freeAsmop (result, NULL, ic, TRUE);
8889   return TRUE;
8890 }
8891 #endif
8892
8893 /*-----------------------------------------------------------------*/
8894 /* genLeftShift - generates code for left shifting                 */
8895 /*-----------------------------------------------------------------*/
8896 static void
8897 genLeftShift (iCode * ic)
8898 {
8899   operand *left, *right, *result;
8900   int size, offset;
8901   char *l;
8902   symbol *tlbl, *tlbl1;
8903
8904   D (emitcode (";", "genLeftShift "););
8905
8906   right = IC_RIGHT (ic);
8907   left = IC_LEFT (ic);
8908   result = IC_RESULT (ic);
8909
8910   aopOp (right, ic, FALSE, FALSE);
8911
8912
8913 #ifdef BETTER_LITERAL_SHIFT
8914   /* if the shift count is known then do it
8915      as efficiently as possible */
8916   if (AOP_TYPE (right) == AOP_LIT)
8917     {
8918       if (genLeftShiftLiteral (left, right, result, ic))
8919       {
8920         return;
8921       }
8922     }
8923 #endif
8924
8925   /* shift count is unknown then we have to form
8926      a loop get the loop count in B : Note: we take
8927      only the lower order byte since shifting
8928      more that 32 bits make no sense anyway, ( the
8929      largest size of an object can be only 32 bits ) */
8930
8931   if (AOP_TYPE (right) == AOP_LIT)
8932   {
8933       /* Really should be handled by genLeftShiftLiteral,
8934        * but since I'm too lazy to fix that today, at least we can make
8935        * some small improvement.
8936        */
8937        emitcode("mov", "b,#!constbyte",
8938                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8939   }
8940   else
8941   {
8942       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8943       emitcode ("inc", "b");
8944   }
8945   freeAsmop (right, NULL, ic, TRUE);
8946   aopOp (left, ic, FALSE, FALSE);
8947   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8948
8949   /* now move the left to the result if they are not the
8950      same */
8951   if (!sameRegs (AOP (left), AOP (result)) &&
8952       AOP_SIZE (result) > 1)
8953     {
8954
8955       size = AOP_SIZE (result);
8956       offset = 0;
8957       _startLazyDPSEvaluation ();
8958       while (size--)
8959         {
8960           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8961           if (*l == '@' && (IS_AOP_PREG (result)))
8962             {
8963
8964               emitcode ("mov", "a,%s", l);
8965               aopPut (AOP (result), "a", offset);
8966             }
8967           else
8968             aopPut (AOP (result), l, offset);
8969           offset++;
8970         }
8971       _endLazyDPSEvaluation ();
8972     }
8973
8974   tlbl = newiTempLabel (NULL);
8975   size = AOP_SIZE (result);
8976   offset = 0;
8977   tlbl1 = newiTempLabel (NULL);
8978
8979   /* if it is only one byte then */
8980   if (size == 1)
8981     {
8982       symbol *tlbl1 = newiTempLabel (NULL);
8983
8984       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8985       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8986       emitcode ("", "!tlabeldef", tlbl->key + 100);
8987       emitcode ("add", "a,acc");
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
8996   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8997   emitcode ("", "!tlabeldef", tlbl->key + 100);
8998   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8999   emitcode ("add", "a,acc");
9000   aopPut (AOP (result), "a", offset++);
9001   _startLazyDPSEvaluation ();
9002   while (--size)
9003     {
9004       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9005       emitcode ("rlc", "a");
9006       aopPut (AOP (result), "a", offset++);
9007     }
9008   _endLazyDPSEvaluation ();
9009   reAdjustPreg (AOP (result));
9010
9011   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9012   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9013 release:
9014   freeAsmop (left, NULL, ic, TRUE);
9015   freeAsmop (result, NULL, ic, TRUE);
9016 }
9017
9018 #ifdef BETTER_LITERAL_SHIFT
9019 /*-----------------------------------------------------------------*/
9020 /* genrshOne - right shift a one byte quantity by known count      */
9021 /*-----------------------------------------------------------------*/
9022 static void
9023 genrshOne (operand * result, operand * left,
9024            int shCount, int sign)
9025 {
9026   D (emitcode (";", "genrshOne"););
9027   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9028 }
9029 #endif
9030
9031 #ifdef BETTER_LITERAL_SHIFT
9032 /*-----------------------------------------------------------------*/
9033 /* genrshTwo - right shift two bytes by known amount != 0          */
9034 /*-----------------------------------------------------------------*/
9035 static void
9036 genrshTwo (operand * result, operand * left,
9037            int shCount, int sign)
9038 {
9039   D (emitcode (";", "genrshTwo"););
9040
9041   /* if shCount >= 8 */
9042   if (shCount >= 8)
9043     {
9044       shCount -= 8;
9045       _startLazyDPSEvaluation();
9046       if (shCount)
9047       {
9048         shiftR1Left2Result (left, MSB16, result, LSB,
9049                             shCount, sign);
9050       }
9051       else
9052       {
9053         movLeft2Result (left, MSB16, result, LSB, sign);
9054       }
9055       addSign (result, MSB16, sign);
9056       _endLazyDPSEvaluation();
9057     }
9058
9059   /*  1 <= shCount <= 7 */
9060   else
9061   {
9062     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9063   }
9064 }
9065 #endif
9066
9067 /*-----------------------------------------------------------------*/
9068 /* shiftRLong - shift right one long from left to result           */
9069 /* offl = LSB or MSB16                                             */
9070 /*-----------------------------------------------------------------*/
9071 static void
9072 shiftRLong (operand * left, int offl,
9073             operand * result, int sign)
9074 {
9075   int isSameRegs=sameRegs(AOP(left),AOP(result));
9076
9077   if (isSameRegs && offl>1) {
9078     // we are in big trouble, but this shouldn't happen
9079     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9080   }
9081
9082   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9083
9084   if (offl==MSB16) {
9085     // shift is > 8
9086     if (sign) {
9087       emitcode ("rlc", "a");
9088       emitcode ("subb", "a,acc");
9089       emitcode ("xch", "a,%s",
9090                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9091     } else {
9092       aopPut (AOP(result), zero, MSB32);
9093     }
9094   }
9095
9096   if (!sign) {
9097     emitcode ("clr", "c");
9098   } else {
9099     emitcode ("mov", "c,acc.7");
9100   }
9101
9102   emitcode ("rrc", "a");
9103
9104   if (isSameRegs && offl==MSB16) {
9105     emitcode ("xch",
9106               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9107   } else {
9108     aopPut (AOP (result), "a", MSB32);
9109     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9110   }
9111
9112   emitcode ("rrc", "a");
9113   if (isSameRegs && offl==1) {
9114     emitcode ("xch", "a,%s",
9115               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9116   } else {
9117     aopPut (AOP (result), "a", MSB24);
9118     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9119   }
9120   emitcode ("rrc", "a");
9121   aopPut (AOP (result), "a", MSB16 - offl);
9122
9123   if (offl == LSB)
9124     {
9125       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9126       emitcode ("rrc", "a");
9127       aopPut (AOP (result), "a", LSB);
9128     }
9129 }
9130
9131 /*-----------------------------------------------------------------*/
9132 /* genrshFour - shift four byte by a known amount != 0             */
9133 /*-----------------------------------------------------------------*/
9134 static void
9135 genrshFour (operand * result, operand * left,
9136             int shCount, int sign)
9137 {
9138   D (emitcode (";", "genrshFour"););
9139
9140   /* if shifting more that 3 bytes */
9141   if (shCount >= 24)
9142     {
9143       shCount -= 24;
9144       _startLazyDPSEvaluation();
9145       if (shCount)
9146         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9147       else
9148         movLeft2Result (left, MSB32, result, LSB, sign);
9149       addSign (result, MSB16, sign);
9150       _endLazyDPSEvaluation();
9151     }
9152   else if (shCount >= 16)
9153     {
9154       shCount -= 16;
9155       _startLazyDPSEvaluation();
9156       if (shCount)
9157         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9158       else
9159         {
9160           movLeft2Result (left, MSB24, result, LSB, 0);
9161           movLeft2Result (left, MSB32, result, MSB16, sign);
9162         }
9163       addSign (result, MSB24, sign);
9164       _endLazyDPSEvaluation();
9165     }
9166   else if (shCount >= 8)
9167     {
9168       shCount -= 8;
9169       _startLazyDPSEvaluation();
9170       if (shCount == 1)
9171         {
9172             shiftRLong (left, MSB16, result, sign);
9173         }
9174       else if (shCount == 0)
9175         {
9176           movLeft2Result (left, MSB16, result, LSB, 0);
9177           movLeft2Result (left, MSB24, result, MSB16, 0);
9178           movLeft2Result (left, MSB32, result, MSB24, sign);
9179           addSign (result, MSB32, sign);
9180         }
9181       else
9182         {
9183           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9184           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9185           /* the last shift is signed */
9186           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9187           addSign (result, MSB32, sign);
9188         }
9189         _endLazyDPSEvaluation();
9190     }
9191   else
9192     {
9193         /* 1 <= shCount <= 7 */
9194       if (shCount <= 2)
9195         {
9196           shiftRLong (left, LSB, result, sign);
9197           if (shCount == 2)
9198             shiftRLong (result, LSB, result, sign);
9199         }
9200       else
9201         {
9202           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9203           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9204           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9205         }
9206     }
9207 }
9208
9209 #ifdef BETTER_LITERAL_SHIFT
9210 /*-----------------------------------------------------------------*/
9211 /* genRightShiftLiteral - right shifting by known count            */
9212 /*-----------------------------------------------------------------*/
9213 static bool
9214 genRightShiftLiteral (operand * left,
9215                       operand * right,
9216                       operand * result,
9217                       iCode * ic,
9218                       int sign)
9219 {
9220   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9221   int size;
9222
9223   size = getSize (operandType (result));
9224
9225   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9226
9227   /* We only handle certain easy cases so far. */
9228   if ((shCount != 0)
9229    && (shCount < (size * 8))
9230    && (size != 1)
9231    && (size != 2)
9232    && (size != 4))
9233   {
9234       D(emitcode (";", "genRightShiftLiteral wimping out"););
9235       return FALSE;
9236   }
9237
9238   freeAsmop (right, NULL, ic, TRUE);
9239
9240   aopOp (left, ic, FALSE, FALSE);
9241   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9242
9243 #if VIEW_SIZE
9244   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9245             AOP_SIZE (left));
9246 #endif
9247
9248   /* test the LEFT size !!! */
9249
9250   /* I suppose that the left size >= result size */
9251   if (shCount == 0)
9252   {
9253       size = getDataSize (result);
9254       _startLazyDPSEvaluation();
9255       while (size--)
9256       {
9257         movLeft2Result (left, size, result, size, 0);
9258       }
9259       _endLazyDPSEvaluation();
9260   }
9261   else if (shCount >= (size * 8))
9262     {
9263       if (sign)
9264       {
9265         /* get sign in acc.7 */
9266         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9267       }
9268       addSign (result, LSB, sign);
9269     }
9270   else
9271     {
9272       switch (size)
9273         {
9274         case 1:
9275           genrshOne (result, left, shCount, sign);
9276           break;
9277
9278         case 2:
9279           genrshTwo (result, left, shCount, sign);
9280           break;
9281 #if 1
9282         case 4:
9283           genrshFour (result, left, shCount, sign);
9284           break;
9285 #endif
9286         default:
9287           break;
9288         }
9289     }
9290   freeAsmop (left, NULL, ic, TRUE);
9291   freeAsmop (result, NULL, ic, TRUE);
9292
9293   return TRUE;
9294 }
9295 #endif
9296
9297 /*-----------------------------------------------------------------*/
9298 /* genSignedRightShift - right shift of signed number              */
9299 /*-----------------------------------------------------------------*/
9300 static void
9301 genSignedRightShift (iCode * ic)
9302 {
9303   operand *right, *left, *result;
9304   int size, offset;
9305   char *l;
9306   symbol *tlbl, *tlbl1;
9307
9308   D (emitcode (";", "genSignedRightShift "););
9309
9310   /* we do it the hard way put the shift count in b
9311      and loop thru preserving the sign */
9312
9313   right = IC_RIGHT (ic);
9314   left = IC_LEFT (ic);
9315   result = IC_RESULT (ic);
9316
9317   aopOp (right, ic, FALSE, FALSE);
9318
9319 #ifdef BETTER_LITERAL_SHIFT
9320   if (AOP_TYPE (right) == AOP_LIT)
9321     {
9322       if (genRightShiftLiteral (left, right, result, ic, 1))
9323       {
9324         return;
9325       }
9326     }
9327 #endif
9328   /* shift count is unknown then we have to form
9329      a loop get the loop count in B : Note: we take
9330      only the lower order byte since shifting
9331      more that 32 bits make no sense anyway, ( the
9332      largest size of an object can be only 32 bits ) */
9333
9334   if (AOP_TYPE (right) == AOP_LIT)
9335   {
9336       /* Really should be handled by genRightShiftLiteral,
9337        * but since I'm too lazy to fix that today, at least we can make
9338        * some small improvement.
9339        */
9340        emitcode("mov", "b,#!constbyte",
9341                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9342   }
9343   else
9344   {
9345         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9346         emitcode ("inc", "b");
9347   }
9348   freeAsmop (right, NULL, ic, TRUE);
9349   aopOp (left, ic, FALSE, FALSE);
9350   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9351
9352   /* now move the left to the result if they are not the
9353      same */
9354   if (!sameRegs (AOP (left), AOP (result)) &&
9355       AOP_SIZE (result) > 1)
9356     {
9357
9358       size = AOP_SIZE (result);
9359       offset = 0;
9360       _startLazyDPSEvaluation ();
9361       while (size--)
9362         {
9363           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9364           if (*l == '@' && IS_AOP_PREG (result))
9365             {
9366
9367               emitcode ("mov", "a,%s", l);
9368               aopPut (AOP (result), "a", offset);
9369             }
9370           else
9371             aopPut (AOP (result), l, offset);
9372           offset++;
9373         }
9374       _endLazyDPSEvaluation ();
9375     }
9376
9377   /* mov the highest order bit to OVR */
9378   tlbl = newiTempLabel (NULL);
9379   tlbl1 = newiTempLabel (NULL);
9380
9381   size = AOP_SIZE (result);
9382   offset = size - 1;
9383   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9384   emitcode ("rlc", "a");
9385   emitcode ("mov", "ov,c");
9386   /* if it is only one byte then */
9387   if (size == 1)
9388     {
9389       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9390       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9391       emitcode ("", "!tlabeldef", tlbl->key + 100);
9392       emitcode ("mov", "c,ov");
9393       emitcode ("rrc", "a");
9394       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9395       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9396       aopPut (AOP (result), "a", 0);
9397       goto release;
9398     }
9399
9400   reAdjustPreg (AOP (result));
9401   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9402   emitcode ("", "!tlabeldef", tlbl->key + 100);
9403   emitcode ("mov", "c,ov");
9404   _startLazyDPSEvaluation ();
9405   while (size--)
9406     {
9407       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9408       emitcode ("rrc", "a");
9409       aopPut (AOP (result), "a", offset--);
9410     }
9411   _endLazyDPSEvaluation ();
9412   reAdjustPreg (AOP (result));
9413   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9414   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9415
9416 release:
9417   freeAsmop (left, NULL, ic, TRUE);
9418   freeAsmop (result, NULL, ic, TRUE);
9419 }
9420
9421 /*-----------------------------------------------------------------*/
9422 /* genRightShift - generate code for right shifting                */
9423 /*-----------------------------------------------------------------*/
9424 static void
9425 genRightShift (iCode * ic)
9426 {
9427   operand *right, *left, *result;
9428   sym_link *letype;
9429   int size, offset;
9430   char *l;
9431   symbol *tlbl, *tlbl1;
9432
9433   D (emitcode (";", "genRightShift "););
9434
9435   /* if signed then we do it the hard way preserve the
9436      sign bit moving it inwards */
9437   letype = getSpec (operandType (IC_LEFT (ic)));
9438
9439   if (!SPEC_USIGN (letype))
9440     {
9441       genSignedRightShift (ic);
9442       return;
9443     }
9444
9445   /* signed & unsigned types are treated the same : i.e. the
9446      signed is NOT propagated inwards : quoting from the
9447      ANSI - standard : "for E1 >> E2, is equivalent to division
9448      by 2**E2 if unsigned or if it has a non-negative value,
9449      otherwise the result is implementation defined ", MY definition
9450      is that the sign does not get propagated */
9451
9452   right = IC_RIGHT (ic);
9453   left = IC_LEFT (ic);
9454   result = IC_RESULT (ic);
9455
9456   aopOp (right, ic, FALSE, FALSE);
9457
9458 #ifdef BETTER_LITERAL_SHIFT
9459   /* if the shift count is known then do it
9460      as efficiently as possible */
9461   if (AOP_TYPE (right) == AOP_LIT)
9462     {
9463       if (genRightShiftLiteral (left, right, result, ic, 0))
9464       {
9465         return;
9466       }
9467     }
9468 #endif
9469
9470   /* shift count is unknown then we have to form
9471      a loop get the loop count in B : Note: we take
9472      only the lower order byte since shifting
9473      more that 32 bits make no sense anyway, ( the
9474      largest size of an object can be only 32 bits ) */
9475
9476   if (AOP_TYPE (right) == AOP_LIT)
9477   {
9478       /* Really should be handled by genRightShiftLiteral,
9479        * but since I'm too lazy to fix that today, at least we can make
9480        * some small improvement.
9481        */
9482        emitcode("mov", "b,#!constbyte",
9483                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9484   }
9485   else
9486   {
9487       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9488       emitcode ("inc", "b");
9489   }
9490   freeAsmop (right, NULL, ic, TRUE);
9491   aopOp (left, ic, FALSE, FALSE);
9492   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9493
9494   /* now move the left to the result if they are not the
9495      same */
9496   if (!sameRegs (AOP (left), AOP (result)) &&
9497       AOP_SIZE (result) > 1)
9498     {
9499
9500       size = AOP_SIZE (result);
9501       offset = 0;
9502       _startLazyDPSEvaluation ();
9503       while (size--)
9504         {
9505           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9506           if (*l == '@' && IS_AOP_PREG (result))
9507             {
9508
9509               emitcode ("mov", "a,%s", l);
9510               aopPut (AOP (result), "a", offset);
9511             }
9512           else
9513             aopPut (AOP (result), l, offset);
9514           offset++;
9515         }
9516       _endLazyDPSEvaluation ();
9517     }
9518
9519   tlbl = newiTempLabel (NULL);
9520   tlbl1 = newiTempLabel (NULL);
9521   size = AOP_SIZE (result);
9522   offset = size - 1;
9523
9524   /* if it is only one byte then */
9525   if (size == 1)
9526     {
9527       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9528       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9529       emitcode ("", "!tlabeldef", tlbl->key + 100);
9530       CLRC;
9531       emitcode ("rrc", "a");
9532       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9533       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9534       aopPut (AOP (result), "a", 0);
9535       goto release;
9536     }
9537
9538   reAdjustPreg (AOP (result));
9539   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9540   emitcode ("", "!tlabeldef", tlbl->key + 100);
9541   CLRC;
9542   _startLazyDPSEvaluation ();
9543   while (size--)
9544     {
9545       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9546       emitcode ("rrc", "a");
9547       aopPut (AOP (result), "a", offset--);
9548     }
9549   _endLazyDPSEvaluation ();
9550   reAdjustPreg (AOP (result));
9551
9552   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9553   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9554
9555 release:
9556   freeAsmop (left, NULL, ic, TRUE);
9557   freeAsmop (result, NULL, ic, TRUE);
9558 }
9559
9560
9561 /*-----------------------------------------------------------------*/
9562 /* emitPtrByteGet - emits code to get a byte into A through a      */
9563 /*                  pointer register (R0, R1, or DPTR). The        */
9564 /*                  original value of A can be preserved in B.     */
9565 /*-----------------------------------------------------------------*/
9566 static void
9567 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9568 {
9569   switch (p_type)
9570     {
9571     case IPOINTER:
9572     case POINTER:
9573       if (preserveAinB)
9574         emitcode ("mov", "b,a");
9575       emitcode ("mov", "a,@%s", rname);
9576       break;
9577
9578     case PPOINTER:
9579       if (preserveAinB)
9580         emitcode ("mov", "b,a");
9581       emitcode ("movx", "a,@%s", rname);
9582       break;
9583
9584     case FPOINTER:
9585       if (preserveAinB)
9586         emitcode ("mov", "b,a");
9587       emitcode ("movx", "a,@dptr");
9588       break;
9589
9590     case CPOINTER:
9591       if (preserveAinB)
9592         emitcode ("mov", "b,a");
9593       emitcode ("clr", "a");
9594       emitcode ("movc", "a,@a+dptr");
9595       break;
9596
9597     case GPOINTER:
9598       if (preserveAinB)
9599         {
9600           emitcode ("push", "b");
9601           emitcode ("push", "acc");
9602         }
9603       emitcode ("lcall", "__gptrget");
9604       if (preserveAinB)
9605         emitcode ("pop", "b");
9606       break;
9607     }
9608 }
9609
9610 /*-----------------------------------------------------------------*/
9611 /* emitPtrByteSet - emits code to set a byte from src through a    */
9612 /*                  pointer register (R0, R1, or DPTR).            */
9613 /*-----------------------------------------------------------------*/
9614 static void
9615 emitPtrByteSet (char *rname, int p_type, char *src)
9616 {
9617   switch (p_type)
9618     {
9619     case IPOINTER:
9620     case POINTER:
9621       if (*src=='@')
9622         {
9623           MOVA (src);
9624           emitcode ("mov", "@%s,a", rname);
9625         }
9626       else
9627         emitcode ("mov", "@%s,%s", rname, src);
9628       break;
9629
9630     case PPOINTER:
9631       MOVA (src);
9632       emitcode ("movx", "@%s,a", rname);
9633       break;
9634
9635     case FPOINTER:
9636       MOVA (src);
9637       emitcode ("movx", "@dptr,a");
9638       break;
9639
9640     case GPOINTER:
9641       MOVA (src);
9642       emitcode ("lcall", "__gptrput");
9643       break;
9644     }
9645 }
9646
9647 /*-----------------------------------------------------------------*/
9648 /* genUnpackBits - generates code for unpacking bits               */
9649 /*-----------------------------------------------------------------*/
9650 static void
9651 genUnpackBits (operand * result, char *rname, int ptype)
9652 {
9653   int offset = 0;       /* result byte offset */
9654   int rsize;            /* result size */
9655   int rlen = 0;         /* remaining bitfield length */
9656   sym_link *etype;      /* bitfield type information */
9657   int blen;             /* bitfield length */
9658   int bstr;             /* bitfield starting bit within byte */
9659
9660   D(emitcode (";     genUnpackBits",""));
9661
9662   etype = getSpec (operandType (result));
9663   rsize = getSize (operandType (result));
9664   blen = SPEC_BLEN (etype);
9665   bstr = SPEC_BSTR (etype);
9666
9667   /* If the bitfield length is less than a byte */
9668   if (blen < 8)
9669     {
9670       emitPtrByteGet (rname, ptype, FALSE);
9671       AccRol (8 - bstr);
9672       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9673       if (!SPEC_USIGN (etype))
9674         {
9675           /* signed bitfield */
9676           symbol *tlbl = newiTempLabel (NULL);
9677
9678           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9679           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9680           emitcode ("", "%05d$:", tlbl->key + 100);
9681         }
9682       aopPut (AOP (result), "a", offset++);
9683       goto finish;
9684     }
9685
9686   /* Bit field did not fit in a byte. Copy all
9687      but the partial byte at the end.  */
9688   for (rlen=blen;rlen>=8;rlen-=8)
9689     {
9690       emitPtrByteGet (rname, ptype, FALSE);
9691       aopPut (AOP (result), "a", offset++);
9692       if (rlen>8)
9693         emitcode ("inc", "%s", rname);
9694     }
9695
9696   /* Handle the partial byte at the end */
9697   if (rlen)
9698     {
9699       emitPtrByteGet (rname, ptype, FALSE);
9700       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9701       if (!SPEC_USIGN (etype))
9702         {
9703           /* signed bitfield */
9704           symbol *tlbl = newiTempLabel (NULL);
9705
9706           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9707           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9708           emitcode ("", "%05d$:", tlbl->key + 100);
9709         }
9710       aopPut (AOP (result), "a", offset++);
9711     }
9712
9713 finish:
9714   if (offset < rsize)
9715     {
9716       char *source;
9717
9718       if (SPEC_USIGN (etype))
9719         source = zero;
9720       else
9721         {
9722           /* signed bitfield: sign extension with 0x00 or 0xff */
9723           emitcode ("rlc", "a");
9724           emitcode ("subb", "a,acc");
9725
9726           source = "a";
9727         }
9728       rsize -= offset;
9729       while (rsize--)
9730         aopPut (AOP (result), source, offset++);
9731     }
9732 }
9733
9734
9735 /*-----------------------------------------------------------------*/
9736 /* genDataPointerGet - generates code when ptr offset is known     */
9737 /*-----------------------------------------------------------------*/
9738 static void
9739 genDataPointerGet (operand * left,
9740                    operand * result,
9741                    iCode * ic)
9742 {
9743   char *l;
9744   char buff[256];
9745   int size, offset = 0;
9746   aopOp (result, ic, TRUE, FALSE);
9747
9748   /* get the string representation of the name */
9749   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9750   size = AOP_SIZE (result);
9751   _startLazyDPSEvaluation ();
9752   while (size--)
9753     {
9754         if (offset)
9755         {
9756             SNPRINTF (buff, sizeof(buff),
9757                       "(%s + %d)", l + 1, offset);
9758         }
9759         else
9760         {
9761             SNPRINTF (buff, sizeof(buff),
9762                       "%s", l + 1);
9763         }
9764       aopPut (AOP (result), buff, offset++);
9765     }
9766   _endLazyDPSEvaluation ();
9767
9768   freeAsmop (left, NULL, ic, TRUE);
9769   freeAsmop (result, NULL, ic, TRUE);
9770 }
9771
9772 /*-----------------------------------------------------------------*/
9773 /* genNearPointerGet - emitcode for near pointer fetch             */
9774 /*-----------------------------------------------------------------*/
9775 static void
9776 genNearPointerGet (operand * left,
9777                    operand * result,
9778                    iCode * ic,
9779                    iCode *pi)
9780 {
9781   asmop *aop = NULL;
9782   regs *preg;
9783   char *rname;
9784   sym_link *rtype, *retype, *letype;
9785   sym_link *ltype = operandType (left);
9786   char buff[80];
9787
9788   rtype = operandType (result);
9789   retype = getSpec (rtype);
9790   letype = getSpec (ltype);
9791
9792   aopOp (left, ic, FALSE, FALSE);
9793
9794   /* if left is rematerialisable and
9795      result is not bitfield variable type and
9796      the left is pointer to data space i.e
9797      lower 128 bytes of space */
9798   if (AOP_TYPE (left) == AOP_IMMD &&
9799       !IS_BITFIELD (retype) &&
9800       !IS_BITFIELD (letype) &&
9801       DCL_TYPE (ltype) == POINTER)
9802     {
9803       genDataPointerGet (left, result, ic);
9804       return;
9805     }
9806
9807   /* if the value is already in a pointer register
9808      then don't need anything more */
9809   if (!AOP_INPREG (AOP (left)))
9810     {
9811       /* otherwise get a free pointer register */
9812       aop = newAsmop (0);
9813       preg = getFreePtr (ic, &aop, FALSE);
9814       emitcode ("mov", "%s,%s",
9815                 preg->name,
9816                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9817       rname = preg->name;
9818     }
9819   else
9820     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9821
9822   freeAsmop (left, NULL, ic, TRUE);
9823   aopOp (result, ic, FALSE, FALSE);
9824
9825   /* if bitfield then unpack the bits */
9826   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9827     genUnpackBits (result, rname, POINTER);
9828   else
9829     {
9830       /* we have can just get the values */
9831       int size = AOP_SIZE (result);
9832       int offset = 0;
9833
9834       while (size--)
9835         {
9836           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9837             {
9838
9839               emitcode ("mov", "a,@%s", rname);
9840               aopPut (AOP (result), "a", offset);
9841             }
9842           else
9843             {
9844               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9845               aopPut (AOP (result), buff, offset);
9846             }
9847           offset++;
9848           if (size || pi)
9849             {
9850                 emitcode ("inc", "%s", rname);
9851             }
9852         }
9853     }
9854
9855   /* now some housekeeping stuff */
9856   if (aop)
9857     {
9858       /* we had to allocate for this iCode */
9859       if (pi) { /* post increment present */
9860         aopPut(AOP ( left ),rname,0);
9861       }
9862       freeAsmop (NULL, aop, ic, TRUE);
9863     }
9864   else
9865     {
9866       /* we did not allocate which means left
9867          already in a pointer register, then
9868          if size > 0 && this could be used again
9869          we have to point it back to where it
9870          belongs */
9871       if (AOP_SIZE (result) > 1 &&
9872           !OP_SYMBOL (left)->remat &&
9873           (OP_SYMBOL (left)->liveTo > ic->seq ||
9874            ic->depth) &&
9875           !pi)
9876         {
9877           int size = AOP_SIZE (result) - 1;
9878           while (size--)
9879             emitcode ("dec", "%s", rname);
9880         }
9881     }
9882
9883   /* done */
9884   freeAsmop (result, NULL, ic, TRUE);
9885   if (pi) pi->generated = 1;
9886 }
9887
9888 /*-----------------------------------------------------------------*/
9889 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9890 /*-----------------------------------------------------------------*/
9891 static void
9892 genPagedPointerGet (operand * left,
9893                     operand * result,
9894                     iCode * ic,
9895                     iCode * pi)
9896 {
9897   asmop *aop = NULL;
9898   regs *preg;
9899   char *rname;
9900   sym_link *rtype, *retype, *letype;
9901
9902   rtype = operandType (result);
9903   retype = getSpec (rtype);
9904   letype = getSpec (operandType (left));
9905   aopOp (left, ic, FALSE, FALSE);
9906
9907   /* if the value is already in a pointer register
9908      then don't need anything more */
9909   if (!AOP_INPREG (AOP (left)))
9910     {
9911       /* otherwise get a free pointer register */
9912       aop = newAsmop (0);
9913       preg = getFreePtr (ic, &aop, FALSE);
9914       emitcode ("mov", "%s,%s",
9915                 preg->name,
9916                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9917       rname = preg->name;
9918     }
9919   else
9920     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9921
9922   freeAsmop (left, NULL, ic, TRUE);
9923   aopOp (result, ic, FALSE, FALSE);
9924
9925   /* if bitfield then unpack the bits */
9926   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9927     genUnpackBits (result, rname, PPOINTER);
9928   else
9929     {
9930       /* we have can just get the values */
9931       int size = AOP_SIZE (result);
9932       int offset = 0;
9933
9934       while (size--)
9935         {
9936
9937           emitcode ("movx", "a,@%s", rname);
9938           aopPut (AOP (result), "a", offset);
9939
9940           offset++;
9941
9942           if (size || pi)
9943             emitcode ("inc", "%s", rname);
9944         }
9945     }
9946
9947   /* now some housekeeping stuff */
9948   if (aop)
9949     {
9950       /* we had to allocate for this iCode */
9951       if (pi) aopPut ( AOP (left), rname, 0);
9952       freeAsmop (NULL, aop, ic, TRUE);
9953     }
9954   else
9955     {
9956       /* we did not allocate which means left
9957          already in a pointer register, then
9958          if size > 0 && this could be used again
9959          we have to point it back to where it
9960          belongs */
9961       if (AOP_SIZE (result) > 1 &&
9962           !OP_SYMBOL (left)->remat &&
9963           (OP_SYMBOL (left)->liveTo > ic->seq ||
9964            ic->depth) &&
9965           !pi)
9966         {
9967           int size = AOP_SIZE (result) - 1;
9968           while (size--)
9969             emitcode ("dec", "%s", rname);
9970         }
9971     }
9972
9973   /* done */
9974   freeAsmop (result, NULL, ic, TRUE);
9975   if (pi) pi->generated = 1;
9976 }
9977
9978 /*-----------------------------------------------------------------*/
9979 /* genFarPointerGet - gget value from far space                    */
9980 /*-----------------------------------------------------------------*/
9981 static void
9982 genFarPointerGet (operand * left,
9983                   operand * result, iCode * ic, iCode *pi)
9984 {
9985     int size, offset, dopi=1;
9986   sym_link *retype = getSpec (operandType (result));
9987   sym_link *letype = getSpec (operandType (left));
9988   D (emitcode (";", "genFarPointerGet"););
9989
9990   aopOp (left, ic, FALSE, FALSE);
9991
9992   /* if the operand is already in dptr
9993      then we do nothing else we move the value to dptr */
9994   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9995     {
9996       /* if this is remateriazable */
9997       if (AOP_TYPE (left) == AOP_IMMD)
9998         {
9999           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10000         }
10001       else
10002         {
10003           /* we need to get it byte by byte */
10004           _startLazyDPSEvaluation ();
10005           if (AOP_TYPE (left) != AOP_DPTR)
10006             {
10007               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10008               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10009               if (options.model == MODEL_FLAT24)
10010                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10011             }
10012           else
10013             {
10014               /* We need to generate a load to DPTR indirect through DPTR. */
10015               D (emitcode (";", "genFarPointerGet -- indirection special case."););
10016               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10017               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10018               if (options.model == MODEL_FLAT24)
10019                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10020               emitcode ("pop", "dph");
10021               emitcode ("pop", "dpl");
10022               dopi =0;
10023             }
10024           _endLazyDPSEvaluation ();
10025         }
10026     }
10027   /* so dptr know contains the address */
10028   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10029
10030   /* if bit then unpack */
10031   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10032       if (AOP_INDPTRn(left)) {
10033           genSetDPTR(AOP(left)->aopu.dptr);
10034       }
10035       genUnpackBits (result, "dptr", FPOINTER);
10036       if (AOP_INDPTRn(left)) {
10037           genSetDPTR(0);
10038       }
10039   } else
10040     {
10041       size = AOP_SIZE (result);
10042       offset = 0;
10043
10044       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10045           while (size--) {
10046               genSetDPTR(AOP(left)->aopu.dptr);
10047               emitcode ("movx", "a,@dptr");
10048               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10049                   emitcode ("inc", "dptr");
10050               genSetDPTR (0);
10051               aopPut (AOP (result), "a", offset++);
10052           }
10053       } else {
10054           _startLazyDPSEvaluation ();
10055           while (size--) {
10056               if (AOP_INDPTRn(left)) {
10057                   genSetDPTR(AOP(left)->aopu.dptr);
10058               } else {
10059                   genSetDPTR (0);
10060               }
10061               _flushLazyDPS ();
10062
10063               emitcode ("movx", "a,@dptr");
10064               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10065                   emitcode ("inc", "dptr");
10066
10067               aopPut (AOP (result), "a", offset++);
10068           }
10069           _endLazyDPSEvaluation ();
10070       }
10071     }
10072   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10073       if (!AOP_INDPTRn(left)) {
10074           _startLazyDPSEvaluation ();
10075           aopPut ( AOP (left), "dpl", 0);
10076           aopPut ( AOP (left), "dph", 1);
10077           if (options.model == MODEL_FLAT24)
10078               aopPut ( AOP (left), "dpx", 2);
10079           _endLazyDPSEvaluation ();
10080       }
10081     pi->generated = 1;
10082   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10083              AOP_SIZE(result) > 1 &&
10084              IS_SYMOP(left) &&
10085              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10086
10087       size = AOP_SIZE (result) - 1;
10088       if (AOP_INDPTRn(left)) {
10089           genSetDPTR(AOP(left)->aopu.dptr);
10090       }
10091       while (size--) emitcode ("lcall","__decdptr");
10092       if (AOP_INDPTRn(left)) {
10093           genSetDPTR(0);
10094       }
10095   }
10096
10097   freeAsmop (left, NULL, ic, TRUE);
10098   freeAsmop (result, NULL, ic, TRUE);
10099 }
10100
10101 /*-----------------------------------------------------------------*/
10102 /* genCodePointerGet - get value from code space                  */
10103 /*-----------------------------------------------------------------*/
10104 static void
10105 genCodePointerGet (operand * left,
10106                     operand * result, iCode * ic, iCode *pi)
10107 {
10108   int size, offset, dopi=1;
10109   sym_link *retype = getSpec (operandType (result));
10110
10111   aopOp (left, ic, FALSE, FALSE);
10112
10113   /* if the operand is already in dptr
10114      then we do nothing else we move the value to dptr */
10115   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10116     {
10117       /* if this is remateriazable */
10118       if (AOP_TYPE (left) == AOP_IMMD)
10119         {
10120           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10121         }
10122       else
10123         {                       /* we need to get it byte by byte */
10124           _startLazyDPSEvaluation ();
10125           if (AOP_TYPE (left) != AOP_DPTR)
10126             {
10127               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10128               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10129               if (options.model == MODEL_FLAT24)
10130                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10131             }
10132           else
10133             {
10134               /* We need to generate a load to DPTR indirect through DPTR. */
10135               D (emitcode (";", "gencodePointerGet -- indirection special case."););
10136               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10137               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10138               if (options.model == MODEL_FLAT24)
10139                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10140               emitcode ("pop", "dph");
10141               emitcode ("pop", "dpl");
10142               dopi=0;
10143             }
10144           _endLazyDPSEvaluation ();
10145         }
10146     }
10147   /* so dptr know contains the address */
10148   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10149
10150   /* if bit then unpack */
10151   if (IS_BITFIELD (retype)) {
10152       if (AOP_INDPTRn(left)) {
10153           genSetDPTR(AOP(left)->aopu.dptr);
10154       }
10155       genUnpackBits (result, "dptr", CPOINTER);
10156       if (AOP_INDPTRn(left)) {
10157           genSetDPTR(0);
10158       }
10159   } else
10160     {
10161       size = AOP_SIZE (result);
10162       offset = 0;
10163       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10164           while (size--) {
10165               genSetDPTR(AOP(left)->aopu.dptr);
10166               emitcode ("clr", "a");
10167               emitcode ("movc", "a,@a+dptr");
10168               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10169                   emitcode ("inc", "dptr");
10170               genSetDPTR (0);
10171               aopPut (AOP (result), "a", offset++);
10172           }
10173       } else {
10174           _startLazyDPSEvaluation ();
10175           while (size--)
10176               {
10177                   if (AOP_INDPTRn(left)) {
10178                       genSetDPTR(AOP(left)->aopu.dptr);
10179                   } else {
10180                       genSetDPTR (0);
10181                   }
10182                   _flushLazyDPS ();
10183
10184                   emitcode ("clr", "a");
10185                   emitcode ("movc", "a,@a+dptr");
10186                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10187                       emitcode ("inc", "dptr");
10188                   aopPut (AOP (result), "a", offset++);
10189               }
10190           _endLazyDPSEvaluation ();
10191       }
10192     }
10193   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10194       if (!AOP_INDPTRn(left)) {
10195           _startLazyDPSEvaluation ();
10196
10197           aopPut ( AOP (left), "dpl", 0);
10198           aopPut ( AOP (left), "dph", 1);
10199           if (options.model == MODEL_FLAT24)
10200               aopPut ( AOP (left), "dpx", 2);
10201
10202           _endLazyDPSEvaluation ();
10203       }
10204       pi->generated = 1;
10205   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10206              AOP_SIZE(result) > 1 &&
10207              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10208
10209       size = AOP_SIZE (result) - 1;
10210       if (AOP_INDPTRn(left)) {
10211           genSetDPTR(AOP(left)->aopu.dptr);
10212       }
10213       while (size--) emitcode ("lcall","__decdptr");
10214       if (AOP_INDPTRn(left)) {
10215           genSetDPTR(0);
10216       }
10217   }
10218
10219   freeAsmop (left, NULL, ic, TRUE);
10220   freeAsmop (result, NULL, ic, TRUE);
10221 }
10222
10223 /*-----------------------------------------------------------------*/
10224 /* genGenPointerGet - gget value from generic pointer space        */
10225 /*-----------------------------------------------------------------*/
10226 static void
10227 genGenPointerGet (operand * left,
10228                   operand * result, iCode * ic, iCode * pi)
10229 {
10230   int size, offset;
10231   sym_link *retype = getSpec (operandType (result));
10232   sym_link *letype = getSpec (operandType (left));
10233
10234   D (emitcode (";", "genGenPointerGet "); );
10235
10236   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10237
10238   /* if the operand is already in dptr
10239      then we do nothing else we move the value to dptr */
10240   if (AOP_TYPE (left) != AOP_STR)
10241     {
10242       /* if this is rematerializable */
10243       if (AOP_TYPE (left) == AOP_IMMD)
10244         {
10245           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10246           if (AOP(left)->aopu.aop_immd.from_cast_remat)
10247             {
10248               MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10249             }
10250           else
10251             {
10252               emitcode ("mov", "b,#%d", pointerCode (retype));
10253             }
10254         }
10255       else
10256         {                       /* we need to get it byte by byte */
10257           _startLazyDPSEvaluation ();
10258           emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10259           emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10260           if (options.model == MODEL_FLAT24) {
10261               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10262               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10263           } else {
10264               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10265           }
10266           _endLazyDPSEvaluation ();
10267         }
10268     }
10269
10270   /* so dptr-b now contains the address */
10271   _G.bInUse++;
10272   aopOp (result, ic, FALSE, TRUE);
10273   _G.bInUse--;
10274
10275   /* if bit then unpack */
10276   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10277   {
10278     genUnpackBits (result, "dptr", GPOINTER);
10279   }
10280   else
10281     {
10282         size = AOP_SIZE (result);
10283         offset = 0;
10284
10285         while (size--)
10286         {
10287             if (size)
10288             {
10289                 // Get two bytes at a time, results in _AP & A.
10290                 // dptr will be incremented ONCE by __gptrgetWord.
10291                 //
10292                 // Note: any change here must be coordinated
10293                 // with the implementation of __gptrgetWord
10294                 // in device/lib/_gptrget.c
10295                 emitcode ("lcall", "__gptrgetWord");
10296                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10297                 aopPut (AOP (result), "a", offset++);
10298                 size--;
10299             }
10300             else
10301             {
10302                 // Only one byte to get.
10303                 emitcode ("lcall", "__gptrget");
10304                 aopPut (AOP (result), "a", offset++);
10305             }
10306
10307             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10308             {
10309                 emitcode ("inc", "dptr");
10310             }
10311         }
10312     }
10313
10314   if (pi && AOP_TYPE (left) != AOP_IMMD) {
10315     _startLazyDPSEvaluation ();
10316
10317     aopPut ( AOP (left), "dpl", 0);
10318     aopPut ( AOP (left), "dph", 1);
10319     if (options.model == MODEL_FLAT24) {
10320         aopPut ( AOP (left), "dpx", 2);
10321         aopPut ( AOP (left), "b", 3);
10322     } else  aopPut ( AOP (left), "b", 2);
10323
10324     _endLazyDPSEvaluation ();
10325
10326     pi->generated = 1;
10327   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10328              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10329
10330       size = AOP_SIZE (result) - 1;
10331       while (size--) emitcode ("lcall","__decdptr");
10332   }
10333
10334   freeAsmop (left, NULL, ic, TRUE);
10335   freeAsmop (result, NULL, ic, TRUE);
10336 }
10337
10338 /*-----------------------------------------------------------------*/
10339 /* genPointerGet - generate code for pointer get                   */
10340 /*-----------------------------------------------------------------*/
10341 static void
10342 genPointerGet (iCode * ic, iCode *pi)
10343 {
10344   operand *left, *result;
10345   sym_link *type, *etype;
10346   int p_type;
10347
10348   D (emitcode (";", "genPointerGet ");
10349     );
10350
10351   left = IC_LEFT (ic);
10352   result = IC_RESULT (ic);
10353
10354   /* depending on the type of pointer we need to
10355      move it to the correct pointer register */
10356   type = operandType (left);
10357   etype = getSpec (type);
10358   /* if left is of type of pointer then it is simple */
10359   if (IS_PTR (type) && !IS_FUNC (type->next))
10360     p_type = DCL_TYPE (type);
10361   else
10362     {
10363       /* we have to go by the storage class */
10364       p_type = PTR_TYPE (SPEC_OCLS (etype));
10365     }
10366   /* special case when cast remat */
10367   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10368       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10369     {
10370       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10371       type = operandType (left);
10372       p_type = DCL_TYPE (type);
10373     }
10374   /* now that we have the pointer type we assign
10375      the pointer values */
10376   switch (p_type)
10377     {
10378
10379     case POINTER:
10380     case IPOINTER:
10381       genNearPointerGet (left, result, ic, pi);
10382       break;
10383
10384     case PPOINTER:
10385       genPagedPointerGet (left, result, ic, pi);
10386       break;
10387
10388     case FPOINTER:
10389       genFarPointerGet (left, result, ic, pi);
10390       break;
10391
10392     case CPOINTER:
10393       genCodePointerGet (left, result, ic, pi);
10394       break;
10395
10396     case GPOINTER:
10397       genGenPointerGet (left, result, ic, pi);
10398       break;
10399     }
10400
10401 }
10402
10403 /*-----------------------------------------------------------------*/
10404 /* genPackBits - generates code for packed bit storage             */
10405 /*-----------------------------------------------------------------*/
10406 static void
10407 genPackBits (sym_link * etype,
10408              operand * right,
10409              char *rname, int p_type)
10410 {
10411   int offset = 0;       /* source byte offset */
10412   int rlen = 0;         /* remaining bitfield length */
10413   int blen;             /* bitfield length */
10414   int bstr;             /* bitfield starting bit within byte */
10415   int litval;           /* source literal value (if AOP_LIT) */
10416   unsigned char mask;   /* bitmask within current byte */
10417
10418   D(emitcode (";     genPackBits",""));
10419
10420   blen = SPEC_BLEN (etype);
10421   bstr = SPEC_BSTR (etype);
10422
10423   /* If the bitfield length is less than a byte */
10424   if (blen < 8)
10425     {
10426       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10427               (unsigned char) (0xFF >> (8 - bstr)));
10428
10429       if (AOP_TYPE (right) == AOP_LIT)
10430         {
10431           /* Case with a bitfield length <8 and literal source
10432           */
10433           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10434           litval <<= bstr;
10435           litval &= (~mask) & 0xff;
10436           emitPtrByteGet (rname, p_type, FALSE);
10437           if ((mask|litval)!=0xff)
10438             emitcode ("anl","a,#!constbyte", mask);
10439           if (litval)
10440             emitcode ("orl","a,#!constbyte", litval);
10441         }
10442       else
10443         {
10444           if ((blen==1) && (p_type!=GPOINTER))
10445             {
10446               /* Case with a bitfield length == 1 and no generic pointer
10447               */
10448               if (AOP_TYPE (right) == AOP_CRY)
10449                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10450               else
10451                 {
10452                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10453                   emitcode ("rrc","a");
10454                 }
10455               emitPtrByteGet (rname, p_type, FALSE);
10456               emitcode ("mov","acc.%d,c",bstr);
10457             }
10458           else
10459             {
10460               /* Case with a bitfield length < 8 and arbitrary source
10461               */
10462               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10463               /* shift and mask source value */
10464               AccLsh (bstr);
10465               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10466
10467               /* transfer A to B and get next byte */
10468               emitPtrByteGet (rname, p_type, TRUE);
10469
10470               emitcode ("anl", "a,#!constbyte", mask);
10471               emitcode ("orl", "a,b");
10472               if (p_type == GPOINTER)
10473                 emitcode ("pop", "b");
10474            }
10475         }
10476
10477       emitPtrByteSet (rname, p_type, "a");
10478       return;
10479     }
10480
10481   /* Bit length is greater than 7 bits. In this case, copy  */
10482   /* all except the partial byte at the end                 */
10483   for (rlen=blen;rlen>=8;rlen-=8)
10484     {
10485       emitPtrByteSet (rname, p_type,
10486                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10487       if (rlen>8)
10488         emitcode ("inc", "%s", rname);
10489     }
10490
10491   /* If there was a partial byte at the end */
10492   if (rlen)
10493     {
10494       mask = (((unsigned char) -1 << rlen) & 0xff);
10495
10496       if (AOP_TYPE (right) == AOP_LIT)
10497         {
10498           /* Case with partial byte and literal source
10499           */
10500           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10501           litval >>= (blen-rlen);
10502           litval &= (~mask) & 0xff;
10503           emitPtrByteGet (rname, p_type, FALSE);
10504           if ((mask|litval)!=0xff)
10505             emitcode ("anl","a,#!constbyte", mask);
10506           if (litval)
10507             emitcode ("orl","a,#!constbyte", litval);
10508         }
10509       else
10510         {
10511           /* Case with partial byte and arbitrary source
10512           */
10513           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10514           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10515
10516           /* transfer A to B and get next byte */
10517           emitPtrByteGet (rname, p_type, TRUE);
10518
10519           emitcode ("anl", "a,#!constbyte", mask);
10520           emitcode ("orl", "a,b");
10521           if (p_type == GPOINTER)
10522             emitcode ("pop", "b");
10523         }
10524       emitPtrByteSet (rname, p_type, "a");
10525     }
10526
10527 }
10528
10529
10530 /*-----------------------------------------------------------------*/
10531 /* genDataPointerSet - remat pointer to data space                 */
10532 /*-----------------------------------------------------------------*/
10533 static void
10534 genDataPointerSet (operand * right,
10535                    operand * result,
10536                    iCode * ic)
10537 {
10538   int size, offset = 0;
10539   char *l, buff[256];
10540
10541   aopOp (right, ic, FALSE, FALSE);
10542
10543   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10544   size = AOP_SIZE (right);
10545   while (size--)
10546     {
10547       if (offset)
10548         {
10549             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10550         }
10551       else
10552         {
10553             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10554         }
10555
10556       emitcode ("mov", "%s,%s", buff,
10557                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10558     }
10559
10560   freeAsmop (right, NULL, ic, TRUE);
10561   freeAsmop (result, NULL, ic, TRUE);
10562 }
10563
10564 /*-----------------------------------------------------------------*/
10565 /* genNearPointerSet - emitcode for near pointer put                */
10566 /*-----------------------------------------------------------------*/
10567 static void
10568 genNearPointerSet (operand * right,
10569                    operand * result,
10570                    iCode * ic,
10571                    iCode * pi)
10572 {
10573   asmop *aop = NULL;
10574   char *rname, *l;
10575   sym_link *retype, *letype;
10576   sym_link *ptype = operandType (result);
10577
10578   retype = getSpec (operandType (right));
10579   letype = getSpec (ptype);
10580
10581   aopOp (result, ic, FALSE, FALSE);
10582
10583   /* if the result is rematerializable &
10584      in data space & not a bit variable */
10585   if (AOP_TYPE (result) == AOP_IMMD &&
10586       DCL_TYPE (ptype) == POINTER &&
10587       !IS_BITVAR (retype) &&
10588       !IS_BITVAR (letype))
10589     {
10590       genDataPointerSet (right, result, ic);
10591       return;
10592     }
10593
10594   /* if the value is already in a pointer register
10595      then don't need anything more */
10596   if (!AOP_INPREG (AOP (result)))
10597     {
10598       /* otherwise get a free pointer register */
10599       regs *preg;
10600
10601       aop = newAsmop (0);
10602       preg = getFreePtr (ic, &aop, FALSE);
10603       emitcode ("mov", "%s,%s",
10604                 preg->name,
10605                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10606       rname = preg->name;
10607     }
10608   else
10609     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10610
10611   aopOp (right, ic, FALSE, FALSE);
10612
10613   /* if bitfield then unpack the bits */
10614   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10615     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10616   else
10617     {
10618       /* we have can just get the values */
10619       int size = AOP_SIZE (right);
10620       int offset = 0;
10621
10622       while (size--)
10623         {
10624           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10625           if (*l == '@')
10626             {
10627               MOVA (l);
10628               emitcode ("mov", "@%s,a", rname);
10629             }
10630           else
10631             emitcode ("mov", "@%s,%s", rname, l);
10632           if (size || pi)
10633             emitcode ("inc", "%s", rname);
10634           offset++;
10635         }
10636     }
10637
10638   /* now some housekeeping stuff */
10639   if (aop)
10640     {
10641       /* we had to allocate for this iCode */
10642       if (pi) aopPut (AOP (result),rname,0);
10643       freeAsmop (NULL, aop, ic, TRUE);
10644     }
10645   else
10646     {
10647       /* we did not allocate which means left
10648          already in a pointer register, then
10649          if size > 0 && this could be used again
10650          we have to point it back to where it
10651          belongs */
10652       if (AOP_SIZE (right) > 1 &&
10653           !OP_SYMBOL (result)->remat &&
10654           (OP_SYMBOL (result)->liveTo > ic->seq ||
10655            ic->depth) &&
10656           !pi)
10657         {
10658           int size = AOP_SIZE (right) - 1;
10659           while (size--)
10660             emitcode ("dec", "%s", rname);
10661         }
10662     }
10663
10664   /* done */
10665   if (pi) pi->generated = 1;
10666   freeAsmop (result, NULL, ic, TRUE);
10667   freeAsmop (right, NULL, ic, TRUE);
10668
10669
10670 }
10671
10672 /*-----------------------------------------------------------------*/
10673 /* genPagedPointerSet - emitcode for Paged pointer put             */
10674 /*-----------------------------------------------------------------*/
10675 static void
10676 genPagedPointerSet (operand * right,
10677                     operand * result,
10678                     iCode * ic,
10679                     iCode *pi)
10680 {
10681   asmop *aop = NULL;
10682   char *rname;
10683   sym_link *retype, *letype;
10684
10685   retype = getSpec (operandType (right));
10686   letype = getSpec (operandType (result));
10687
10688   aopOp (result, ic, FALSE, FALSE);
10689
10690   /* if the value is already in a pointer register
10691      then don't need anything more */
10692   if (!AOP_INPREG (AOP (result)))
10693     {
10694       /* otherwise get a free pointer register */
10695       regs *preg;
10696
10697       aop = newAsmop (0);
10698       preg = getFreePtr (ic, &aop, FALSE);
10699       emitcode ("mov", "%s,%s",
10700                 preg->name,
10701                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10702       rname = preg->name;
10703     }
10704   else
10705     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10706
10707   aopOp (right, ic, FALSE, FALSE);
10708
10709   /* if bitfield then unpack the bits */
10710   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10711     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10712   else
10713     {
10714       /* we have can just get the values */
10715       int size = AOP_SIZE (right);
10716       int offset = 0;
10717
10718       while (size--)
10719         {
10720           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10721
10722           emitcode ("movx", "@%s,a", rname);
10723
10724           if (size || pi)
10725             emitcode ("inc", "%s", rname);
10726
10727           offset++;
10728         }
10729     }
10730
10731   /* now some housekeeping stuff */
10732   if (aop)
10733     {
10734       if (pi) aopPut (AOP (result),rname,0);
10735       /* we had to allocate for this iCode */
10736       freeAsmop (NULL, aop, ic, TRUE);
10737     }
10738   else
10739     {
10740       /* we did not allocate which means left
10741          already in a pointer register, then
10742          if size > 0 && this could be used again
10743          we have to point it back to where it
10744          belongs */
10745       if (AOP_SIZE (right) > 1 &&
10746           !OP_SYMBOL (result)->remat &&
10747           (OP_SYMBOL (result)->liveTo > ic->seq ||
10748            ic->depth) &&
10749           !pi)
10750         {
10751           int size = AOP_SIZE (right) - 1;
10752           while (size--)
10753             emitcode ("dec", "%s", rname);
10754         }
10755     }
10756
10757   /* done */
10758   if (pi) pi->generated = 1;
10759   freeAsmop (result, NULL, ic, TRUE);
10760   freeAsmop (right, NULL, ic, TRUE);
10761
10762
10763 }
10764
10765 /*-----------------------------------------------------------------*/
10766 /* genFarPointerSet - set value from far space                     */
10767 /*-----------------------------------------------------------------*/
10768 static void
10769 genFarPointerSet (operand * right,
10770                   operand * result, iCode * ic, iCode *pi)
10771 {
10772   int size, offset, dopi=1;
10773   sym_link *retype = getSpec (operandType (right));
10774   sym_link *letype = getSpec (operandType (result));
10775
10776   aopOp (result, ic, FALSE, FALSE);
10777
10778   /* if the operand is already in dptr
10779      then we do nothing else we move the value to dptr */
10780   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10781     {
10782       /* if this is remateriazable */
10783       if (AOP_TYPE (result) == AOP_IMMD)
10784         emitcode ("mov", "dptr,%s",
10785                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10786       else
10787         {
10788           /* we need to get it byte by byte */
10789           _startLazyDPSEvaluation ();
10790           if (AOP_TYPE (result) != AOP_DPTR)
10791             {
10792               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10793               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10794               if (options.model == MODEL_FLAT24)
10795                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10796             }
10797           else
10798             {
10799               /* We need to generate a load to DPTR indirect through DPTR. */
10800               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10801
10802               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10803               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10804               if (options.model == MODEL_FLAT24)
10805                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10806               emitcode ("pop", "dph");
10807               emitcode ("pop", "dpl");
10808               dopi=0;
10809             }
10810           _endLazyDPSEvaluation ();
10811         }
10812     }
10813   /* so dptr know contains the address */
10814   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10815
10816   /* if bit then unpack */
10817   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10818       if (AOP_INDPTRn(result)) {
10819           genSetDPTR(AOP(result)->aopu.dptr);
10820       }
10821       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10822       if (AOP_INDPTRn(result)) {
10823           genSetDPTR(0);
10824       }
10825   } else {
10826       size = AOP_SIZE (right);
10827       offset = 0;
10828       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10829           while (size--) {
10830               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10831
10832               genSetDPTR(AOP(result)->aopu.dptr);
10833               emitcode ("movx", "@dptr,a");
10834               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10835                   emitcode ("inc", "dptr");
10836               genSetDPTR (0);
10837           }
10838       } else {
10839           _startLazyDPSEvaluation ();
10840           while (size--) {
10841               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10842
10843               if (AOP_INDPTRn(result)) {
10844                   genSetDPTR(AOP(result)->aopu.dptr);
10845               } else {
10846                   genSetDPTR (0);
10847               }
10848               _flushLazyDPS ();
10849
10850               emitcode ("movx", "@dptr,a");
10851               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10852                   emitcode ("inc", "dptr");
10853           }
10854           _endLazyDPSEvaluation ();
10855       }
10856   }
10857
10858   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10859       if (!AOP_INDPTRn(result)) {
10860           _startLazyDPSEvaluation ();
10861
10862           aopPut (AOP(result),"dpl",0);
10863           aopPut (AOP(result),"dph",1);
10864           if (options.model == MODEL_FLAT24)
10865               aopPut (AOP(result),"dpx",2);
10866
10867           _endLazyDPSEvaluation ();
10868       }
10869       pi->generated=1;
10870   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10871              AOP_SIZE(right) > 1 &&
10872              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10873
10874       size = AOP_SIZE (right) - 1;
10875       if (AOP_INDPTRn(result)) {
10876           genSetDPTR(AOP(result)->aopu.dptr);
10877       }
10878       while (size--) emitcode ("lcall","__decdptr");
10879       if (AOP_INDPTRn(result)) {
10880           genSetDPTR(0);
10881       }
10882   }
10883   freeAsmop (result, NULL, ic, TRUE);
10884   freeAsmop (right, NULL, ic, TRUE);
10885 }
10886
10887 /*-----------------------------------------------------------------*/
10888 /* genGenPointerSet - set value from generic pointer space         */
10889 /*-----------------------------------------------------------------*/
10890 static void
10891 genGenPointerSet (operand * right,
10892                   operand * result, iCode * ic, iCode *pi)
10893 {
10894   int size, offset;
10895   sym_link *retype = getSpec (operandType (right));
10896   sym_link *letype = getSpec (operandType (result));
10897
10898   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10899
10900   /* if the operand is already in dptr
10901      then we do nothing else we move the value to dptr */
10902   if (AOP_TYPE (result) != AOP_STR)
10903     {
10904       _startLazyDPSEvaluation ();
10905       /* if this is remateriazable */
10906       if (AOP_TYPE (result) == AOP_IMMD)
10907         {
10908           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10909           if (AOP(result)->aopu.aop_immd.from_cast_remat)
10910           {
10911               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10912           }
10913           else
10914           {
10915               emitcode ("mov",
10916                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10917           }
10918         }
10919       else
10920         {                       /* we need to get it byte by byte */
10921           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10922           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10923           if (options.model == MODEL_FLAT24) {
10924             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10925             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10926           } else {
10927             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10928           }
10929         }
10930       _endLazyDPSEvaluation ();
10931     }
10932   /* so dptr + b now contains the address */
10933   _G.bInUse++;
10934   aopOp (right, ic, FALSE, TRUE);
10935   _G.bInUse--;
10936
10937
10938   /* if bit then unpack */
10939   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10940     {
10941         genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10942     }
10943   else
10944     {
10945         size = AOP_SIZE (right);
10946         offset = 0;
10947
10948         _startLazyDPSEvaluation ();
10949         while (size--)
10950         {
10951             if (size)
10952             {
10953                 // Set two bytes at a time, passed in _AP & A.
10954                 // dptr will be incremented ONCE by __gptrputWord.
10955                 //
10956                 // Note: any change here must be coordinated
10957                 // with the implementation of __gptrputWord
10958                 // in device/lib/_gptrput.c
10959                 emitcode("mov", "_ap, %s",
10960                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10961                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10962
10963                 genSetDPTR (0);
10964                 _flushLazyDPS ();
10965                 emitcode ("lcall", "__gptrputWord");
10966                 size--;
10967             }
10968             else
10969             {
10970                 // Only one byte to put.
10971                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10972
10973                 genSetDPTR (0);
10974                 _flushLazyDPS ();
10975                 emitcode ("lcall", "__gptrput");
10976             }
10977
10978             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10979             {
10980                 emitcode ("inc", "dptr");
10981             }
10982         }
10983         _endLazyDPSEvaluation ();
10984     }
10985
10986   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10987       _startLazyDPSEvaluation ();
10988
10989       aopPut (AOP(result),"dpl",0);
10990       aopPut (AOP(result),"dph",1);
10991       if (options.model == MODEL_FLAT24) {
10992           aopPut (AOP(result),"dpx",2);
10993           aopPut (AOP(result),"b",3);
10994       } else {
10995           aopPut (AOP(result),"b",2);
10996       }
10997       _endLazyDPSEvaluation ();
10998
10999       pi->generated=1;
11000   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11001              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11002
11003       size = AOP_SIZE (right) - 1;
11004       while (size--) emitcode ("lcall","__decdptr");
11005   }
11006   freeAsmop (result, NULL, ic, TRUE);
11007   freeAsmop (right, NULL, ic, TRUE);
11008 }
11009
11010 /*-----------------------------------------------------------------*/
11011 /* genPointerSet - stores the value into a pointer location        */
11012 /*-----------------------------------------------------------------*/
11013 static void
11014 genPointerSet (iCode * ic, iCode *pi)
11015 {
11016   operand *right, *result;
11017   sym_link *type, *etype;
11018   int p_type;
11019
11020   D (emitcode (";", "genPointerSet "););
11021
11022   right = IC_RIGHT (ic);
11023   result = IC_RESULT (ic);
11024
11025   /* depending on the type of pointer we need to
11026      move it to the correct pointer register */
11027   type = operandType (result);
11028   etype = getSpec (type);
11029   /* if left is of type of pointer then it is simple */
11030   if (IS_PTR (type) && !IS_FUNC (type->next))
11031     {
11032       p_type = DCL_TYPE (type);
11033     }
11034   else
11035     {
11036       /* we have to go by the storage class */
11037       p_type = PTR_TYPE (SPEC_OCLS (etype));
11038     }
11039   /* special case when cast remat */
11040   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11041       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11042           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11043           type = operandType (result);
11044           p_type = DCL_TYPE (type);
11045   }
11046
11047   /* now that we have the pointer type we assign
11048      the pointer values */
11049   switch (p_type)
11050     {
11051
11052     case POINTER:
11053     case IPOINTER:
11054       genNearPointerSet (right, result, ic, pi);
11055       break;
11056
11057     case PPOINTER:
11058       genPagedPointerSet (right, result, ic, pi);
11059       break;
11060
11061     case FPOINTER:
11062       genFarPointerSet (right, result, ic, pi);
11063       break;
11064
11065     case GPOINTER:
11066       genGenPointerSet (right, result, ic, pi);
11067       break;
11068
11069     default:
11070       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11071               "genPointerSet: illegal pointer type");
11072     }
11073
11074 }
11075
11076 /*-----------------------------------------------------------------*/
11077 /* genIfx - generate code for Ifx statement                        */
11078 /*-----------------------------------------------------------------*/
11079 static void
11080 genIfx (iCode * ic, iCode * popIc)
11081 {
11082   operand *cond = IC_COND (ic);
11083   int isbit = 0;
11084
11085   D (emitcode (";", "genIfx "););
11086
11087   aopOp (cond, ic, FALSE, FALSE);
11088
11089   /* get the value into acc */
11090   if (AOP_TYPE (cond) != AOP_CRY)
11091     {
11092         toBoolean (cond);
11093     }
11094   else
11095     {
11096         isbit = 1;
11097     }
11098
11099   /* the result is now in the accumulator */
11100   freeAsmop (cond, NULL, ic, TRUE);
11101
11102   /* if there was something to be popped then do it */
11103   if (popIc)
11104     genIpop (popIc);
11105
11106   /* if the condition is  a bit variable */
11107   if (isbit && IS_ITEMP (cond) &&
11108       SPIL_LOC (cond))
11109     {
11110         genIfxJump (ic, SPIL_LOC (cond)->rname);
11111     }
11112   else if (isbit && !IS_ITEMP (cond))
11113     {
11114         genIfxJump (ic, OP_SYMBOL (cond)->rname);
11115     }
11116   else
11117     {
11118         genIfxJump (ic, "a");
11119     }
11120
11121   ic->generated = 1;
11122 }
11123
11124 /*-----------------------------------------------------------------*/
11125 /* genAddrOf - generates code for address of                       */
11126 /*-----------------------------------------------------------------*/
11127 static void
11128 genAddrOf (iCode * ic)
11129 {
11130   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11131   int size, offset;
11132
11133   D (emitcode (";", "genAddrOf ");
11134     );
11135
11136   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11137
11138   /* if the operand is on the stack then we
11139      need to get the stack offset of this
11140      variable */
11141   if (sym->onStack) {
11142
11143       /* if 10 bit stack */
11144       if (options.stack10bit) {
11145           char buff[10];
11146           int  offset;
11147
11148           tsprintf(buff, sizeof(buff),
11149                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
11150           /* if it has an offset then we need to compute it */
11151 /*        emitcode ("subb", "a,#!constbyte", */
11152 /*                  -((sym->stack < 0) ? */
11153 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
11154 /*                    ((short) sym->stack)) & 0xff); */
11155 /*        emitcode ("mov","b,a"); */
11156 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11157 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
11158 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
11159           if (sym->stack) {
11160               emitcode ("mov", "a,_bpx");
11161               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11162                                              ((char) (sym->stack - _G.nRegsSaved)) :
11163                                              ((char) sym->stack )) & 0xff);
11164               emitcode ("mov", "b,a");
11165               emitcode ("mov", "a,_bpx+1");
11166
11167               offset = (((sym->stack < 0) ?
11168                          ((short) (sym->stack - _G.nRegsSaved)) :
11169                          ((short) sym->stack )) >> 8) & 0xff;
11170
11171               emitcode ("addc","a,#!constbyte", offset);
11172
11173               aopPut (AOP (IC_RESULT (ic)), "b", 0);
11174               aopPut (AOP (IC_RESULT (ic)), "a", 1);
11175               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11176           } else {
11177               /* we can just move _bp */
11178               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11179               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11180               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11181           }
11182       } else {
11183           /* if it has an offset then we need to compute it */
11184           if (sym->stack) {
11185               emitcode ("mov", "a,_bp");
11186               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11187               aopPut (AOP (IC_RESULT (ic)), "a", 0);
11188           } else {
11189               /* we can just move _bp */
11190               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11191           }
11192           /* fill the result with zero */
11193           size = AOP_SIZE (IC_RESULT (ic)) - 1;
11194
11195
11196           if (options.stack10bit && size < (FPTRSIZE - 1)) {
11197               fprintf (stderr,
11198                        "*** warning: pointer to stack var truncated.\n");
11199           }
11200
11201           offset = 1;
11202           while (size--) {
11203               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11204           }
11205       }
11206       goto release;
11207   }
11208
11209   /* object not on stack then we need the name */
11210   size = AOP_SIZE (IC_RESULT (ic));
11211   offset = 0;
11212
11213   while (size--)
11214     {
11215       char s[SDCC_NAME_MAX];
11216       if (offset) {
11217           switch (offset) {
11218           case 1:
11219               tsprintf(s, sizeof(s), "#!his",sym->rname);
11220               break;
11221           case 2:
11222               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11223               break;
11224           case 3:
11225               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11226               break;
11227           default: /* should not need this (just in case) */
11228               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11229                        sym->rname,
11230                        offset * 8);
11231           }
11232       }
11233       else
11234       {
11235           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11236       }
11237
11238       aopPut (AOP (IC_RESULT (ic)), s, offset++);
11239     }
11240
11241 release:
11242   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11243
11244 }
11245
11246 #if 0 // obsolete, and buggy for != xdata
11247 /*-----------------------------------------------------------------*/
11248 /* genArrayInit - generates code for address of                       */
11249 /*-----------------------------------------------------------------*/
11250 static void
11251 genArrayInit (iCode * ic)
11252 {
11253     literalList *iLoop;
11254     int         ix, count;
11255     int         elementSize = 0, eIndex;
11256     unsigned    val, lastVal;
11257     sym_link    *type;
11258     operand     *left=IC_LEFT(ic);
11259
11260     D (emitcode (";", "genArrayInit "););
11261
11262     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11263
11264     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11265     {
11266         // Load immediate value into DPTR.
11267         emitcode("mov", "dptr, %s",
11268              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11269     }
11270     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11271     {
11272 #if 0
11273       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11274               "Unexpected operand to genArrayInit.\n");
11275       exit(1);
11276 #else
11277       // a regression because of SDCCcse.c:1.52
11278       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11279       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11280       if (options.model == MODEL_FLAT24)
11281         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11282 #endif
11283     }
11284
11285     type = operandType(IC_LEFT(ic));
11286
11287     if (type && type->next)
11288     {
11289         elementSize = getSize(type->next);
11290     }
11291     else
11292     {
11293         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11294                                 "can't determine element size in genArrayInit.\n");
11295         exit(1);
11296     }
11297
11298     iLoop = IC_ARRAYILIST(ic);
11299     lastVal = 0xffff;
11300
11301     while (iLoop)
11302     {
11303         bool firstpass = TRUE;
11304
11305         emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11306                  iLoop->count, (int)iLoop->literalValue, elementSize);
11307
11308         ix = iLoop->count;
11309
11310         while (ix)
11311         {
11312             symbol *tlbl = NULL;
11313
11314             count = ix > 256 ? 256 : ix;
11315
11316             if (count > 1)
11317             {
11318                 tlbl = newiTempLabel (NULL);
11319                 if (firstpass || (count & 0xff))
11320                 {
11321                     emitcode("mov", "b, #!constbyte", count & 0xff);
11322                 }
11323
11324                 emitcode ("", "!tlabeldef", tlbl->key + 100);
11325             }
11326
11327             firstpass = FALSE;
11328
11329             for (eIndex = 0; eIndex < elementSize; eIndex++)
11330             {
11331                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11332                 if (val != lastVal)
11333                 {
11334                     emitcode("mov", "a, #!constbyte", val);
11335                     lastVal = val;
11336                 }
11337
11338                 emitcode("movx", "@dptr, a");
11339                 emitcode("inc", "dptr");
11340             }
11341
11342             if (count > 1)
11343             {
11344                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11345             }
11346
11347             ix -= count;
11348         }
11349
11350         iLoop = iLoop->next;
11351     }
11352
11353     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11354 }
11355 #endif
11356
11357 /*-----------------------------------------------------------------*/
11358 /* genFarFarAssign - assignment when both are in far space         */
11359 /*-----------------------------------------------------------------*/
11360 static void
11361 genFarFarAssign (operand * result, operand * right, iCode * ic)
11362 {
11363   int size = AOP_SIZE (right);
11364   int offset = 0;
11365   symbol *rSym = NULL;
11366
11367   if (size == 1)
11368   {
11369       /* quick & easy case. */
11370       D(emitcode(";","genFarFarAssign (1 byte case)"););
11371       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11372       freeAsmop (right, NULL, ic, FALSE);
11373       /* now assign DPTR to result */
11374       _G.accInUse++;
11375       aopOp(result, ic, FALSE, FALSE);
11376       _G.accInUse--;
11377       aopPut(AOP(result), "a", 0);
11378       freeAsmop(result, NULL, ic, FALSE);
11379       return;
11380   }
11381
11382   /* See if we've got an underlying symbol to abuse. */
11383   if (IS_SYMOP(result) && OP_SYMBOL(result))
11384   {
11385       if (IS_TRUE_SYMOP(result))
11386       {
11387           rSym = OP_SYMBOL(result);
11388       }
11389       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11390       {
11391           rSym = OP_SYMBOL(result)->usl.spillLoc;
11392       }
11393   }
11394
11395   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11396   {
11397       /* We can use the '390 auto-toggle feature to good effect here. */
11398
11399       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11400       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
11401       emitcode ("mov", "dptr,#%s", rSym->rname);
11402       /* DP2 = result, DP1 = right, DP1 is current. */
11403       while (size)
11404       {
11405           emitcode("movx", "a,@dptr");
11406           emitcode("movx", "@dptr,a");
11407           if (--size)
11408           {
11409                emitcode("inc", "dptr");
11410                emitcode("inc", "dptr");
11411           }
11412       }
11413       emitcode("mov", "dps,#0");
11414       freeAsmop (right, NULL, ic, FALSE);
11415 #if 0
11416 some alternative code for processors without auto-toggle
11417 no time to test now, so later well put in...kpb
11418         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11419         emitcode("mov", "dps,#1");      /* Select DPTR2. */
11420         emitcode ("mov", "dptr,#%s", rSym->rname);
11421         /* DP2 = result, DP1 = right, DP1 is current. */
11422         while (size)
11423         {
11424           --size;
11425           emitcode("movx", "a,@dptr");
11426           if (size)
11427             emitcode("inc", "dptr");
11428           emitcode("inc", "dps");
11429           emitcode("movx", "@dptr,a");
11430           if (size)
11431             emitcode("inc", "dptr");
11432           emitcode("inc", "dps");
11433         }
11434         emitcode("mov", "dps,#0");
11435         freeAsmop (right, NULL, ic, FALSE);
11436 #endif
11437   }
11438   else
11439   {
11440       D (emitcode (";", "genFarFarAssign"););
11441       aopOp (result, ic, TRUE, TRUE);
11442
11443       _startLazyDPSEvaluation ();
11444
11445       while (size--)
11446         {
11447           aopPut (AOP (result),
11448                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11449           offset++;
11450         }
11451       _endLazyDPSEvaluation ();
11452       freeAsmop (result, NULL, ic, FALSE);
11453       freeAsmop (right, NULL, ic, FALSE);
11454   }
11455 }
11456
11457 /*-----------------------------------------------------------------*/
11458 /* genAssign - generate code for assignment                        */
11459 /*-----------------------------------------------------------------*/
11460 static void
11461 genAssign (iCode * ic)
11462 {
11463   operand *result, *right;
11464   int size, offset;
11465   unsigned long lit = 0L;
11466
11467   D (emitcode (";", "genAssign ");
11468     );
11469
11470   result = IC_RESULT (ic);
11471   right = IC_RIGHT (ic);
11472
11473   /* if they are the same */
11474   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11475     return;
11476
11477   aopOp (right, ic, FALSE, FALSE);
11478
11479   emitcode (";", "genAssign: resultIsFar = %s",
11480             isOperandInFarSpace (result) ?
11481             "TRUE" : "FALSE");
11482
11483   /* special case both in far space */
11484   if ((AOP_TYPE (right) == AOP_DPTR ||
11485        AOP_TYPE (right) == AOP_DPTR2) &&
11486   /* IS_TRUE_SYMOP(result)       && */
11487       isOperandInFarSpace (result))
11488     {
11489       genFarFarAssign (result, right, ic);
11490       return;
11491     }
11492
11493   aopOp (result, ic, TRUE, FALSE);
11494
11495   /* if they are the same registers */
11496   if (sameRegs (AOP (right), AOP (result)))
11497     goto release;
11498
11499   /* if the result is a bit */
11500   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11501     {
11502       /* if the right size is a literal then
11503          we know what the value is */
11504       if (AOP_TYPE (right) == AOP_LIT)
11505         {
11506           if (((int) operandLitValue (right)))
11507             aopPut (AOP (result), one, 0);
11508           else
11509             aopPut (AOP (result), zero, 0);
11510           goto release;
11511         }
11512
11513       /* the right is also a bit variable */
11514       if (AOP_TYPE (right) == AOP_CRY)
11515         {
11516           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11517           aopPut (AOP (result), "c", 0);
11518           goto release;
11519         }
11520
11521       /* we need to or */
11522       toBoolean (right);
11523       aopPut (AOP (result), "a", 0);
11524       goto release;
11525     }
11526
11527   /* bit variables done */
11528   /* general case */
11529   size = AOP_SIZE (result);
11530   offset = 0;
11531   if (AOP_TYPE (right) == AOP_LIT)
11532     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11533
11534   if ((size > 1) &&
11535       (AOP_TYPE (result) != AOP_REG) &&
11536       (AOP_TYPE (right) == AOP_LIT) &&
11537       !IS_FLOAT (operandType (right)))
11538     {
11539       _startLazyDPSEvaluation ();
11540       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11541         {
11542           aopPut (AOP (result),
11543                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11544                   offset);
11545           offset++;
11546           size--;
11547         }
11548       /* And now fill the rest with zeros. */
11549       if (size)
11550         {
11551           emitcode ("clr", "a");
11552         }
11553       while (size--)
11554         {
11555           aopPut (AOP (result), "a", offset++);
11556         }
11557       _endLazyDPSEvaluation ();
11558     }
11559   else
11560     {
11561       _startLazyDPSEvaluation ();
11562       while (size--)
11563         {
11564           aopPut (AOP (result),
11565                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11566                   offset);
11567           offset++;
11568         }
11569       _endLazyDPSEvaluation ();
11570     }
11571
11572 release:
11573   freeAsmop (right, NULL, ic, FALSE);
11574   freeAsmop (result, NULL, ic, TRUE);
11575 }
11576
11577 /*-----------------------------------------------------------------*/
11578 /* genJumpTab - generates code for jump table                      */
11579 /*-----------------------------------------------------------------*/
11580 static void
11581 genJumpTab (iCode * ic)
11582 {
11583   symbol *jtab;
11584   char *l;
11585
11586   D (emitcode (";", "genJumpTab ");
11587     );
11588
11589   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11590   /* get the condition into accumulator */
11591   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11592   MOVA (l);
11593   /* multiply by four! */
11594   emitcode ("add", "a,acc");
11595   emitcode ("add", "a,acc");
11596   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11597
11598   jtab = newiTempLabel (NULL);
11599   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11600   emitcode ("jmp", "@a+dptr");
11601   emitcode ("", "!tlabeldef", jtab->key + 100);
11602   /* now generate the jump labels */
11603   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11604        jtab = setNextItem (IC_JTLABELS (ic)))
11605     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11606
11607 }
11608
11609 /*-----------------------------------------------------------------*/
11610 /* genCast - gen code for casting                                  */
11611 /*-----------------------------------------------------------------*/
11612 static void
11613 genCast (iCode * ic)
11614 {
11615   operand *result = IC_RESULT (ic);
11616   sym_link *ctype = operandType (IC_LEFT (ic));
11617   sym_link *rtype = operandType (IC_RIGHT (ic));
11618   operand *right = IC_RIGHT (ic);
11619   int size, offset;
11620
11621   D (emitcode (";", "genCast "););
11622
11623   /* if they are equivalent then do nothing */
11624   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11625     return;
11626
11627   aopOp (right, ic, FALSE, AOP_IS_STR (result));
11628   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11629
11630   /* if the result is a bit */
11631   if (IS_BITVAR (OP_SYMBOL (result)->type)
11632       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11633     {
11634       /* if the right size is a literal then
11635          we know what the value is */
11636       if (AOP_TYPE (right) == AOP_LIT)
11637         {
11638           if (((int) operandLitValue (right)))
11639             aopPut (AOP (result), one, 0);
11640           else
11641             aopPut (AOP (result), zero, 0);
11642
11643           goto release;
11644         }
11645
11646       /* the right is also a bit variable */
11647       if (AOP_TYPE (right) == AOP_CRY)
11648         {
11649           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11650           aopPut (AOP (result), "c", 0);
11651           goto release;
11652         }
11653
11654       /* we need to or */
11655       toBoolean (right);
11656       aopPut (AOP (result), "a", 0);
11657       goto release;
11658     }
11659
11660   /* if they are the same size : or less */
11661   if (AOP_SIZE (result) <= AOP_SIZE (right))
11662     {
11663
11664       /* if they are in the same place */
11665       if (sameRegs (AOP (right), AOP (result)))
11666         goto release;
11667
11668       /* if they in different places then copy */
11669       size = AOP_SIZE (result);
11670       offset = 0;
11671       _startLazyDPSEvaluation ();
11672       while (size--)
11673         {
11674           aopPut (AOP (result),
11675                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11676                   offset);
11677           offset++;
11678         }
11679       _endLazyDPSEvaluation ();
11680       goto release;
11681     }
11682
11683
11684   /* if the result is of type pointer */
11685   if (IS_PTR (ctype))
11686     {
11687
11688       int p_type;
11689       sym_link *type = operandType (right);
11690
11691       /* pointer to generic pointer */
11692       if (IS_GENPTR (ctype))
11693         {
11694           if (IS_PTR (type))
11695             {
11696               p_type = DCL_TYPE (type);
11697             }
11698           else
11699             {
11700 #if OLD_CAST_BEHAVIOR
11701               /* KV: we are converting a non-pointer type to
11702                * a generic pointer. This (ifdef'd out) code
11703                * says that the resulting generic pointer
11704                * should have the same class as the storage
11705                * location of the non-pointer variable.
11706                *
11707                * For example, converting an int (which happens
11708                * to be stored in DATA space) to a pointer results
11709                * in a DATA generic pointer; if the original int
11710                * in XDATA space, so will be the resulting pointer.
11711                *
11712                * I don't like that behavior, and thus this change:
11713                * all such conversions will be forced to XDATA and
11714                * throw a warning. If you want some non-XDATA
11715                * type, or you want to suppress the warning, you
11716                * must go through an intermediate cast, like so:
11717                *
11718                * char _generic *gp = (char _xdata *)(intVar);
11719                */
11720               sym_link *etype = getSpec (type);
11721
11722               /* we have to go by the storage class */
11723               if (SPEC_OCLS (etype) != generic)
11724                 {
11725                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11726                 }
11727               else
11728 #endif
11729                 {
11730                   /* Converting unknown class (i.e. register variable)
11731                    * to generic pointer. This is not good, but
11732                    * we'll make a guess (and throw a warning).
11733                    */
11734                   p_type = FPOINTER;
11735                   werror (W_INT_TO_GEN_PTR_CAST);
11736                 }
11737             }
11738
11739           /* the first two bytes are known */
11740           size = GPTRSIZE - 1;
11741           offset = 0;
11742           _startLazyDPSEvaluation ();
11743           while (size--)
11744             {
11745               aopPut (AOP (result),
11746                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11747                       offset);
11748               offset++;
11749             }
11750           _endLazyDPSEvaluation ();
11751
11752           /* the last byte depending on type */
11753             {
11754                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11755                 char gpValStr[10];
11756
11757                 if (gpVal == -1)
11758                 {
11759                     // pointerTypeToGPByte will have bitched.
11760                     exit(1);
11761                 }
11762
11763                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
11764                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11765             }
11766           goto release;
11767         }
11768
11769       /* just copy the pointers */
11770       size = AOP_SIZE (result);
11771       offset = 0;
11772       _startLazyDPSEvaluation ();
11773       while (size--)
11774         {
11775           aopPut (AOP (result),
11776                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11777                   offset);
11778           offset++;
11779         }
11780       _endLazyDPSEvaluation ();
11781       goto release;
11782     }
11783
11784   /* so we now know that the size of destination is greater
11785      than the size of the source */
11786   /* we move to result for the size of source */
11787   size = AOP_SIZE (right);
11788   offset = 0;
11789   _startLazyDPSEvaluation ();
11790   while (size--)
11791     {
11792       aopPut (AOP (result),
11793               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11794               offset);
11795       offset++;
11796     }
11797   _endLazyDPSEvaluation ();
11798
11799   /* now depending on the sign of the source && destination */
11800   size = AOP_SIZE (result) - AOP_SIZE (right);
11801   /* if unsigned or not an integral type */
11802   /* also, if the source is a bit, we don't need to sign extend, because
11803    * it can't possibly have set the sign bit.
11804    */
11805   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11806     {
11807       while (size--)
11808         {
11809           aopPut (AOP (result), zero, offset++);
11810         }
11811     }
11812   else
11813     {
11814       /* we need to extend the sign :{ */
11815       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11816                         FALSE, FALSE, NULL));
11817       emitcode ("rlc", "a");
11818       emitcode ("subb", "a,acc");
11819       while (size--)
11820         aopPut (AOP (result), "a", offset++);
11821     }
11822
11823   /* we are done hurray !!!! */
11824
11825 release:
11826   freeAsmop (right, NULL, ic, TRUE);
11827   freeAsmop (result, NULL, ic, TRUE);
11828
11829 }
11830
11831 /*-----------------------------------------------------------------*/
11832 /* genDjnz - generate decrement & jump if not zero instrucion      */
11833 /*-----------------------------------------------------------------*/
11834 static int
11835 genDjnz (iCode * ic, iCode * ifx)
11836 {
11837   symbol *lbl, *lbl1;
11838   if (!ifx)
11839     return 0;
11840
11841   /* if the if condition has a false label
11842      then we cannot save */
11843   if (IC_FALSE (ifx))
11844     return 0;
11845
11846   /* if the minus is not of the form
11847      a = a - 1 */
11848   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11849       !IS_OP_LITERAL (IC_RIGHT (ic)))
11850     return 0;
11851
11852   if (operandLitValue (IC_RIGHT (ic)) != 1)
11853     return 0;
11854
11855   /* if the size of this greater than one then no
11856      saving */
11857   if (getSize (operandType (IC_RESULT (ic))) > 1)
11858     return 0;
11859
11860   /* otherwise we can save BIG */
11861   D(emitcode(";", "genDjnz"););
11862
11863   lbl = newiTempLabel (NULL);
11864   lbl1 = newiTempLabel (NULL);
11865
11866   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11867
11868   if (AOP_NEEDSACC(IC_RESULT(ic)))
11869   {
11870       /* If the result is accessed indirectly via
11871        * the accumulator, we must explicitly write
11872        * it back after the decrement.
11873        */
11874       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11875
11876       if (strcmp(rByte, "a"))
11877       {
11878            /* Something is hopelessly wrong */
11879            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11880                    __FILE__, __LINE__);
11881            /* We can just give up; the generated code will be inefficient,
11882             * but what the hey.
11883             */
11884            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11885            return 0;
11886       }
11887       emitcode ("dec", "%s", rByte);
11888       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11889       emitcode ("jnz", "!tlabel", lbl->key + 100);
11890   }
11891   else if (IS_AOP_PREG (IC_RESULT (ic)))
11892     {
11893       emitcode ("dec", "%s",
11894                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11895       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11896       emitcode ("jnz", "!tlabel", lbl->key + 100);
11897     }
11898   else
11899     {
11900       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11901                 lbl->key + 100);
11902     }
11903   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11904   emitcode ("", "!tlabeldef", lbl->key + 100);
11905   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11906   emitcode ("", "!tlabeldef", lbl1->key + 100);
11907
11908   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11909   ifx->generated = 1;
11910   return 1;
11911 }
11912
11913 /*-----------------------------------------------------------------*/
11914 /* genReceive - generate code for a receive iCode                  */
11915 /*-----------------------------------------------------------------*/
11916 static void
11917 genReceive (iCode * ic)
11918 {
11919     int size = getSize (operandType (IC_RESULT (ic)));
11920     int offset = 0;
11921     int rb1off ;
11922
11923     D (emitcode (";", "genReceive "););
11924
11925     if (ic->argreg == 1)
11926     {
11927         /* first parameter */
11928         if (AOP_IS_STR(IC_RESULT(ic)))
11929         {
11930             /* Nothing to do: it's already in the proper place. */
11931             return;
11932         }
11933         else
11934         {
11935             bool useDp2;
11936
11937             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11938                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11939                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11940
11941             _G.accInUse++;
11942             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11943             _G.accInUse--;
11944
11945             /* Sanity checking... */
11946             if (AOP_USESDPTR(IC_RESULT(ic)))
11947             {
11948                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11949                         "genReceive got unexpected DPTR.");
11950             }
11951             assignResultValue (IC_RESULT (ic));
11952         }
11953     }
11954     else
11955     {
11956         /* second receive onwards */
11957         /* this gets a little tricky since unused recevies will be
11958          eliminated, we have saved the reg in the type field . and
11959          we use that to figure out which register to use */
11960         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11961         rb1off = ic->argreg;
11962         while (size--)
11963         {
11964             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11965         }
11966     }
11967     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11968 }
11969
11970 /*-----------------------------------------------------------------*/
11971 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11972 /*-----------------------------------------------------------------*/
11973 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11974 {
11975     operand *from , *to , *count;
11976     symbol *lbl;
11977     bitVect *rsave;
11978     int i;
11979
11980     /* we know it has to be 3 parameters */
11981     assert (nparms == 3);
11982
11983     rsave = newBitVect(16);
11984     /* save DPTR if it needs to be saved */
11985     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11986             if (bitVectBitValue(ic->rMask,i))
11987                     rsave = bitVectSetBit(rsave,i);
11988     }
11989     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11990                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11991     savermask(rsave);
11992
11993     to = parms[0];
11994     from = parms[1];
11995     count = parms[2];
11996
11997     aopOp (from, ic->next, FALSE, FALSE);
11998
11999     /* get from into DPTR1 */
12000     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12001     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12002     if (options.model == MODEL_FLAT24) {
12003         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12004     }
12005
12006     freeAsmop (from, NULL, ic, FALSE);
12007     aopOp (to, ic, FALSE, FALSE);
12008     /* get "to" into DPTR */
12009     /* if the operand is already in dptr
12010        then we do nothing else we move the value to dptr */
12011     if (AOP_TYPE (to) != AOP_STR) {
12012         /* if already in DPTR then we need to push */
12013         if (AOP_TYPE(to) == AOP_DPTR) {
12014             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12015             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12016             if (options.model == MODEL_FLAT24)
12017                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12018             emitcode ("pop", "dph");
12019             emitcode ("pop", "dpl");
12020         } else {
12021             _startLazyDPSEvaluation ();
12022             /* if this is remateriazable */
12023             if (AOP_TYPE (to) == AOP_IMMD) {
12024                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12025             } else {                    /* we need to get it byte by byte */
12026                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12027                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12028                 if (options.model == MODEL_FLAT24) {
12029                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12030                 }
12031             }
12032             _endLazyDPSEvaluation ();
12033         }
12034     }
12035     freeAsmop (to, NULL, ic, FALSE);
12036     _G.dptrInUse = _G.dptr1InUse = 1;
12037     aopOp (count, ic->next->next, FALSE,FALSE);
12038     lbl =newiTempLabel(NULL);
12039
12040     /* now for the actual copy */
12041     if (AOP_TYPE(count) == AOP_LIT &&
12042         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12043         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12044         if (fromc) {
12045             emitcode ("lcall","__bi_memcpyc2x_s");
12046         } else {
12047             emitcode ("lcall","__bi_memcpyx2x_s");
12048         }
12049         freeAsmop (count, NULL, ic, FALSE);
12050     } else {
12051         symbol *lbl1 = newiTempLabel(NULL);
12052
12053         emitcode (";"," Auto increment but no djnz");
12054         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12055         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12056         freeAsmop (count, NULL, ic, FALSE);
12057         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12058         emitcode ("","!tlabeldef",lbl->key+100);
12059         if (fromc) {
12060             emitcode ("clr","a");
12061             emitcode ("movc", "a,@a+dptr");
12062         } else
12063             emitcode ("movx", "a,@dptr");
12064         emitcode ("movx", "@dptr,a");
12065         emitcode ("inc", "dptr");
12066         emitcode ("inc", "dptr");
12067         emitcode ("mov","a,b");
12068         emitcode ("orl","a,_ap");
12069         emitcode ("jz","!tlabel",lbl1->key+100);
12070         emitcode ("mov","a,_ap");
12071         emitcode ("add","a,#!constbyte",0xFF);
12072         emitcode ("mov","_ap,a");
12073         emitcode ("mov","a,b");
12074         emitcode ("addc","a,#!constbyte",0xFF);
12075         emitcode ("mov","b,a");
12076         emitcode ("sjmp","!tlabel",lbl->key+100);
12077         emitcode ("","!tlabeldef",lbl1->key+100);
12078     }
12079     emitcode ("mov", "dps,#0");
12080     _G.dptrInUse = _G.dptr1InUse = 0;
12081     unsavermask(rsave);
12082
12083 }
12084
12085 /*-----------------------------------------------------------------*/
12086 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
12087 /*-----------------------------------------------------------------*/
12088 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12089 {
12090     operand *from , *to , *count;
12091     symbol *lbl,*lbl2;
12092     bitVect *rsave;
12093     int i;
12094
12095     /* we know it has to be 3 parameters */
12096     assert (nparms == 3);
12097
12098     rsave = newBitVect(16);
12099     /* save DPTR if it needs to be saved */
12100     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12101             if (bitVectBitValue(ic->rMask,i))
12102                     rsave = bitVectSetBit(rsave,i);
12103     }
12104     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12105                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12106     savermask(rsave);
12107
12108     to = parms[0];
12109     from = parms[1];
12110     count = parms[2];
12111
12112     aopOp (from, ic->next, FALSE, FALSE);
12113
12114     /* get from into DPTR1 */
12115     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12116     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12117     if (options.model == MODEL_FLAT24) {
12118         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12119     }
12120
12121     freeAsmop (from, NULL, ic, FALSE);
12122     aopOp (to, ic, FALSE, FALSE);
12123     /* get "to" into DPTR */
12124     /* if the operand is already in dptr
12125        then we do nothing else we move the value to dptr */
12126     if (AOP_TYPE (to) != AOP_STR) {
12127         /* if already in DPTR then we need to push */
12128         if (AOP_TYPE(to) == AOP_DPTR) {
12129             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12130             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12131             if (options.model == MODEL_FLAT24)
12132                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12133             emitcode ("pop", "dph");
12134             emitcode ("pop", "dpl");
12135         } else {
12136             _startLazyDPSEvaluation ();
12137             /* if this is remateriazable */
12138             if (AOP_TYPE (to) == AOP_IMMD) {
12139                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12140             } else {                    /* we need to get it byte by byte */
12141                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12142                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12143                 if (options.model == MODEL_FLAT24) {
12144                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12145                 }
12146             }
12147             _endLazyDPSEvaluation ();
12148         }
12149     }
12150     freeAsmop (to, NULL, ic, FALSE);
12151     _G.dptrInUse = _G.dptr1InUse = 1;
12152     aopOp (count, ic->next->next, FALSE,FALSE);
12153     lbl =newiTempLabel(NULL);
12154     lbl2 =newiTempLabel(NULL);
12155
12156     /* now for the actual compare */
12157     if (AOP_TYPE(count) == AOP_LIT &&
12158         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12159         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12160         if (fromc)
12161             emitcode("lcall","__bi_memcmpc2x_s");
12162         else
12163             emitcode("lcall","__bi_memcmpx2x_s");
12164         freeAsmop (count, NULL, ic, FALSE);
12165         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12166         aopPut(AOP(IC_RESULT(ic)),"a",0);
12167         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12168     } else {
12169         symbol *lbl1 = newiTempLabel(NULL);
12170
12171         emitcode("push","ar0");
12172         emitcode (";"," Auto increment but no djnz");
12173         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12174         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12175         freeAsmop (count, NULL, ic, FALSE);
12176         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12177         emitcode ("","!tlabeldef",lbl->key+100);
12178         if (fromc) {
12179             emitcode ("clr","a");
12180             emitcode ("movc", "a,@a+dptr");
12181         } else
12182             emitcode ("movx", "a,@dptr");
12183         emitcode ("mov","r0,a");
12184         emitcode ("movx", "a,@dptr");
12185         emitcode ("clr","c");
12186         emitcode ("subb","a,r0");
12187         emitcode ("jnz","!tlabel",lbl2->key+100);
12188         emitcode ("inc", "dptr");
12189         emitcode ("inc", "dptr");
12190         emitcode ("mov","a,b");
12191         emitcode ("orl","a,_ap");
12192         emitcode ("jz","!tlabel",lbl1->key+100);
12193         emitcode ("mov","a,_ap");
12194         emitcode ("add","a,#!constbyte",0xFF);
12195         emitcode ("mov","_ap,a");
12196         emitcode ("mov","a,b");
12197         emitcode ("addc","a,#!constbyte",0xFF);
12198         emitcode ("mov","b,a");
12199         emitcode ("sjmp","!tlabel",lbl->key+100);
12200         emitcode ("","!tlabeldef",lbl1->key+100);
12201         emitcode ("clr","a");
12202         emitcode ("","!tlabeldef",lbl2->key+100);
12203         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12204         aopPut(AOP(IC_RESULT(ic)),"a",0);
12205         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12206         emitcode("pop","ar0");
12207         emitcode ("mov", "dps,#0");
12208     }
12209     _G.dptrInUse = _G.dptr1InUse = 0;
12210     unsavermask(rsave);
12211
12212 }
12213
12214 /*-----------------------------------------------------------------*/
12215 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12216 /* port, first parameter output area second parameter pointer to   */
12217 /* port third parameter count                                      */
12218 /*-----------------------------------------------------------------*/
12219 static void genInp( iCode *ic, int nparms, operand **parms)
12220 {
12221     operand *from , *to , *count;
12222     symbol *lbl;
12223     bitVect *rsave;
12224     int i;
12225
12226     /* we know it has to be 3 parameters */
12227     assert (nparms == 3);
12228
12229     rsave = newBitVect(16);
12230     /* save DPTR if it needs to be saved */
12231     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12232             if (bitVectBitValue(ic->rMask,i))
12233                     rsave = bitVectSetBit(rsave,i);
12234     }
12235     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12236                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12237     savermask(rsave);
12238
12239     to = parms[0];
12240     from = parms[1];
12241     count = parms[2];
12242
12243     aopOp (from, ic->next, FALSE, FALSE);
12244
12245     /* get from into DPTR1 */
12246     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12247     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12248     if (options.model == MODEL_FLAT24) {
12249         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12250     }
12251
12252     freeAsmop (from, NULL, ic, FALSE);
12253     aopOp (to, ic, FALSE, FALSE);
12254     /* get "to" into DPTR */
12255     /* if the operand is already in dptr
12256        then we do nothing else we move the value to dptr */
12257     if (AOP_TYPE (to) != AOP_STR) {
12258         /* if already in DPTR then we need to push */
12259         if (AOP_TYPE(to) == AOP_DPTR) {
12260             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12261             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12262             if (options.model == MODEL_FLAT24)
12263                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12264             emitcode ("pop", "dph");
12265             emitcode ("pop", "dpl");
12266         } else {
12267             _startLazyDPSEvaluation ();
12268             /* if this is remateriazable */
12269             if (AOP_TYPE (to) == AOP_IMMD) {
12270                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12271             } else {                    /* we need to get it byte by byte */
12272                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12273                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12274                 if (options.model == MODEL_FLAT24) {
12275                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12276                 }
12277             }
12278             _endLazyDPSEvaluation ();
12279         }
12280     }
12281     freeAsmop (to, NULL, ic, FALSE);
12282
12283     _G.dptrInUse = _G.dptr1InUse = 1;
12284     aopOp (count, ic->next->next, FALSE,FALSE);
12285     lbl =newiTempLabel(NULL);
12286
12287     /* now for the actual copy */
12288     if (AOP_TYPE(count) == AOP_LIT &&
12289         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12290         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12291         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12292         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12293         freeAsmop (count, NULL, ic, FALSE);
12294         emitcode ("","!tlabeldef",lbl->key+100);
12295         emitcode ("movx", "a,@dptr");   /* read data from port */
12296         emitcode ("dec","dps");         /* switch to DPTR */
12297         emitcode ("movx", "@dptr,a");   /* save into location */
12298         emitcode ("inc", "dptr");       /* point to next area */
12299         emitcode ("inc","dps");         /* switch to DPTR2 */
12300         emitcode ("djnz","b,!tlabel",lbl->key+100);
12301     } else {
12302         symbol *lbl1 = newiTempLabel(NULL);
12303
12304         emitcode (";"," Auto increment but no djnz");
12305         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12306         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12307         freeAsmop (count, NULL, ic, FALSE);
12308         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12309         emitcode ("","!tlabeldef",lbl->key+100);
12310         emitcode ("movx", "a,@dptr");
12311         emitcode ("dec","dps");         /* switch to DPTR */
12312         emitcode ("movx", "@dptr,a");
12313         emitcode ("inc", "dptr");
12314         emitcode ("inc","dps");         /* switch to DPTR2 */
12315 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
12316 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12317         emitcode ("mov","a,b");
12318         emitcode ("orl","a,_ap");
12319         emitcode ("jz","!tlabel",lbl1->key+100);
12320         emitcode ("mov","a,_ap");
12321         emitcode ("add","a,#!constbyte",0xFF);
12322         emitcode ("mov","_ap,a");
12323         emitcode ("mov","a,b");
12324         emitcode ("addc","a,#!constbyte",0xFF);
12325         emitcode ("mov","b,a");
12326         emitcode ("sjmp","!tlabel",lbl->key+100);
12327         emitcode ("","!tlabeldef",lbl1->key+100);
12328     }
12329     emitcode ("mov", "dps,#0");
12330     _G.dptrInUse = _G.dptr1InUse = 0;
12331     unsavermask(rsave);
12332
12333 }
12334
12335 /*-----------------------------------------------------------------*/
12336 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12337 /* port, first parameter output area second parameter pointer to   */
12338 /* port third parameter count                                      */
12339 /*-----------------------------------------------------------------*/
12340 static void genOutp( iCode *ic, int nparms, operand **parms)
12341 {
12342     operand *from , *to , *count;
12343     symbol *lbl;
12344     bitVect *rsave;
12345     int i;
12346
12347     /* we know it has to be 3 parameters */
12348     assert (nparms == 3);
12349
12350     rsave = newBitVect(16);
12351     /* save DPTR if it needs to be saved */
12352     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12353             if (bitVectBitValue(ic->rMask,i))
12354                     rsave = bitVectSetBit(rsave,i);
12355     }
12356     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12357                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12358     savermask(rsave);
12359
12360     to = parms[0];
12361     from = parms[1];
12362     count = parms[2];
12363
12364     aopOp (from, ic->next, FALSE, FALSE);
12365
12366     /* get from into DPTR1 */
12367     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12368     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12369     if (options.model == MODEL_FLAT24) {
12370         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12371     }
12372
12373     freeAsmop (from, NULL, ic, FALSE);
12374     aopOp (to, ic, FALSE, FALSE);
12375     /* get "to" into DPTR */
12376     /* if the operand is already in dptr
12377        then we do nothing else we move the value to dptr */
12378     if (AOP_TYPE (to) != AOP_STR) {
12379         /* if already in DPTR then we need to push */
12380         if (AOP_TYPE(to) == AOP_DPTR) {
12381             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12382             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12383             if (options.model == MODEL_FLAT24)
12384                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12385             emitcode ("pop", "dph");
12386             emitcode ("pop", "dpl");
12387         } else {
12388             _startLazyDPSEvaluation ();
12389             /* if this is remateriazable */
12390             if (AOP_TYPE (to) == AOP_IMMD) {
12391                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12392             } else {                    /* we need to get it byte by byte */
12393                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12394                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12395                 if (options.model == MODEL_FLAT24) {
12396                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12397                 }
12398             }
12399             _endLazyDPSEvaluation ();
12400         }
12401     }
12402     freeAsmop (to, NULL, ic, FALSE);
12403
12404     _G.dptrInUse = _G.dptr1InUse = 1;
12405     aopOp (count, ic->next->next, FALSE,FALSE);
12406     lbl =newiTempLabel(NULL);
12407
12408     /* now for the actual copy */
12409     if (AOP_TYPE(count) == AOP_LIT &&
12410         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12411         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12412         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12413         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12414         emitcode ("","!tlabeldef",lbl->key+100);
12415         emitcode ("movx", "a,@dptr");   /* read data from port */
12416         emitcode ("inc","dps");         /* switch to DPTR2 */
12417         emitcode ("movx", "@dptr,a");   /* save into location */
12418         emitcode ("inc", "dptr");       /* point to next area */
12419         emitcode ("dec","dps");         /* switch to DPTR */
12420         emitcode ("djnz","b,!tlabel",lbl->key+100);
12421         freeAsmop (count, NULL, ic, FALSE);
12422     } else {
12423         symbol *lbl1 = newiTempLabel(NULL);
12424
12425         emitcode (";"," Auto increment but no djnz");
12426         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12427         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12428         freeAsmop (count, NULL, ic, FALSE);
12429         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12430         emitcode ("","!tlabeldef",lbl->key+100);
12431         emitcode ("movx", "a,@dptr");
12432         emitcode ("inc", "dptr");
12433         emitcode ("inc","dps");         /* switch to DPTR2 */
12434         emitcode ("movx", "@dptr,a");
12435         emitcode ("dec","dps");         /* switch to DPTR */
12436         emitcode ("mov","a,b");
12437         emitcode ("orl","a,_ap");
12438         emitcode ("jz","!tlabel",lbl1->key+100);
12439         emitcode ("mov","a,_ap");
12440         emitcode ("add","a,#!constbyte",0xFF);
12441         emitcode ("mov","_ap,a");
12442         emitcode ("mov","a,b");
12443         emitcode ("addc","a,#!constbyte",0xFF);
12444         emitcode ("mov","b,a");
12445         emitcode ("sjmp","!tlabel",lbl->key+100);
12446         emitcode ("","!tlabeldef",lbl1->key+100);
12447     }
12448     emitcode ("mov", "dps,#0");
12449     _G.dptrInUse = _G.dptr1InUse = 0;
12450     unsavermask(rsave);
12451
12452 }
12453
12454 /*-----------------------------------------------------------------*/
12455 /* genSwapW - swap lower & high order bytes                        */
12456 /*-----------------------------------------------------------------*/
12457 static void genSwapW(iCode *ic, int nparms, operand **parms)
12458 {
12459     operand *dest;
12460     operand *src;
12461     assert (nparms==1);
12462
12463     src = parms[0];
12464     dest=IC_RESULT(ic);
12465
12466     assert(getSize(operandType(src))==2);
12467
12468     aopOp (src, ic, FALSE, FALSE);
12469     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12470     _G.accInUse++;
12471     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12472     _G.accInUse--;
12473     freeAsmop (src, NULL, ic, FALSE);
12474
12475     aopOp (dest,ic, FALSE, FALSE);
12476     aopPut(AOP(dest),"b",0);
12477     aopPut(AOP(dest),"a",1);
12478     freeAsmop (dest, NULL, ic, FALSE);
12479 }
12480
12481 /*-----------------------------------------------------------------*/
12482 /* genMemsetX - gencode for memSetX data                           */
12483 /*-----------------------------------------------------------------*/
12484 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12485 {
12486     operand *to , *val , *count;
12487     symbol *lbl;
12488     char *l;
12489     int i;
12490     bitVect *rsave;
12491
12492     /* we know it has to be 3 parameters */
12493     assert (nparms == 3);
12494
12495     to = parms[0];
12496     val = parms[1];
12497     count = parms[2];
12498
12499     /* save DPTR if it needs to be saved */
12500     rsave = newBitVect(16);
12501     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12502             if (bitVectBitValue(ic->rMask,i))
12503                     rsave = bitVectSetBit(rsave,i);
12504     }
12505     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12506                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12507     savermask(rsave);
12508
12509     aopOp (to, ic, FALSE, FALSE);
12510     /* get "to" into DPTR */
12511     /* if the operand is already in dptr
12512        then we do nothing else we move the value to dptr */
12513     if (AOP_TYPE (to) != AOP_STR) {
12514         /* if already in DPTR then we need to push */
12515         if (AOP_TYPE(to) == AOP_DPTR) {
12516             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12517             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12518             if (options.model == MODEL_FLAT24)
12519                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12520             emitcode ("pop", "dph");
12521             emitcode ("pop", "dpl");
12522         } else {
12523             _startLazyDPSEvaluation ();
12524             /* if this is remateriazable */
12525             if (AOP_TYPE (to) == AOP_IMMD) {
12526                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12527             } else {                    /* we need to get it byte by byte */
12528                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12529                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12530                 if (options.model == MODEL_FLAT24) {
12531                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12532                 }
12533             }
12534             _endLazyDPSEvaluation ();
12535         }
12536     }
12537     freeAsmop (to, NULL, ic, FALSE);
12538
12539     aopOp (val, ic->next->next, FALSE,FALSE);
12540     aopOp (count, ic->next->next, FALSE,FALSE);
12541     lbl =newiTempLabel(NULL);
12542     /* now for the actual copy */
12543     if (AOP_TYPE(count) == AOP_LIT &&
12544         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12545         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12546         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12547         MOVA(l);
12548         emitcode ("","!tlabeldef",lbl->key+100);
12549         emitcode ("movx", "@dptr,a");
12550         emitcode ("inc", "dptr");
12551         emitcode ("djnz","b,!tlabel",lbl->key+100);
12552     } else {
12553         symbol *lbl1 = newiTempLabel(NULL);
12554
12555         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12556         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12557         emitcode ("","!tlabeldef",lbl->key+100);
12558         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12559         emitcode ("movx", "@dptr,a");
12560         emitcode ("inc", "dptr");
12561         emitcode ("mov","a,b");
12562         emitcode ("orl","a,_ap");
12563         emitcode ("jz","!tlabel",lbl1->key+100);
12564         emitcode ("mov","a,_ap");
12565         emitcode ("add","a,#!constbyte",0xFF);
12566         emitcode ("mov","_ap,a");
12567         emitcode ("mov","a,b");
12568         emitcode ("addc","a,#!constbyte",0xFF);
12569         emitcode ("mov","b,a");
12570         emitcode ("sjmp","!tlabel",lbl->key+100);
12571         emitcode ("","!tlabeldef",lbl1->key+100);
12572     }
12573     freeAsmop (count, NULL, ic, FALSE);
12574     unsavermask(rsave);
12575 }
12576
12577 /*-----------------------------------------------------------------*/
12578 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12579 /*-----------------------------------------------------------------*/
12580 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12581 {
12582         bitVect *rsave ;
12583         operand *pnum, *result;
12584         int i;
12585
12586         assert (nparms==1);
12587         /* save registers that need to be saved */
12588         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12589                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12590
12591         pnum = parms[0];
12592         aopOp (pnum, ic, FALSE, FALSE);
12593         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12594         freeAsmop (pnum, NULL, ic, FALSE);
12595         emitcode ("lcall","NatLib_LoadPrimitive");
12596         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12597         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12598             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12599                 for (i = (size-1) ; i >= 0 ; i-- ) {
12600                         emitcode ("push","a%s",javaRet[i]);
12601                 }
12602                 for (i=0; i < size ; i++ ) {
12603                         emitcode ("pop","a%s",
12604                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12605                 }
12606         } else {
12607                 for (i = 0 ; i < size ; i++ ) {
12608                         aopPut(AOP(result),javaRet[i],i);
12609                 }
12610         }
12611         freeAsmop (result, NULL, ic, FALSE);
12612         unsavermask(rsave);
12613 }
12614
12615 /*-----------------------------------------------------------------*/
12616 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12617 /*-----------------------------------------------------------------*/
12618 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12619 {
12620         bitVect *rsave ;
12621         operand *pnum, *result;
12622         int size = 3;
12623         int i;
12624
12625         assert (nparms==1);
12626         /* save registers that need to be saved */
12627         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12628                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12629
12630         pnum = parms[0];
12631         aopOp (pnum, ic, FALSE, FALSE);
12632         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12633         freeAsmop (pnum, NULL, ic, FALSE);
12634         emitcode ("lcall","NatLib_LoadPointer");
12635         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12636         if (AOP_TYPE(result)!=AOP_STR) {
12637                 for (i = 0 ; i < size ; i++ ) {
12638                         aopPut(AOP(result),fReturn[i],i);
12639                 }
12640         }
12641         freeAsmop (result, NULL, ic, FALSE);
12642         unsavermask(rsave);
12643 }
12644
12645 /*-----------------------------------------------------------------*/
12646 /* genNatLibInstallStateBlock -                                    */
12647 /*-----------------------------------------------------------------*/
12648 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12649                                        operand **parms, const char *name)
12650 {
12651         bitVect *rsave ;
12652         operand *psb, *handle;
12653         assert (nparms==2);
12654
12655         /* save registers that need to be saved */
12656         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12657                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12658         psb = parms[0];
12659         handle = parms[1];
12660
12661         /* put pointer to state block into DPTR1 */
12662         aopOp (psb, ic, FALSE, FALSE);
12663         if (AOP_TYPE (psb) == AOP_IMMD) {
12664                 emitcode ("mov","dps,#1");
12665                 emitcode ("mov", "dptr,%s",
12666                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12667                 emitcode ("mov","dps,#0");
12668         } else {
12669                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12670                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12671                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12672         }
12673         freeAsmop (psb, NULL, ic, FALSE);
12674
12675         /* put libraryID into DPTR */
12676         emitcode ("mov","dptr,#LibraryID");
12677
12678         /* put handle into r3:r2 */
12679         aopOp (handle, ic, FALSE, FALSE);
12680         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12681                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12682                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12683                 emitcode ("pop","ar3");
12684                 emitcode ("pop","ar2");
12685         } else {
12686                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12687                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12688         }
12689         freeAsmop (psb, NULL, ic, FALSE);
12690
12691         /* make the call */
12692         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12693
12694         /* put return value into place*/
12695         _G.accInUse++;
12696         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12697         _G.accInUse--;
12698         aopPut(AOP(IC_RESULT(ic)),"a",0);
12699         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12700         unsavermask(rsave);
12701 }
12702
12703 /*-----------------------------------------------------------------*/
12704 /* genNatLibRemoveStateBlock -                                     */
12705 /*-----------------------------------------------------------------*/
12706 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12707 {
12708         bitVect *rsave ;
12709
12710         assert(nparms==0);
12711
12712         /* save registers that need to be saved */
12713         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12714                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12715
12716         /* put libraryID into DPTR */
12717         emitcode ("mov","dptr,#LibraryID");
12718         /* make the call */
12719         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12720         unsavermask(rsave);
12721 }
12722
12723 /*-----------------------------------------------------------------*/
12724 /* genNatLibGetStateBlock -                                        */
12725 /*-----------------------------------------------------------------*/
12726 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12727                                    operand **parms,const char *name)
12728 {
12729         bitVect *rsave ;
12730         symbol *lbl = newiTempLabel(NULL);
12731
12732         assert(nparms==0);
12733         /* save registers that need to be saved */
12734         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12735                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12736
12737         /* put libraryID into DPTR */
12738         emitcode ("mov","dptr,#LibraryID");
12739         /* make the call */
12740         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12741         emitcode ("jnz","!tlabel",lbl->key+100);
12742
12743         /* put return value into place */
12744         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12745         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12746                 emitcode ("push","ar3");
12747                 emitcode ("push","ar2");
12748                 emitcode ("pop","%s",
12749                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12750                 emitcode ("pop","%s",
12751                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12752         } else {
12753                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12754                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12755         }
12756         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12757         emitcode ("","!tlabeldef",lbl->key+100);
12758         unsavermask(rsave);
12759 }
12760
12761 /*-----------------------------------------------------------------*/
12762 /* genMMMalloc -                                                   */
12763 /*-----------------------------------------------------------------*/
12764 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12765                          int size, const char *name)
12766 {
12767         bitVect *rsave ;
12768         operand *bsize;
12769         symbol *rsym;
12770         symbol *lbl = newiTempLabel(NULL);
12771
12772         assert (nparms == 1);
12773         /* save registers that need to be saved */
12774         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12775                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12776
12777         bsize=parms[0];
12778         aopOp (bsize,ic,FALSE,FALSE);
12779
12780         /* put the size in R4-R2 */
12781         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12782                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12783                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12784                 if (size==3) {
12785                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12786                         emitcode("pop","ar4");
12787                 }
12788                 emitcode("pop","ar3");
12789                 emitcode("pop","ar2");
12790         } else {
12791                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12792                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12793                 if (size==3) {
12794                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12795                 }
12796         }
12797         freeAsmop (bsize, NULL, ic, FALSE);
12798
12799         /* make the call */
12800         emitcode ("lcall","MM_%s",name);
12801         emitcode ("jz","!tlabel",lbl->key+100);
12802         emitcode ("mov","r2,#!constbyte",0xff);
12803         emitcode ("mov","r3,#!constbyte",0xff);
12804         emitcode ("","!tlabeldef",lbl->key+100);
12805         /* we don't care about the pointer : we just save the handle */
12806         rsym = OP_SYMBOL(IC_RESULT(ic));
12807         if (rsym->liveFrom != rsym->liveTo) {
12808                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12809                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12810                         emitcode ("push","ar3");
12811                         emitcode ("push","ar2");
12812                         emitcode ("pop","%s",
12813                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12814                         emitcode ("pop","%s",
12815                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12816                 } else {
12817                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12818                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12819                 }
12820                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12821         }
12822         unsavermask(rsave);
12823 }
12824
12825 /*-----------------------------------------------------------------*/
12826 /* genMMDeref -                                                    */
12827 /*-----------------------------------------------------------------*/
12828 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12829 {
12830         bitVect *rsave ;
12831         operand *handle;
12832
12833         assert (nparms == 1);
12834         /* save registers that need to be saved */
12835         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12836                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12837
12838         handle=parms[0];
12839         aopOp (handle,ic,FALSE,FALSE);
12840
12841         /* put the size in R4-R2 */
12842         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12843                 emitcode("push","%s",
12844                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12845                 emitcode("push","%s",
12846                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12847                 emitcode("pop","ar3");
12848                 emitcode("pop","ar2");
12849         } else {
12850                 emitcode ("mov","r2,%s",
12851                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12852                 emitcode ("mov","r3,%s",
12853                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12854         }
12855         freeAsmop (handle, NULL, ic, FALSE);
12856
12857         /* make the call */
12858         emitcode ("lcall","MM_Deref");
12859
12860         {
12861                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12862                 if (rsym->liveFrom != rsym->liveTo) {
12863                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12864                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12865                             _startLazyDPSEvaluation ();
12866
12867                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12868                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12869                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12870
12871                             _endLazyDPSEvaluation ();
12872
12873                         }
12874                 }
12875         }
12876         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12877         unsavermask(rsave);
12878 }
12879
12880 /*-----------------------------------------------------------------*/
12881 /* genMMUnrestrictedPersist -                                      */
12882 /*-----------------------------------------------------------------*/
12883 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12884 {
12885         bitVect *rsave ;
12886         operand *handle;
12887
12888         assert (nparms == 1);
12889         /* save registers that need to be saved */
12890         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12891                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12892
12893         handle=parms[0];
12894         aopOp (handle,ic,FALSE,FALSE);
12895
12896         /* put the size in R3-R2 */
12897         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12898                 emitcode("push","%s",
12899                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12900                 emitcode("push","%s",
12901                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12902                 emitcode("pop","ar3");
12903                 emitcode("pop","ar2");
12904         } else {
12905                 emitcode ("mov","r2,%s",
12906                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12907                 emitcode ("mov","r3,%s",
12908                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12909         }
12910         freeAsmop (handle, NULL, ic, FALSE);
12911
12912         /* make the call */
12913         emitcode ("lcall","MM_UnrestrictedPersist");
12914
12915         {
12916                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12917                 if (rsym->liveFrom != rsym->liveTo) {
12918                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12919                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12920                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12921                 }
12922         }
12923         unsavermask(rsave);
12924 }
12925
12926 /*-----------------------------------------------------------------*/
12927 /* genSystemExecJavaProcess -                                      */
12928 /*-----------------------------------------------------------------*/
12929 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12930 {
12931         bitVect *rsave ;
12932         operand *handle, *pp;
12933
12934         assert (nparms==2);
12935         /* save registers that need to be saved */
12936         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12937                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12938
12939         pp = parms[0];
12940         handle = parms[1];
12941
12942         /* put the handle in R3-R2 */
12943         aopOp (handle,ic,FALSE,FALSE);
12944         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12945                 emitcode("push","%s",
12946                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12947                 emitcode("push","%s",
12948                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12949                 emitcode("pop","ar3");
12950                 emitcode("pop","ar2");
12951         } else {
12952                 emitcode ("mov","r2,%s",
12953                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12954                 emitcode ("mov","r3,%s",
12955                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12956         }
12957         freeAsmop (handle, NULL, ic, FALSE);
12958
12959         /* put pointer in DPTR */
12960         aopOp (pp,ic,FALSE,FALSE);
12961         if (AOP_TYPE(pp) == AOP_IMMD) {
12962                 emitcode ("mov", "dptr,%s",
12963                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12964         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12965                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12966                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12967                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12968         }
12969         freeAsmop (handle, NULL, ic, FALSE);
12970
12971         /* make the call */
12972         emitcode ("lcall","System_ExecJavaProcess");
12973
12974         /* put result in place */
12975         {
12976                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12977                 if (rsym->liveFrom != rsym->liveTo) {
12978                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12979                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12980                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12981                 }
12982         }
12983
12984         unsavermask(rsave);
12985 }
12986
12987 /*-----------------------------------------------------------------*/
12988 /* genSystemRTCRegisters -                                         */
12989 /*-----------------------------------------------------------------*/
12990 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12991                                   char *name)
12992 {
12993         bitVect *rsave ;
12994         operand *pp;
12995
12996         assert (nparms==1);
12997         /* save registers that need to be saved */
12998         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12999                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13000
13001         pp=parms[0];
13002         /* put pointer in DPTR */
13003         aopOp (pp,ic,FALSE,FALSE);
13004         if (AOP_TYPE (pp) == AOP_IMMD) {
13005                 emitcode ("mov","dps,#1");
13006                 emitcode ("mov", "dptr,%s",
13007                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
13008                 emitcode ("mov","dps,#0");
13009         } else {
13010                 emitcode ("mov","dpl1,%s",
13011                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
13012                 emitcode ("mov","dph1,%s",
13013                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
13014                 emitcode ("mov","dpx1,%s",
13015                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
13016         }
13017         freeAsmop (pp, NULL, ic, FALSE);
13018
13019         /* make the call */
13020         emitcode ("lcall","System_%sRTCRegisters",name);
13021
13022         unsavermask(rsave);
13023 }
13024
13025 /*-----------------------------------------------------------------*/
13026 /* genSystemThreadSleep -                                          */
13027 /*-----------------------------------------------------------------*/
13028 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13029 {
13030         bitVect *rsave ;
13031         operand *to, *s;
13032
13033         assert (nparms==1);
13034         /* save registers that need to be saved */
13035         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13036                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13037
13038         to = parms[0];
13039         aopOp(to,ic,FALSE,FALSE);
13040         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13041             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13042                 emitcode ("push","%s",
13043                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13044                 emitcode ("push","%s",
13045                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13046                 emitcode ("push","%s",
13047                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13048                 emitcode ("push","%s",
13049                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13050                 emitcode ("pop","ar3");
13051                 emitcode ("pop","ar2");
13052                 emitcode ("pop","ar1");
13053                 emitcode ("pop","ar0");
13054         } else {
13055                 emitcode ("mov","r0,%s",
13056                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13057                 emitcode ("mov","r1,%s",
13058                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13059                 emitcode ("mov","r2,%s",
13060                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13061                 emitcode ("mov","r3,%s",
13062                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13063         }
13064         freeAsmop (to, NULL, ic, FALSE);
13065
13066         /* suspend in acc */
13067         s = parms[1];
13068         aopOp(s,ic,FALSE,FALSE);
13069         emitcode ("mov","a,%s",
13070                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
13071         freeAsmop (s, NULL, ic, FALSE);
13072
13073         /* make the call */
13074         emitcode ("lcall","System_%s",name);
13075
13076         unsavermask(rsave);
13077 }
13078
13079 /*-----------------------------------------------------------------*/
13080 /* genSystemThreadResume -                                         */
13081 /*-----------------------------------------------------------------*/
13082 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13083 {
13084         bitVect *rsave ;
13085         operand *tid,*pid;
13086
13087         assert (nparms==2);
13088         /* save registers that need to be saved */
13089         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13090                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13091
13092         tid = parms[0];
13093         pid = parms[1];
13094
13095         /* PID in R0 */
13096         aopOp(pid,ic,FALSE,FALSE);
13097         emitcode ("mov","r0,%s",
13098                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13099         freeAsmop (pid, NULL, ic, FALSE);
13100
13101         /* tid into ACC */
13102         aopOp(tid,ic,FALSE,FALSE);
13103         emitcode ("mov","a,%s",
13104                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13105         freeAsmop (tid, NULL, ic, FALSE);
13106
13107         emitcode ("lcall","System_ThreadResume");
13108
13109         /* put result into place */
13110         {
13111                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13112                 if (rsym->liveFrom != rsym->liveTo) {
13113                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13114                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13115                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13116                 }
13117         }
13118         unsavermask(rsave);
13119 }
13120
13121 /*-----------------------------------------------------------------*/
13122 /* genSystemProcessResume -                                        */
13123 /*-----------------------------------------------------------------*/
13124 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13125 {
13126         bitVect *rsave ;
13127         operand *pid;
13128
13129         assert (nparms==1);
13130         /* save registers that need to be saved */
13131         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13132                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13133
13134         pid = parms[0];
13135
13136         /* pid into ACC */
13137         aopOp(pid,ic,FALSE,FALSE);
13138         emitcode ("mov","a,%s",
13139                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13140         freeAsmop (pid, NULL, ic, FALSE);
13141
13142         emitcode ("lcall","System_ProcessResume");
13143
13144         unsavermask(rsave);
13145 }
13146
13147 /*-----------------------------------------------------------------*/
13148 /* genSystem -                                                     */
13149 /*-----------------------------------------------------------------*/
13150 static void genSystem (iCode *ic,int nparms,char *name)
13151 {
13152         assert(nparms == 0);
13153
13154         emitcode ("lcall","System_%s",name);
13155 }
13156
13157 /*-----------------------------------------------------------------*/
13158 /* genSystemPoll -                                                  */
13159 /*-----------------------------------------------------------------*/
13160 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13161 {
13162         bitVect *rsave ;
13163         operand *fp;
13164
13165         assert (nparms==1);
13166         /* save registers that need to be saved */
13167         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13168                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13169
13170         fp = parms[0];
13171         aopOp (fp,ic,FALSE,FALSE);
13172         if (AOP_TYPE (fp) == AOP_IMMD) {
13173                 emitcode ("mov", "dptr,%s",
13174                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13175         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13176                 emitcode ("mov","dpl,%s",
13177                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13178                 emitcode ("mov","dph,%s",
13179                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13180                 emitcode ("mov","dpx,%s",
13181                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13182         }
13183         freeAsmop (fp, NULL, ic, FALSE);
13184
13185         emitcode ("lcall","System_%sPoll",name);
13186
13187         /* put result into place */
13188         {
13189                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13190                 if (rsym->liveFrom != rsym->liveTo) {
13191                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13192                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13193                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13194                 }
13195         }
13196         unsavermask(rsave);
13197 }
13198
13199 /*-----------------------------------------------------------------*/
13200 /* genSystemGetCurrentID -                                         */
13201 /*-----------------------------------------------------------------*/
13202 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13203 {
13204         assert (nparms==0);
13205
13206         emitcode ("lcall","System_GetCurrent%sId",name);
13207         /* put result into place */
13208         {
13209                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13210                 if (rsym->liveFrom != rsym->liveTo) {
13211                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13212                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13213                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13214                 }
13215         }
13216 }
13217
13218 /*-----------------------------------------------------------------*/
13219 /* genDummyRead - generate code for dummy read of volatiles        */
13220 /*-----------------------------------------------------------------*/
13221 static void
13222 genDummyRead (iCode * ic)
13223 {
13224   operand *op;
13225   int size, offset;
13226
13227   D(emitcode(";     genDummyRead",""));
13228
13229   op = IC_RIGHT (ic);
13230   if (op && IS_SYMOP (op))
13231     {
13232       aopOp (op, ic, FALSE, FALSE);
13233
13234       /* if the result is a bit */
13235       if (AOP_TYPE (op) == AOP_CRY)
13236         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13237       else
13238         {
13239           /* bit variables done */
13240           /* general case */
13241           size = AOP_SIZE (op);
13242           offset = 0;
13243           while (size--)
13244           {
13245             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13246             offset++;
13247           }
13248         }
13249
13250       freeAsmop (op, NULL, ic, TRUE);
13251     }
13252
13253   op = IC_LEFT (ic);
13254   if (op && IS_SYMOP (op))
13255     {
13256       aopOp (op, ic, FALSE, FALSE);
13257
13258       /* if the result is a bit */
13259       if (AOP_TYPE (op) == AOP_CRY)
13260         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13261       else
13262         {
13263           /* bit variables done */
13264           /* general case */
13265           size = AOP_SIZE (op);
13266           offset = 0;
13267           while (size--)
13268           {
13269             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13270             offset++;
13271           }
13272         }
13273
13274       freeAsmop (op, NULL, ic, TRUE);
13275     }
13276
13277 }
13278
13279 /*-----------------------------------------------------------------*/
13280 /* genCritical - generate code for start of a critical sequence    */
13281 /*-----------------------------------------------------------------*/
13282 static void
13283 genCritical (iCode *ic)
13284 {
13285   symbol *tlbl = newiTempLabel (NULL);
13286
13287   D(emitcode(";     genCritical",""));
13288
13289   if (IC_RESULT (ic))
13290     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13291
13292   emitcode ("setb", "c");
13293   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13294   emitcode ("clr", "c");
13295   emitcode ("", "%05d$:", (tlbl->key + 100));
13296
13297   if (IC_RESULT (ic))
13298     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13299   else
13300     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13301
13302   if (IC_RESULT (ic))
13303     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13304 }
13305
13306 /*-----------------------------------------------------------------*/
13307 /* genEndCritical - generate code for end of a critical sequence   */
13308 /*-----------------------------------------------------------------*/
13309 static void
13310 genEndCritical (iCode *ic)
13311 {
13312   D(emitcode(";     genEndCritical",""));
13313
13314   if (IC_RIGHT (ic))
13315     {
13316       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13317       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13318         {
13319           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13320           emitcode ("mov", "ea,c");
13321         }
13322       else
13323         {
13324           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13325           emitcode ("rrc", "a");
13326           emitcode ("mov", "ea,c");
13327         }
13328       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13329     }
13330   else
13331     {
13332       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13333       emitcode ("mov", "ea,c");
13334     }
13335 }
13336
13337
13338
13339 /*-----------------------------------------------------------------*/
13340 /* genBuiltIn - calls the appropriate function to  generating code */
13341 /* for a built in function                                         */
13342 /*-----------------------------------------------------------------*/
13343 static void genBuiltIn (iCode *ic)
13344 {
13345         operand *bi_parms[MAX_BUILTIN_ARGS];
13346         int nbi_parms;
13347         iCode *bi_iCode;
13348         symbol *bif;
13349
13350         /* get all the arguments for a built in function */
13351         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13352
13353         /* which function is it */
13354         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13355         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13356                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13357         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13358                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13359         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13360                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13361         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13362                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13363         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13364                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13365         } else if (strcmp(bif->name,"__builtin_inp")==0) {
13366                 genInp(bi_iCode,nbi_parms,bi_parms);
13367         } else if (strcmp(bif->name,"__builtin_outp")==0) {
13368                 genOutp(bi_iCode,nbi_parms,bi_parms);
13369         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13370                 genSwapW(bi_iCode,nbi_parms,bi_parms);
13371                 /* JavaNative builtIns */
13372         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13373                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13374         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13375                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13376         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13377                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13378         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13379                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13380         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13381                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13382         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13383                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13384         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13385                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13386         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13387                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13388         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13389                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13390         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13391                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13392         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13393                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13394         } else if (strcmp(bif->name,"MM_Malloc")==0) {
13395                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13396         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13397                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13398         } else if (strcmp(bif->name,"MM_Free")==0) {
13399                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13400         } else if (strcmp(bif->name,"MM_Deref")==0) {
13401                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13402         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13403                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13404         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13405                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13406         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13407                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13408         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13409                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13410         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13411                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13412         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13413                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13414         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13415                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13416         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13417                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13418         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13419                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13420         } else if (strcmp(bif->name,"System_SaveThread")==0) {
13421                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13422         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13423                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13424         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13425                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13426         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13427                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13428         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13429                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13430         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13431                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13432         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13433                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13434         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13435                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13436         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13437                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13438         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13439                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13440         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13441                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13442         } else {
13443                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13444                 return ;
13445         }
13446         return ;
13447 }
13448
13449 /*-----------------------------------------------------------------*/
13450 /* gen390Code - generate code for Dallas 390 based controllers     */
13451 /*-----------------------------------------------------------------*/
13452 void
13453 gen390Code (iCode * lic)
13454 {
13455   iCode *ic;
13456   int cln = 0;
13457
13458   lineHead = lineCurr = NULL;
13459   dptrn[1][0] = "dpl1";
13460   dptrn[1][1] = "dph1";
13461   dptrn[1][2] = "dpx1";
13462
13463   if (options.model == MODEL_FLAT24) {
13464     fReturnSizeDS390 = 5;
13465     fReturn = fReturn24;
13466   } else {
13467     fReturnSizeDS390 = 4;
13468     fReturn = fReturn16;
13469     options.stack10bit=0;
13470   }
13471 #if 1
13472   /* print the allocation information */
13473   if (allocInfo && currFunc)
13474     printAllocInfo (currFunc, codeOutFile);
13475 #endif
13476   /* if debug information required */
13477   if (options.debug && currFunc)
13478     {
13479       debugFile->writeFunction (currFunc, lic);
13480     }
13481   /* stack pointer name */
13482   if (options.useXstack)
13483     spname = "_spx";
13484   else
13485     spname = "sp";
13486
13487
13488   for (ic = lic; ic; ic = ic->next)
13489     {
13490       _G.current_iCode = ic;
13491
13492       if (ic->lineno && cln != ic->lineno)
13493         {
13494           if (options.debug)
13495             {
13496               debugFile->writeCLine (ic);
13497             }
13498           if (!options.noCcodeInAsm) {
13499             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13500                       printCLine(ic->filename, ic->lineno));
13501           }
13502           cln = ic->lineno;
13503         }
13504       if (options.iCodeInAsm) {
13505         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13506       }
13507       /* if the result is marked as
13508          spilt and rematerializable or code for
13509          this has already been generated then
13510          do nothing */
13511       if (resultRemat (ic) || ic->generated)
13512         continue;
13513
13514       /* depending on the operation */
13515       switch (ic->op)
13516         {
13517         case '!':
13518           genNot (ic);
13519           break;
13520
13521         case '~':
13522           genCpl (ic);
13523           break;
13524
13525         case UNARYMINUS:
13526           genUminus (ic);
13527           break;
13528
13529         case IPUSH:
13530           genIpush (ic);
13531           break;
13532
13533         case IPOP:
13534           /* IPOP happens only when trying to restore a
13535              spilt live range, if there is an ifx statement
13536              following this pop then the if statement might
13537              be using some of the registers being popped which
13538              would destory the contents of the register so
13539              we need to check for this condition and handle it */
13540           if (ic->next &&
13541               ic->next->op == IFX &&
13542               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13543             genIfx (ic->next, ic);
13544           else
13545             genIpop (ic);
13546           break;
13547
13548         case CALL:
13549           genCall (ic);
13550           break;
13551
13552         case PCALL:
13553           genPcall (ic);
13554           break;
13555
13556         case FUNCTION:
13557           genFunction (ic);
13558           break;
13559
13560         case ENDFUNCTION:
13561           genEndFunction (ic);
13562           break;
13563
13564         case RETURN:
13565           genRet (ic);
13566           break;
13567
13568         case LABEL:
13569           genLabel (ic);
13570           break;
13571
13572         case GOTO:
13573           genGoto (ic);
13574           break;
13575
13576         case '+':
13577           genPlus (ic);
13578           break;
13579
13580         case '-':
13581           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13582             genMinus (ic);
13583           break;
13584
13585         case '*':
13586           genMult (ic);
13587           break;
13588
13589         case '/':
13590           genDiv (ic);
13591           break;
13592
13593         case '%':
13594           genMod (ic);
13595           break;
13596
13597         case '>':
13598           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13599           break;
13600
13601         case '<':
13602           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13603           break;
13604
13605         case LE_OP:
13606         case GE_OP:
13607         case NE_OP:
13608
13609           /* note these two are xlated by algebraic equivalence
13610              during parsing SDCC.y */
13611           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13612                   "got '>=' or '<=' shouldn't have come here");
13613           break;
13614
13615         case EQ_OP:
13616           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13617           break;
13618
13619         case AND_OP:
13620           genAndOp (ic);
13621           break;
13622
13623         case OR_OP:
13624           genOrOp (ic);
13625           break;
13626
13627         case '^':
13628           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13629           break;
13630
13631         case '|':
13632           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13633           break;
13634
13635         case BITWISEAND:
13636           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13637           break;
13638
13639         case INLINEASM:
13640           genInline (ic);
13641           break;
13642
13643         case RRC:
13644           genRRC (ic);
13645           break;
13646
13647         case RLC:
13648           genRLC (ic);
13649           break;
13650
13651         case GETHBIT:
13652           genGetHbit (ic);
13653           break;
13654
13655         case LEFT_OP:
13656           genLeftShift (ic);
13657           break;
13658
13659         case RIGHT_OP:
13660           genRightShift (ic);
13661           break;
13662
13663         case GET_VALUE_AT_ADDRESS:
13664           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13665           break;
13666
13667         case '=':
13668           if (POINTER_SET (ic))
13669             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13670           else
13671             genAssign (ic);
13672           break;
13673
13674         case IFX:
13675           genIfx (ic, NULL);
13676           break;
13677
13678         case ADDRESS_OF:
13679           genAddrOf (ic);
13680           break;
13681
13682         case JUMPTABLE:
13683           genJumpTab (ic);
13684           break;
13685
13686         case CAST:
13687           genCast (ic);
13688           break;
13689
13690         case RECEIVE:
13691           genReceive (ic);
13692           break;
13693
13694         case SEND:
13695           if (ic->builtinSEND) genBuiltIn(ic);
13696           else addSet (&_G.sendSet, ic);
13697           break;
13698
13699         case DUMMY_READ_VOLATILE:
13700           genDummyRead (ic);
13701           break;
13702
13703         case CRITICAL:
13704           genCritical (ic);
13705           break;
13706
13707         case ENDCRITICAL:
13708           genEndCritical (ic);
13709           break;
13710
13711         case SWAP:
13712           genSwap (ic);
13713           break;
13714
13715 #if 0 // obsolete, and buggy for != xdata
13716         case ARRAYINIT:
13717             genArrayInit(ic);
13718             break;
13719 #endif
13720
13721         default:
13722           ic = ic;
13723         }
13724     }
13725
13726
13727   /* now we are ready to call the
13728      peep hole optimizer */
13729   if (!options.nopeep)
13730     peepHole (&lineHead);
13731
13732   /* now do the actual printing */
13733   printLine (lineHead, codeOutFile);
13734   return;
13735 }