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