Use only 3 bytes of generic pointers in comparisons
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for 8051
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   
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12   
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17   
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21   
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25   
26   Notes:
27   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
28                 Made everything static
29 -------------------------------------------------------------------------*/
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "SDCCglobl.h"
36
37 #ifdef HAVE_SYS_ISA_DEFS_H
38 #include <sys/isa_defs.h>
39 #else
40 #ifdef HAVE_ENDIAN_H
41 #include <endian.h>
42 #else
43 #ifndef __BORLANDC__
44 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
45 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
46 #endif
47 #endif
48 #endif
49
50 #include "common.h"
51 #include "SDCCpeeph.h"
52 #include "ralloc.h"
53 #include "gen.h"
54
55 char *aopLiteral (value *val, int offset);
56 extern int allocInfo;
57
58 /* this is the down and dirty file with all kinds of 
59    kludgy & hacky stuff. This is what it is all about
60    CODE GENERATION for a specific MCU . some of the
61    routines may be reusable, will have to see */
62
63 static char *zero = "#0x00";
64 static char *one  = "#0x01";
65 static char *spname ;
66
67 #define D(x) x
68
69 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
70 static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
71 static char *accUse[] = {"a","b"};
72
73 static short rbank = -1;
74
75 static struct {
76     short r0Pushed;
77     short r1Pushed;
78     short accInUse;
79     short inLine;
80     short debugLine;
81     short nRegsSaved;
82     set *sendSet;
83 } _G;
84
85 extern int ds390_ptrRegReq ;
86 extern int ds390_nRegs;
87 extern FILE *codeOutFile;
88 static void saverbank (int, iCode *,bool);
89 #define RESULTONSTACK(x) \
90                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
91                          IC_RESULT(x)->aop->type == AOP_STK )
92
93 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
94 #define MOVA(x) { char *_mova_tmp = strdup(x); \
95                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
96                  { \
97                     emitcode("mov","a,%s",_mova_tmp); \
98                  } \
99                  free(_mova_tmp); \
100                 }
101 #define CLRC    emitcode("clr","c")
102 #define SETC    emitcode("setb","c")
103
104 static lineNode *lineHead = NULL;
105 static lineNode *lineCurr = NULL;
106
107 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
108 0xE0, 0xC0, 0x80, 0x00};
109 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
110 0x07, 0x03, 0x01, 0x00};
111
112 #define LSB     0
113 #define MSB16   1
114 #define MSB24   2
115 #define MSB32   3
116
117 /*-----------------------------------------------------------------*/
118 /* emitcode - writes the code into a file : for now it is simple    */
119 /*-----------------------------------------------------------------*/
120 static void emitcode (char *inst,char *fmt, ...)
121 {
122     va_list ap;
123     char lb[MAX_INLINEASM];  
124     char *lbp = lb;
125
126     va_start(ap,fmt);   
127
128     if (inst && *inst) {
129         if (fmt && *fmt)
130             sprintf(lb,"%s\t",inst);
131         else
132             sprintf(lb,"%s",inst);
133         vsprintf(lb+(strlen(lb)),fmt,ap);
134     }  else
135         vsprintf(lb,fmt,ap);
136
137     while (isspace(*lbp)) lbp++;
138
139     if (lbp && *lbp) 
140         lineCurr = (lineCurr ?
141                     connectLine(lineCurr,newLineNode(lb)) :
142                     (lineHead = newLineNode(lb)));
143     lineCurr->isInline = _G.inLine;
144     lineCurr->isDebug  = _G.debugLine;
145     va_end(ap);
146 }
147
148 /*-----------------------------------------------------------------*/
149 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
150 /*-----------------------------------------------------------------*/
151 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
152 {
153     bool r0iu = FALSE , r1iu = FALSE;
154     bool r0ou = FALSE , r1ou = FALSE;
155
156     /* the logic: if r0 & r1 used in the instruction
157     then we are in trouble otherwise */
158
159     /* first check if r0 & r1 are used by this
160     instruction, in which case we are in trouble */
161     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
162         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
163     {
164         goto endOfWorld;      
165     }
166
167     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
168     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
169
170     /* if no usage of r0 then return it */
171     if (!r0iu && !r0ou) {
172         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
173         (*aopp)->type = AOP_R0;
174         
175         return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
176     }
177
178     /* if no usage of r1 then return it */
179     if (!r1iu && !r1ou) {
180         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
181         (*aopp)->type = AOP_R1;
182
183         return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
184     }    
185
186     /* now we know they both have usage */
187     /* if r0 not used in this instruction */
188     if (!r0iu) {
189         /* push it if not already pushed */
190         if (!_G.r0Pushed) {
191             emitcode ("push","%s",
192                       ds390_regWithIdx(R0_IDX)->dname);
193             _G.r0Pushed++ ;
194         }
195         
196         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
197         (*aopp)->type = AOP_R0;
198
199         return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
200     }
201
202     /* if r1 not used then */
203
204     if (!r1iu) {
205         /* push it if not already pushed */
206         if (!_G.r1Pushed) {
207             emitcode ("push","%s",
208                       ds390_regWithIdx(R1_IDX)->dname);
209             _G.r1Pushed++ ;
210         }
211         
212         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
213         (*aopp)->type = AOP_R1;
214         return ds390_regWithIdx(R1_IDX);
215     }
216
217 endOfWorld :
218     /* I said end of world but not quite end of world yet */
219     /* if this is a result then we can push it on the stack*/
220     if (result) {
221         (*aopp)->type = AOP_STK;    
222         return NULL;
223     }
224
225     piCode(ic,stdout);
226     /* other wise this is true end of the world */
227     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
228            "getFreePtr should never reach here");
229     exit(1);
230 }
231
232 /*-----------------------------------------------------------------*/
233 /* newAsmop - creates a new asmOp                                  */
234 /*-----------------------------------------------------------------*/
235 static asmop *newAsmop (short type)
236 {
237     asmop *aop;
238
239     ALLOC(aop,sizeof(asmop));
240     aop->type = type;
241     return aop;
242 }
243
244 static void genSetDPTR(int n)
245 {
246     if (!n)
247     {
248         emitcode("mov", "dps, #0x00");
249     }
250     else
251     {
252         emitcode("mov", "dps, #0x01");
253     }
254 }
255
256 /*-----------------------------------------------------------------*/
257 /* pointerCode - returns the code for a pointer type               */
258 /*-----------------------------------------------------------------*/
259 static int pointerCode (link *etype)
260 {
261
262     return PTR_TYPE(SPEC_OCLS(etype));
263
264 }
265
266 /*-----------------------------------------------------------------*/
267 /* aopForSym - for a true symbol                                   */
268 /*-----------------------------------------------------------------*/
269 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
270 {
271     asmop *aop;
272     memmap *space= SPEC_OCLS(sym->etype);
273
274     /* if already has one */
275     if (sym->aop)
276         return sym->aop;
277
278     /* assign depending on the storage class */
279     /* if it is on the stack or indirectly addressable */
280     /* space we need to assign either r0 or r1 to it   */    
281     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
282         sym->aop = aop = newAsmop(0);
283         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
284         aop->size = getSize(sym->type);
285
286         /* now assign the address of the variable to 
287         the pointer register */
288         if (aop->type != AOP_STK) {
289
290             if (sym->onStack) {
291                     if ( _G.accInUse )
292                         emitcode("push","acc");
293
294                     emitcode("mov","a,_bp");
295                     emitcode("add","a,#0x%02x",
296                              ((sym->stack < 0) ?
297                               ((char)(sym->stack - _G.nRegsSaved )) :
298                               ((char)sym->stack)) & 0xff);
299                     emitcode("mov","%s,a",
300                              aop->aopu.aop_ptr->name);
301
302                     if ( _G.accInUse )
303                         emitcode("pop","acc");
304             } else
305                 emitcode("mov","%s,#%s",
306                          aop->aopu.aop_ptr->name,
307                          sym->rname);
308             aop->paged = space->paged;
309         } else
310             aop->aopu.aop_stk = sym->stack;
311         return aop;
312     }
313     
314     if (sym->onStack && options.stack10bit)
315     {
316         /* It's on the 10 bit stack, which is located in
317          * far data space.
318          */
319          
320         if ( _G.accInUse )
321                 emitcode("push","acc");
322
323         emitcode("mov","a,_bp");
324         emitcode("add","a,#0x%02x",
325                  ((sym->stack < 0) ?
326                    ((char)(sym->stack - _G.nRegsSaved )) :
327                    ((char)sym->stack)) & 0xff);
328         
329         if (useDP2)
330         {        
331         genSetDPTR(1);
332         emitcode ("mov","dpx1,#0x40");
333         emitcode ("mov","dph1,#0x00");
334         emitcode ("mov","dpl1, a");
335         genSetDPTR(0);
336         }
337         else
338         {
339             emitcode ("mov","dpx,#0x40");
340             emitcode ("mov","dph,#0x00");
341             emitcode ("mov","dpl, a");           
342         }
343         
344         if ( _G.accInUse )
345             emitcode("pop","acc");
346             
347         sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
348         aop->size = getSize(sym->type); 
349         return aop;
350     }
351
352     /* if in bit space */
353     if (IN_BITSPACE(space)) {
354         sym->aop = aop = newAsmop (AOP_CRY);
355         aop->aopu.aop_dir = sym->rname ;
356         aop->size = getSize(sym->type);
357         return aop;
358     }
359     /* if it is in direct space */
360     if (IN_DIRSPACE(space)) {
361         sym->aop = aop = newAsmop (AOP_DIR);
362         aop->aopu.aop_dir = sym->rname ;
363         aop->size = getSize(sym->type);
364         return aop;
365     }
366
367     /* special case for a function */
368     if (IS_FUNC(sym->type)) {   
369         sym->aop = aop = newAsmop(AOP_IMMD);    
370         ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
371         strcpy(aop->aopu.aop_immd,sym->rname);
372         aop->size = FPTRSIZE; 
373         return aop;
374     }
375
376     /* only remaining is far space */
377     /* in which case DPTR gets the address */
378     sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
379     if (useDP2)
380     {        
381         genSetDPTR(1);
382     emitcode ("mov","dptr,#%s", sym->rname);
383         genSetDPTR(0);
384     }    
385     else
386     {
387         emitcode ("mov","dptr,#%s", sym->rname);
388     }
389     aop->size = getSize(sym->type);
390
391     /* if it is in code space */
392     if (IN_CODESPACE(space))
393         aop->code = 1;
394
395     return aop;     
396 }
397
398 /*-----------------------------------------------------------------*/
399 /* aopForRemat - rematerialzes an object                           */
400 /*-----------------------------------------------------------------*/
401 static asmop *aopForRemat (symbol *sym)
402 {
403     iCode *ic = sym->rematiCode;
404     asmop *aop = newAsmop(AOP_IMMD);
405
406     int val = 0;
407
408     for (;;) {
409         if (ic->op == '+')
410             val += operandLitValue(IC_RIGHT(ic));
411         else if (ic->op == '-')
412             val -= operandLitValue(IC_RIGHT(ic));
413         else
414             break;
415         
416         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
417     }
418
419     if (val)
420         sprintf(buffer,"(%s %c 0x%04x)",
421                 OP_SYMBOL(IC_LEFT(ic))->rname, 
422                 val >= 0 ? '+' : '-',
423                 abs(val) & 0xffff);
424     else
425         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
426
427     ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
428     strcpy(aop->aopu.aop_immd,buffer);    
429     return aop;        
430 }
431
432 /*-----------------------------------------------------------------*/
433 /* regsInCommon - two operands have some registers in common       */
434 /*-----------------------------------------------------------------*/
435 static bool regsInCommon (operand *op1, operand *op2)
436 {
437     symbol *sym1, *sym2;
438     int i;
439
440     /* if they have registers in common */
441     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
442         return FALSE ;
443
444     sym1 = OP_SYMBOL(op1);
445     sym2 = OP_SYMBOL(op2);
446
447     if (sym1->nRegs == 0 || sym2->nRegs == 0)
448         return FALSE ;
449
450     for (i = 0 ; i < sym1->nRegs ; i++) {
451         int j;
452         if (!sym1->regs[i])
453             continue ;
454
455         for (j = 0 ; j < sym2->nRegs ;j++ ) {
456             if (!sym2->regs[j])
457                 continue ;
458
459             if (sym2->regs[j] == sym1->regs[i])
460                 return TRUE ;
461         }
462     }
463
464     return FALSE ;
465 }
466
467 /*-----------------------------------------------------------------*/
468 /* operandsEqu - equivalent                                        */
469 /*-----------------------------------------------------------------*/
470 static bool operandsEqu ( operand *op1, operand *op2)
471 {
472     symbol *sym1, *sym2;
473
474     /* if they not symbols */
475     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
476         return FALSE;
477
478     sym1 = OP_SYMBOL(op1);
479     sym2 = OP_SYMBOL(op2);
480
481     /* if both are itemps & one is spilt
482        and the other is not then false */
483     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
484         sym1->isspilt != sym2->isspilt )
485         return FALSE ;
486
487     /* if they are the same */
488     if (sym1 == sym2)
489         return TRUE ;
490
491     if (strcmp(sym1->rname,sym2->rname) == 0)
492         return TRUE;
493
494
495     /* if left is a tmp & right is not */
496     if (IS_ITEMP(op1)  && 
497         !IS_ITEMP(op2) &&
498         sym1->isspilt  &&
499         (sym1->usl.spillLoc == sym2))
500         return TRUE;
501
502     if (IS_ITEMP(op2)  && 
503         !IS_ITEMP(op1) &&
504         sym2->isspilt  &&
505         sym1->level > 0 &&
506         (sym2->usl.spillLoc == sym1))
507         return TRUE ;
508
509     return FALSE ;
510 }
511
512 /*-----------------------------------------------------------------*/
513 /* sameRegs - two asmops have the same registers                   */
514 /*-----------------------------------------------------------------*/
515 static bool sameRegs (asmop *aop1, asmop *aop2 )
516 {
517     int i;
518
519     if (aop1 == aop2)
520     {
521         if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
522         {
523             return FALSE;
524         }
525         return TRUE ;
526     }
527
528     if (aop1->type != AOP_REG ||
529         aop2->type != AOP_REG )
530         return FALSE ;
531
532     if (aop1->size != aop2->size )
533         return FALSE ;
534
535     for (i = 0 ; i < aop1->size ; i++ )
536         if (aop1->aopu.aop_reg[i] !=
537             aop2->aopu.aop_reg[i] )
538             return FALSE ;
539
540     return TRUE ;
541 }
542
543 /*-----------------------------------------------------------------*/
544 /* aopOp - allocates an asmop for an operand  :                    */
545 /*-----------------------------------------------------------------*/
546 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
547 {
548     asmop *aop;
549     symbol *sym;
550     int i;
551
552     if (!op)
553         return ;
554
555     /* if this a literal */
556     if (IS_OP_LITERAL(op)) {
557         op->aop = aop = newAsmop(AOP_LIT);
558         aop->aopu.aop_lit = op->operand.valOperand;
559         aop->size = getSize(operandType(op));
560         return;
561     }
562
563     /* if already has a asmop then continue */
564     if (op->aop)
565         return ;
566
567     /* if the underlying symbol has a aop */
568     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
569         op->aop = OP_SYMBOL(op)->aop;
570         return;
571     }
572
573     /* if this is a true symbol */
574     if (IS_TRUE_SYMOP(op)) {    
575         op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
576         return ;
577     }
578
579     /* this is a temporary : this has
580     only four choices :
581     a) register
582     b) spillocation
583     c) rematerialize 
584     d) conditional   
585     e) can be a return use only */
586
587     sym = OP_SYMBOL(op);
588
589
590     /* if the type is a conditional */
591     if (sym->regType == REG_CND) {
592         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
593         aop->size = 0;
594         return;
595     }
596
597     /* if it is spilt then two situations
598     a) is rematerialize 
599     b) has a spill location */
600     if (sym->isspilt || sym->nRegs == 0) {
601
602         /* rematerialize it NOW */
603         if (sym->remat) {
604             sym->aop = op->aop = aop =
605                                       aopForRemat (sym);
606             aop->size = getSize(sym->type);
607             return;
608         }
609
610         if (sym->accuse) {
611             int i;
612             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
613             aop->size = getSize(sym->type);
614             for ( i = 0 ; i < 2 ; i++ )
615                 aop->aopu.aop_str[i] = accUse[i];
616             return;  
617         }
618
619         if (sym->ruonly ) {
620             int i;
621             aop = op->aop = sym->aop = newAsmop(AOP_STR);
622             aop->size = getSize(sym->type);
623             for ( i = 0 ; i < fReturnSize_390 ; i++ )
624                 aop->aopu.aop_str[i] = fReturn[i];
625             return;
626         }
627
628         /* else spill location  */
629         sym->aop = op->aop = aop = 
630                 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
631         aop->size = getSize(sym->type);
632         return;
633     }
634
635     /* must be in a register */
636     sym->aop = op->aop = aop = newAsmop(AOP_REG);
637     aop->size = sym->nRegs;
638     for ( i = 0 ; i < sym->nRegs ;i++)
639         aop->aopu.aop_reg[i] = sym->regs[i];
640 }
641
642 /*-----------------------------------------------------------------*/
643 /* freeAsmop - free up the asmop given to an operand               */
644 /*----------------------------------------------------------------*/
645 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
646 {   
647     asmop *aop ;
648
649     if (!op)
650         aop = aaop;
651     else 
652         aop = op->aop;
653
654     if (!aop)
655         return ;
656
657     if (aop->freed)
658         goto dealloc; 
659
660     aop->freed = 1;
661
662     /* depending on the asmop type only three cases need work AOP_RO
663        , AOP_R1 && AOP_STK */
664     switch (aop->type) {
665         case AOP_R0 :
666             if (_G.r0Pushed ) {
667                 if (pop) {
668                     emitcode ("pop","ar0");     
669                     _G.r0Pushed--;
670                 }
671             }
672             bitVectUnSetBit(ic->rUsed,R0_IDX);
673             break;
674
675         case AOP_R1 :
676             if (_G.r1Pushed ) {
677                 if (pop) {
678                     emitcode ("pop","ar1");
679                     _G.r1Pushed--;
680                 }
681             }
682             bitVectUnSetBit(ic->rUsed,R1_IDX);          
683             break;
684
685         case AOP_STK :
686         {
687             int sz = aop->size;    
688             int stk = aop->aopu.aop_stk + aop->size;
689             bitVectUnSetBit(ic->rUsed,R0_IDX);
690             bitVectUnSetBit(ic->rUsed,R1_IDX);          
691
692             getFreePtr(ic,&aop,FALSE);
693             
694             if (options.stack10bit)
695             {
696                 /* I'm not sure what to do here yet... */
697                 /* #STUB */
698                 fprintf(stderr, 
699                         "*** Warning: probably generating bad code for "
700                         "10 bit stack mode.\n");
701             }
702             
703             if (stk) {
704                 emitcode ("mov","a,_bp");
705                 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
706                 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
707             } else {
708                 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
709             }
710
711             while (sz--) {
712                 emitcode("pop","acc");
713                 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
714                 if (!sz) break;
715                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
716             }
717             op->aop = aop;
718             freeAsmop(op,NULL,ic,TRUE);
719             if (_G.r0Pushed) {
720                 emitcode("pop","ar0");
721                 _G.r0Pushed--;
722             }
723
724             if (_G.r1Pushed) {
725                 emitcode("pop","ar1");
726                 _G.r1Pushed--;
727             }       
728         }
729     }
730
731 dealloc:
732     /* all other cases just dealloc */
733     if (op ) {
734         op->aop = NULL;
735         if (IS_SYMOP(op)) {
736             OP_SYMBOL(op)->aop = NULL;    
737             /* if the symbol has a spill */
738             if (SPIL_LOC(op))
739                 SPIL_LOC(op)->aop = NULL;
740         }
741     }
742 }
743
744 /*------------------------------------------------------------------*/
745 /* aopGet - for fetching value of the aop                           */
746 /*                                                                  */
747 /* Set canClobberACC if you are aure it is OK to clobber the value  */
748 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe,*/
749 /* just less efficient.                                             */
750 /*------------------------------------------------------------------*/
751
752 static char *aopGet (asmop *aop, 
753                      int offset, 
754                      bool bit16,
755                      bool dname,
756                      bool canClobberACC)
757 {
758     char *s = buffer ;
759     char *rs;
760
761     /* offset is greater than
762     size then zero */
763     if (offset > (aop->size - 1) &&
764         aop->type != AOP_LIT)
765         return zero;
766
767     /* depending on type */
768     switch (aop->type) {
769         
770     case AOP_R0:
771     case AOP_R1:
772         /* if we need to increment it */       
773         while (offset > aop->coff) {        
774             emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
775             aop->coff++;
776         }
777         
778         while (offset < aop->coff) {
779             emitcode("dec","%s",aop->aopu.aop_ptr->name);
780             aop->coff--;
781         }
782         
783         aop->coff = offset ;
784         if (aop->paged) {
785             emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
786             return (dname ? "acc" : "a");
787         }       
788         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
789         ALLOC_ATOMIC(rs,strlen(s)+1);
790         strcpy(rs,s);   
791         return rs;
792         
793     case AOP_DPTR:
794     case AOP_DPTR2:
795     
796     if (aop->type == AOP_DPTR2)
797     {
798         genSetDPTR(1);
799         
800 #ifndef KEVIN_BROKE_IT        
801         if (!canClobberACC)
802 #endif        
803         {
804             emitcode("xch", "a, ap");
805         }
806     }
807     
808         while (offset > aop->coff) {
809             emitcode ("inc","dptr");
810             aop->coff++;
811         }
812         
813         while (offset < aop->coff) {        
814             emitcode("lcall","__decdptr");
815             aop->coff--;
816         }
817         
818         aop->coff = offset;
819         if (aop->code) {
820             emitcode("clr","a");
821             emitcode("movc","a,@a+dptr");
822         }
823     else {
824             emitcode("movx","a,@dptr");
825     }
826             
827     if (aop->type == AOP_DPTR2)
828     {
829         genSetDPTR(0);
830
831 #ifndef KEVIN_BROKE_IT        
832         if (!canClobberACC)
833 #endif        
834         {
835             emitcode("xch", "a, ap");
836             return "ap";
837         }
838     }
839             
840     return (dname ? "acc" : "a");
841         
842         
843     case AOP_IMMD:
844         if (bit16) 
845             sprintf (s,"#%s",aop->aopu.aop_immd);
846         else
847             if (offset) 
848                 sprintf(s,"#(%s >> %d)",
849                         aop->aopu.aop_immd,
850                         offset*8);
851             else
852                 sprintf(s,"#%s",
853                         aop->aopu.aop_immd);
854         ALLOC_ATOMIC(rs,strlen(s)+1);
855         strcpy(rs,s);   
856         return rs;
857         
858     case AOP_DIR:
859         if (offset)
860             sprintf(s,"(%s + %d)",
861                     aop->aopu.aop_dir,
862                     offset);
863         else
864             sprintf(s,"%s",aop->aopu.aop_dir);
865         ALLOC_ATOMIC(rs,strlen(s)+1);
866         strcpy(rs,s);   
867         return rs;
868         
869     case AOP_REG:
870         if (dname) 
871             return aop->aopu.aop_reg[offset]->dname;
872         else
873             return aop->aopu.aop_reg[offset]->name;
874         
875     case AOP_CRY:
876         emitcode("clr","a");
877         emitcode("mov","c,%s",aop->aopu.aop_dir);
878         emitcode("rlc","a") ;
879         return (dname ? "acc" : "a");
880         
881     case AOP_ACC:
882         if (!offset && dname)
883             return "acc";
884         return aop->aopu.aop_str[offset];
885
886     case AOP_LIT:
887         return aopLiteral (aop->aopu.aop_lit,offset);
888         
889     case AOP_STR:
890         aop->coff = offset ;
891         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
892             dname)
893             return "acc";
894         
895         return aop->aopu.aop_str[offset];
896         
897     }
898
899     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
900            "aopget got unsupported aop->type");
901     exit(1);
902 }
903 /*-----------------------------------------------------------------*/
904 /* aopPut - puts a string for a aop                                */
905 /*-----------------------------------------------------------------*/
906 static void aopPut (asmop *aop, char *s, int offset)
907 {
908     char *d = buffer ;
909     symbol *lbl ;
910
911     if (aop->size && offset > ( aop->size - 1)) {
912         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
913                "aopPut got offset > aop->size");
914         exit(1);
915     }
916
917     /* will assign value to value */
918     /* depending on where it is ofcourse */
919     switch (aop->type) {
920     case AOP_DIR:
921         if (offset)
922             sprintf(d,"(%s + %d)",
923                     aop->aopu.aop_dir,offset);
924         else
925             sprintf(d,"%s",aop->aopu.aop_dir);
926         
927         if (strcmp(d,s))
928             emitcode("mov","%s,%s",d,s);
929         
930         break;
931         
932     case AOP_REG:
933         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
934             strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
935             if (*s == '@'           ||
936                 strcmp(s,"r0") == 0 ||
937                 strcmp(s,"r1") == 0 ||
938                 strcmp(s,"r2") == 0 ||
939                 strcmp(s,"r3") == 0 ||
940                 strcmp(s,"r4") == 0 ||
941                 strcmp(s,"r5") == 0 ||
942                 strcmp(s,"r6") == 0 || 
943                 strcmp(s,"r7") == 0 )
944                 emitcode("mov","%s,%s",
945                          aop->aopu.aop_reg[offset]->dname,s);
946             else
947                 emitcode("mov","%s,%s",
948                          aop->aopu.aop_reg[offset]->name,s);
949         }
950         break;
951         
952     case AOP_DPTR:
953     case AOP_DPTR2:
954     
955     if (aop->type == AOP_DPTR2)
956     {
957         genSetDPTR(1);
958     }
959     
960         if (aop->code) {
961             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
962                    "aopPut writting to code space");
963             exit(1);
964         }
965         
966         while (offset > aop->coff) {
967             aop->coff++;
968             emitcode ("inc","dptr");
969         }
970         
971         while (offset < aop->coff) {
972             aop->coff-- ;
973             emitcode("lcall","__decdptr");
974         }
975         
976         aop->coff = offset;
977         
978         /* if not in accumulater */
979         MOVA(s);        
980         
981         emitcode ("movx","@dptr,a");
982         
983     if (aop->type == AOP_DPTR2)
984     {
985         genSetDPTR(0);
986     }
987         break;
988         
989     case AOP_R0:
990     case AOP_R1:
991         while (offset > aop->coff) {
992             aop->coff++;
993             emitcode("inc","%s",aop->aopu.aop_ptr->name);
994         }
995         while (offset < aop->coff) {
996             aop->coff-- ;
997             emitcode ("dec","%s",aop->aopu.aop_ptr->name);
998         }
999         aop->coff = offset;
1000         
1001         if (aop->paged) {
1002             MOVA(s);           
1003             emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1004             
1005         } else
1006             if (*s == '@') {
1007                 MOVA(s);
1008                 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1009             } else
1010                 if (strcmp(s,"r0") == 0 ||
1011                     strcmp(s,"r1") == 0 ||
1012                     strcmp(s,"r2") == 0 ||
1013                     strcmp(s,"r3") == 0 ||
1014                     strcmp(s,"r4") == 0 ||
1015                     strcmp(s,"r5") == 0 ||
1016                     strcmp(s,"r6") == 0 || 
1017                     strcmp(s,"r7") == 0 ) {
1018                     char buffer[10];
1019                     sprintf(buffer,"a%s",s);
1020                     emitcode("mov","@%s,%s",
1021                              aop->aopu.aop_ptr->name,buffer);
1022                 } else
1023                     emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1024         
1025         break;
1026         
1027     case AOP_STK:
1028         if (strcmp(s,"a") == 0)
1029             emitcode("push","acc");
1030         else
1031             emitcode("push","%s",s);
1032         
1033         break;
1034         
1035     case AOP_CRY:
1036         /* if bit variable */
1037         if (!aop->aopu.aop_dir) {
1038             emitcode("clr","a");
1039             emitcode("rlc","a");
1040         } else {
1041             if (s == zero) 
1042                 emitcode("clr","%s",aop->aopu.aop_dir);
1043             else
1044                 if (s == one)
1045                     emitcode("setb","%s",aop->aopu.aop_dir);
1046                 else
1047                     if (!strcmp(s,"c"))
1048                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1049                     else {
1050                         lbl = newiTempLabel(NULL);
1051                         
1052                         if (strcmp(s,"a")) {
1053                             MOVA(s);
1054                         }
1055                         emitcode("clr","c");
1056                         emitcode("jz","%05d$",lbl->key+100);
1057                         emitcode("cpl","c");
1058                         emitcode("","%05d$:",lbl->key+100);
1059                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1060                     }
1061         }
1062         break;
1063         
1064     case AOP_STR:
1065         aop->coff = offset;
1066         if (strcmp(aop->aopu.aop_str[offset],s))
1067             emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1068         break;
1069         
1070     case AOP_ACC:
1071         aop->coff = offset;
1072         if (!offset && (strcmp(s,"acc") == 0))
1073             break;
1074         
1075         if (strcmp(aop->aopu.aop_str[offset],s))
1076             emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1077         break;
1078
1079     default :
1080         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1081                "aopPut got unsupported aop->type");
1082         exit(1);    
1083     }    
1084
1085 }
1086
1087
1088 #if 0
1089 /*-----------------------------------------------------------------*/
1090 /* pointToEnd :- points to the last byte of the operand            */
1091 /*-----------------------------------------------------------------*/
1092 static void pointToEnd (asmop *aop)
1093 {
1094     int count ;
1095     if (!aop)
1096         return ;
1097
1098     aop->coff = count = (aop->size - 1);
1099     switch (aop->type) {
1100         case AOP_R0 :
1101         case AOP_R1 :
1102             while (count--)
1103                 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1104             break;
1105         case AOP_DPTR :
1106             while (count--)
1107                 emitcode("inc","dptr");
1108             break;
1109     }
1110
1111 }
1112 #endif
1113
1114 /*-----------------------------------------------------------------*/
1115 /* reAdjustPreg - points a register back to where it should        */
1116 /*-----------------------------------------------------------------*/
1117 static void reAdjustPreg (asmop *aop)
1118 {
1119     int size ;
1120
1121     aop->coff = 0;
1122     if ((size = aop->size) <= 1)
1123         return ;
1124     size-- ;
1125     switch (aop->type) {
1126         case AOP_R0 :
1127         case AOP_R1 :
1128             while (size--)
1129                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1130             break;          
1131         case AOP_DPTR :
1132         case AOP_DPTR2:
1133             if (aop->type == AOP_DPTR2)
1134             {
1135                 genSetDPTR(1);
1136             } 
1137             while (size--)
1138             {
1139                 emitcode("lcall","__decdptr");
1140             }
1141                 
1142             if (aop->type == AOP_DPTR2)
1143             {
1144                 genSetDPTR(0);
1145             }                
1146             break;  
1147
1148     }   
1149
1150 }
1151
1152 #define AOP(op) op->aop
1153 #define AOP_TYPE(op) AOP(op)->type
1154 #define AOP_SIZE(op) AOP(op)->size
1155 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1156                        AOP_TYPE(x) == AOP_R0))
1157
1158 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1159                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1160                          AOP(x)->paged)) 
1161
1162 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1163                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1164                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1165
1166 /* Workaround for DS80C390 bug: div ab may return bogus results
1167  * if A is accessed in instruction immediately before the div.
1168  *
1169  * Will be fixed in B4 rev of processor, Dallas claims.
1170  */
1171  
1172 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)                         \
1173     if (!AOP_NEEDSACC(RIGHT))                                   \
1174     {                                                           \
1175         /* We can load A first, then B, since                   \
1176          * B (the RIGHT operand) won't clobber A,               \
1177          * thus avoiding touching A right before the div.       \
1178          */                                                     \
1179         D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1180         L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);               \
1181         MOVA(L);                                                \
1182         emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1183     }                                                           \
1184     else                                                        \
1185     {                                                           \
1186         /* Just stuff in a nop after loading A. */              \
1187         emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1188         L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);               \
1189         MOVA(L);                                                \
1190         emitcode("nop", "; workaround for DS80C390 div bug.");  \
1191     }
1192
1193 /*-----------------------------------------------------------------*/
1194 /* genNotFloat - generates not for float operations              */
1195 /*-----------------------------------------------------------------*/
1196 static void genNotFloat (operand *op, operand *res)
1197 {
1198     int size, offset;
1199     char *l;
1200     symbol *tlbl ;
1201
1202     D(emitcode(";", "genNotFloat "););
1203
1204     /* we will put 127 in the first byte of 
1205     the result */
1206     aopPut(AOP(res),"#127",0);
1207     size = AOP_SIZE(op) - 1;
1208     offset = 1;
1209
1210     l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1211     MOVA(l);    
1212
1213     while(size--) {
1214         emitcode("orl","a,%s",
1215                  aopGet(op->aop,
1216                         offset++,FALSE,FALSE,FALSE));
1217     }
1218     tlbl = newiTempLabel(NULL);
1219
1220     tlbl = newiTempLabel(NULL);
1221     aopPut(res->aop,one,1);
1222     emitcode("jz","%05d$",(tlbl->key+100));
1223     aopPut(res->aop,zero,1);
1224     emitcode("","%05d$:",(tlbl->key+100));
1225
1226     size = res->aop->size - 2;
1227     offset = 2;    
1228     /* put zeros in the rest */
1229     while (size--) 
1230         aopPut(res->aop,zero,offset++);
1231 }
1232
1233 /*-----------------------------------------------------------------*/
1234 /* opIsGptr: returns non-zero if the passed operand is             */   
1235 /* a generic pointer type.                                         */
1236 /*-----------------------------------------------------------------*/ 
1237 static int opIsGptr(operand *op)
1238 {
1239     link *type = operandType(op);
1240     
1241     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1242     {
1243         return 1;
1244     }
1245     return 0;        
1246 }
1247
1248 /*-----------------------------------------------------------------*/
1249 /* getDataSize - get the operand data size                         */
1250 /*-----------------------------------------------------------------*/
1251 static int getDataSize(operand *op)
1252 {
1253     int size;
1254     size = AOP_SIZE(op);
1255     if (size == GPTRSIZE)
1256     {
1257         link *type = operandType(op);
1258         if (IS_GENPTR(type))
1259         {
1260             /* generic pointer; arithmetic operations
1261              * should ignore the high byte (pointer type).
1262              */
1263             size--;
1264         }
1265     }
1266     return size;
1267 }
1268
1269 /*-----------------------------------------------------------------*/
1270 /* outAcc - output Acc                                             */
1271 /*-----------------------------------------------------------------*/
1272 static void outAcc(operand *result)
1273 {
1274     int size, offset;
1275     size = getDataSize(result);
1276     if(size){
1277         aopPut(AOP(result),"a",0);
1278         size--;
1279         offset = 1;
1280         /* unsigned or positive */
1281         while(size--){
1282             aopPut(AOP(result),zero,offset++);
1283         }
1284     }
1285 }
1286
1287 /*-----------------------------------------------------------------*/
1288 /* outBitC - output a bit C                                        */
1289 /*-----------------------------------------------------------------*/
1290 static void outBitC(operand *result)
1291 {
1292     /* if the result is bit */
1293     if (AOP_TYPE(result) == AOP_CRY) 
1294         aopPut(AOP(result),"c",0);
1295     else {
1296         emitcode("clr","a");
1297         emitcode("rlc","a");
1298         outAcc(result);
1299     }
1300 }
1301
1302 /*-----------------------------------------------------------------*/
1303 /* toBoolean - emit code for orl a,operator(sizeop)                */
1304 /*-----------------------------------------------------------------*/
1305 static void toBoolean(operand *oper)
1306 {
1307     int size = AOP_SIZE(oper) - 1;
1308     int offset = 1;
1309
1310     /* The generic part of a generic pointer should
1311      * not participate in it's truth value.
1312      *
1313      * i.e. 0x10000000 is zero.
1314      */
1315     if (opIsGptr(oper))
1316     {
1317         D(emitcode(";", "toBoolean: generic ptr special case."););
1318         size--;
1319     }
1320
1321     if (AOP_NEEDSACC(oper))
1322     {
1323         emitcode("push", "b");
1324         emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1325     }
1326     else
1327     {
1328         MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1329     }
1330     while (size--) 
1331     {
1332         if (AOP_NEEDSACC(oper))
1333         {
1334             emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1335         }
1336         else
1337         {
1338         emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1339 }
1340     }
1341     
1342     if (AOP_NEEDSACC(oper))
1343     {
1344         emitcode("mov", "a,b");
1345         emitcode("pop", "b");
1346     }
1347 }
1348
1349
1350 /*-----------------------------------------------------------------*/
1351 /* genNot - generate code for ! operation                          */
1352 /*-----------------------------------------------------------------*/
1353 static void genNot (iCode *ic)
1354 {
1355     symbol *tlbl;
1356     link *optype = operandType(IC_LEFT(ic));
1357
1358     D(emitcode(";", "genNot "););
1359
1360     /* assign asmOps to operand & result */
1361     aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1362     aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1363
1364     /* if in bit space then a special case */
1365     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1366         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1367         emitcode("cpl","c"); 
1368         outBitC(IC_RESULT(ic));
1369         goto release;
1370     }
1371
1372     /* if type float then do float */
1373     if (IS_FLOAT(optype)) {
1374         genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1375         goto release;
1376     }
1377
1378     toBoolean(IC_LEFT(ic));
1379
1380     tlbl = newiTempLabel(NULL);
1381     emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1382     emitcode("","%05d$:",tlbl->key+100);
1383     outBitC(IC_RESULT(ic));
1384
1385 release:    
1386     /* release the aops */
1387     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1388     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1389 }
1390
1391
1392 /*-----------------------------------------------------------------*/
1393 /* genCpl - generate code for complement                           */
1394 /*-----------------------------------------------------------------*/
1395 static void genCpl (iCode *ic)
1396 {
1397     int offset = 0;
1398     int size ;
1399
1400     D(emitcode(";", "genCpl "););
1401
1402
1403     /* assign asmOps to operand & result */
1404     aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1405     aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1406
1407     /* if both are in bit space then 
1408     a special case */
1409     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1410         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1411
1412         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1413         emitcode("cpl","c"); 
1414         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1415         goto release; 
1416     } 
1417
1418     size = AOP_SIZE(IC_RESULT(ic));
1419     while (size--) {
1420         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1421         MOVA(l);       
1422         emitcode("cpl","a");
1423         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1424     }
1425
1426
1427 release:
1428     /* release the aops */
1429     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1430     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1431 }
1432
1433 /*-----------------------------------------------------------------*/
1434 /* genUminusFloat - unary minus for floating points                */
1435 /*-----------------------------------------------------------------*/
1436 static void genUminusFloat(operand *op,operand *result)
1437 {
1438     int size ,offset =0 ;
1439     char *l;
1440     /* for this we just need to flip the 
1441     first it then copy the rest in place */
1442     D(emitcode(";", "genUminusFloat"););
1443     
1444     size = AOP_SIZE(op) - 1;
1445     l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1446     MOVA(l);    
1447
1448     emitcode("cpl","acc.7");
1449     aopPut(AOP(result),"a",3);    
1450
1451     while(size--) {
1452         aopPut(AOP(result),
1453                aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1454                offset);
1455         offset++;
1456     }          
1457 }
1458
1459 /*-----------------------------------------------------------------*/
1460 /* genUminus - unary minus code generation                         */
1461 /*-----------------------------------------------------------------*/
1462 static void genUminus (iCode *ic)
1463 {
1464     int offset ,size ;
1465     link *optype, *rtype;
1466
1467     D(emitcode(";", "genUminus "););
1468
1469
1470     /* assign asmops */
1471     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1472     aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1473
1474     /* if both in bit space then special
1475     case */
1476     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1477         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1478
1479         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1480         emitcode("cpl","c"); 
1481         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1482         goto release; 
1483     } 
1484
1485     optype = operandType(IC_LEFT(ic));
1486     rtype = operandType(IC_RESULT(ic));
1487
1488     /* if float then do float stuff */
1489     if (IS_FLOAT(optype)) {
1490         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1491         goto release;
1492     }
1493
1494     /* otherwise subtract from zero */
1495     size = AOP_SIZE(IC_LEFT(ic));
1496     offset = 0 ;
1497     //CLRC ;
1498     while(size--) {
1499         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1500         if (!strcmp(l,"a")) {
1501           if (offset==0)
1502             SETC;
1503           emitcode("cpl","a");
1504           emitcode("addc", "a,#0");
1505         } else {
1506           if (offset==0)
1507             CLRC;
1508           emitcode("clr","a");
1509           emitcode("subb","a,%s",l);
1510         }       
1511         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1512     }
1513
1514     /* if any remaining bytes in the result */
1515     /* we just need to propagate the sign   */
1516     if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1517         emitcode("rlc","a");
1518         emitcode("subb","a,acc");
1519         while (size--) 
1520             aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1521     }       
1522
1523 release:
1524     /* release the aops */
1525     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1526     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1527 }
1528
1529 /*-----------------------------------------------------------------*/
1530 /* saveRegisters - will look for a call and save the registers     */
1531 /*-----------------------------------------------------------------*/
1532 static void saveRegisters(iCode *lic) 
1533 {
1534     int i;
1535     iCode *ic;
1536     bitVect *rsave;
1537     link *detype;
1538
1539     /* look for call */
1540     for (ic = lic ; ic ; ic = ic->next) 
1541         if (ic->op == CALL || ic->op == PCALL)
1542             break;
1543
1544     if (!ic) {
1545         fprintf(stderr,"found parameter push with no function call\n");
1546         return ;
1547     }
1548
1549     /* if the registers have been saved already then
1550     do nothing */
1551     if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1552         return ;
1553
1554     /* find the registers in use at this time 
1555     and push them away to safety */
1556     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1557                           ic->rUsed);
1558
1559     ic->regsSaved = 1;
1560     if (options.useXstack) {
1561         if (bitVectBitValue(rsave,R0_IDX))
1562             emitcode("mov","b,r0");
1563         emitcode("mov","r0,%s",spname);
1564         for (i = 0 ; i < ds390_nRegs ; i++) {
1565             if (bitVectBitValue(rsave,i)) {
1566                 if (i == R0_IDX)
1567                     emitcode("mov","a,b");
1568                 else
1569                     emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1570                 emitcode("movx","@r0,a");
1571                 emitcode("inc","r0");
1572             }
1573         }
1574         emitcode("mov","%s,r0",spname);
1575         if (bitVectBitValue(rsave,R0_IDX))
1576             emitcode("mov","r0,b");         
1577     } else
1578         for (i = 0 ; i < ds390_nRegs ; i++) {
1579             if (bitVectBitValue(rsave,i))
1580                 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1581         }
1582
1583     detype = getSpec(operandType(IC_LEFT(ic)));
1584     if (detype        && 
1585         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1586         IS_ISR(currFunc->etype) &&
1587         !ic->bankSaved) 
1588
1589         saverbank(SPEC_BANK(detype),ic,TRUE);
1590
1591 }
1592 /*-----------------------------------------------------------------*/
1593 /* unsaveRegisters - pop the pushed registers                      */
1594 /*-----------------------------------------------------------------*/
1595 static void unsaveRegisters (iCode *ic)
1596 {
1597     int i;
1598     bitVect *rsave;
1599     /* find the registers in use at this time 
1600     and push them away to safety */
1601     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1602                           ic->rUsed);
1603     
1604     if (options.useXstack) {
1605         emitcode("mov","r0,%s",spname); 
1606         for (i =  ds390_nRegs ; i >= 0 ; i--) {
1607             if (bitVectBitValue(rsave,i)) {
1608                 emitcode("dec","r0");
1609                 emitcode("movx","a,@r0");
1610                 if (i == R0_IDX)
1611                     emitcode("mov","b,a");
1612                 else
1613                     emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1614             }       
1615
1616         }
1617         emitcode("mov","%s,r0",spname);
1618         if (bitVectBitValue(rsave,R0_IDX))
1619             emitcode("mov","r0,b");
1620     } else
1621         for (i =  ds390_nRegs ; i >= 0 ; i--) {
1622             if (bitVectBitValue(rsave,i))
1623                 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1624         }
1625
1626 }  
1627
1628
1629 /*-----------------------------------------------------------------*/
1630 /* pushSide -                                                      */
1631 /*-----------------------------------------------------------------*/
1632 static void pushSide(operand * oper, int size)
1633 {
1634         int offset = 0;
1635         while (size--) {
1636                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1637                 if (AOP_TYPE(oper) != AOP_REG &&
1638                     AOP_TYPE(oper) != AOP_DIR &&
1639                     strcmp(l,"a") ) {
1640                         emitcode("mov","a,%s",l);
1641                         emitcode("push","acc");
1642                 } else
1643                         emitcode("push","%s",l);
1644         }
1645 }
1646
1647 /*-----------------------------------------------------------------*/
1648 /* assignResultValue -                                             */
1649 /*-----------------------------------------------------------------*/
1650 static void assignResultValue(operand * oper)
1651 {
1652         int offset = 0;
1653         int size = AOP_SIZE(oper);
1654         while (size--) {
1655                 aopPut(AOP(oper),fReturn[offset],offset);
1656                 offset++;
1657         }
1658 }
1659
1660
1661 /*-----------------------------------------------------------------*/
1662 /* genXpush - pushes onto the external stack                       */
1663 /*-----------------------------------------------------------------*/
1664 static void genXpush (iCode *ic)
1665 {
1666     asmop *aop = newAsmop(0);
1667     regs *r ;
1668     int size,offset = 0;
1669
1670     D(emitcode(";", "genXpush "););
1671
1672     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1673     r = getFreePtr(ic,&aop,FALSE);
1674
1675     
1676     emitcode("mov","%s,_spx",r->name);
1677
1678     size = AOP_SIZE(IC_LEFT(ic));
1679     while(size--) {
1680
1681         char *l = aopGet(AOP(IC_LEFT(ic)),
1682                          offset++,FALSE,FALSE,TRUE);    
1683         MOVA(l);            
1684         emitcode("movx","@%s,a",r->name);       
1685         emitcode("inc","%s",r->name);
1686
1687     }
1688
1689         
1690     emitcode("mov","_spx,%s",r->name);
1691
1692     freeAsmop(NULL,aop,ic,TRUE);
1693     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1694 }
1695
1696 /*-----------------------------------------------------------------*/
1697 /* genIpush - genrate code for pushing this gets a little complex  */
1698 /*-----------------------------------------------------------------*/
1699 static void genIpush (iCode *ic)
1700 {
1701     int size, offset = 0 ;
1702     char *l;
1703
1704     D(emitcode(";", "genIpush "););
1705
1706
1707     /* if this is not a parm push : ie. it is spill push 
1708     and spill push is always done on the local stack */
1709     if (!ic->parmPush) {
1710
1711         /* and the item is spilt then do nothing */
1712         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1713             return ;
1714
1715         aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1716         size = AOP_SIZE(IC_LEFT(ic));
1717         /* push it on the stack */
1718         while(size--) {
1719             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1720             if (*l == '#') {
1721                 MOVA(l);
1722                 l = "acc";
1723             }
1724             emitcode("push","%s",l);
1725         }
1726         return ;        
1727     }
1728
1729     /* this is a paramter push: in this case we call
1730     the routine to find the call and save those
1731     registers that need to be saved */   
1732     saveRegisters(ic);
1733
1734     /* if use external stack then call the external
1735     stack pushing routine */
1736     if (options.useXstack) {
1737         genXpush(ic);
1738         return ;
1739     }
1740
1741     /* then do the push */
1742     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1743
1744
1745         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1746     size = AOP_SIZE(IC_LEFT(ic));
1747
1748     while (size--) {
1749         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1750         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
1751             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1752             strcmp(l,"a") ) {
1753             emitcode("mov","a,%s",l);
1754             emitcode("push","acc");
1755         } else
1756             emitcode("push","%s",l);
1757     }       
1758
1759     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1760 }
1761
1762 /*-----------------------------------------------------------------*/
1763 /* genIpop - recover the registers: can happen only for spilling   */
1764 /*-----------------------------------------------------------------*/
1765 static void genIpop (iCode *ic)
1766 {
1767     int size,offset ;
1768
1769     D(emitcode(";", "genIpop "););
1770
1771
1772     /* if the temp was not pushed then */
1773     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1774         return ;
1775
1776     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1777     size = AOP_SIZE(IC_LEFT(ic));
1778     offset = (size-1);
1779     while (size--) 
1780         emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1781                                    FALSE,TRUE,TRUE));
1782
1783     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1784 }
1785
1786 /*-----------------------------------------------------------------*/
1787 /* unsaverbank - restores the resgister bank from stack            */
1788 /*-----------------------------------------------------------------*/
1789 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1790 {
1791     int i;
1792     asmop *aop ;
1793     regs *r = NULL;
1794
1795     if (popPsw) {
1796         if (options.useXstack) {
1797             aop = newAsmop(0);
1798             r = getFreePtr(ic,&aop,FALSE);
1799             
1800             
1801             emitcode("mov","%s,_spx",r->name);
1802             emitcode("movx","a,@%s",r->name);
1803             emitcode("mov","psw,a");
1804             emitcode("dec","%s",r->name);
1805             
1806         }else
1807             emitcode ("pop","psw");
1808     }
1809
1810     for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1811         if (options.useXstack) {       
1812             emitcode("movx","a,@%s",r->name);
1813             emitcode("mov","(%s+%d),a",
1814                      regs390[i].base,8*bank+regs390[i].offset);
1815             emitcode("dec","%s",r->name);
1816
1817         } else 
1818             emitcode("pop","(%s+%d)",
1819                      regs390[i].base,8*bank+regs390[i].offset);
1820     }
1821
1822     if (options.useXstack) {
1823
1824         emitcode("mov","_spx,%s",r->name);
1825         freeAsmop(NULL,aop,ic,TRUE);
1826
1827     } 
1828 }
1829
1830 /*-----------------------------------------------------------------*/
1831 /* saverbank - saves an entire register bank on the stack          */
1832 /*-----------------------------------------------------------------*/
1833 static void saverbank (int bank, iCode *ic, bool pushPsw)
1834 {
1835     int i;
1836     asmop *aop ;
1837     regs *r = NULL;
1838
1839     if (options.useXstack) {
1840
1841         aop = newAsmop(0);
1842         r = getFreePtr(ic,&aop,FALSE);  
1843         emitcode("mov","%s,_spx",r->name);
1844
1845     }
1846
1847     for (i = 0 ; i < ds390_nRegs ;i++) {
1848         if (options.useXstack) {
1849             emitcode("inc","%s",r->name);
1850             emitcode("mov","a,(%s+%d)",
1851                      regs390[i].base,8*bank+regs390[i].offset);
1852             emitcode("movx","@%s,a",r->name);           
1853         } else 
1854             emitcode("push","(%s+%d)",
1855                      regs390[i].base,8*bank+regs390[i].offset);
1856     }
1857     
1858     if (pushPsw) {
1859         if (options.useXstack) {
1860             emitcode("mov","a,psw");
1861             emitcode("movx","@%s,a",r->name);   
1862             emitcode("inc","%s",r->name);
1863             emitcode("mov","_spx,%s",r->name);       
1864             freeAsmop (NULL,aop,ic,TRUE);
1865             
1866         } else
1867             emitcode("push","psw");
1868         
1869         emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1870     }
1871     ic->bankSaved = 1;
1872
1873 }
1874
1875 /*-----------------------------------------------------------------*/
1876 /* genCall - generates a call statement                            */
1877 /*-----------------------------------------------------------------*/
1878 static void genCall (iCode *ic)
1879 {
1880     link *detype;   
1881
1882     D(emitcode(";", "genCall "););
1883
1884     /* if caller saves & we have not saved then */
1885     if (!ic->regsSaved)
1886         saveRegisters(ic);
1887
1888     /* if we are calling a function that is not using
1889     the same register bank then we need to save the
1890     destination registers on the stack */
1891     detype = getSpec(operandType(IC_LEFT(ic)));
1892     if (detype        && 
1893         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1894         IS_ISR(currFunc->etype) &&
1895         !ic->bankSaved) 
1896
1897         saverbank(SPEC_BANK(detype),ic,TRUE);
1898
1899     /* if send set is not empty the assign */
1900     if (_G.sendSet) {
1901         iCode *sic ;
1902
1903         for (sic = setFirstItem(_G.sendSet) ; sic ; 
1904              sic = setNextItem(_G.sendSet)) {
1905             int size, offset = 0;
1906         aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
1907             size = AOP_SIZE(IC_LEFT(sic));
1908             while (size--) {
1909                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1910                                 FALSE, FALSE, FALSE);
1911                 if (strcmp(l,fReturn[offset]))
1912                     emitcode("mov","%s,%s",
1913                              fReturn[offset],
1914                              l);
1915                 offset++;
1916             }
1917             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1918         }
1919         _G.sendSet = NULL;
1920     }
1921     /* make the call */
1922     emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1923                            OP_SYMBOL(IC_LEFT(ic))->rname :
1924                            OP_SYMBOL(IC_LEFT(ic))->name));
1925
1926     /* if we need assign a result value */
1927     if ((IS_ITEMP(IC_RESULT(ic)) && 
1928          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1929           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1930         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1931
1932         if (!isOperandInFarSpace(IC_RESULT(ic)))
1933         {
1934         _G.accInUse++;
1935             aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1936         _G.accInUse--;
1937
1938         assignResultValue(IC_RESULT(ic));
1939                 
1940         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1941     }
1942         else
1943         {
1944             /* Result is in far space, and requires DPTR to access
1945              * it. Push the result onto the stack and restore from
1946              * there.
1947              */
1948             int size = getSize(operandType(IC_RESULT(ic)));
1949             int offset = size - 1;
1950             char *l;
1951             
1952             emitcode(";", "Kevin function call abuse #1");
1953
1954             /* first push the right side on to the stack */
1955             /* NB: this relies on the fact that "a" is the last
1956              * register in fReturn. If it were not, the MOVA
1957              * would potentially clobber a returned byte in A.
1958              */
1959             while (size--) {
1960                 l = fReturn[offset--];
1961                 MOVA(l);
1962                 emitcode ("push","acc");
1963             }
1964     
1965             /* now assign DPTR to result */
1966             aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1967             size = AOP_SIZE(IC_RESULT(ic));
1968             aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
1969             while (size--) {
1970                 emitcode ("pop","acc");
1971                 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
1972             }
1973             freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1974         }
1975     }
1976
1977     /* adjust the stack for parameters if 
1978     required */
1979     if (IC_LEFT(ic)->parmBytes) {
1980         int i;
1981         if (IC_LEFT(ic)->parmBytes > 3) {
1982             emitcode("mov","a,%s",spname);
1983             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1984             emitcode("mov","%s,a",spname);
1985         } else 
1986             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
1987                 emitcode("dec","%s",spname);
1988
1989     }
1990
1991     /* if register bank was saved then pop them */
1992     if (ic->bankSaved)
1993         unsaverbank(SPEC_BANK(detype),ic,TRUE);
1994
1995     /* if we hade saved some registers then unsave them */
1996     if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1997         unsaveRegisters (ic);
1998
1999
2000 }
2001
2002 /*-----------------------------------------------------------------*/
2003 /* genPcall - generates a call by pointer statement                */
2004 /*-----------------------------------------------------------------*/
2005 static void genPcall (iCode *ic)
2006 {
2007     link *detype;
2008     symbol *rlbl = newiTempLabel(NULL);
2009
2010     D(emitcode(";", "genPcall "););
2011
2012
2013     /* if caller saves & we have not saved then */
2014     if (!ic->regsSaved)
2015         saveRegisters(ic);
2016
2017     /* if we are calling a function that is not using
2018     the same register bank then we need to save the
2019     destination registers on the stack */
2020     detype = getSpec(operandType(IC_LEFT(ic)));
2021     if (detype        && 
2022         IS_ISR(currFunc->etype) &&
2023         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2024         saverbank(SPEC_BANK(detype),ic,TRUE);
2025
2026
2027     /* push the return address on to the stack */
2028     emitcode("mov","a,#%05d$",(rlbl->key+100));
2029     emitcode("push","acc");    
2030     emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2031     emitcode("push","acc");
2032     
2033     if (options.model == MODEL_FLAT24)
2034     {
2035         emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2036         emitcode("push","acc");    
2037     }
2038
2039     /* now push the calling address */
2040     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2041
2042     pushSide(IC_LEFT(ic), FPTRSIZE);
2043
2044     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2045
2046     /* if send set is not empty the assign */
2047     if (_G.sendSet) {
2048         iCode *sic ;
2049
2050         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2051              sic = setNextItem(_G.sendSet)) {
2052             int size, offset = 0;
2053             aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2054             size = AOP_SIZE(IC_LEFT(sic));
2055             while (size--) {
2056                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2057                                 FALSE,FALSE,FALSE);
2058                 if (strcmp(l,fReturn[offset]))
2059                     emitcode("mov","%s,%s",
2060                              fReturn[offset],
2061                              l);
2062                 offset++;
2063             }
2064             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2065         }
2066         _G.sendSet = NULL;
2067     }
2068
2069     emitcode("ret","");
2070     emitcode("","%05d$:",(rlbl->key+100));
2071
2072
2073     /* if we need assign a result value */
2074     if ((IS_ITEMP(IC_RESULT(ic)) &&
2075          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2076           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2077         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2078
2079         _G.accInUse++;
2080         aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2081         _G.accInUse--;
2082         
2083         assignResultValue(IC_RESULT(ic));
2084
2085         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2086     }
2087
2088     /* adjust the stack for parameters if 
2089     required */
2090     if (IC_LEFT(ic)->parmBytes) {
2091         int i;
2092         if (IC_LEFT(ic)->parmBytes > 3) {
2093             emitcode("mov","a,%s",spname);
2094             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2095             emitcode("mov","%s,a",spname);
2096         } else 
2097             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
2098                 emitcode("dec","%s",spname);
2099
2100     }
2101
2102     /* if register bank was saved then unsave them */
2103     if (detype        && 
2104         (SPEC_BANK(currFunc->etype) != 
2105          SPEC_BANK(detype)))
2106         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2107
2108     /* if we hade saved some registers then
2109     unsave them */
2110     if (ic->regsSaved)
2111         unsaveRegisters (ic);
2112
2113 }
2114
2115 /*-----------------------------------------------------------------*/
2116 /* resultRemat - result  is rematerializable                       */
2117 /*-----------------------------------------------------------------*/
2118 static int resultRemat (iCode *ic)
2119 {
2120     if (SKIP_IC(ic) || ic->op == IFX)
2121         return 0;
2122
2123     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2124         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2125         if (sym->remat && !POINTER_SET(ic)) 
2126             return 1;
2127     }
2128
2129     return 0;
2130 }
2131
2132 #ifdef __BORLANDC__
2133 #define STRCASECMP stricmp
2134 #else
2135 #define STRCASECMP strcasecmp
2136 #endif
2137
2138 /*-----------------------------------------------------------------*/
2139 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2140 /*-----------------------------------------------------------------*/
2141 static bool inExcludeList(char *s)
2142 {
2143     int i =0;
2144     
2145     if (options.excludeRegs[i] &&
2146     STRCASECMP(options.excludeRegs[i],"none") == 0)
2147         return FALSE ;
2148
2149     for ( i = 0 ; options.excludeRegs[i]; i++) {
2150         if (options.excludeRegs[i] &&
2151         STRCASECMP(s,options.excludeRegs[i]) == 0)
2152             return TRUE;
2153     }
2154     return FALSE ;
2155 }
2156
2157 /*-----------------------------------------------------------------*/
2158 /* genFunction - generated code for function entry                 */
2159 /*-----------------------------------------------------------------*/
2160 static void genFunction (iCode *ic)
2161 {
2162     symbol *sym;
2163     link *fetype;
2164
2165     D(emitcode(";", "genFunction "););
2166
2167     _G.nRegsSaved = 0;
2168     /* create the function header */
2169     emitcode(";","-----------------------------------------");
2170     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2171     emitcode(";","-----------------------------------------");
2172
2173     emitcode("","%s:",sym->rname);
2174     fetype = getSpec(operandType(IC_LEFT(ic)));
2175
2176     /* if critical function then turn interrupts off */
2177     if (SPEC_CRTCL(fetype))
2178         emitcode("clr","ea");
2179
2180     /* here we need to generate the equates for the
2181        register bank if required */
2182     if (SPEC_BANK(fetype) != rbank) {
2183         int i ;
2184
2185         rbank = SPEC_BANK(fetype);
2186         for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2187             if (strcmp(regs390[i].base,"0") == 0)
2188                 emitcode("","%s = 0x%02x",
2189                          regs390[i].dname,
2190                          8*rbank+regs390[i].offset);
2191             else
2192                 emitcode ("","%s = %s + 0x%02x",
2193                           regs390[i].dname,
2194                           regs390[i].base,
2195                           8*rbank+regs390[i].offset);
2196         }
2197     }
2198
2199     /* if this is an interrupt service routine then
2200     save acc, b, dpl, dph  */
2201     if (IS_ISR(sym->etype)) {
2202         
2203         if (!inExcludeList("acc"))          
2204             emitcode ("push","acc");    
2205         if (!inExcludeList("b"))
2206             emitcode ("push","b");
2207         if (!inExcludeList("dpl"))
2208             emitcode ("push","dpl");
2209         if (!inExcludeList("dph"))
2210             emitcode ("push","dph");
2211         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2212         {
2213             emitcode ("push", "dpx");
2214             /* Make sure we're using standard DPTR */
2215             emitcode ("push", "dps");
2216             emitcode ("mov", "dps, #0x00");
2217             if (options.stack10bit)
2218             {   
2219                 /* This ISR could conceivably use DPTR2. Better save it. */
2220                 emitcode ("push", "dpl1");
2221                 emitcode ("push", "dph1");
2222                 emitcode ("push", "dpx1");
2223             emitcode ("push", "ap");
2224             }
2225         }
2226         /* if this isr has no bank i.e. is going to
2227            run with bank 0 , then we need to save more
2228            registers :-) */
2229         if (!SPEC_BANK(sym->etype)) {
2230
2231             /* if this function does not call any other
2232                function then we can be economical and
2233                save only those registers that are used */
2234             if (! sym->hasFcall) {
2235                 int i;
2236
2237                 /* if any registers used */
2238                 if (sym->regsUsed) {
2239                     /* save the registers used */
2240                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2241                         if (bitVectBitValue(sym->regsUsed,i) ||
2242                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2243                             emitcode("push","%s",ds390_regWithIdx(i)->dname);                       
2244                     }
2245                 }
2246                 
2247             } else {
2248                 /* this function has  a function call cannot
2249                    determines register usage so we will have the
2250                    entire bank */
2251                 saverbank(0,ic,FALSE);
2252             }       
2253         }
2254     } else {
2255         /* if callee-save to be used for this function
2256            then save the registers being used in this function */
2257         if (sym->calleeSave) {
2258             int i;
2259             
2260             /* if any registers used */
2261             if (sym->regsUsed) {
2262                 /* save the registers used */
2263                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2264                     if (bitVectBitValue(sym->regsUsed,i) ||
2265                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2266                         emitcode("push","%s",ds390_regWithIdx(i)->dname);
2267                         _G.nRegsSaved++;
2268                     }
2269                 }
2270             }
2271         }
2272     }
2273
2274     /* set the register bank to the desired value */
2275     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2276         emitcode("push","psw");
2277         emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);   
2278     }
2279
2280     if (IS_RENT(sym->etype) || options.stackAuto) {
2281
2282         if (options.useXstack) {
2283             emitcode("mov","r0,%s",spname);
2284             emitcode("mov","a,_bp");
2285             emitcode("movx","@r0,a");
2286             emitcode("inc","%s",spname);
2287         }
2288         else
2289         {
2290             /* set up the stack */
2291             emitcode ("push","_bp");     /* save the callers stack  */
2292         }
2293         emitcode ("mov","_bp,%s",spname);
2294     }
2295
2296     /* adjust the stack for the function */
2297     if (sym->stack) {
2298
2299         int i = sym->stack;
2300         if (i > 256 ) 
2301             werror(W_STACK_OVERFLOW,sym->name);
2302
2303         if (i > 3 && sym->recvSize < 4) {              
2304
2305             emitcode ("mov","a,sp");
2306             emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2307             emitcode ("mov","sp,a");
2308            
2309         }
2310         else
2311             while(i--)
2312                 emitcode("inc","sp");
2313     }
2314
2315      if (sym->xstack) {
2316
2317         emitcode ("mov","a,_spx");
2318         emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2319         emitcode ("mov","_spx,a");
2320     }    
2321
2322 }
2323
2324 /*-----------------------------------------------------------------*/
2325 /* genEndFunction - generates epilogue for functions               */
2326 /*-----------------------------------------------------------------*/
2327 static void genEndFunction (iCode *ic)
2328 {
2329     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2330
2331     D(emitcode(";", "genEndFunction "););
2332
2333     if (IS_RENT(sym->etype) || options.stackAuto)
2334     {
2335         emitcode ("mov","%s,_bp",spname);
2336     }
2337
2338     /* if use external stack but some variables were
2339     added to the local stack then decrement the
2340     local stack */
2341     if (options.useXstack && sym->stack) {      
2342         emitcode("mov","a,sp");
2343         emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2344         emitcode("mov","sp,a");
2345     }
2346
2347
2348     if ((IS_RENT(sym->etype) || options.stackAuto)) {
2349         if (options.useXstack) {
2350             emitcode("mov","r0,%s",spname);
2351             emitcode("movx","a,@r0");
2352             emitcode("mov","_bp,a");
2353             emitcode("dec","%s",spname);
2354         }
2355         else
2356         {
2357             emitcode ("pop","_bp");
2358         }
2359     }
2360
2361     /* restore the register bank  */    
2362     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2363         emitcode ("pop","psw");
2364
2365     if (IS_ISR(sym->etype)) {
2366
2367         /* now we need to restore the registers */
2368         /* if this isr has no bank i.e. is going to
2369            run with bank 0 , then we need to save more
2370            registers :-) */
2371         if (!SPEC_BANK(sym->etype)) {
2372             
2373             /* if this function does not call any other
2374                function then we can be economical and
2375                save only those registers that are used */
2376             if (! sym->hasFcall) {
2377                 int i;
2378                 
2379                 /* if any registers used */
2380                 if (sym->regsUsed) {
2381                     /* save the registers used */
2382                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2383                         if (bitVectBitValue(sym->regsUsed,i) ||
2384                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2385                             emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2386                     }
2387                 }
2388                 
2389             } else {
2390                 /* this function has  a function call cannot
2391                    determines register usage so we will have the
2392                    entire bank */
2393                 unsaverbank(0,ic,FALSE);
2394             }       
2395         }
2396
2397         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2398         {
2399             if (options.stack10bit)
2400             {
2401             emitcode ("pop", "ap");
2402                 emitcode ("pop", "dpx1");
2403                 emitcode ("pop", "dph1");
2404                 emitcode ("pop", "dpl1");
2405             }   
2406             emitcode ("pop", "dps");
2407             emitcode ("pop", "dpx");
2408         }
2409         if (!inExcludeList("dph"))
2410             emitcode ("pop","dph");
2411         if (!inExcludeList("dpl"))
2412             emitcode ("pop","dpl");
2413         if (!inExcludeList("b"))
2414             emitcode ("pop","b");
2415         if (!inExcludeList("acc"))
2416             emitcode ("pop","acc");
2417
2418         if (SPEC_CRTCL(sym->etype))
2419             emitcode("setb","ea");
2420
2421         /* if debug then send end of function */
2422 /*      if (options.debug && currFunc) { */
2423         if (currFunc) {
2424             _G.debugLine = 1;
2425             emitcode("","C$%s$%d$%d$%d ==.",
2426                      ic->filename,currFunc->lastLine,
2427                      ic->level,ic->block); 
2428             if (IS_STATIC(currFunc->etype))         
2429                 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2430             else
2431                 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2432             _G.debugLine = 0;
2433         }
2434         
2435         emitcode ("reti","");
2436     }
2437     else {
2438         if (SPEC_CRTCL(sym->etype))
2439             emitcode("setb","ea");
2440         
2441         if (sym->calleeSave) {
2442             int i;
2443             
2444             /* if any registers used */
2445             if (sym->regsUsed) {
2446                 /* save the registers used */
2447                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2448                     if (bitVectBitValue(sym->regsUsed,i) ||
2449                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2450                         emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2451                 }
2452             }
2453             
2454         }
2455
2456         /* if debug then send end of function */
2457         if (currFunc) {
2458             _G.debugLine = 1;
2459             emitcode("","C$%s$%d$%d$%d ==.",
2460                      ic->filename,currFunc->lastLine,
2461                      ic->level,ic->block); 
2462             if (IS_STATIC(currFunc->etype))         
2463                 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2464             else
2465                 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2466             _G.debugLine = 0;
2467         }
2468
2469         emitcode ("ret","");
2470     }
2471
2472 }
2473
2474 /*-----------------------------------------------------------------*/
2475 /* genRet - generate code for return statement                     */
2476 /*-----------------------------------------------------------------*/
2477 static void genRet (iCode *ic)
2478 {
2479     int size,offset = 0 , pushed = 0;
2480     
2481     D(emitcode(";", "genRet "););
2482
2483     /* if we have no return value then
2484        just generate the "ret" */
2485     if (!IC_LEFT(ic)) 
2486         goto jumpret;       
2487     
2488     /* we have something to return then
2489        move the return value into place */
2490     aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2491     size = AOP_SIZE(IC_LEFT(ic));
2492     
2493     while (size--) {
2494             char *l ;
2495             if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2496                     l = aopGet(AOP(IC_LEFT(ic)),offset++,
2497                            FALSE,TRUE,FALSE);
2498                     emitcode("push","%s",l);
2499                     pushed++;
2500             } else {
2501                     l = aopGet(AOP(IC_LEFT(ic)),offset,
2502                                FALSE,FALSE,FALSE);
2503                     if (strcmp(fReturn[offset],l))
2504                             emitcode("mov","%s,%s",fReturn[offset++],l);
2505             }
2506     }    
2507
2508     if (pushed) {
2509         while(pushed) {
2510             pushed--;
2511             if (strcmp(fReturn[pushed],"a"))
2512                 emitcode("pop",fReturn[pushed]);
2513             else
2514                 emitcode("pop","acc");
2515         }
2516     }
2517     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2518     
2519  jumpret:
2520         /* generate a jump to the return label
2521            if the next is not the return statement */
2522     if (!(ic->next && ic->next->op == LABEL &&
2523           IC_LABEL(ic->next) == returnLabel))
2524         
2525         emitcode("ljmp","%05d$",(returnLabel->key+100));
2526     
2527 }
2528
2529 /*-----------------------------------------------------------------*/
2530 /* genLabel - generates a label                                    */
2531 /*-----------------------------------------------------------------*/
2532 static void genLabel (iCode *ic)
2533 {
2534     /* special case never generate */
2535     if (IC_LABEL(ic) == entryLabel)
2536         return ;
2537
2538     D(emitcode(";", "genLabel "););
2539
2540     emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2541 }
2542
2543 /*-----------------------------------------------------------------*/
2544 /* genGoto - generates a ljmp                                      */
2545 /*-----------------------------------------------------------------*/
2546 static void genGoto (iCode *ic)
2547 {
2548     D(emitcode(";", "genGoto "););
2549     emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2550 }
2551
2552 /*-----------------------------------------------------------------*/
2553 /* findLabelBackwards: walks back through the iCode chain looking  */
2554 /* for the given label. Returns number of iCode instructions       */
2555 /* between that label and given ic.                                */
2556 /* Returns zero if label not found.                                */
2557 /*-----------------------------------------------------------------*/
2558 static int findLabelBackwards(iCode *ic, int key)
2559 {
2560     int count = 0;
2561     
2562     while (ic->prev)
2563     {
2564         ic = ic->prev;
2565         count++;
2566         
2567         if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2568         {
2569             /* printf("findLabelBackwards = %d\n", count); */
2570             return count;
2571         }
2572     }
2573     
2574     return 0;
2575 }
2576
2577 /*-----------------------------------------------------------------*/
2578 /* genPlusIncr :- does addition with increment if possible         */
2579 /*-----------------------------------------------------------------*/
2580 static bool genPlusIncr (iCode *ic)
2581 {
2582     unsigned int icount ;
2583     unsigned int size = getDataSize(IC_RESULT(ic));
2584     
2585     /* will try to generate an increment */
2586     /* if the right side is not a literal 
2587        we cannot */
2588     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2589         return FALSE ;
2590     
2591     /* if the literal value of the right hand side
2592        is greater than 4 then it is not worth it */
2593     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2594         return FALSE ;
2595     
2596     /* if increment 16 bits in register */
2597     if (
2598         AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2599         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2600         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2601         (size > 1) &&
2602         (icount == 1)) {
2603         symbol *tlbl;
2604         int emitTlbl;
2605         int labelRange;
2606
2607         /* If the next instruction is a goto and the goto target
2608          * is <= 5 instructions previous to this, we can generate
2609          * jumps straight to that target.
2610          */
2611         if (ic->next && ic->next->op == GOTO
2612             && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2613             && labelRange <= 5 )
2614         {
2615            emitcode(";", "tail increment optimized (range %d)", labelRange);
2616            tlbl = IC_LABEL(ic->next);
2617            emitTlbl = 0;
2618         }
2619         else
2620         {
2621             tlbl = newiTempLabel(NULL);
2622             emitTlbl = 1;
2623         }
2624         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2625         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2626            IS_AOP_PREG(IC_RESULT(ic)))
2627             emitcode("cjne","%s,#0x00,%05d$"
2628                      ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2629                      ,tlbl->key+100);
2630         else {
2631             emitcode("clr","a");
2632             emitcode("cjne","a,%s,%05d$"
2633                      ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2634                      ,tlbl->key+100);
2635         }
2636     
2637         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2638         if (size > 2)
2639         {
2640             if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2641                IS_AOP_PREG(IC_RESULT(ic)))
2642                 emitcode("cjne","%s,#0x00,%05d$"
2643                          ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2644                          ,tlbl->key+100);
2645             else
2646                 emitcode("cjne","a,%s,%05d$"
2647                          ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2648                          ,tlbl->key+100);
2649             
2650             emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2651        }
2652        if (size > 3)
2653        {
2654             if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2655                IS_AOP_PREG(IC_RESULT(ic)))
2656                 emitcode("cjne","%s,#0x00,%05d$"
2657                          ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2658                          ,tlbl->key+100);
2659             else{
2660                 emitcode("cjne","a,%s,%05d$"
2661                          ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2662                          ,tlbl->key+100);
2663             }
2664             emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2665         }
2666         
2667         if (emitTlbl)
2668         {
2669             emitcode("","%05d$:",tlbl->key+100);
2670         }
2671         return TRUE;
2672     }
2673     
2674     /* if the sizes are greater than 1 then we cannot */
2675     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2676         AOP_SIZE(IC_LEFT(ic)) > 1   )
2677         return FALSE ;
2678     
2679     /* we can if the aops of the left & result match or
2680        if they are in registers and the registers are the
2681        same */
2682     if (
2683         AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2684         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2685         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2686         
2687         if (icount > 3) {
2688             MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2689             emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2690             aopPut(AOP(IC_RESULT(ic)),"a",0);
2691         } else {
2692             
2693             while (icount--) 
2694                 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2695         }
2696         
2697         return TRUE ;
2698     }
2699     
2700     return FALSE ;
2701 }
2702
2703 /*-----------------------------------------------------------------*/
2704 /* outBitAcc - output a bit in acc                                 */
2705 /*-----------------------------------------------------------------*/
2706 static void outBitAcc(operand *result)
2707 {
2708     symbol *tlbl = newiTempLabel(NULL);
2709     /* if the result is a bit */
2710     if (AOP_TYPE(result) == AOP_CRY){
2711         aopPut(AOP(result),"a",0);
2712     }
2713     else {
2714         emitcode("jz","%05d$",tlbl->key+100);
2715         emitcode("mov","a,%s",one);
2716         emitcode("","%05d$:",tlbl->key+100);
2717         outAcc(result);
2718     }
2719 }
2720
2721 /*-----------------------------------------------------------------*/
2722 /* genPlusBits - generates code for addition of two bits           */
2723 /*-----------------------------------------------------------------*/
2724 static void genPlusBits (iCode *ic)
2725 {
2726     D(emitcode(";", "genPlusBits "););
2727     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2728         symbol *lbl = newiTempLabel(NULL);
2729         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2730         emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2731         emitcode("cpl","c");
2732         emitcode("","%05d$:",(lbl->key+100));
2733         outBitC(IC_RESULT(ic));
2734     }
2735     else{
2736         emitcode("clr","a");
2737         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2738         emitcode("rlc","a");
2739         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2740         emitcode("addc","a,#0x00");
2741         outAcc(IC_RESULT(ic));
2742     }
2743 }
2744
2745 static void adjustArithmeticResult(iCode *ic)
2746 {
2747     if (opIsGptr(IC_RESULT(ic)) &&
2748         opIsGptr(IC_LEFT(ic))   &&
2749         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2750     {
2751         aopPut(AOP(IC_RESULT(ic)),
2752                aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2753                GPTRSIZE - 1);
2754     }
2755
2756     if (opIsGptr(IC_RESULT(ic)) &&
2757         opIsGptr(IC_RIGHT(ic))   &&
2758         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2759     {
2760         aopPut(AOP(IC_RESULT(ic)),
2761                aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2762                GPTRSIZE - 1);
2763     }
2764
2765     if (opIsGptr(IC_RESULT(ic))            &&
2766         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
2767         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
2768          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2769          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2770          char buffer[5];
2771          sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2772          aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2773      }
2774 }
2775
2776 #define AOP_OP_3(ic) \
2777     aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2778     aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2779     aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2780     if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2781         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2782     { \
2783         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2784         fprintf(stderr,                                  \
2785                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
2786     }
2787
2788 #define AOP_SET_LOCALS(ic) \
2789     left = IC_LEFT(ic); \
2790     right = IC_RIGHT(ic); \
2791     result = IC_RESULT(ic);
2792
2793 /*-----------------------------------------------------------------*/
2794 /* genPlus - generates code for addition                           */
2795 /*-----------------------------------------------------------------*/
2796 static void genPlus (iCode *ic)
2797 {
2798     int size, offset = 0;
2799     bool pushResult = FALSE;
2800     int  rSize;
2801
2802     D(emitcode(";", "genPlus "););
2803
2804     /* special cases :- */
2805
2806     aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2807     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2808     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2809         (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2810     {
2811         pushResult = TRUE;
2812     }
2813     else
2814     {
2815         aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR);
2816
2817     /* if literal, literal on the right or
2818        if left requires ACC or right is already
2819        in ACC */
2820     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2821         (AOP_NEEDSACC(IC_LEFT(ic))) ||
2822         AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2823         operand *t = IC_RIGHT(ic);
2824         IC_RIGHT(ic) = IC_LEFT(ic);
2825         IC_LEFT(ic) = t;
2826     }
2827
2828     /* if both left & right are in bit
2829     space */
2830     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2831         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2832         genPlusBits (ic);
2833         goto release ;
2834     }
2835
2836     /* if left in bit space & right literal */
2837     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2838         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2839         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2840         /* if result in bit space */
2841         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2842             if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2843                 emitcode("cpl","c");
2844             outBitC(IC_RESULT(ic));
2845         } else {
2846             size = getDataSize(IC_RESULT(ic));
2847             while (size--) {
2848                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
2849                 emitcode("addc","a,#00");
2850                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2851             }
2852         }
2853         goto release ;
2854     }
2855
2856     /* if I can do an increment instead
2857     of add then GOOD for ME */
2858     if (genPlusIncr (ic) == TRUE)
2859         goto release;   
2860
2861     }
2862     size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
2863
2864     while(size--){
2865         if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2866             MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
2867             if(offset == 0)
2868                 emitcode("add","a,%s",
2869                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
2870             else
2871                 emitcode("addc","a,%s",
2872                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
2873         } else {
2874             MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
2875             if(offset == 0)
2876                 emitcode("add","a,%s",
2877                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
2878             else
2879                 emitcode("addc","a,%s",
2880                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
2881         }
2882         if (!pushResult)
2883         {
2884             aopPut(AOP(IC_RESULT(ic)),"a",offset);
2885         }
2886         else
2887         {
2888             emitcode("push", "acc");
2889         }
2890         offset++;
2891     }
2892
2893     if (pushResult)
2894     {
2895         aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2896
2897         size = getDataSize(IC_LEFT(ic));
2898         rSize = getDataSize(IC_RESULT(ic));
2899         
2900         /* If the pushed data is bigger than the result,
2901          * simply discard unused bytes. Icky, but works.
2902          *
2903          * Should we throw a warning here? We're losing data...
2904          */
2905         while (size > rSize)
2906         {
2907            D(emitcode(";", "discarding unused result byte."););
2908            emitcode("pop", "acc");
2909            size--;
2910            offset--; 
2911         }
2912         if (size < rSize)
2913         {
2914             emitcode("clr", "a");
2915             /* Conversly, we haven't pushed enough here.
2916              * just zero-pad, and all is well. 
2917              */
2918             while (size < rSize)
2919             {
2920                 emitcode("push", "acc");
2921                 size++;
2922                 offset++;
2923             }
2924         }
2925
2926         while(size--)
2927         {
2928             emitcode("pop", "acc");
2929             aopPut(AOP(IC_RESULT(ic)), "a", --offset);
2930         }
2931     }
2932
2933     adjustArithmeticResult(ic);
2934
2935 release:
2936     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2937     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2938     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2939 }
2940
2941 /*-----------------------------------------------------------------*/
2942 /* genMinusDec :- does subtraction with deccrement if possible     */
2943 /*-----------------------------------------------------------------*/
2944 static bool genMinusDec (iCode *ic)
2945 {
2946     unsigned int icount ;
2947     unsigned int size = getDataSize(IC_RESULT(ic));
2948
2949     /* will try to generate an increment */
2950     /* if the right side is not a literal 
2951     we cannot */
2952     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2953         return FALSE ;
2954
2955     /* if the literal value of the right hand side
2956     is greater than 4 then it is not worth it */
2957     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2958         return FALSE ;
2959
2960     /* if decrement 16 bits in register */
2961     if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2962         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2963         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2964         (size > 1) &&
2965         (icount == 1)) {
2966             symbol *tlbl;
2967             int emitTlbl;
2968             int labelRange;
2969
2970             /* If the next instruction is a goto and the goto target
2971          * is <= 5 instructions previous to this, we can generate
2972              * jumps straight to that target.
2973              */
2974             if (ic->next && ic->next->op == GOTO
2975                 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2976                 && labelRange <= 5 )
2977             {        
2978                emitcode(";", "tail decrement optimized (range %d)", labelRange);
2979                tlbl = IC_LABEL(ic->next);
2980                emitTlbl = 0;
2981             }
2982             else
2983             {
2984                 tlbl = newiTempLabel(NULL);
2985                 emitTlbl = 1;
2986             }
2987         
2988                 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2989                 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2990                    AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2991                    IS_AOP_PREG(IC_RESULT(ic)))
2992                         emitcode("cjne","%s,#0xff,%05d$"
2993                                          ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2994                                          ,tlbl->key+100);
2995                 else{
2996                         emitcode("mov","a,#0xff");
2997                         emitcode("cjne","a,%s,%05d$"
2998                                          ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2999                                          ,tlbl->key+100);
3000                 }
3001                 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3002                 if (size > 2)
3003                 {
3004                         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3005                            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3006                            IS_AOP_PREG(IC_RESULT(ic)))
3007                                 emitcode("cjne","%s,#0xff,%05d$"
3008                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3009                                                  ,tlbl->key+100);
3010                         else{
3011                                 emitcode("cjne","a,%s,%05d$"
3012                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3013                                                  ,tlbl->key+100);
3014                         }
3015                         emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3016                 }
3017                 if (size > 3)
3018                 {
3019                         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3020                            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3021                            IS_AOP_PREG(IC_RESULT(ic)))
3022                                 emitcode("cjne","%s,#0xff,%05d$"
3023                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3024                                                  ,tlbl->key+100);
3025                         else{
3026                                 emitcode("cjne","a,%s,%05d$"
3027                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3028                                                  ,tlbl->key+100);
3029                         }
3030                         emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3031                 }
3032                 if (emitTlbl)
3033                 {
3034                     emitcode("","%05d$:",tlbl->key+100);
3035                 }
3036         return TRUE;
3037     }
3038
3039     /* if the sizes are greater than 1 then we cannot */
3040     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3041         AOP_SIZE(IC_LEFT(ic)) > 1   )
3042         return FALSE ;
3043
3044     /* we can if the aops of the left & result match or
3045     if they are in registers and the registers are the
3046     same */
3047     if (
3048         AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3049         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3050         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3051
3052         while (icount--) 
3053             emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3054
3055         return TRUE ;
3056     }
3057
3058     return FALSE ;
3059 }
3060
3061 /*-----------------------------------------------------------------*/
3062 /* addSign - complete with sign                                    */
3063 /*-----------------------------------------------------------------*/
3064 static void addSign(operand *result, int offset, int sign)
3065 {
3066     int size = (getDataSize(result) - offset);
3067     if(size > 0){
3068         if(sign){
3069             emitcode("rlc","a");
3070             emitcode("subb","a,acc");
3071             while(size--)
3072                 aopPut(AOP(result),"a",offset++); 
3073         } else
3074             while(size--)
3075                 aopPut(AOP(result),zero,offset++);
3076     }
3077 }
3078
3079 /*-----------------------------------------------------------------*/
3080 /* genMinusBits - generates code for subtraction  of two bits      */
3081 /*-----------------------------------------------------------------*/
3082 static void genMinusBits (iCode *ic)
3083 {
3084     symbol *lbl = newiTempLabel(NULL);
3085     
3086     D(emitcode(";", "genMinusBits "););    
3087
3088     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3089         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3090         emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3091         emitcode("cpl","c");
3092         emitcode("","%05d$:",(lbl->key+100));
3093         outBitC(IC_RESULT(ic));
3094     }
3095     else{
3096         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3097         emitcode("subb","a,acc");
3098         emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3099         emitcode("inc","a");
3100         emitcode("","%05d$:",(lbl->key+100));
3101         aopPut(AOP(IC_RESULT(ic)),"a",0);
3102         addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3103     }
3104 }
3105
3106 /*-----------------------------------------------------------------*/
3107 /* genMinus - generates code for subtraction                       */
3108 /*-----------------------------------------------------------------*/
3109 static void genMinus (iCode *ic)
3110 {
3111     int size, offset = 0;
3112     int rSize;
3113     unsigned long lit = 0L;
3114     bool pushResult = FALSE;
3115
3116     D(emitcode(";", "genMinus "););
3117
3118     aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3119     aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3120     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3121         (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3122     {
3123         pushResult = TRUE;
3124     }
3125     else
3126     {
3127         aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3128
3129     /* special cases :- */
3130     /* if both left & right are in bit space */
3131     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3132         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3133         genMinusBits (ic);
3134         goto release ;
3135     }
3136
3137     /* if I can do an decrement instead
3138     of subtract then GOOD for ME */
3139     if (genMinusDec (ic) == TRUE)
3140         goto release;
3141
3142     }
3143
3144     size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3145
3146     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3147         CLRC;
3148     }
3149     else{
3150         lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3151         lit = - (long)lit;
3152     }
3153
3154
3155     /* if literal, add a,#-lit, else normal subb */
3156     while (size--) {
3157         MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3158         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
3159             emitcode("subb","a,%s",
3160                      aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3161         else{
3162             /* first add without previous c */
3163             if(!offset)
3164                 emitcode("add","a,#0x%02x",
3165                          (unsigned int)(lit & 0x0FFL));
3166             else
3167                 emitcode("addc","a,#0x%02x",
3168                          (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3169         }
3170
3171         if (pushResult)
3172         {
3173             emitcode("push", "acc");
3174         }
3175         else
3176         {
3177             aopPut(AOP(IC_RESULT(ic)),"a",offset);
3178         }
3179         offset++;
3180     }
3181
3182     if (pushResult)
3183     {
3184         aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3185
3186         size = getDataSize(IC_LEFT(ic));
3187         rSize = getDataSize(IC_RESULT(ic));
3188
3189         /* If the pushed data is bigger than the result,
3190          * simply discard unused bytes. Icky, but works.
3191          *
3192          * Should we throw a warning here? We're losing data...
3193          */
3194         while (size > getDataSize(IC_RESULT(ic)))
3195         {
3196            emitcode(";", "discarding unused result byte.");
3197            emitcode("pop", "acc");
3198            size--;
3199            offset--; 
3200         }
3201         if (size < rSize)
3202         {
3203             emitcode("clr", "a");
3204             /* Conversly, we haven't pushed enough here.
3205              * just zero-pad, and all is well. 
3206              */
3207             while (size < rSize)
3208             {
3209                 emitcode("push", "acc");
3210                 size++;
3211                 offset++;
3212             }
3213         }
3214
3215         while(size--)
3216         {
3217             emitcode("pop", "acc");
3218             aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3219         }
3220     }
3221
3222     adjustArithmeticResult(ic);
3223         
3224 release:
3225     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3226     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3227     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3228 }
3229
3230
3231 /*-----------------------------------------------------------------*/
3232 /* genMultbits :- multiplication of bits                           */
3233 /*-----------------------------------------------------------------*/
3234 static void genMultbits (operand *left, 
3235                          operand *right, 
3236                          operand *result)
3237 {
3238     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3239     emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3240     outBitC(result);
3241 }
3242
3243
3244 /*-----------------------------------------------------------------*/
3245 /* genMultOneByte : 8 bit multiplication & division                */
3246 /*-----------------------------------------------------------------*/
3247 static void genMultOneByte (operand *left,
3248                             operand *right,
3249                             operand *result)
3250 {
3251     link *opetype = operandType(result);
3252     char *l ;
3253     symbol *lbl ;
3254     int size,offset;
3255
3256     /* (if two literals, the value is computed before) */
3257     /* if one literal, literal on the right */
3258     if (AOP_TYPE(left) == AOP_LIT){
3259         operand *t = right;
3260         right = left;
3261         left = t;
3262     }
3263
3264     size = AOP_SIZE(result);
3265     /* signed or unsigned */
3266     emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3267     l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3268     MOVA(l);       
3269     emitcode("mul","ab");
3270     /* if result size = 1, mul signed = mul unsigned */
3271     aopPut(AOP(result),"a",0);
3272     if (size > 1){
3273         if (SPEC_USIGN(opetype)){
3274             aopPut(AOP(result),"b",1);
3275             if (size > 2)
3276                 /* for filling the MSBs */
3277                 emitcode("clr","a");
3278         }
3279         else{
3280             emitcode("mov","a,b");
3281
3282             /* adjust the MSB if left or right neg */
3283
3284             /* if one literal */
3285             if (AOP_TYPE(right) == AOP_LIT){
3286                 /* AND literal negative */
3287                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3288                     /* adjust MSB (c==0 after mul) */
3289                     emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3290                 }
3291             }
3292             else{
3293                 lbl = newiTempLabel(NULL);
3294                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3295                 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3296                 emitcode("","%05d$:",(lbl->key+100));
3297                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3298                 lbl = newiTempLabel(NULL);      
3299                 emitcode("jc","%05d$",(lbl->key+100));          
3300                 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3301                 emitcode("","%05d$:",(lbl->key+100));
3302             }
3303
3304             lbl = newiTempLabel(NULL);
3305             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3306             emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3307             emitcode("","%05d$:",(lbl->key+100));
3308             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3309             lbl = newiTempLabel(NULL);      
3310             emitcode("jc","%05d$",(lbl->key+100));          
3311             emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3312             emitcode("","%05d$:",(lbl->key+100));
3313
3314             aopPut(AOP(result),"a",1);
3315             if(size > 2){
3316                 /* get the sign */
3317                 emitcode("rlc","a");
3318                 emitcode("subb","a,acc");
3319             }
3320         }
3321         size -= 2;   
3322         offset = 2;
3323         if (size > 0)
3324             while (size--)
3325                 aopPut(AOP(result),"a",offset++);
3326     }
3327 }
3328
3329 /*-----------------------------------------------------------------*/
3330 /* genMult - generates code for multiplication                     */
3331 /*-----------------------------------------------------------------*/
3332 static void genMult (iCode *ic)
3333 {
3334     operand *left = IC_LEFT(ic);
3335     operand *right = IC_RIGHT(ic);
3336     operand *result= IC_RESULT(ic);   
3337
3338     D(emitcode(";", "genMult "););
3339
3340     /* assign the amsops */
3341     AOP_OP_3(ic);
3342 #if 0
3343     aopOp (left,ic,FALSE, FALSE);
3344     aopOp (right,ic,FALSE, TRUE);
3345     aopOp (result,ic,TRUE, FALSE);
3346 #endif
3347
3348     /* special cases first */
3349     /* both are bits */
3350     if (AOP_TYPE(left) == AOP_CRY &&
3351         AOP_TYPE(right)== AOP_CRY) {
3352         genMultbits(left,right,result);
3353         goto release ;
3354     }
3355
3356     /* if both are of size == 1 */
3357     if (AOP_SIZE(left) == 1 &&
3358         AOP_SIZE(right) == 1 ) {
3359         genMultOneByte(left,right,result);
3360         goto release ;
3361     }
3362
3363     /* should have been converted to function call */       
3364     assert(1) ;
3365
3366 release :
3367     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3368     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3369     freeAsmop(result,NULL,ic,TRUE); 
3370 }
3371
3372 /*-----------------------------------------------------------------*/
3373 /* genDivbits :- division of bits                                  */
3374 /*-----------------------------------------------------------------*/
3375 static void genDivbits (operand *left, 
3376                         operand *right, 
3377                         operand *result)
3378 {
3379
3380     char *l;
3381
3382     /* the result must be bit */
3383     LOAD_AB_FOR_DIV(left, right, l);
3384     emitcode("div","ab");
3385     emitcode("rrc","a");
3386     aopPut(AOP(result),"c",0);
3387 }
3388
3389 /*-----------------------------------------------------------------*/
3390 /* genDivOneByte : 8 bit division                                  */
3391 /*-----------------------------------------------------------------*/
3392 static void genDivOneByte (operand *left,
3393                            operand *right,
3394                            operand *result)
3395 {
3396     link *opetype = operandType(result);
3397     char *l ;
3398     symbol *lbl ;
3399     int size,offset;
3400
3401     size = AOP_SIZE(result) - 1;
3402     offset = 1;
3403     /* signed or unsigned */
3404     if (SPEC_USIGN(opetype)) {
3405         /* unsigned is easy */
3406         LOAD_AB_FOR_DIV(left, right, l);
3407         emitcode("div","ab");
3408         aopPut(AOP(result),"a",0);
3409         while (size--)
3410             aopPut(AOP(result),zero,offset++);
3411         return ;
3412     }
3413
3414     /* signed is a little bit more difficult */
3415
3416     /* save the signs of the operands */
3417     l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);    
3418     MOVA(l);    
3419     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3420     emitcode("push","acc"); /* save it on the stack */
3421
3422     /* now sign adjust for both left & right */
3423     l =  aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3424     MOVA(l);       
3425     lbl = newiTempLabel(NULL);
3426     emitcode("jnb","acc.7,%05d$",(lbl->key+100));   
3427     emitcode("cpl","a");   
3428     emitcode("inc","a");
3429     emitcode("","%05d$:",(lbl->key+100));
3430     emitcode("mov","b,a");
3431
3432     /* sign adjust left side */
3433     l =  aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3434     MOVA(l);
3435
3436     lbl = newiTempLabel(NULL);
3437     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3438     emitcode("cpl","a");
3439     emitcode("inc","a");
3440     emitcode("","%05d$:",(lbl->key+100));
3441
3442     /* now the division */
3443     emitcode("nop", "; workaround for DS80C390 div bug.");
3444     emitcode("div","ab");
3445     /* we are interested in the lower order
3446     only */
3447     emitcode("mov","b,a");
3448     lbl = newiTempLabel(NULL);
3449     emitcode("pop","acc");   
3450     /* if there was an over flow we don't 
3451     adjust the sign of the result */
3452     emitcode("jb","ov,%05d$",(lbl->key+100));
3453     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3454     CLRC;
3455     emitcode("clr","a");
3456     emitcode("subb","a,b");
3457     emitcode("mov","b,a");
3458     emitcode("","%05d$:",(lbl->key+100));
3459
3460     /* now we are done */
3461     aopPut(AOP(result),"b",0);
3462     if(size > 0){
3463         emitcode("mov","c,b.7");
3464         emitcode("subb","a,acc");   
3465     }
3466     while (size--)
3467         aopPut(AOP(result),"a",offset++);
3468
3469 }
3470
3471 /*-----------------------------------------------------------------*/
3472 /* genDiv - generates code for division                            */
3473 /*-----------------------------------------------------------------*/
3474 static void genDiv (iCode *ic)
3475 {
3476     operand *left = IC_LEFT(ic);
3477     operand *right = IC_RIGHT(ic);
3478     operand *result= IC_RESULT(ic);   
3479
3480     D(emitcode(";", "genDiv "););
3481
3482     /* assign the amsops */
3483     AOP_OP_3(ic);
3484 #if 0
3485     aopOp (left,ic,FALSE, FALSE);
3486     aopOp (right,ic,FALSE, TRUE);
3487     aopOp (result,ic,TRUE, FALSE);
3488 #endif
3489
3490     /* special cases first */
3491     /* both are bits */
3492     if (AOP_TYPE(left) == AOP_CRY &&
3493         AOP_TYPE(right)== AOP_CRY) {
3494         genDivbits(left,right,result);
3495         goto release ;
3496     }
3497
3498     /* if both are of size == 1 */
3499     if (AOP_SIZE(left) == 1 &&
3500         AOP_SIZE(right) == 1 ) {
3501         genDivOneByte(left,right,result);
3502         goto release ;
3503     }
3504
3505     /* should have been converted to function call */
3506     assert(1);
3507 release :
3508     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3509     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3510     freeAsmop(result,NULL,ic,TRUE); 
3511 }
3512
3513 /*-----------------------------------------------------------------*/
3514 /* genModbits :- modulus of bits                                   */
3515 /*-----------------------------------------------------------------*/
3516 static void genModbits (operand *left, 
3517                         operand *right, 
3518                         operand *result)
3519 {
3520
3521     char *l;
3522
3523     /* the result must be bit */    
3524     LOAD_AB_FOR_DIV(left, right, l);
3525     emitcode("div","ab");
3526     emitcode("mov","a,b");
3527     emitcode("rrc","a");
3528     aopPut(AOP(result),"c",0);
3529 }
3530
3531 /*-----------------------------------------------------------------*/
3532 /* genModOneByte : 8 bit modulus                                   */
3533 /*-----------------------------------------------------------------*/
3534 static void genModOneByte (operand *left,
3535                            operand *right,
3536                            operand *result)
3537 {
3538     link *opetype = operandType(result);
3539     char *l ;
3540     symbol *lbl ;
3541
3542     /* signed or unsigned */
3543     if (SPEC_USIGN(opetype)) {
3544         /* unsigned is easy */
3545         LOAD_AB_FOR_DIV(left, right, l);
3546         emitcode("div","ab");
3547         aopPut(AOP(result),"b",0);
3548         return ;
3549     }
3550
3551     /* signed is a little bit more difficult */
3552
3553     /* save the signs of the operands */
3554     l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3555     MOVA(l);
3556
3557     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3558     emitcode("push","acc"); /* save it on the stack */
3559
3560     /* now sign adjust for both left & right */
3561     l =  aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3562     MOVA(l);
3563
3564     lbl = newiTempLabel(NULL);
3565     emitcode("jnb","acc.7,%05d$",(lbl->key+100));  
3566     emitcode("cpl","a");   
3567     emitcode("inc","a");
3568     emitcode("","%05d$:",(lbl->key+100));
3569     emitcode("mov","b,a"); 
3570
3571     /* sign adjust left side */
3572     l =  aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3573     MOVA(l);
3574
3575     lbl = newiTempLabel(NULL);
3576     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3577     emitcode("cpl","a");   
3578     emitcode("inc","a");
3579     emitcode("","%05d$:",(lbl->key+100));
3580
3581     /* now the multiplication */
3582     emitcode("nop", "; workaround for DS80C390 div bug.");
3583     emitcode("div","ab");
3584     /* we are interested in the lower order
3585     only */
3586     lbl = newiTempLabel(NULL);
3587     emitcode("pop","acc");   
3588     /* if there was an over flow we don't 
3589     adjust the sign of the result */
3590     emitcode("jb","ov,%05d$",(lbl->key+100));
3591     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3592     CLRC ;
3593     emitcode("clr","a");
3594     emitcode("subb","a,b");
3595     emitcode("mov","b,a");
3596     emitcode("","%05d$:",(lbl->key+100));
3597
3598     /* now we are done */
3599     aopPut(AOP(result),"b",0);
3600
3601 }
3602
3603 /*-----------------------------------------------------------------*/
3604 /* genMod - generates code for division                            */
3605 /*-----------------------------------------------------------------*/
3606 static void genMod (iCode *ic)
3607 {
3608     operand *left = IC_LEFT(ic);
3609     operand *right = IC_RIGHT(ic);
3610     operand *result= IC_RESULT(ic);  
3611
3612     D(emitcode(";", "genMod "););
3613
3614     /* assign the amsops */
3615     AOP_OP_3(ic);
3616 #if 0
3617     aopOp (left,ic,FALSE, FALSE);
3618     aopOp (right,ic,FALSE, TRUE);
3619     aopOp (result,ic,TRUE, FALSE);
3620 #endif
3621
3622     /* special cases first */
3623     /* both are bits */
3624     if (AOP_TYPE(left) == AOP_CRY &&
3625         AOP_TYPE(right)== AOP_CRY) {
3626         genModbits(left,right,result);
3627         goto release ;
3628     }
3629
3630     /* if both are of size == 1 */
3631     if (AOP_SIZE(left) == 1 &&
3632         AOP_SIZE(right) == 1 ) {
3633         genModOneByte(left,right,result);
3634         goto release ;
3635     }
3636
3637     /* should have been converted to function call */
3638     assert(1);
3639
3640 release :
3641     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3642     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3643     freeAsmop(result,NULL,ic,TRUE); 
3644 }
3645
3646 /*-----------------------------------------------------------------*/
3647 /* genIfxJump :- will create a jump depending on the ifx           */
3648 /*-----------------------------------------------------------------*/
3649 static void genIfxJump (iCode *ic, char *jval)
3650 {
3651     symbol *jlbl ;
3652     symbol *tlbl = newiTempLabel(NULL);
3653     char *inst;
3654
3655     D(emitcode(";", "genIfxJump "););
3656
3657     /* if true label then we jump if condition
3658     supplied is true */
3659     if ( IC_TRUE(ic) ) {
3660         jlbl = IC_TRUE(ic);
3661         inst = ((strcmp(jval,"a") == 0 ? "jz" :
3662                  (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3663     }
3664     else {
3665         /* false label is present */
3666         jlbl = IC_FALSE(ic) ;
3667         inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3668                  (strcmp(jval,"c") == 0 ? "jc" : "jb" )));              
3669     }
3670     if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0) 
3671         emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3672     else
3673         emitcode(inst,"%05d$",tlbl->key+100);
3674     emitcode("ljmp","%05d$",jlbl->key+100);
3675     emitcode("","%05d$:",tlbl->key+100);                
3676
3677     /* mark the icode as generated */
3678     ic->generated = 1;
3679 }
3680
3681 /*-----------------------------------------------------------------*/
3682 /* genCmp :- greater or less than comparison                       */
3683 /*-----------------------------------------------------------------*/
3684 static void genCmp (operand *left,operand *right,
3685                     operand *result, iCode *ifx, int sign)
3686 {
3687     int size, offset = 0 ;
3688     unsigned long lit = 0L;
3689     bool swappedOps = FALSE;
3690
3691     D(emitcode(";", "genCmp"););
3692
3693 #if 0
3694     /* If left if lit and right isn't, swap 'em. */
3695     if (AOP_TYPE(left) == AOP_LIT &&
3696         AOP_TYPE(right) != AOP_LIT)
3697     {
3698         operand *tmp = left;
3699         left = right;
3700         right = tmp;
3701         D(emitcode(";", "kevin literal hack"););
3702         swappedOps = !swappedOps;
3703     }
3704
3705     if (AOP_NEEDSACC(right))
3706     {
3707         if (AOP_NEEDSACC(left))
3708         {
3709             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3710                    "both CMP operands need ACC!");
3711             exit(1);
3712         }
3713         else
3714         {
3715             operand *tmp = left;
3716             left = right;
3717             right = tmp;
3718             D(emitcode(";", "kevin ACC hack"););
3719             swappedOps = !swappedOps;
3720         }
3721     }
3722 #endif
3723
3724     /* if left & right are bit variables */
3725     if (AOP_TYPE(left) == AOP_CRY &&
3726         AOP_TYPE(right) == AOP_CRY ) {
3727         emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3728         emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3729     } else {
3730         /* subtract right from left if at the
3731         end the carry flag is set then we know that
3732         left is greater than right */
3733         size = max(AOP_SIZE(left),AOP_SIZE(right));
3734
3735         /* if unsigned char cmp with lit, do cjne left,#right,zz */
3736         if((size == 1) && !sign &&
3737            (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3738             symbol *lbl  = newiTempLabel(NULL);
3739             emitcode("cjne","%s,%s,%05d$",
3740                      aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3741                      aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3742                      lbl->key+100);
3743             emitcode("","%05d$:",lbl->key+100);
3744         } else {
3745             if(AOP_TYPE(right) == AOP_LIT){
3746                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3747                 /* optimize if(x < 0) or if(x >= 0) */
3748                 if(lit == 0L){
3749                     if(!sign){
3750                         CLRC;
3751                     }
3752                     else{
3753                         MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3754                         if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3755                             genIfxJump (ifx,"acc.7");
3756                             return;
3757                         }
3758                         else    
3759                             emitcode("rlc","a");
3760                     }
3761                     goto release;
3762                 }
3763             }
3764             CLRC;
3765             while (size--)
3766             {
3767                 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3768                 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3769                 emitcode(";", "genCmp #2");
3770                 if (sign && (size == 0))
3771                 {
3772                     emitcode(";", "genCmp #3");
3773                     emitcode("xrl","a,#0x80");
3774                     if (AOP_TYPE(right) == AOP_LIT)
3775                     {
3776                         unsigned long lit = (unsigned long)
3777                             floatFromVal(AOP(right)->aopu.aop_lit);
3778                         emitcode(";", "genCmp #3.1");
3779                         emitcode("subb","a,#0x%02x",
3780                             0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3781                     }
3782                     else
3783                     {
3784                         emitcode(";", "genCmp #3.2");
3785                         if (AOP_NEEDSACC(right))
3786                         {
3787                             emitcode("push", "acc");
3788                         }
3789                         emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3790                                   FALSE,FALSE,FALSE));
3791                         emitcode("xrl","b,#0x80");
3792                         if (AOP_NEEDSACC(right))
3793                         {
3794                             emitcode("pop", "acc");
3795                         }
3796                         emitcode("subb","a,b");
3797                     }
3798                 }
3799                 else
3800                 {
3801                     const char *s;
3802
3803                     emitcode(";", "genCmp #4");
3804                     if (AOP_NEEDSACC(right))
3805                     {
3806                         /* Yuck!! */
3807                         emitcode(";", "genCmp #4.1");
3808                         emitcode("xch", "a, b");
3809                         MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3810                         emitcode("xch", "a, b");
3811                         s = "b";
3812                     }
3813                     else
3814                     {
3815                         emitcode(";", "genCmp #4.2");
3816                         s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3817                     }
3818
3819                     emitcode("subb","a,%s",s);
3820                 }
3821             }
3822         }
3823     }
3824
3825 release:
3826     if (swappedOps)
3827     {
3828         D(emitcode(";","kevHack: flip carry."););
3829         emitcode("cpl", "c");
3830     }
3831
3832     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3833         outBitC(result);
3834     } else {
3835         /* if the result is used in the next
3836         ifx conditional branch then generate
3837         code a little differently */
3838         if (ifx )
3839             genIfxJump (ifx,"c");
3840         else
3841             outBitC(result);
3842         /* leave the result in acc */
3843     }
3844 }
3845
3846 /*-----------------------------------------------------------------*/
3847 /* genCmpGt :- greater than comparison                             */
3848 /*-----------------------------------------------------------------*/
3849 static void genCmpGt (iCode *ic, iCode *ifx)
3850 {
3851     operand *left, *right, *result;
3852     link *letype , *retype;
3853     int sign ;
3854
3855     D(emitcode(";", "genCmpGt "););
3856
3857     left = IC_LEFT(ic);
3858     right= IC_RIGHT(ic);
3859     result = IC_RESULT(ic);
3860
3861     letype = getSpec(operandType(left));
3862     retype =getSpec(operandType(right));
3863     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3864     /* assign the amsops */
3865     AOP_OP_3(ic);
3866 #if 0
3867     aopOp (left,ic,FALSE, TRUE);
3868     aopOp (right,ic,FALSE, FALSE);
3869     aopOp (result,ic,TRUE, FALSE);
3870 #endif
3871
3872     genCmp(right, left, result, ifx, sign);
3873
3874     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3875     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3876     freeAsmop(result,NULL,ic,TRUE); 
3877 }
3878
3879 /*-----------------------------------------------------------------*/
3880 /* genCmpLt - less than comparisons                                */
3881 /*-----------------------------------------------------------------*/
3882 static void genCmpLt (iCode *ic, iCode *ifx)
3883 {
3884     operand *left, *right, *result;
3885     link *letype , *retype;
3886     int sign ;
3887
3888     D(emitcode(";", "genCmpLt "););
3889
3890     left = IC_LEFT(ic);
3891     right= IC_RIGHT(ic);
3892     result = IC_RESULT(ic);
3893
3894     letype = getSpec(operandType(left));
3895     retype =getSpec(operandType(right));
3896     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3897
3898     /* assign the amsops */
3899     AOP_OP_3(ic);
3900 #if 0
3901     aopOp (left,ic,FALSE, FALSE);
3902     aopOp (right,ic,FALSE, TRUE);
3903     aopOp (result,ic,TRUE, FALSE);
3904 #endif
3905
3906     genCmp(left, right, result, ifx, sign);
3907
3908     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3909     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3910     freeAsmop(result,NULL,ic,TRUE); 
3911 }
3912
3913 /*-----------------------------------------------------------------*/
3914 /* gencjneshort - compare and jump if not equal                    */
3915 /*-----------------------------------------------------------------*/
3916 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3917 {
3918     int size = max(AOP_SIZE(left),AOP_SIZE(right));
3919     int offset = 0;
3920     unsigned long lit = 0L;
3921
3922     D(emitcode(";", "gencjneshort"););
3923
3924     /* if the left side is a literal or 
3925     if the right is in a pointer register and left 
3926     is not */
3927     if ((AOP_TYPE(left) == AOP_LIT) || 
3928         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3929         operand *t = right;
3930         right = left;
3931         left = t;
3932     }
3933     
3934     if(AOP_TYPE(right) == AOP_LIT)
3935         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3936         
3937     if (opIsGptr(left) || opIsGptr(right))
3938     {
3939         /* We are comparing a generic pointer to something.
3940          * Exclude the generic type byte from the comparison.
3941          */
3942         size--;
3943         D(emitcode(";", "cjneshort: generic ptr special case.");) 
3944     }
3945          
3946
3947     /* if the right side is a literal then anything goes */
3948     if (AOP_TYPE(right) == AOP_LIT &&
3949         AOP_TYPE(left) != AOP_DIR ) {
3950         while (size--) {
3951             char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
3952             MOVA(l);
3953             emitcode("cjne","a,%s,%05d$",
3954                      aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3955                      lbl->key+100);
3956             offset++;
3957         }
3958     }
3959
3960     /* if the right side is in a register or in direct space or
3961     if the left is a pointer register & right is not */    
3962     else if (AOP_TYPE(right) == AOP_REG ||
3963              AOP_TYPE(right) == AOP_DIR || 
3964              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3965              (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3966         while (size--) {
3967             MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3968             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3969                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3970                 emitcode("jnz","%05d$",lbl->key+100);
3971             else
3972                 emitcode("cjne","a,%s,%05d$",
3973                          aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
3974                          lbl->key+100);
3975             offset++;
3976         }
3977     } else {
3978         /* right is a pointer reg need both a & b */
3979         while(size--) {
3980             char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
3981             if(strcmp(l,"b"))
3982                 emitcode("mov","b,%s",l);
3983             MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
3984             emitcode("cjne","a,b,%05d$",lbl->key+100);    
3985             offset++;
3986         }
3987     }
3988 }
3989
3990 /*-----------------------------------------------------------------*/
3991 /* gencjne - compare and jump if not equal                         */
3992 /*-----------------------------------------------------------------*/
3993 static void gencjne(operand *left, operand *right, symbol *lbl)
3994 {
3995     symbol *tlbl  = newiTempLabel(NULL);
3996
3997     D(emitcode(";", "gencjne"););
3998
3999     gencjneshort(left, right, lbl);
4000
4001     emitcode("mov","a,%s",one);
4002     emitcode("sjmp","%05d$",tlbl->key+100);
4003     emitcode("","%05d$:",lbl->key+100);
4004     emitcode("clr","a");
4005     emitcode("","%05d$:",tlbl->key+100);
4006 }
4007
4008 /*-----------------------------------------------------------------*/
4009 /* genCmpEq - generates code for equal to                          */
4010 /*-----------------------------------------------------------------*/
4011 static void genCmpEq (iCode *ic, iCode *ifx)
4012 {
4013     operand *left, *right, *result;
4014
4015     D(emitcode(";", "genCmpEq "););
4016
4017     AOP_OP_3(ic);
4018     AOP_SET_LOCALS(ic);
4019 #if 0
4020     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4021     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4022     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4023 #endif
4024
4025     /* if literal, literal on the right or 
4026     if the right is in a pointer register and left 
4027     is not */
4028     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4029         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4030         operand *t = IC_RIGHT(ic);
4031         IC_RIGHT(ic) = IC_LEFT(ic);
4032         IC_LEFT(ic) = t;
4033     }
4034
4035     if(ifx && !AOP_SIZE(result)){
4036         symbol *tlbl;
4037         /* if they are both bit variables */
4038         if (AOP_TYPE(left) == AOP_CRY &&
4039             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4040             if(AOP_TYPE(right) == AOP_LIT){
4041                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4042                 if(lit == 0L){
4043                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4044                     emitcode("cpl","c");
4045                 } else if(lit == 1L) {
4046                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4047                 } else {
4048                     emitcode("clr","c");
4049                 }
4050                 /* AOP_TYPE(right) == AOP_CRY */
4051             } else {
4052                 symbol *lbl = newiTempLabel(NULL);
4053                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4054                 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4055                 emitcode("cpl","c");
4056                 emitcode("","%05d$:",(lbl->key+100));
4057             }
4058             /* if true label then we jump if condition
4059             supplied is true */
4060             tlbl = newiTempLabel(NULL);
4061             if ( IC_TRUE(ifx) ) {
4062                 emitcode("jnc","%05d$",tlbl->key+100);
4063                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4064             } else {
4065                 emitcode("jc","%05d$",tlbl->key+100);
4066                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4067             }
4068             emitcode("","%05d$:",tlbl->key+100);                
4069         } else {
4070             tlbl = newiTempLabel(NULL);
4071             gencjneshort(left, right, tlbl);
4072             if ( IC_TRUE(ifx) ) {
4073                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4074                 emitcode("","%05d$:",tlbl->key+100);                
4075             } else {
4076                 symbol *lbl = newiTempLabel(NULL);
4077                 emitcode("sjmp","%05d$",lbl->key+100);
4078                 emitcode("","%05d$:",tlbl->key+100);                
4079                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4080                 emitcode("","%05d$:",lbl->key+100);             
4081             }
4082         }
4083         /* mark the icode as generated */
4084         ifx->generated = 1;
4085         goto release ;
4086     }
4087
4088     /* if they are both bit variables */
4089     if (AOP_TYPE(left) == AOP_CRY &&
4090         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4091         if(AOP_TYPE(right) == AOP_LIT){
4092             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4093             if(lit == 0L){
4094                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4095                 emitcode("cpl","c");
4096             } else if(lit == 1L) {
4097                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4098             } else {
4099                 emitcode("clr","c");
4100             }
4101             /* AOP_TYPE(right) == AOP_CRY */
4102         } else {
4103             symbol *lbl = newiTempLabel(NULL);
4104             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4105             emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4106             emitcode("cpl","c");
4107             emitcode("","%05d$:",(lbl->key+100));
4108         }
4109         /* c = 1 if egal */
4110         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4111             outBitC(result);
4112             goto release ;
4113         }
4114         if (ifx) {
4115             genIfxJump (ifx,"c");
4116             goto release ;
4117         }
4118         /* if the result is used in an arithmetic operation
4119         then put the result in place */
4120         outBitC(result);
4121     } else {
4122         gencjne(left,right,newiTempLabel(NULL));    
4123         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4124             aopPut(AOP(result),"a",0);
4125             goto release ;
4126         }
4127         if (ifx) {
4128             genIfxJump (ifx,"a");
4129             goto release ;
4130         }
4131         /* if the result is used in an arithmetic operation
4132         then put the result in place */
4133         if (AOP_TYPE(result) != AOP_CRY) 
4134             outAcc(result);
4135         /* leave the result in acc */
4136     }
4137
4138 release:
4139     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4140     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4141     freeAsmop(result,NULL,ic,TRUE);
4142 }
4143
4144 /*-----------------------------------------------------------------*/
4145 /* ifxForOp - returns the icode containing the ifx for operand     */
4146 /*-----------------------------------------------------------------*/
4147 static iCode *ifxForOp ( operand *op, iCode *ic )
4148 {
4149     /* if true symbol then needs to be assigned */
4150     if (IS_TRUE_SYMOP(op))
4151         return NULL ;
4152
4153     /* if this has register type condition and
4154     the next instruction is ifx with the same operand
4155     and live to of the operand is upto the ifx only then */
4156     if (ic->next &&
4157         ic->next->op == IFX &&
4158         IC_COND(ic->next)->key == op->key &&
4159         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4160         return ic->next;
4161
4162     return NULL;
4163 }
4164 /*-----------------------------------------------------------------*/
4165 /* genAndOp - for && operation                                     */
4166 /*-----------------------------------------------------------------*/
4167 static void genAndOp (iCode *ic)
4168 {
4169     operand *left,*right, *result;
4170     symbol *tlbl;
4171
4172     D(emitcode(";", "genAndOp "););
4173
4174     /* note here that && operations that are in an
4175     if statement are taken away by backPatchLabels
4176     only those used in arthmetic operations remain */
4177     AOP_OP_3(ic);
4178     AOP_SET_LOCALS(ic);
4179 #if 0
4180     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4181     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4182     aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4183 #endif
4184
4185     /* if both are bit variables */
4186     if (AOP_TYPE(left) == AOP_CRY &&
4187         AOP_TYPE(right) == AOP_CRY ) {
4188         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4189         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4190         outBitC(result);
4191     } else {
4192         tlbl = newiTempLabel(NULL);
4193         toBoolean(left);    
4194         emitcode("jz","%05d$",tlbl->key+100);
4195         toBoolean(right);
4196         emitcode("","%05d$:",tlbl->key+100);
4197         outBitAcc(result);
4198     }
4199
4200     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4201     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4202     freeAsmop(result,NULL,ic,TRUE);
4203 }
4204
4205
4206 /*-----------------------------------------------------------------*/
4207 /* genOrOp - for || operation                                      */
4208 /*-----------------------------------------------------------------*/
4209 static void genOrOp (iCode *ic)
4210 {
4211     operand *left,*right, *result;
4212     symbol *tlbl;
4213
4214     D(emitcode(";", "genOrOp "););
4215
4216     /* note here that || operations that are in an
4217     if statement are taken away by backPatchLabels
4218     only those used in arthmetic operations remain */
4219     AOP_OP_3(ic);
4220     AOP_SET_LOCALS(ic);
4221 #if 0
4222     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4223     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4224     aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4225 #endif
4226
4227     /* if both are bit variables */
4228     if (AOP_TYPE(left) == AOP_CRY &&
4229         AOP_TYPE(right) == AOP_CRY ) {
4230         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4231         emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4232         outBitC(result);
4233     } else {
4234         tlbl = newiTempLabel(NULL);
4235         toBoolean(left);
4236         emitcode("jnz","%05d$",tlbl->key+100);
4237         toBoolean(right);
4238         emitcode("","%05d$:",tlbl->key+100);
4239         outBitAcc(result);
4240     }
4241
4242     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4243     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4244     freeAsmop(result,NULL,ic,TRUE);            
4245 }
4246
4247 /*-----------------------------------------------------------------*/
4248 /* isLiteralBit - test if lit == 2^n                               */
4249 /*-----------------------------------------------------------------*/
4250 static int isLiteralBit(unsigned long lit)
4251 {
4252     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4253     0x100L,0x200L,0x400L,0x800L,
4254     0x1000L,0x2000L,0x4000L,0x8000L,
4255     0x10000L,0x20000L,0x40000L,0x80000L,
4256     0x100000L,0x200000L,0x400000L,0x800000L,
4257     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4258     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4259     int idx;
4260     
4261     for(idx = 0; idx < 32; idx++)
4262         if(lit == pw[idx])
4263             return idx+1;
4264     return 0;
4265 }
4266
4267 /*-----------------------------------------------------------------*/
4268 /* continueIfTrue -                                                */
4269 /*-----------------------------------------------------------------*/
4270 static void continueIfTrue (iCode *ic)
4271 {
4272     if(IC_TRUE(ic))
4273         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4274     ic->generated = 1;
4275 }
4276
4277 /*-----------------------------------------------------------------*/
4278 /* jmpIfTrue -                                                     */
4279 /*-----------------------------------------------------------------*/
4280 static void jumpIfTrue (iCode *ic)
4281 {
4282     if(!IC_TRUE(ic))
4283         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4284     ic->generated = 1;
4285 }
4286
4287 /*-----------------------------------------------------------------*/
4288 /* jmpTrueOrFalse -                                                */
4289 /*-----------------------------------------------------------------*/
4290 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4291 {
4292     // ugly but optimized by peephole
4293     if(IC_TRUE(ic)){
4294         symbol *nlbl = newiTempLabel(NULL);
4295         emitcode("sjmp","%05d$",nlbl->key+100);                 
4296         emitcode("","%05d$:",tlbl->key+100);
4297         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4298         emitcode("","%05d$:",nlbl->key+100);
4299     }
4300     else{
4301         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4302         emitcode("","%05d$:",tlbl->key+100);
4303     }
4304     ic->generated = 1;
4305 }
4306
4307 /*-----------------------------------------------------------------*/
4308 /* genAnd  - code for and                                          */
4309 /*-----------------------------------------------------------------*/
4310 static void genAnd (iCode *ic, iCode *ifx)
4311 {
4312     operand *left, *right, *result;
4313     int size, offset=0;  
4314     unsigned long lit = 0L;
4315     int bytelit = 0;
4316     char buffer[10];
4317
4318     D(emitcode(";", "genAnd "););
4319
4320     AOP_OP_3(ic);
4321     AOP_SET_LOCALS(ic);
4322 #if 0
4323     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4324     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4325     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4326 #endif
4327
4328 #ifdef DEBUG_TYPE
4329     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4330              AOP_TYPE(result),
4331              AOP_TYPE(left), AOP_TYPE(right));
4332     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4333              AOP_SIZE(result),
4334              AOP_SIZE(left), AOP_SIZE(right));
4335 #endif
4336
4337     /* if left is a literal & right is not then exchange them */
4338     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4339         AOP_NEEDSACC(left)) {
4340         operand *tmp = right ;
4341         right = left;
4342         left = tmp;
4343     }
4344
4345     /* if result = right then exchange them */
4346     if(sameRegs(AOP(result),AOP(right))){
4347         operand *tmp = right ;
4348         right = left;
4349         left = tmp;
4350     }
4351
4352     /* if right is bit then exchange them */
4353     if (AOP_TYPE(right) == AOP_CRY &&
4354         AOP_TYPE(left) != AOP_CRY){
4355         operand *tmp = right ;
4356         right = left;
4357         left = tmp;
4358     }
4359     if(AOP_TYPE(right) == AOP_LIT)
4360         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4361
4362     size = AOP_SIZE(result);
4363
4364     // if(bit & yy)
4365     // result = bit & yy;
4366     if (AOP_TYPE(left) == AOP_CRY){
4367         // c = bit & literal;
4368         if(AOP_TYPE(right) == AOP_LIT){
4369             if(lit & 1) {
4370                 if(size && sameRegs(AOP(result),AOP(left)))
4371                     // no change
4372                     goto release;
4373                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4374             } else {
4375                 // bit(result) = 0;
4376                 if(size && (AOP_TYPE(result) == AOP_CRY)){
4377                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4378                     goto release;
4379                 }
4380                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4381                     jumpIfTrue(ifx);
4382                     goto release;
4383                 }
4384                 emitcode("clr","c");
4385             }
4386         } else {
4387             if (AOP_TYPE(right) == AOP_CRY){
4388                 // c = bit & bit;
4389                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4390                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4391             } else {
4392                 // c = bit & val;
4393                 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4394                 // c = lsb
4395                 emitcode("rrc","a");
4396                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4397             }
4398         }
4399         // bit = c
4400         // val = c
4401         if(size)
4402             outBitC(result);
4403         // if(bit & ...)
4404         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4405             genIfxJump(ifx, "c");           
4406         goto release ;
4407     }
4408
4409     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4410     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4411     if((AOP_TYPE(right) == AOP_LIT) &&
4412        (AOP_TYPE(result) == AOP_CRY) &&
4413        (AOP_TYPE(left) != AOP_CRY)){
4414         int posbit = isLiteralBit(lit);
4415         /* left &  2^n */
4416         if(posbit){
4417             posbit--;
4418             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4419             // bit = left & 2^n
4420             if(size)
4421                 emitcode("mov","c,acc.%d",posbit&0x07);
4422             // if(left &  2^n)
4423             else{
4424                 if(ifx){
4425                     sprintf(buffer,"acc.%d",posbit&0x07);
4426                     genIfxJump(ifx, buffer);
4427                 }
4428                 goto release;
4429             }
4430         } else {
4431             symbol *tlbl = newiTempLabel(NULL);
4432             int sizel = AOP_SIZE(left);
4433             if(size)
4434                 emitcode("setb","c");
4435             while(sizel--){
4436                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4437                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4438                     // byte ==  2^n ?
4439                     if((posbit = isLiteralBit(bytelit)) != 0)
4440                         emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4441                     else{
4442                         if(bytelit != 0x0FFL)
4443                             emitcode("anl","a,%s",
4444                                      aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4445                         emitcode("jnz","%05d$",tlbl->key+100);
4446                     }
4447                 }
4448                 offset++;
4449             }
4450             // bit = left & literal
4451             if(size){
4452                 emitcode("clr","c");
4453                 emitcode("","%05d$:",tlbl->key+100);
4454             }
4455             // if(left & literal)
4456             else{
4457                 if(ifx)
4458                     jmpTrueOrFalse(ifx, tlbl);
4459                 goto release ;
4460             }
4461         }
4462         outBitC(result);
4463         goto release ;
4464     }
4465
4466     /* if left is same as result */
4467     if(sameRegs(AOP(result),AOP(left))){
4468         for(;size--; offset++) {
4469             if(AOP_TYPE(right) == AOP_LIT){
4470                 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4471                     continue;
4472                 else 
4473                     if (bytelit == 0)
4474                         aopPut(AOP(result),zero,offset);
4475                     else 
4476                         if (IS_AOP_PREG(result)) {
4477                             MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4478                             emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4479                             aopPut(AOP(result),"a",offset);
4480                         } else
4481                             emitcode("anl","%s,%s",
4482                                      aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4483                                      aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4484             } else {
4485                 if (AOP_TYPE(left) == AOP_ACC)
4486                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4487                 else {
4488                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4489                     if (IS_AOP_PREG(result)) {
4490                         emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4491                         aopPut(AOP(result),"a",offset);
4492
4493                     } else
4494                         emitcode("anl","%s,a",
4495                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4496                 }
4497             }
4498         }
4499     } else {
4500         // left & result in different registers
4501         if(AOP_TYPE(result) == AOP_CRY){
4502             // result = bit
4503             // if(size), result in bit
4504             // if(!size && ifx), conditional oper: if(left & right)
4505             symbol *tlbl = newiTempLabel(NULL);
4506             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4507             if(size)
4508                 emitcode("setb","c");
4509             while(sizer--){
4510                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4511                 emitcode("anl","a,%s",
4512                          aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4513                 emitcode("jnz","%05d$",tlbl->key+100);
4514                 offset++;
4515             }
4516             if(size){
4517                 CLRC;
4518                 emitcode("","%05d$:",tlbl->key+100);
4519                 outBitC(result);
4520             } else if(ifx)
4521                 jmpTrueOrFalse(ifx, tlbl);
4522         } else {
4523             for(;(size--);offset++) {
4524                 // normal case
4525                 // result = left & right
4526                 if(AOP_TYPE(right) == AOP_LIT){
4527                     if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4528                         aopPut(AOP(result),
4529                                aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4530                                offset);
4531                         continue;
4532                     } else if(bytelit == 0){
4533                         aopPut(AOP(result),zero,offset);
4534                         continue;
4535                     }
4536                 }
4537                 // faster than result <- left, anl result,right
4538                 // and better if result is SFR
4539                 if (AOP_TYPE(left) == AOP_ACC) 
4540                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4541                 else {
4542                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4543                     emitcode("anl","a,%s",
4544                              aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4545                 }
4546                 aopPut(AOP(result),"a",offset);
4547             }
4548         }
4549     }
4550
4551 release :
4552     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4553     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4554     freeAsmop(result,NULL,ic,TRUE);     
4555 }
4556
4557 /*-----------------------------------------------------------------*/
4558 /* genOr  - code for or                                            */
4559 /*-----------------------------------------------------------------*/
4560 static void genOr (iCode *ic, iCode *ifx)
4561 {
4562     operand *left, *right, *result;
4563     int size, offset=0;
4564     unsigned long lit = 0L;
4565
4566     D(emitcode(";", "genOr "););
4567
4568     AOP_OP_3(ic);
4569     AOP_SET_LOCALS(ic);
4570     #if 0
4571     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4572     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4573     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4574     #endif
4575
4576 #ifdef DEBUG_TYPE
4577     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4578              AOP_TYPE(result),
4579              AOP_TYPE(left), AOP_TYPE(right));
4580     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4581              AOP_SIZE(result),
4582              AOP_SIZE(left), AOP_SIZE(right));
4583 #endif
4584
4585     /* if left is a literal & right is not then exchange them */
4586     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4587         AOP_NEEDSACC(left)) {
4588         operand *tmp = right ;
4589         right = left;
4590         left = tmp;
4591     }
4592
4593     /* if result = right then exchange them */
4594     if(sameRegs(AOP(result),AOP(right))){
4595         operand *tmp = right ;
4596         right = left;
4597         left = tmp;
4598     }
4599
4600     /* if right is bit then exchange them */
4601     if (AOP_TYPE(right) == AOP_CRY &&
4602         AOP_TYPE(left) != AOP_CRY){
4603         operand *tmp = right ;
4604         right = left;
4605         left = tmp;
4606     }
4607     if(AOP_TYPE(right) == AOP_LIT)
4608         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4609
4610     size = AOP_SIZE(result);
4611
4612     // if(bit | yy)
4613     // xx = bit | yy;
4614     if (AOP_TYPE(left) == AOP_CRY){
4615         if(AOP_TYPE(right) == AOP_LIT){
4616             // c = bit & literal;
4617             if(lit){
4618                 // lit != 0 => result = 1
4619                 if(AOP_TYPE(result) == AOP_CRY){
4620                     if(size)
4621                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4622                     else if(ifx)
4623                         continueIfTrue(ifx);
4624                     goto release;
4625                 }
4626                 emitcode("setb","c");
4627             } else {
4628                 // lit == 0 => result = left
4629                 if(size && sameRegs(AOP(result),AOP(left)))
4630                     goto release;
4631                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4632             }
4633         } else {
4634             if (AOP_TYPE(right) == AOP_CRY){
4635                 // c = bit | bit;
4636                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4637                 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4638             }
4639             else{
4640                 // c = bit | val;
4641                 symbol *tlbl = newiTempLabel(NULL);
4642                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4643                     emitcode("setb","c");
4644                 emitcode("jb","%s,%05d$",
4645                          AOP(left)->aopu.aop_dir,tlbl->key+100);
4646                 toBoolean(right);
4647                 emitcode("jnz","%05d$",tlbl->key+100);
4648                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4649                     jmpTrueOrFalse(ifx, tlbl);
4650                     goto release;
4651                 } else {
4652                     CLRC;
4653                     emitcode("","%05d$:",tlbl->key+100);
4654                 }
4655             }
4656         }
4657         // bit = c
4658         // val = c
4659         if(size)
4660             outBitC(result);
4661         // if(bit | ...)
4662         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4663             genIfxJump(ifx, "c");           
4664         goto release ;
4665     }
4666
4667     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4668     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4669     if((AOP_TYPE(right) == AOP_LIT) &&
4670        (AOP_TYPE(result) == AOP_CRY) &&
4671        (AOP_TYPE(left) != AOP_CRY)){
4672         if(lit){
4673             // result = 1
4674             if(size)
4675                 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4676             else 
4677                 continueIfTrue(ifx);
4678             goto release;
4679         } else {
4680             // lit = 0, result = boolean(left)
4681             if(size)
4682                 emitcode("setb","c");
4683             toBoolean(right);
4684             if(size){
4685                 symbol *tlbl = newiTempLabel(NULL);
4686                 emitcode("jnz","%05d$",tlbl->key+100);
4687                 CLRC;
4688                 emitcode("","%05d$:",tlbl->key+100);
4689             } else {
4690                 genIfxJump (ifx,"a");
4691                 goto release;
4692             }
4693         }
4694         outBitC(result);
4695         goto release ;
4696     }
4697
4698     /* if left is same as result */
4699     if(sameRegs(AOP(result),AOP(left))){
4700         for(;size--; offset++) {
4701             if(AOP_TYPE(right) == AOP_LIT){
4702                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4703                     continue;
4704                 else 
4705                     if (IS_AOP_PREG(left)) {
4706                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4707                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4708                         aopPut(AOP(result),"a",offset);
4709                     } else
4710                         emitcode("orl","%s,%s",
4711                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4712                                  aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4713             } else {
4714                 if (AOP_TYPE(left) == AOP_ACC) 
4715                     emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4716                 else {              
4717                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4718                     if (IS_AOP_PREG(left)) {
4719                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4720                         aopPut(AOP(result),"a",offset);
4721                     } else
4722                         emitcode("orl","%s,a",
4723                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4724                 }
4725             }
4726         }
4727     } else {
4728         // left & result in different registers
4729         if(AOP_TYPE(result) == AOP_CRY){
4730             // result = bit
4731             // if(size), result in bit
4732             // if(!size && ifx), conditional oper: if(left | right)
4733             symbol *tlbl = newiTempLabel(NULL);
4734             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4735             if(size)
4736                 emitcode("setb","c");
4737             while(sizer--){
4738                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4739                 emitcode("orl","a,%s",
4740                          aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4741                 emitcode("jnz","%05d$",tlbl->key+100);
4742                 offset++;
4743             }
4744             if(size){
4745                 CLRC;
4746                 emitcode("","%05d$:",tlbl->key+100);
4747                 outBitC(result);
4748             } else if(ifx)
4749                 jmpTrueOrFalse(ifx, tlbl);
4750         } else for(;(size--);offset++){
4751             // normal case
4752             // result = left & right
4753             if(AOP_TYPE(right) == AOP_LIT){
4754                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4755                     aopPut(AOP(result),
4756                            aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4757                            offset);
4758                     continue;
4759                 }
4760             }
4761             // faster than result <- left, anl result,right
4762             // and better if result is SFR
4763             if (AOP_TYPE(left) == AOP_ACC) 
4764                 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4765             else {
4766                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4767                 emitcode("orl","a,%s",
4768                          aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4769             }
4770             aopPut(AOP(result),"a",offset);                     
4771         }
4772     }
4773
4774 release :
4775     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4776     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4777     freeAsmop(result,NULL,ic,TRUE);     
4778 }
4779
4780 /*-----------------------------------------------------------------*/
4781 /* genXor - code for xclusive or                                   */
4782 /*-----------------------------------------------------------------*/
4783 static void genXor (iCode *ic, iCode *ifx)
4784 {
4785     operand *left, *right, *result;
4786     int size, offset=0;
4787     unsigned long lit = 0L;
4788
4789     D(emitcode(";", "genXor "););
4790
4791     AOP_OP_3(ic);
4792     AOP_SET_LOCALS(ic);
4793 #if 0
4794     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4795     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4796     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4797 #endif
4798
4799 #ifdef DEBUG_TYPE
4800     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4801              AOP_TYPE(result),
4802              AOP_TYPE(left), AOP_TYPE(right));
4803     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4804              AOP_SIZE(result),
4805              AOP_SIZE(left), AOP_SIZE(right));
4806 #endif
4807
4808     /* if left is a literal & right is not ||
4809        if left needs acc & right does not */
4810     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4811         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4812         operand *tmp = right ;
4813         right = left;
4814         left = tmp;
4815     }
4816
4817     /* if result = right then exchange them */
4818     if(sameRegs(AOP(result),AOP(right))){
4819         operand *tmp = right ;
4820         right = left;
4821         left = tmp;
4822     }
4823
4824     /* if right is bit then exchange them */
4825     if (AOP_TYPE(right) == AOP_CRY &&
4826         AOP_TYPE(left) != AOP_CRY){
4827         operand *tmp = right ;
4828         right = left;
4829         left = tmp;
4830     }
4831     if(AOP_TYPE(right) == AOP_LIT)
4832         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4833
4834     size = AOP_SIZE(result);
4835
4836     // if(bit ^ yy)
4837     // xx = bit ^ yy;
4838     if (AOP_TYPE(left) == AOP_CRY){
4839         if(AOP_TYPE(right) == AOP_LIT){
4840             // c = bit & literal;
4841             if(lit>>1){
4842                 // lit>>1  != 0 => result = 1
4843                 if(AOP_TYPE(result) == AOP_CRY){
4844                     if(size)
4845                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4846                     else if(ifx)
4847                         continueIfTrue(ifx);
4848                     goto release;
4849                 }
4850                 emitcode("setb","c");
4851             } else{
4852                 // lit == (0 or 1)
4853                 if(lit == 0){
4854                     // lit == 0, result = left
4855                     if(size && sameRegs(AOP(result),AOP(left)))
4856                         goto release;
4857                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4858                 } else{
4859                     // lit == 1, result = not(left)
4860                     if(size && sameRegs(AOP(result),AOP(left))){
4861                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4862                         goto release;
4863                     } else {
4864                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4865                         emitcode("cpl","c");
4866                     }
4867                 }
4868             }
4869
4870         } else {
4871             // right != literal
4872             symbol *tlbl = newiTempLabel(NULL);
4873             if (AOP_TYPE(right) == AOP_CRY){
4874                 // c = bit ^ bit;
4875                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4876             }
4877             else{
4878                 int sizer = AOP_SIZE(right);
4879                 // c = bit ^ val
4880                 // if val>>1 != 0, result = 1
4881                 emitcode("setb","c");
4882                 while(sizer){
4883                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
4884                     if(sizer == 1)
4885                         // test the msb of the lsb
4886                         emitcode("anl","a,#0xfe");
4887                     emitcode("jnz","%05d$",tlbl->key+100);
4888                     sizer--;
4889                 }
4890                 // val = (0,1)
4891                 emitcode("rrc","a");
4892             }
4893             emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4894             emitcode("cpl","c");
4895             emitcode("","%05d$:",(tlbl->key+100));
4896         }
4897         // bit = c
4898         // val = c
4899         if(size)
4900             outBitC(result);
4901         // if(bit | ...)
4902         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4903             genIfxJump(ifx, "c");           
4904         goto release ;
4905     }
4906
4907     if(sameRegs(AOP(result),AOP(left))){
4908         /* if left is same as result */
4909         for(;size--; offset++) {
4910             if(AOP_TYPE(right) == AOP_LIT){
4911                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4912                     continue;
4913                 else
4914                     if (IS_AOP_PREG(left)) {
4915                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4916                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4917                         aopPut(AOP(result),"a",offset);
4918                     } else 
4919                         emitcode("xrl","%s,%s",
4920                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4921                                  aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4922             } else {
4923                 if (AOP_TYPE(left) == AOP_ACC)
4924                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4925                 else {
4926                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4927                     if (IS_AOP_PREG(left)) {
4928                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4929                         aopPut(AOP(result),"a",offset);
4930                     } else
4931                         emitcode("xrl","%s,a",
4932                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4933                 }
4934             }
4935         }
4936     } else {
4937         // left & result in different registers
4938         if(AOP_TYPE(result) == AOP_CRY){
4939             // result = bit
4940             // if(size), result in bit
4941             // if(!size && ifx), conditional oper: if(left ^ right)
4942             symbol *tlbl = newiTempLabel(NULL);
4943             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4944             if(size)
4945                 emitcode("setb","c");
4946             while(sizer--){
4947                 if((AOP_TYPE(right) == AOP_LIT) &&
4948                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4949                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4950                 } else {
4951                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4952                     emitcode("xrl","a,%s",
4953                              aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4954                 }
4955                 emitcode("jnz","%05d$",tlbl->key+100);
4956                 offset++;
4957             }
4958             if(size){
4959                 CLRC;
4960                 emitcode("","%05d$:",tlbl->key+100);
4961                 outBitC(result);
4962             } else if(ifx)
4963                 jmpTrueOrFalse(ifx, tlbl);
4964         } else for(;(size--);offset++){
4965             // normal case
4966             // result = left & right
4967             if(AOP_TYPE(right) == AOP_LIT){
4968                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4969                     aopPut(AOP(result),
4970                            aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4971                            offset);
4972                     continue;
4973                 }
4974             }
4975             // faster than result <- left, anl result,right
4976             // and better if result is SFR
4977             if (AOP_TYPE(left) == AOP_ACC)
4978                 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4979             else {
4980                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4981                 emitcode("xrl","a,%s",
4982                          aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4983             }
4984             aopPut(AOP(result),"a",offset);
4985         }
4986     }
4987
4988 release :
4989     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4990     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4991     freeAsmop(result,NULL,ic,TRUE);     
4992 }
4993
4994 /*-----------------------------------------------------------------*/
4995 /* genInline - write the inline code out                           */
4996 /*-----------------------------------------------------------------*/
4997 static void genInline (iCode *ic)
4998 {
4999     char buffer[MAX_INLINEASM];
5000     char *bp = buffer;
5001     char *bp1= buffer;
5002     
5003     D(emitcode(";", "genInline "););
5004
5005     _G.inLine += (!options.asmpeep);
5006     strcpy(buffer,IC_INLINE(ic));
5007
5008     /* emit each line as a code */
5009     while (*bp) {
5010         if (*bp == '\n') {
5011             *bp++ = '\0';
5012             emitcode(bp1,"");
5013             bp1 = bp;
5014         } else {
5015             if (*bp == ':') {
5016                 bp++;
5017                 *bp = '\0';
5018                 bp++;
5019                 emitcode(bp1,"");
5020                 bp1 = bp;
5021             } else
5022                 bp++;
5023         }
5024     }
5025     if (bp1 != bp)
5026         emitcode(bp1,"");
5027     /*     emitcode("",buffer); */
5028     _G.inLine -= (!options.asmpeep);
5029 }
5030
5031 /*-----------------------------------------------------------------*/
5032 /* genRRC - rotate right with carry                                */
5033 /*-----------------------------------------------------------------*/
5034 static void genRRC (iCode *ic)
5035 {
5036     operand *left , *result ;
5037     int size, offset = 0;
5038     char *l;    
5039
5040     D(emitcode(";", "genRRC "););
5041
5042     /* rotate right with carry */
5043     left = IC_LEFT(ic);
5044     result=IC_RESULT(ic);
5045     aopOp (left,ic,FALSE, FALSE);
5046     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5047
5048     /* move it to the result */
5049     size = AOP_SIZE(result);    
5050     offset = size - 1 ;
5051     CLRC;
5052     while (size--) {
5053         l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5054         MOVA(l);
5055         emitcode("rrc","a");
5056         if (AOP_SIZE(result) > 1)
5057             aopPut(AOP(result),"a",offset--);
5058     }
5059     /* now we need to put the carry into the
5060     highest order byte of the result */
5061     if (AOP_SIZE(result) > 1) {
5062         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5063         MOVA(l);
5064     }
5065     emitcode("mov","acc.7,c");
5066     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5067     freeAsmop(left,NULL,ic,TRUE);
5068     freeAsmop(result,NULL,ic,TRUE);
5069 }
5070
5071 /*-----------------------------------------------------------------*/
5072 /* genRLC - generate code for rotate left with carry               */
5073 /*-----------------------------------------------------------------*/
5074 static void genRLC (iCode *ic)
5075 {    
5076     operand *left , *result ;
5077     int size, offset = 0;
5078     char *l;    
5079
5080     D(emitcode(";", "genRLC "););
5081
5082     /* rotate right with carry */
5083     left = IC_LEFT(ic);
5084     result=IC_RESULT(ic);
5085     aopOp (left,ic,FALSE, FALSE);
5086     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5087
5088     /* move it to the result */
5089     size = AOP_SIZE(result);    
5090     offset = 0 ;
5091     if (size--) {
5092         l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5093         MOVA(l);
5094         emitcode("add","a,acc");
5095         if (AOP_SIZE(result) > 1)
5096             aopPut(AOP(result),"a",offset++);
5097         while (size--) {
5098             l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5099             MOVA(l);
5100             emitcode("rlc","a");
5101             if (AOP_SIZE(result) > 1)
5102                 aopPut(AOP(result),"a",offset++);
5103         }
5104     }
5105     /* now we need to put the carry into the
5106     highest order byte of the result */
5107     if (AOP_SIZE(result) > 1) {
5108         l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5109         MOVA(l);
5110     }
5111     emitcode("mov","acc.0,c");
5112     aopPut(AOP(result),"a",0);
5113     freeAsmop(left,NULL,ic,TRUE);
5114     freeAsmop(result,NULL,ic,TRUE);
5115 }
5116
5117 /*-----------------------------------------------------------------*/
5118 /* genGetHbit - generates code get highest order bit               */
5119 /*-----------------------------------------------------------------*/
5120 static void genGetHbit (iCode *ic)
5121 {
5122     operand *left, *result;
5123     left = IC_LEFT(ic);
5124     result=IC_RESULT(ic);
5125     aopOp (left,ic,FALSE, FALSE);
5126     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5127
5128     D(emitcode(";", "genGetHbit "););
5129
5130     /* get the highest order byte into a */
5131     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5132     if(AOP_TYPE(result) == AOP_CRY){
5133         emitcode("rlc","a");
5134         outBitC(result);
5135     }
5136     else{
5137         emitcode("rl","a");
5138         emitcode("anl","a,#0x01");
5139         outAcc(result);
5140     }
5141
5142
5143     freeAsmop(left,NULL,ic,TRUE);
5144     freeAsmop(result,NULL,ic,TRUE);
5145 }
5146
5147 /*-----------------------------------------------------------------*/
5148 /* AccRol - rotate left accumulator by known count                 */
5149 /*-----------------------------------------------------------------*/
5150 static void AccRol (int shCount)
5151 {
5152     shCount &= 0x0007;              // shCount : 0..7
5153     switch(shCount){
5154         case 0 :
5155             break;
5156         case 1 :
5157             emitcode("rl","a");
5158             break;
5159         case 2 :
5160             emitcode("rl","a");
5161             emitcode("rl","a");
5162             break;
5163         case 3 :
5164             emitcode("swap","a");
5165             emitcode("rr","a");
5166             break;
5167         case 4 :
5168             emitcode("swap","a");
5169             break;
5170         case 5 :
5171             emitcode("swap","a");
5172             emitcode("rl","a");
5173             break;
5174         case 6 :
5175             emitcode("rr","a");
5176             emitcode("rr","a");
5177             break;
5178         case 7 :
5179             emitcode("rr","a");
5180             break;
5181     }
5182 }
5183
5184 /*-----------------------------------------------------------------*/
5185 /* AccLsh - left shift accumulator by known count                  */
5186 /*-----------------------------------------------------------------*/
5187 static void AccLsh (int shCount)
5188 {
5189     if(shCount != 0){
5190         if(shCount == 1)
5191             emitcode("add","a,acc");
5192         else 
5193             if(shCount == 2) {
5194             emitcode("add","a,acc");
5195             emitcode("add","a,acc");
5196         } else {
5197             /* rotate left accumulator */
5198             AccRol(shCount);
5199             /* and kill the lower order bits */
5200             emitcode("anl","a,#0x%02x", SLMask[shCount]);
5201         }
5202     }
5203 }
5204
5205 /*-----------------------------------------------------------------*/
5206 /* AccRsh - right shift accumulator by known count                 */
5207 /*-----------------------------------------------------------------*/
5208 static void AccRsh (int shCount)
5209 {
5210     if(shCount != 0){
5211         if(shCount == 1){
5212             CLRC;
5213             emitcode("rrc","a");
5214         } else {
5215             /* rotate right accumulator */
5216             AccRol(8 - shCount);
5217             /* and kill the higher order bits */
5218             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5219         }
5220     }
5221 }
5222
5223 /*-----------------------------------------------------------------*/
5224 /* AccSRsh - signed right shift accumulator by known count                 */
5225 /*-----------------------------------------------------------------*/
5226 static void AccSRsh (int shCount)
5227 {
5228     symbol *tlbl ;
5229     if(shCount != 0){
5230         if(shCount == 1){
5231             emitcode("mov","c,acc.7");
5232             emitcode("rrc","a");
5233         } else if(shCount == 2){
5234             emitcode("mov","c,acc.7");
5235             emitcode("rrc","a");
5236             emitcode("mov","c,acc.7");
5237             emitcode("rrc","a");
5238         } else {
5239             tlbl = newiTempLabel(NULL);
5240             /* rotate right accumulator */
5241             AccRol(8 - shCount);
5242             /* and kill the higher order bits */
5243             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5244             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5245             emitcode("orl","a,#0x%02x",
5246                      (unsigned char)~SRMask[shCount]);
5247             emitcode("","%05d$:",tlbl->key+100);
5248         }
5249     }
5250 }
5251
5252 /*-----------------------------------------------------------------*/
5253 /* shiftR1Left2Result - shift right one byte from left to result   */
5254 /*-----------------------------------------------------------------*/
5255 static void shiftR1Left2Result (operand *left, int offl,
5256                                 operand *result, int offr,
5257                                 int shCount, int sign)
5258 {
5259     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5260     /* shift right accumulator */
5261     if(sign)
5262         AccSRsh(shCount);
5263     else
5264         AccRsh(shCount);
5265     aopPut(AOP(result),"a",offr);
5266 }
5267
5268 /*-----------------------------------------------------------------*/
5269 /* shiftL1Left2Result - shift left one byte from left to result    */
5270 /*-----------------------------------------------------------------*/
5271 static void shiftL1Left2Result (operand *left, int offl,
5272                                 operand *result, int offr, int shCount)
5273 {
5274     char *l;
5275     l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5276     MOVA(l);
5277     /* shift left accumulator */
5278     AccLsh(shCount);
5279     aopPut(AOP(result),"a",offr);
5280 }
5281
5282 /*-----------------------------------------------------------------*/
5283 /* movLeft2Result - move byte from left to result                  */
5284 /*-----------------------------------------------------------------*/
5285 static void movLeft2Result (operand *left, int offl,
5286                             operand *result, int offr, int sign)
5287 {
5288     char *l;
5289     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5290         l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5291
5292         if (*l == '@' && (IS_AOP_PREG(result))) {
5293             emitcode("mov","a,%s",l);
5294             aopPut(AOP(result),"a",offr);
5295         } else {
5296             if(!sign)
5297                 aopPut(AOP(result),l,offr);
5298             else{
5299                 /* MSB sign in acc.7 ! */
5300                 if(getDataSize(left) == offl+1){
5301                     emitcode("mov","a,%s",l);
5302                     aopPut(AOP(result),"a",offr);
5303                 }
5304             }
5305         }
5306     }
5307 }
5308
5309 /*-----------------------------------------------------------------*/
5310 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
5311 /*-----------------------------------------------------------------*/
5312 static void AccAXRrl1 (char *x)
5313 {
5314     emitcode("rrc","a");
5315     emitcode("xch","a,%s", x);
5316     emitcode("rrc","a");
5317     emitcode("xch","a,%s", x);
5318 }
5319
5320 /*-----------------------------------------------------------------*/
5321 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5322 /*-----------------------------------------------------------------*/
5323 static void AccAXLrl1 (char *x)
5324 {
5325     emitcode("xch","a,%s",x);
5326     emitcode("rlc","a");
5327     emitcode("xch","a,%s",x);
5328     emitcode("rlc","a");
5329 }
5330
5331 /*-----------------------------------------------------------------*/
5332 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5333 /*-----------------------------------------------------------------*/
5334 static void AccAXLsh1 (char *x)
5335 {
5336     emitcode("xch","a,%s",x);
5337     emitcode("add","a,acc");
5338     emitcode("xch","a,%s",x);
5339     emitcode("rlc","a");
5340 }
5341
5342 /*-----------------------------------------------------------------*/
5343 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5344 /*-----------------------------------------------------------------*/
5345 static void AccAXLsh (char *x, int shCount)
5346 {
5347     switch(shCount){
5348         case 0 :
5349             break;
5350         case 1 :
5351             AccAXLsh1(x);
5352             break;
5353         case 2 :
5354             AccAXLsh1(x);
5355             AccAXLsh1(x);
5356             break;
5357         case 3 :
5358         case 4 :
5359         case 5 :                        // AAAAABBB:CCCCCDDD
5360             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
5361             emitcode("anl","a,#0x%02x",
5362                      SLMask[shCount]);  // BBB00000:CCCCCDDD
5363             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
5364             AccRol(shCount);            // DDDCCCCC:BBB00000
5365             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
5366             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
5367             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
5368             emitcode("anl","a,#0x%02x",
5369                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
5370             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
5371             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
5372             break;
5373         case 6 :                        // AAAAAABB:CCCCCCDD
5374             emitcode("anl","a,#0x%02x",
5375                      SRMask[shCount]);  // 000000BB:CCCCCCDD
5376             emitcode("mov","c,acc.0");  // c = B
5377             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
5378             AccAXRrl1(x);               // BCCCCCCD:D000000B
5379             AccAXRrl1(x);               // BBCCCCCC:DD000000
5380             break;
5381         case 7 :                        // a:x <<= 7
5382             emitcode("anl","a,#0x%02x",
5383                      SRMask[shCount]);  // 0000000B:CCCCCCCD
5384             emitcode("mov","c,acc.0");  // c = B
5385             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
5386             AccAXRrl1(x);               // BCCCCCCC:D0000000
5387             break;
5388         default :
5389             break;
5390     }
5391 }
5392
5393 /*-----------------------------------------------------------------*/
5394 /* AccAXRsh - right shift a:x known count (0..7)                   */
5395 /*-----------------------------------------------------------------*/
5396 static void AccAXRsh (char *x, int shCount)
5397 {   
5398     switch(shCount){
5399         case 0 :
5400             break;
5401         case 1 :
5402             CLRC;
5403             AccAXRrl1(x);               // 0->a:x
5404             break;
5405         case 2 :
5406             CLRC;
5407             AccAXRrl1(x);               // 0->a:x
5408             CLRC;
5409             AccAXRrl1(x);               // 0->a:x
5410             break;
5411         case 3 :
5412         case 4 :
5413         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5414             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
5415             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5416             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5417             emitcode("anl","a,#0x%02x",
5418                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5419             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5420             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5421             emitcode("anl","a,#0x%02x",
5422                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5423             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5424             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5425             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
5426             break;
5427         case 6 :                        // AABBBBBB:CCDDDDDD
5428             emitcode("mov","c,acc.7");
5429             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5430             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5431             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5432             emitcode("anl","a,#0x%02x",
5433                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5434             break;
5435         case 7 :                        // ABBBBBBB:CDDDDDDD
5436             emitcode("mov","c,acc.7");  // c = A
5437             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5438             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5439             emitcode("anl","a,#0x%02x",
5440                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5441             break;
5442         default :
5443             break;
5444     }
5445 }
5446
5447 /*-----------------------------------------------------------------*/
5448 /* AccAXRshS - right shift signed a:x known count (0..7)           */
5449 /*-----------------------------------------------------------------*/
5450 static void AccAXRshS (char *x, int shCount)
5451 {   
5452     symbol *tlbl ;
5453     switch(shCount){
5454         case 0 :
5455             break;
5456         case 1 :
5457             emitcode("mov","c,acc.7");
5458             AccAXRrl1(x);               // s->a:x
5459             break;
5460         case 2 :
5461             emitcode("mov","c,acc.7");
5462             AccAXRrl1(x);               // s->a:x
5463             emitcode("mov","c,acc.7");
5464             AccAXRrl1(x);               // s->a:x
5465             break;
5466         case 3 :
5467         case 4 :
5468         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5469             tlbl = newiTempLabel(NULL);
5470             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
5471             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5472             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5473             emitcode("anl","a,#0x%02x",
5474                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5475             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5476             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5477             emitcode("anl","a,#0x%02x",
5478                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5479             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5480             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5481             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
5482             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5483             emitcode("orl","a,#0x%02x",
5484                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
5485             emitcode("","%05d$:",tlbl->key+100);
5486             break;                      // SSSSAAAA:BBBCCCCC
5487         case 6 :                        // AABBBBBB:CCDDDDDD
5488             tlbl = newiTempLabel(NULL);
5489             emitcode("mov","c,acc.7");
5490             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5491             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5492             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5493             emitcode("anl","a,#0x%02x",
5494                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5495             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5496             emitcode("orl","a,#0x%02x",
5497                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
5498             emitcode("","%05d$:",tlbl->key+100);
5499             break;
5500         case 7 :                        // ABBBBBBB:CDDDDDDD
5501             tlbl = newiTempLabel(NULL);
5502             emitcode("mov","c,acc.7");  // c = A
5503             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5504             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5505             emitcode("anl","a,#0x%02x",
5506                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5507             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5508             emitcode("orl","a,#0x%02x",
5509                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
5510             emitcode("","%05d$:",tlbl->key+100);
5511             break;
5512         default :
5513             break;
5514     }
5515 }
5516
5517 /*-----------------------------------------------------------------*/
5518 /* shiftL2Left2Result - shift left two bytes from left to result   */
5519 /*-----------------------------------------------------------------*/
5520 static void shiftL2Left2Result (operand *left, int offl,
5521                                 operand *result, int offr, int shCount)
5522 {
5523     if(sameRegs(AOP(result), AOP(left)) &&
5524        ((offl + MSB16) == offr)){
5525         /* don't crash result[offr] */
5526         MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5527         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5528     } else {
5529         movLeft2Result(left,offl, result, offr, 0);
5530         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5531     }
5532     /* ax << shCount (x = lsb(result))*/
5533     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5534     aopPut(AOP(result),"a",offr+MSB16);
5535 }
5536
5537
5538 /*-----------------------------------------------------------------*/
5539 /* shiftR2Left2Result - shift right two bytes from left to result  */
5540 /*-----------------------------------------------------------------*/
5541 static void shiftR2Left2Result (operand *left, int offl,
5542                                 operand *result, int offr,
5543                                 int shCount, int sign)
5544 {
5545     if(sameRegs(AOP(result), AOP(left)) &&
5546        ((offl + MSB16) == offr)){
5547         /* don't crash result[offr] */
5548         MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5549         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5550     } else {
5551         movLeft2Result(left,offl, result, offr, 0);
5552         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5553     }
5554     /* a:x >> shCount (x = lsb(result))*/
5555     if(sign)
5556         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5557     else
5558         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5559     if(getDataSize(result) > 1)
5560         aopPut(AOP(result),"a",offr+MSB16);
5561 }
5562
5563 /*-----------------------------------------------------------------*/
5564 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5565 /*-----------------------------------------------------------------*/
5566 static void shiftLLeftOrResult (operand *left, int offl,
5567                                 operand *result, int offr, int shCount)
5568 {
5569     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5570     /* shift left accumulator */
5571     AccLsh(shCount);
5572     /* or with result */
5573     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5574     /* back to result */
5575     aopPut(AOP(result),"a",offr);
5576 }
5577
5578 /*-----------------------------------------------------------------*/
5579 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5580 /*-----------------------------------------------------------------*/
5581 static void shiftRLeftOrResult (operand *left, int offl,
5582                                 operand *result, int offr, int shCount)
5583 {
5584     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5585     /* shift right accumulator */
5586     AccRsh(shCount);
5587     /* or with result */
5588     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5589     /* back to result */
5590     aopPut(AOP(result),"a",offr);
5591 }
5592
5593 /*-----------------------------------------------------------------*/
5594 /* genlshOne - left shift a one byte quantity by known count       */
5595 /*-----------------------------------------------------------------*/
5596 static void genlshOne (operand *result, operand *left, int shCount)
5597 {       
5598     D(emitcode(";", "genlshOne "););
5599     shiftL1Left2Result(left, LSB, result, LSB, shCount);
5600 }
5601
5602 /*-----------------------------------------------------------------*/
5603 /* genlshTwo - left shift two bytes by known amount != 0           */
5604 /*-----------------------------------------------------------------*/
5605 static void genlshTwo (operand *result,operand *left, int shCount)
5606 {
5607     int size;
5608     
5609     D(emitcode(";", "genlshTwo "););
5610
5611     size = getDataSize(result);
5612
5613     /* if shCount >= 8 */
5614     if (shCount >= 8) {
5615         shCount -= 8 ;
5616
5617         if (size > 1){
5618             if (shCount)
5619                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5620             else 
5621                 movLeft2Result(left, LSB, result, MSB16, 0);
5622         }
5623         aopPut(AOP(result),zero,LSB);   
5624     }
5625
5626     /*  1 <= shCount <= 7 */
5627     else {  
5628         if(size == 1)
5629             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
5630         else 
5631             shiftL2Left2Result(left, LSB, result, LSB, shCount);
5632     }
5633 }
5634
5635 /*-----------------------------------------------------------------*/
5636 /* shiftLLong - shift left one long from left to result            */
5637 /* offl = LSB or MSB16                                             */
5638 /*-----------------------------------------------------------------*/
5639 static void shiftLLong (operand *left, operand *result, int offr )
5640 {
5641     char *l;
5642     int size = AOP_SIZE(result);
5643
5644     if(size >= LSB+offr){
5645         l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5646         MOVA(l);
5647         emitcode("add","a,acc");
5648         if (sameRegs(AOP(left),AOP(result)) && 
5649             size >= MSB16+offr && offr != LSB )
5650             emitcode("xch","a,%s",
5651                      aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5652         else        
5653             aopPut(AOP(result),"a",LSB+offr);
5654     }
5655
5656     if(size >= MSB16+offr){
5657         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5658             l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5659             MOVA(l);
5660         }
5661         emitcode("rlc","a");
5662         if (sameRegs(AOP(left),AOP(result)) && 
5663             size >= MSB24+offr && offr != LSB)
5664             emitcode("xch","a,%s",
5665                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5666         else        
5667             aopPut(AOP(result),"a",MSB16+offr);
5668     }
5669
5670     if(size >= MSB24+offr){
5671         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5672             l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5673             MOVA(l);
5674         }
5675         emitcode("rlc","a");
5676         if (sameRegs(AOP(left),AOP(result)) && 
5677             size >= MSB32+offr && offr != LSB )
5678             emitcode("xch","a,%s",
5679                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5680         else        
5681             aopPut(AOP(result),"a",MSB24+offr);
5682     }
5683
5684     if(size > MSB32+offr){
5685         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5686             l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5687             MOVA(l);    
5688         }
5689         emitcode("rlc","a");
5690         aopPut(AOP(result),"a",MSB32+offr);
5691     }
5692     if(offr != LSB)
5693         aopPut(AOP(result),zero,LSB);       
5694 }
5695
5696 /*-----------------------------------------------------------------*/
5697 /* genlshFour - shift four byte by a known amount != 0             */
5698 /*-----------------------------------------------------------------*/
5699 static void genlshFour (operand *result, operand *left, int shCount)
5700 {
5701     int size;
5702
5703     D(emitcode(";", "genlshFour "););
5704
5705     size = AOP_SIZE(result);
5706
5707     /* if shifting more that 3 bytes */
5708     if (shCount >= 24 ) {
5709         shCount -= 24;
5710         if (shCount)
5711             /* lowest order of left goes to the highest
5712             order of the destination */
5713             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5714         else
5715             movLeft2Result(left, LSB, result, MSB32, 0);
5716         aopPut(AOP(result),zero,LSB);
5717         aopPut(AOP(result),zero,MSB16);
5718         aopPut(AOP(result),zero,MSB32);
5719         return;
5720     }
5721
5722     /* more than two bytes */
5723     else if ( shCount >= 16 ) {
5724         /* lower order two bytes goes to higher order two bytes */
5725         shCount -= 16;
5726         /* if some more remaining */
5727         if (shCount)
5728             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5729         else {
5730             movLeft2Result(left, MSB16, result, MSB32, 0);
5731             movLeft2Result(left, LSB, result, MSB24, 0);
5732         }
5733         aopPut(AOP(result),zero,MSB16);
5734         aopPut(AOP(result),zero,LSB);
5735         return;
5736     }    
5737
5738     /* if more than 1 byte */
5739     else if ( shCount >= 8 ) {
5740         /* lower order three bytes goes to higher order  three bytes */
5741         shCount -= 8;
5742         if(size == 2){
5743             if(shCount)
5744                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5745             else
5746                 movLeft2Result(left, LSB, result, MSB16, 0);
5747         }
5748         else{   /* size = 4 */
5749             if(shCount == 0){
5750                 movLeft2Result(left, MSB24, result, MSB32, 0);
5751                 movLeft2Result(left, MSB16, result, MSB24, 0);
5752                 movLeft2Result(left, LSB, result, MSB16, 0);
5753                 aopPut(AOP(result),zero,LSB);
5754             }
5755             else if(shCount == 1)
5756                 shiftLLong(left, result, MSB16);
5757             else{
5758                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5759                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5760                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5761                 aopPut(AOP(result),zero,LSB);
5762             }
5763         }
5764     }
5765
5766     /* 1 <= shCount <= 7 */
5767     else if(shCount <= 2){
5768         shiftLLong(left, result, LSB);
5769         if(shCount == 2)
5770             shiftLLong(result, result, LSB);
5771     }
5772     /* 3 <= shCount <= 7, optimize */
5773     else{
5774         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5775         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5776         shiftL2Left2Result(left, LSB, result, LSB, shCount);
5777     }
5778 }
5779
5780 /*-----------------------------------------------------------------*/
5781 /* genLeftShiftLiteral - left shifting by known count              */
5782 /*-----------------------------------------------------------------*/
5783 static void genLeftShiftLiteral (operand *left,
5784                                  operand *right,
5785                                  operand *result,
5786                                  iCode *ic)
5787 {    
5788     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5789     int size;
5790
5791     D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5792
5793     freeAsmop(right,NULL,ic,TRUE);
5794
5795     aopOp(left,ic,FALSE, FALSE);
5796     aopOp(result,ic,FALSE, TRUE);
5797
5798     size = getSize(operandType(result));
5799
5800 #if VIEW_SIZE
5801     emitcode("; shift left ","result %d, left %d",size,
5802              AOP_SIZE(left));
5803 #endif
5804
5805     /* I suppose that the left size >= result size */
5806     if(shCount == 0){
5807         while(size--){
5808             movLeft2Result(left, size, result, size, 0);
5809         }
5810     }
5811
5812     else if(shCount >= (size * 8))
5813         while(size--)
5814             aopPut(AOP(result),zero,size);
5815     else{
5816         switch (size) {
5817             case 1:
5818                 genlshOne (result,left,shCount);
5819                 break;
5820
5821             case 2:
5822             case 3: /* bug: this is for generic pointers, I bet. */
5823                 genlshTwo (result,left,shCount);
5824                 break;
5825
5826             case 4:
5827                 genlshFour (result,left,shCount);
5828                 break;
5829         }
5830     }
5831     freeAsmop(left,NULL,ic,TRUE);
5832     freeAsmop(result,NULL,ic,TRUE);
5833 }
5834
5835 /*-----------------------------------------------------------------*/
5836 /* genLeftShift - generates code for left shifting                 */
5837 /*-----------------------------------------------------------------*/
5838 static void genLeftShift (iCode *ic)
5839 {
5840     operand *left,*right, *result;
5841     int size, offset;
5842     char *l;
5843     symbol *tlbl , *tlbl1;
5844
5845     D(emitcode(";", "genLeftShift "););
5846
5847     right = IC_RIGHT(ic);
5848     left  = IC_LEFT(ic);
5849     result = IC_RESULT(ic);
5850
5851     aopOp(right,ic,FALSE, FALSE);
5852
5853     #if 0
5854     /* if the shift count is known then do it 
5855     as efficiently as possible */
5856     if (AOP_TYPE(right) == AOP_LIT) {
5857         genLeftShiftLiteral (left,right,result,ic);
5858         return ;
5859     }
5860     #endif
5861
5862     /* shift count is unknown then we have to form 
5863     a loop get the loop count in B : Note: we take
5864     only the lower order byte since shifting
5865     more that 32 bits make no sense anyway, ( the
5866     largest size of an object can be only 32 bits ) */  
5867
5868     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
5869     emitcode("inc","b");
5870     freeAsmop (right,NULL,ic,TRUE);
5871     aopOp(left,ic,FALSE, FALSE);
5872     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5873
5874     /* now move the left to the result if they are not the
5875     same */
5876     if (!sameRegs(AOP(left),AOP(result)) && 
5877         AOP_SIZE(result) > 1) {
5878
5879         size = AOP_SIZE(result);
5880         offset=0;
5881         while (size--) {
5882             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
5883             if (*l == '@' && (IS_AOP_PREG(result))) {
5884
5885                 emitcode("mov","a,%s",l);
5886                 aopPut(AOP(result),"a",offset);
5887             } else
5888                 aopPut(AOP(result),l,offset);
5889             offset++;
5890         }
5891     }
5892
5893     tlbl = newiTempLabel(NULL);
5894     size = AOP_SIZE(result);
5895     offset = 0 ;   
5896     tlbl1 = newiTempLabel(NULL);
5897
5898     /* if it is only one byte then */
5899     if (size == 1) {
5900         symbol *tlbl1 = newiTempLabel(NULL);
5901
5902         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
5903         MOVA(l);
5904         emitcode("sjmp","%05d$",tlbl1->key+100); 
5905         emitcode("","%05d$:",tlbl->key+100);
5906         emitcode("add","a,acc");
5907         emitcode("","%05d$:",tlbl1->key+100);
5908         emitcode("djnz","b,%05d$",tlbl->key+100);      
5909         aopPut(AOP(result),"a",0);
5910         goto release ;
5911     }
5912     
5913     reAdjustPreg(AOP(result));    
5914     
5915     emitcode("sjmp","%05d$",tlbl1->key+100); 
5916     emitcode("","%05d$:",tlbl->key+100);    
5917     l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5918     MOVA(l);
5919     emitcode("add","a,acc");         
5920     aopPut(AOP(result),"a",offset++);
5921     while (--size) {
5922         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5923         MOVA(l);
5924         emitcode("rlc","a");         
5925         aopPut(AOP(result),"a",offset++);
5926     }
5927     reAdjustPreg(AOP(result));
5928
5929     emitcode("","%05d$:",tlbl1->key+100);
5930     emitcode("djnz","b,%05d$",tlbl->key+100);
5931 release:
5932     freeAsmop(left,NULL,ic,TRUE);
5933     freeAsmop(result,NULL,ic,TRUE);
5934 }
5935
5936 /*-----------------------------------------------------------------*/
5937 /* genrshOne - right shift a one byte quantity by known count      */
5938 /*-----------------------------------------------------------------*/
5939 static void genrshOne (operand *result, operand *left,
5940                        int shCount, int sign)
5941 {
5942     D(emitcode(";", "genrshOne"););
5943     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5944 }
5945
5946 /*-----------------------------------------------------------------*/
5947 /* genrshTwo - right shift two bytes by known amount != 0          */
5948 /*-----------------------------------------------------------------*/
5949 static void genrshTwo (operand *result,operand *left,
5950                        int shCount, int sign)
5951 {
5952     D(emitcode(";", "genrshTwo"););
5953
5954     /* if shCount >= 8 */
5955     if (shCount >= 8) {
5956         shCount -= 8 ;
5957         if (shCount)
5958             shiftR1Left2Result(left, MSB16, result, LSB,
5959                                shCount, sign);
5960         else 
5961             movLeft2Result(left, MSB16, result, LSB, sign);
5962         addSign(result, MSB16, sign);
5963     }
5964
5965     /*  1 <= shCount <= 7 */
5966     else
5967         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
5968 }
5969
5970 /*-----------------------------------------------------------------*/
5971 /* shiftRLong - shift right one long from left to result           */
5972 /* offl = LSB or MSB16                                             */
5973 /*-----------------------------------------------------------------*/
5974 static void shiftRLong (operand *left, int offl,
5975                         operand *result, int sign)
5976 {
5977     if(!sign)
5978         emitcode("clr","c");
5979     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
5980     if(sign)
5981         emitcode("mov","c,acc.7");
5982     emitcode("rrc","a");
5983     aopPut(AOP(result),"a",MSB32-offl);
5984     if(offl == MSB16)
5985         /* add sign of "a" */
5986         addSign(result, MSB32, sign);
5987
5988     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
5989     emitcode("rrc","a");
5990     aopPut(AOP(result),"a",MSB24-offl);
5991
5992     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
5993     emitcode("rrc","a");
5994     aopPut(AOP(result),"a",MSB16-offl);
5995
5996     if(offl == LSB){
5997         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
5998         emitcode("rrc","a");
5999         aopPut(AOP(result),"a",LSB);
6000     }
6001 }
6002
6003 /*-----------------------------------------------------------------*/
6004 /* genrshFour - shift four byte by a known amount != 0             */
6005 /*-----------------------------------------------------------------*/
6006 static void genrshFour (operand *result, operand *left,
6007                         int shCount, int sign)
6008 {
6009     D(emitcode(";", "genrshFour"););
6010     
6011     /* if shifting more that 3 bytes */
6012     if(shCount >= 24 ) {
6013         shCount -= 24;
6014         if(shCount)
6015             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6016         else
6017             movLeft2Result(left, MSB32, result, LSB, sign);
6018         addSign(result, MSB16, sign);
6019     }
6020     else if(shCount >= 16){
6021         shCount -= 16;
6022         if(shCount)
6023             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6024         else{
6025             movLeft2Result(left, MSB24, result, LSB, 0);
6026             movLeft2Result(left, MSB32, result, MSB16, sign);
6027         }
6028         addSign(result, MSB24, sign);
6029     }
6030     else if(shCount >= 8){
6031         shCount -= 8;
6032         if(shCount == 1)
6033             shiftRLong(left, MSB16, result, sign);
6034         else if(shCount == 0){
6035             movLeft2Result(left, MSB16, result, LSB, 0);
6036             movLeft2Result(left, MSB24, result, MSB16, 0);
6037             movLeft2Result(left, MSB32, result, MSB24, sign);
6038             addSign(result, MSB32, sign);
6039         }
6040         else{
6041             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6042             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6043             /* the last shift is signed */
6044             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6045             addSign(result, MSB32, sign);
6046         }
6047     }
6048     else{   /* 1 <= shCount <= 7 */
6049         if(shCount <= 2){
6050             shiftRLong(left, LSB, result, sign);
6051             if(shCount == 2)
6052                 shiftRLong(result, LSB, result, sign);
6053         }
6054         else{
6055             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6056             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6057             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6058         }
6059     }
6060 }
6061
6062 /*-----------------------------------------------------------------*/
6063 /* genRightShiftLiteral - right shifting by known count            */
6064 /*-----------------------------------------------------------------*/
6065 static void genRightShiftLiteral (operand *left,
6066                                   operand *right,
6067                                   operand *result,
6068                                   iCode *ic,
6069                                   int sign)
6070 {    
6071     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6072     int size;
6073
6074     D(emitcode(";", "genRightShiftLiteral"););
6075
6076     freeAsmop(right,NULL,ic,TRUE);
6077
6078     aopOp(left,ic,FALSE, FALSE);
6079     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6080
6081 #if VIEW_SIZE
6082     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6083              AOP_SIZE(left));
6084 #endif
6085
6086     size = getDataSize(left);
6087     /* test the LEFT size !!! */
6088
6089     /* I suppose that the left size >= result size */
6090     if(shCount == 0){
6091         size = getDataSize(result);
6092         while(size--)
6093             movLeft2Result(left, size, result, size, 0);
6094     }
6095
6096     else if(shCount >= (size * 8)){
6097         if(sign)
6098             /* get sign in acc.7 */
6099             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6100         addSign(result, LSB, sign);
6101     } else{
6102         switch (size) {
6103             case 1:
6104                 genrshOne (result,left,shCount,sign);
6105                 break;
6106
6107             case 2:
6108                 genrshTwo (result,left,shCount,sign);
6109                 break;
6110
6111             case 4:
6112                 genrshFour (result,left,shCount,sign);
6113                 break;
6114             default :
6115                 break;
6116         }
6117
6118         freeAsmop(left,NULL,ic,TRUE);
6119         freeAsmop(result,NULL,ic,TRUE);
6120     }
6121 }
6122
6123 /*-----------------------------------------------------------------*/
6124 /* genSignedRightShift - right shift of signed number              */
6125 /*-----------------------------------------------------------------*/
6126 static void genSignedRightShift (iCode *ic)
6127 {
6128     operand *right, *left, *result;
6129     int size, offset;
6130     char *l;
6131     symbol *tlbl, *tlbl1 ;
6132
6133     D(emitcode(";", "genSignedRightShift "););
6134
6135     /* we do it the hard way put the shift count in b
6136     and loop thru preserving the sign */
6137
6138     right = IC_RIGHT(ic);
6139     left  = IC_LEFT(ic);
6140     result = IC_RESULT(ic);
6141
6142     aopOp(right,ic,FALSE, FALSE);
6143
6144     #if 0
6145     if ( AOP_TYPE(right) == AOP_LIT) {
6146         genRightShiftLiteral (left,right,result,ic,1);
6147         return ;
6148     }
6149     #endif
6150         /* shift count is unknown then we have to form 
6151        a loop get the loop count in B : Note: we take
6152        only the lower order byte since shifting
6153        more that 32 bits make no sense anyway, ( the
6154        largest size of an object can be only 32 bits ) */  
6155
6156     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6157     emitcode("inc","b");
6158     freeAsmop (right,NULL,ic,TRUE);
6159     aopOp(left,ic,FALSE, FALSE);
6160     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6161
6162     /* now move the left to the result if they are not the
6163     same */
6164     if (!sameRegs(AOP(left),AOP(result)) && 
6165         AOP_SIZE(result) > 1) {
6166
6167         size = AOP_SIZE(result);
6168         offset=0;
6169         while (size--) {
6170             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6171             if (*l == '@' && IS_AOP_PREG(result)) {
6172
6173                 emitcode("mov","a,%s",l);
6174                 aopPut(AOP(result),"a",offset);
6175             } else
6176                 aopPut(AOP(result),l,offset);
6177             offset++;
6178         }
6179     }
6180
6181     /* mov the highest order bit to OVR */    
6182     tlbl = newiTempLabel(NULL);
6183     tlbl1= newiTempLabel(NULL);
6184
6185     size = AOP_SIZE(result);
6186     offset = size - 1;
6187     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6188     emitcode("rlc","a");
6189     emitcode("mov","ov,c");
6190     /* if it is only one byte then */
6191     if (size == 1) {
6192         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6193         MOVA(l);
6194         emitcode("sjmp","%05d$",tlbl1->key+100);
6195         emitcode("","%05d$:",tlbl->key+100);
6196         emitcode("mov","c,ov");
6197         emitcode("rrc","a");
6198         emitcode("","%05d$:",tlbl1->key+100);
6199         emitcode("djnz","b,%05d$",tlbl->key+100);
6200         aopPut(AOP(result),"a",0);
6201         goto release ;
6202     }
6203
6204     reAdjustPreg(AOP(result));
6205     emitcode("sjmp","%05d$",tlbl1->key+100);
6206     emitcode("","%05d$:",tlbl->key+100);    
6207     emitcode("mov","c,ov");
6208     while (size--) {
6209         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6210         MOVA(l);
6211         emitcode("rrc","a");         
6212         aopPut(AOP(result),"a",offset--);
6213     }
6214     reAdjustPreg(AOP(result));
6215     emitcode("","%05d$:",tlbl1->key+100);
6216     emitcode("djnz","b,%05d$",tlbl->key+100);
6217
6218 release:
6219     freeAsmop(left,NULL,ic,TRUE);
6220     freeAsmop(result,NULL,ic,TRUE);
6221 }
6222
6223 /*-----------------------------------------------------------------*/
6224 /* genRightShift - generate code for right shifting                */
6225 /*-----------------------------------------------------------------*/
6226 static void genRightShift (iCode *ic)
6227 {
6228     operand *right, *left, *result;
6229     link *retype ;
6230     int size, offset;
6231     char *l;
6232     symbol *tlbl, *tlbl1 ;
6233
6234     D(emitcode(";", "genRightShift "););
6235
6236     /* if signed then we do it the hard way preserve the
6237     sign bit moving it inwards */
6238     retype = getSpec(operandType(IC_RESULT(ic)));
6239
6240     if (!SPEC_USIGN(retype)) {
6241         genSignedRightShift (ic);
6242         return ;
6243     }
6244
6245     /* signed & unsigned types are treated the same : i.e. the
6246     signed is NOT propagated inwards : quoting from the
6247     ANSI - standard : "for E1 >> E2, is equivalent to division
6248     by 2**E2 if unsigned or if it has a non-negative value,
6249     otherwise the result is implementation defined ", MY definition
6250     is that the sign does not get propagated */
6251
6252     right = IC_RIGHT(ic);
6253     left  = IC_LEFT(ic);
6254     result = IC_RESULT(ic);
6255
6256     aopOp(right,ic,FALSE, FALSE);
6257
6258     #if 0
6259     /* if the shift count is known then do it 
6260     as efficiently as possible */
6261     if (AOP_TYPE(right) == AOP_LIT) {
6262         genRightShiftLiteral (left,right,result,ic, 0);
6263         return ;
6264     }
6265     #endif
6266
6267     /* shift count is unknown then we have to form 
6268     a loop get the loop count in B : Note: we take
6269     only the lower order byte since shifting
6270     more that 32 bits make no sense anyway, ( the
6271     largest size of an object can be only 32 bits ) */  
6272
6273     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6274     emitcode("inc","b");
6275     freeAsmop (right,NULL,ic,TRUE);
6276     aopOp(left,ic,FALSE, FALSE);
6277     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6278
6279     /* now move the left to the result if they are not the
6280     same */
6281     if (!sameRegs(AOP(left),AOP(result)) && 
6282         AOP_SIZE(result) > 1) {
6283
6284         size = AOP_SIZE(result);
6285         offset=0;
6286         while (size--) {
6287             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6288             if (*l == '@' && IS_AOP_PREG(result)) {
6289
6290                 emitcode("mov","a,%s",l);
6291                 aopPut(AOP(result),"a",offset);
6292             } else
6293                 aopPut(AOP(result),l,offset);
6294             offset++;
6295         }
6296     }
6297
6298     tlbl = newiTempLabel(NULL);
6299     tlbl1= newiTempLabel(NULL);
6300     size = AOP_SIZE(result);
6301     offset = size - 1;
6302
6303     /* if it is only one byte then */
6304     if (size == 1) {
6305         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6306         MOVA(l);
6307         emitcode("sjmp","%05d$",tlbl1->key+100);
6308         emitcode("","%05d$:",tlbl->key+100);
6309         CLRC;
6310         emitcode("rrc","a");
6311         emitcode("","%05d$:",tlbl1->key+100);
6312         emitcode("djnz","b,%05d$",tlbl->key+100);
6313         aopPut(AOP(result),"a",0);
6314         goto release ;
6315     }
6316
6317     reAdjustPreg(AOP(result));
6318     emitcode("sjmp","%05d$",tlbl1->key+100);
6319     emitcode("","%05d$:",tlbl->key+100);    
6320     CLRC;
6321     while (size--) {
6322         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6323         MOVA(l);
6324         emitcode("rrc","a");         
6325         aopPut(AOP(result),"a",offset--);
6326     }
6327     reAdjustPreg(AOP(result));
6328
6329     emitcode("","%05d$:",tlbl1->key+100);
6330     emitcode("djnz","b,%05d$",tlbl->key+100);
6331
6332 release:
6333     freeAsmop(left,NULL,ic,TRUE);
6334     freeAsmop(result,NULL,ic,TRUE);
6335 }
6336
6337 /*-----------------------------------------------------------------*/
6338 /* genUnpackBits - generates code for unpacking bits               */
6339 /*-----------------------------------------------------------------*/
6340 static void genUnpackBits (operand *result, char *rname, int ptype)
6341 {    
6342     int shCnt ;
6343     int rlen = 0 ;
6344     link *etype;
6345     int offset = 0 ;
6346
6347     D(emitcode(";", "genUnpackBits "););
6348
6349     etype = getSpec(operandType(result));
6350
6351     /* read the first byte  */
6352     switch (ptype) {
6353
6354     case POINTER:
6355     case IPOINTER:
6356         emitcode("mov","a,@%s",rname);
6357         break;
6358         
6359     case PPOINTER:
6360         emitcode("movx","a,@%s",rname);
6361         break;
6362         
6363     case FPOINTER:
6364         emitcode("movx","a,@dptr");
6365         break;
6366
6367     case CPOINTER:
6368         emitcode("clr","a");
6369         emitcode("movc","a","@a+dptr");
6370         break;
6371
6372     case GPOINTER:
6373         emitcode("lcall","__gptrget");
6374         break;
6375     }
6376
6377     /* if we have bitdisplacement then it fits   */
6378     /* into this byte completely or if length is */
6379     /* less than a byte                          */
6380     if ((shCnt = SPEC_BSTR(etype)) || 
6381         (SPEC_BLEN(etype) <= 8))  {
6382
6383         /* shift right acc */
6384         AccRsh(shCnt);
6385
6386         emitcode("anl","a,#0x%02x",
6387                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6388         aopPut(AOP(result),"a",offset);
6389         return ;
6390     }
6391
6392     /* bit field did not fit in a byte  */
6393     rlen = SPEC_BLEN(etype) - 8;
6394     aopPut(AOP(result),"a",offset++);
6395
6396     while (1)  {
6397
6398         switch (ptype) {
6399         case POINTER:
6400         case IPOINTER:
6401             emitcode("inc","%s",rname);
6402             emitcode("mov","a,@%s",rname);
6403             break;
6404             
6405         case PPOINTER:
6406             emitcode("inc","%s",rname);
6407             emitcode("movx","a,@%s",rname);
6408             break;
6409
6410         case FPOINTER:
6411             emitcode("inc","dptr");
6412             emitcode("movx","a,@dptr");
6413             break;
6414             
6415         case CPOINTER:
6416             emitcode("clr","a");
6417             emitcode("inc","dptr");
6418             emitcode("movc","a","@a+dptr");
6419             break;
6420             
6421         case GPOINTER:
6422             emitcode("inc","dptr");
6423             emitcode("lcall","__gptrget");
6424             break;
6425         }
6426
6427         rlen -= 8;            
6428         /* if we are done */
6429         if ( rlen <= 0 )
6430             break ;
6431         
6432         aopPut(AOP(result),"a",offset++);
6433                               
6434     }
6435     
6436     if (rlen) {
6437         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6438         aopPut(AOP(result),"a",offset);        
6439     }
6440     
6441     return ;
6442 }
6443
6444
6445 /*-----------------------------------------------------------------*/
6446 /* genDataPointerGet - generates code when ptr offset is known     */
6447 /*-----------------------------------------------------------------*/
6448 static void genDataPointerGet (operand *left, 
6449                                operand *result, 
6450                                iCode *ic)
6451 {
6452     char *l;
6453     char buffer[256];
6454     int size , offset = 0;
6455     aopOp(result,ic,TRUE, FALSE);
6456
6457     /* get the string representation of the name */
6458     l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6459     size = AOP_SIZE(result);
6460     while (size--) {
6461         if (offset)
6462             sprintf(buffer,"(%s + %d)",l+1,offset);
6463         else
6464             sprintf(buffer,"%s",l+1);
6465         aopPut(AOP(result),buffer,offset++);
6466     }
6467
6468     freeAsmop(left,NULL,ic,TRUE);
6469     freeAsmop(result,NULL,ic,TRUE);
6470 }
6471
6472 /*-----------------------------------------------------------------*/
6473 /* genNearPointerGet - emitcode for near pointer fetch             */
6474 /*-----------------------------------------------------------------*/
6475 static void genNearPointerGet (operand *left, 
6476                                operand *result, 
6477                                iCode *ic)
6478 {
6479     asmop *aop = NULL;
6480     regs *preg = NULL ;
6481     char *rname ;
6482     link *rtype, *retype;
6483     link *ltype = operandType(left);    
6484     char buffer[80];
6485
6486     rtype = operandType(result);
6487     retype= getSpec(rtype);
6488     
6489     aopOp(left,ic,FALSE, FALSE);
6490     
6491     /* if left is rematerialisable and
6492        result is not bit variable type and
6493        the left is pointer to data space i.e
6494        lower 128 bytes of space */
6495     if (AOP_TYPE(left) == AOP_IMMD &&
6496         !IS_BITVAR(retype)         &&
6497         DCL_TYPE(ltype) == POINTER) {
6498         genDataPointerGet (left,result,ic);
6499         return ;
6500     }
6501     
6502         /* if the value is already in a pointer register
6503        then don't need anything more */
6504     if (!AOP_INPREG(AOP(left))) {
6505         /* otherwise get a free pointer register */
6506         aop = newAsmop(0);
6507         preg = getFreePtr(ic,&aop,FALSE);
6508         emitcode("mov","%s,%s",
6509                 preg->name,
6510                 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6511         rname = preg->name ;
6512     } else
6513         rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6514     
6515     freeAsmop(left,NULL,ic,TRUE);
6516     aopOp (result,ic,FALSE, FALSE);
6517     
6518       /* if bitfield then unpack the bits */
6519     if (IS_BITVAR(retype)) 
6520         genUnpackBits (result,rname,POINTER);
6521     else {
6522         /* we have can just get the values */
6523         int size = AOP_SIZE(result);
6524         int offset = 0 ;        
6525         
6526         while (size--) {
6527             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6528
6529                 emitcode("mov","a,@%s",rname);
6530                 aopPut(AOP(result),"a",offset);
6531             } else {
6532                 sprintf(buffer,"@%s",rname);
6533                 aopPut(AOP(result),buffer,offset);
6534             }
6535             offset++ ;
6536             if (size)
6537                 emitcode("inc","%s",rname);
6538         }
6539     }
6540
6541     /* now some housekeeping stuff */
6542     if (aop) {
6543         /* we had to allocate for this iCode */
6544         freeAsmop(NULL,aop,ic,TRUE);
6545     } else { 
6546         /* we did not allocate which means left
6547            already in a pointer register, then
6548            if size > 0 && this could be used again
6549            we have to point it back to where it 
6550            belongs */
6551         if (AOP_SIZE(result) > 1 &&
6552             !OP_SYMBOL(left)->remat &&
6553             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6554               ic->depth )) {
6555             int size = AOP_SIZE(result) - 1;
6556             while (size--)
6557                 emitcode("dec","%s",rname);
6558         }
6559     }
6560
6561     /* done */
6562     freeAsmop(result,NULL,ic,TRUE);
6563      
6564 }
6565
6566 /*-----------------------------------------------------------------*/
6567 /* genPagedPointerGet - emitcode for paged pointer fetch           */
6568 /*-----------------------------------------------------------------*/
6569 static void genPagedPointerGet (operand *left, 
6570                                operand *result, 
6571                                iCode *ic)
6572 {
6573     asmop *aop = NULL;
6574     regs *preg = NULL ;
6575     char *rname ;
6576     link *rtype, *retype;    
6577
6578     rtype = operandType(result);
6579     retype= getSpec(rtype);
6580     
6581     aopOp(left,ic,FALSE, FALSE);
6582
6583   /* if the value is already in a pointer register
6584        then don't need anything more */
6585     if (!AOP_INPREG(AOP(left))) {
6586         /* otherwise get a free pointer register */
6587         aop = newAsmop(0);
6588         preg = getFreePtr(ic,&aop,FALSE);
6589         emitcode("mov","%s,%s",
6590                 preg->name,
6591                 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6592         rname = preg->name ;
6593     } else
6594         rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6595     
6596     freeAsmop(left,NULL,ic,TRUE);
6597     aopOp (result,ic,FALSE, FALSE);
6598
6599     /* if bitfield then unpack the bits */
6600     if (IS_BITVAR(retype)) 
6601         genUnpackBits (result,rname,PPOINTER);
6602     else {
6603         /* we have can just get the values */
6604         int size = AOP_SIZE(result);
6605         int offset = 0 ;        
6606         
6607         while (size--) {
6608             
6609             emitcode("movx","a,@%s",rname);
6610             aopPut(AOP(result),"a",offset);
6611             
6612             offset++ ;
6613             
6614             if (size)
6615                 emitcode("inc","%s",rname);
6616         }
6617     }
6618
6619     /* now some housekeeping stuff */
6620     if (aop) {
6621         /* we had to allocate for this iCode */
6622         freeAsmop(NULL,aop,ic,TRUE);
6623     } else { 
6624         /* we did not allocate which means left
6625            already in a pointer register, then
6626            if size > 0 && this could be used again
6627            we have to point it back to where it 
6628            belongs */
6629         if (AOP_SIZE(result) > 1 &&
6630             !OP_SYMBOL(left)->remat &&
6631             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6632               ic->depth )) {
6633             int size = AOP_SIZE(result) - 1;
6634             while (size--)
6635                 emitcode("dec","%s",rname);
6636         }
6637     }
6638
6639     /* done */
6640     freeAsmop(result,NULL,ic,TRUE);
6641     
6642         
6643 }
6644
6645 /*-----------------------------------------------------------------*/
6646 /* genFarPointerGet - gget value from far space                    */
6647 /*-----------------------------------------------------------------*/
6648 static void genFarPointerGet (operand *left,
6649                               operand *result, iCode *ic)
6650 {
6651     int size, offset ;
6652     link *retype = getSpec(operandType(result));
6653
6654     D(emitcode(";", "genFarPointerGet"););
6655
6656     aopOp(left,ic,FALSE, FALSE);
6657
6658     /* if the operand is already in dptr 
6659     then we do nothing else we move the value to dptr */
6660     if (AOP_TYPE(left) != AOP_STR) {
6661         /* if this is remateriazable */
6662         if (AOP_TYPE(left) == AOP_IMMD)
6663         {
6664             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6665         }
6666         else 
6667         { 
6668             /* we need to get it byte by byte */
6669             if (AOP_TYPE(left) != AOP_DPTR)
6670             {
6671                 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6672                 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6673                 if (options.model == MODEL_FLAT24)
6674                 {
6675                     emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6676                 }
6677             }
6678             else
6679             {
6680                  /* We need to generate a load to DPTR indirect through DPTR. */
6681                  D(emitcode(";", "genFarPointerGet -- indirection special case."););
6682                  emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6683                  emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6684                  emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6685                  emitcode("pop", "dph");
6686                  emitcode("pop", "dpl");
6687             }
6688         }
6689     }
6690     /* so dptr know contains the address */
6691     freeAsmop(left,NULL,ic,TRUE);
6692     aopOp(result,ic,FALSE, TRUE);
6693
6694     /* if bit then unpack */
6695     if (IS_BITVAR(retype)) 
6696         genUnpackBits(result,"dptr",FPOINTER);
6697     else {
6698         size = AOP_SIZE(result);
6699         offset = 0 ;
6700
6701         while (size--) {
6702             emitcode("movx","a,@dptr");
6703             aopPut(AOP(result),"a",offset++);
6704             if (size)
6705                 emitcode("inc","dptr");
6706         }
6707     }
6708
6709     freeAsmop(result,NULL,ic,TRUE);
6710 }
6711
6712 /*-----------------------------------------------------------------*/
6713 /* emitcodePointerGet - gget value from code space                  */
6714 /*-----------------------------------------------------------------*/
6715 static void emitcodePointerGet (operand *left,
6716                                 operand *result, iCode *ic)
6717 {
6718     int size, offset ;
6719     link *retype = getSpec(operandType(result));
6720
6721     aopOp(left,ic,FALSE, FALSE);
6722
6723     /* if the operand is already in dptr 
6724     then we do nothing else we move the value to dptr */
6725     if (AOP_TYPE(left) != AOP_STR) {
6726         /* if this is remateriazable */
6727         if (AOP_TYPE(left) == AOP_IMMD)
6728             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6729         else { /* we need to get it byte by byte */
6730             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6731             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6732             if (options.model == MODEL_FLAT24)
6733             {
6734                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6735             }
6736         }
6737     }
6738     /* so dptr know contains the address */
6739     freeAsmop(left,NULL,ic,TRUE);
6740     aopOp(result,ic,FALSE, FALSE);
6741
6742     /* if bit then unpack */
6743     if (IS_BITVAR(retype)) 
6744         genUnpackBits(result,"dptr",CPOINTER);
6745     else {
6746         size = AOP_SIZE(result);
6747         offset = 0 ;
6748
6749         while (size--) {
6750             emitcode("clr","a");
6751             emitcode("movc","a,@a+dptr");
6752             aopPut(AOP(result),"a",offset++);
6753             if (size)
6754                 emitcode("inc","dptr");
6755         }
6756     }
6757
6758     freeAsmop(result,NULL,ic,TRUE);
6759 }
6760
6761 /*-----------------------------------------------------------------*/
6762 /* genGenPointerGet - gget value from generic pointer space        */
6763 /*-----------------------------------------------------------------*/
6764 static void genGenPointerGet (operand *left,
6765                               operand *result, iCode *ic)
6766 {
6767     int size, offset ;
6768     link *retype = getSpec(operandType(result));
6769
6770     aopOp(left,ic,FALSE, TRUE);
6771
6772     /* if the operand is already in dptr 
6773     then we do nothing else we move the value to dptr */
6774     if (AOP_TYPE(left) != AOP_STR) {
6775         /* if this is remateriazable */
6776         if (AOP_TYPE(left) == AOP_IMMD) {
6777             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6778             emitcode("mov","b,#%d",pointerCode(retype));
6779         }
6780         else { /* we need to get it byte by byte */
6781             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6782             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6783             if (options.model == MODEL_FLAT24)
6784             {
6785                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6786                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
6787             }
6788             else
6789             {
6790                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6791             }
6792         }
6793     }
6794     /* so dptr know contains the address */
6795     freeAsmop(left,NULL,ic,TRUE);
6796     aopOp(result,ic,FALSE, TRUE);
6797
6798     /* if bit then unpack */
6799     if (IS_BITVAR(retype)) 
6800         genUnpackBits(result,"dptr",GPOINTER);
6801     else {
6802         size = AOP_SIZE(result);
6803         offset = 0 ;
6804
6805         while (size--) {
6806             emitcode("lcall","__gptrget");
6807             aopPut(AOP(result),"a",offset++);
6808             if (size)
6809                 emitcode("inc","dptr");
6810         }
6811     }
6812
6813     freeAsmop(result,NULL,ic,TRUE);
6814 }
6815
6816 /*-----------------------------------------------------------------*/
6817 /* genPointerGet - generate code for pointer get                   */
6818 /*-----------------------------------------------------------------*/
6819 static void genPointerGet (iCode *ic)
6820 {
6821     operand *left, *result ;
6822     link *type, *etype;
6823     int p_type;
6824
6825     D(emitcode(";", "genPointerGet "););
6826
6827     left = IC_LEFT(ic);
6828     result = IC_RESULT(ic) ;
6829
6830     /* depending on the type of pointer we need to
6831     move it to the correct pointer register */
6832     type = operandType(left);
6833     etype = getSpec(type);
6834     /* if left is of type of pointer then it is simple */
6835     if (IS_PTR(type) && !IS_FUNC(type->next)) 
6836         p_type = DCL_TYPE(type);
6837     else {
6838         /* we have to go by the storage class */
6839         p_type = PTR_TYPE(SPEC_OCLS(etype));
6840
6841 /*      if (SPEC_OCLS(etype)->codesp ) { */
6842 /*          p_type = CPOINTER ;  */
6843 /*      } */
6844 /*      else */
6845 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6846 /*              p_type = FPOINTER ; */
6847 /*          else */
6848 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6849 /*                  p_type = PPOINTER; */
6850 /*              else */
6851 /*                  if (SPEC_OCLS(etype) == idata ) */
6852 /*                      p_type = IPOINTER; */
6853 /*                  else */
6854 /*                      p_type = POINTER ; */
6855     }
6856
6857     /* now that we have the pointer type we assign
6858     the pointer values */
6859     switch (p_type) {
6860
6861     case POINTER:       
6862     case IPOINTER:
6863         genNearPointerGet (left,result,ic);
6864         break;
6865
6866     case PPOINTER:
6867         genPagedPointerGet(left,result,ic);
6868         break;
6869
6870     case FPOINTER:
6871         genFarPointerGet (left,result,ic);
6872         break;
6873
6874     case CPOINTER:
6875         emitcodePointerGet (left,result,ic);
6876         break;
6877
6878     case GPOINTER:
6879         genGenPointerGet (left,result,ic);
6880         break;
6881     }
6882
6883 }
6884
6885 /*-----------------------------------------------------------------*/
6886 /* genPackBits - generates code for packed bit storage             */
6887 /*-----------------------------------------------------------------*/
6888 static void genPackBits (link    *etype ,
6889                          operand *right ,
6890                          char *rname, int p_type)
6891 {
6892     int shCount = 0 ;
6893     int offset = 0  ;
6894     int rLen = 0 ;
6895     int blen, bstr ;   
6896     char *l ;
6897
6898     blen = SPEC_BLEN(etype);
6899     bstr = SPEC_BSTR(etype);
6900
6901     l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
6902     MOVA(l);   
6903
6904     /* if the bit lenth is less than or    */
6905     /* it exactly fits a byte then         */
6906     if (SPEC_BLEN(etype) <= 8 )  {
6907         shCount = SPEC_BSTR(etype) ;
6908
6909         /* shift left acc */
6910         AccLsh(shCount);
6911
6912         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6913
6914
6915             switch (p_type) {
6916                 case POINTER:
6917                     emitcode ("mov","b,a");
6918                     emitcode("mov","a,@%s",rname);
6919                     break;
6920
6921                 case FPOINTER:
6922                     emitcode ("mov","b,a");
6923                     emitcode("movx","a,@dptr");
6924                     break;
6925
6926                 case GPOINTER:
6927                     emitcode ("push","b");
6928                     emitcode ("push","acc");
6929                     emitcode ("lcall","__gptrget");
6930                     emitcode ("pop","b");
6931                     break;
6932             }
6933
6934             emitcode ("anl","a,#0x%02x",(unsigned char)
6935                       ((unsigned char)(0xFF << (blen+bstr)) | 
6936                        (unsigned char)(0xFF >> (8-bstr)) ) );
6937             emitcode ("orl","a,b");
6938             if (p_type == GPOINTER)
6939                 emitcode("pop","b");
6940         }
6941     }
6942
6943     switch (p_type) {
6944         case POINTER:
6945             emitcode("mov","@%s,a",rname);
6946             break;
6947
6948         case FPOINTER:
6949             emitcode("movx","@dptr,a");
6950             break;
6951
6952         case GPOINTER:
6953             emitcode("lcall","__gptrput");
6954             break;
6955     }
6956
6957     /* if we r done */
6958     if ( SPEC_BLEN(etype) <= 8 )
6959         return ;
6960
6961     emitcode("inc","%s",rname);
6962     rLen = SPEC_BLEN(etype) ;     
6963
6964     /* now generate for lengths greater than one byte */
6965     while (1) {
6966
6967         l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
6968
6969         rLen -= 8 ;
6970         if (rLen <= 0 )
6971             break ;
6972
6973         switch (p_type) {
6974             case POINTER:
6975                 if (*l == '@') {
6976                     MOVA(l);
6977                     emitcode("mov","@%s,a",rname);
6978                 } else
6979                     emitcode("mov","@%s,%s",rname,l);
6980                 break;
6981
6982             case FPOINTER:
6983                 MOVA(l);
6984                 emitcode("movx","@dptr,a");
6985                 break;
6986
6987             case GPOINTER:
6988                 MOVA(l);
6989                 emitcode("lcall","__gptrput");
6990                 break;  
6991         }   
6992         emitcode ("inc","%s",rname);
6993     }
6994
6995     MOVA(l);
6996
6997     /* last last was not complete */
6998     if (rLen)   {
6999         /* save the byte & read byte */
7000         switch (p_type) {
7001             case POINTER:
7002                 emitcode ("mov","b,a");
7003                 emitcode("mov","a,@%s",rname);
7004                 break;
7005
7006             case FPOINTER:
7007                 emitcode ("mov","b,a");
7008                 emitcode("movx","a,@dptr");
7009                 break;
7010
7011             case GPOINTER:
7012                 emitcode ("push","b");
7013                 emitcode ("push","acc");
7014                 emitcode ("lcall","__gptrget");
7015                 emitcode ("pop","b");
7016                 break;
7017         }
7018
7019         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7020         emitcode ("orl","a,b");
7021     }
7022
7023     if (p_type == GPOINTER)
7024         emitcode("pop","b");
7025
7026     switch (p_type) {
7027
7028     case POINTER:
7029         emitcode("mov","@%s,a",rname);
7030         break;
7031         
7032     case FPOINTER:
7033         emitcode("movx","@dptr,a");
7034         break;
7035         
7036     case GPOINTER:
7037         emitcode("lcall","__gptrput");
7038         break;                  
7039     }
7040 }
7041 /*-----------------------------------------------------------------*/
7042 /* genDataPointerSet - remat pointer to data space                 */
7043 /*-----------------------------------------------------------------*/
7044 static void genDataPointerSet(operand *right,
7045                               operand *result,
7046                               iCode *ic)
7047 {
7048     int size, offset = 0 ;
7049     char *l, buffer[256];
7050
7051     aopOp(right,ic,FALSE, FALSE);
7052     
7053     l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7054     size = AOP_SIZE(right);
7055     while (size--) {
7056         if (offset)
7057             sprintf(buffer,"(%s + %d)",l+1,offset);
7058         else
7059             sprintf(buffer,"%s",l+1);
7060         emitcode("mov","%s,%s",buffer,
7061                  aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7062     }
7063
7064     freeAsmop(right,NULL,ic,TRUE);
7065     freeAsmop(result,NULL,ic,TRUE);
7066 }
7067
7068 /*-----------------------------------------------------------------*/
7069 /* genNearPointerSet - emitcode for near pointer put                */
7070 /*-----------------------------------------------------------------*/
7071 static void genNearPointerSet (operand *right,
7072                                operand *result, 
7073                                iCode *ic)
7074 {
7075     asmop *aop = NULL;
7076     regs *preg = NULL ;
7077     char *rname , *l;
7078     link *retype;
7079     link *ptype = operandType(result);
7080     
7081     retype= getSpec(operandType(right));
7082
7083     aopOp(result,ic,FALSE, FALSE);
7084     
7085     /* if the result is rematerializable &
7086        in data space & not a bit variable */
7087     if (AOP_TYPE(result) == AOP_IMMD &&
7088         DCL_TYPE(ptype) == POINTER   &&
7089         !IS_BITVAR(retype)) {
7090         genDataPointerSet (right,result,ic);
7091         return;
7092     }
7093
7094     /* if the value is already in a pointer register
7095     then don't need anything more */
7096     if (!AOP_INPREG(AOP(result))) {
7097         /* otherwise get a free pointer register */
7098         aop = newAsmop(0);
7099         preg = getFreePtr(ic,&aop,FALSE);
7100         emitcode("mov","%s,%s",
7101                  preg->name,
7102                  aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7103         rname = preg->name ;
7104     } else
7105         rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7106
7107     freeAsmop(result,NULL,ic,TRUE);
7108     aopOp (right,ic,FALSE, FALSE);
7109
7110     /* if bitfield then unpack the bits */
7111     if (IS_BITVAR(retype)) 
7112         genPackBits (retype,right,rname,POINTER);
7113     else {
7114         /* we have can just get the values */
7115         int size = AOP_SIZE(right);
7116         int offset = 0 ;    
7117
7118         while (size--) {
7119             l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7120             if (*l == '@' ) {
7121                 MOVA(l);
7122                 emitcode("mov","@%s,a",rname);
7123             } else
7124                 emitcode("mov","@%s,%s",rname,l);
7125             if (size)
7126                 emitcode("inc","%s",rname);
7127             offset++;
7128         }
7129     }
7130
7131     /* now some housekeeping stuff */
7132     if (aop) {
7133         /* we had to allocate for this iCode */
7134         freeAsmop(NULL,aop,ic,TRUE);
7135     } else { 
7136         /* we did not allocate which means left
7137         already in a pointer register, then
7138         if size > 0 && this could be used again
7139         we have to point it back to where it 
7140         belongs */
7141         if (AOP_SIZE(right) > 1 &&
7142             !OP_SYMBOL(result)->remat &&
7143             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7144               ic->depth )) {
7145             int size = AOP_SIZE(right) - 1;
7146             while (size--)
7147                 emitcode("dec","%s",rname);
7148         }
7149     }
7150
7151     /* done */
7152     freeAsmop(right,NULL,ic,TRUE);
7153
7154
7155 }
7156
7157 /*-----------------------------------------------------------------*/
7158 /* genPagedPointerSet - emitcode for Paged pointer put             */
7159 /*-----------------------------------------------------------------*/
7160 static void genPagedPointerSet (operand *right,
7161                                operand *result, 
7162                                iCode *ic)
7163 {
7164     asmop *aop = NULL;
7165     regs *preg = NULL ;
7166     char *rname , *l;
7167     link *retype;
7168        
7169     retype= getSpec(operandType(right));
7170     
7171     aopOp(result,ic,FALSE, FALSE);
7172     
7173     /* if the value is already in a pointer register
7174        then don't need anything more */
7175     if (!AOP_INPREG(AOP(result))) {
7176         /* otherwise get a free pointer register */
7177         aop = newAsmop(0);
7178         preg = getFreePtr(ic,&aop,FALSE);
7179         emitcode("mov","%s,%s",
7180                 preg->name,
7181                 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7182         rname = preg->name ;
7183     } else
7184         rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7185     
7186     freeAsmop(result,NULL,ic,TRUE);
7187     aopOp (right,ic,FALSE, FALSE);
7188
7189     /* if bitfield then unpack the bits */
7190     if (IS_BITVAR(retype)) 
7191         genPackBits (retype,right,rname,PPOINTER);
7192     else {
7193         /* we have can just get the values */
7194         int size = AOP_SIZE(right);
7195         int offset = 0 ;        
7196         
7197         while (size--) {
7198             l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7199             
7200             MOVA(l);
7201             emitcode("movx","@%s,a",rname);
7202
7203             if (size)
7204                 emitcode("inc","%s",rname);
7205
7206             offset++;
7207         }
7208     }
7209     
7210     /* now some housekeeping stuff */
7211     if (aop) {
7212         /* we had to allocate for this iCode */
7213         freeAsmop(NULL,aop,ic,TRUE);
7214     } else { 
7215         /* we did not allocate which means left
7216            already in a pointer register, then
7217            if size > 0 && this could be used again
7218            we have to point it back to where it 
7219            belongs */
7220         if (AOP_SIZE(right) > 1 &&
7221             !OP_SYMBOL(result)->remat &&
7222             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7223               ic->depth )) {
7224             int size = AOP_SIZE(right) - 1;
7225             while (size--)
7226                 emitcode("dec","%s",rname);
7227         }
7228     }
7229
7230     /* done */
7231     freeAsmop(right,NULL,ic,TRUE);
7232     
7233         
7234 }
7235
7236 /*-----------------------------------------------------------------*/
7237 /* genFarPointerSet - set value from far space                     */
7238 /*-----------------------------------------------------------------*/
7239 static void genFarPointerSet (operand *right,
7240                               operand *result, iCode *ic)
7241 {
7242     int size, offset ;
7243     link *retype = getSpec(operandType(right));
7244
7245     aopOp(result,ic,FALSE, FALSE);
7246
7247     /* if the operand is already in dptr 
7248     then we do nothing else we move the value to dptr */
7249     if (AOP_TYPE(result) != AOP_STR) {
7250         /* if this is remateriazable */
7251         if (AOP_TYPE(result) == AOP_IMMD)
7252             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7253         else 
7254         {
7255             /* we need to get it byte by byte */
7256             if (AOP_TYPE(result) != AOP_DPTR)
7257             {
7258                 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7259                 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7260                 if (options.model == MODEL_FLAT24)
7261                 {
7262                     emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7263                 }
7264             }
7265             else
7266             {
7267                  /* We need to generate a load to DPTR indirect through DPTR. */
7268                  D(emitcode(";", "genFarPointerSet -- indirection special case."););
7269                  emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7270                  emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7271                  emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7272                  emitcode("pop", "dph");
7273                  emitcode("pop", "dpl");
7274             }
7275         }
7276     }
7277     /* so dptr know contains the address */
7278     freeAsmop(result,NULL,ic,TRUE);
7279     aopOp(right,ic,FALSE, TRUE);
7280
7281     /* if bit then unpack */
7282     if (IS_BITVAR(retype)) 
7283         genPackBits(retype,right,"dptr",FPOINTER);
7284     else {
7285         size = AOP_SIZE(right);
7286         offset = 0 ;
7287
7288         while (size--) {
7289             char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7290             MOVA(l);
7291             emitcode("movx","@dptr,a");
7292             if (size)
7293                 emitcode("inc","dptr");
7294         }
7295     }
7296
7297     freeAsmop(right,NULL,ic,TRUE);
7298 }
7299
7300 /*-----------------------------------------------------------------*/
7301 /* genGenPointerSet - set value from generic pointer space         */
7302 /*-----------------------------------------------------------------*/
7303 static void genGenPointerSet (operand *right,
7304                               operand *result, iCode *ic)
7305 {
7306     int size, offset ;
7307     link *retype = getSpec(operandType(right));
7308
7309     aopOp(result,ic,FALSE, TRUE);
7310
7311     /* if the operand is already in dptr 
7312     then we do nothing else we move the value to dptr */
7313     if (AOP_TYPE(result) != AOP_STR) {
7314         /* if this is remateriazable */
7315         if (AOP_TYPE(result) == AOP_IMMD) {
7316             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7317             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7318         }
7319         else { /* we need to get it byte by byte */
7320             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7321             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7322             if (options.model == MODEL_FLAT24)
7323             {
7324                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7325                emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7326             }
7327             else
7328             {
7329                 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7330             }
7331         }
7332     }
7333     /* so dptr know contains the address */
7334     freeAsmop(result,NULL,ic,TRUE);
7335     aopOp(right,ic,FALSE, TRUE);
7336
7337     /* if bit then unpack */
7338     if (IS_BITVAR(retype)) 
7339         genPackBits(retype,right,"dptr",GPOINTER);
7340     else {
7341         size = AOP_SIZE(right);
7342         offset = 0 ;
7343
7344         while (size--) {
7345             char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7346             MOVA(l);
7347             emitcode("lcall","__gptrput");
7348             if (size)
7349                 emitcode("inc","dptr");
7350         }
7351     }
7352
7353     freeAsmop(right,NULL,ic,TRUE);
7354 }
7355
7356 /*-----------------------------------------------------------------*/
7357 /* genPointerSet - stores the value into a pointer location        */
7358 /*-----------------------------------------------------------------*/
7359 static void genPointerSet (iCode *ic)
7360 {    
7361     operand *right, *result ;
7362     link *type, *etype;
7363     int p_type;
7364
7365     D(emitcode(";", "genPointerSet "););
7366
7367     right = IC_RIGHT(ic);
7368     result = IC_RESULT(ic) ;
7369
7370     /* depending on the type of pointer we need to
7371     move it to the correct pointer register */
7372     type = operandType(result);
7373     etype = getSpec(type);
7374     /* if left is of type of pointer then it is simple */
7375     if (IS_PTR(type) && !IS_FUNC(type->next)) {
7376         p_type = DCL_TYPE(type);
7377     }
7378     else {
7379         /* we have to go by the storage class */
7380         p_type = PTR_TYPE(SPEC_OCLS(etype));
7381
7382 /*      if (SPEC_OCLS(etype)->codesp ) { */
7383 /*          p_type = CPOINTER ;  */
7384 /*      } */
7385 /*      else */
7386 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7387 /*              p_type = FPOINTER ; */
7388 /*          else */
7389 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7390 /*                  p_type = PPOINTER ; */
7391 /*              else */
7392 /*                  if (SPEC_OCLS(etype) == idata ) */
7393 /*                      p_type = IPOINTER ; */
7394 /*                  else */
7395 /*                      p_type = POINTER ; */
7396     }
7397
7398     /* now that we have the pointer type we assign
7399     the pointer values */
7400     switch (p_type) {
7401
7402     case POINTER:
7403     case IPOINTER:
7404         genNearPointerSet (right,result,ic);
7405         break;
7406
7407     case PPOINTER:
7408         genPagedPointerSet (right,result,ic);
7409         break;
7410
7411     case FPOINTER:
7412         genFarPointerSet (right,result,ic);
7413         break;
7414
7415     case GPOINTER:
7416         genGenPointerSet (right,result,ic);
7417         break;
7418     }
7419
7420 }
7421
7422 /*-----------------------------------------------------------------*/
7423 /* genIfx - generate code for Ifx statement                        */
7424 /*-----------------------------------------------------------------*/
7425 static void genIfx (iCode *ic, iCode *popIc)
7426 {
7427     operand *cond = IC_COND(ic);
7428     int isbit =0;
7429
7430     D(emitcode(";", "genIfx "););
7431
7432     aopOp(cond,ic,FALSE, FALSE);
7433
7434     /* get the value into acc */
7435     if (AOP_TYPE(cond) != AOP_CRY)
7436         toBoolean(cond);
7437     else
7438         isbit = 1;
7439     /* the result is now in the accumulator */
7440     freeAsmop(cond,NULL,ic,TRUE);
7441
7442     /* if there was something to be popped then do it */
7443     if (popIc)
7444         genIpop(popIc);
7445
7446     /* if the condition is  a bit variable */
7447     if (isbit && IS_ITEMP(cond) && 
7448         SPIL_LOC(cond))
7449         genIfxJump(ic,SPIL_LOC(cond)->rname);
7450     else
7451         if (isbit && !IS_ITEMP(cond))
7452             genIfxJump(ic,OP_SYMBOL(cond)->rname);
7453         else
7454             genIfxJump(ic,"a");
7455
7456     ic->generated = 1;
7457 }
7458
7459 /*-----------------------------------------------------------------*/
7460 /* genAddrOf - generates code for address of                       */
7461 /*-----------------------------------------------------------------*/
7462 static void genAddrOf (iCode *ic)
7463 {
7464     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7465     int size, offset ;
7466
7467     D(emitcode(";", "genAddrOf "););
7468
7469     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7470
7471     /* if the operand is on the stack then we 
7472     need to get the stack offset of this
7473     variable */
7474     if (sym->onStack) {
7475         /* if it has an offset then we need to compute
7476         it */
7477         if (sym->stack) {
7478             emitcode("mov","a,_bp");
7479             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7480             aopPut(AOP(IC_RESULT(ic)),"a",0);       
7481         } else {
7482             /* we can just move _bp */
7483             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7484         }
7485         /* fill the result with zero */
7486         size = AOP_SIZE(IC_RESULT(ic)) - 1;
7487         
7488         
7489         if (options.stack10bit && size < (FPTRSIZE - 1))
7490         {
7491             fprintf(stderr, 
7492                     "*** warning: pointer to stack var truncated.\n");
7493         }
7494         
7495         offset = 1;
7496         while (size--)
7497         {
7498             /* Yuck! */
7499             if (options.stack10bit && offset == 2)
7500             {
7501                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7502             }
7503             else
7504             {
7505                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7506             }
7507         }
7508
7509         goto release;
7510     }
7511
7512     /* object not on stack then we need the name */
7513     size = AOP_SIZE(IC_RESULT(ic));
7514     offset = 0;
7515
7516     while (size--) {
7517         char s[SDCC_NAME_MAX];
7518         if (offset) 
7519             sprintf(s,"#(%s >> %d)",
7520                     sym->rname,
7521                     offset*8);
7522         else
7523             sprintf(s,"#%s",sym->rname);
7524         aopPut(AOP(IC_RESULT(ic)),s,offset++);
7525     }
7526
7527 release:
7528     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7529
7530 }
7531
7532 /*-----------------------------------------------------------------*/
7533 /* genFarFarAssign - assignment when both are in far space         */
7534 /*-----------------------------------------------------------------*/
7535 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7536 {
7537     int size = AOP_SIZE(right);
7538     int offset = 0;
7539     char *l ;
7540     /* first push the right side on to the stack */
7541     while (size--) {
7542         l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7543         MOVA(l);
7544         emitcode ("push","acc");
7545     }
7546     
7547     D(emitcode(";", "genFarFarAssign "););
7548
7549     freeAsmop(right,NULL,ic,FALSE);
7550     /* now assign DPTR to result */
7551     aopOp(result,ic,FALSE, FALSE);
7552     size = AOP_SIZE(result);
7553     while (size--) {
7554         emitcode ("pop","acc");
7555         aopPut(AOP(result),"a",--offset);
7556     }
7557     freeAsmop(result,NULL,ic,FALSE);
7558         
7559 }
7560
7561 /*-----------------------------------------------------------------*/
7562 /* genAssign - generate code for assignment                        */
7563 /*-----------------------------------------------------------------*/
7564 static void genAssign (iCode *ic)
7565 {
7566     operand *result, *right;
7567     int size, offset ;
7568         unsigned long lit = 0L;
7569
7570     D(emitcode(";", "genAssign "););
7571
7572     result = IC_RESULT(ic);
7573     right  = IC_RIGHT(ic) ;
7574
7575     /* if they are the same */
7576     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7577         return ;
7578
7579     aopOp(right,ic,FALSE, FALSE);
7580     
7581     emitcode(";", "genAssign: resultIsFar = %s",
7582              isOperandInFarSpace(result) ?
7583              "TRUE" : "FALSE");
7584
7585     /* special case both in far space */
7586     if ((AOP_TYPE(right) == AOP_DPTR ||
7587          AOP_TYPE(right) == AOP_DPTR2) &&
7588     /* IS_TRUE_SYMOP(result)       && */
7589     isOperandInFarSpace(result)) {
7590         
7591         genFarFarAssign (result,right,ic);
7592         return ;
7593     }
7594
7595     aopOp(result,ic,TRUE, FALSE);
7596
7597     /* if they are the same registers */
7598     if (sameRegs(AOP(right),AOP(result)))
7599         goto release;
7600
7601     /* if the result is a bit */
7602     if (AOP_TYPE(result) == AOP_CRY) {
7603
7604         /* if the right size is a literal then
7605         we know what the value is */
7606         if (AOP_TYPE(right) == AOP_LIT) {
7607             if (((int) operandLitValue(right))) 
7608                 aopPut(AOP(result),one,0);
7609             else
7610                 aopPut(AOP(result),zero,0);
7611             goto release;
7612         }
7613
7614         /* the right is also a bit variable */
7615         if (AOP_TYPE(right) == AOP_CRY) {
7616             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7617             aopPut(AOP(result),"c",0);
7618             goto release ;
7619         }
7620
7621         /* we need to or */
7622         toBoolean(right);
7623         aopPut(AOP(result),"a",0);
7624         goto release ;
7625     }
7626
7627     /* bit variables done */
7628     /* general case */
7629     size = AOP_SIZE(result);
7630     offset = 0 ;
7631     if(AOP_TYPE(right) == AOP_LIT)
7632         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7633     if((size > 1) &&
7634        (AOP_TYPE(result) != AOP_REG) &&
7635        (AOP_TYPE(right) == AOP_LIT) &&
7636        !IS_FLOAT(operandType(right)) &&
7637        (lit < 256L)){
7638         emitcode("clr","a");
7639         while (size--) {
7640             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7641                 aopPut(AOP(result),"a",size);
7642             else
7643                 aopPut(AOP(result),
7644                        aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7645                        size);
7646         }
7647     } else {
7648         while (size--) {
7649             aopPut(AOP(result),
7650                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7651                    offset);
7652             offset++;
7653         }
7654     }
7655     
7656 release:
7657     freeAsmop (right,NULL,ic,FALSE);
7658     freeAsmop (result,NULL,ic,TRUE);
7659 }   
7660
7661 /*-----------------------------------------------------------------*/
7662 /* genJumpTab - genrates code for jump table                       */
7663 /*-----------------------------------------------------------------*/
7664 static void genJumpTab (iCode *ic)
7665 {
7666     symbol *jtab;
7667     char *l;
7668
7669     D(emitcode(";", "genJumpTab "););
7670
7671     aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7672     /* get the condition into accumulator */
7673     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
7674     MOVA(l);
7675     /* multiply by four! */
7676     emitcode("add","a,acc");
7677     emitcode("add","a,acc");
7678     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7679
7680     jtab = newiTempLabel(NULL);
7681     emitcode("mov","dptr,#%05d$",jtab->key+100);
7682     emitcode("jmp","@a+dptr");
7683     emitcode("","%05d$:",jtab->key+100);
7684     /* now generate the jump labels */
7685     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7686          jtab = setNextItem(IC_JTLABELS(ic)))
7687         emitcode("ljmp","%05d$",jtab->key+100);
7688
7689 }
7690
7691 /*-----------------------------------------------------------------*/
7692 /* genCast - gen code for casting                                  */
7693 /*-----------------------------------------------------------------*/
7694 static void genCast (iCode *ic)
7695 {
7696     operand *result = IC_RESULT(ic);
7697     link *ctype = operandType(IC_LEFT(ic));
7698     link *rtype = operandType(IC_RIGHT(ic));
7699     operand *right = IC_RIGHT(ic);
7700     int size, offset ;
7701
7702     D(emitcode(";", "genCast "););
7703
7704     /* if they are equivalent then do nothing */
7705     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7706         return ;
7707
7708     aopOp(right,ic,FALSE, FALSE) ;
7709     aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7710
7711     /* if the result is a bit */
7712     if (AOP_TYPE(result) == AOP_CRY) {
7713         /* if the right size is a literal then
7714         we know what the value is */
7715         if (AOP_TYPE(right) == AOP_LIT) {
7716             if (((int) operandLitValue(right))) 
7717                 aopPut(AOP(result),one,0);
7718             else
7719                 aopPut(AOP(result),zero,0);
7720
7721             goto release;
7722         }
7723
7724         /* the right is also a bit variable */
7725         if (AOP_TYPE(right) == AOP_CRY) {
7726             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7727             aopPut(AOP(result),"c",0);
7728             goto release ;
7729         }
7730
7731         /* we need to or */
7732         toBoolean(right);
7733         aopPut(AOP(result),"a",0);
7734         goto release ;
7735     }
7736
7737     /* if they are the same size : or less */
7738     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7739
7740         /* if they are in the same place */
7741         if (sameRegs(AOP(right),AOP(result)))
7742             goto release;
7743
7744         /* if they in different places then copy */
7745         size = AOP_SIZE(result);
7746         offset = 0 ;
7747         while (size--) {
7748             aopPut(AOP(result),
7749                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7750                    offset);
7751             offset++;
7752         }
7753         goto release;
7754     }
7755
7756
7757     /* if the result is of type pointer */
7758     if (IS_PTR(ctype)) {
7759
7760         int p_type;
7761         link *type = operandType(right);
7762
7763         /* pointer to generic pointer */
7764         if (IS_GENPTR(ctype)) {
7765             char *l = zero;
7766             
7767             if (IS_PTR(type)) 
7768             {
7769                 p_type = DCL_TYPE(type);
7770             }
7771             else 
7772             {
7773 #if OLD_CAST_BEHAVIOR
7774                 /* KV: we are converting a non-pointer type to
7775                  * a generic pointer. This (ifdef'd out) code
7776                  * says that the resulting generic pointer 
7777                  * should have the same class as the storage
7778                  * location of the non-pointer variable.
7779                  * 
7780                  * For example, converting an int (which happens
7781                  * to be stored in DATA space) to a pointer results
7782                  * in a DATA generic pointer; if the original int
7783                  * in XDATA space, so will be the resulting pointer.
7784                  *
7785                  * I don't like that behavior, and thus this change:
7786                  * all such conversions will be forced to XDATA and
7787                  * throw a warning. If you want some non-XDATA
7788                  * type, or you want to suppress the warning, you
7789                  * must go through an intermediate cast, like so:
7790                  *
7791                  * char _generic *gp = (char _xdata *)(intVar);
7792                  */
7793                 link *etype = getSpec(type);             
7794
7795                 /* we have to go by the storage class */
7796                 if (SPEC_OCLS(etype) != generic)
7797                 {
7798                     p_type = PTR_TYPE(SPEC_OCLS(etype));
7799                 }
7800                 else
7801 #endif          
7802                 {
7803                     /* Converting unknown class (i.e. register variable)
7804                      * to generic pointer. This is not good, but
7805                      * we'll make a guess (and throw a warning).
7806                      */
7807                     p_type = FPOINTER;
7808                     werror(W_INT_TO_GEN_PTR_CAST);           
7809                 }
7810             }
7811                 
7812             /* the first two bytes are known */
7813             size = GPTRSIZE - 1; 
7814             offset = 0 ;
7815             while (size--) {
7816                 aopPut(AOP(result),
7817                        aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7818                        offset);
7819                 offset++;
7820             }
7821             
7822             /* the last byte depending on type */
7823             switch (p_type) {
7824             case IPOINTER:
7825             case POINTER:
7826                 l = zero;
7827                 break;
7828             case FPOINTER:
7829                 l = one;
7830                 break;
7831             case CPOINTER:
7832                 l = "#0x02";
7833                 break;                          
7834             case PPOINTER:
7835                 l = "#0x03";
7836                 break;
7837                 
7838             default:
7839                 /* this should never happen */
7840                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7841                        "got unknown pointer type");
7842                 exit(1);
7843             }
7844             aopPut(AOP(result),l, GPTRSIZE - 1);            
7845             goto release ;
7846         }
7847         
7848         /* just copy the pointers */
7849         size = AOP_SIZE(result);
7850         offset = 0 ;
7851         while (size--) {
7852             aopPut(AOP(result),
7853                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7854                    offset);
7855             offset++;
7856         }
7857         goto release ;
7858     }
7859     
7860     /* so we now know that the size of destination is greater
7861     than the size of the source */
7862     /* we move to result for the size of source */
7863     size = AOP_SIZE(right);
7864     offset = 0 ;
7865     while (size--) {
7866         aopPut(AOP(result),
7867                aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7868                offset);
7869         offset++;
7870     }
7871
7872     /* now depending on the sign of the source && destination */
7873     size = AOP_SIZE(result) - AOP_SIZE(right);
7874     /* if unsigned or not an integral type */
7875     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7876         while (size--)
7877             aopPut(AOP(result),zero,offset++);
7878     } else {
7879         /* we need to extend the sign :{ */
7880         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7881                          FALSE,FALSE,TRUE);
7882         MOVA(l);
7883         emitcode("rlc","a");
7884         emitcode("subb","a,acc");
7885         while (size--)
7886             aopPut(AOP(result),"a",offset++);   
7887     }
7888
7889     /* we are done hurray !!!! */
7890
7891 release:
7892     freeAsmop(right,NULL,ic,TRUE);
7893     freeAsmop(result,NULL,ic,TRUE);
7894
7895 }
7896
7897 /*-----------------------------------------------------------------*/
7898 /* genDjnz - generate decrement & jump if not zero instrucion      */
7899 /*-----------------------------------------------------------------*/
7900 static int genDjnz (iCode *ic, iCode *ifx)
7901 {
7902     symbol *lbl, *lbl1;
7903     if (!ifx)
7904         return 0;
7905     
7906     /* if the if condition has a false label
7907        then we cannot save */
7908     if (IC_FALSE(ifx))
7909         return 0;
7910
7911     /* if the minus is not of the form 
7912        a = a - 1 */
7913     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7914         !IS_OP_LITERAL(IC_RIGHT(ic)))
7915         return 0;
7916
7917     if (operandLitValue(IC_RIGHT(ic)) != 1)
7918         return 0;
7919
7920     /* if the size of this greater than one then no
7921        saving */
7922     if (getSize(operandType(IC_RESULT(ic))) > 1)
7923         return 0;
7924
7925     /* otherwise we can save BIG */
7926     lbl = newiTempLabel(NULL);
7927     lbl1= newiTempLabel(NULL);
7928
7929     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7930     
7931     if (IS_AOP_PREG(IC_RESULT(ic))) {
7932         emitcode("dec","%s",
7933                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7934         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7935         emitcode("jnz","%05d$",lbl->key+100);
7936     } else {    
7937         emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
7938                   lbl->key+100);
7939     }
7940     emitcode ("sjmp","%05d$",lbl1->key+100);
7941     emitcode ("","%05d$:",lbl->key+100);
7942     emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7943     emitcode ("","%05d$:",lbl1->key+100);
7944     
7945     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7946     ifx->generated = 1;
7947     return 1;
7948 }
7949
7950 /*-----------------------------------------------------------------*/
7951 /* genReceive - generate code for a receive iCode                  */
7952 /*-----------------------------------------------------------------*/
7953 static void genReceive (iCode *ic)
7954 {    
7955
7956     D(emitcode(";", "genReceive "););
7957
7958     if (isOperandInFarSpace(IC_RESULT(ic)) && 
7959         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7960           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7961         int size = getSize(operandType(IC_RESULT(ic)));
7962         int offset =  fReturnSize_390 - size;
7963         while (size--) {
7964             emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
7965                                     fReturn[fReturnSize_390 - offset - 1] : "acc"));
7966             offset++;
7967         }
7968         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7969         size = AOP_SIZE(IC_RESULT(ic));
7970         offset = 0;
7971         while (size--) {
7972             emitcode ("pop","acc");
7973             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7974         }
7975         
7976     } else {
7977         _G.accInUse++;
7978         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);  
7979         _G.accInUse--;
7980         assignResultValue(IC_RESULT(ic));       
7981     }
7982
7983     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7984 }
7985
7986 /*-----------------------------------------------------------------*/
7987 /* gen390Code - generate code for 8051 based controllers            */
7988 /*-----------------------------------------------------------------*/
7989 void gen390Code (iCode *lic)
7990 {
7991     iCode *ic;
7992     int cln = 0;
7993
7994     lineHead = lineCurr = NULL;
7995
7996     /* print the allocation information */
7997     if (allocInfo)
7998         printAllocInfo( currFunc, codeOutFile);
7999     /* if debug information required */
8000 /*     if (options.debug && currFunc) { */
8001     if (currFunc) {
8002         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8003         _G.debugLine = 1;
8004         if (IS_STATIC(currFunc->etype))
8005             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
8006         else
8007             emitcode("","G$%s$0$0 ==.",currFunc->name);
8008         _G.debugLine = 0;
8009     }
8010     /* stack pointer name */
8011     if (options.useXstack)
8012         spname = "_spx";
8013     else
8014         spname = "sp";
8015     
8016  
8017     for (ic = lic ; ic ; ic = ic->next ) {
8018         
8019         if ( cln != ic->lineno ) {
8020             if ( options.debug ) {
8021                 _G.debugLine = 1;
8022                 emitcode("","C$%s$%d$%d$%d ==.",
8023                          ic->filename,ic->lineno,
8024                          ic->level,ic->block);
8025                 _G.debugLine = 0;
8026             }
8027             emitcode(";","%s %d",ic->filename,ic->lineno);
8028             cln = ic->lineno ;
8029         }
8030         /* if the result is marked as
8031            spilt and rematerializable or code for
8032            this has already been generated then
8033            do nothing */
8034         if (resultRemat(ic) || ic->generated ) 
8035             continue ;
8036         
8037         /* depending on the operation */
8038         switch (ic->op) {
8039         case '!' :
8040             genNot(ic);
8041             break;
8042             
8043         case '~' :
8044             genCpl(ic);
8045             break;
8046             
8047         case UNARYMINUS:
8048             genUminus (ic);
8049             break;
8050             
8051         case IPUSH:
8052             genIpush (ic);
8053             break;
8054             
8055         case IPOP:
8056             /* IPOP happens only when trying to restore a 
8057                spilt live range, if there is an ifx statement
8058                following this pop then the if statement might
8059                be using some of the registers being popped which
8060                would destory the contents of the register so
8061                we need to check for this condition and handle it */
8062             if (ic->next            && 
8063                 ic->next->op == IFX &&
8064                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
8065                 genIfx (ic->next,ic);
8066             else
8067                 genIpop (ic);
8068             break; 
8069             
8070         case CALL:
8071             genCall (ic);
8072             break;
8073             
8074         case PCALL:
8075             genPcall (ic);
8076             break;
8077             
8078         case FUNCTION:
8079             genFunction (ic);
8080             break;
8081             
8082         case ENDFUNCTION:
8083             genEndFunction (ic);
8084             break;
8085             
8086         case RETURN:
8087             genRet (ic);
8088             break;
8089             
8090         case LABEL:
8091             genLabel (ic);
8092             break;
8093             
8094         case GOTO:
8095             genGoto (ic);
8096             break;
8097             
8098         case '+' :
8099             genPlus (ic) ;
8100             break;
8101             
8102         case '-' :
8103             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8104                 genMinus (ic);
8105             break;
8106             
8107         case '*' :
8108             genMult (ic);
8109             break;
8110             
8111         case '/' :
8112             genDiv (ic) ;
8113             break;
8114             
8115         case '%' :
8116             genMod (ic);
8117             break;
8118             
8119         case '>' :
8120             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
8121             break;
8122             
8123         case '<' :
8124             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8125             break;
8126             
8127         case LE_OP:
8128         case GE_OP:
8129         case NE_OP:
8130             
8131             /* note these two are xlated by algebraic equivalence
8132                during parsing SDCC.y */
8133             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8134                    "got '>=' or '<=' shouldn't have come here");
8135             break;      
8136             
8137         case EQ_OP:
8138             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8139             break;          
8140             
8141         case AND_OP:
8142             genAndOp (ic);
8143             break;
8144             
8145         case OR_OP:
8146             genOrOp (ic);
8147             break;
8148             
8149         case '^' :
8150             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8151             break;
8152             
8153         case '|' :
8154                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8155             break;
8156             
8157         case BITWISEAND:
8158             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8159             break;
8160             
8161         case INLINEASM:
8162             genInline (ic);
8163             break;
8164             
8165         case RRC:
8166             genRRC (ic);
8167             break;
8168             
8169         case RLC:
8170             genRLC (ic);
8171             break;
8172             
8173         case GETHBIT:
8174             genGetHbit (ic);
8175             break;
8176             
8177         case LEFT_OP:
8178             genLeftShift (ic);
8179             break;
8180             
8181         case RIGHT_OP:
8182             genRightShift (ic);
8183             break;
8184             
8185         case GET_VALUE_AT_ADDRESS:
8186             genPointerGet(ic);
8187             break;
8188             
8189         case '=' :
8190             if (POINTER_SET(ic))
8191                 genPointerSet(ic);
8192             else
8193                 genAssign(ic);
8194             break;
8195             
8196         case IFX:
8197             genIfx (ic,NULL);
8198             break;
8199             
8200         case ADDRESS_OF:
8201             genAddrOf (ic);
8202             break;
8203             
8204         case JUMPTABLE:
8205             genJumpTab (ic);
8206             break;
8207             
8208         case CAST:
8209             genCast (ic);
8210             break;
8211             
8212         case RECEIVE:
8213             genReceive(ic);
8214             break;
8215             
8216         case SEND:
8217             addSet(&_G.sendSet,ic);
8218             break;
8219
8220         default :
8221             ic = ic;
8222             /*      piCode(ic,stdout); */
8223             
8224         }
8225     }
8226     
8227
8228     /* now we are ready to call the 
8229        peep hole optimizer */
8230     if (!options.nopeep)
8231         peepHole (&lineHead);
8232
8233     /* now do the actual printing */
8234     printLine (lineHead,codeOutFile);    
8235     return;
8236 }