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