* as/hc08/lkaomf51.c (OutputName): made name unsigned char,
[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           werror(W_COMPLEMENT);
1934           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1935           goto release;
1936         }
1937       tlbl=newiTempLabel(NULL);
1938       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE, NULL);
1939       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1940           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1941           IS_AOP_PREG (IC_LEFT (ic)))
1942         {
1943           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1944         }
1945       else
1946         {
1947           MOVA (l);
1948           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1949         }
1950       emitcode ("", "%05d$:", tlbl->key+100);
1951       outBitC (IC_RESULT(ic));
1952       goto release;
1953     }
1954
1955   size = AOP_SIZE (IC_RESULT (ic));
1956   _startLazyDPSEvaluation ();
1957   while (size--)
1958     {
1959       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1960       emitcode ("cpl", "a");
1961       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1962     }
1963   _endLazyDPSEvaluation ();
1964
1965
1966 release:
1967   /* release the aops */
1968   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1969   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1970 }
1971
1972 /*-----------------------------------------------------------------*/
1973 /* genUminusFloat - unary minus for floating points                */
1974 /*-----------------------------------------------------------------*/
1975 static void
1976 genUminusFloat (operand * op, operand * result)
1977 {
1978   int size, offset = 0;
1979
1980   D(emitcode (";", "genUminusFloat"););
1981
1982   /* for this we just copy and then flip the bit */
1983
1984   _startLazyDPSEvaluation ();
1985   size = AOP_SIZE (op) - 1;
1986
1987   while (size--)
1988     {
1989       aopPut (AOP (result),
1990               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1991               offset);
1992       offset++;
1993     }
1994
1995   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1996
1997   emitcode ("cpl", "acc.7");
1998   aopPut (AOP (result), "a", offset);
1999   _endLazyDPSEvaluation ();
2000 }
2001
2002 /*-----------------------------------------------------------------*/
2003 /* genUminus - unary minus code generation                         */
2004 /*-----------------------------------------------------------------*/
2005 static void
2006 genUminus (iCode * ic)
2007 {
2008   int offset, size;
2009   sym_link *optype;
2010
2011   D (emitcode (";", "genUminus "););
2012
2013   /* assign asmops */
2014   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2015   aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2016
2017   /* if both in bit space then special
2018      case */
2019   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2020       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2021     {
2022
2023       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2024       emitcode ("cpl", "c");
2025       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2026       goto release;
2027     }
2028
2029   optype = operandType (IC_LEFT (ic));
2030
2031   /* if float then do float stuff */
2032   if (IS_FLOAT (optype))
2033     {
2034       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2035       goto release;
2036     }
2037
2038   /* otherwise subtract from zero */
2039   size = AOP_SIZE (IC_LEFT (ic));
2040   offset = 0;
2041   _startLazyDPSEvaluation ();
2042   while (size--)
2043     {
2044       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2045       if (!strcmp (l, "a"))
2046         {
2047           if (offset == 0)
2048             SETC;
2049           emitcode ("cpl", "a");
2050           emitcode ("addc", "a,#0");
2051         }
2052       else
2053         {
2054           if (offset == 0)
2055             CLRC;
2056           emitcode ("clr", "a");
2057           emitcode ("subb", "a,%s", l);
2058         }
2059       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2060     }
2061   _endLazyDPSEvaluation ();
2062
2063   /* if any remaining bytes in the result */
2064   /* we just need to propagate the sign   */
2065   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2066     {
2067       emitcode ("rlc", "a");
2068       emitcode ("subb", "a,acc");
2069       while (size--)
2070         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2071     }
2072
2073 release:
2074   /* release the aops */
2075   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2076   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2077 }
2078
2079 /*-----------------------------------------------------------------*/
2080 /* savermask - saves registers in the mask                         */
2081 /*-----------------------------------------------------------------*/
2082 static void savermask(bitVect *rs_mask)
2083 {
2084     int i;
2085     if (options.useXstack) {
2086         if (bitVectBitValue (rs_mask, R0_IDX))
2087             emitcode ("mov", "b,r0");
2088         emitcode ("mov", "r0,%s", spname);
2089         for (i = 0; i < ds390_nRegs; i++) {
2090             if (bitVectBitValue (rs_mask, i)) {
2091                 if (i == R0_IDX)
2092                     emitcode ("mov", "a,b");
2093                 else
2094                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2095                 emitcode ("movx", "@r0,a");
2096                 emitcode ("inc", "r0");
2097             }
2098         }
2099         emitcode ("mov", "%s,r0", spname);
2100         if (bitVectBitValue (rs_mask, R0_IDX))
2101             emitcode ("mov", "r0,b");
2102     } else {
2103         for (i = 0; i < ds390_nRegs; i++) {
2104             if (bitVectBitValue (rs_mask, i))
2105                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2106         }
2107     }
2108 }
2109
2110 /*-----------------------------------------------------------------*/
2111 /* saveRegisters - will look for a call and save the registers     */
2112 /*-----------------------------------------------------------------*/
2113 static void
2114 saveRegisters (iCode * lic)
2115 {
2116   iCode *ic;
2117   bitVect *rsave;
2118
2119   /* look for call */
2120   for (ic = lic; ic; ic = ic->next)
2121     if (ic->op == CALL || ic->op == PCALL)
2122       break;
2123
2124   if (!ic)
2125     {
2126       fprintf (stderr, "found parameter push with no function call\n");
2127       return;
2128     }
2129
2130   /* if the registers have been saved already then
2131      do nothing */
2132   if (ic->regsSaved
2133       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2134     return ;
2135
2136   /* special case if DPTR alive across a function call then must save it
2137      even though callee saves */
2138   if (IS_SYMOP(IC_LEFT(ic)) &&
2139       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2140       int i;
2141       rsave = newBitVect(ic->rMask->size);
2142       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2143           if (bitVectBitValue(ic->rMask,i))
2144               rsave = bitVectSetBit(rsave,i);
2145       }
2146       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2147   } else {
2148     /* safe the registers in use at this time but skip the
2149        ones for the result */
2150     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2151                            ds390_rUmaskForOp (IC_RESULT(ic)));
2152   }
2153   ic->regsSaved = 1;
2154   savermask(rsave);
2155 }
2156
2157 /*-----------------------------------------------------------------*/
2158 /* usavermask - restore registers with mask                        */
2159 /*-----------------------------------------------------------------*/
2160 static void unsavermask(bitVect *rs_mask)
2161 {
2162     int i;
2163     if (options.useXstack) {
2164         emitcode ("mov", "r0,%s", spname);
2165         for (i = ds390_nRegs; i >= 0; i--) {
2166             if (bitVectBitValue (rs_mask, i)) {
2167                 emitcode ("dec", "r0");
2168                 emitcode ("movx", "a,@r0");
2169                 if (i == R0_IDX)
2170                     emitcode ("mov", "b,a");
2171                 else
2172                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2173             }
2174         }
2175         emitcode ("mov", "%s,r0", spname);
2176         if (bitVectBitValue (rs_mask, R0_IDX))
2177             emitcode ("mov", "r0,b");
2178     } else {
2179         for (i = ds390_nRegs; i >= 0; i--) {
2180             if (bitVectBitValue (rs_mask, i))
2181                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2182         }
2183     }
2184 }
2185
2186 /*-----------------------------------------------------------------*/
2187 /* unsaveRegisters - pop the pushed registers                      */
2188 /*-----------------------------------------------------------------*/
2189 static void
2190 unsaveRegisters (iCode * ic)
2191 {
2192   bitVect *rsave;
2193
2194   if (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 c->a:x->c by 1                         */
8067 /*-----------------------------------------------------------------*/
8068 static void
8069 AccAXRrl1 (char *x)
8070 {
8071   emitcode ("rrc", "a");
8072   emitcode ("xch", "a,%s", x);
8073   emitcode ("rrc", "a");
8074   emitcode ("xch", "a,%s", x);
8075 }
8076 #endif
8077
8078 #ifdef BETTER_LITERAL_SHIFT
8079 //REMOVE ME!!!
8080 /*-----------------------------------------------------------------*/
8081 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8082 /*-----------------------------------------------------------------*/
8083 static void
8084 AccAXLrl1 (char *x)
8085 {
8086   emitcode ("xch", "a,%s", x);
8087   emitcode ("rlc", "a");
8088   emitcode ("xch", "a,%s", x);
8089   emitcode ("rlc", "a");
8090 }
8091 #endif
8092
8093 #ifdef BETTER_LITERAL_SHIFT
8094 /*-----------------------------------------------------------------*/
8095 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8096 /*-----------------------------------------------------------------*/
8097 static void
8098 AccAXLsh1 (char *x)
8099 {
8100   emitcode ("xch", "a,%s", x);
8101   emitcode ("add", "a,acc");
8102   emitcode ("xch", "a,%s", x);
8103   emitcode ("rlc", "a");
8104 }
8105 #endif
8106
8107 #ifdef BETTER_LITERAL_SHIFT
8108 /*-----------------------------------------------------------------*/
8109 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8110 /*-----------------------------------------------------------------*/
8111 static void
8112 AccAXLsh (char *x, int shCount)
8113 {
8114   switch (shCount)
8115     {
8116     case 0:
8117       break;
8118     case 1:
8119       AccAXLsh1 (x);
8120       break;
8121     case 2:
8122       AccAXLsh1 (x);
8123       AccAXLsh1 (x);
8124       break;
8125     case 3:
8126     case 4:
8127     case 5:                     // AAAAABBB:CCCCCDDD
8128
8129       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8130
8131       emitcode ("anl", "a,#!constbyte",
8132                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8133
8134       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8135
8136       AccRol (shCount);         // DDDCCCCC:BBB00000
8137
8138       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8139
8140       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8141
8142       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8143
8144       emitcode ("anl", "a,#!constbyte",
8145                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8146
8147       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8148
8149       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8150
8151       break;
8152     case 6:                     // AAAAAABB:CCCCCCDD
8153       emitcode ("anl", "a,#!constbyte",
8154                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8155       emitcode ("mov", "c,acc.0");      // c = B
8156       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8157 #if 0
8158       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8159       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8160 #else
8161       emitcode("rrc","a");
8162       emitcode("xch","a,%s", x);
8163       emitcode("rrc","a");
8164       emitcode("mov","c,acc.0"); //<< get correct bit
8165       emitcode("xch","a,%s", x);
8166
8167       emitcode("rrc","a");
8168       emitcode("xch","a,%s", x);
8169       emitcode("rrc","a");
8170       emitcode("xch","a,%s", x);
8171 #endif
8172       break;
8173     case 7:                     // a:x <<= 7
8174
8175       emitcode ("anl", "a,#!constbyte",
8176                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8177
8178       emitcode ("mov", "c,acc.0");      // c = B
8179
8180       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8181
8182       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8183
8184       break;
8185     default:
8186       break;
8187     }
8188 }
8189 #endif
8190
8191 #ifdef BETTER_LITERAL_SHIFT
8192 //REMOVE ME!!!
8193 /*-----------------------------------------------------------------*/
8194 /* AccAXRsh - right shift a:x known count (0..7)                   */
8195 /*-----------------------------------------------------------------*/
8196 static void
8197 AccAXRsh (char *x, int shCount)
8198 {
8199   switch (shCount)
8200     {
8201     case 0:
8202       break;
8203     case 1:
8204       CLRC;
8205       AccAXRrl1 (x);            // 0->a:x
8206
8207       break;
8208     case 2:
8209       CLRC;
8210       AccAXRrl1 (x);            // 0->a:x
8211
8212       CLRC;
8213       AccAXRrl1 (x);            // 0->a:x
8214
8215       break;
8216     case 3:
8217     case 4:
8218     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8219
8220       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8221
8222       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8223
8224       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8225
8226       emitcode ("anl", "a,#!constbyte",
8227                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8228
8229       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8230
8231       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8232
8233       emitcode ("anl", "a,#!constbyte",
8234                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8235
8236       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8237
8238       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8239
8240       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8241
8242       break;
8243     case 6:                     // AABBBBBB:CCDDDDDD
8244
8245       emitcode ("mov", "c,acc.7");
8246       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8247
8248       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8249
8250       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8251
8252       emitcode ("anl", "a,#!constbyte",
8253                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8254
8255       break;
8256     case 7:                     // ABBBBBBB:CDDDDDDD
8257
8258       emitcode ("mov", "c,acc.7");      // c = A
8259
8260       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8261
8262       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8263
8264       emitcode ("anl", "a,#!constbyte",
8265                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8266
8267       break;
8268     default:
8269       break;
8270     }
8271 }
8272 #endif
8273
8274 #ifdef BETTER_LITERAL_SHIFT
8275 /*-----------------------------------------------------------------*/
8276 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8277 /*-----------------------------------------------------------------*/
8278 static void
8279 AccAXRshS (char *x, int shCount)
8280 {
8281   symbol *tlbl;
8282   switch (shCount)
8283     {
8284     case 0:
8285       break;
8286     case 1:
8287       emitcode ("mov", "c,acc.7");
8288       AccAXRrl1 (x);            // s->a:x
8289
8290       break;
8291     case 2:
8292       emitcode ("mov", "c,acc.7");
8293       AccAXRrl1 (x);            // s->a:x
8294
8295       emitcode ("mov", "c,acc.7");
8296       AccAXRrl1 (x);            // s->a:x
8297
8298       break;
8299     case 3:
8300     case 4:
8301     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8302
8303       tlbl = newiTempLabel (NULL);
8304       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8305
8306       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8307
8308       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8309
8310       emitcode ("anl", "a,#!constbyte",
8311                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8312
8313       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8314
8315       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8316
8317       emitcode ("anl", "a,#!constbyte",
8318                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8319
8320       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8321
8322       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8323
8324       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8325
8326       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8327       emitcode ("orl", "a,#!constbyte",
8328                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8329
8330       emitcode ("", "!tlabeldef", tlbl->key + 100);
8331       break;                    // SSSSAAAA:BBBCCCCC
8332
8333     case 6:                     // AABBBBBB:CCDDDDDD
8334
8335       tlbl = newiTempLabel (NULL);
8336       emitcode ("mov", "c,acc.7");
8337       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8338
8339       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8340
8341       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8342
8343       emitcode ("anl", "a,#!constbyte",
8344                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8345
8346       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8347       emitcode ("orl", "a,#!constbyte",
8348                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8349
8350       emitcode ("", "!tlabeldef", tlbl->key + 100);
8351       break;
8352     case 7:                     // ABBBBBBB:CDDDDDDD
8353
8354       tlbl = newiTempLabel (NULL);
8355       emitcode ("mov", "c,acc.7");      // c = A
8356
8357       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8358
8359       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8360
8361       emitcode ("anl", "a,#!constbyte",
8362                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8363
8364       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8365       emitcode ("orl", "a,#!constbyte",
8366                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8367
8368       emitcode ("", "!tlabeldef", tlbl->key + 100);
8369       break;
8370     default:
8371       break;
8372     }
8373 }
8374 #endif
8375
8376 #ifdef BETTER_LITERAL_SHIFT
8377 static void
8378 _loadLeftIntoAx(char    **lsb,
8379                 operand *left,
8380                 operand *result,
8381                 int     offl,
8382                 int     offr)
8383 {
8384   // Get the initial value from left into a pair of registers.
8385   // MSB must be in A, LSB can be any register.
8386   //
8387   // If the result is held in registers, it is an optimization
8388   // if the LSB can be held in the register which will hold the,
8389   // result LSB since this saves us from having to copy it into
8390   // the result following AccAXLsh.
8391   //
8392   // If the result is addressed indirectly, this is not a gain.
8393   if (AOP_NEEDSACC(result))
8394   {
8395        char *leftByte;
8396
8397        _startLazyDPSEvaluation();
8398       if (AOP_TYPE(left) == AOP_DPTR2)
8399        {
8400            // Get MSB in A.
8401            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8402            // get LSB in DP2_RESULT_REG.
8403            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8404            assert(!strcmp(leftByte, DP2_RESULT_REG));
8405        }
8406        else
8407        {
8408            // get LSB into DP2_RESULT_REG
8409            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8410            if (strcmp(leftByte, DP2_RESULT_REG))
8411            {
8412                TR_AP("#7");
8413                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8414            }
8415            // And MSB in A.
8416            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8417            assert(strcmp(leftByte, DP2_RESULT_REG));
8418            MOVA(leftByte);
8419        }
8420        _endLazyDPSEvaluation();
8421        *lsb = DP2_RESULT_REG;
8422   }
8423   else
8424   {
8425       if (sameRegs (AOP (result), AOP (left)) &&
8426         ((offl + MSB16) == offr))
8427       {
8428           /* don't crash result[offr] */
8429           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8430           emitcode ("xch", "a,%s",
8431                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8432       }
8433       else
8434       {
8435           movLeft2Result (left, offl, result, offr, 0);
8436           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8437       }
8438       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8439       assert(strcmp(*lsb,"a"));
8440   }
8441 }
8442
8443 static void
8444 _storeAxResults(char    *lsb,
8445                 operand *result,
8446                 int     offr)
8447 {
8448   _startLazyDPSEvaluation();
8449   if (AOP_NEEDSACC(result))
8450   {
8451       /* We have to explicitly update the result LSB.
8452        */
8453       emitcode("xch","a,%s", lsb);
8454       aopPut(AOP(result), "a", offr);
8455       emitcode("mov","a,%s", lsb);
8456   }
8457   if (getDataSize (result) > 1)
8458   {
8459       aopPut (AOP (result), "a", offr + MSB16);
8460   }
8461   _endLazyDPSEvaluation();
8462 }
8463
8464 /*-----------------------------------------------------------------*/
8465 /* shiftL2Left2Result - shift left two bytes from left to result   */
8466 /*-----------------------------------------------------------------*/
8467 static void
8468 shiftL2Left2Result (operand * left, int offl,
8469                     operand * result, int offr, int shCount)
8470 {
8471   char *lsb;
8472
8473   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8474
8475   AccAXLsh (lsb, shCount);
8476
8477   _storeAxResults(lsb, result, offr);
8478 }
8479 #endif
8480
8481 #ifdef BETTER_LITERAL_SHIFT
8482 /*-----------------------------------------------------------------*/
8483 /* shiftR2Left2Result - shift right two bytes from left to result  */
8484 /*-----------------------------------------------------------------*/
8485 static void
8486 shiftR2Left2Result (operand * left, int offl,
8487                     operand * result, int offr,
8488                     int shCount, int sign)
8489 {
8490   char *lsb;
8491
8492   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8493
8494   /* a:x >> shCount (x = lsb(result)) */
8495   if (sign)
8496   {
8497      AccAXRshS(lsb, shCount);
8498   }
8499   else
8500   {
8501     AccAXRsh(lsb, shCount);
8502   }
8503
8504   _storeAxResults(lsb, result, offr);
8505 }
8506 #endif
8507
8508 /*-----------------------------------------------------------------*/
8509 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8510 /*-----------------------------------------------------------------*/
8511 static void
8512 shiftLLeftOrResult (operand * left, int offl,
8513                     operand * result, int offr, int shCount)
8514 {
8515   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8516   /* shift left accumulator */
8517   AccLsh (shCount);
8518   /* or with result */
8519   emitcode ("orl", "a,%s",
8520             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8521   /* back to result */
8522   aopPut (AOP (result), "a", offr);
8523 }
8524
8525 #if 0
8526 //REMOVE ME!!!
8527 /*-----------------------------------------------------------------*/
8528 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8529 /*-----------------------------------------------------------------*/
8530 static void
8531 shiftRLeftOrResult (operand * left, int offl,
8532                     operand * result, int offr, int shCount)
8533 {
8534   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8535   /* shift right accumulator */
8536   AccRsh (shCount);
8537   /* or with result */
8538   emitcode ("orl", "a,%s",
8539             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8540   /* back to result */
8541   aopPut (AOP (result), "a", offr);
8542 }
8543 #endif
8544
8545 #ifdef BETTER_LITERAL_SHIFT
8546 /*-----------------------------------------------------------------*/
8547 /* genlshOne - left shift a one byte quantity by known count       */
8548 /*-----------------------------------------------------------------*/
8549 static void
8550 genlshOne (operand * result, operand * left, int shCount)
8551 {
8552   D (emitcode (";", "genlshOne "););
8553   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8554 }
8555 #endif
8556
8557 #ifdef BETTER_LITERAL_SHIFT
8558 /*-----------------------------------------------------------------*/
8559 /* genlshTwo - left shift two bytes by known amount != 0           */
8560 /*-----------------------------------------------------------------*/
8561 static void
8562 genlshTwo (operand * result, operand * left, int shCount)
8563 {
8564   int size;
8565
8566   D (emitcode (";", "genlshTwo "););
8567
8568   size = getDataSize (result);
8569
8570   /* if shCount >= 8 */
8571   if (shCount >= 8)
8572   {
8573       shCount -= 8;
8574
8575       _startLazyDPSEvaluation();
8576
8577       if (size > 1)
8578         {
8579           if (shCount)
8580           {
8581             _endLazyDPSEvaluation();
8582             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8583             aopPut (AOP (result), zero, LSB);
8584           }
8585           else
8586           {
8587             movLeft2Result (left, LSB, result, MSB16, 0);
8588             aopPut (AOP (result), zero, LSB);
8589             _endLazyDPSEvaluation();
8590           }
8591         }
8592         else
8593         {
8594           aopPut (AOP (result), zero, LSB);
8595           _endLazyDPSEvaluation();
8596         }
8597   }
8598
8599   /*  1 <= shCount <= 7 */
8600   else
8601     {
8602       if (size == 1)
8603       {
8604         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8605       }
8606       else
8607       {
8608         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8609       }
8610     }
8611 }
8612 #endif
8613
8614 #if 0
8615 //REMOVE ME!!!
8616 /*-----------------------------------------------------------------*/
8617 /* shiftLLong - shift left one long from left to result            */
8618 /* offl = LSB or MSB16                                             */
8619 /*-----------------------------------------------------------------*/
8620 static void
8621 shiftLLong (operand * left, operand * result, int offr)
8622 {
8623   char *l;
8624   int size = AOP_SIZE (result);
8625
8626   if (size >= LSB + offr)
8627     {
8628       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8629       MOVA (l);
8630       emitcode ("add", "a,acc");
8631       if (sameRegs (AOP (left), AOP (result)) &&
8632           size >= MSB16 + offr && offr != LSB)
8633         emitcode ("xch", "a,%s",
8634                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8635       else
8636         aopPut (AOP (result), "a", LSB + offr);
8637     }
8638
8639   if (size >= MSB16 + offr)
8640     {
8641       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8642         {
8643           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8644         }
8645       emitcode ("rlc", "a");
8646       if (sameRegs (AOP (left), AOP (result)) &&
8647           size >= MSB24 + offr && offr != LSB)
8648         emitcode ("xch", "a,%s",
8649                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8650       else
8651         aopPut (AOP (result), "a", MSB16 + offr);
8652     }
8653
8654   if (size >= MSB24 + offr)
8655     {
8656       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8657         {
8658           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8659         }
8660       emitcode ("rlc", "a");
8661       if (sameRegs (AOP (left), AOP (result)) &&
8662           size >= MSB32 + offr && offr != LSB)
8663         emitcode ("xch", "a,%s",
8664                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8665       else
8666         aopPut (AOP (result), "a", MSB24 + offr);
8667     }
8668
8669   if (size > MSB32 + offr)
8670     {
8671       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8672         {
8673           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8674         }
8675       emitcode ("rlc", "a");
8676       aopPut (AOP (result), "a", MSB32 + offr);
8677     }
8678   if (offr != LSB)
8679     aopPut (AOP (result), zero, LSB);
8680 }
8681 #endif
8682
8683 #if 0
8684 //REMOVE ME!!!
8685 /*-----------------------------------------------------------------*/
8686 /* genlshFour - shift four byte by a known amount != 0             */
8687 /*-----------------------------------------------------------------*/
8688 static void
8689 genlshFour (operand * result, operand * left, int shCount)
8690 {
8691   int size;
8692
8693   D (emitcode (";", "genlshFour ");
8694     );
8695
8696   size = AOP_SIZE (result);
8697
8698   /* if shifting more that 3 bytes */
8699   if (shCount >= 24)
8700     {
8701       shCount -= 24;
8702       if (shCount)
8703         /* lowest order of left goes to the highest
8704            order of the destination */
8705         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8706       else
8707         movLeft2Result (left, LSB, result, MSB32, 0);
8708       aopPut (AOP (result), zero, LSB);
8709       aopPut (AOP (result), zero, MSB16);
8710       aopPut (AOP (result), zero, MSB24);
8711       return;
8712     }
8713
8714   /* more than two bytes */
8715   else if (shCount >= 16)
8716     {
8717       /* lower order two bytes goes to higher order two bytes */
8718       shCount -= 16;
8719       /* if some more remaining */
8720       if (shCount)
8721         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8722       else
8723         {
8724           movLeft2Result (left, MSB16, result, MSB32, 0);
8725           movLeft2Result (left, LSB, result, MSB24, 0);
8726         }
8727       aopPut (AOP (result), zero, MSB16);
8728       aopPut (AOP (result), zero, LSB);
8729       return;
8730     }
8731
8732   /* if more than 1 byte */
8733   else if (shCount >= 8)
8734     {
8735       /* lower order three bytes goes to higher order  three bytes */
8736       shCount -= 8;
8737       if (size == 2)
8738         {
8739           if (shCount)
8740             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8741           else
8742             movLeft2Result (left, LSB, result, MSB16, 0);
8743         }
8744       else
8745         {                       /* size = 4 */
8746           if (shCount == 0)
8747             {
8748               movLeft2Result (left, MSB24, result, MSB32, 0);
8749               movLeft2Result (left, MSB16, result, MSB24, 0);
8750               movLeft2Result (left, LSB, result, MSB16, 0);
8751               aopPut (AOP (result), zero, LSB);
8752             }
8753           else if (shCount == 1)
8754             shiftLLong (left, result, MSB16);
8755           else
8756             {
8757               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8758               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8759               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8760               aopPut (AOP (result), zero, LSB);
8761             }
8762         }
8763     }
8764
8765   /* 1 <= shCount <= 7 */
8766   else if (shCount <= 2)
8767     {
8768       shiftLLong (left, result, LSB);
8769       if (shCount == 2)
8770         shiftLLong (result, result, LSB);
8771     }
8772   /* 3 <= shCount <= 7, optimize */
8773   else
8774     {
8775       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8776       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8777       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8778     }
8779 }
8780 #endif
8781
8782 #ifdef BETTER_LITERAL_SHIFT
8783 /*-----------------------------------------------------------------*/
8784 /* genLeftShiftLiteral - left shifting by known count              */
8785 /*-----------------------------------------------------------------*/
8786 static bool
8787 genLeftShiftLiteral (operand * left,
8788                      operand * right,
8789                      operand * result,
8790                      iCode * ic)
8791 {
8792   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8793   int size;
8794
8795   size = getSize (operandType (result));
8796
8797   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8798
8799   /* We only handle certain easy cases so far. */
8800   if ((shCount != 0)
8801    && (shCount < (size * 8))
8802    && (size != 1)
8803    && (size != 2))
8804   {
8805       D(emitcode (";", "genLeftShiftLiteral wimping out"););
8806       return FALSE;
8807   }
8808
8809   freeAsmop (right, NULL, ic, TRUE);
8810
8811   aopOp(left, ic, FALSE, FALSE);
8812   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8813
8814 #if 0 // debug spew
8815   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8816   {
8817         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8818         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8819         {
8820            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8821         }
8822   }
8823   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8824   {
8825         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8826         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8827         {
8828            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8829         }
8830   }
8831 #endif
8832
8833 #if VIEW_SIZE
8834   emitcode ("; shift left ", "result %d, left %d", size,
8835             AOP_SIZE (left));
8836 #endif
8837
8838   /* I suppose that the left size >= result size */
8839   if (shCount == 0)
8840   {
8841         _startLazyDPSEvaluation();
8842         while (size--)
8843         {
8844           movLeft2Result (left, size, result, size, 0);
8845         }
8846         _endLazyDPSEvaluation();
8847   }
8848   else if (shCount >= (size * 8))
8849   {
8850     _startLazyDPSEvaluation();
8851     while (size--)
8852     {
8853       aopPut (AOP (result), zero, size);
8854     }
8855     _endLazyDPSEvaluation();
8856   }
8857   else
8858   {
8859       switch (size)
8860         {
8861         case 1:
8862           genlshOne (result, left, shCount);
8863           break;
8864
8865         case 2:
8866           genlshTwo (result, left, shCount);
8867           break;
8868 #if 0
8869         case 4:
8870           genlshFour (result, left, shCount);
8871           break;
8872 #endif
8873         default:
8874           fprintf(stderr, "*** ack! mystery literal shift!\n");
8875           break;
8876         }
8877     }
8878   freeAsmop (left, NULL, ic, TRUE);
8879   freeAsmop (result, NULL, ic, TRUE);
8880   return TRUE;
8881 }
8882 #endif
8883
8884 /*-----------------------------------------------------------------*/
8885 /* genLeftShift - generates code for left shifting                 */
8886 /*-----------------------------------------------------------------*/
8887 static void
8888 genLeftShift (iCode * ic)
8889 {
8890   operand *left, *right, *result;
8891   int size, offset;
8892   char *l;
8893   symbol *tlbl, *tlbl1;
8894
8895   D (emitcode (";", "genLeftShift "););
8896
8897   right = IC_RIGHT (ic);
8898   left = IC_LEFT (ic);
8899   result = IC_RESULT (ic);
8900
8901   aopOp (right, ic, FALSE, FALSE);
8902
8903
8904 #ifdef BETTER_LITERAL_SHIFT
8905   /* if the shift count is known then do it
8906      as efficiently as possible */
8907   if (AOP_TYPE (right) == AOP_LIT)
8908     {
8909       if (genLeftShiftLiteral (left, right, result, ic))
8910       {
8911         return;
8912       }
8913     }
8914 #endif
8915
8916   /* shift count is unknown then we have to form
8917      a loop get the loop count in B : Note: we take
8918      only the lower order byte since shifting
8919      more that 32 bits make no sense anyway, ( the
8920      largest size of an object can be only 32 bits ) */
8921
8922   if (AOP_TYPE (right) == AOP_LIT)
8923   {
8924       /* Really should be handled by genLeftShiftLiteral,
8925        * but since I'm too lazy to fix that today, at least we can make
8926        * some small improvement.
8927        */
8928        emitcode("mov", "b,#!constbyte",
8929                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8930   }
8931   else
8932   {
8933       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8934       emitcode ("inc", "b");
8935   }
8936   freeAsmop (right, NULL, ic, TRUE);
8937   aopOp (left, ic, FALSE, FALSE);
8938   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8939
8940   /* now move the left to the result if they are not the
8941      same */
8942   if (!sameRegs (AOP (left), AOP (result)) &&
8943       AOP_SIZE (result) > 1)
8944     {
8945
8946       size = AOP_SIZE (result);
8947       offset = 0;
8948       _startLazyDPSEvaluation ();
8949       while (size--)
8950         {
8951           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8952           if (*l == '@' && (IS_AOP_PREG (result)))
8953             {
8954
8955               emitcode ("mov", "a,%s", l);
8956               aopPut (AOP (result), "a", offset);
8957             }
8958           else
8959             aopPut (AOP (result), l, offset);
8960           offset++;
8961         }
8962       _endLazyDPSEvaluation ();
8963     }
8964
8965   tlbl = newiTempLabel (NULL);
8966   size = AOP_SIZE (result);
8967   offset = 0;
8968   tlbl1 = newiTempLabel (NULL);
8969
8970   /* if it is only one byte then */
8971   if (size == 1)
8972     {
8973       symbol *tlbl1 = newiTempLabel (NULL);
8974
8975       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8976       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8977       emitcode ("", "!tlabeldef", tlbl->key + 100);
8978       emitcode ("add", "a,acc");
8979       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8980       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8981       aopPut (AOP (result), "a", 0);
8982       goto release;
8983     }
8984
8985   reAdjustPreg (AOP (result));
8986
8987   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8988   emitcode ("", "!tlabeldef", tlbl->key + 100);
8989   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8990   emitcode ("add", "a,acc");
8991   aopPut (AOP (result), "a", offset++);
8992   _startLazyDPSEvaluation ();
8993   while (--size)
8994     {
8995       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8996       emitcode ("rlc", "a");
8997       aopPut (AOP (result), "a", offset++);
8998     }
8999   _endLazyDPSEvaluation ();
9000   reAdjustPreg (AOP (result));
9001
9002   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9003   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9004 release:
9005   freeAsmop (left, NULL, ic, TRUE);
9006   freeAsmop (result, NULL, ic, TRUE);
9007 }
9008
9009 #ifdef BETTER_LITERAL_SHIFT
9010 /*-----------------------------------------------------------------*/
9011 /* genrshOne - right shift a one byte quantity by known count      */
9012 /*-----------------------------------------------------------------*/
9013 static void
9014 genrshOne (operand * result, operand * left,
9015            int shCount, int sign)
9016 {
9017   D (emitcode (";", "genrshOne"););
9018   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9019 }
9020 #endif
9021
9022 #ifdef BETTER_LITERAL_SHIFT
9023 /*-----------------------------------------------------------------*/
9024 /* genrshTwo - right shift two bytes by known amount != 0          */
9025 /*-----------------------------------------------------------------*/
9026 static void
9027 genrshTwo (operand * result, operand * left,
9028            int shCount, int sign)
9029 {
9030   D (emitcode (";", "genrshTwo"););
9031
9032   /* if shCount >= 8 */
9033   if (shCount >= 8)
9034     {
9035       shCount -= 8;
9036       _startLazyDPSEvaluation();
9037       if (shCount)
9038       {
9039         shiftR1Left2Result (left, MSB16, result, LSB,
9040                             shCount, sign);
9041       }
9042       else
9043       {
9044         movLeft2Result (left, MSB16, result, LSB, sign);
9045       }
9046       addSign (result, MSB16, sign);
9047       _endLazyDPSEvaluation();
9048     }
9049
9050   /*  1 <= shCount <= 7 */
9051   else
9052   {
9053     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9054   }
9055 }
9056 #endif
9057
9058 /*-----------------------------------------------------------------*/
9059 /* shiftRLong - shift right one long from left to result           */
9060 /* offl = LSB or MSB16                                             */
9061 /*-----------------------------------------------------------------*/
9062 static void
9063 shiftRLong (operand * left, int offl,
9064             operand * result, int sign)
9065 {
9066   int isSameRegs=sameRegs(AOP(left),AOP(result));
9067
9068   if (isSameRegs && offl>1) {
9069     // we are in big trouble, but this shouldn't happen
9070     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9071   }
9072
9073   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9074
9075   if (offl==MSB16) {
9076     // shift is > 8
9077     if (sign) {
9078       emitcode ("rlc", "a");
9079       emitcode ("subb", "a,acc");
9080       emitcode ("xch", "a,%s",
9081                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9082     } else {
9083       aopPut (AOP(result), zero, MSB32);
9084     }
9085   }
9086
9087   if (!sign) {
9088     emitcode ("clr", "c");
9089   } else {
9090     emitcode ("mov", "c,acc.7");
9091   }
9092
9093   emitcode ("rrc", "a");
9094
9095   if (isSameRegs && offl==MSB16) {
9096     emitcode ("xch",
9097               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9098   } else {
9099     aopPut (AOP (result), "a", MSB32);
9100     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9101   }
9102
9103   emitcode ("rrc", "a");
9104   if (isSameRegs && offl==1) {
9105     emitcode ("xch", "a,%s",
9106               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9107   } else {
9108     aopPut (AOP (result), "a", MSB24);
9109     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9110   }
9111   emitcode ("rrc", "a");
9112   aopPut (AOP (result), "a", MSB16 - offl);
9113
9114   if (offl == LSB)
9115     {
9116       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9117       emitcode ("rrc", "a");
9118       aopPut (AOP (result), "a", LSB);
9119     }
9120 }
9121
9122 /*-----------------------------------------------------------------*/
9123 /* genrshFour - shift four byte by a known amount != 0             */
9124 /*-----------------------------------------------------------------*/
9125 static void
9126 genrshFour (operand * result, operand * left,
9127             int shCount, int sign)
9128 {
9129   D (emitcode (";", "genrshFour"););
9130
9131   /* if shifting more that 3 bytes */
9132   if (shCount >= 24)
9133     {
9134       shCount -= 24;
9135       _startLazyDPSEvaluation();
9136       if (shCount)
9137         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9138       else
9139         movLeft2Result (left, MSB32, result, LSB, sign);
9140       addSign (result, MSB16, sign);
9141       _endLazyDPSEvaluation();
9142     }
9143   else if (shCount >= 16)
9144     {
9145       shCount -= 16;
9146       _startLazyDPSEvaluation();
9147       if (shCount)
9148         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9149       else
9150         {
9151           movLeft2Result (left, MSB24, result, LSB, 0);
9152           movLeft2Result (left, MSB32, result, MSB16, sign);
9153         }
9154       addSign (result, MSB24, sign);
9155       _endLazyDPSEvaluation();
9156     }
9157   else if (shCount >= 8)
9158     {
9159       shCount -= 8;
9160       _startLazyDPSEvaluation();
9161       if (shCount == 1)
9162         {
9163             shiftRLong (left, MSB16, result, sign);
9164         }
9165       else if (shCount == 0)
9166         {
9167           movLeft2Result (left, MSB16, result, LSB, 0);
9168           movLeft2Result (left, MSB24, result, MSB16, 0);
9169           movLeft2Result (left, MSB32, result, MSB24, sign);
9170           addSign (result, MSB32, sign);
9171         }
9172       else
9173         {
9174           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9175           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9176           /* the last shift is signed */
9177           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9178           addSign (result, MSB32, sign);
9179         }
9180         _endLazyDPSEvaluation();
9181     }
9182   else
9183     {
9184         /* 1 <= shCount <= 7 */
9185       if (shCount <= 2)
9186         {
9187           shiftRLong (left, LSB, result, sign);
9188           if (shCount == 2)
9189             shiftRLong (result, LSB, result, sign);
9190         }
9191       else
9192         {
9193           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9194           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9195           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9196         }
9197     }
9198 }
9199
9200 #ifdef BETTER_LITERAL_SHIFT
9201 /*-----------------------------------------------------------------*/
9202 /* genRightShiftLiteral - right shifting by known count            */
9203 /*-----------------------------------------------------------------*/
9204 static bool
9205 genRightShiftLiteral (operand * left,
9206                       operand * right,
9207                       operand * result,
9208                       iCode * ic,
9209                       int sign)
9210 {
9211   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9212   int size;
9213
9214   size = getSize (operandType (result));
9215
9216   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9217
9218   /* We only handle certain easy cases so far. */
9219   if ((shCount != 0)
9220    && (shCount < (size * 8))
9221    && (size != 1)
9222    && (size != 2)
9223    && (size != 4))
9224   {
9225       D(emitcode (";", "genRightShiftLiteral wimping out"););
9226       return FALSE;
9227   }
9228
9229   freeAsmop (right, NULL, ic, TRUE);
9230
9231   aopOp (left, ic, FALSE, FALSE);
9232   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9233
9234 #if VIEW_SIZE
9235   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9236             AOP_SIZE (left));
9237 #endif
9238
9239   /* test the LEFT size !!! */
9240
9241   /* I suppose that the left size >= result size */
9242   if (shCount == 0)
9243   {
9244       size = getDataSize (result);
9245       _startLazyDPSEvaluation();
9246       while (size--)
9247       {
9248         movLeft2Result (left, size, result, size, 0);
9249       }
9250       _endLazyDPSEvaluation();
9251   }
9252   else if (shCount >= (size * 8))
9253     {
9254       if (sign)
9255       {
9256         /* get sign in acc.7 */
9257         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9258       }
9259       addSign (result, LSB, sign);
9260     }
9261   else
9262     {
9263       switch (size)
9264         {
9265         case 1:
9266           genrshOne (result, left, shCount, sign);
9267           break;
9268
9269         case 2:
9270           genrshTwo (result, left, shCount, sign);
9271           break;
9272 #if 1
9273         case 4:
9274           genrshFour (result, left, shCount, sign);
9275           break;
9276 #endif
9277         default:
9278           break;
9279         }
9280     }
9281   freeAsmop (left, NULL, ic, TRUE);
9282   freeAsmop (result, NULL, ic, TRUE);
9283
9284   return TRUE;
9285 }
9286 #endif
9287
9288 /*-----------------------------------------------------------------*/
9289 /* genSignedRightShift - right shift of signed number              */
9290 /*-----------------------------------------------------------------*/
9291 static void
9292 genSignedRightShift (iCode * ic)
9293 {
9294   operand *right, *left, *result;
9295   int size, offset;
9296   char *l;
9297   symbol *tlbl, *tlbl1;
9298
9299   D (emitcode (";", "genSignedRightShift "););
9300
9301   /* we do it the hard way put the shift count in b
9302      and loop thru preserving the sign */
9303
9304   right = IC_RIGHT (ic);
9305   left = IC_LEFT (ic);
9306   result = IC_RESULT (ic);
9307
9308   aopOp (right, ic, FALSE, FALSE);
9309
9310 #ifdef BETTER_LITERAL_SHIFT
9311   if (AOP_TYPE (right) == AOP_LIT)
9312     {
9313       if (genRightShiftLiteral (left, right, result, ic, 1))
9314       {
9315         return;
9316       }
9317     }
9318 #endif
9319   /* shift count is unknown then we have to form
9320      a loop get the loop count in B : Note: we take
9321      only the lower order byte since shifting
9322      more that 32 bits make no sense anyway, ( the
9323      largest size of an object can be only 32 bits ) */
9324
9325   if (AOP_TYPE (right) == AOP_LIT)
9326   {
9327       /* Really should be handled by genRightShiftLiteral,
9328        * but since I'm too lazy to fix that today, at least we can make
9329        * some small improvement.
9330        */
9331        emitcode("mov", "b,#!constbyte",
9332                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9333   }
9334   else
9335   {
9336         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9337         emitcode ("inc", "b");
9338   }
9339   freeAsmop (right, NULL, ic, TRUE);
9340   aopOp (left, ic, FALSE, FALSE);
9341   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9342
9343   /* now move the left to the result if they are not the
9344      same */
9345   if (!sameRegs (AOP (left), AOP (result)) &&
9346       AOP_SIZE (result) > 1)
9347     {
9348
9349       size = AOP_SIZE (result);
9350       offset = 0;
9351       _startLazyDPSEvaluation ();
9352       while (size--)
9353         {
9354           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9355           if (*l == '@' && IS_AOP_PREG (result))
9356             {
9357
9358               emitcode ("mov", "a,%s", l);
9359               aopPut (AOP (result), "a", offset);
9360             }
9361           else
9362             aopPut (AOP (result), l, offset);
9363           offset++;
9364         }
9365       _endLazyDPSEvaluation ();
9366     }
9367
9368   /* mov the highest order bit to OVR */
9369   tlbl = newiTempLabel (NULL);
9370   tlbl1 = newiTempLabel (NULL);
9371
9372   size = AOP_SIZE (result);
9373   offset = size - 1;
9374   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9375   emitcode ("rlc", "a");
9376   emitcode ("mov", "ov,c");
9377   /* if it is only one byte then */
9378   if (size == 1)
9379     {
9380       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9381       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9382       emitcode ("", "!tlabeldef", tlbl->key + 100);
9383       emitcode ("mov", "c,ov");
9384       emitcode ("rrc", "a");
9385       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9386       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9387       aopPut (AOP (result), "a", 0);
9388       goto release;
9389     }
9390
9391   reAdjustPreg (AOP (result));
9392   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9393   emitcode ("", "!tlabeldef", tlbl->key + 100);
9394   emitcode ("mov", "c,ov");
9395   _startLazyDPSEvaluation ();
9396   while (size--)
9397     {
9398       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9399       emitcode ("rrc", "a");
9400       aopPut (AOP (result), "a", offset--);
9401     }
9402   _endLazyDPSEvaluation ();
9403   reAdjustPreg (AOP (result));
9404   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9405   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9406
9407 release:
9408   freeAsmop (left, NULL, ic, TRUE);
9409   freeAsmop (result, NULL, ic, TRUE);
9410 }
9411
9412 /*-----------------------------------------------------------------*/
9413 /* genRightShift - generate code for right shifting                */
9414 /*-----------------------------------------------------------------*/
9415 static void
9416 genRightShift (iCode * ic)
9417 {
9418   operand *right, *left, *result;
9419   sym_link *letype;
9420   int size, offset;
9421   char *l;
9422   symbol *tlbl, *tlbl1;
9423
9424   D (emitcode (";", "genRightShift "););
9425
9426   /* if signed then we do it the hard way preserve the
9427      sign bit moving it inwards */
9428   letype = getSpec (operandType (IC_LEFT (ic)));
9429
9430   if (!SPEC_USIGN (letype))
9431     {
9432       genSignedRightShift (ic);
9433       return;
9434     }
9435
9436   /* signed & unsigned types are treated the same : i.e. the
9437      signed is NOT propagated inwards : quoting from the
9438      ANSI - standard : "for E1 >> E2, is equivalent to division
9439      by 2**E2 if unsigned or if it has a non-negative value,
9440      otherwise the result is implementation defined ", MY definition
9441      is that the sign does not get propagated */
9442
9443   right = IC_RIGHT (ic);
9444   left = IC_LEFT (ic);
9445   result = IC_RESULT (ic);
9446
9447   aopOp (right, ic, FALSE, FALSE);
9448
9449 #ifdef BETTER_LITERAL_SHIFT
9450   /* if the shift count is known then do it
9451      as efficiently as possible */
9452   if (AOP_TYPE (right) == AOP_LIT)
9453     {
9454       if (genRightShiftLiteral (left, right, result, ic, 0))
9455       {
9456         return;
9457       }
9458     }
9459 #endif
9460
9461   /* shift count is unknown then we have to form
9462      a loop get the loop count in B : Note: we take
9463      only the lower order byte since shifting
9464      more that 32 bits make no sense anyway, ( the
9465      largest size of an object can be only 32 bits ) */
9466
9467   if (AOP_TYPE (right) == AOP_LIT)
9468   {
9469       /* Really should be handled by genRightShiftLiteral,
9470        * but since I'm too lazy to fix that today, at least we can make
9471        * some small improvement.
9472        */
9473        emitcode("mov", "b,#!constbyte",
9474                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9475   }
9476   else
9477   {
9478       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9479       emitcode ("inc", "b");
9480   }
9481   freeAsmop (right, NULL, ic, TRUE);
9482   aopOp (left, ic, FALSE, FALSE);
9483   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9484
9485   /* now move the left to the result if they are not the
9486      same */
9487   if (!sameRegs (AOP (left), AOP (result)) &&
9488       AOP_SIZE (result) > 1)
9489     {
9490
9491       size = AOP_SIZE (result);
9492       offset = 0;
9493       _startLazyDPSEvaluation ();
9494       while (size--)
9495         {
9496           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9497           if (*l == '@' && IS_AOP_PREG (result))
9498             {
9499
9500               emitcode ("mov", "a,%s", l);
9501               aopPut (AOP (result), "a", offset);
9502             }
9503           else
9504             aopPut (AOP (result), l, offset);
9505           offset++;
9506         }
9507       _endLazyDPSEvaluation ();
9508     }
9509
9510   tlbl = newiTempLabel (NULL);
9511   tlbl1 = newiTempLabel (NULL);
9512   size = AOP_SIZE (result);
9513   offset = size - 1;
9514
9515   /* if it is only one byte then */
9516   if (size == 1)
9517     {
9518       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9519       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9520       emitcode ("", "!tlabeldef", tlbl->key + 100);
9521       CLRC;
9522       emitcode ("rrc", "a");
9523       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9524       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9525       aopPut (AOP (result), "a", 0);
9526       goto release;
9527     }
9528
9529   reAdjustPreg (AOP (result));
9530   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9531   emitcode ("", "!tlabeldef", tlbl->key + 100);
9532   CLRC;
9533   _startLazyDPSEvaluation ();
9534   while (size--)
9535     {
9536       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9537       emitcode ("rrc", "a");
9538       aopPut (AOP (result), "a", offset--);
9539     }
9540   _endLazyDPSEvaluation ();
9541   reAdjustPreg (AOP (result));
9542
9543   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9544   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9545
9546 release:
9547   freeAsmop (left, NULL, ic, TRUE);
9548   freeAsmop (result, NULL, ic, TRUE);
9549 }
9550
9551
9552 /*-----------------------------------------------------------------*/
9553 /* emitPtrByteGet - emits code to get a byte into A through a      */
9554 /*                  pointer register (R0, R1, or DPTR). The        */
9555 /*                  original value of A can be preserved in B.     */
9556 /*-----------------------------------------------------------------*/
9557 static void
9558 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9559 {
9560   switch (p_type)
9561     {
9562     case IPOINTER:
9563     case POINTER:
9564       if (preserveAinB)
9565         emitcode ("mov", "b,a");
9566       emitcode ("mov", "a,@%s", rname);
9567       break;
9568
9569     case PPOINTER:
9570       if (preserveAinB)
9571         emitcode ("mov", "b,a");
9572       emitcode ("movx", "a,@%s", rname);
9573       break;
9574
9575     case FPOINTER:
9576       if (preserveAinB)
9577         emitcode ("mov", "b,a");
9578       emitcode ("movx", "a,@dptr");
9579       break;
9580
9581     case CPOINTER:
9582       if (preserveAinB)
9583         emitcode ("mov", "b,a");
9584       emitcode ("clr", "a");
9585       emitcode ("movc", "a,@a+dptr");
9586       break;
9587
9588     case GPOINTER:
9589       if (preserveAinB)
9590         {
9591           emitcode ("push", "b");
9592           emitcode ("push", "acc");
9593         }
9594       emitcode ("lcall", "__gptrget");
9595       if (preserveAinB)
9596         emitcode ("pop", "b");
9597       break;
9598     }
9599 }
9600
9601 /*-----------------------------------------------------------------*/
9602 /* emitPtrByteSet - emits code to set a byte from src through a    */
9603 /*                  pointer register (R0, R1, or DPTR).            */
9604 /*-----------------------------------------------------------------*/
9605 static void
9606 emitPtrByteSet (char *rname, int p_type, char *src)
9607 {
9608   switch (p_type)
9609     {
9610     case IPOINTER:
9611     case POINTER:
9612       if (*src=='@')
9613         {
9614           MOVA (src);
9615           emitcode ("mov", "@%s,a", rname);
9616         }
9617       else
9618         emitcode ("mov", "@%s,%s", rname, src);
9619       break;
9620
9621     case PPOINTER:
9622       MOVA (src);
9623       emitcode ("movx", "@%s,a", rname);
9624       break;
9625
9626     case FPOINTER:
9627       MOVA (src);
9628       emitcode ("movx", "@dptr,a");
9629       break;
9630
9631     case GPOINTER:
9632       MOVA (src);
9633       emitcode ("lcall", "__gptrput");
9634       break;
9635     }
9636 }
9637
9638 /*-----------------------------------------------------------------*/
9639 /* genUnpackBits - generates code for unpacking bits               */
9640 /*-----------------------------------------------------------------*/
9641 static void
9642 genUnpackBits (operand * result, char *rname, int ptype)
9643 {
9644   int offset = 0;       /* result byte offset */
9645   int rsize;            /* result size */
9646   int rlen = 0;         /* remaining bitfield length */
9647   sym_link *etype;      /* bitfield type information */
9648   int blen;             /* bitfield length */
9649   int bstr;             /* bitfield starting bit within byte */
9650
9651   D(emitcode (";     genUnpackBits",""));
9652
9653   etype = getSpec (operandType (result));
9654   rsize = getSize (operandType (result));
9655   blen = SPEC_BLEN (etype);
9656   bstr = SPEC_BSTR (etype);
9657
9658   /* If the bitfield length is less than a byte */
9659   if (blen < 8)
9660     {
9661       emitPtrByteGet (rname, ptype, FALSE);
9662       AccRsh (bstr);
9663       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9664       aopPut (AOP (result), "a", offset++);
9665       goto finish;
9666     }
9667
9668   /* Bit field did not fit in a byte. Copy all
9669      but the partial byte at the end.  */
9670   for (rlen=blen;rlen>=8;rlen-=8)
9671     {
9672       emitPtrByteGet (rname, ptype, FALSE);
9673       aopPut (AOP (result), "a", offset++);
9674       if (rlen>8)
9675         emitcode ("inc", "%s", rname);
9676     }
9677
9678   /* Handle the partial byte at the end */
9679   if (rlen)
9680     {
9681       emitPtrByteGet (rname, ptype, FALSE);
9682       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9683       aopPut (AOP (result), "a", offset++);
9684     }
9685
9686 finish:
9687   if (offset < rsize)
9688     {
9689       rsize -= offset;
9690       while (rsize--)
9691         aopPut (AOP (result), zero, offset++);
9692     }
9693 }
9694
9695
9696 /*-----------------------------------------------------------------*/
9697 /* genDataPointerGet - generates code when ptr offset is known     */
9698 /*-----------------------------------------------------------------*/
9699 static void
9700 genDataPointerGet (operand * left,
9701                    operand * result,
9702                    iCode * ic)
9703 {
9704   char *l;
9705   char buff[256];
9706   int size, offset = 0;
9707   aopOp (result, ic, TRUE, FALSE);
9708
9709   /* get the string representation of the name */
9710   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9711   size = AOP_SIZE (result);
9712   _startLazyDPSEvaluation ();
9713   while (size--)
9714     {
9715         if (offset)
9716         {
9717             SNPRINTF (buff, sizeof(buff),
9718                       "(%s + %d)", l + 1, offset);
9719         }
9720         else
9721         {
9722             SNPRINTF (buff, sizeof(buff),
9723                       "%s", l + 1);
9724         }
9725       aopPut (AOP (result), buff, offset++);
9726     }
9727   _endLazyDPSEvaluation ();
9728
9729   freeAsmop (left, NULL, ic, TRUE);
9730   freeAsmop (result, NULL, ic, TRUE);
9731 }
9732
9733 /*-----------------------------------------------------------------*/
9734 /* genNearPointerGet - emitcode for near pointer fetch             */
9735 /*-----------------------------------------------------------------*/
9736 static void
9737 genNearPointerGet (operand * left,
9738                    operand * result,
9739                    iCode * ic,
9740                    iCode *pi)
9741 {
9742   asmop *aop = NULL;
9743   regs *preg;
9744   char *rname;
9745   sym_link *rtype, *retype, *letype;
9746   sym_link *ltype = operandType (left);
9747   char buff[80];
9748
9749   rtype = operandType (result);
9750   retype = getSpec (rtype);
9751   letype = getSpec (ltype);
9752
9753   aopOp (left, ic, FALSE, FALSE);
9754
9755   /* if left is rematerialisable and
9756      result is not bitfield variable type and
9757      the left is pointer to data space i.e
9758      lower 128 bytes of space */
9759   if (AOP_TYPE (left) == AOP_IMMD &&
9760       !IS_BITFIELD (retype) &&
9761       !IS_BITFIELD (letype) &&
9762       DCL_TYPE (ltype) == POINTER)
9763     {
9764       genDataPointerGet (left, result, ic);
9765       return;
9766     }
9767
9768   /* if the value is already in a pointer register
9769      then don't need anything more */
9770   if (!AOP_INPREG (AOP (left)))
9771     {
9772       /* otherwise get a free pointer register */
9773       aop = newAsmop (0);
9774       preg = getFreePtr (ic, &aop, FALSE);
9775       emitcode ("mov", "%s,%s",
9776                 preg->name,
9777                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9778       rname = preg->name;
9779     }
9780   else
9781     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9782
9783   freeAsmop (left, NULL, ic, TRUE);
9784   aopOp (result, ic, FALSE, FALSE);
9785
9786   /* if bitfield then unpack the bits */
9787   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9788     genUnpackBits (result, rname, POINTER);
9789   else
9790     {
9791       /* we have can just get the values */
9792       int size = AOP_SIZE (result);
9793       int offset = 0;
9794
9795       while (size--)
9796         {
9797           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9798             {
9799
9800               emitcode ("mov", "a,@%s", rname);
9801               aopPut (AOP (result), "a", offset);
9802             }
9803           else
9804             {
9805               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9806               aopPut (AOP (result), buff, offset);
9807             }
9808           offset++;
9809           if (size || pi)
9810             {
9811                 emitcode ("inc", "%s", rname);
9812             }
9813         }
9814     }
9815
9816   /* now some housekeeping stuff */
9817   if (aop)
9818     {
9819       /* we had to allocate for this iCode */
9820       if (pi) { /* post increment present */
9821         aopPut(AOP ( left ),rname,0);
9822       }
9823       freeAsmop (NULL, aop, ic, TRUE);
9824     }
9825   else
9826     {
9827       /* we did not allocate which means left
9828          already in a pointer register, then
9829          if size > 0 && this could be used again
9830          we have to point it back to where it
9831          belongs */
9832       if (AOP_SIZE (result) > 1 &&
9833           !OP_SYMBOL (left)->remat &&
9834           (OP_SYMBOL (left)->liveTo > ic->seq ||
9835            ic->depth) &&
9836           !pi)
9837         {
9838           int size = AOP_SIZE (result) - 1;
9839           while (size--)
9840             emitcode ("dec", "%s", rname);
9841         }
9842     }
9843
9844   /* done */
9845   freeAsmop (result, NULL, ic, TRUE);
9846   if (pi) pi->generated = 1;
9847 }
9848
9849 /*-----------------------------------------------------------------*/
9850 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9851 /*-----------------------------------------------------------------*/
9852 static void
9853 genPagedPointerGet (operand * left,
9854                     operand * result,
9855                     iCode * ic,
9856                     iCode * pi)
9857 {
9858   asmop *aop = NULL;
9859   regs *preg;
9860   char *rname;
9861   sym_link *rtype, *retype, *letype;
9862
9863   rtype = operandType (result);
9864   retype = getSpec (rtype);
9865   letype = getSpec (operandType (left));
9866   aopOp (left, ic, FALSE, FALSE);
9867
9868   /* if the value is already in a pointer register
9869      then don't need anything more */
9870   if (!AOP_INPREG (AOP (left)))
9871     {
9872       /* otherwise get a free pointer register */
9873       aop = newAsmop (0);
9874       preg = getFreePtr (ic, &aop, FALSE);
9875       emitcode ("mov", "%s,%s",
9876                 preg->name,
9877                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9878       rname = preg->name;
9879     }
9880   else
9881     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9882
9883   freeAsmop (left, NULL, ic, TRUE);
9884   aopOp (result, ic, FALSE, FALSE);
9885
9886   /* if bitfield then unpack the bits */
9887   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9888     genUnpackBits (result, rname, PPOINTER);
9889   else
9890     {
9891       /* we have can just get the values */
9892       int size = AOP_SIZE (result);
9893       int offset = 0;
9894
9895       while (size--)
9896         {
9897
9898           emitcode ("movx", "a,@%s", rname);
9899           aopPut (AOP (result), "a", offset);
9900
9901           offset++;
9902
9903           if (size || pi)
9904             emitcode ("inc", "%s", rname);
9905         }
9906     }
9907
9908   /* now some housekeeping stuff */
9909   if (aop)
9910     {
9911       /* we had to allocate for this iCode */
9912       if (pi) aopPut ( AOP (left), rname, 0);
9913       freeAsmop (NULL, aop, ic, TRUE);
9914     }
9915   else
9916     {
9917       /* we did not allocate which means left
9918          already in a pointer register, then
9919          if size > 0 && this could be used again
9920          we have to point it back to where it
9921          belongs */
9922       if (AOP_SIZE (result) > 1 &&
9923           !OP_SYMBOL (left)->remat &&
9924           (OP_SYMBOL (left)->liveTo > ic->seq ||
9925            ic->depth) &&
9926           !pi)
9927         {
9928           int size = AOP_SIZE (result) - 1;
9929           while (size--)
9930             emitcode ("dec", "%s", rname);
9931         }
9932     }
9933
9934   /* done */
9935   freeAsmop (result, NULL, ic, TRUE);
9936   if (pi) pi->generated = 1;
9937 }
9938
9939 /*-----------------------------------------------------------------*/
9940 /* genFarPointerGet - gget value from far space                    */
9941 /*-----------------------------------------------------------------*/
9942 static void
9943 genFarPointerGet (operand * left,
9944                   operand * result, iCode * ic, iCode *pi)
9945 {
9946     int size, offset, dopi=1;
9947   sym_link *retype = getSpec (operandType (result));
9948   sym_link *letype = getSpec (operandType (left));
9949   D (emitcode (";", "genFarPointerGet"););
9950
9951   aopOp (left, ic, FALSE, FALSE);
9952
9953   /* if the operand is already in dptr
9954      then we do nothing else we move the value to dptr */
9955   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9956     {
9957       /* if this is remateriazable */
9958       if (AOP_TYPE (left) == AOP_IMMD)
9959         {
9960           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9961         }
9962       else
9963         {
9964           /* we need to get it byte by byte */
9965           _startLazyDPSEvaluation ();
9966           if (AOP_TYPE (left) != AOP_DPTR)
9967             {
9968               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9969               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9970               if (options.model == MODEL_FLAT24)
9971                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9972             }
9973           else
9974             {
9975               /* We need to generate a load to DPTR indirect through DPTR. */
9976               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9977               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9978               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9979               if (options.model == MODEL_FLAT24)
9980                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9981               emitcode ("pop", "dph");
9982               emitcode ("pop", "dpl");
9983               dopi =0;
9984             }
9985           _endLazyDPSEvaluation ();
9986         }
9987     }
9988   /* so dptr know contains the address */
9989   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9990
9991   /* if bit then unpack */
9992   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9993       if (AOP_INDPTRn(left)) {
9994           genSetDPTR(AOP(left)->aopu.dptr);
9995       }
9996       genUnpackBits (result, "dptr", FPOINTER);
9997       if (AOP_INDPTRn(left)) {
9998           genSetDPTR(0);
9999       }
10000   } else
10001     {
10002       size = AOP_SIZE (result);
10003       offset = 0;
10004
10005       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10006           while (size--) {
10007               genSetDPTR(AOP(left)->aopu.dptr);
10008               emitcode ("movx", "a,@dptr");
10009               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10010                   emitcode ("inc", "dptr");
10011               genSetDPTR (0);
10012               aopPut (AOP (result), "a", offset++);
10013           }
10014       } else {
10015           _startLazyDPSEvaluation ();
10016           while (size--) {
10017               if (AOP_INDPTRn(left)) {
10018                   genSetDPTR(AOP(left)->aopu.dptr);
10019               } else {
10020                   genSetDPTR (0);
10021               }
10022               _flushLazyDPS ();
10023
10024               emitcode ("movx", "a,@dptr");
10025               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10026                   emitcode ("inc", "dptr");
10027
10028               aopPut (AOP (result), "a", offset++);
10029           }
10030           _endLazyDPSEvaluation ();
10031       }
10032     }
10033   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10034       if (!AOP_INDPTRn(left)) {
10035           _startLazyDPSEvaluation ();
10036           aopPut ( AOP (left), "dpl", 0);
10037           aopPut ( AOP (left), "dph", 1);
10038           if (options.model == MODEL_FLAT24)
10039               aopPut ( AOP (left), "dpx", 2);
10040           _endLazyDPSEvaluation ();
10041       }
10042     pi->generated = 1;
10043   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10044              AOP_SIZE(result) > 1 &&
10045              IS_SYMOP(left) &&
10046              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10047
10048       size = AOP_SIZE (result) - 1;
10049       if (AOP_INDPTRn(left)) {
10050           genSetDPTR(AOP(left)->aopu.dptr);
10051       }
10052       while (size--) emitcode ("lcall","__decdptr");
10053       if (AOP_INDPTRn(left)) {
10054           genSetDPTR(0);
10055       }
10056   }
10057
10058   freeAsmop (left, NULL, ic, TRUE);
10059   freeAsmop (result, NULL, ic, TRUE);
10060 }
10061
10062 /*-----------------------------------------------------------------*/
10063 /* genCodePointerGet - get value from code space                  */
10064 /*-----------------------------------------------------------------*/
10065 static void
10066 genCodePointerGet (operand * left,
10067                     operand * result, iCode * ic, iCode *pi)
10068 {
10069   int size, offset, dopi=1;
10070   sym_link *retype = getSpec (operandType (result));
10071
10072   aopOp (left, ic, FALSE, FALSE);
10073
10074   /* if the operand is already in dptr
10075      then we do nothing else we move the value to dptr */
10076   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10077     {
10078       /* if this is remateriazable */
10079       if (AOP_TYPE (left) == AOP_IMMD)
10080         {
10081           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10082         }
10083       else
10084         {                       /* we need to get it byte by byte */
10085           _startLazyDPSEvaluation ();
10086           if (AOP_TYPE (left) != AOP_DPTR)
10087             {
10088               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10089               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10090               if (options.model == MODEL_FLAT24)
10091                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10092             }
10093           else
10094             {
10095               /* We need to generate a load to DPTR indirect through DPTR. */
10096               D (emitcode (";", "gencodePointerGet -- indirection special case."););
10097               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10098               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10099               if (options.model == MODEL_FLAT24)
10100                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10101               emitcode ("pop", "dph");
10102               emitcode ("pop", "dpl");
10103               dopi=0;
10104             }
10105           _endLazyDPSEvaluation ();
10106         }
10107     }
10108   /* so dptr know contains the address */
10109   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10110
10111   /* if bit then unpack */
10112   if (IS_BITFIELD (retype)) {
10113       if (AOP_INDPTRn(left)) {
10114           genSetDPTR(AOP(left)->aopu.dptr);
10115       }
10116       genUnpackBits (result, "dptr", CPOINTER);
10117       if (AOP_INDPTRn(left)) {
10118           genSetDPTR(0);
10119       }
10120   } else
10121     {
10122       size = AOP_SIZE (result);
10123       offset = 0;
10124       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10125           while (size--) {
10126               genSetDPTR(AOP(left)->aopu.dptr);
10127               emitcode ("clr", "a");
10128               emitcode ("movc", "a,@a+dptr");
10129               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10130                   emitcode ("inc", "dptr");
10131               genSetDPTR (0);
10132               aopPut (AOP (result), "a", offset++);
10133           }
10134       } else {
10135           _startLazyDPSEvaluation ();
10136           while (size--)
10137               {
10138                   if (AOP_INDPTRn(left)) {
10139                       genSetDPTR(AOP(left)->aopu.dptr);
10140                   } else {
10141                       genSetDPTR (0);
10142                   }
10143                   _flushLazyDPS ();
10144
10145                   emitcode ("clr", "a");
10146                   emitcode ("movc", "a,@a+dptr");
10147                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10148                       emitcode ("inc", "dptr");
10149                   aopPut (AOP (result), "a", offset++);
10150               }
10151           _endLazyDPSEvaluation ();
10152       }
10153     }
10154   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10155       if (!AOP_INDPTRn(left)) {
10156           _startLazyDPSEvaluation ();
10157
10158           aopPut ( AOP (left), "dpl", 0);
10159           aopPut ( AOP (left), "dph", 1);
10160           if (options.model == MODEL_FLAT24)
10161               aopPut ( AOP (left), "dpx", 2);
10162
10163           _endLazyDPSEvaluation ();
10164       }
10165       pi->generated = 1;
10166   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10167              AOP_SIZE(result) > 1 &&
10168              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10169
10170       size = AOP_SIZE (result) - 1;
10171       if (AOP_INDPTRn(left)) {
10172           genSetDPTR(AOP(left)->aopu.dptr);
10173       }
10174       while (size--) emitcode ("lcall","__decdptr");
10175       if (AOP_INDPTRn(left)) {
10176           genSetDPTR(0);
10177       }
10178   }
10179
10180   freeAsmop (left, NULL, ic, TRUE);
10181   freeAsmop (result, NULL, ic, TRUE);
10182 }
10183
10184 /*-----------------------------------------------------------------*/
10185 /* genGenPointerGet - gget value from generic pointer space        */
10186 /*-----------------------------------------------------------------*/
10187 static void
10188 genGenPointerGet (operand * left,
10189                   operand * result, iCode * ic, iCode * pi)
10190 {
10191   int size, offset;
10192   sym_link *retype = getSpec (operandType (result));
10193   sym_link *letype = getSpec (operandType (left));
10194
10195   D (emitcode (";", "genGenPointerGet "); );
10196
10197   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10198
10199   /* if the operand is already in dptr
10200      then we do nothing else we move the value to dptr */
10201   if (AOP_TYPE (left) != AOP_STR)
10202     {
10203       /* if this is rematerializable */
10204       if (AOP_TYPE (left) == AOP_IMMD)
10205         {
10206           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10207           if (AOP(left)->aopu.aop_immd.from_cast_remat)
10208             {
10209               MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10210             }
10211           else
10212             {
10213               emitcode ("mov", "b,#%d", pointerCode (retype));
10214             }
10215         }
10216       else
10217         {                       /* we need to get it byte by byte */
10218           _startLazyDPSEvaluation ();
10219           emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10220           emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10221           if (options.model == MODEL_FLAT24) {
10222               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10223               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10224           } else {
10225               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10226           }
10227           _endLazyDPSEvaluation ();
10228         }
10229     }
10230
10231   /* so dptr-b now contains the address */
10232   _G.bInUse++;
10233   aopOp (result, ic, FALSE, TRUE);
10234   _G.bInUse--;
10235
10236   /* if bit then unpack */
10237   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10238   {
10239     genUnpackBits (result, "dptr", GPOINTER);
10240   }
10241   else
10242     {
10243         size = AOP_SIZE (result);
10244         offset = 0;
10245
10246         while (size--)
10247         {
10248             if (size)
10249             {
10250                 // Get two bytes at a time, results in _AP & A.
10251                 // dptr will be incremented ONCE by __gptrgetWord.
10252                 //
10253                 // Note: any change here must be coordinated
10254                 // with the implementation of __gptrgetWord
10255                 // in device/lib/_gptrget.c
10256                 emitcode ("lcall", "__gptrgetWord");
10257                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10258                 aopPut (AOP (result), "a", offset++);
10259                 size--;
10260             }
10261             else
10262             {
10263                 // Only one byte to get.
10264                 emitcode ("lcall", "__gptrget");
10265                 aopPut (AOP (result), "a", offset++);
10266             }
10267
10268             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10269             {
10270                 emitcode ("inc", "dptr");
10271             }
10272         }
10273     }
10274
10275   if (pi && AOP_TYPE (left) != AOP_IMMD) {
10276     _startLazyDPSEvaluation ();
10277
10278     aopPut ( AOP (left), "dpl", 0);
10279     aopPut ( AOP (left), "dph", 1);
10280     if (options.model == MODEL_FLAT24) {
10281         aopPut ( AOP (left), "dpx", 2);
10282         aopPut ( AOP (left), "b", 3);
10283     } else  aopPut ( AOP (left), "b", 2);
10284
10285     _endLazyDPSEvaluation ();
10286
10287     pi->generated = 1;
10288   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10289              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10290
10291       size = AOP_SIZE (result) - 1;
10292       while (size--) emitcode ("lcall","__decdptr");
10293   }
10294
10295   freeAsmop (left, NULL, ic, TRUE);
10296   freeAsmop (result, NULL, ic, TRUE);
10297 }
10298
10299 /*-----------------------------------------------------------------*/
10300 /* genPointerGet - generate code for pointer get                   */
10301 /*-----------------------------------------------------------------*/
10302 static void
10303 genPointerGet (iCode * ic, iCode *pi)
10304 {
10305   operand *left, *result;
10306   sym_link *type, *etype;
10307   int p_type;
10308
10309   D (emitcode (";", "genPointerGet ");
10310     );
10311
10312   left = IC_LEFT (ic);
10313   result = IC_RESULT (ic);
10314
10315   /* depending on the type of pointer we need to
10316      move it to the correct pointer register */
10317   type = operandType (left);
10318   etype = getSpec (type);
10319   /* if left is of type of pointer then it is simple */
10320   if (IS_PTR (type) && !IS_FUNC (type->next))
10321     p_type = DCL_TYPE (type);
10322   else
10323     {
10324       /* we have to go by the storage class */
10325       p_type = PTR_TYPE (SPEC_OCLS (etype));
10326     }
10327   /* special case when cast remat */
10328   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10329       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10330     {
10331       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10332       type = operandType (left);
10333       p_type = DCL_TYPE (type);
10334     }
10335   /* now that we have the pointer type we assign
10336      the pointer values */
10337   switch (p_type)
10338     {
10339
10340     case POINTER:
10341     case IPOINTER:
10342       genNearPointerGet (left, result, ic, pi);
10343       break;
10344
10345     case PPOINTER:
10346       genPagedPointerGet (left, result, ic, pi);
10347       break;
10348
10349     case FPOINTER:
10350       genFarPointerGet (left, result, ic, pi);
10351       break;
10352
10353     case CPOINTER:
10354       genCodePointerGet (left, result, ic, pi);
10355       break;
10356
10357     case GPOINTER:
10358       genGenPointerGet (left, result, ic, pi);
10359       break;
10360     }
10361
10362 }
10363
10364 /*-----------------------------------------------------------------*/
10365 /* genPackBits - generates code for packed bit storage             */
10366 /*-----------------------------------------------------------------*/
10367 static void
10368 genPackBits (sym_link * etype,
10369              operand * right,
10370              char *rname, int p_type)
10371 {
10372   int offset = 0;       /* source byte offset */
10373   int rlen = 0;         /* remaining bitfield length */
10374   int blen;             /* bitfield length */
10375   int bstr;             /* bitfield starting bit within byte */
10376   int litval;           /* source literal value (if AOP_LIT) */
10377   unsigned char mask;   /* bitmask within current byte */
10378
10379   D(emitcode (";     genPackBits",""));
10380
10381   blen = SPEC_BLEN (etype);
10382   bstr = SPEC_BSTR (etype);
10383
10384   /* If the bitfield length is less than a byte */
10385   if (blen < 8)
10386     {
10387       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10388               (unsigned char) (0xFF >> (8 - bstr)));
10389
10390       if (AOP_TYPE (right) == AOP_LIT)
10391         {
10392           /* Case with a bitfield length <8 and literal source
10393           */
10394           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10395           litval <<= bstr;
10396           litval &= (~mask) & 0xff;
10397           emitPtrByteGet (rname, p_type, FALSE);
10398           if ((mask|litval)!=0xff)
10399             emitcode ("anl","a,#!constbyte", mask);
10400           if (litval)
10401             emitcode ("orl","a,#!constbyte", litval);
10402         }
10403       else
10404         {
10405           if ((blen==1) && (p_type!=GPOINTER))
10406             {
10407               /* Case with a bitfield length == 1 and no generic pointer
10408               */
10409               if (AOP_TYPE (right) == AOP_CRY)
10410                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10411               else
10412                 {
10413                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10414                   emitcode ("rrc","a");
10415                 }
10416               emitPtrByteGet (rname, p_type, FALSE);
10417               emitcode ("mov","acc.%d,c",bstr);
10418             }
10419           else
10420             {
10421               /* Case with a bitfield length < 8 and arbitrary source
10422               */
10423               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10424               /* shift and mask source value */
10425               AccLsh (bstr);
10426               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10427
10428               /* transfer A to B and get next byte */
10429               emitPtrByteGet (rname, p_type, TRUE);
10430
10431               emitcode ("anl", "a,#!constbyte", mask);
10432               emitcode ("orl", "a,b");
10433               if (p_type == GPOINTER)
10434                 emitcode ("pop", "b");
10435            }
10436         }
10437
10438       emitPtrByteSet (rname, p_type, "a");
10439       return;
10440     }
10441
10442   /* Bit length is greater than 7 bits. In this case, copy  */
10443   /* all except the partial byte at the end                 */
10444   for (rlen=blen;rlen>=8;rlen-=8)
10445     {
10446       emitPtrByteSet (rname, p_type,
10447                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10448       if (rlen>8)
10449         emitcode ("inc", "%s", rname);
10450     }
10451
10452   /* If there was a partial byte at the end */
10453   if (rlen)
10454     {
10455       mask = (((unsigned char) -1 << rlen) & 0xff);
10456
10457       if (AOP_TYPE (right) == AOP_LIT)
10458         {
10459           /* Case with partial byte and literal source
10460           */
10461           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10462           litval >>= (blen-rlen);
10463           litval &= (~mask) & 0xff;
10464           emitPtrByteGet (rname, p_type, FALSE);
10465           if ((mask|litval)!=0xff)
10466             emitcode ("anl","a,#!constbyte", mask);
10467           if (litval)
10468             emitcode ("orl","a,#!constbyte", litval);
10469         }
10470       else
10471         {
10472           /* Case with partial byte and arbitrary source
10473           */
10474           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10475           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10476
10477           /* transfer A to B and get next byte */
10478           emitPtrByteGet (rname, p_type, TRUE);
10479
10480           emitcode ("anl", "a,#!constbyte", mask);
10481           emitcode ("orl", "a,b");
10482           if (p_type == GPOINTER)
10483             emitcode ("pop", "b");
10484         }
10485       emitPtrByteSet (rname, p_type, "a");
10486     }
10487
10488 }
10489
10490
10491 /*-----------------------------------------------------------------*/
10492 /* genDataPointerSet - remat pointer to data space                 */
10493 /*-----------------------------------------------------------------*/
10494 static void
10495 genDataPointerSet (operand * right,
10496                    operand * result,
10497                    iCode * ic)
10498 {
10499   int size, offset = 0;
10500   char *l, buff[256];
10501
10502   aopOp (right, ic, FALSE, FALSE);
10503
10504   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10505   size = AOP_SIZE (right);
10506   while (size--)
10507     {
10508       if (offset)
10509         {
10510             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10511         }
10512       else
10513         {
10514             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10515         }
10516
10517       emitcode ("mov", "%s,%s", buff,
10518                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10519     }
10520
10521   freeAsmop (right, NULL, ic, TRUE);
10522   freeAsmop (result, NULL, ic, TRUE);
10523 }
10524
10525 /*-----------------------------------------------------------------*/
10526 /* genNearPointerSet - emitcode for near pointer put                */
10527 /*-----------------------------------------------------------------*/
10528 static void
10529 genNearPointerSet (operand * right,
10530                    operand * result,
10531                    iCode * ic,
10532                    iCode * pi)
10533 {
10534   asmop *aop = NULL;
10535   char *rname, *l;
10536   sym_link *retype, *letype;
10537   sym_link *ptype = operandType (result);
10538
10539   retype = getSpec (operandType (right));
10540   letype = getSpec (ptype);
10541
10542   aopOp (result, ic, FALSE, FALSE);
10543
10544   /* if the result is rematerializable &
10545      in data space & not a bit variable */
10546   if (AOP_TYPE (result) == AOP_IMMD &&
10547       DCL_TYPE (ptype) == POINTER &&
10548       !IS_BITVAR (retype) &&
10549       !IS_BITVAR (letype))
10550     {
10551       genDataPointerSet (right, result, ic);
10552       return;
10553     }
10554
10555   /* if the value is already in a pointer register
10556      then don't need anything more */
10557   if (!AOP_INPREG (AOP (result)))
10558     {
10559       /* otherwise get a free pointer register */
10560       regs *preg;
10561
10562       aop = newAsmop (0);
10563       preg = getFreePtr (ic, &aop, FALSE);
10564       emitcode ("mov", "%s,%s",
10565                 preg->name,
10566                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10567       rname = preg->name;
10568     }
10569   else
10570     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10571
10572   aopOp (right, ic, FALSE, FALSE);
10573
10574   /* if bitfield then unpack the bits */
10575   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10576     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10577   else
10578     {
10579       /* we have can just get the values */
10580       int size = AOP_SIZE (right);
10581       int offset = 0;
10582
10583       while (size--)
10584         {
10585           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10586           if (*l == '@')
10587             {
10588               MOVA (l);
10589               emitcode ("mov", "@%s,a", rname);
10590             }
10591           else
10592             emitcode ("mov", "@%s,%s", rname, l);
10593           if (size || pi)
10594             emitcode ("inc", "%s", rname);
10595           offset++;
10596         }
10597     }
10598
10599   /* now some housekeeping stuff */
10600   if (aop)
10601     {
10602       /* we had to allocate for this iCode */
10603       if (pi) aopPut (AOP (result),rname,0);
10604       freeAsmop (NULL, aop, ic, TRUE);
10605     }
10606   else
10607     {
10608       /* we did not allocate which means left
10609          already in a pointer register, then
10610          if size > 0 && this could be used again
10611          we have to point it back to where it
10612          belongs */
10613       if (AOP_SIZE (right) > 1 &&
10614           !OP_SYMBOL (result)->remat &&
10615           (OP_SYMBOL (result)->liveTo > ic->seq ||
10616            ic->depth) &&
10617           !pi)
10618         {
10619           int size = AOP_SIZE (right) - 1;
10620           while (size--)
10621             emitcode ("dec", "%s", rname);
10622         }
10623     }
10624
10625   /* done */
10626   if (pi) pi->generated = 1;
10627   freeAsmop (result, NULL, ic, TRUE);
10628   freeAsmop (right, NULL, ic, TRUE);
10629
10630
10631 }
10632
10633 /*-----------------------------------------------------------------*/
10634 /* genPagedPointerSet - emitcode for Paged pointer put             */
10635 /*-----------------------------------------------------------------*/
10636 static void
10637 genPagedPointerSet (operand * right,
10638                     operand * result,
10639                     iCode * ic,
10640                     iCode *pi)
10641 {
10642   asmop *aop = NULL;
10643   char *rname;
10644   sym_link *retype, *letype;
10645
10646   retype = getSpec (operandType (right));
10647   letype = getSpec (operandType (result));
10648
10649   aopOp (result, ic, FALSE, FALSE);
10650
10651   /* if the value is already in a pointer register
10652      then don't need anything more */
10653   if (!AOP_INPREG (AOP (result)))
10654     {
10655       /* otherwise get a free pointer register */
10656       regs *preg;
10657
10658       aop = newAsmop (0);
10659       preg = getFreePtr (ic, &aop, FALSE);
10660       emitcode ("mov", "%s,%s",
10661                 preg->name,
10662                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10663       rname = preg->name;
10664     }
10665   else
10666     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10667
10668   aopOp (right, ic, FALSE, FALSE);
10669
10670   /* if bitfield then unpack the bits */
10671   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10672     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10673   else
10674     {
10675       /* we have can just get the values */
10676       int size = AOP_SIZE (right);
10677       int offset = 0;
10678
10679       while (size--)
10680         {
10681           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10682
10683           emitcode ("movx", "@%s,a", rname);
10684
10685           if (size || pi)
10686             emitcode ("inc", "%s", rname);
10687
10688           offset++;
10689         }
10690     }
10691
10692   /* now some housekeeping stuff */
10693   if (aop)
10694     {
10695       if (pi) aopPut (AOP (result),rname,0);
10696       /* we had to allocate for this iCode */
10697       freeAsmop (NULL, aop, ic, TRUE);
10698     }
10699   else
10700     {
10701       /* we did not allocate which means left
10702          already in a pointer register, then
10703          if size > 0 && this could be used again
10704          we have to point it back to where it
10705          belongs */
10706       if (AOP_SIZE (right) > 1 &&
10707           !OP_SYMBOL (result)->remat &&
10708           (OP_SYMBOL (result)->liveTo > ic->seq ||
10709            ic->depth) &&
10710           !pi)
10711         {
10712           int size = AOP_SIZE (right) - 1;
10713           while (size--)
10714             emitcode ("dec", "%s", rname);
10715         }
10716     }
10717
10718   /* done */
10719   if (pi) pi->generated = 1;
10720   freeAsmop (result, NULL, ic, TRUE);
10721   freeAsmop (right, NULL, ic, TRUE);
10722
10723
10724 }
10725
10726 /*-----------------------------------------------------------------*/
10727 /* genFarPointerSet - set value from far space                     */
10728 /*-----------------------------------------------------------------*/
10729 static void
10730 genFarPointerSet (operand * right,
10731                   operand * result, iCode * ic, iCode *pi)
10732 {
10733   int size, offset, dopi=1;
10734   sym_link *retype = getSpec (operandType (right));
10735   sym_link *letype = getSpec (operandType (result));
10736
10737   aopOp (result, ic, FALSE, FALSE);
10738
10739   /* if the operand is already in dptr
10740      then we do nothing else we move the value to dptr */
10741   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10742     {
10743       /* if this is remateriazable */
10744       if (AOP_TYPE (result) == AOP_IMMD)
10745         emitcode ("mov", "dptr,%s",
10746                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10747       else
10748         {
10749           /* we need to get it byte by byte */
10750           _startLazyDPSEvaluation ();
10751           if (AOP_TYPE (result) != AOP_DPTR)
10752             {
10753               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10754               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10755               if (options.model == MODEL_FLAT24)
10756                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10757             }
10758           else
10759             {
10760               /* We need to generate a load to DPTR indirect through DPTR. */
10761               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10762
10763               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10764               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10765               if (options.model == MODEL_FLAT24)
10766                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10767               emitcode ("pop", "dph");
10768               emitcode ("pop", "dpl");
10769               dopi=0;
10770             }
10771           _endLazyDPSEvaluation ();
10772         }
10773     }
10774   /* so dptr know contains the address */
10775   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10776
10777   /* if bit then unpack */
10778   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10779       if (AOP_INDPTRn(result)) {
10780           genSetDPTR(AOP(result)->aopu.dptr);
10781       }
10782       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10783       if (AOP_INDPTRn(result)) {
10784           genSetDPTR(0);
10785       }
10786   } else {
10787       size = AOP_SIZE (right);
10788       offset = 0;
10789       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10790           while (size--) {
10791               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10792
10793               genSetDPTR(AOP(result)->aopu.dptr);
10794               emitcode ("movx", "@dptr,a");
10795               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10796                   emitcode ("inc", "dptr");
10797               genSetDPTR (0);
10798           }
10799       } else {
10800           _startLazyDPSEvaluation ();
10801           while (size--) {
10802               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10803
10804               if (AOP_INDPTRn(result)) {
10805                   genSetDPTR(AOP(result)->aopu.dptr);
10806               } else {
10807                   genSetDPTR (0);
10808               }
10809               _flushLazyDPS ();
10810
10811               emitcode ("movx", "@dptr,a");
10812               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10813                   emitcode ("inc", "dptr");
10814           }
10815           _endLazyDPSEvaluation ();
10816       }
10817   }
10818
10819   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10820       if (!AOP_INDPTRn(result)) {
10821           _startLazyDPSEvaluation ();
10822
10823           aopPut (AOP(result),"dpl",0);
10824           aopPut (AOP(result),"dph",1);
10825           if (options.model == MODEL_FLAT24)
10826               aopPut (AOP(result),"dpx",2);
10827
10828           _endLazyDPSEvaluation ();
10829       }
10830       pi->generated=1;
10831   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10832              AOP_SIZE(right) > 1 &&
10833              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10834
10835       size = AOP_SIZE (right) - 1;
10836       if (AOP_INDPTRn(result)) {
10837           genSetDPTR(AOP(result)->aopu.dptr);
10838       }
10839       while (size--) emitcode ("lcall","__decdptr");
10840       if (AOP_INDPTRn(result)) {
10841           genSetDPTR(0);
10842       }
10843   }
10844   freeAsmop (result, NULL, ic, TRUE);
10845   freeAsmop (right, NULL, ic, TRUE);
10846 }
10847
10848 /*-----------------------------------------------------------------*/
10849 /* genGenPointerSet - set value from generic pointer space         */
10850 /*-----------------------------------------------------------------*/
10851 static void
10852 genGenPointerSet (operand * right,
10853                   operand * result, iCode * ic, iCode *pi)
10854 {
10855   int size, offset;
10856   sym_link *retype = getSpec (operandType (right));
10857   sym_link *letype = getSpec (operandType (result));
10858
10859   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10860
10861   /* if the operand is already in dptr
10862      then we do nothing else we move the value to dptr */
10863   if (AOP_TYPE (result) != AOP_STR)
10864     {
10865       _startLazyDPSEvaluation ();
10866       /* if this is remateriazable */
10867       if (AOP_TYPE (result) == AOP_IMMD)
10868         {
10869           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10870           if (AOP(result)->aopu.aop_immd.from_cast_remat)
10871           {
10872               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10873           }
10874           else
10875           {
10876               emitcode ("mov",
10877                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10878           }
10879         }
10880       else
10881         {                       /* we need to get it byte by byte */
10882           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10883           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10884           if (options.model == MODEL_FLAT24) {
10885             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10886             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10887           } else {
10888             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10889           }
10890         }
10891       _endLazyDPSEvaluation ();
10892     }
10893   /* so dptr + b now contains the address */
10894   _G.bInUse++;
10895   aopOp (right, ic, FALSE, TRUE);
10896   _G.bInUse--;
10897
10898
10899   /* if bit then unpack */
10900   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10901     {
10902         genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10903     }
10904   else
10905     {
10906         size = AOP_SIZE (right);
10907         offset = 0;
10908
10909         _startLazyDPSEvaluation ();
10910         while (size--)
10911         {
10912             if (size)
10913             {
10914                 // Set two bytes at a time, passed in _AP & A.
10915                 // dptr will be incremented ONCE by __gptrputWord.
10916                 //
10917                 // Note: any change here must be coordinated
10918                 // with the implementation of __gptrputWord
10919                 // in device/lib/_gptrput.c
10920                 emitcode("mov", "_ap, %s",
10921                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10922                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10923
10924                 genSetDPTR (0);
10925                 _flushLazyDPS ();
10926                 emitcode ("lcall", "__gptrputWord");
10927                 size--;
10928             }
10929             else
10930             {
10931                 // Only one byte to put.
10932                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10933
10934                 genSetDPTR (0);
10935                 _flushLazyDPS ();
10936                 emitcode ("lcall", "__gptrput");
10937             }
10938
10939             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10940             {
10941                 emitcode ("inc", "dptr");
10942             }
10943         }
10944         _endLazyDPSEvaluation ();
10945     }
10946
10947   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10948       _startLazyDPSEvaluation ();
10949
10950       aopPut (AOP(result),"dpl",0);
10951       aopPut (AOP(result),"dph",1);
10952       if (options.model == MODEL_FLAT24) {
10953           aopPut (AOP(result),"dpx",2);
10954           aopPut (AOP(result),"b",3);
10955       } else {
10956           aopPut (AOP(result),"b",2);
10957       }
10958       _endLazyDPSEvaluation ();
10959
10960       pi->generated=1;
10961   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10962              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10963
10964       size = AOP_SIZE (right) - 1;
10965       while (size--) emitcode ("lcall","__decdptr");
10966   }
10967   freeAsmop (result, NULL, ic, TRUE);
10968   freeAsmop (right, NULL, ic, TRUE);
10969 }
10970
10971 /*-----------------------------------------------------------------*/
10972 /* genPointerSet - stores the value into a pointer location        */
10973 /*-----------------------------------------------------------------*/
10974 static void
10975 genPointerSet (iCode * ic, iCode *pi)
10976 {
10977   operand *right, *result;
10978   sym_link *type, *etype;
10979   int p_type;
10980
10981   D (emitcode (";", "genPointerSet "););
10982
10983   right = IC_RIGHT (ic);
10984   result = IC_RESULT (ic);
10985
10986   /* depending on the type of pointer we need to
10987      move it to the correct pointer register */
10988   type = operandType (result);
10989   etype = getSpec (type);
10990   /* if left is of type of pointer then it is simple */
10991   if (IS_PTR (type) && !IS_FUNC (type->next))
10992     {
10993       p_type = DCL_TYPE (type);
10994     }
10995   else
10996     {
10997       /* we have to go by the storage class */
10998       p_type = PTR_TYPE (SPEC_OCLS (etype));
10999     }
11000   /* special case when cast remat */
11001   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11002       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11003           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11004           type = operandType (result);
11005           p_type = DCL_TYPE (type);
11006   }
11007
11008   /* now that we have the pointer type we assign
11009      the pointer values */
11010   switch (p_type)
11011     {
11012
11013     case POINTER:
11014     case IPOINTER:
11015       genNearPointerSet (right, result, ic, pi);
11016       break;
11017
11018     case PPOINTER:
11019       genPagedPointerSet (right, result, ic, pi);
11020       break;
11021
11022     case FPOINTER:
11023       genFarPointerSet (right, result, ic, pi);
11024       break;
11025
11026     case GPOINTER:
11027       genGenPointerSet (right, result, ic, pi);
11028       break;
11029
11030     default:
11031       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11032               "genPointerSet: illegal pointer type");
11033     }
11034
11035 }
11036
11037 /*-----------------------------------------------------------------*/
11038 /* genIfx - generate code for Ifx statement                        */
11039 /*-----------------------------------------------------------------*/
11040 static void
11041 genIfx (iCode * ic, iCode * popIc)
11042 {
11043   operand *cond = IC_COND (ic);
11044   int isbit = 0;
11045
11046   D (emitcode (";", "genIfx "););
11047
11048   aopOp (cond, ic, FALSE, FALSE);
11049
11050   /* get the value into acc */
11051   if (AOP_TYPE (cond) != AOP_CRY)
11052     {
11053         toBoolean (cond);
11054     }
11055   else
11056     {
11057         isbit = 1;
11058     }
11059
11060   /* the result is now in the accumulator */
11061   freeAsmop (cond, NULL, ic, TRUE);
11062
11063   /* if there was something to be popped then do it */
11064   if (popIc)
11065     genIpop (popIc);
11066
11067   /* if the condition is  a bit variable */
11068   if (isbit && IS_ITEMP (cond) &&
11069       SPIL_LOC (cond))
11070     {
11071         genIfxJump (ic, SPIL_LOC (cond)->rname);
11072     }
11073   else if (isbit && !IS_ITEMP (cond))
11074     {
11075         genIfxJump (ic, OP_SYMBOL (cond)->rname);
11076     }
11077   else
11078     {
11079         genIfxJump (ic, "a");
11080     }
11081
11082   ic->generated = 1;
11083 }
11084
11085 /*-----------------------------------------------------------------*/
11086 /* genAddrOf - generates code for address of                       */
11087 /*-----------------------------------------------------------------*/
11088 static void
11089 genAddrOf (iCode * ic)
11090 {
11091   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11092   int size, offset;
11093
11094   D (emitcode (";", "genAddrOf ");
11095     );
11096
11097   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11098
11099   /* if the operand is on the stack then we
11100      need to get the stack offset of this
11101      variable */
11102   if (sym->onStack) {
11103
11104       /* if 10 bit stack */
11105       if (options.stack10bit) {
11106           char buff[10];
11107           int  offset;
11108
11109           tsprintf(buff, sizeof(buff),
11110                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
11111           /* if it has an offset then we need to compute it */
11112 /*        emitcode ("subb", "a,#!constbyte", */
11113 /*                  -((sym->stack < 0) ? */
11114 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
11115 /*                    ((short) sym->stack)) & 0xff); */
11116 /*        emitcode ("mov","b,a"); */
11117 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11118 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
11119 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
11120           if (sym->stack) {
11121               emitcode ("mov", "a,_bpx");
11122               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11123                                              ((char) (sym->stack - _G.nRegsSaved)) :
11124                                              ((char) sym->stack )) & 0xff);
11125               emitcode ("mov", "b,a");
11126               emitcode ("mov", "a,_bpx+1");
11127
11128               offset = (((sym->stack < 0) ?
11129                          ((short) (sym->stack - _G.nRegsSaved)) :
11130                          ((short) sym->stack )) >> 8) & 0xff;
11131
11132               emitcode ("addc","a,#!constbyte", offset);
11133
11134               aopPut (AOP (IC_RESULT (ic)), "b", 0);
11135               aopPut (AOP (IC_RESULT (ic)), "a", 1);
11136               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11137           } else {
11138               /* we can just move _bp */
11139               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11140               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11141               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11142           }
11143       } else {
11144           /* if it has an offset then we need to compute it */
11145           if (sym->stack) {
11146               emitcode ("mov", "a,_bp");
11147               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11148               aopPut (AOP (IC_RESULT (ic)), "a", 0);
11149           } else {
11150               /* we can just move _bp */
11151               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11152           }
11153           /* fill the result with zero */
11154           size = AOP_SIZE (IC_RESULT (ic)) - 1;
11155
11156
11157           if (options.stack10bit && size < (FPTRSIZE - 1)) {
11158               fprintf (stderr,
11159                        "*** warning: pointer to stack var truncated.\n");
11160           }
11161
11162           offset = 1;
11163           while (size--) {
11164               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11165           }
11166       }
11167       goto release;
11168   }
11169
11170   /* object not on stack then we need the name */
11171   size = AOP_SIZE (IC_RESULT (ic));
11172   offset = 0;
11173
11174   while (size--)
11175     {
11176       char s[SDCC_NAME_MAX];
11177       if (offset) {
11178           switch (offset) {
11179           case 1:
11180               tsprintf(s, sizeof(s), "#!his",sym->rname);
11181               break;
11182           case 2:
11183               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11184               break;
11185           case 3:
11186               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11187               break;
11188           default: /* should not need this (just in case) */
11189               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11190                        sym->rname,
11191                        offset * 8);
11192           }
11193       }
11194       else
11195       {
11196           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11197       }
11198
11199       aopPut (AOP (IC_RESULT (ic)), s, offset++);
11200     }
11201
11202 release:
11203   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11204
11205 }
11206
11207 #if 0 // obsolete, and buggy for != xdata
11208 /*-----------------------------------------------------------------*/
11209 /* genArrayInit - generates code for address of                       */
11210 /*-----------------------------------------------------------------*/
11211 static void
11212 genArrayInit (iCode * ic)
11213 {
11214     literalList *iLoop;
11215     int         ix, count;
11216     int         elementSize = 0, eIndex;
11217     unsigned    val, lastVal;
11218     sym_link    *type;
11219     operand     *left=IC_LEFT(ic);
11220
11221     D (emitcode (";", "genArrayInit "););
11222
11223     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11224
11225     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11226     {
11227         // Load immediate value into DPTR.
11228         emitcode("mov", "dptr, %s",
11229              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11230     }
11231     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11232     {
11233 #if 0
11234       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11235               "Unexpected operand to genArrayInit.\n");
11236       exit(1);
11237 #else
11238       // a regression because of SDCCcse.c:1.52
11239       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11240       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11241       if (options.model == MODEL_FLAT24)
11242         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11243 #endif
11244     }
11245
11246     type = operandType(IC_LEFT(ic));
11247
11248     if (type && type->next)
11249     {
11250         elementSize = getSize(type->next);
11251     }
11252     else
11253     {
11254         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11255                                 "can't determine element size in genArrayInit.\n");
11256         exit(1);
11257     }
11258
11259     iLoop = IC_ARRAYILIST(ic);
11260     lastVal = 0xffff;
11261
11262     while (iLoop)
11263     {
11264         bool firstpass = TRUE;
11265
11266         emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11267                  iLoop->count, (int)iLoop->literalValue, elementSize);
11268
11269         ix = iLoop->count;
11270
11271         while (ix)
11272         {
11273             symbol *tlbl = NULL;
11274
11275             count = ix > 256 ? 256 : ix;
11276
11277             if (count > 1)
11278             {
11279                 tlbl = newiTempLabel (NULL);
11280                 if (firstpass || (count & 0xff))
11281                 {
11282                     emitcode("mov", "b, #!constbyte", count & 0xff);
11283                 }
11284
11285                 emitcode ("", "!tlabeldef", tlbl->key + 100);
11286             }
11287
11288             firstpass = FALSE;
11289
11290             for (eIndex = 0; eIndex < elementSize; eIndex++)
11291             {
11292                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11293                 if (val != lastVal)
11294                 {
11295                     emitcode("mov", "a, #!constbyte", val);
11296                     lastVal = val;
11297                 }
11298
11299                 emitcode("movx", "@dptr, a");
11300                 emitcode("inc", "dptr");
11301             }
11302
11303             if (count > 1)
11304             {
11305                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11306             }
11307
11308             ix -= count;
11309         }
11310
11311         iLoop = iLoop->next;
11312     }
11313
11314     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11315 }
11316 #endif
11317
11318 /*-----------------------------------------------------------------*/
11319 /* genFarFarAssign - assignment when both are in far space         */
11320 /*-----------------------------------------------------------------*/
11321 static void
11322 genFarFarAssign (operand * result, operand * right, iCode * ic)
11323 {
11324   int size = AOP_SIZE (right);
11325   int offset = 0;
11326   symbol *rSym = NULL;
11327
11328   if (size == 1)
11329   {
11330       /* quick & easy case. */
11331       D(emitcode(";","genFarFarAssign (1 byte case)"););
11332       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11333       freeAsmop (right, NULL, ic, FALSE);
11334       /* now assign DPTR to result */
11335       _G.accInUse++;
11336       aopOp(result, ic, FALSE, FALSE);
11337       _G.accInUse--;
11338       aopPut(AOP(result), "a", 0);
11339       freeAsmop(result, NULL, ic, FALSE);
11340       return;
11341   }
11342
11343   /* See if we've got an underlying symbol to abuse. */
11344   if (IS_SYMOP(result) && OP_SYMBOL(result))
11345   {
11346       if (IS_TRUE_SYMOP(result))
11347       {
11348           rSym = OP_SYMBOL(result);
11349       }
11350       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11351       {
11352           rSym = OP_SYMBOL(result)->usl.spillLoc;
11353       }
11354   }
11355
11356   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11357   {
11358       /* We can use the '390 auto-toggle feature to good effect here. */
11359
11360       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11361       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
11362       emitcode ("mov", "dptr,#%s", rSym->rname);
11363       /* DP2 = result, DP1 = right, DP1 is current. */
11364       while (size)
11365       {
11366           emitcode("movx", "a,@dptr");
11367           emitcode("movx", "@dptr,a");
11368           if (--size)
11369           {
11370                emitcode("inc", "dptr");
11371                emitcode("inc", "dptr");
11372           }
11373       }
11374       emitcode("mov", "dps,#0");
11375       freeAsmop (right, NULL, ic, FALSE);
11376 #if 0
11377 some alternative code for processors without auto-toggle
11378 no time to test now, so later well put in...kpb
11379         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11380         emitcode("mov", "dps,#1");      /* Select DPTR2. */
11381         emitcode ("mov", "dptr,#%s", rSym->rname);
11382         /* DP2 = result, DP1 = right, DP1 is current. */
11383         while (size)
11384         {
11385           --size;
11386           emitcode("movx", "a,@dptr");
11387           if (size)
11388             emitcode("inc", "dptr");
11389           emitcode("inc", "dps");
11390           emitcode("movx", "@dptr,a");
11391           if (size)
11392             emitcode("inc", "dptr");
11393           emitcode("inc", "dps");
11394         }
11395         emitcode("mov", "dps,#0");
11396         freeAsmop (right, NULL, ic, FALSE);
11397 #endif
11398   }
11399   else
11400   {
11401       D (emitcode (";", "genFarFarAssign"););
11402       aopOp (result, ic, TRUE, TRUE);
11403
11404       _startLazyDPSEvaluation ();
11405
11406       while (size--)
11407         {
11408           aopPut (AOP (result),
11409                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11410           offset++;
11411         }
11412       _endLazyDPSEvaluation ();
11413       freeAsmop (result, NULL, ic, FALSE);
11414       freeAsmop (right, NULL, ic, FALSE);
11415   }
11416 }
11417
11418 /*-----------------------------------------------------------------*/
11419 /* genAssign - generate code for assignment                        */
11420 /*-----------------------------------------------------------------*/
11421 static void
11422 genAssign (iCode * ic)
11423 {
11424   operand *result, *right;
11425   int size, offset;
11426   unsigned long lit = 0L;
11427
11428   D (emitcode (";", "genAssign ");
11429     );
11430
11431   result = IC_RESULT (ic);
11432   right = IC_RIGHT (ic);
11433
11434   /* if they are the same */
11435   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11436     return;
11437
11438   aopOp (right, ic, FALSE, FALSE);
11439
11440   emitcode (";", "genAssign: resultIsFar = %s",
11441             isOperandInFarSpace (result) ?
11442             "TRUE" : "FALSE");
11443
11444   /* special case both in far space */
11445   if ((AOP_TYPE (right) == AOP_DPTR ||
11446        AOP_TYPE (right) == AOP_DPTR2) &&
11447   /* IS_TRUE_SYMOP(result)       && */
11448       isOperandInFarSpace (result))
11449     {
11450       genFarFarAssign (result, right, ic);
11451       return;
11452     }
11453
11454   aopOp (result, ic, TRUE, FALSE);
11455
11456   /* if they are the same registers */
11457   if (sameRegs (AOP (right), AOP (result)))
11458     goto release;
11459
11460   /* if the result is a bit */
11461   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11462     {
11463       /* if the right size is a literal then
11464          we know what the value is */
11465       if (AOP_TYPE (right) == AOP_LIT)
11466         {
11467           if (((int) operandLitValue (right)))
11468             aopPut (AOP (result), one, 0);
11469           else
11470             aopPut (AOP (result), zero, 0);
11471           goto release;
11472         }
11473
11474       /* the right is also a bit variable */
11475       if (AOP_TYPE (right) == AOP_CRY)
11476         {
11477           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11478           aopPut (AOP (result), "c", 0);
11479           goto release;
11480         }
11481
11482       /* we need to or */
11483       toBoolean (right);
11484       aopPut (AOP (result), "a", 0);
11485       goto release;
11486     }
11487
11488   /* bit variables done */
11489   /* general case */
11490   size = AOP_SIZE (result);
11491   offset = 0;
11492   if (AOP_TYPE (right) == AOP_LIT)
11493     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11494
11495   if ((size > 1) &&
11496       (AOP_TYPE (result) != AOP_REG) &&
11497       (AOP_TYPE (right) == AOP_LIT) &&
11498       !IS_FLOAT (operandType (right)))
11499     {
11500       _startLazyDPSEvaluation ();
11501       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11502         {
11503           aopPut (AOP (result),
11504                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11505                   offset);
11506           offset++;
11507           size--;
11508         }
11509       /* And now fill the rest with zeros. */
11510       if (size)
11511         {
11512           emitcode ("clr", "a");
11513         }
11514       while (size--)
11515         {
11516           aopPut (AOP (result), "a", offset++);
11517         }
11518       _endLazyDPSEvaluation ();
11519     }
11520   else
11521     {
11522       _startLazyDPSEvaluation ();
11523       while (size--)
11524         {
11525           aopPut (AOP (result),
11526                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11527                   offset);
11528           offset++;
11529         }
11530       _endLazyDPSEvaluation ();
11531     }
11532
11533 release:
11534   freeAsmop (right, NULL, ic, FALSE);
11535   freeAsmop (result, NULL, ic, TRUE);
11536 }
11537
11538 /*-----------------------------------------------------------------*/
11539 /* genJumpTab - generates code for jump table                      */
11540 /*-----------------------------------------------------------------*/
11541 static void
11542 genJumpTab (iCode * ic)
11543 {
11544   symbol *jtab;
11545   char *l;
11546
11547   D (emitcode (";", "genJumpTab ");
11548     );
11549
11550   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11551   /* get the condition into accumulator */
11552   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11553   MOVA (l);
11554   /* multiply by four! */
11555   emitcode ("add", "a,acc");
11556   emitcode ("add", "a,acc");
11557   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11558
11559   jtab = newiTempLabel (NULL);
11560   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11561   emitcode ("jmp", "@a+dptr");
11562   emitcode ("", "!tlabeldef", jtab->key + 100);
11563   /* now generate the jump labels */
11564   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11565        jtab = setNextItem (IC_JTLABELS (ic)))
11566     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11567
11568 }
11569
11570 /*-----------------------------------------------------------------*/
11571 /* genCast - gen code for casting                                  */
11572 /*-----------------------------------------------------------------*/
11573 static void
11574 genCast (iCode * ic)
11575 {
11576   operand *result = IC_RESULT (ic);
11577   sym_link *ctype = operandType (IC_LEFT (ic));
11578   sym_link *rtype = operandType (IC_RIGHT (ic));
11579   operand *right = IC_RIGHT (ic);
11580   int size, offset;
11581
11582   D (emitcode (";", "genCast "););
11583
11584   /* if they are equivalent then do nothing */
11585   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11586     return;
11587
11588   aopOp (right, ic, FALSE, AOP_IS_STR (result));
11589   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11590
11591   /* if the result is a bit */
11592   if (IS_BITVAR (OP_SYMBOL (result)->type)
11593       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11594     {
11595       /* if the right size is a literal then
11596          we know what the value is */
11597       if (AOP_TYPE (right) == AOP_LIT)
11598         {
11599           if (((int) operandLitValue (right)))
11600             aopPut (AOP (result), one, 0);
11601           else
11602             aopPut (AOP (result), zero, 0);
11603
11604           goto release;
11605         }
11606
11607       /* the right is also a bit variable */
11608       if (AOP_TYPE (right) == AOP_CRY)
11609         {
11610           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11611           aopPut (AOP (result), "c", 0);
11612           goto release;
11613         }
11614
11615       /* we need to or */
11616       toBoolean (right);
11617       aopPut (AOP (result), "a", 0);
11618       goto release;
11619     }
11620
11621   /* if they are the same size : or less */
11622   if (AOP_SIZE (result) <= AOP_SIZE (right))
11623     {
11624
11625       /* if they are in the same place */
11626       if (sameRegs (AOP (right), AOP (result)))
11627         goto release;
11628
11629       /* if they in different places then copy */
11630       size = AOP_SIZE (result);
11631       offset = 0;
11632       _startLazyDPSEvaluation ();
11633       while (size--)
11634         {
11635           aopPut (AOP (result),
11636                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11637                   offset);
11638           offset++;
11639         }
11640       _endLazyDPSEvaluation ();
11641       goto release;
11642     }
11643
11644
11645   /* if the result is of type pointer */
11646   if (IS_PTR (ctype))
11647     {
11648
11649       int p_type;
11650       sym_link *type = operandType (right);
11651
11652       /* pointer to generic pointer */
11653       if (IS_GENPTR (ctype))
11654         {
11655           if (IS_PTR (type))
11656             {
11657               p_type = DCL_TYPE (type);
11658             }
11659           else
11660             {
11661 #if OLD_CAST_BEHAVIOR
11662               /* KV: we are converting a non-pointer type to
11663                * a generic pointer. This (ifdef'd out) code
11664                * says that the resulting generic pointer
11665                * should have the same class as the storage
11666                * location of the non-pointer variable.
11667                *
11668                * For example, converting an int (which happens
11669                * to be stored in DATA space) to a pointer results
11670                * in a DATA generic pointer; if the original int
11671                * in XDATA space, so will be the resulting pointer.
11672                *
11673                * I don't like that behavior, and thus this change:
11674                * all such conversions will be forced to XDATA and
11675                * throw a warning. If you want some non-XDATA
11676                * type, or you want to suppress the warning, you
11677                * must go through an intermediate cast, like so:
11678                *
11679                * char _generic *gp = (char _xdata *)(intVar);
11680                */
11681               sym_link *etype = getSpec (type);
11682
11683               /* we have to go by the storage class */
11684               if (SPEC_OCLS (etype) != generic)
11685                 {
11686                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11687                 }
11688               else
11689 #endif
11690                 {
11691                   /* Converting unknown class (i.e. register variable)
11692                    * to generic pointer. This is not good, but
11693                    * we'll make a guess (and throw a warning).
11694                    */
11695                   p_type = FPOINTER;
11696                   werror (W_INT_TO_GEN_PTR_CAST);
11697                 }
11698             }
11699
11700           /* the first two bytes are known */
11701           size = GPTRSIZE - 1;
11702           offset = 0;
11703           _startLazyDPSEvaluation ();
11704           while (size--)
11705             {
11706               aopPut (AOP (result),
11707                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11708                       offset);
11709               offset++;
11710             }
11711           _endLazyDPSEvaluation ();
11712
11713           /* the last byte depending on type */
11714             {
11715                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11716                 char gpValStr[10];
11717
11718                 if (gpVal == -1)
11719                 {
11720                     // pointerTypeToGPByte will have bitched.
11721                     exit(1);
11722                 }
11723
11724                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
11725                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11726             }
11727           goto release;
11728         }
11729
11730       /* just copy the pointers */
11731       size = AOP_SIZE (result);
11732       offset = 0;
11733       _startLazyDPSEvaluation ();
11734       while (size--)
11735         {
11736           aopPut (AOP (result),
11737                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11738                   offset);
11739           offset++;
11740         }
11741       _endLazyDPSEvaluation ();
11742       goto release;
11743     }
11744
11745   /* so we now know that the size of destination is greater
11746      than the size of the source */
11747   /* we move to result for the size of source */
11748   size = AOP_SIZE (right);
11749   offset = 0;
11750   _startLazyDPSEvaluation ();
11751   while (size--)
11752     {
11753       aopPut (AOP (result),
11754               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11755               offset);
11756       offset++;
11757     }
11758   _endLazyDPSEvaluation ();
11759
11760   /* now depending on the sign of the source && destination */
11761   size = AOP_SIZE (result) - AOP_SIZE (right);
11762   /* if unsigned or not an integral type */
11763   /* also, if the source is a bit, we don't need to sign extend, because
11764    * it can't possibly have set the sign bit.
11765    */
11766   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11767     {
11768       while (size--)
11769         {
11770           aopPut (AOP (result), zero, offset++);
11771         }
11772     }
11773   else
11774     {
11775       /* we need to extend the sign :{ */
11776       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11777                         FALSE, FALSE, NULL));
11778       emitcode ("rlc", "a");
11779       emitcode ("subb", "a,acc");
11780       while (size--)
11781         aopPut (AOP (result), "a", offset++);
11782     }
11783
11784   /* we are done hurray !!!! */
11785
11786 release:
11787   freeAsmop (right, NULL, ic, TRUE);
11788   freeAsmop (result, NULL, ic, TRUE);
11789
11790 }
11791
11792 /*-----------------------------------------------------------------*/
11793 /* genDjnz - generate decrement & jump if not zero instrucion      */
11794 /*-----------------------------------------------------------------*/
11795 static int
11796 genDjnz (iCode * ic, iCode * ifx)
11797 {
11798   symbol *lbl, *lbl1;
11799   if (!ifx)
11800     return 0;
11801
11802   /* if the if condition has a false label
11803      then we cannot save */
11804   if (IC_FALSE (ifx))
11805     return 0;
11806
11807   /* if the minus is not of the form
11808      a = a - 1 */
11809   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11810       !IS_OP_LITERAL (IC_RIGHT (ic)))
11811     return 0;
11812
11813   if (operandLitValue (IC_RIGHT (ic)) != 1)
11814     return 0;
11815
11816   /* if the size of this greater than one then no
11817      saving */
11818   if (getSize (operandType (IC_RESULT (ic))) > 1)
11819     return 0;
11820
11821   /* otherwise we can save BIG */
11822   D(emitcode(";", "genDjnz"););
11823
11824   lbl = newiTempLabel (NULL);
11825   lbl1 = newiTempLabel (NULL);
11826
11827   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11828
11829   if (AOP_NEEDSACC(IC_RESULT(ic)))
11830   {
11831       /* If the result is accessed indirectly via
11832        * the accumulator, we must explicitly write
11833        * it back after the decrement.
11834        */
11835       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11836
11837       if (strcmp(rByte, "a"))
11838       {
11839            /* Something is hopelessly wrong */
11840            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11841                    __FILE__, __LINE__);
11842            /* We can just give up; the generated code will be inefficient,
11843             * but what the hey.
11844             */
11845            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11846            return 0;
11847       }
11848       emitcode ("dec", "%s", rByte);
11849       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11850       emitcode ("jnz", "!tlabel", lbl->key + 100);
11851   }
11852   else if (IS_AOP_PREG (IC_RESULT (ic)))
11853     {
11854       emitcode ("dec", "%s",
11855                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11856       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11857       emitcode ("jnz", "!tlabel", lbl->key + 100);
11858     }
11859   else
11860     {
11861       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11862                 lbl->key + 100);
11863     }
11864   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11865   emitcode ("", "!tlabeldef", lbl->key + 100);
11866   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11867   emitcode ("", "!tlabeldef", lbl1->key + 100);
11868
11869   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11870   ifx->generated = 1;
11871   return 1;
11872 }
11873
11874 /*-----------------------------------------------------------------*/
11875 /* genReceive - generate code for a receive iCode                  */
11876 /*-----------------------------------------------------------------*/
11877 static void
11878 genReceive (iCode * ic)
11879 {
11880     int size = getSize (operandType (IC_RESULT (ic)));
11881     int offset = 0;
11882     int rb1off ;
11883
11884     D (emitcode (";", "genReceive "););
11885
11886     if (ic->argreg == 1)
11887     {
11888         /* first parameter */
11889         if (AOP_IS_STR(IC_RESULT(ic)))
11890         {
11891             /* Nothing to do: it's already in the proper place. */
11892             return;
11893         }
11894         else
11895         {
11896             bool useDp2;
11897
11898             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11899                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11900                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11901
11902             _G.accInUse++;
11903             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11904             _G.accInUse--;
11905
11906             /* Sanity checking... */
11907             if (AOP_USESDPTR(IC_RESULT(ic)))
11908             {
11909                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11910                         "genReceive got unexpected DPTR.");
11911             }
11912             assignResultValue (IC_RESULT (ic));
11913         }
11914     }
11915     else
11916     {
11917         /* second receive onwards */
11918         /* this gets a little tricky since unused recevies will be
11919          eliminated, we have saved the reg in the type field . and
11920          we use that to figure out which register to use */
11921         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11922         rb1off = ic->argreg;
11923         while (size--)
11924         {
11925             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11926         }
11927     }
11928     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11929 }
11930
11931 /*-----------------------------------------------------------------*/
11932 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11933 /*-----------------------------------------------------------------*/
11934 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11935 {
11936     operand *from , *to , *count;
11937     symbol *lbl;
11938     bitVect *rsave;
11939     int i;
11940
11941     /* we know it has to be 3 parameters */
11942     assert (nparms == 3);
11943
11944     rsave = newBitVect(16);
11945     /* save DPTR if it needs to be saved */
11946     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11947             if (bitVectBitValue(ic->rMask,i))
11948                     rsave = bitVectSetBit(rsave,i);
11949     }
11950     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11951                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11952     savermask(rsave);
11953
11954     to = parms[0];
11955     from = parms[1];
11956     count = parms[2];
11957
11958     aopOp (from, ic->next, FALSE, FALSE);
11959
11960     /* get from into DPTR1 */
11961     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11962     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11963     if (options.model == MODEL_FLAT24) {
11964         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11965     }
11966
11967     freeAsmop (from, NULL, ic, FALSE);
11968     aopOp (to, ic, FALSE, FALSE);
11969     /* get "to" into DPTR */
11970     /* if the operand is already in dptr
11971        then we do nothing else we move the value to dptr */
11972     if (AOP_TYPE (to) != AOP_STR) {
11973         /* if already in DPTR then we need to push */
11974         if (AOP_TYPE(to) == AOP_DPTR) {
11975             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11976             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11977             if (options.model == MODEL_FLAT24)
11978                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11979             emitcode ("pop", "dph");
11980             emitcode ("pop", "dpl");
11981         } else {
11982             _startLazyDPSEvaluation ();
11983             /* if this is remateriazable */
11984             if (AOP_TYPE (to) == AOP_IMMD) {
11985                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11986             } else {                    /* we need to get it byte by byte */
11987                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11988                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11989                 if (options.model == MODEL_FLAT24) {
11990                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11991                 }
11992             }
11993             _endLazyDPSEvaluation ();
11994         }
11995     }
11996     freeAsmop (to, NULL, ic, FALSE);
11997     _G.dptrInUse = _G.dptr1InUse = 1;
11998     aopOp (count, ic->next->next, FALSE,FALSE);
11999     lbl =newiTempLabel(NULL);
12000
12001     /* now for the actual copy */
12002     if (AOP_TYPE(count) == AOP_LIT &&
12003         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12004         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12005         if (fromc) {
12006             emitcode ("lcall","__bi_memcpyc2x_s");
12007         } else {
12008             emitcode ("lcall","__bi_memcpyx2x_s");
12009         }
12010         freeAsmop (count, NULL, ic, FALSE);
12011     } else {
12012         symbol *lbl1 = newiTempLabel(NULL);
12013
12014         emitcode (";"," Auto increment but no djnz");
12015         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12016         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12017         freeAsmop (count, NULL, ic, FALSE);
12018         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12019         emitcode ("","!tlabeldef",lbl->key+100);
12020         if (fromc) {
12021             emitcode ("clr","a");
12022             emitcode ("movc", "a,@a+dptr");
12023         } else
12024             emitcode ("movx", "a,@dptr");
12025         emitcode ("movx", "@dptr,a");
12026         emitcode ("inc", "dptr");
12027         emitcode ("inc", "dptr");
12028         emitcode ("mov","a,b");
12029         emitcode ("orl","a,_ap");
12030         emitcode ("jz","!tlabel",lbl1->key+100);
12031         emitcode ("mov","a,_ap");
12032         emitcode ("add","a,#!constbyte",0xFF);
12033         emitcode ("mov","_ap,a");
12034         emitcode ("mov","a,b");
12035         emitcode ("addc","a,#!constbyte",0xFF);
12036         emitcode ("mov","b,a");
12037         emitcode ("sjmp","!tlabel",lbl->key+100);
12038         emitcode ("","!tlabeldef",lbl1->key+100);
12039     }
12040     emitcode ("mov", "dps,#0");
12041     _G.dptrInUse = _G.dptr1InUse = 0;
12042     unsavermask(rsave);
12043
12044 }
12045
12046 /*-----------------------------------------------------------------*/
12047 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
12048 /*-----------------------------------------------------------------*/
12049 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12050 {
12051     operand *from , *to , *count;
12052     symbol *lbl,*lbl2;
12053     bitVect *rsave;
12054     int i;
12055
12056     /* we know it has to be 3 parameters */
12057     assert (nparms == 3);
12058
12059     rsave = newBitVect(16);
12060     /* save DPTR if it needs to be saved */
12061     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12062             if (bitVectBitValue(ic->rMask,i))
12063                     rsave = bitVectSetBit(rsave,i);
12064     }
12065     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12066                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12067     savermask(rsave);
12068
12069     to = parms[0];
12070     from = parms[1];
12071     count = parms[2];
12072
12073     aopOp (from, ic->next, FALSE, FALSE);
12074
12075     /* get from into DPTR1 */
12076     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12077     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12078     if (options.model == MODEL_FLAT24) {
12079         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12080     }
12081
12082     freeAsmop (from, NULL, ic, FALSE);
12083     aopOp (to, ic, FALSE, FALSE);
12084     /* get "to" into DPTR */
12085     /* if the operand is already in dptr
12086        then we do nothing else we move the value to dptr */
12087     if (AOP_TYPE (to) != AOP_STR) {
12088         /* if already in DPTR then we need to push */
12089         if (AOP_TYPE(to) == AOP_DPTR) {
12090             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12091             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12092             if (options.model == MODEL_FLAT24)
12093                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12094             emitcode ("pop", "dph");
12095             emitcode ("pop", "dpl");
12096         } else {
12097             _startLazyDPSEvaluation ();
12098             /* if this is remateriazable */
12099             if (AOP_TYPE (to) == AOP_IMMD) {
12100                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12101             } else {                    /* we need to get it byte by byte */
12102                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12103                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12104                 if (options.model == MODEL_FLAT24) {
12105                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12106                 }
12107             }
12108             _endLazyDPSEvaluation ();
12109         }
12110     }
12111     freeAsmop (to, NULL, ic, FALSE);
12112     _G.dptrInUse = _G.dptr1InUse = 1;
12113     aopOp (count, ic->next->next, FALSE,FALSE);
12114     lbl =newiTempLabel(NULL);
12115     lbl2 =newiTempLabel(NULL);
12116
12117     /* now for the actual compare */
12118     if (AOP_TYPE(count) == AOP_LIT &&
12119         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12120         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12121         if (fromc)
12122             emitcode("lcall","__bi_memcmpc2x_s");
12123         else
12124             emitcode("lcall","__bi_memcmpx2x_s");
12125         freeAsmop (count, NULL, ic, FALSE);
12126         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12127         aopPut(AOP(IC_RESULT(ic)),"a",0);
12128         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12129     } else {
12130         symbol *lbl1 = newiTempLabel(NULL);
12131
12132         emitcode("push","ar0");
12133         emitcode (";"," Auto increment but no djnz");
12134         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12135         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12136         freeAsmop (count, NULL, ic, FALSE);
12137         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12138         emitcode ("","!tlabeldef",lbl->key+100);
12139         if (fromc) {
12140             emitcode ("clr","a");
12141             emitcode ("movc", "a,@a+dptr");
12142         } else
12143             emitcode ("movx", "a,@dptr");
12144         emitcode ("mov","r0,a");
12145         emitcode ("movx", "a,@dptr");
12146         emitcode ("clr","c");
12147         emitcode ("subb","a,r0");
12148         emitcode ("jnz","!tlabel",lbl2->key+100);
12149         emitcode ("inc", "dptr");
12150         emitcode ("inc", "dptr");
12151         emitcode ("mov","a,b");
12152         emitcode ("orl","a,_ap");
12153         emitcode ("jz","!tlabel",lbl1->key+100);
12154         emitcode ("mov","a,_ap");
12155         emitcode ("add","a,#!constbyte",0xFF);
12156         emitcode ("mov","_ap,a");
12157         emitcode ("mov","a,b");
12158         emitcode ("addc","a,#!constbyte",0xFF);
12159         emitcode ("mov","b,a");
12160         emitcode ("sjmp","!tlabel",lbl->key+100);
12161         emitcode ("","!tlabeldef",lbl1->key+100);
12162         emitcode ("clr","a");
12163         emitcode ("","!tlabeldef",lbl2->key+100);
12164         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12165         aopPut(AOP(IC_RESULT(ic)),"a",0);
12166         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12167         emitcode("pop","ar0");
12168         emitcode ("mov", "dps,#0");
12169     }
12170     _G.dptrInUse = _G.dptr1InUse = 0;
12171     unsavermask(rsave);
12172
12173 }
12174
12175 /*-----------------------------------------------------------------*/
12176 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12177 /* port, first parameter output area second parameter pointer to   */
12178 /* port third parameter count                                      */
12179 /*-----------------------------------------------------------------*/
12180 static void genInp( iCode *ic, int nparms, operand **parms)
12181 {
12182     operand *from , *to , *count;
12183     symbol *lbl;
12184     bitVect *rsave;
12185     int i;
12186
12187     /* we know it has to be 3 parameters */
12188     assert (nparms == 3);
12189
12190     rsave = newBitVect(16);
12191     /* save DPTR if it needs to be saved */
12192     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12193             if (bitVectBitValue(ic->rMask,i))
12194                     rsave = bitVectSetBit(rsave,i);
12195     }
12196     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12197                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12198     savermask(rsave);
12199
12200     to = parms[0];
12201     from = parms[1];
12202     count = parms[2];
12203
12204     aopOp (from, ic->next, FALSE, FALSE);
12205
12206     /* get from into DPTR1 */
12207     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12208     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12209     if (options.model == MODEL_FLAT24) {
12210         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12211     }
12212
12213     freeAsmop (from, NULL, ic, FALSE);
12214     aopOp (to, ic, FALSE, FALSE);
12215     /* get "to" into DPTR */
12216     /* if the operand is already in dptr
12217        then we do nothing else we move the value to dptr */
12218     if (AOP_TYPE (to) != AOP_STR) {
12219         /* if already in DPTR then we need to push */
12220         if (AOP_TYPE(to) == AOP_DPTR) {
12221             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12222             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12223             if (options.model == MODEL_FLAT24)
12224                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12225             emitcode ("pop", "dph");
12226             emitcode ("pop", "dpl");
12227         } else {
12228             _startLazyDPSEvaluation ();
12229             /* if this is remateriazable */
12230             if (AOP_TYPE (to) == AOP_IMMD) {
12231                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12232             } else {                    /* we need to get it byte by byte */
12233                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12234                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12235                 if (options.model == MODEL_FLAT24) {
12236                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12237                 }
12238             }
12239             _endLazyDPSEvaluation ();
12240         }
12241     }
12242     freeAsmop (to, NULL, ic, FALSE);
12243
12244     _G.dptrInUse = _G.dptr1InUse = 1;
12245     aopOp (count, ic->next->next, FALSE,FALSE);
12246     lbl =newiTempLabel(NULL);
12247
12248     /* now for the actual copy */
12249     if (AOP_TYPE(count) == AOP_LIT &&
12250         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12251         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12252         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12253         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12254         freeAsmop (count, NULL, ic, FALSE);
12255         emitcode ("","!tlabeldef",lbl->key+100);
12256         emitcode ("movx", "a,@dptr");   /* read data from port */
12257         emitcode ("dec","dps");         /* switch to DPTR */
12258         emitcode ("movx", "@dptr,a");   /* save into location */
12259         emitcode ("inc", "dptr");       /* point to next area */
12260         emitcode ("inc","dps");         /* switch to DPTR2 */
12261         emitcode ("djnz","b,!tlabel",lbl->key+100);
12262     } else {
12263         symbol *lbl1 = newiTempLabel(NULL);
12264
12265         emitcode (";"," Auto increment but no djnz");
12266         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12267         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12268         freeAsmop (count, NULL, ic, FALSE);
12269         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12270         emitcode ("","!tlabeldef",lbl->key+100);
12271         emitcode ("movx", "a,@dptr");
12272         emitcode ("dec","dps");         /* switch to DPTR */
12273         emitcode ("movx", "@dptr,a");
12274         emitcode ("inc", "dptr");
12275         emitcode ("inc","dps");         /* switch to DPTR2 */
12276 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
12277 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12278         emitcode ("mov","a,b");
12279         emitcode ("orl","a,_ap");
12280         emitcode ("jz","!tlabel",lbl1->key+100);
12281         emitcode ("mov","a,_ap");
12282         emitcode ("add","a,#!constbyte",0xFF);
12283         emitcode ("mov","_ap,a");
12284         emitcode ("mov","a,b");
12285         emitcode ("addc","a,#!constbyte",0xFF);
12286         emitcode ("mov","b,a");
12287         emitcode ("sjmp","!tlabel",lbl->key+100);
12288         emitcode ("","!tlabeldef",lbl1->key+100);
12289     }
12290     emitcode ("mov", "dps,#0");
12291     _G.dptrInUse = _G.dptr1InUse = 0;
12292     unsavermask(rsave);
12293
12294 }
12295
12296 /*-----------------------------------------------------------------*/
12297 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12298 /* port, first parameter output area second parameter pointer to   */
12299 /* port third parameter count                                      */
12300 /*-----------------------------------------------------------------*/
12301 static void genOutp( iCode *ic, int nparms, operand **parms)
12302 {
12303     operand *from , *to , *count;
12304     symbol *lbl;
12305     bitVect *rsave;
12306     int i;
12307
12308     /* we know it has to be 3 parameters */
12309     assert (nparms == 3);
12310
12311     rsave = newBitVect(16);
12312     /* save DPTR if it needs to be saved */
12313     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12314             if (bitVectBitValue(ic->rMask,i))
12315                     rsave = bitVectSetBit(rsave,i);
12316     }
12317     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12318                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12319     savermask(rsave);
12320
12321     to = parms[0];
12322     from = parms[1];
12323     count = parms[2];
12324
12325     aopOp (from, ic->next, FALSE, FALSE);
12326
12327     /* get from into DPTR1 */
12328     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12329     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12330     if (options.model == MODEL_FLAT24) {
12331         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12332     }
12333
12334     freeAsmop (from, NULL, ic, FALSE);
12335     aopOp (to, ic, FALSE, FALSE);
12336     /* get "to" into DPTR */
12337     /* if the operand is already in dptr
12338        then we do nothing else we move the value to dptr */
12339     if (AOP_TYPE (to) != AOP_STR) {
12340         /* if already in DPTR then we need to push */
12341         if (AOP_TYPE(to) == AOP_DPTR) {
12342             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12343             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12344             if (options.model == MODEL_FLAT24)
12345                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12346             emitcode ("pop", "dph");
12347             emitcode ("pop", "dpl");
12348         } else {
12349             _startLazyDPSEvaluation ();
12350             /* if this is remateriazable */
12351             if (AOP_TYPE (to) == AOP_IMMD) {
12352                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12353             } else {                    /* we need to get it byte by byte */
12354                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12355                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12356                 if (options.model == MODEL_FLAT24) {
12357                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12358                 }
12359             }
12360             _endLazyDPSEvaluation ();
12361         }
12362     }
12363     freeAsmop (to, NULL, ic, FALSE);
12364
12365     _G.dptrInUse = _G.dptr1InUse = 1;
12366     aopOp (count, ic->next->next, FALSE,FALSE);
12367     lbl =newiTempLabel(NULL);
12368
12369     /* now for the actual copy */
12370     if (AOP_TYPE(count) == AOP_LIT &&
12371         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12372         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12373         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12374         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12375         emitcode ("","!tlabeldef",lbl->key+100);
12376         emitcode ("movx", "a,@dptr");   /* read data from port */
12377         emitcode ("inc","dps");         /* switch to DPTR2 */
12378         emitcode ("movx", "@dptr,a");   /* save into location */
12379         emitcode ("inc", "dptr");       /* point to next area */
12380         emitcode ("dec","dps");         /* switch to DPTR */
12381         emitcode ("djnz","b,!tlabel",lbl->key+100);
12382         freeAsmop (count, NULL, ic, FALSE);
12383     } else {
12384         symbol *lbl1 = newiTempLabel(NULL);
12385
12386         emitcode (";"," Auto increment but no djnz");
12387         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12388         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12389         freeAsmop (count, NULL, ic, FALSE);
12390         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12391         emitcode ("","!tlabeldef",lbl->key+100);
12392         emitcode ("movx", "a,@dptr");
12393         emitcode ("inc", "dptr");
12394         emitcode ("inc","dps");         /* switch to DPTR2 */
12395         emitcode ("movx", "@dptr,a");
12396         emitcode ("dec","dps");         /* switch to DPTR */
12397         emitcode ("mov","a,b");
12398         emitcode ("orl","a,_ap");
12399         emitcode ("jz","!tlabel",lbl1->key+100);
12400         emitcode ("mov","a,_ap");
12401         emitcode ("add","a,#!constbyte",0xFF);
12402         emitcode ("mov","_ap,a");
12403         emitcode ("mov","a,b");
12404         emitcode ("addc","a,#!constbyte",0xFF);
12405         emitcode ("mov","b,a");
12406         emitcode ("sjmp","!tlabel",lbl->key+100);
12407         emitcode ("","!tlabeldef",lbl1->key+100);
12408     }
12409     emitcode ("mov", "dps,#0");
12410     _G.dptrInUse = _G.dptr1InUse = 0;
12411     unsavermask(rsave);
12412
12413 }
12414
12415 /*-----------------------------------------------------------------*/
12416 /* genSwapW - swap lower & high order bytes                        */
12417 /*-----------------------------------------------------------------*/
12418 static void genSwapW(iCode *ic, int nparms, operand **parms)
12419 {
12420     operand *dest;
12421     operand *src;
12422     assert (nparms==1);
12423
12424     src = parms[0];
12425     dest=IC_RESULT(ic);
12426
12427     assert(getSize(operandType(src))==2);
12428
12429     aopOp (src, ic, FALSE, FALSE);
12430     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12431     _G.accInUse++;
12432     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12433     _G.accInUse--;
12434     freeAsmop (src, NULL, ic, FALSE);
12435
12436     aopOp (dest,ic, FALSE, FALSE);
12437     aopPut(AOP(dest),"b",0);
12438     aopPut(AOP(dest),"a",1);
12439     freeAsmop (dest, NULL, ic, FALSE);
12440 }
12441
12442 /*-----------------------------------------------------------------*/
12443 /* genMemsetX - gencode for memSetX data                           */
12444 /*-----------------------------------------------------------------*/
12445 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12446 {
12447     operand *to , *val , *count;
12448     symbol *lbl;
12449     char *l;
12450     int i;
12451     bitVect *rsave;
12452
12453     /* we know it has to be 3 parameters */
12454     assert (nparms == 3);
12455
12456     to = parms[0];
12457     val = parms[1];
12458     count = parms[2];
12459
12460     /* save DPTR if it needs to be saved */
12461     rsave = newBitVect(16);
12462     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12463             if (bitVectBitValue(ic->rMask,i))
12464                     rsave = bitVectSetBit(rsave,i);
12465     }
12466     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12467                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12468     savermask(rsave);
12469
12470     aopOp (to, ic, FALSE, FALSE);
12471     /* get "to" into DPTR */
12472     /* if the operand is already in dptr
12473        then we do nothing else we move the value to dptr */
12474     if (AOP_TYPE (to) != AOP_STR) {
12475         /* if already in DPTR then we need to push */
12476         if (AOP_TYPE(to) == AOP_DPTR) {
12477             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12478             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12479             if (options.model == MODEL_FLAT24)
12480                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12481             emitcode ("pop", "dph");
12482             emitcode ("pop", "dpl");
12483         } else {
12484             _startLazyDPSEvaluation ();
12485             /* if this is remateriazable */
12486             if (AOP_TYPE (to) == AOP_IMMD) {
12487                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12488             } else {                    /* we need to get it byte by byte */
12489                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12490                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12491                 if (options.model == MODEL_FLAT24) {
12492                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12493                 }
12494             }
12495             _endLazyDPSEvaluation ();
12496         }
12497     }
12498     freeAsmop (to, NULL, ic, FALSE);
12499
12500     aopOp (val, ic->next->next, FALSE,FALSE);
12501     aopOp (count, ic->next->next, FALSE,FALSE);
12502     lbl =newiTempLabel(NULL);
12503     /* now for the actual copy */
12504     if (AOP_TYPE(count) == AOP_LIT &&
12505         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12506         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12507         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12508         MOVA(l);
12509         emitcode ("","!tlabeldef",lbl->key+100);
12510         emitcode ("movx", "@dptr,a");
12511         emitcode ("inc", "dptr");
12512         emitcode ("djnz","b,!tlabel",lbl->key+100);
12513     } else {
12514         symbol *lbl1 = newiTempLabel(NULL);
12515
12516         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12517         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12518         emitcode ("","!tlabeldef",lbl->key+100);
12519         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12520         emitcode ("movx", "@dptr,a");
12521         emitcode ("inc", "dptr");
12522         emitcode ("mov","a,b");
12523         emitcode ("orl","a,_ap");
12524         emitcode ("jz","!tlabel",lbl1->key+100);
12525         emitcode ("mov","a,_ap");
12526         emitcode ("add","a,#!constbyte",0xFF);
12527         emitcode ("mov","_ap,a");
12528         emitcode ("mov","a,b");
12529         emitcode ("addc","a,#!constbyte",0xFF);
12530         emitcode ("mov","b,a");
12531         emitcode ("sjmp","!tlabel",lbl->key+100);
12532         emitcode ("","!tlabeldef",lbl1->key+100);
12533     }
12534     freeAsmop (count, NULL, ic, FALSE);
12535     unsavermask(rsave);
12536 }
12537
12538 /*-----------------------------------------------------------------*/
12539 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12540 /*-----------------------------------------------------------------*/
12541 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12542 {
12543         bitVect *rsave ;
12544         operand *pnum, *result;
12545         int i;
12546
12547         assert (nparms==1);
12548         /* save registers that need to be saved */
12549         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12550                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12551
12552         pnum = parms[0];
12553         aopOp (pnum, ic, FALSE, FALSE);
12554         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12555         freeAsmop (pnum, NULL, ic, FALSE);
12556         emitcode ("lcall","NatLib_LoadPrimitive");
12557         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12558         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12559             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12560                 for (i = (size-1) ; i >= 0 ; i-- ) {
12561                         emitcode ("push","a%s",javaRet[i]);
12562                 }
12563                 for (i=0; i < size ; i++ ) {
12564                         emitcode ("pop","a%s",
12565                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12566                 }
12567         } else {
12568                 for (i = 0 ; i < size ; i++ ) {
12569                         aopPut(AOP(result),javaRet[i],i);
12570                 }
12571         }
12572         freeAsmop (result, NULL, ic, FALSE);
12573         unsavermask(rsave);
12574 }
12575
12576 /*-----------------------------------------------------------------*/
12577 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12578 /*-----------------------------------------------------------------*/
12579 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12580 {
12581         bitVect *rsave ;
12582         operand *pnum, *result;
12583         int size = 3;
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_LoadPointer");
12596         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12597         if (AOP_TYPE(result)!=AOP_STR) {
12598                 for (i = 0 ; i < size ; i++ ) {
12599                         aopPut(AOP(result),fReturn[i],i);
12600                 }
12601         }
12602         freeAsmop (result, NULL, ic, FALSE);
12603         unsavermask(rsave);
12604 }
12605
12606 /*-----------------------------------------------------------------*/
12607 /* genNatLibInstallStateBlock -                                    */
12608 /*-----------------------------------------------------------------*/
12609 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12610                                        operand **parms, const char *name)
12611 {
12612         bitVect *rsave ;
12613         operand *psb, *handle;
12614         assert (nparms==2);
12615
12616         /* save registers that need to be saved */
12617         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12618                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12619         psb = parms[0];
12620         handle = parms[1];
12621
12622         /* put pointer to state block into DPTR1 */
12623         aopOp (psb, ic, FALSE, FALSE);
12624         if (AOP_TYPE (psb) == AOP_IMMD) {
12625                 emitcode ("mov","dps,#1");
12626                 emitcode ("mov", "dptr,%s",
12627                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12628                 emitcode ("mov","dps,#0");
12629         } else {
12630                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12631                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12632                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12633         }
12634         freeAsmop (psb, NULL, ic, FALSE);
12635
12636         /* put libraryID into DPTR */
12637         emitcode ("mov","dptr,#LibraryID");
12638
12639         /* put handle into r3:r2 */
12640         aopOp (handle, ic, FALSE, FALSE);
12641         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12642                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12643                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12644                 emitcode ("pop","ar3");
12645                 emitcode ("pop","ar2");
12646         } else {
12647                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12648                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12649         }
12650         freeAsmop (psb, NULL, ic, FALSE);
12651
12652         /* make the call */
12653         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12654
12655         /* put return value into place*/
12656         _G.accInUse++;
12657         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12658         _G.accInUse--;
12659         aopPut(AOP(IC_RESULT(ic)),"a",0);
12660         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12661         unsavermask(rsave);
12662 }
12663
12664 /*-----------------------------------------------------------------*/
12665 /* genNatLibRemoveStateBlock -                                     */
12666 /*-----------------------------------------------------------------*/
12667 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12668 {
12669         bitVect *rsave ;
12670
12671         assert(nparms==0);
12672
12673         /* save registers that need to be saved */
12674         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12675                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12676
12677         /* put libraryID into DPTR */
12678         emitcode ("mov","dptr,#LibraryID");
12679         /* make the call */
12680         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12681         unsavermask(rsave);
12682 }
12683
12684 /*-----------------------------------------------------------------*/
12685 /* genNatLibGetStateBlock -                                        */
12686 /*-----------------------------------------------------------------*/
12687 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12688                                    operand **parms,const char *name)
12689 {
12690         bitVect *rsave ;
12691         symbol *lbl = newiTempLabel(NULL);
12692
12693         assert(nparms==0);
12694         /* save registers that need to be saved */
12695         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12696                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12697
12698         /* put libraryID into DPTR */
12699         emitcode ("mov","dptr,#LibraryID");
12700         /* make the call */
12701         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12702         emitcode ("jnz","!tlabel",lbl->key+100);
12703
12704         /* put return value into place */
12705         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12706         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12707                 emitcode ("push","ar3");
12708                 emitcode ("push","ar2");
12709                 emitcode ("pop","%s",
12710                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12711                 emitcode ("pop","%s",
12712                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12713         } else {
12714                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12715                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12716         }
12717         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12718         emitcode ("","!tlabeldef",lbl->key+100);
12719         unsavermask(rsave);
12720 }
12721
12722 /*-----------------------------------------------------------------*/
12723 /* genMMMalloc -                                                   */
12724 /*-----------------------------------------------------------------*/
12725 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12726                          int size, const char *name)
12727 {
12728         bitVect *rsave ;
12729         operand *bsize;
12730         symbol *rsym;
12731         symbol *lbl = newiTempLabel(NULL);
12732
12733         assert (nparms == 1);
12734         /* save registers that need to be saved */
12735         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12736                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12737
12738         bsize=parms[0];
12739         aopOp (bsize,ic,FALSE,FALSE);
12740
12741         /* put the size in R4-R2 */
12742         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12743                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12744                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12745                 if (size==3) {
12746                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12747                         emitcode("pop","ar4");
12748                 }
12749                 emitcode("pop","ar3");
12750                 emitcode("pop","ar2");
12751         } else {
12752                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12753                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12754                 if (size==3) {
12755                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12756                 }
12757         }
12758         freeAsmop (bsize, NULL, ic, FALSE);
12759
12760         /* make the call */
12761         emitcode ("lcall","MM_%s",name);
12762         emitcode ("jz","!tlabel",lbl->key+100);
12763         emitcode ("mov","r2,#!constbyte",0xff);
12764         emitcode ("mov","r3,#!constbyte",0xff);
12765         emitcode ("","!tlabeldef",lbl->key+100);
12766         /* we don't care about the pointer : we just save the handle */
12767         rsym = OP_SYMBOL(IC_RESULT(ic));
12768         if (rsym->liveFrom != rsym->liveTo) {
12769                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12770                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12771                         emitcode ("push","ar3");
12772                         emitcode ("push","ar2");
12773                         emitcode ("pop","%s",
12774                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12775                         emitcode ("pop","%s",
12776                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12777                 } else {
12778                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12779                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12780                 }
12781                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12782         }
12783         unsavermask(rsave);
12784 }
12785
12786 /*-----------------------------------------------------------------*/
12787 /* genMMDeref -                                                    */
12788 /*-----------------------------------------------------------------*/
12789 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12790 {
12791         bitVect *rsave ;
12792         operand *handle;
12793
12794         assert (nparms == 1);
12795         /* save registers that need to be saved */
12796         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12797                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12798
12799         handle=parms[0];
12800         aopOp (handle,ic,FALSE,FALSE);
12801
12802         /* put the size in R4-R2 */
12803         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12804                 emitcode("push","%s",
12805                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12806                 emitcode("push","%s",
12807                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12808                 emitcode("pop","ar3");
12809                 emitcode("pop","ar2");
12810         } else {
12811                 emitcode ("mov","r2,%s",
12812                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12813                 emitcode ("mov","r3,%s",
12814                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12815         }
12816         freeAsmop (handle, NULL, ic, FALSE);
12817
12818         /* make the call */
12819         emitcode ("lcall","MM_Deref");
12820
12821         {
12822                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12823                 if (rsym->liveFrom != rsym->liveTo) {
12824                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12825                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12826                             _startLazyDPSEvaluation ();
12827
12828                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12829                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12830                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12831
12832                             _endLazyDPSEvaluation ();
12833
12834                         }
12835                 }
12836         }
12837         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12838         unsavermask(rsave);
12839 }
12840
12841 /*-----------------------------------------------------------------*/
12842 /* genMMUnrestrictedPersist -                                      */
12843 /*-----------------------------------------------------------------*/
12844 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12845 {
12846         bitVect *rsave ;
12847         operand *handle;
12848
12849         assert (nparms == 1);
12850         /* save registers that need to be saved */
12851         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12852                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12853
12854         handle=parms[0];
12855         aopOp (handle,ic,FALSE,FALSE);
12856
12857         /* put the size in R3-R2 */
12858         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12859                 emitcode("push","%s",
12860                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12861                 emitcode("push","%s",
12862                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12863                 emitcode("pop","ar3");
12864                 emitcode("pop","ar2");
12865         } else {
12866                 emitcode ("mov","r2,%s",
12867                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12868                 emitcode ("mov","r3,%s",
12869                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12870         }
12871         freeAsmop (handle, NULL, ic, FALSE);
12872
12873         /* make the call */
12874         emitcode ("lcall","MM_UnrestrictedPersist");
12875
12876         {
12877                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12878                 if (rsym->liveFrom != rsym->liveTo) {
12879                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12880                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12881                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12882                 }
12883         }
12884         unsavermask(rsave);
12885 }
12886
12887 /*-----------------------------------------------------------------*/
12888 /* genSystemExecJavaProcess -                                      */
12889 /*-----------------------------------------------------------------*/
12890 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12891 {
12892         bitVect *rsave ;
12893         operand *handle, *pp;
12894
12895         assert (nparms==2);
12896         /* save registers that need to be saved */
12897         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12898                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12899
12900         pp = parms[0];
12901         handle = parms[1];
12902
12903         /* put the handle in R3-R2 */
12904         aopOp (handle,ic,FALSE,FALSE);
12905         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12906                 emitcode("push","%s",
12907                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12908                 emitcode("push","%s",
12909                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12910                 emitcode("pop","ar3");
12911                 emitcode("pop","ar2");
12912         } else {
12913                 emitcode ("mov","r2,%s",
12914                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12915                 emitcode ("mov","r3,%s",
12916                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12917         }
12918         freeAsmop (handle, NULL, ic, FALSE);
12919
12920         /* put pointer in DPTR */
12921         aopOp (pp,ic,FALSE,FALSE);
12922         if (AOP_TYPE(pp) == AOP_IMMD) {
12923                 emitcode ("mov", "dptr,%s",
12924                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12925         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12926                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12927                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12928                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12929         }
12930         freeAsmop (handle, NULL, ic, FALSE);
12931
12932         /* make the call */
12933         emitcode ("lcall","System_ExecJavaProcess");
12934
12935         /* put result in place */
12936         {
12937                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12938                 if (rsym->liveFrom != rsym->liveTo) {
12939                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12940                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12941                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12942                 }
12943         }
12944
12945         unsavermask(rsave);
12946 }
12947
12948 /*-----------------------------------------------------------------*/
12949 /* genSystemRTCRegisters -                                         */
12950 /*-----------------------------------------------------------------*/
12951 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12952                                   char *name)
12953 {
12954         bitVect *rsave ;
12955         operand *pp;
12956
12957         assert (nparms==1);
12958         /* save registers that need to be saved */
12959         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12960                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12961
12962         pp=parms[0];
12963         /* put pointer in DPTR */
12964         aopOp (pp,ic,FALSE,FALSE);
12965         if (AOP_TYPE (pp) == AOP_IMMD) {
12966                 emitcode ("mov","dps,#1");
12967                 emitcode ("mov", "dptr,%s",
12968                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12969                 emitcode ("mov","dps,#0");
12970         } else {
12971                 emitcode ("mov","dpl1,%s",
12972                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12973                 emitcode ("mov","dph1,%s",
12974                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12975                 emitcode ("mov","dpx1,%s",
12976                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12977         }
12978         freeAsmop (pp, NULL, ic, FALSE);
12979
12980         /* make the call */
12981         emitcode ("lcall","System_%sRTCRegisters",name);
12982
12983         unsavermask(rsave);
12984 }
12985
12986 /*-----------------------------------------------------------------*/
12987 /* genSystemThreadSleep -                                          */
12988 /*-----------------------------------------------------------------*/
12989 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12990 {
12991         bitVect *rsave ;
12992         operand *to, *s;
12993
12994         assert (nparms==1);
12995         /* save registers that need to be saved */
12996         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12997                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12998
12999         to = parms[0];
13000         aopOp(to,ic,FALSE,FALSE);
13001         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13002             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13003                 emitcode ("push","%s",
13004                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13005                 emitcode ("push","%s",
13006                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13007                 emitcode ("push","%s",
13008                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13009                 emitcode ("push","%s",
13010                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13011                 emitcode ("pop","ar3");
13012                 emitcode ("pop","ar2");
13013                 emitcode ("pop","ar1");
13014                 emitcode ("pop","ar0");
13015         } else {
13016                 emitcode ("mov","r0,%s",
13017                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13018                 emitcode ("mov","r1,%s",
13019                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13020                 emitcode ("mov","r2,%s",
13021                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13022                 emitcode ("mov","r3,%s",
13023                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13024         }
13025         freeAsmop (to, NULL, ic, FALSE);
13026
13027         /* suspend in acc */
13028         s = parms[1];
13029         aopOp(s,ic,FALSE,FALSE);
13030         emitcode ("mov","a,%s",
13031                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
13032         freeAsmop (s, NULL, ic, FALSE);
13033
13034         /* make the call */
13035         emitcode ("lcall","System_%s",name);
13036
13037         unsavermask(rsave);
13038 }
13039
13040 /*-----------------------------------------------------------------*/
13041 /* genSystemThreadResume -                                         */
13042 /*-----------------------------------------------------------------*/
13043 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13044 {
13045         bitVect *rsave ;
13046         operand *tid,*pid;
13047
13048         assert (nparms==2);
13049         /* save registers that need to be saved */
13050         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13051                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13052
13053         tid = parms[0];
13054         pid = parms[1];
13055
13056         /* PID in R0 */
13057         aopOp(pid,ic,FALSE,FALSE);
13058         emitcode ("mov","r0,%s",
13059                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13060         freeAsmop (pid, NULL, ic, FALSE);
13061
13062         /* tid into ACC */
13063         aopOp(tid,ic,FALSE,FALSE);
13064         emitcode ("mov","a,%s",
13065                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13066         freeAsmop (tid, NULL, ic, FALSE);
13067
13068         emitcode ("lcall","System_ThreadResume");
13069
13070         /* put result into place */
13071         {
13072                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13073                 if (rsym->liveFrom != rsym->liveTo) {
13074                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13075                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13076                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13077                 }
13078         }
13079         unsavermask(rsave);
13080 }
13081
13082 /*-----------------------------------------------------------------*/
13083 /* genSystemProcessResume -                                        */
13084 /*-----------------------------------------------------------------*/
13085 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13086 {
13087         bitVect *rsave ;
13088         operand *pid;
13089
13090         assert (nparms==1);
13091         /* save registers that need to be saved */
13092         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13093                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13094
13095         pid = parms[0];
13096
13097         /* pid into ACC */
13098         aopOp(pid,ic,FALSE,FALSE);
13099         emitcode ("mov","a,%s",
13100                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13101         freeAsmop (pid, NULL, ic, FALSE);
13102
13103         emitcode ("lcall","System_ProcessResume");
13104
13105         unsavermask(rsave);
13106 }
13107
13108 /*-----------------------------------------------------------------*/
13109 /* genSystem -                                                     */
13110 /*-----------------------------------------------------------------*/
13111 static void genSystem (iCode *ic,int nparms,char *name)
13112 {
13113         assert(nparms == 0);
13114
13115         emitcode ("lcall","System_%s",name);
13116 }
13117
13118 /*-----------------------------------------------------------------*/
13119 /* genSystemPoll -                                                  */
13120 /*-----------------------------------------------------------------*/
13121 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13122 {
13123         bitVect *rsave ;
13124         operand *fp;
13125
13126         assert (nparms==1);
13127         /* save registers that need to be saved */
13128         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13129                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13130
13131         fp = parms[0];
13132         aopOp (fp,ic,FALSE,FALSE);
13133         if (AOP_TYPE (fp) == AOP_IMMD) {
13134                 emitcode ("mov", "dptr,%s",
13135                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13136         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13137                 emitcode ("mov","dpl,%s",
13138                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13139                 emitcode ("mov","dph,%s",
13140                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13141                 emitcode ("mov","dpx,%s",
13142                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13143         }
13144         freeAsmop (fp, NULL, ic, FALSE);
13145
13146         emitcode ("lcall","System_%sPoll",name);
13147
13148         /* put result into place */
13149         {
13150                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13151                 if (rsym->liveFrom != rsym->liveTo) {
13152                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13153                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13154                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13155                 }
13156         }
13157         unsavermask(rsave);
13158 }
13159
13160 /*-----------------------------------------------------------------*/
13161 /* genSystemGetCurrentID -                                         */
13162 /*-----------------------------------------------------------------*/
13163 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13164 {
13165         assert (nparms==0);
13166
13167         emitcode ("lcall","System_GetCurrent%sId",name);
13168         /* put result into place */
13169         {
13170                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13171                 if (rsym->liveFrom != rsym->liveTo) {
13172                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13173                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13174                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13175                 }
13176         }
13177 }
13178
13179 /*-----------------------------------------------------------------*/
13180 /* genDummyRead - generate code for dummy read of volatiles        */
13181 /*-----------------------------------------------------------------*/
13182 static void
13183 genDummyRead (iCode * ic)
13184 {
13185   operand *op;
13186   int size, offset;
13187
13188   D(emitcode(";     genDummyRead",""));
13189
13190   op = IC_RIGHT (ic);
13191   if (op && IS_SYMOP (op))
13192     {
13193       aopOp (op, ic, FALSE, FALSE);
13194
13195       /* if the result is a bit */
13196       if (AOP_TYPE (op) == AOP_CRY)
13197         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13198       else
13199         {
13200           /* bit variables done */
13201           /* general case */
13202           size = AOP_SIZE (op);
13203           offset = 0;
13204           while (size--)
13205           {
13206             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13207             offset++;
13208           }
13209         }
13210
13211       freeAsmop (op, NULL, ic, TRUE);
13212     }
13213
13214   op = IC_LEFT (ic);
13215   if (op && IS_SYMOP (op))
13216     {
13217       aopOp (op, ic, FALSE, FALSE);
13218
13219       /* if the result is a bit */
13220       if (AOP_TYPE (op) == AOP_CRY)
13221         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13222       else
13223         {
13224           /* bit variables done */
13225           /* general case */
13226           size = AOP_SIZE (op);
13227           offset = 0;
13228           while (size--)
13229           {
13230             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13231             offset++;
13232           }
13233         }
13234
13235       freeAsmop (op, NULL, ic, TRUE);
13236     }
13237
13238 }
13239
13240 /*-----------------------------------------------------------------*/
13241 /* genCritical - generate code for start of a critical sequence    */
13242 /*-----------------------------------------------------------------*/
13243 static void
13244 genCritical (iCode *ic)
13245 {
13246   symbol *tlbl = newiTempLabel (NULL);
13247
13248   D(emitcode(";     genCritical",""));
13249
13250   if (IC_RESULT (ic))
13251     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13252
13253   emitcode ("setb", "c");
13254   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13255   emitcode ("clr", "c");
13256   emitcode ("", "%05d$:", (tlbl->key + 100));
13257
13258   if (IC_RESULT (ic))
13259     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13260   else
13261     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13262
13263   if (IC_RESULT (ic))
13264     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13265 }
13266
13267 /*-----------------------------------------------------------------*/
13268 /* genEndCritical - generate code for end of a critical sequence   */
13269 /*-----------------------------------------------------------------*/
13270 static void
13271 genEndCritical (iCode *ic)
13272 {
13273   D(emitcode(";     genEndCritical",""));
13274
13275   if (IC_RIGHT (ic))
13276     {
13277       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13278       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13279         {
13280           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13281           emitcode ("mov", "ea,c");
13282         }
13283       else
13284         {
13285           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13286           emitcode ("rrc", "a");
13287           emitcode ("mov", "ea,c");
13288         }
13289       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13290     }
13291   else
13292     {
13293       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13294       emitcode ("mov", "ea,c");
13295     }
13296 }
13297
13298
13299
13300 /*-----------------------------------------------------------------*/
13301 /* genBuiltIn - calls the appropriate function to  generating code */
13302 /* for a built in function                                         */
13303 /*-----------------------------------------------------------------*/
13304 static void genBuiltIn (iCode *ic)
13305 {
13306         operand *bi_parms[MAX_BUILTIN_ARGS];
13307         int nbi_parms;
13308         iCode *bi_iCode;
13309         symbol *bif;
13310
13311         /* get all the arguments for a built in function */
13312         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13313
13314         /* which function is it */
13315         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13316         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13317                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13318         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13319                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13320         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13321                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13322         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13323                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13324         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13325                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13326         } else if (strcmp(bif->name,"__builtin_inp")==0) {
13327                 genInp(bi_iCode,nbi_parms,bi_parms);
13328         } else if (strcmp(bif->name,"__builtin_outp")==0) {
13329                 genOutp(bi_iCode,nbi_parms,bi_parms);
13330         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13331                 genSwapW(bi_iCode,nbi_parms,bi_parms);
13332                 /* JavaNative builtIns */
13333         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13334                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13335         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13336                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13337         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13338                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13339         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13340                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13341         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13342                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13343         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13344                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13345         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13346                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13347         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13348                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13349         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13350                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13351         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13352                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13353         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13354                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13355         } else if (strcmp(bif->name,"MM_Malloc")==0) {
13356                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13357         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13358                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13359         } else if (strcmp(bif->name,"MM_Free")==0) {
13360                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13361         } else if (strcmp(bif->name,"MM_Deref")==0) {
13362                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13363         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13364                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13365         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13366                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13367         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13368                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13369         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13370                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13371         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13372                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13373         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13374                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13375         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13376                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13377         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13378                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13379         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13380                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13381         } else if (strcmp(bif->name,"System_SaveThread")==0) {
13382                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13383         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13384                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13385         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13386                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13387         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13388                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13389         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13390                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13391         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13392                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13393         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13394                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13395         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13396                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13397         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13398                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13399         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13400                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13401         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13402                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13403         } else {
13404                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13405                 return ;
13406         }
13407         return ;
13408 }
13409
13410 /*-----------------------------------------------------------------*/
13411 /* gen390Code - generate code for Dallas 390 based controllers     */
13412 /*-----------------------------------------------------------------*/
13413 void
13414 gen390Code (iCode * lic)
13415 {
13416   iCode *ic;
13417   int cln = 0;
13418
13419   lineHead = lineCurr = NULL;
13420   dptrn[1][0] = "dpl1";
13421   dptrn[1][1] = "dph1";
13422   dptrn[1][2] = "dpx1";
13423
13424   if (options.model == MODEL_FLAT24) {
13425     fReturnSizeDS390 = 5;
13426     fReturn = fReturn24;
13427   } else {
13428     fReturnSizeDS390 = 4;
13429     fReturn = fReturn16;
13430     options.stack10bit=0;
13431   }
13432 #if 1
13433   /* print the allocation information */
13434   if (allocInfo && currFunc)
13435     printAllocInfo (currFunc, codeOutFile);
13436 #endif
13437   /* if debug information required */
13438   if (options.debug && currFunc)
13439     {
13440       debugFile->writeFunction (currFunc, lic);
13441     }
13442   /* stack pointer name */
13443   if (options.useXstack)
13444     spname = "_spx";
13445   else
13446     spname = "sp";
13447
13448
13449   for (ic = lic; ic; ic = ic->next)
13450     {
13451       _G.current_iCode = ic;
13452
13453       if (ic->lineno && cln != ic->lineno)
13454         {
13455           if (options.debug)
13456             {
13457               debugFile->writeCLine (ic);
13458             }
13459           if (!options.noCcodeInAsm) {
13460             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13461                       printCLine(ic->filename, ic->lineno));
13462           }
13463           cln = ic->lineno;
13464         }
13465       if (options.iCodeInAsm) {
13466         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13467       }
13468       /* if the result is marked as
13469          spilt and rematerializable or code for
13470          this has already been generated then
13471          do nothing */
13472       if (resultRemat (ic) || ic->generated)
13473         continue;
13474
13475       /* depending on the operation */
13476       switch (ic->op)
13477         {
13478         case '!':
13479           genNot (ic);
13480           break;
13481
13482         case '~':
13483           genCpl (ic);
13484           break;
13485
13486         case UNARYMINUS:
13487           genUminus (ic);
13488           break;
13489
13490         case IPUSH:
13491           genIpush (ic);
13492           break;
13493
13494         case IPOP:
13495           /* IPOP happens only when trying to restore a
13496              spilt live range, if there is an ifx statement
13497              following this pop then the if statement might
13498              be using some of the registers being popped which
13499              would destory the contents of the register so
13500              we need to check for this condition and handle it */
13501           if (ic->next &&
13502               ic->next->op == IFX &&
13503               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13504             genIfx (ic->next, ic);
13505           else
13506             genIpop (ic);
13507           break;
13508
13509         case CALL:
13510           genCall (ic);
13511           break;
13512
13513         case PCALL:
13514           genPcall (ic);
13515           break;
13516
13517         case FUNCTION:
13518           genFunction (ic);
13519           break;
13520
13521         case ENDFUNCTION:
13522           genEndFunction (ic);
13523           break;
13524
13525         case RETURN:
13526           genRet (ic);
13527           break;
13528
13529         case LABEL:
13530           genLabel (ic);
13531           break;
13532
13533         case GOTO:
13534           genGoto (ic);
13535           break;
13536
13537         case '+':
13538           genPlus (ic);
13539           break;
13540
13541         case '-':
13542           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13543             genMinus (ic);
13544           break;
13545
13546         case '*':
13547           genMult (ic);
13548           break;
13549
13550         case '/':
13551           genDiv (ic);
13552           break;
13553
13554         case '%':
13555           genMod (ic);
13556           break;
13557
13558         case '>':
13559           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13560           break;
13561
13562         case '<':
13563           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13564           break;
13565
13566         case LE_OP:
13567         case GE_OP:
13568         case NE_OP:
13569
13570           /* note these two are xlated by algebraic equivalence
13571              during parsing SDCC.y */
13572           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13573                   "got '>=' or '<=' shouldn't have come here");
13574           break;
13575
13576         case EQ_OP:
13577           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13578           break;
13579
13580         case AND_OP:
13581           genAndOp (ic);
13582           break;
13583
13584         case OR_OP:
13585           genOrOp (ic);
13586           break;
13587
13588         case '^':
13589           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13590           break;
13591
13592         case '|':
13593           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13594           break;
13595
13596         case BITWISEAND:
13597           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13598           break;
13599
13600         case INLINEASM:
13601           genInline (ic);
13602           break;
13603
13604         case RRC:
13605           genRRC (ic);
13606           break;
13607
13608         case RLC:
13609           genRLC (ic);
13610           break;
13611
13612         case GETHBIT:
13613           genGetHbit (ic);
13614           break;
13615
13616         case LEFT_OP:
13617           genLeftShift (ic);
13618           break;
13619
13620         case RIGHT_OP:
13621           genRightShift (ic);
13622           break;
13623
13624         case GET_VALUE_AT_ADDRESS:
13625           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13626           break;
13627
13628         case '=':
13629           if (POINTER_SET (ic))
13630             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13631           else
13632             genAssign (ic);
13633           break;
13634
13635         case IFX:
13636           genIfx (ic, NULL);
13637           break;
13638
13639         case ADDRESS_OF:
13640           genAddrOf (ic);
13641           break;
13642
13643         case JUMPTABLE:
13644           genJumpTab (ic);
13645           break;
13646
13647         case CAST:
13648           genCast (ic);
13649           break;
13650
13651         case RECEIVE:
13652           genReceive (ic);
13653           break;
13654
13655         case SEND:
13656           if (ic->builtinSEND) genBuiltIn(ic);
13657           else addSet (&_G.sendSet, ic);
13658           break;
13659
13660         case DUMMY_READ_VOLATILE:
13661           genDummyRead (ic);
13662           break;
13663
13664         case CRITICAL:
13665           genCritical (ic);
13666           break;
13667
13668         case ENDCRITICAL:
13669           genEndCritical (ic);
13670           break;
13671
13672         case SWAP:
13673           genSwap (ic);
13674           break;
13675
13676 #if 0 // obsolete, and buggy for != xdata
13677         case ARRAYINIT:
13678             genArrayInit(ic);
13679             break;
13680 #endif
13681
13682         default:
13683           ic = ic;
13684         }
13685     }
13686
13687
13688   /* now we are ready to call the
13689      peep hole optimizer */
13690   if (!options.nopeep)
13691     peepHole (&lineHead);
13692
13693   /* now do the actual printing */
13694   printLine (lineHead, codeOutFile);
13695   return;
13696 }