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