* src/SDCCcse.c (ifxOptimize),
[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           {
2084             werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2085                     "Bad rIdx in asmToBool");
2086             return;
2087           }
2088         break;
2089       case AOP_EXT:
2090         if (resultInA)
2091           needpula = FALSE;
2092         else
2093           needpula = pushRegIfUsed (hc08_reg_a);
2094         loadRegFromAop (hc08_reg_a, aop, 0);
2095         for (offset=1; offset<size; offset++)
2096           accopWithAop ("ora", aop, offset);
2097         if (needpula)
2098           pullReg (hc08_reg_a);
2099         else
2100           {
2101             hc08_freeReg (hc08_reg_a);
2102             flagsonly = FALSE;
2103           }
2104         break;
2105       default:
2106         if (size==1)
2107           {
2108             if (resultInA)
2109               {
2110                 loadRegFromAop (hc08_reg_a, aop, 0);
2111                 hc08_freeReg (hc08_reg_a);
2112                 flagsonly = FALSE;
2113               }
2114             else
2115               emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2116             break;
2117           }
2118         else if (size==2)
2119           {
2120             if (hc08_reg_a->isFree)
2121               {
2122                 loadRegFromAop (hc08_reg_a, aop, 0);
2123                 accopWithAop ("ora", aop, 1);
2124                 hc08_freeReg (hc08_reg_a);
2125                 flagsonly = FALSE;
2126               }
2127             else
2128               {
2129                 tlbl = newiTempLabel (NULL);
2130                 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2131                 emitcode ("bne", "%05d$", (tlbl->key + 100));
2132                 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2133                 emitcode ("", "%05d$:", (tlbl->key + 100));
2134                 break;
2135               }
2136           }
2137         else
2138           {
2139             needpula = pushRegIfUsed (hc08_reg_a);
2140             loadRegFromAop (hc08_reg_a, aop, 0);
2141             for (offset=1; offset<size; offset++)
2142               accopWithAop ("ora", aop, offset);
2143             if (needpula)
2144               pullReg (hc08_reg_a);
2145             else
2146               {
2147                 hc08_freeReg (hc08_reg_a);
2148                 flagsonly = FALSE;
2149               }
2150           }
2151     }
2152
2153   if (resultInA)
2154     {
2155       tlbl = newiTempLabel (NULL);
2156
2157       if (flagsonly)
2158         {
2159           tlbl1 = newiTempLabel (NULL);
2160           emitBranch ("bne", tlbl1);
2161           loadRegFromConst (hc08_reg_a, zero);
2162           emitBranch ("bra", tlbl);
2163           emitLabel (tlbl1);
2164           loadRegFromConst (hc08_reg_a, one);
2165         }
2166       else
2167         {
2168           emitBranch ("beq", tlbl);
2169           loadRegFromConst (hc08_reg_a, one);
2170         }
2171       emitLabel (tlbl);
2172       hc08_useReg (hc08_reg_a);
2173     }
2174 }
2175
2176
2177
2178 /*-----------------------------------------------------------------*/
2179 /* genNot - generate code for ! operation                          */
2180 /*-----------------------------------------------------------------*/
2181 static void
2182 genNot (iCode * ic)
2183 {
2184   D(emitcode (";     genNot",""));
2185
2186   /* assign asmOps to operand & result */
2187   aopOp (IC_LEFT (ic), ic, FALSE);
2188   aopOp (IC_RESULT (ic), ic, TRUE);
2189
2190   asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2191   emitcode ("eor", one);
2192   storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2193   
2194   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2195   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2196 }
2197
2198
2199 /*-----------------------------------------------------------------*/
2200 /* genCpl - generate code for complement                           */
2201 /*-----------------------------------------------------------------*/
2202 static void
2203 genCpl (iCode * ic)
2204 {
2205   int offset = 0;
2206   int size;
2207   regs* reg = hc08_reg_a;
2208   
2209 //  symbol *tlbl;
2210
2211   D(emitcode (";     genCpl",""));
2212
2213   /* assign asmOps to operand & result */
2214   aopOp (IC_LEFT (ic), ic, FALSE);
2215   aopOp (IC_RESULT (ic), ic, TRUE);
2216
2217   size = AOP_SIZE (IC_RESULT (ic));
2218   while (size--)
2219     {
2220       loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2221       rmwWithReg ("com", reg);
2222       hc08_useReg (reg);
2223       storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2224       hc08_freeReg (reg);
2225     }
2226
2227   /* release the aops */
2228   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2229   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2230 }
2231
2232 /*-----------------------------------------------------------------*/
2233 /* genUminusFloat - unary minus for floating points                */
2234 /*-----------------------------------------------------------------*/
2235 static void
2236 genUminusFloat (operand * op, operand * result)
2237 {
2238   int size, offset = 0;
2239   bool needpula;
2240
2241   D(emitcode (";     genUminusFloat",""));
2242
2243   /* for this we just copy and then flip the bit */
2244
2245   size = AOP_SIZE (op) - 1;
2246
2247   while (size--)
2248     {
2249       if (!size)
2250         {
2251           needpula = pushRegIfUsed (hc08_reg_a);
2252           loadRegFromAop (hc08_reg_a, AOP (op), offset);
2253           emitcode ("eor", "#0x80");
2254           hc08_useReg (hc08_reg_a);
2255           storeRegToAop (hc08_reg_a, AOP (result), offset);
2256           pullOrFreeReg (hc08_reg_a, needpula);
2257         }
2258       else
2259         transferAopAop (AOP (op), offset, AOP (result), offset);
2260       offset++;
2261     }
2262
2263 }
2264
2265 /*-----------------------------------------------------------------*/
2266 /* genUminus - unary minus code generation                         */
2267 /*-----------------------------------------------------------------*/
2268 static void
2269 genUminus (iCode * ic)
2270 {
2271   int offset, size;
2272   sym_link *optype, *rtype;
2273   char *sub;
2274   bool needpula;
2275
2276   D(emitcode (";     genUminus",""));
2277
2278   /* assign asmops */
2279   aopOp (IC_LEFT (ic), ic, FALSE);
2280   aopOp (IC_RESULT (ic), ic, TRUE);
2281
2282   optype = operandType (IC_LEFT (ic));
2283   rtype = operandType (IC_RESULT (ic));
2284
2285   /* if float then do float stuff */
2286   if (IS_FLOAT (optype))
2287     {
2288       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2289       goto release;
2290     }
2291
2292   /* otherwise subtract from zero */
2293   size = AOP_SIZE (IC_LEFT (ic));
2294   offset = 0;
2295
2296   if (size == 1)
2297     {
2298       needpula = pushRegIfUsed (hc08_reg_a);
2299       loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2300       emitcode ("nega", "");
2301       hc08_freeReg (hc08_reg_a);
2302       storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)), 
2303                          SPEC_USIGN (operandType (IC_LEFT (ic))));
2304       pullOrFreeReg (hc08_reg_a, needpula);
2305     }
2306   else
2307     {
2308       needpula = pushRegIfUsed (hc08_reg_a);
2309       sub="sub";
2310       while (size--)
2311         {
2312           loadRegFromConst (hc08_reg_a, zero);
2313           accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2314           storeRegToAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset++);
2315           sub = "sbc";
2316         }
2317         storeRegSignToUpperAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset, 
2318                                 SPEC_USIGN (operandType (IC_LEFT (ic))));
2319       pullOrFreeReg (hc08_reg_a, needpula);
2320     }
2321
2322
2323
2324 release:
2325   /* release the aops */
2326   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2327   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2328 }
2329
2330 /*-----------------------------------------------------------------*/
2331 /* saveRegisters - will look for a call and save the registers     */
2332 /*-----------------------------------------------------------------*/
2333 static void
2334 saveRegisters (iCode * lic)
2335 {
2336   int i;
2337   iCode *ic;
2338   bitVect *rsave;
2339
2340   /* look for call */
2341   for (ic = lic; ic; ic = ic->next)
2342     if (ic->op == CALL || ic->op == PCALL)
2343       break;
2344
2345   if (!ic)
2346     {
2347       fprintf (stderr, "found parameter push with no function call\n");
2348       return;
2349     }
2350
2351   /* if the registers have been saved already or don't need to be then
2352      do nothing */
2353   if (ic->regsSaved)
2354     return;
2355   if (IS_SYMOP(IC_LEFT(ic)) &&
2356       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2357        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2358     return;
2359   
2360   /* safe the registers in use at this time but skip the
2361      ones for the result */
2362   rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2363                          hc08_rUmaskForOp (IC_RESULT(ic)));
2364
2365   ic->regsSaved = 1;
2366   for (i = 0; i < hc08_nRegs; i++)
2367     {
2368       if (bitVectBitValue (rsave, i))
2369         pushReg ( hc08_regWithIdx (i), FALSE);
2370     }
2371 }
2372
2373 /*-----------------------------------------------------------------*/
2374 /* unsaveRegisters - pop the pushed registers                      */
2375 /*-----------------------------------------------------------------*/
2376 static void
2377 unsaveRegisters (iCode * ic)
2378 {
2379   int i;
2380   bitVect *rsave;
2381
2382   /* restore the registers in use at this time but skip the
2383      ones for the result */
2384   rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2385                          hc08_rUmaskForOp (IC_RESULT(ic)));
2386
2387   for (i = hc08_nRegs; i >= 0; i--)
2388     {
2389       if (bitVectBitValue (rsave, i))
2390         pullReg ( hc08_regWithIdx (i));
2391     }
2392
2393 }
2394
2395
2396 /*-----------------------------------------------------------------*/
2397 /* pushSide -                */
2398 /*-----------------------------------------------------------------*/
2399 static void
2400 pushSide (operand * oper, int size)
2401 {
2402   int offset = 0;
2403   while (size--)
2404     {
2405       loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2406       pushReg ( hc08_reg_a, TRUE);
2407     }
2408 }
2409
2410 /*-----------------------------------------------------------------*/
2411 /* assignResultValue -               */
2412 /*-----------------------------------------------------------------*/
2413 static void
2414 assignResultValue (operand * oper)
2415 {
2416   int size = AOP_SIZE (oper);
2417   int offset = 0;
2418   while (size--)
2419     {
2420       transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2421       if (hc08_aop_pass[offset]->type == AOP_REG)
2422         hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2423       offset++;
2424     }
2425 }
2426
2427
2428
2429 /*-----------------------------------------------------------------*/
2430 /* genIpush - genrate code for pushing this gets a little complex  */
2431 /*-----------------------------------------------------------------*/
2432 static void
2433 genIpush (iCode * ic)
2434 {
2435   int size, offset = 0;
2436 //  char *l;
2437
2438   D(emitcode (";     genIpush",""));
2439
2440   /* if this is not a parm push : ie. it is spill push
2441      and spill push is always done on the local stack */
2442   if (!ic->parmPush)
2443     {
2444
2445       /* and the item is spilt then do nothing */
2446       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2447         return;
2448
2449       aopOp (IC_LEFT (ic), ic, FALSE);
2450       size = AOP_SIZE (IC_LEFT (ic));
2451       offset = 0;
2452       /* push it on the stack */
2453       while (size--)
2454         {
2455           loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2456           pushReg ( hc08_reg_a, TRUE);
2457         }
2458
2459       return;
2460     }
2461
2462   /* this is a paramter push: in this case we call
2463      the routine to find the call and save those
2464      registers that need to be saved */
2465   saveRegisters (ic);
2466
2467   /* then do the push */
2468   aopOp (IC_LEFT (ic), ic, FALSE);
2469
2470
2471   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2472   size = AOP_SIZE (IC_LEFT (ic));
2473   offset = 0;
2474
2475 //  l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2476   if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2477     {
2478       if ((size==2) && hc08_reg_hx->isFree)
2479         {
2480           loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2481           pushReg (hc08_reg_hx, TRUE);
2482           goto release;
2483         }
2484     }
2485
2486   while (size--)
2487     {
2488 //      printf("loading %d\n", offset);
2489       loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2490 //      printf("pushing \n");
2491       pushReg (hc08_reg_a, TRUE);
2492     }
2493
2494 release:
2495   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2496 }
2497
2498 /*-----------------------------------------------------------------*/
2499 /* genIpop - recover the registers: can happen only for spilling   */
2500 /*-----------------------------------------------------------------*/
2501 static void
2502 genIpop (iCode * ic)
2503 {
2504   int size, offset;
2505
2506   D(emitcode (";     genIpop",""));
2507
2508   /* if the temp was not pushed then */
2509   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2510     return;
2511
2512   aopOp (IC_LEFT (ic), ic, FALSE);
2513   size = AOP_SIZE (IC_LEFT (ic));
2514   offset = size - 1;
2515   while (size--)
2516     {
2517       pullReg (hc08_reg_a);
2518       storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2519     }
2520   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2521 }
2522
2523
2524 /*-----------------------------------------------------------------*/
2525 /* genSend - gen code for SEND                                     */
2526 /*-----------------------------------------------------------------*/
2527 static void genSend(set *sendSet)
2528 {
2529     iCode *sic;
2530
2531     for (sic = setFirstItem (_G.sendSet); sic;
2532          sic = setNextItem (_G.sendSet)) {
2533           int size, offset = 0;
2534           aopOp (IC_LEFT (sic), sic, FALSE);
2535           size = AOP_SIZE (IC_LEFT (sic));
2536
2537           if (sic->argreg) {
2538               offset = size-1;
2539               while (size--) {
2540                   transferAopAop( AOP (IC_LEFT (sic)), offset,
2541                                   hc08_aop_pass[offset+(sic->argreg-1)], 0);
2542                   offset--;
2543               }
2544           }       
2545           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2546     }
2547 }
2548
2549 /*-----------------------------------------------------------------*/
2550 /* genCall - generates a call statement                            */
2551 /*-----------------------------------------------------------------*/
2552 static void
2553 genCall (iCode * ic)
2554 {
2555   sym_link *dtype;
2556 //  bool restoreBank = FALSE;
2557 //  bool swapBanks = FALSE;
2558
2559   D(emitcode(";     genCall",""));
2560
2561   dtype = operandType (IC_LEFT (ic));
2562   /* if send set is not empty the assign */
2563   if (_G.sendSet)
2564     {
2565         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2566             genSend(reverseSet(_G.sendSet));
2567         } else {
2568             genSend(_G.sendSet);
2569         }
2570
2571       _G.sendSet = NULL;
2572     }
2573
2574   /* if caller saves & we have not saved then */
2575   if (!ic->regsSaved)
2576       saveRegisters (ic);
2577
2578
2579   /* make the call */
2580   emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2581                           OP_SYMBOL (IC_LEFT (ic))->rname :
2582                           OP_SYMBOL (IC_LEFT (ic))->name));
2583
2584
2585   /* if we need assign a result value */
2586   if ((IS_ITEMP (IC_RESULT (ic)) &&
2587        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2588         OP_SYMBOL (IC_RESULT (ic))->accuse || 
2589         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2590       IS_TRUE_SYMOP (IC_RESULT (ic)))
2591     {
2592
2593       _G.accInUse++;
2594       aopOp (IC_RESULT (ic), ic, FALSE);
2595       _G.accInUse--;
2596
2597       assignResultValue (IC_RESULT (ic));
2598
2599       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2600     }
2601
2602   /* adjust the stack for parameters if
2603      required */
2604   if (ic->parmBytes)
2605     {
2606       pullNull (ic->parmBytes);
2607     }
2608
2609   /* if we had saved some registers then unsave them */
2610   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2611     unsaveRegisters (ic);
2612
2613 }
2614
2615 /*-----------------------------------------------------------------*/
2616 /* -10l - generates a call by pointer statement                */
2617 /*-----------------------------------------------------------------*/
2618 static void
2619 genPcall (iCode * ic)
2620 {
2621   sym_link *dtype;
2622   symbol *rlbl = newiTempLabel (NULL);
2623   symbol *tlbl = newiTempLabel (NULL);
2624 //  bool restoreBank=FALSE;
2625 //  bool swapBanks = FALSE;
2626
2627   D(emitcode(";     genPCall",""));
2628
2629   /* if caller saves & we have not saved then */
2630   if (!ic->regsSaved)
2631     saveRegisters (ic);
2632
2633   /* if we are calling a not _naked function that is not using
2634      the same register bank then we need to save the
2635      destination registers on the stack */
2636   dtype = operandType (IC_LEFT (ic))->next;
2637
2638   /* now push the calling address */
2639   emitBranch ("bsr", tlbl);
2640   emitBranch ("bra", rlbl);
2641   emitLabel (tlbl);
2642
2643   /* Push the function's address */
2644   aopOp (IC_LEFT (ic), ic, FALSE);
2645   pushSide (IC_LEFT (ic), FPTRSIZE);
2646   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2647
2648   /* if send set is not empty the assign */
2649   if (_G.sendSet)
2650     {
2651         genSend(reverseSet(_G.sendSet));
2652         _G.sendSet = NULL;
2653     }
2654
2655
2656   /* make the call */
2657   emitcode ("rts", "");
2658
2659   emitLabel (rlbl);
2660
2661
2662   /* if we need assign a result value */
2663   if ((IS_ITEMP (IC_RESULT (ic)) &&
2664        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2665         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2666       IS_TRUE_SYMOP (IC_RESULT (ic)))
2667     {
2668
2669       _G.accInUse++;
2670       aopOp (IC_RESULT (ic), ic, FALSE);
2671       _G.accInUse--;
2672
2673       assignResultValue (IC_RESULT (ic));
2674
2675       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2676     }
2677
2678   /* adjust the stack for parameters if
2679      required */
2680   if (ic->parmBytes)
2681     {
2682       pullNull (ic->parmBytes);
2683     }
2684
2685   /* if we hade saved some registers then
2686      unsave them */
2687   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2688     unsaveRegisters (ic);
2689 }
2690
2691 /*-----------------------------------------------------------------*/
2692 /* resultRemat - result  is rematerializable                       */
2693 /*-----------------------------------------------------------------*/
2694 static int
2695 resultRemat (iCode * ic)
2696 {
2697   if (SKIP_IC (ic) || ic->op == IFX)
2698     return 0;
2699
2700   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2701     {
2702       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2703       if (sym->remat && !POINTER_SET (ic))
2704         return 1;
2705     }
2706
2707   return 0;
2708 }
2709
2710 #if defined(__BORLANDC__) || defined(_MSC_VER)
2711 #define STRCASECMP stricmp
2712 #else
2713 #define STRCASECMP strcasecmp
2714 #endif
2715
2716 /*-----------------------------------------------------------------*/
2717 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2718 /*-----------------------------------------------------------------*/
2719 static int
2720 regsCmp(void *p1, void *p2)
2721 {
2722   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2723 }
2724
2725 static bool
2726 inExcludeList (char *s)
2727 {
2728   const char *p = setFirstItem(options.excludeRegsSet);
2729
2730   if (p == NULL || STRCASECMP(p, "none") == 0)
2731     return FALSE;
2732
2733
2734   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2735 }
2736
2737 /*-----------------------------------------------------------------*/
2738 /* genFunction - generated code for function entry                 */
2739 /*-----------------------------------------------------------------*/
2740 static void
2741 genFunction (iCode * ic)
2742 {
2743   symbol *sym;
2744   sym_link *ftype;
2745   int calleesaves_saved_register = -1;
2746
2747   _G.nRegsSaved = 0;
2748   _G.stackPushes = 0;
2749   /* create the function header */
2750   emitcode (";", "-----------------------------------------");
2751   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2752   emitcode (";", "-----------------------------------------");
2753
2754   emitcode ("", "%s:", sym->rname);
2755   ftype = operandType (IC_LEFT (ic));
2756
2757   if (IFFUNC_ISNAKED(ftype))
2758   {
2759       emitcode(";", "naked function: no prologue.");
2760       return;
2761   }
2762
2763
2764
2765   /* if this is an interrupt service routine then
2766      save h  */
2767   if (IFFUNC_ISISR (sym->type))
2768     {
2769
2770       if (!inExcludeList ("h"))
2771         emitcode ("pshh", "");
2772     }
2773   else
2774     {
2775       /* if callee-save to be used for this function
2776          then save the registers being used in this function */
2777       if (IFFUNC_CALLEESAVES(sym->type))
2778         {
2779           int i;
2780
2781           /* if any registers used */
2782           if (sym->regsUsed)
2783             {
2784               /* save the registers used */
2785               for (i = 0; i < sym->regsUsed->size; i++)
2786                 {
2787                   if (bitVectBitValue (sym->regsUsed, i))
2788                     {
2789                       /* remember one saved register for later usage */
2790                       if (calleesaves_saved_register < 0)
2791                         calleesaves_saved_register = i;
2792                       pushReg (hc08_regWithIdx (i), FALSE);
2793                       _G.nRegsSaved++;
2794                     }
2795                 }
2796             }
2797         }
2798     }
2799
2800   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2801     {
2802
2803     }
2804
2805   /* adjust the stack for the function */
2806   if (sym->stack)
2807     {
2808
2809       int i = sym->stack;
2810 //      if (i > 256)
2811 //      werror (W_STACK_OVERFLOW, sym->name);
2812
2813       adjustStack (-i);
2814     }
2815   _G.stackOfs = sym->stack;
2816   _G.stackPushes = 0;
2817   
2818   /* if critical function then turn interrupts off */
2819   if (IFFUNC_ISCRITICAL (ftype))
2820     {
2821       if (IFFUNC_ARGS (ftype))
2822         {
2823           /* Function was passed parameters, so make sure A is preserved */
2824           pushReg (hc08_reg_a, FALSE);
2825           pushReg (hc08_reg_a, FALSE);
2826           emitcode ("tpa", "");
2827           emitcode ("sta", "2,s");
2828           emitcode ("sei", "");
2829           pullReg (hc08_reg_a);
2830         }
2831       else
2832         {
2833           /* No passed parameters, so A can be freely modified */
2834           emitcode ("tpa", "");
2835           pushReg (hc08_reg_a, TRUE);
2836           emitcode ("sei", "");
2837         }
2838     }
2839
2840 }
2841
2842 /*-----------------------------------------------------------------*/
2843 /* genEndFunction - generates epilogue for functions               */
2844 /*-----------------------------------------------------------------*/
2845 static void
2846 genEndFunction (iCode * ic)
2847 {
2848   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2849
2850   if (IFFUNC_ISNAKED(sym->type))
2851   {
2852       emitcode(";", "naked function: no epilogue.");
2853       return;
2854   }
2855
2856   if (IFFUNC_ISCRITICAL (sym->type))
2857     {
2858       if (!IS_VOID(sym->type->next))
2859         {
2860           /* Function has return value, so make sure A is preserved */
2861           pushReg (hc08_reg_a, FALSE);
2862           emitcode ("lda", "2,s");
2863           emitcode ("tap", "");
2864           pullReg (hc08_reg_a);
2865           pullNull (1);
2866         }
2867       else
2868         {
2869           /* Function returns void, so A can be freely modified */
2870           pullReg (hc08_reg_a);
2871           emitcode ("tap", "");
2872         }
2873     }
2874
2875   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2876     {
2877     }
2878
2879   if (sym->stack)
2880     {
2881       _G.stackPushes += sym->stack;
2882       adjustStack (sym->stack);
2883     }
2884
2885
2886   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2887     {
2888     }
2889
2890   if (IFFUNC_ISISR (sym->type))
2891     {
2892
2893       if (!inExcludeList ("h"))
2894         emitcode ("pulh", "");
2895
2896
2897       /* if debug then send end of function */
2898       if (options.debug && currFunc)
2899         {
2900           _G.debugLine = 1;
2901           emitcode ("", "C$%s$%d$%d$%d ==.",
2902                     FileBaseName (ic->filename), currFunc->lastLine,
2903                     ic->level, ic->block);
2904           if (IS_STATIC (currFunc->etype))
2905             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2906           else
2907             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2908           _G.debugLine = 0;
2909         }
2910
2911       emitcode ("rti", "");
2912     }
2913   else
2914     {
2915       if (IFFUNC_CALLEESAVES(sym->type))
2916         {
2917           int i;
2918
2919           /* if any registers used */
2920           if (sym->regsUsed)
2921             {
2922               /* save the registers used */
2923               for (i = sym->regsUsed->size; i >= 0; i--)
2924                 {
2925                   if (bitVectBitValue (sym->regsUsed, i) ||
2926                       (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
2927                     emitcode ("pop", "%s", hc08_regWithIdx (i)->dname);
2928                 }
2929             }
2930
2931         }
2932
2933       /* if debug then send end of function */
2934       if (options.debug && currFunc)
2935         {
2936           _G.debugLine = 1;
2937           emitcode ("", "C$%s$%d$%d$%d ==.",
2938                     FileBaseName (ic->filename), currFunc->lastLine,
2939                     ic->level, ic->block);
2940           if (IS_STATIC (currFunc->etype))
2941             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2942           else
2943             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2944           _G.debugLine = 0;
2945         }
2946
2947       emitcode ("rts", "");
2948     }
2949
2950 }
2951
2952 /*-----------------------------------------------------------------*/
2953 /* genRet - generate code for return statement                     */
2954 /*-----------------------------------------------------------------*/
2955 static void
2956 genRet (iCode * ic)
2957 {
2958   int size, offset = 0;
2959 //  int pushed = 0;
2960
2961   D(emitcode (";     genRet",""));
2962
2963   /* if we have no return value then
2964      just generate the "ret" */
2965   if (!IC_LEFT (ic))
2966     goto jumpret;
2967
2968   /* we have something to return then
2969      move the return value into place */
2970   aopOp (IC_LEFT (ic), ic, FALSE);
2971   size = AOP_SIZE (IC_LEFT (ic));
2972
2973 #if 1
2974    offset = size - 1;
2975    while (size--)
2976      {
2977        transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
2978        offset--;
2979      }
2980 #else
2981   switch (size)
2982     {
2983       case 4:
2984         /* 4 byte return: store value in the global return variable */
2985         offset = size-1;
2986         while (size--)
2987           {
2988             loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
2989             STA (fReturn2[offset--], FALSE);
2990             hc08_freeReg (hc08_reg_a);
2991           }
2992         break;
2993       case 2:
2994         /* 2 byte return: store value in x:a */
2995         loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
2996         hc08_freeReg (hc08_reg_xa);
2997         break;
2998       case 1:
2999         /* 1 byte return: store value in a */
3000         loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3001         hc08_freeReg (hc08_reg_a);
3002         break;
3003     }
3004 #endif
3005
3006   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3007
3008 jumpret:
3009   /* generate a jump to the return label
3010      if the next is not the return statement */
3011   if (!(ic->next && ic->next->op == LABEL &&
3012         IC_LABEL (ic->next) == returnLabel))
3013
3014     emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3015
3016 }
3017
3018 /*-----------------------------------------------------------------*/
3019 /* genLabel - generates a label                                    */
3020 /*-----------------------------------------------------------------*/
3021 static void
3022 genLabel (iCode * ic)
3023 {
3024   int i;
3025   regs *reg;
3026   
3027   /* For the high level labels we cannot depend on any */
3028   /* register's contents. Amnesia time.                */
3029   for (i=A_IDX;i<=XA_IDX;i++)
3030     {
3031       reg = hc08_regWithIdx(i);
3032       if (reg)
3033         reg->aop = NULL;
3034     }
3035
3036   /* special case never generate */
3037   if (IC_LABEL (ic) == entryLabel)
3038     return;
3039
3040   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3041
3042 }
3043
3044 /*-----------------------------------------------------------------*/
3045 /* genGoto - generates a jmp                                      */
3046 /*-----------------------------------------------------------------*/
3047 static void
3048 genGoto (iCode * ic)
3049 {
3050   emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3051 }
3052
3053 #if 0
3054 /*-----------------------------------------------------------------*/
3055 /* findLabelBackwards: walks back through the iCode chain looking  */
3056 /* for the given label. Returns number of iCode instructions     */
3057 /* between that label and given ic.          */
3058 /* Returns zero if label not found.          */
3059 /*-----------------------------------------------------------------*/
3060 static int
3061 findLabelBackwards (iCode * ic, int key)
3062 {
3063   int count = 0;
3064
3065   while (ic->prev)
3066     {
3067       ic = ic->prev;
3068       count++;
3069
3070       /* If we have any pushes or pops, we cannot predict the distance.
3071          I don't like this at all, this should be dealt with in the 
3072          back-end */
3073       if (ic->op == IPUSH || ic->op == IPOP) {
3074         return 0;
3075       }
3076
3077       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3078         {
3079           return count;
3080         }
3081     }
3082
3083   return 0;
3084 }
3085 #endif
3086
3087 /*-----------------------------------------------------------------*/
3088 /* genPlusIncr :- does addition with increment if possible         */
3089 /*-----------------------------------------------------------------*/
3090 static bool
3091 genPlusIncr (iCode * ic)
3092 {
3093   int icount;
3094   operand *left;
3095   operand *result;
3096   bool needpulx;
3097   bool needpulh;
3098   bool needpula;
3099   unsigned int size = getDataSize (IC_RESULT (ic));
3100   int offset;
3101   symbol *tlbl = NULL;
3102   
3103   left = IC_LEFT (ic);
3104   result = IC_RESULT (ic);
3105
3106   /* will try to generate an increment */
3107   /* if the right side is not a literal
3108      we cannot */
3109   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3110     return FALSE;
3111
3112   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3113
3114   emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left)));
3115   
3116   if ((IS_AOP_HX (AOP (left)) ||
3117        ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3118       )
3119       && (icount>=-128) && (icount<=127) && (size==2))
3120     {
3121       needpulx = pushRegIfUsed (hc08_reg_x);
3122       needpulh = pushRegIfUsed (hc08_reg_h);
3123       loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3124       emitcode ("aix","#%d", icount);
3125       hc08_dirtyReg (hc08_reg_hx, FALSE);
3126       storeRegToAop (hc08_reg_hx, AOP(result), 0);
3127       pullOrFreeReg (hc08_reg_h, needpulh);
3128       pullOrFreeReg (hc08_reg_x, needpulx);
3129       return TRUE;
3130     }
3131
3132   emitcode ("", "; icount = %d, sameRegs=%d", icount, 
3133             sameRegs (AOP (left), AOP (result)));
3134   
3135   if ((icount > 255) || (icount<0))
3136     return FALSE;
3137
3138   if (!sameRegs (AOP (left), AOP (result)))
3139     return FALSE;
3140
3141   D(emitcode (";     genPlusIncr",""));
3142
3143   if (size>1)
3144     tlbl = newiTempLabel (NULL);
3145
3146   if (icount==1)
3147     {
3148       needpula = FALSE;
3149       rmwWithAop ("inc", AOP (result), 0);
3150       if (1<size)
3151         emitBranch ("bne", tlbl);
3152     }
3153   else
3154     {
3155       needpula = pushRegIfUsed (hc08_reg_a);
3156       loadRegFromAop (hc08_reg_a, AOP (result), 0);
3157       accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3158       hc08_useReg (hc08_reg_a);
3159       storeRegToAop (hc08_reg_a, AOP (result), 0);
3160       hc08_freeReg (hc08_reg_a);
3161       if (1<size)
3162         emitBranch ("bcc", tlbl);
3163     }
3164   for (offset=1; offset<size; offset++)
3165     {
3166       rmwWithAop ("inc", AOP (result), offset);
3167       if ((offset+1)<size)
3168         emitBranch ("bne", tlbl);
3169     }
3170
3171   if (size>1)
3172     emitLabel (tlbl);
3173   
3174   pullOrFreeReg (hc08_reg_a, needpula);
3175       
3176   return TRUE;
3177 }
3178
3179
3180
3181 /*-----------------------------------------------------------------*/
3182 /* genPlus - generates code for addition                           */
3183 /*-----------------------------------------------------------------*/
3184 static void
3185 genPlus (iCode * ic)
3186 {
3187   int size, offset = 0;
3188   char *add;
3189   asmop *leftOp, *rightOp;
3190
3191   /* special cases :- */
3192
3193   D(emitcode (";     genPlus",""));
3194
3195   aopOp (IC_LEFT (ic), ic, FALSE);
3196   aopOp (IC_RIGHT (ic), ic, FALSE);
3197   aopOp (IC_RESULT (ic), ic, TRUE);
3198
3199   /* we want registers on the left and literals on the right */
3200   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3201       (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3202     {
3203       operand *t = IC_RIGHT (ic);
3204       IC_RIGHT (ic) = IC_LEFT (ic);
3205       IC_LEFT (ic) = t;
3206     }
3207
3208
3209   /* if I can do an increment instead
3210      of add then GOOD for ME */
3211   if (genPlusIncr (ic) == TRUE)
3212     goto release;
3213
3214   emitcode("",";  left size = %d", getDataSize (IC_LEFT(ic)));
3215   emitcode("",";  right size = %d", getDataSize (IC_RIGHT(ic)));
3216   emitcode("",";  result size = %d", getDataSize (IC_RESULT(ic)));
3217   
3218   size = getDataSize (IC_RESULT (ic));
3219
3220   leftOp = AOP(IC_LEFT(ic));
3221   rightOp = AOP(IC_RIGHT(ic));
3222   add = "add";
3223
3224   offset = 0;
3225   while (size--)
3226     {
3227       loadRegFromAop (hc08_reg_a, leftOp, offset);
3228       accopWithAop(add, rightOp, offset);
3229       storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3230       hc08_freeReg (hc08_reg_a);
3231       add = "adc";  /* further adds must propagate carry */
3232     }
3233
3234
3235 //  adjustArithmeticResult (ic);
3236
3237 release:
3238   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3239   freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3240   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3241 }
3242
3243 /*-----------------------------------------------------------------*/
3244 /* genMinusDec :- does subtraction with deccrement if possible     */
3245 /*-----------------------------------------------------------------*/
3246 static bool
3247 genMinusDec (iCode * ic)
3248 {
3249   unsigned int icount;
3250   operand *left;
3251   operand *result;
3252   bool needpulx;
3253   bool needpulh;
3254   unsigned int size = getDataSize (IC_RESULT (ic));
3255 //  int offset;
3256 //  symbol *tlbl;
3257   
3258   left = IC_LEFT (ic);
3259   result = IC_RESULT (ic);
3260
3261   /* will try to generate an increment */
3262   /* if the right side is not a literal
3263      we cannot */
3264   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3265     return FALSE;
3266
3267   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3268
3269   if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3270       && (icount>=-127) && (icount<=128) && (size==2))
3271     {
3272       needpulx = pushRegIfUsed (hc08_reg_x);
3273       needpulh = pushRegIfUsed (hc08_reg_h);
3274       loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3275       emitcode ("aix","#%d", -icount);
3276       hc08_dirtyReg (hc08_reg_hx, FALSE);
3277       storeRegToAop (hc08_reg_hx, AOP(result), 0);
3278       pullOrFreeReg (hc08_reg_h, needpulh);
3279       pullOrFreeReg (hc08_reg_x, needpulx);
3280       return TRUE;
3281     }
3282   
3283   if ((icount > 1) || (icount<0))
3284     return FALSE;
3285
3286   if (!sameRegs (AOP (left), AOP (result)))
3287     return FALSE;
3288
3289   if (size!=1)
3290     return FALSE;
3291
3292   D(emitcode (";     genMinusDec",""));
3293
3294   rmwWithAop ("dec", AOP (result), 0);
3295   
3296   return TRUE;
3297 }
3298
3299 /*-----------------------------------------------------------------*/
3300 /* addSign - complete with sign                                    */
3301 /*-----------------------------------------------------------------*/
3302 static void
3303 addSign (operand * result, int offset, int sign)
3304 {
3305   int size = (getDataSize (result) - offset);
3306   if (size > 0)
3307     {
3308       if (sign)
3309         {
3310           emitcode ("rola", "");
3311           emitcode ("clra", "");
3312           emitcode ("sbc", zero);
3313           while (size--)
3314             storeRegToAop (hc08_reg_a, AOP (result), offset++);
3315         }
3316       else
3317         while (size--)
3318           storeConstToAop (zero, AOP (result), offset++);
3319     }
3320 }
3321
3322
3323 /*-----------------------------------------------------------------*/
3324 /* genMinus - generates code for subtraction                       */
3325 /*-----------------------------------------------------------------*/
3326 static void
3327 genMinus (iCode * ic)
3328 {
3329   char *sub;
3330   int size, offset = 0;
3331   
3332   asmop *leftOp, *rightOp;
3333
3334   D(emitcode (";     genMinus",""));
3335
3336   aopOp (IC_LEFT (ic), ic, FALSE);
3337   aopOp (IC_RIGHT (ic), ic, FALSE);
3338   aopOp (IC_RESULT (ic), ic, TRUE);
3339
3340   /* special cases :- */
3341   /* if I can do an decrement instead
3342      of subtract then GOOD for ME */
3343   if (genMinusDec (ic) == TRUE)
3344     goto release;
3345
3346   size = getDataSize (IC_RESULT (ic));
3347
3348
3349   leftOp = AOP(IC_LEFT(ic));
3350   rightOp = AOP(IC_RIGHT(ic));
3351
3352   sub = "sub";
3353   offset = 0;
3354   while (size--)
3355     {
3356       loadRegFromAop ( hc08_reg_a, leftOp, offset);
3357       accopWithAop(sub, rightOp, offset);
3358       storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3359       sub = "sbc";
3360     }
3361   
3362   
3363 //  adjustArithmeticResult (ic);
3364
3365 release:
3366   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3367   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3368   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3369 }
3370
3371
3372
3373 /*-----------------------------------------------------------------*/
3374 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3375 /*-----------------------------------------------------------------*/
3376 static void
3377 genMultOneByte (operand * left,
3378                 operand * right,
3379                 operand * result)
3380 {
3381   sym_link *opetype = operandType (result);
3382   symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3383   int size=AOP_SIZE(result);
3384   bool negLiteral = FALSE;
3385
3386   D(emitcode (";     genMultOneByte",""));
3387
3388   if (size<1 || size>2) {
3389     // this should never happen
3390       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3391                AOP_SIZE(result), __FILE__, lineno);
3392       exit (1);
3393   }
3394
3395   /* (if two literals: the value is computed before) */
3396   /* if one literal, literal on the right */
3397   if (AOP_TYPE (left) == AOP_LIT)
3398     {
3399       operand *t = right;
3400       right = left;
3401       left = t;
3402       //emitcode (";", "swapped left and right");
3403     }
3404
3405   if (SPEC_USIGN(opetype))
3406     {
3407       // just an unsigned 8*8=8/16 multiply
3408       //emitcode (";","unsigned");
3409
3410       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3411       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3412       emitcode ("mul", "");
3413       hc08_dirtyReg (hc08_reg_xa, FALSE);
3414       storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3415       hc08_freeReg (hc08_reg_xa);
3416       
3417       return;
3418     }
3419
3420   // we have to do a signed multiply
3421
3422
3423   //emitcode (";", "signed");
3424   adjustStack (-1);
3425   emitcode ("clr", "1,s");
3426
3427   tlbl1 = newiTempLabel (NULL);
3428   loadRegFromAop (hc08_reg_a, AOP (left), 0);
3429   emitcode ("tsta","");
3430   emitBranch ("bpl", tlbl1);
3431   emitcode ("inc", "1,s");
3432   rmwWithReg ("neg", hc08_reg_a);
3433   emitLabel (tlbl1);
3434
3435   if (AOP_TYPE(right)==AOP_LIT)
3436     {
3437       signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3438       /* AND literal negative */
3439       if (val < 0) {
3440         emitcode ("ldx", "#0x%02x", -val);
3441         negLiteral = TRUE;
3442       } else {
3443         emitcode ("ldx", "#0x%02x", val);
3444       }
3445       hc08_useReg (hc08_reg_x);
3446     }
3447   else
3448     {
3449       tlbl2 = newiTempLabel (NULL);
3450       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3451       emitcode ("tstx", "");
3452       emitBranch ("bpl", tlbl2);
3453       emitcode ("inc", "1,s");
3454       rmwWithReg ("neg", hc08_reg_x);
3455       emitLabel (tlbl2);
3456     }
3457
3458   emitcode ("mul", "");
3459   hc08_dirtyReg (hc08_reg_xa, FALSE);
3460
3461   tlbl3 = newiTempLabel (NULL);
3462   emitcode ("dec", "1,s");
3463   if (negLiteral)
3464     emitBranch ("bne", tlbl3);
3465   else
3466     emitBranch ("beq", tlbl3);
3467
3468   rmwWithReg ("neg", hc08_reg_a);
3469   if (size>1)
3470     {
3471       tlbl4 = newiTempLabel (NULL);
3472       emitBranch ("bcc", tlbl4);
3473       rmwWithReg ("inc", hc08_reg_x);
3474       emitLabel (tlbl4);
3475       rmwWithReg ("neg", hc08_reg_x);
3476     }
3477
3478   emitLabel (tlbl3);
3479   adjustStack (1);
3480   storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3481   hc08_freeReg (hc08_reg_xa);
3482
3483 }
3484
3485 /*-----------------------------------------------------------------*/
3486 /* genMult - generates code for multiplication                     */
3487 /*-----------------------------------------------------------------*/
3488 static void
3489 genMult (iCode * ic)
3490 {
3491   operand *left = IC_LEFT (ic);
3492   operand *right = IC_RIGHT (ic);
3493   operand *result = IC_RESULT (ic);
3494
3495   D(emitcode (";     genMult",""));
3496
3497   /* assign the amsops */
3498   aopOp (left, ic, FALSE);
3499   aopOp (right, ic, FALSE);
3500   aopOp (result, ic, TRUE);
3501
3502   /* special cases first */
3503   /* if both are of size == 1 */
3504 //  if (getSize(operandType(left)) == 1 && 
3505 //      getSize(operandType(right)) == 1)
3506   if (AOP_SIZE (left) == 1 && 
3507       AOP_SIZE (right) == 1)
3508     {
3509       genMultOneByte (left, right, result);
3510       goto release;
3511     }
3512
3513   /* should have been converted to function call */
3514     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3515              getSize(OP_SYMBOL(right)->type));
3516     fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3517              AOP_SIZE (right));
3518   assert (0);
3519
3520 release:
3521   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3522   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3523   freeAsmop (result, NULL, ic, TRUE);
3524 }
3525
3526 /*-----------------------------------------------------------------*/
3527 /* genDivOneByte : 8 bit division                                  */
3528 /*-----------------------------------------------------------------*/
3529 static void
3530 genDivOneByte (operand * left,
3531                operand * right,
3532                operand * result)
3533 {
3534   sym_link *opetype = operandType (result);
3535 //  char *l;
3536   symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3537   int size;
3538   bool negLiteral = FALSE;
3539
3540   D(emitcode (";     genDivOneByte",""));
3541
3542   size = AOP_SIZE (result);
3543   /* signed or unsigned */
3544   if (SPEC_USIGN (opetype))
3545     {
3546       /* unsigned is easy */
3547       loadRegFromAop (hc08_reg_h, AOP (left), 1);
3548       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3549       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3550       emitcode ("div", "");
3551       hc08_dirtyReg (hc08_reg_a, FALSE);
3552       hc08_dirtyReg (hc08_reg_h, FALSE);
3553       storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3554       hc08_freeReg (hc08_reg_a);
3555       hc08_freeReg (hc08_reg_x);
3556       hc08_freeReg (hc08_reg_h);
3557       return;
3558     }
3559
3560   /* signed is a little bit more difficult */
3561
3562   adjustStack (-1);
3563   emitcode ("clr", "1,s");
3564
3565   tlbl1 = newiTempLabel (NULL);
3566   tlbl2 = newiTempLabel (NULL);
3567   loadRegFromAop (hc08_reg_a, AOP (left), 0);
3568   loadRegFromAop (hc08_reg_x, AOP (left), 1);
3569   emitBranch ("bpl", tlbl1);
3570   emitcode ("inc", "1,s");
3571   rmwWithReg ("neg", hc08_reg_a);
3572   emitBranch ("bcc", tlbl2);
3573   rmwWithReg ("inc", hc08_reg_x);
3574   emitLabel (tlbl2);
3575   rmwWithReg ("neg", hc08_reg_x);
3576   transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3577   emitLabel (tlbl1);
3578
3579   if (AOP_TYPE(right)==AOP_LIT)
3580     {
3581       signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3582       /* AND literal negative */
3583       if (val < 0) {
3584         emitcode ("ldx", "#0x%02x", -val);
3585         negLiteral = TRUE;
3586       } else {
3587         emitcode ("ldx", "#0x%02x", val);
3588       }
3589       hc08_useReg (hc08_reg_x);
3590     }
3591   else
3592     {
3593       tlbl3 = newiTempLabel (NULL);
3594       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3595       emitBranch ("bpl", tlbl3);
3596       emitcode ("inc", "1,s");
3597       rmwWithReg ("neg", hc08_reg_x);
3598       emitLabel (tlbl3);
3599     }
3600
3601   emitcode ("div", "");
3602   hc08_dirtyReg (hc08_reg_x, FALSE);
3603   hc08_dirtyReg (hc08_reg_a, FALSE);
3604   hc08_dirtyReg (hc08_reg_h, FALSE);
3605
3606   tlbl4 = newiTempLabel (NULL);
3607   emitcode ("dec", "1,s");
3608   if (negLiteral)
3609     emitBranch ("bne", tlbl4);
3610   else
3611     emitBranch ("beq", tlbl4);
3612   rmwWithReg ("neg", hc08_reg_a);
3613
3614   emitLabel (tlbl4);
3615   adjustStack (1);
3616   storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3617   hc08_freeReg (hc08_reg_a);
3618   hc08_freeReg (hc08_reg_x);
3619   hc08_freeReg (hc08_reg_h);
3620
3621
3622 }
3623
3624 /*-----------------------------------------------------------------*/
3625 /* genDiv - generates code for division                            */
3626 /*-----------------------------------------------------------------*/
3627 static void
3628 genDiv (iCode * ic)
3629 {
3630   operand *left = IC_LEFT (ic);
3631   operand *right = IC_RIGHT (ic);
3632   operand *result = IC_RESULT (ic);
3633
3634   D(emitcode (";     genDiv",""));
3635
3636   /* assign the amsops */
3637   aopOp (left, ic, FALSE);
3638   aopOp (right, ic, FALSE);
3639   aopOp (result, ic, TRUE);
3640
3641   /* special cases first */
3642   /* if both are of size == 1 */
3643   if (AOP_SIZE (left) <= 2 &&
3644       AOP_SIZE (right) == 1)
3645     {
3646       genDivOneByte (left, right, result);
3647       goto release;
3648     }
3649
3650   /* should have been converted to function call */
3651   assert (0);
3652 release:
3653   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3654   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3655   freeAsmop (result, NULL, ic, TRUE);
3656 }
3657
3658 /*-----------------------------------------------------------------*/
3659 /* genModOneByte : 8 bit modulus                                   */
3660 /*-----------------------------------------------------------------*/
3661 static void
3662 genModOneByte (operand * left,
3663                operand * right,
3664                operand * result)
3665 {
3666   sym_link *opetype = operandType (result);
3667 //  symbol *lbl;
3668   symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3669   int size;
3670   bool negLiteral = FALSE;
3671
3672   D(emitcode (";     genModOneByte",""));
3673
3674   size = AOP_SIZE (result);
3675   /* signed or unsigned */
3676   if (SPEC_USIGN (opetype))
3677     {
3678       /* unsigned is easy */
3679       loadRegFromAop (hc08_reg_h, AOP (left), 1);
3680       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3681       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3682       emitcode ("div", "");
3683       hc08_dirtyReg (hc08_reg_a, FALSE);
3684       hc08_dirtyReg (hc08_reg_h, FALSE);
3685       storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3686       hc08_freeReg (hc08_reg_a);
3687       hc08_freeReg (hc08_reg_x);
3688       hc08_freeReg (hc08_reg_h);
3689       return;
3690     }
3691
3692   /* signed is a little bit more difficult */
3693
3694   adjustStack (-1);
3695   emitcode ("clr", "1,s");
3696
3697   tlbl1 = newiTempLabel (NULL);
3698   tlbl2 = newiTempLabel (NULL);
3699   loadRegFromAop (hc08_reg_a, AOP (left), 0);
3700   loadRegFromAop (hc08_reg_x, AOP (left), 1);
3701   emitBranch ("bpl", tlbl1);
3702   emitcode ("inc", "1,s");
3703   rmwWithReg ("neg", hc08_reg_a);
3704   emitBranch ("bcc", tlbl2);
3705   rmwWithReg ("inc", hc08_reg_x);
3706   emitLabel (tlbl2);
3707   rmwWithReg ("neg", hc08_reg_x);
3708   transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3709   emitLabel (tlbl1);
3710
3711   if (AOP_TYPE(right)==AOP_LIT)
3712     {
3713       signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3714       /* AND literal negative */
3715       if (val < 0) {
3716         emitcode ("ldx", "#0x%02x", -val);
3717         negLiteral = TRUE;
3718       } else {
3719         emitcode ("ldx", "#0x%02x", val);
3720       }
3721       hc08_useReg (hc08_reg_x);
3722     }
3723   else
3724     {
3725       tlbl3 = newiTempLabel (NULL);
3726       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3727       emitBranch ("bpl", tlbl3);
3728       emitcode ("inc", "1,s");
3729       rmwWithReg ("neg", hc08_reg_x);
3730       emitLabel (tlbl3);
3731     }
3732
3733   emitcode ("div", "");
3734   hc08_dirtyReg (hc08_reg_x, FALSE);
3735   hc08_dirtyReg (hc08_reg_a, FALSE);
3736   hc08_dirtyReg (hc08_reg_h, FALSE);
3737
3738   tlbl4 = newiTempLabel (NULL);
3739   transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3740   emitcode ("dec", "1,s");
3741   if (negLiteral)
3742     emitBranch ("bne", tlbl4);
3743   else
3744     emitBranch ("beq", tlbl4);
3745   rmwWithReg ("neg", hc08_reg_a);
3746
3747   emitLabel (tlbl4);
3748   adjustStack (1);
3749   storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3750   hc08_freeReg (hc08_reg_a);
3751   hc08_freeReg (hc08_reg_x);
3752   hc08_freeReg (hc08_reg_h);
3753
3754 }
3755
3756 /*-----------------------------------------------------------------*/
3757 /* genMod - generates code for division                            */
3758 /*-----------------------------------------------------------------*/
3759 static void
3760 genMod (iCode * ic)
3761 {
3762   operand *left = IC_LEFT (ic);
3763   operand *right = IC_RIGHT (ic);
3764   operand *result = IC_RESULT (ic);
3765
3766   D(emitcode (";     genMod",""));
3767
3768   /* assign the amsops */
3769   aopOp (left, ic, FALSE);
3770   aopOp (right, ic, FALSE);
3771   aopOp (result, ic, TRUE);
3772
3773   /* special cases first */
3774   /* if both are of size == 1 */
3775   if (AOP_SIZE (left) <= 2 &&
3776       AOP_SIZE (right) == 1)
3777     {
3778       genModOneByte (left, right, result);
3779       goto release;
3780     }
3781
3782   /* should have been converted to function call */
3783   assert (0);
3784
3785 release:
3786   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3787   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3788   freeAsmop (result, NULL, ic, TRUE);
3789 }
3790
3791 /*-----------------------------------------------------------------*/
3792 /* genIfxJump :- will create a jump depending on the ifx           */
3793 /*-----------------------------------------------------------------*/
3794 static void
3795 genIfxJump (iCode * ic, char *jval)
3796 {
3797   symbol *jlbl;
3798   symbol *tlbl = newiTempLabel (NULL);
3799   char *inst;
3800
3801   D(emitcode (";     genIfxJump",""));
3802
3803   /* if true label then we jump if condition
3804      supplied is true */
3805   if (IC_TRUE (ic))
3806     {
3807       jlbl = IC_TRUE (ic);
3808       if (!strcmp (jval, "a"))
3809         inst = "beq";
3810       else if (!strcmp (jval, "c"))
3811         inst = "bcc";
3812       else
3813         inst = "bge";
3814     }
3815   else
3816     {
3817       /* false label is present */
3818       jlbl = IC_FALSE (ic);
3819       if (!strcmp (jval, "a"))
3820         inst = "bne";
3821       else if (!strcmp (jval, "c"))
3822         inst = "bcs";
3823       else
3824         inst = "blt";
3825     }
3826   emitBranch (inst, tlbl);
3827   emitBranch ("jmp", jlbl);
3828   emitLabel (tlbl);
3829
3830   /* mark the icode as generated */
3831   ic->generated = 1;
3832 }
3833
3834 /*-----------------------------------------------------------------*/
3835 /* genCmp :- greater or less than comparison                       */
3836 /*-----------------------------------------------------------------*/
3837 static void
3838 genCmp (operand * left, operand * right,
3839         operand * result, iCode * ifx, int sign, iCode *ic)
3840 {
3841   int size, offset = 0;
3842   unsigned long lit = 0L;
3843   char *sub;
3844   bool needpula = FALSE;
3845
3846   D(emitcode (";     genCmp",""));
3847
3848   /* subtract right from left if at the
3849      end the carry flag is set then we know that
3850      left is greater than right */
3851   size = max (AOP_SIZE (left), AOP_SIZE (right));
3852
3853   if (AOP_TYPE (right) == AOP_LIT)
3854     {
3855       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3856       /* optimize if(x < 0) or if(x >= 0) */
3857       if (lit == 0L)
3858         {
3859           if (!sign)
3860             {
3861               CLRC;
3862             }
3863           else
3864             {
3865               needpula = pushRegIfUsed (hc08_reg_a);
3866               loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3867               emitcode ("rola", "");
3868               hc08_useReg (hc08_reg_a);
3869             }
3870           sign = 0;
3871           goto release;
3872         }
3873     }
3874
3875   if ((size==2)
3876       && ((AOP_TYPE (right) == AOP_LIT) || 
3877           ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3878       && hc08_reg_hx->isFree)
3879     {
3880       loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3881       emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3882       hc08_freeReg (hc08_reg_hx);
3883       goto release;
3884     }
3885
3886   offset = 0;
3887   if (size==1)
3888     sub="cmp";
3889   else
3890     sub="sub";
3891   while (size--)
3892     {
3893       loadRegFromAop (hc08_reg_a, AOP (left), offset);
3894       accopWithAop (sub, AOP (right), offset);
3895       hc08_freeReg (hc08_reg_a);
3896       offset++;
3897       sub="sbc";
3898     }
3899
3900 release:
3901   freeAsmop (right, NULL, ic, TRUE);
3902   freeAsmop (left, NULL, ic, TRUE);
3903   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3904     {
3905       outBitC (result);
3906     }
3907   else
3908     {
3909       /* if the result is used in the next
3910          ifx conditional branch then generate
3911          code a little differently */
3912       if (ifx)
3913         {
3914           pullOrFreeReg(hc08_reg_a,needpula);
3915           genIfxJump (ifx, sign ? "s" : "c");
3916         }
3917       else
3918         if (!sign)
3919           outBitC (result);
3920         else
3921           outBitNV (result);
3922         pullOrFreeReg(hc08_reg_a,needpula);
3923     }
3924 }
3925
3926 /*-----------------------------------------------------------------*/
3927 /* genCmpGt :- greater than comparison                             */
3928 /*-----------------------------------------------------------------*/
3929 static void
3930 genCmpGt (iCode * ic, iCode * ifx)
3931 {
3932   operand *left, *right, *result;
3933   sym_link *letype, *retype;
3934   int sign;
3935
3936   D(emitcode (";     genCmpGt",""));
3937
3938   result = IC_RESULT (ic);
3939   left = IC_LEFT (ic);
3940   right = IC_RIGHT (ic);
3941
3942   letype = getSpec (operandType (left));
3943   retype = getSpec (operandType (right));
3944   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3945   /* assign the amsops */
3946   aopOp (left, ic, FALSE);
3947   aopOp (right, ic, FALSE);
3948   aopOp (result, ic, TRUE);
3949
3950   genCmp (right, left, result, ifx, sign,ic);
3951
3952   freeAsmop (result, NULL, ic, TRUE);
3953 }
3954
3955 /*-----------------------------------------------------------------*/
3956 /* genCmpLt - less than comparisons                                */
3957 /*-----------------------------------------------------------------*/
3958 static void
3959 genCmpLt (iCode * ic, iCode * ifx)
3960 {
3961   operand *left, *right, *result;
3962   sym_link *letype, *retype;
3963   int sign;
3964
3965   D(emitcode (";     genCmpLt",""));
3966
3967   result = IC_RESULT (ic);
3968   left = IC_LEFT (ic);
3969   right = IC_RIGHT (ic);
3970
3971   letype = getSpec (operandType (left));
3972   retype = getSpec (operandType (right));
3973   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3974
3975   /* assign the amsops */
3976   aopOp (left, ic, FALSE);
3977   aopOp (right, ic, FALSE);
3978   aopOp (result, ic, TRUE);
3979
3980   genCmp (left, right, result, ifx, sign,ic);
3981
3982   freeAsmop (result, NULL, ic, TRUE);
3983 }
3984
3985 /*-----------------------------------------------------------------*/
3986 /*  - compare and branch if not equal                    */
3987 /*-----------------------------------------------------------------*/
3988 static void
3989 gencbneshort (operand * left, operand * right, symbol * lbl)
3990 {
3991   int size = max (AOP_SIZE (left), AOP_SIZE (right));
3992   int offset = 0;
3993   unsigned long lit = 0L;
3994
3995   /* if the left side is a literal or
3996      if the right is in a pointer register and left
3997      is not */
3998   if (AOP_TYPE (left) == AOP_LIT)
3999     {
4000       operand *t = right;
4001       right = left;
4002       left = t;
4003     }
4004   if (AOP_TYPE (right) == AOP_LIT)
4005     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4006
4007   while (size--)
4008     {
4009       loadRegFromAop (hc08_reg_a, AOP (left), offset);
4010       accopWithAop ("cmp", AOP (right), offset);
4011       hc08_useReg (hc08_reg_a);
4012       hc08_freeReg (hc08_reg_a);
4013       emitBranch ("bne", lbl);
4014       offset++;
4015     }
4016
4017 }
4018
4019 /*-----------------------------------------------------------------*/
4020 /* gencjne - compare and jump if not equal                         */
4021 /*-----------------------------------------------------------------*/
4022 static void
4023 gencjne (operand * left, operand * right, symbol * lbl)
4024 {
4025   symbol *tlbl = newiTempLabel (NULL);
4026
4027   gencbneshort (left, right, lbl);
4028
4029   loadRegFromConst (hc08_reg_a, one);
4030   emitBranch ("bra", tlbl);
4031   emitLabel (lbl);
4032   loadRegFromConst (hc08_reg_a, zero);
4033   emitLabel (tlbl);
4034
4035   hc08_useReg(hc08_reg_a);
4036   hc08_freeReg(hc08_reg_a);
4037 }
4038
4039 /*-----------------------------------------------------------------*/
4040 /* genCmpEq - generates code for equal to                          */
4041 /*-----------------------------------------------------------------*/
4042 static void
4043 genCmpEq (iCode * ic, iCode * ifx)
4044 {
4045   operand *left, *right, *result;
4046
4047   D(emitcode (";     genCmpEq",""));
4048
4049   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4050   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4051   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4052
4053   /* if literal, literal on the right or
4054      if the right is in a pointer register and left
4055      is not */
4056   if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4057     {
4058       operand *t = IC_RIGHT (ic);
4059       IC_RIGHT (ic) = IC_LEFT (ic);
4060       IC_LEFT (ic) = t;
4061     }
4062
4063   if (ifx && !AOP_SIZE (result))
4064     {
4065       symbol *tlbl;
4066       tlbl = newiTempLabel (NULL);
4067       gencbneshort (left, right, tlbl);
4068       if (IC_TRUE (ifx))
4069         {
4070           emitBranch ("jmp", IC_TRUE (ifx));
4071           emitLabel (tlbl);
4072         }
4073       else
4074         {
4075           symbol *lbl = newiTempLabel (NULL);
4076           emitBranch ("bra", lbl);
4077           emitLabel (tlbl);
4078           emitBranch ("jmp", IC_FALSE (ifx));
4079           emitLabel (lbl);
4080         }
4081       
4082       /* mark the icode as generated */
4083       ifx->generated = 1;
4084       goto release;
4085     }
4086
4087   gencjne (left, right, newiTempLabel (NULL));
4088   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4089     {
4090       storeRegToAop (hc08_reg_a, AOP (result), 0);
4091       goto release;
4092     }
4093   if (ifx)
4094     {
4095       genIfxJump (ifx, "a");
4096       goto release;
4097     }
4098   /* if the result is used in an arithmetic operation
4099      then put the result in place */
4100   if (AOP_TYPE (result) != AOP_CRY)
4101     outAcc (result);
4102
4103 release:
4104   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4105   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4106   freeAsmop (result, NULL, ic, TRUE);
4107 }
4108
4109 /*-----------------------------------------------------------------*/
4110 /* ifxForOp - returns the icode containing the ifx for operand     */
4111 /*-----------------------------------------------------------------*/
4112 static iCode *
4113 ifxForOp (operand * op, iCode * ic)
4114 {
4115   /* if true symbol then needs to be assigned */
4116   if (IS_TRUE_SYMOP (op))
4117     return NULL;
4118
4119   /* if this has register type condition and
4120      the next instruction is ifx with the same operand
4121      and live to of the operand is upto the ifx only then */
4122   if (ic->next &&
4123       ic->next->op == IFX &&
4124       IC_COND (ic->next)->key == op->key &&
4125       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4126     return ic->next;
4127
4128   return NULL;
4129 }
4130
4131 static bool
4132 genPointerGetSetOfs (iCode *ic)
4133 {
4134   iCode *lic = ic->next;
4135   bool pset, pget;
4136   int offset, size;
4137   symbol *sym;
4138   asmop *derefaop;
4139
4140   /* Make sure we have a next iCode */
4141   emitcode("","; checking lic");
4142   if (!lic)
4143     return FALSE;
4144
4145   /* Make sure the result of the addition is an iCode */
4146   emitcode("","; checking IS_ITEMP");
4147   if (!IS_ITEMP (IC_RESULT (ic)))
4148     return FALSE;
4149
4150   /* Make sure the next iCode is a pointer set or get */
4151   pset = POINTER_SET(lic);
4152   pget = POINTER_GET(lic);
4153   emitcode("","; pset=%d, pget=%d",pset,pget);
4154   if (!pset && !pget)
4155     return FALSE;
4156
4157   emitcode("", "; checking pset operandsEqu");
4158   if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4159     return FALSE;
4160
4161   emitcode("", "; checking pget operandsEqu");
4162   if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4163     return FALSE;
4164
4165   emitcode("", "; checking IS_SYMOP");
4166   if (!IS_SYMOP (IC_LEFT (ic)))
4167     return FALSE;
4168
4169   emitcode("", "; checking !IS_TRUE_SYMOP");
4170   if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4171     return FALSE;
4172
4173   sym = OP_SYMBOL (IC_LEFT (ic));
4174   
4175   emitcode("", "; checking remat");
4176   if (!sym->remat)
4177     return FALSE;
4178     
4179   if (pget)
4180     {
4181       D(emitcode (";     genPointerGetOfs",""));
4182       aopOp (IC_LEFT(ic), ic, FALSE);
4183       derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4184       freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4185       
4186       aopOp (IC_RIGHT(ic), ic, FALSE);
4187       aopOp (IC_RESULT(lic), lic, FALSE);
4188       
4189
4190       loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4191       size = AOP_SIZE (IC_RESULT(lic));
4192       derefaop->size = size;
4193       offset=0;
4194       
4195       while (size--)
4196         {
4197           emitcode ("lda", "%s,x",
4198                     aopAdrStr (derefaop, offset, TRUE));
4199           hc08_useReg (hc08_reg_a);
4200           storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4201           hc08_freeReg (hc08_reg_a);
4202         }
4203
4204       lic->generated = 1;
4205       hc08_freeReg (hc08_reg_hx);
4206
4207       freeAsmop (NULL, derefaop, ic, TRUE);
4208       freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4209       freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4210       
4211       return TRUE;
4212     }
4213
4214   if (pset)
4215     {
4216       D(emitcode (";     genPointerSetOfs",""));
4217       aopOp (IC_LEFT(ic), ic, FALSE);
4218       derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4219       freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4220
4221       aopOp (IC_RIGHT(ic), ic, FALSE);
4222       aopOp (IC_RIGHT(lic), lic, FALSE);
4223       
4224
4225       loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4226       size = AOP_SIZE (IC_RIGHT(lic));
4227       derefaop->size = size;
4228       offset=0;
4229       
4230       while (size--)
4231         {
4232           loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4233           emitcode ("sta", "%s,x",
4234                     aopAdrStr (derefaop, offset, TRUE));
4235           hc08_freeReg (hc08_reg_a);
4236           offset++;
4237         }
4238
4239       lic->generated = 1;
4240       hc08_freeReg (hc08_reg_hx);
4241
4242       freeAsmop (NULL, derefaop, ic, TRUE);
4243       freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4244       freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4245       
4246       return TRUE;
4247     }
4248     
4249   return FALSE;
4250 }
4251
4252
4253 /*-----------------------------------------------------------------*/
4254 /* hasInc - operand is incremented before any other use            */
4255 /*-----------------------------------------------------------------*/
4256 static iCode *
4257 hasInc (operand *op, iCode *ic,int osize)
4258 {
4259   sym_link *type = operandType(op);
4260   sym_link *retype = getSpec (type);
4261   iCode *lic = ic->next;
4262   int isize ;
4263   
4264   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4265   if (!IS_SYMOP(op)) return NULL;
4266
4267   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4268   if (IS_AGGREGATE(type->next)) return NULL;
4269   if (osize != (isize = getSize(type->next))) return NULL;
4270
4271   while (lic) {
4272     /* if operand of the form op = op + <sizeof *op> */
4273     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4274         isOperandEqual(IC_RESULT(lic),op) && 
4275         isOperandLiteral(IC_RIGHT(lic)) &&
4276         operandLitValue(IC_RIGHT(lic)) == isize) {
4277       return lic;
4278     }
4279     /* if the operand used or deffed */
4280     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4281       return NULL;
4282     }
4283     /* if GOTO or IFX */
4284     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4285     lic = lic->next;
4286   }
4287   return NULL;
4288 }
4289
4290 /*-----------------------------------------------------------------*/
4291 /* genAndOp - for && operation                                     */
4292 /*-----------------------------------------------------------------*/
4293 static void
4294 genAndOp (iCode * ic)
4295 {
4296   operand *left, *right, *result;
4297   symbol *tlbl, *tlbl0;
4298
4299   D(emitcode (";     genAndOp",""));
4300
4301   /* note here that && operations that are in an
4302      if statement are taken away by backPatchLabels
4303      only those used in arthmetic operations remain */
4304   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4305   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4306   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4307
4308   tlbl = newiTempLabel (NULL);
4309   tlbl0 = newiTempLabel (NULL);
4310   
4311   asmopToBool (AOP (left), FALSE);
4312   emitBranch ("beq", tlbl0);
4313   asmopToBool (AOP (right), FALSE);
4314   emitBranch ("beq", tlbl0);
4315   loadRegFromConst (hc08_reg_a,one);
4316   emitBranch ("bra", tlbl);
4317   emitLabel (tlbl0);
4318   loadRegFromConst (hc08_reg_a,zero);
4319   emitLabel (tlbl);
4320
4321   hc08_useReg (hc08_reg_a);
4322   hc08_freeReg (hc08_reg_a);
4323   
4324   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4325
4326   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4327   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4328   freeAsmop (result, NULL, ic, TRUE);
4329 }
4330
4331
4332 /*-----------------------------------------------------------------*/
4333 /* genOrOp - for || operation                                      */
4334 /*-----------------------------------------------------------------*/
4335 static void
4336 genOrOp (iCode * ic)
4337 {
4338   operand *left, *right, *result;
4339   symbol *tlbl, *tlbl0;
4340
4341   D(emitcode (";     genOrOp",""));
4342
4343   /* note here that || operations that are in an
4344      if statement are taken away by backPatchLabels
4345      only those used in arthmetic operations remain */
4346   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4347   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4348   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4349
4350   tlbl = newiTempLabel (NULL);
4351   tlbl0 = newiTempLabel (NULL);
4352   
4353   asmopToBool (AOP (left), FALSE);
4354   emitBranch ("bne", tlbl0);
4355   asmopToBool (AOP (right), FALSE);
4356   emitBranch ("bne", tlbl0);
4357   loadRegFromConst (hc08_reg_a,zero);
4358   emitBranch ("bra", tlbl);
4359   emitLabel (tlbl0);
4360   loadRegFromConst (hc08_reg_a,one);
4361   emitLabel (tlbl);
4362
4363   hc08_useReg (hc08_reg_a);
4364   hc08_freeReg (hc08_reg_a);
4365   
4366   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4367
4368
4369   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4370   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4371   freeAsmop (result, NULL, ic, TRUE);
4372 }
4373
4374 /*-----------------------------------------------------------------*/
4375 /* isLiteralBit - test if lit == 2^n                               */
4376 /*-----------------------------------------------------------------*/
4377 static int
4378 isLiteralBit (unsigned long lit)
4379 {
4380   unsigned long pw[32] =
4381   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4382    0x100L, 0x200L, 0x400L, 0x800L,
4383    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4384    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4385    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4386    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4387    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4388   int idx;
4389
4390   for (idx = 0; idx < 32; idx++)
4391     if (lit == pw[idx])
4392       return idx + 1;
4393   return 0;
4394 }
4395
4396 #if 0
4397 /*-----------------------------------------------------------------*/
4398 /* continueIfTrue -                                                */
4399 /*-----------------------------------------------------------------*/
4400 static void
4401 continueIfTrue (iCode * ic)
4402 {
4403   if (IC_TRUE (ic))
4404     emitBranch ("jmp", IC_TRUE (ic));
4405   ic->generated = 1;
4406 }
4407
4408 /*-----------------------------------------------------------------*/
4409 /* jmpIfTrue -                                                     */
4410 /*-----------------------------------------------------------------*/
4411 static void
4412 jumpIfTrue (iCode * ic)
4413 {
4414   if (!IC_TRUE (ic))
4415     emitBranch ("jmp", IC_FALSE (ic));
4416   ic->generated = 1;
4417 }
4418
4419 /*-----------------------------------------------------------------*/
4420 /* jmpTrueOrFalse -                                                */
4421 /*-----------------------------------------------------------------*/
4422 static void
4423 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4424 {
4425   // ugly but optimized by peephole
4426   if (IC_TRUE (ic))
4427     {
4428       symbol *nlbl = newiTempLabel (NULL);
4429       emitBranch ("bra", nlbl);
4430       emitLabel (tlbl);
4431       emitBranch ("jmp", IC_TRUE (ic));
4432       emitLabel (nlbl);
4433     }
4434   else
4435     {
4436       emitBranch ("jmp", IC_FALSE (ic));
4437       emitLabel (tlbl);
4438     }
4439   ic->generated = 1;
4440 }
4441 #endif
4442
4443 /*-----------------------------------------------------------------*/
4444 /* genAnd  - code for and                                          */
4445 /*-----------------------------------------------------------------*/
4446 static void
4447 genAnd (iCode * ic, iCode * ifx)
4448 {
4449   operand *left, *right, *result;
4450   int size, offset = 0;
4451   unsigned long lit = 0L;
4452   unsigned long litinv;
4453
4454   
4455 //  int bytelit = 0;
4456 //  char buffer[10];
4457
4458   D(emitcode (";     genAnd",""));
4459
4460   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4461   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4462   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4463
4464 #ifdef DEBUG_TYPE
4465   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4466             AOP_TYPE (result),
4467             AOP_TYPE (left), AOP_TYPE (right));
4468   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4469             AOP_SIZE (result),
4470             AOP_SIZE (left), AOP_SIZE (right));
4471 #endif
4472
4473   /* if left is a literal & right is not then exchange them */
4474   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4475     {
4476       operand *tmp = right;
4477       right = left;
4478       left = tmp;
4479     }
4480
4481   /* if left is accumulator & right is not then exchange them */
4482   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4483     {
4484       operand *tmp = right;
4485       right = left;
4486       left = tmp;
4487     }
4488
4489   size = AOP_SIZE (result);
4490
4491   if (AOP_TYPE (right) == AOP_LIT)
4492     {
4493       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4494       litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4495
4496       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4497           (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4498         {
4499           int bitpos = isLiteralBit(litinv)-1;
4500           emitcode ("bclr","#%d,%s",bitpos & 7,
4501                     aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4502           goto release;
4503         }
4504     }
4505
4506   offset = 0;
4507   while (size--)
4508     {
4509       loadRegFromAop (hc08_reg_a, AOP (left), offset);
4510       if ((AOP_TYPE (right) != AOP_LIT)
4511           || (((lit >> (offset*8)) & 0xff) != 0xff))
4512         accopWithAop ("and", AOP (right), offset);
4513       storeRegToAop (hc08_reg_a, AOP (result), offset++);
4514       hc08_freeReg( hc08_reg_a);      
4515     }
4516
4517 release:
4518   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4519   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4520   freeAsmop (result, NULL, ic, TRUE);
4521 }
4522
4523 /*-----------------------------------------------------------------*/
4524 /* genOr  - code for or                                            */
4525 /*-----------------------------------------------------------------*/
4526 static void
4527 genOr (iCode * ic, iCode * ifx)
4528 {
4529   operand *left, *right, *result;
4530   int size, offset = 0;
4531   unsigned long lit = 0L;
4532
4533   D(emitcode (";     genOr",""));
4534
4535   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4536   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4537   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4538
4539 #ifdef DEBUG_TYPE
4540   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4541             AOP_TYPE (result),
4542             AOP_TYPE (left), AOP_TYPE (right));
4543   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4544             AOP_SIZE (result),
4545             AOP_SIZE (left), AOP_SIZE (right));
4546 #endif
4547
4548   /* if left is a literal & right is not then exchange them */
4549   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4550     {
4551       operand *tmp = right;
4552       right = left;
4553       left = tmp;
4554     }
4555
4556   /* if left is accumulator & right is not then exchange them */
4557   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4558     {
4559       operand *tmp = right;
4560       right = left;
4561       left = tmp;
4562     }
4563
4564   /* if right is bit then exchange them */
4565   if (AOP_TYPE (right) == AOP_CRY &&
4566       AOP_TYPE (left) != AOP_CRY)
4567     {
4568       operand *tmp = right;
4569       right = left;
4570       left = tmp;
4571     }
4572   if (AOP_TYPE (right) == AOP_LIT)
4573     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4574
4575   size = AOP_SIZE (result);
4576
4577   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4578       (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4579       (AOP_TYPE (left) == AOP_DIR))
4580     {
4581       int bitpos = isLiteralBit(lit)-1;
4582       emitcode ("bset","#%d,%s",bitpos & 7,
4583                 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4584       goto release;
4585     }
4586     
4587
4588
4589   offset = 0;
4590   while (size--)
4591     {
4592       loadRegFromAop (hc08_reg_a, AOP (left), offset);
4593       accopWithAop ("ora", AOP (right), offset);
4594       storeRegToAop (hc08_reg_a, AOP (result), offset++);
4595       hc08_freeReg( hc08_reg_a);      
4596     }
4597
4598
4599 release:
4600   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4601   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4602   freeAsmop (result, NULL, ic, TRUE);
4603 }
4604
4605 /*-----------------------------------------------------------------*/
4606 /* genXor - code for xclusive or                                   */
4607 /*-----------------------------------------------------------------*/
4608 static void
4609 genXor (iCode * ic, iCode * ifx)
4610 {
4611   operand *left, *right, *result;
4612   int size, offset = 0;
4613   unsigned long lit = 0L;
4614
4615   D(emitcode (";     genXor",""));
4616
4617   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4618   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4619   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4620
4621 #ifdef DEBUG_TYPE
4622   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4623             AOP_TYPE (result),
4624             AOP_TYPE (left), AOP_TYPE (right));
4625   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4626             AOP_SIZE (result),
4627             AOP_SIZE (left), AOP_SIZE (right));
4628 #endif
4629
4630   /* if left is a literal & right is not ||
4631      if left needs acc & right does not */
4632   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4633     {
4634       operand *tmp = right;
4635       right = left;
4636       left = tmp;
4637     }
4638
4639   /* if left is accumulator & right is not then exchange them */
4640   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4641     {
4642       operand *tmp = right;
4643       right = left;
4644       left = tmp;
4645     }
4646
4647   /* if right is bit then exchange them */
4648   if (AOP_TYPE (right) == AOP_CRY &&
4649       AOP_TYPE (left) != AOP_CRY)
4650     {
4651       operand *tmp = right;
4652       right = left;
4653       left = tmp;
4654     }
4655   if (AOP_TYPE (right) == AOP_LIT)
4656     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4657
4658   size = AOP_SIZE (result);
4659   offset = 0;
4660   while (size--)
4661     {
4662       loadRegFromAop (hc08_reg_a, AOP (left), offset);
4663       accopWithAop ("eor", AOP (right), offset);
4664       storeRegToAop (hc08_reg_a, AOP (result), offset++);
4665       hc08_freeReg( hc08_reg_a);      
4666     }
4667
4668
4669 //release:
4670   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4671   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4672   freeAsmop (result, NULL, ic, TRUE);
4673 }
4674
4675 static void
4676 emitinline (iCode * ic, char *inlin)
4677 {
4678   char buffer[512];
4679   char *symname;
4680   char c;
4681   char *bp=buffer;
4682   symbol *sym, *tempsym;
4683   asmop *aop;
4684   char *l;
4685   
4686   while (*inlin)
4687     {
4688       if (*inlin == '_')
4689         {
4690           symname = ++inlin;
4691           while (isalnum(*inlin) || (*inlin == '_'))
4692             inlin++;
4693           c = *inlin;
4694           *inlin = '\0';
4695           //printf("Found possible symbol '%s'\n",symname);
4696           tempsym = newSymbol (symname, ic->level);
4697           tempsym->block = ic->block;
4698           sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4699           *inlin = c;
4700           if (!sym)
4701             {
4702               *bp++ = '_';
4703               inlin = symname;
4704             }
4705           else
4706             {
4707               aop = aopForSym (ic, sym, FALSE);
4708               l = aopAdrStr (aop, aop->size - 1, TRUE);
4709               if (*l=='#')
4710                 l++;
4711               sym->isref = 1;
4712               if (!sym->allocreq && !sym->ismyparm)
4713                 {
4714                   werror (E_ID_UNDEF, sym->name);
4715                   werror (W_CONTINUE,
4716                           "  Add 'volatile' to the variable declaration so that it\n"
4717                           "  can be referenced within inline assembly");
4718                 }
4719               //printf("Replacing with '%s'\n",l);
4720               while (*l)
4721                 {
4722                   *bp++ = *l++;
4723                   if ((2+bp-buffer)>sizeof(buffer))
4724                     goto endofline;
4725                 }
4726             }
4727         }
4728       else
4729         {
4730           *bp++ = *inlin++;
4731         }
4732       if ((2+bp-buffer)>sizeof(buffer))
4733         goto endofline;
4734     }
4735
4736 endofline:
4737   *bp = '\0';
4738
4739   if ((2+bp-buffer)>sizeof(buffer))
4740     fprintf(stderr, "Inline assembly buffer overflow\n");
4741   
4742   //printf("%s\n",buffer);
4743   emitcode (buffer,"");
4744 }
4745
4746
4747 /*-----------------------------------------------------------------*/
4748 /* genInline - write the inline code out                           */
4749 /*-----------------------------------------------------------------*/
4750 static void
4751 genInline (iCode * ic)
4752 {
4753   char *buffer, *bp, *bp1;
4754
4755   D(emitcode (";     genInline",""));
4756
4757   _G.inLine += (!options.asmpeep);
4758
4759   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4760   strcpy (buffer, IC_INLINE (ic));
4761
4762   /* emit each line as a code */
4763   while (*bp)
4764     {
4765       if (*bp == '\n')
4766         {
4767           *bp++ = '\0';
4768           /* emitcode (bp1, ""); */
4769           emitinline (ic, bp1);
4770           bp1 = bp;
4771         }
4772       else
4773         {
4774           if (*bp == ':')
4775             {
4776               bp++;
4777               *bp = '\0';
4778               bp++;
4779               emitcode (bp1, "");
4780               bp1 = bp;
4781             }
4782           else
4783             bp++;
4784         }
4785     }
4786   if (bp1 != bp)
4787     {
4788       /* emitcode (bp1, ""); */
4789       emitinline (ic, bp1);
4790     }
4791   /*     emitcode("",buffer); */
4792   _G.inLine -= (!options.asmpeep);
4793 }
4794
4795 /*-----------------------------------------------------------------*/
4796 /* genRRC - rotate right with carry                                */
4797 /*-----------------------------------------------------------------*/
4798 static void
4799 genRRC (iCode * ic)
4800 {
4801   operand *left, *result;
4802   int size, offset = 0;
4803   bool needpula = FALSE;
4804   bool resultInA = FALSE;
4805   char *shift;
4806
4807   D(emitcode (";     genRRC",""));
4808
4809   /* rotate right with carry */
4810   left = IC_LEFT (ic);
4811   result = IC_RESULT (ic);
4812   aopOp (left, ic, FALSE);
4813   aopOp (result, ic, FALSE);
4814
4815   if ((AOP_TYPE (result) == AOP_REG)
4816       && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4817    resultInA = TRUE;
4818
4819   size = AOP_SIZE (result);
4820   offset = size-1;
4821
4822   shift="lsr";
4823   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4824     {
4825       while (size--)
4826         {
4827           rmwWithAop (shift, AOP (result), offset--);
4828           shift="ror";
4829         }
4830     }
4831   else
4832     {
4833       while (size--)
4834         {
4835           loadRegFromAop (hc08_reg_a, AOP (left), offset);
4836           rmwWithReg (shift, hc08_reg_a);
4837           storeRegToAop (hc08_reg_a, AOP (result), offset--);
4838           hc08_freeReg (hc08_reg_a);
4839           shift="ror";
4840         }
4841     }
4842
4843   if ((!hc08_reg_a->isFree) || resultInA)
4844     {
4845       pushReg (hc08_reg_a, TRUE);
4846       needpula = TRUE;
4847     }
4848
4849   /* now we need to put the carry into the
4850      highest order byte of the result */
4851   offset = AOP_SIZE (result) - 1;
4852   emitcode ("clra","");
4853   emitcode ("rora","");
4854   hc08_dirtyReg (hc08_reg_a, FALSE);
4855   if (resultInA)
4856     {
4857       emitcode ("ora", "1,s");
4858       emitcode ("ais", "#1");
4859       hc08_dirtyReg (hc08_reg_a, FALSE);
4860       needpula = FALSE;
4861     }
4862   else
4863     accopWithAop ("ora", AOP (result), offset);
4864   storeRegToAop (hc08_reg_a, AOP (result), offset);
4865
4866   pullOrFreeReg (hc08_reg_a, needpula);
4867
4868   freeAsmop (left, NULL, ic, TRUE);
4869   freeAsmop (result, NULL, ic, TRUE);
4870 }
4871
4872 /*-----------------------------------------------------------------*/
4873 /* genRLC - generate code for rotate left with carry               */
4874 /*-----------------------------------------------------------------*/
4875 static void
4876 genRLC (iCode * ic)
4877 {
4878   operand *left, *result;
4879   int size, offset = 0;
4880   char *shift;
4881   bool resultInA = FALSE;
4882   bool needpula = FALSE;
4883
4884   D(emitcode (";     genRLC",""));
4885
4886   /* rotate right with carry */
4887   left = IC_LEFT (ic);
4888   result = IC_RESULT (ic);
4889   aopOp (left, ic, FALSE);
4890   aopOp (result, ic, FALSE);
4891
4892   if ((AOP_TYPE (result) == AOP_REG)
4893       && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4894    resultInA = TRUE;
4895
4896   size = AOP_SIZE (result);
4897   offset = 0;
4898
4899   shift="lsl";
4900   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4901     {
4902       while (size--)
4903         {
4904           rmwWithAop (shift, AOP (result), offset--);
4905           shift="rol";
4906         }
4907     }
4908   else
4909     {
4910       while (size--)
4911         {
4912           loadRegFromAop (hc08_reg_a, AOP (left), offset);
4913           rmwWithReg (shift, hc08_reg_a);
4914           storeRegToAop (hc08_reg_a, AOP (result), offset++);
4915           hc08_freeReg (hc08_reg_a);
4916           shift="rol";
4917         }
4918     }
4919
4920   if ((!hc08_reg_a->isFree) || resultInA)
4921     {
4922       pushReg (hc08_reg_a, TRUE);
4923       needpula = TRUE;
4924     }
4925
4926   /* now we need to put the carry into the
4927      lowest order byte of the result */
4928   offset = 0;
4929   emitcode ("clra","");
4930   emitcode ("rola","");
4931   hc08_dirtyReg (hc08_reg_a, FALSE);
4932   if (resultInA)
4933     {
4934       emitcode ("ora", "1,s");
4935       emitcode ("ais", "#1");
4936       hc08_dirtyReg (hc08_reg_a, FALSE);
4937       needpula = FALSE;
4938     }
4939   else
4940     accopWithAop ("ora", AOP (result), offset);
4941   storeRegToAop (hc08_reg_a, AOP (result), offset);
4942
4943   pullOrFreeReg (hc08_reg_a, needpula);
4944
4945   freeAsmop (left, NULL, ic, TRUE);
4946   freeAsmop (result, NULL, ic, TRUE);
4947 }
4948
4949 /*-----------------------------------------------------------------*/
4950 /* genGetHbit - generates code get highest order bit               */
4951 /*-----------------------------------------------------------------*/
4952 static void
4953 genGetHbit (iCode * ic)
4954 {
4955   operand *left, *result;
4956
4957   D(emitcode (";     genGetHbit",""));
4958
4959   left = IC_LEFT (ic);
4960   result = IC_RESULT (ic);
4961   aopOp (left, ic, FALSE);
4962   aopOp (result, ic, FALSE);
4963
4964   /* get the highest order byte into a */
4965   loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
4966   emitcode ("rola", "");
4967   emitcode ("clra", "");
4968   emitcode ("rola", "");
4969   hc08_dirtyReg (hc08_reg_a, FALSE);
4970   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4971   
4972   freeAsmop (left, NULL, ic, TRUE);
4973   freeAsmop (result, NULL, ic, TRUE);
4974 }
4975
4976 #if 0
4977 /*-----------------------------------------------------------------*/
4978 /* AccRol - rotate left accumulator by known count                 */
4979 /*-----------------------------------------------------------------*/
4980 static void
4981 AccRol (int shCount)
4982 {
4983   shCount &= 0x0007;            // shCount : 0..7
4984
4985   switch (shCount)
4986     {
4987     case 0:
4988       break;
4989     case 1:
4990       emitcode ("rola", "");    /* 1 cycle */
4991       break;
4992     case 2:
4993       emitcode ("rola", "");    /* 1 cycle */
4994       emitcode ("rola", "");    /* 1 cycle */
4995       break;
4996     case 3:
4997       emitcode ("nsa", "");
4998       emitcode ("rora", "");
4999       break;
5000     case 4:
5001       emitcode ("nsa", "");     /* 3 cycles */
5002       break;
5003     case 5:
5004       emitcode ("nsa", "");     /* 3 cycles */
5005       emitcode ("rola", "");    /* 1 cycle */
5006       break;
5007     case 6:
5008       emitcode ("nsa", "");     /* 3 cycles */
5009       emitcode ("rola", "");    /* 1 cycle */
5010       emitcode ("rola", "");    /* 1 cycle */
5011       break;
5012     case 7:
5013       emitcode ("nsa", "");     /* 3 cycles */
5014       emitcode ("rola", "");    /* 1 cycle */
5015       emitcode ("rola", "");    /* 1 cycle */
5016       emitcode ("rola", "");    /* 1 cycle */
5017       break;
5018     }
5019 }
5020 #endif
5021
5022
5023 /*-----------------------------------------------------------------*/
5024 /* AccLsh - left shift accumulator by known count                  */
5025 /*-----------------------------------------------------------------*/
5026 static void
5027 AccLsh (int shCount)
5028 {
5029   int i;
5030   
5031   shCount &= 0x0007;            // shCount : 0..7
5032
5033   /* Shift counts of 4 and 5 are currently optimized for code size.        */
5034   /* Falling through to the unrolled loop would be optimal for code speed. */
5035   /* For shift counts of 6 and 7, the unrolled loop is never optimal.      */
5036   switch (shCount)
5037     {
5038     case 4:
5039       accopWithMisc ("nsa", "");
5040       accopWithMisc ("and", "#0xf0");
5041       /* total: 5 cycles, 3 bytes */
5042       return;
5043     case 5:
5044       accopWithMisc ("nsa", "");
5045       accopWithMisc ("and", "#0xf0");
5046       accopWithMisc ("lsla", "");
5047       /* total: 6 cycles, 4 bytes */
5048       return;
5049     case 6:
5050       accopWithMisc ("rora", "");
5051       accopWithMisc ("rora", "");
5052       accopWithMisc ("rora", "");
5053       accopWithMisc ("and", "#0xc0");
5054       /* total: 5 cycles, 5 bytes */
5055       return;
5056     case 7:
5057       accopWithMisc ("rora", "");
5058       accopWithMisc ("clra", "");
5059       accopWithMisc ("rora", "");
5060       /* total: 3 cycles, 3 bytes */
5061       return;
5062     }
5063
5064     /* lsla is only 1 cycle and byte, so an unrolled loop is often  */
5065     /* the fastest (shCount<6) and shortest (shCount<4).            */
5066     for (i=0;i<shCount;i++)
5067       accopWithMisc ("lsla", "");
5068 }
5069
5070
5071 /*-----------------------------------------------------------------*/
5072 /* AccSRsh - signed right shift accumulator by known count         */
5073 /*-----------------------------------------------------------------*/
5074 static void
5075 AccSRsh (int shCount)
5076 {
5077   int i;
5078   
5079   shCount &= 0x0007;            // shCount : 0..7
5080
5081   if (shCount == 7)
5082     {
5083       accopWithMisc ("rola", "");
5084       accopWithMisc ("clra", "");
5085       accopWithMisc ("sbc", zero);
5086       /* total: 4 cycles, 4 bytes */
5087       return;
5088     }
5089
5090     for (i=0;i<shCount;i++)
5091       accopWithMisc ("asra", "");
5092 }
5093
5094 /*-----------------------------------------------------------------*/
5095 /* AccRsh - right shift accumulator by known count                 */
5096 /*-----------------------------------------------------------------*/
5097 static void
5098 AccRsh (int shCount, bool sign)
5099 {
5100   int i;
5101   
5102   if (sign)
5103     {
5104       AccSRsh (shCount);
5105       return;
5106     }
5107   
5108   shCount &= 0x0007;            // shCount : 0..7
5109
5110   /* Shift counts of 4 and 5 are currently optimized for code size.        */
5111   /* Falling through to the unrolled loop would be optimal for code speed. */
5112   /* For shift counts of 6 and 7, the unrolled loop is never optimal.      */
5113   switch (shCount)
5114     {
5115     case 4:
5116       accopWithMisc ("nsa", "");
5117       accopWithMisc ("and", "#0x0f");
5118       /* total: 5 cycles, 3 bytes */
5119       return;
5120     case 5:
5121       accopWithMisc ("nsa", "");
5122       accopWithMisc ("and", "#0x0f");
5123       accopWithMisc ("lsra", "");
5124       /* total: 6 cycles, 4 bytes */
5125       return;
5126     case 6:
5127       accopWithMisc ("rola", "");
5128       accopWithMisc ("rola", "");
5129       accopWithMisc ("rola", "");
5130       accopWithMisc ("and", "#0x03");
5131       /* total: 5 cycles, 5 bytes */
5132       return;
5133     case 7:
5134       accopWithMisc ("rola", "");
5135       accopWithMisc ("clra", "");
5136       accopWithMisc ("rola", "");
5137       /* total: 3 cycles, 3 bytes */
5138       return;
5139     }
5140
5141     /* lsra is only 1 cycle and byte, so an unrolled loop is often  */
5142     /* the fastest (shCount<6) and shortest (shCount<4).            */
5143     for (i=0;i<shCount;i++)
5144       accopWithMisc ("lsra", "");
5145 }
5146
5147
5148 /*-----------------------------------------------------------------*/
5149 /* XAccLsh - left shift register pair XA by known count            */
5150 /*-----------------------------------------------------------------*/
5151 static void
5152 XAccLsh (int shCount)
5153 {
5154   int i;
5155   
5156   shCount &= 0x000f;            // shCount : 0..15
5157
5158   if (shCount>=8)
5159     {
5160       AccLsh (shCount-8);
5161       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5162       loadRegFromConst (hc08_reg_a, zero);
5163       return;
5164     }
5165
5166   /* if we can beat 2n cycles or bytes for some special case, do it here */
5167   switch (shCount)
5168     {
5169     case 7:
5170       /*          bytes  cycles     reg x      reg a   carry
5171       **                          abcd efgh  ijkl mnop   ?
5172       **   lsrx       1  1        0abc defg  ijkl mnop   h
5173       **   rora       1  1        0abc defg  hijk lmno   p
5174       **   tax        1  1        hijk lmno  hijk lmno   p
5175       **   clra       1  1        hijk lmno  0000 0000   p
5176       **   rora       1  1        hijk lmno  p000 0000   0
5177       ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5178       */
5179       rmwWithReg ("lsr", hc08_reg_x);
5180       rmwWithReg ("ror", hc08_reg_a);
5181       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5182       loadRegFromConst (hc08_reg_a, zero);
5183       rmwWithReg ("ror", hc08_reg_a);
5184       return;
5185
5186     default:
5187       ;
5188     }
5189
5190   /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often  */
5191   /* the fastest and shortest.                                           */
5192   for (i=0;i<shCount;i++)
5193     {
5194       rmwWithReg ("lsl", hc08_reg_a);
5195       rmwWithReg ("rol", hc08_reg_x);
5196     }
5197 }
5198
5199 /*-----------------------------------------------------------------*/
5200 /* XAccSRsh - signed right shift register pair XA by known count   */
5201 /*-----------------------------------------------------------------*/
5202 static void
5203 XAccSRsh (int shCount)
5204 {
5205   int i;
5206   
5207   shCount &= 0x000f;            // shCount : 0..7
5208
5209   /* if we can beat 2n cycles or bytes for some special case, do it here */
5210   switch (shCount)
5211     {
5212     case 15:
5213       /*          bytes  cycles     reg x      reg a   carry
5214       **                          abcd efgh  ijkl mnop   ?
5215       **   lslx       1  1        bcde fgh0  ijkl mnop   a
5216       **   clra       1  1        bcde fgh0  0000 0000   a
5217       **   rola       1  1        bcde fgh0  0000 000a   0
5218       **   nega       1  1        bcde fgh0  aaaa aaaa   a
5219       **   tax        1  1        aaaa aaaa  aaaa aaaa   a
5220       ** total: 5 cycles, 5 bytes
5221       */
5222       rmwWithReg ("lsl", hc08_reg_x);
5223       loadRegFromConst (hc08_reg_a, zero);
5224       rmwWithReg ("rol", hc08_reg_a);
5225       rmwWithReg ("neg", hc08_reg_a);
5226       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5227       return;
5228
5229     case 14:
5230     case 13:
5231     case 12:
5232     case 11:
5233     case 10:
5234     case 9:
5235     case 8:
5236       /*          bytes  cycles     reg x      reg a   carry
5237       **                          abcd efgh  ijkl mnop   ?
5238       **   txa        1  1        abcd efgh  abcd efgh   ?
5239       **   (AccSRsh) <8 <8        abcd efgh  LSBresult   ?
5240       **   lsla       1  1        abcd efgh  ???? ????   a
5241       **   clrx       1  1        0000 0000  ???? ????   a
5242       **   rolx       1  1        0000 000a  ???? ????   0
5243       **   negx       1  1        aaaa aaaa  ???? ????   a
5244       **   rora       1  1        aaaa aaaa  LSBresult   0
5245       ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5246       */
5247       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5248       AccSRsh (shCount-8);
5249       rmwWithReg ("lsl", hc08_reg_a);
5250       loadRegFromConst (hc08_reg_x, zero);
5251       rmwWithReg ("rol", hc08_reg_x);
5252       rmwWithReg ("neg", hc08_reg_x);
5253       rmwWithReg ("ror", hc08_reg_a);
5254       return;
5255
5256     default:
5257       ;
5258     }
5259
5260   /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often  */
5261   /* the fastest and shortest.                                           */
5262   for (i=0;i<shCount;i++)
5263     {
5264       rmwWithReg ("asr", hc08_reg_x);
5265       rmwWithReg ("ror", hc08_reg_a);
5266     }
5267 }
5268
5269 /*-----------------------------------------------------------------*/
5270 /* XAccRsh - right shift register pair XA by known count           */
5271 /*-----------------------------------------------------------------*/
5272 static void
5273 XAccRsh (int shCount, bool sign)
5274 {
5275   int i;
5276   
5277   if (sign)
5278     {
5279       XAccSRsh (shCount);
5280       return;
5281     }
5282   
5283   shCount &= 0x000f;            // shCount : 0..f
5284
5285   /* if we can beat 2n cycles or bytes for some special case, do it here */
5286   switch (shCount)
5287     {
5288     case 15:
5289       /*          bytes  cycles     reg x      reg a   carry
5290       **                          abcd efgh  ijkl mnop   ?
5291       **   clra       1  1        abcd efgh  0000 0000   a
5292       **   lslx       1  1        bcde fgh0  0000 0000   a
5293       **   rola       1  1        bcde fgh0  0000 000a   0
5294       **   clrx       1  1        0000 0000  0000 000a   0
5295       ** total: 4 cycles, 4 bytes
5296       */
5297       loadRegFromConst (hc08_reg_x, zero);
5298       rmwWithReg ("lsl", hc08_reg_x);
5299       rmwWithReg ("rol", hc08_reg_a);
5300       loadRegFromConst (hc08_reg_a, zero);
5301       return;
5302
5303     case 14:
5304       /*          bytes  cycles     reg x      reg a   carry
5305       **                          abcd efgh  ijkl mnop   ?
5306       **   clra       1  1        abcd efgh  0000 0000   a
5307       **   lslx       1  1        bcde fgh0  0000 0000   a
5308       **   rola       1  1        bcde fgh0  0000 000a   0
5309       **   lslx       1  1        cdef gh00  0000 000a   b
5310       **   rola       1  1        cdef gh00  0000 00ab   0
5311       **   clrx       1  1        0000 0000  0000 000a   0
5312       ** total: 6 cycles, 6 bytes
5313       */
5314       loadRegFromConst (hc08_reg_x, zero);
5315       rmwWithReg ("lsl", hc08_reg_x);
5316       rmwWithReg ("rol", hc08_reg_a);
5317       rmwWithReg ("lsl", hc08_reg_x);
5318       rmwWithReg ("rol", hc08_reg_a);
5319       loadRegFromConst (hc08_reg_a, zero);
5320       return;
5321
5322     case 13:
5323     case 12:
5324     case 11:
5325     case 10:
5326     case 9:
5327     case 8:
5328       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5329       AccRsh (shCount-8, FALSE);
5330       loadRegFromConst (hc08_reg_x, zero);
5331       return;
5332
5333     case 7:
5334       /*          bytes  cycles     reg x      reg a   carry
5335       **                          abcd efgh  ijkl mnop   ?
5336       **   lsla       1  1        abcd efgh  jklm nop0   i
5337       **   txa        1  1        abcd efgh  abcd efgh   i
5338       **   rola       1  1        abcd efgh  bcde fghi   a
5339       **   clrx       1  1        0000 0000  bcde fghi   a
5340       **   rolx       1  1        0000 000a  bcde fghi   0
5341       ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5342       */
5343       rmwWithReg ("lsl", hc08_reg_a);
5344       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5345       rmwWithReg ("rol", hc08_reg_a);
5346       loadRegFromConst (hc08_reg_x, zero);
5347       rmwWithReg ("rol", hc08_reg_x);
5348       return;
5349     case 6:
5350       /*          bytes  cycles     reg x      reg a   carry
5351       **                          abcd efgh  ijkl mnop   ?
5352       **   lsla       1  1        abcd efgh  jklm nop0   i
5353       **   rolx       1  1        bcde fghi  jklm nop0   a
5354       **   rola       1  1        bcde fghi  klmn op0a   j
5355       **   rolx       1  1        cdef ghij  klmn op0a   b
5356       **   rola       1  1        cdef ghij  lmno p0ab   k
5357       **   and #3     2  2        cdef ghij  0000 00ab   k
5358       **   psha       1  2        cdef ghij  0000 00ab   k
5359       **   txa        1  1        cdef ghij  cdef ghij   k
5360       **   pula       1  2        0000 00ab  cdef ghij   k
5361       ** total: 12 cycles, 10 bytes (beats 12 bytes)
5362       */
5363     default:
5364       ;
5365     }
5366
5367   /* lslx/rola is only 2 cycles and bytes, so an unrolled loop is often  */
5368   /* the fastest and shortest.                                           */
5369   for (i=0;i<shCount;i++)
5370     {
5371       rmwWithReg ("lsl", hc08_reg_x);
5372       rmwWithReg ("rol", hc08_reg_a);
5373     }
5374
5375 }
5376
5377
5378 #if 0
5379 /*-----------------------------------------------------------------*/
5380 /* shiftR1Left2Result - shift right one byte from left to result   */
5381 /*-----------------------------------------------------------------*/
5382 static void
5383 shiftR1Left2Result (operand * left, int offl,
5384                     operand * result, int offr,
5385                     int shCount, int sign)
5386 {
5387   loadRegFromAop (hc08_reg_a, AOP (left), offl);
5388   /* shift right accumulator */
5389   AccRsh (shCount, sign);
5390   storeRegToAop (hc08_reg_a, AOP (result), offr);
5391 }
5392 #endif
5393
5394 /*-----------------------------------------------------------------*/
5395 /* shiftL1Left2Result - shift left one byte from left to result    */
5396 /*-----------------------------------------------------------------*/
5397 static void
5398 shiftL1Left2Result (operand * left, int offl,
5399                     operand * result, int offr, int shCount)
5400 {
5401   loadRegFromAop (hc08_reg_a, AOP (left), offl);
5402   /* shift left accumulator */
5403   AccLsh (shCount);
5404   storeRegToAop (hc08_reg_a, AOP (result), offr);
5405 }
5406
5407 /*-----------------------------------------------------------------*/
5408 /* movLeft2Result - move byte from left to result                  */
5409 /*-----------------------------------------------------------------*/
5410 static void
5411 movLeft2Result (operand * left, int offl,
5412                 operand * result, int offr, int sign)
5413 {
5414   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5415     {
5416       transferAopAop (AOP (left), offl, AOP (result), offr);
5417     }
5418 }
5419
5420
5421 /*-----------------------------------------------------------------*/
5422 /* shiftL2Left2Result - shift left two bytes from left to result   */
5423 /*-----------------------------------------------------------------*/
5424 static void
5425 shiftL2Left2Result (operand * left, int offl,
5426                     operand * result, int offr, int shCount)
5427 {
5428   int i;
5429   bool needpula = FALSE;
5430   bool needpulx = FALSE;
5431
5432   needpula = pushRegIfUsed (hc08_reg_a);
5433   needpulx = pushRegIfUsed (hc08_reg_x);
5434
5435   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5436
5437   switch (shCount)
5438     {
5439       case 7:
5440         rmwWithReg ("lsr", hc08_reg_x);
5441         rmwWithReg ("ror", hc08_reg_a);
5442         transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5443         rmwWithReg ("clr", hc08_reg_a);
5444         rmwWithReg ("ror", hc08_reg_a);
5445         break;
5446       default:
5447         for (i=0; i<shCount; i++)
5448           {
5449             rmwWithReg ("lsl", hc08_reg_a);
5450             rmwWithReg ("rol", hc08_reg_x);
5451           }
5452     }
5453   storeRegToAop (hc08_reg_xa, AOP (result), offl);
5454
5455   pullOrFreeReg (hc08_reg_x, needpulx);
5456   pullOrFreeReg (hc08_reg_a, needpula);
5457
5458 }
5459
5460
5461 #if 0
5462 /*-----------------------------------------------------------------*/
5463 /* shiftR2Left2Result - shift right two bytes from left to result  */
5464 /*-----------------------------------------------------------------*/
5465 static void
5466 shiftR2Left2Result (operand * left, int offl,
5467                     operand * result, int offr,
5468                     int shCount, int sign)
5469 {
5470   int i;
5471   bool needpula = FALSE;
5472   bool needpulx = FALSE;
5473   
5474   needpula = pushRegIfUsed (hc08_reg_a);
5475   needpulx = pushRegIfUsed (hc08_reg_x);
5476
5477   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5478   for (i=0; i<shCount; i++)
5479     {
5480       if (sign)
5481         rmwWithReg ("asr", hc08_reg_x);
5482       else
5483         rmwWithReg ("lsr", hc08_reg_x);
5484       rmwWithReg ("ror", hc08_reg_a);
5485     }
5486   storeRegToAop (hc08_reg_xa, AOP (result), offl);
5487
5488   pullOrFreeReg (hc08_reg_x, needpulx);
5489   pullOrFreeReg (hc08_reg_a, needpula);
5490 }
5491 #endif
5492
5493 #if 0
5494 /*-----------------------------------------------------------------*/
5495 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5496 /*-----------------------------------------------------------------*/
5497 static void
5498 shiftLLeftOrResult (operand * left, int offl,
5499                     operand * result, int offr, int shCount)
5500 {
5501   loadRegFromAop (hc08_reg_a, AOP (left), offl);
5502   /* shift left accumulator */
5503   AccLsh (shCount);
5504   /* or with result */
5505   accopWithAop ("ora", AOP (result), offr);
5506   /* back to result */
5507   storeRegToAop (hc08_reg_a, AOP (result), offr);
5508   hc08_freeReg (hc08_reg_a);
5509 }
5510 #endif
5511
5512 /*-----------------------------------------------------------------*/
5513 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5514 /*-----------------------------------------------------------------*/
5515 static void
5516 shiftRLeftOrResult (operand * left, int offl,
5517                     operand * result, int offr, int shCount)
5518 {
5519   loadRegFromAop (hc08_reg_a, AOP (left), offl);
5520   /* shift left accumulator */
5521   AccRsh (shCount, FALSE);
5522   /* or with result */
5523   accopWithAop ("ora", AOP (result), offr);
5524   /* back to result */
5525   storeRegToAop (hc08_reg_a, AOP (result), offr);
5526   hc08_freeReg (hc08_reg_a);
5527 }
5528
5529 /*-----------------------------------------------------------------*/
5530 /* genlshOne - left shift a one byte quantity by known count       */
5531 /*-----------------------------------------------------------------*/
5532 static void
5533 genlshOne (operand * result, operand * left, int shCount)
5534 {
5535   D(emitcode (";     genlshOne",""));
5536
5537   shiftL1Left2Result (left, LSB, result, LSB, shCount);
5538 }
5539
5540 /*-----------------------------------------------------------------*/
5541 /* genlshTwo - left shift two bytes by known amount != 0           */
5542 /*-----------------------------------------------------------------*/
5543 static void
5544 genlshTwo (operand * result, operand * left, int shCount)
5545 {
5546   int size;
5547
5548   D(emitcode (";     genlshTwo",""));
5549
5550   
5551   size = getDataSize (result);
5552
5553   /* if shCount >= 8 */
5554   if (shCount >= 8)
5555     {
5556       shCount -= 8;
5557
5558       if (size > 1)
5559         {
5560           loadRegFromAop (hc08_reg_a, AOP (left), 0);
5561           AccLsh (shCount);
5562           storeRegToAop (hc08_reg_a, AOP (result), 1);
5563         }
5564       storeConstToAop(zero, AOP (result), LSB);
5565     }
5566
5567   /*  1 <= shCount <= 7 */
5568   else
5569     {
5570       loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5571       XAccLsh (shCount);
5572       storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
5573     }
5574 }
5575
5576 /*-----------------------------------------------------------------*/
5577 /* shiftLLong - shift left one long from left to result            */
5578 /* offl = LSB or MSB16                                             */
5579 /*-----------------------------------------------------------------*/
5580 static void
5581 shiftLLong (operand * left, operand * result, int offr)
5582 {
5583 //  char *l;
5584 //  int size = AOP_SIZE (result);
5585
5586   bool needpula = FALSE;
5587   bool needpulx = FALSE;
5588
5589   needpula = pushRegIfUsed (hc08_reg_a);
5590   needpulx = pushRegIfUsed (hc08_reg_x);
5591
5592   loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5593   rmwWithReg ("lsl", hc08_reg_a);
5594   rmwWithReg ("rol", hc08_reg_x);
5595   storeRegToAop (hc08_reg_xa, AOP (result), offr);
5596
5597   if (offr==LSB)
5598     {
5599       loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5600       rmwWithReg ("rol", hc08_reg_a);
5601       rmwWithReg ("rol", hc08_reg_x);
5602       storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5603     }
5604   else if (offr==MSB16)
5605     {
5606       loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5607       rmwWithReg ("rol", hc08_reg_a);
5608       storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5609     }
5610
5611   pullOrFreeReg (hc08_reg_x, needpulx);
5612   pullOrFreeReg (hc08_reg_a, needpula);
5613 }
5614
5615 /*-----------------------------------------------------------------*/
5616 /* genlshFour - shift four byte by a known amount != 0             */
5617 /*-----------------------------------------------------------------*/
5618 static void
5619 genlshFour (operand * result, operand * left, int shCount)
5620 {
5621   int size;
5622
5623   D(emitcode (";     genlshFour",""));
5624
5625   size = AOP_SIZE (result);
5626
5627   /* TODO: deal with the &result == &left case */
5628
5629   /* if shifting more that 3 bytes */
5630   if (shCount >= 24)
5631     {
5632       shCount -= 24;
5633       if (shCount)
5634         /* lowest order of left goes to the highest
5635            order of the destination */
5636         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5637       else
5638         movLeft2Result (left, LSB, result, MSB32, 0);
5639       storeConstToAop (zero, AOP (result), LSB);
5640       storeConstToAop (zero, AOP (result), MSB16);
5641       storeConstToAop (zero, AOP (result), MSB24);
5642       return;
5643     }
5644
5645   /* more than two bytes */
5646   else if (shCount >= 16)
5647     {
5648       /* lower order two bytes goes to higher order two bytes */
5649       shCount -= 16;
5650       /* if some more remaining */
5651       if (shCount)
5652         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5653       else
5654         {
5655           movLeft2Result (left, MSB16, result, MSB32, 0);
5656           movLeft2Result (left, LSB, result, MSB24, 0);
5657         }
5658       storeConstToAop (zero, AOP (result), LSB);
5659       storeConstToAop (zero, AOP (result), MSB16);
5660       return;
5661     }
5662
5663   /* if more than 1 byte */
5664   else if (shCount >= 8)
5665     {
5666       /* lower order three bytes goes to higher order  three bytes */
5667       shCount -= 8;
5668       if (size == 2)
5669         {
5670           if (shCount)
5671             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5672           else
5673             movLeft2Result (left, LSB, result, MSB16, 0);
5674         }
5675       else
5676         {                       /* size = 4 */
5677           if (shCount == 0)
5678             {
5679               movLeft2Result (left, MSB24, result, MSB32, 0);
5680               movLeft2Result (left, MSB16, result, MSB24, 0);
5681               movLeft2Result (left, LSB, result, MSB16, 0);
5682               storeConstToAop (zero, AOP (result), LSB);
5683             }
5684           else if (shCount == 1)
5685             shiftLLong (left, result, MSB16);
5686           else
5687             {
5688               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5689               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5690               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5691               storeConstToAop (zero, AOP (result), LSB);
5692             }
5693         }
5694     }
5695
5696   /* 1 <= shCount <= 7 */
5697   else if (shCount <= 2)
5698     {
5699       shiftLLong (left, result, LSB);
5700       if (shCount == 2)
5701         shiftLLong (result, result, LSB);
5702     }
5703   /* 3 <= shCount <= 7, optimize */
5704   else
5705     {
5706       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5707       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5708       shiftL2Left2Result (left, LSB, result, LSB, shCount);
5709     }
5710 }
5711
5712 /*-----------------------------------------------------------------*/
5713 /* genLeftShiftLiteral - left shifting by known count              */
5714 /*-----------------------------------------------------------------*/
5715 static void
5716 genLeftShiftLiteral (operand * left,
5717                      operand * right,
5718                      operand * result,
5719                      iCode * ic)
5720 {
5721   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5722   int size;
5723
5724   D(emitcode (";     genLeftShiftLiteral",""));
5725
5726   freeAsmop (right, NULL, ic, TRUE);
5727
5728   aopOp (left, ic, FALSE);
5729   aopOp (result, ic, FALSE);
5730
5731 //  size = getSize (operandType (result));
5732   size = AOP_SIZE (result);
5733
5734 #if VIEW_SIZE
5735   emitcode ("; shift left ", "result %d, left %d", size,
5736             AOP_SIZE (left));
5737 #endif
5738
5739   if (shCount == 0)
5740     {
5741       while (size--)
5742         transferAopAop( AOP(left), size, AOP(result), size);
5743     }
5744   else if (shCount >= (size * 8))
5745     {
5746       while (size--)
5747         storeConstToAop (zero, AOP (result), size);
5748     }
5749   else
5750     {
5751       switch (size)
5752         {
5753         case 1:
5754           genlshOne (result, left, shCount);
5755           break;
5756
5757         case 2:
5758           genlshTwo (result, left, shCount);
5759           break;
5760
5761         case 4:
5762           genlshFour (result, left, shCount);
5763           break;
5764         default:
5765           werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
5766                   "*** ack! mystery literal shift!\n");
5767           break;
5768         }
5769     }
5770   freeAsmop (left, NULL, ic, TRUE);
5771   freeAsmop (result, NULL, ic, TRUE);
5772 }
5773
5774 /*-----------------------------------------------------------------*/
5775 /* genLeftShift - generates code for left shifting                 */
5776 /*-----------------------------------------------------------------*/
5777 static void
5778 genLeftShift (iCode * ic)
5779 {
5780   operand *left, *right, *result;
5781   int size, offset;
5782   symbol *tlbl, *tlbl1;
5783 //  int i;
5784   char *shift;
5785   regs *reg;
5786
5787   D(emitcode (";     genLeftShift",""));
5788
5789   right = IC_RIGHT (ic);
5790   left = IC_LEFT (ic);
5791   result = IC_RESULT (ic);
5792
5793   aopOp (right, ic, FALSE);
5794
5795   /* if the shift count is known then do it
5796      as efficiently as possible */
5797   if (AOP_TYPE (right) == AOP_LIT)
5798     {
5799       genLeftShiftLiteral (left, right, result, ic);
5800       return;
5801     }
5802
5803   /* shift count is unknown then we have to form
5804      a loop get the loop count in A : Note: we take
5805      only the lower order byte since shifting
5806      more that 32 bits make no sense anyway, ( the
5807      largest size of an object can be only 32 bits ) */
5808
5809   aopOp (left, ic, FALSE);
5810   aopOp (result, ic, FALSE);
5811
5812   /* now move the left to the result if they are not the
5813      same */
5814   if (!sameRegs (AOP (left), AOP (result)))
5815     {
5816
5817       size = AOP_SIZE (result);
5818       offset = 0;
5819       while (size--)
5820         {
5821           transferAopAop (AOP (left), offset, AOP (result), offset);
5822           offset++;
5823         }
5824     }
5825   freeAsmop (left, NULL, ic, TRUE);
5826   
5827   tlbl = newiTempLabel (NULL);
5828   size = AOP_SIZE (result);
5829   offset = 0;
5830   tlbl1 = newiTempLabel (NULL);
5831
5832   reg = hc08_reg_a;
5833
5834   loadRegFromAop (reg, AOP (right), 0);
5835   freeAsmop (right, NULL, ic, TRUE);
5836   emitBranch ("beq", tlbl1);
5837   emitLabel (tlbl);
5838   
5839   shift="lsl";
5840   for (offset=0;offset<size;offset++)
5841     {
5842       rmwWithAop (shift, AOP (result), offset);  
5843       shift="rol";
5844     }
5845   rmwWithReg ("dec", reg);
5846   emitBranch ("bne", tlbl);
5847   emitLabel (tlbl1);
5848   hc08_freeReg (reg);
5849   
5850   freeAsmop (result, NULL, ic, TRUE);
5851 }
5852
5853 /*-----------------------------------------------------------------*/
5854 /* genrshOne - right shift a one byte quantity by known count      */
5855 /*-----------------------------------------------------------------*/
5856 static void
5857 genrshOne (operand * result, operand * left,
5858            int shCount, int sign)
5859 {
5860   D(emitcode (";     genrshOne",""));
5861
5862   loadRegFromAop (hc08_reg_a, AOP (left), 0);
5863   AccRsh (shCount, sign);
5864   storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5865 }
5866
5867 /*-----------------------------------------------------------------*/
5868 /* genrshTwo - right shift two bytes by known amount != 0          */
5869 /*-----------------------------------------------------------------*/
5870 static void
5871 genrshTwo (operand * result, operand * left,
5872            int shCount, int sign)
5873 {
5874   D(emitcode (";     genrshTwo",""));
5875
5876   /* if shCount >= 8 */
5877   if (shCount >= 8)
5878     {
5879       if (shCount || sign)
5880         {
5881           loadRegFromAop (hc08_reg_a, AOP (left), 1);
5882           AccRsh (shCount-8, sign);
5883           storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5884         }
5885       else
5886         {
5887           transferAopAop (AOP (left), 1, AOP (result), 0);
5888           storeConstToAop (zero, AOP (result), 1);
5889         }
5890     }
5891
5892   /*  1 <= shCount <= 7 */
5893   else
5894     {
5895       loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5896       XAccRsh (shCount, sign);
5897       storeRegToAop (hc08_reg_xa, AOP (result), 0);
5898     }
5899 }
5900
5901 /*-----------------------------------------------------------------*/
5902 /* shiftRLong - shift right one long from left to result           */
5903 /* offl = LSB or MSB16                                             */
5904 /*-----------------------------------------------------------------*/
5905 static void
5906 shiftRLong (operand * left, int offl,
5907             operand * result, int sign)
5908 {
5909 //  char *l;
5910  // int size = AOP_SIZE (result);
5911
5912   bool needpula = FALSE;
5913   bool needpulx = FALSE;
5914
5915   needpula = pushRegIfUsed (hc08_reg_a);
5916   needpulx = pushRegIfUsed (hc08_reg_x);
5917
5918   if (offl==LSB)
5919     {
5920       loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5921       if (sign)
5922         rmwWithReg ("asr", hc08_reg_x);
5923       else
5924         rmwWithReg ("lsr", hc08_reg_x);
5925       rmwWithReg ("rol", hc08_reg_a);
5926       storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
5927     }
5928   else if (offl==MSB16)
5929     {
5930       loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
5931       if (sign)
5932         rmwWithReg ("asr", hc08_reg_a);
5933       else
5934         rmwWithReg ("lsr", hc08_reg_a);
5935       storeRegToAop (hc08_reg_a, AOP (result), MSB24);
5936     }
5937
5938   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5939   rmwWithReg ("ror", hc08_reg_x);
5940   rmwWithReg ("ror", hc08_reg_a);
5941   storeRegToAop (hc08_reg_xa, AOP (result), LSB);
5942
5943
5944   pullOrFreeReg (hc08_reg_x, needpulx);
5945   pullOrFreeReg (hc08_reg_a, needpula);
5946 }
5947
5948 /*-----------------------------------------------------------------*/
5949 /* genrshFour - shift four byte by a known amount != 0             */
5950 /*-----------------------------------------------------------------*/
5951 static void
5952 genrshFour (operand * result, operand * left,
5953             int shCount, int sign)
5954 {
5955   /* TODO: handle cases where left == result */
5956   
5957   D(emitcode (";     genrshFour",""));
5958
5959   /* if shifting more that 3 bytes */
5960   if (shCount >= 24)
5961     {
5962       loadRegFromAop (hc08_reg_a, AOP (left), 3);
5963       AccRsh (shCount-24, sign);
5964       storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5965       return;
5966     }
5967   else if (shCount >= 16)
5968     {
5969       loadRegFromAop (hc08_reg_xa, AOP (left), 2);
5970       XAccRsh (shCount-16, sign);
5971       storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
5972       return;
5973     }
5974   else if (shCount >= 8)
5975     {
5976       if (shCount == 1)
5977         shiftRLong (left, MSB16, result, sign);
5978       else if (shCount == 8)
5979         {
5980           transferAopAop (AOP (left), 1, AOP (result), 0);
5981           transferAopAop (AOP (left), 2, AOP (result), 1);
5982           loadRegFromAop (hc08_reg_a, AOP (left), 3);
5983           storeRegToAop (hc08_reg_a, AOP (result), 2);
5984           storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
5985         }
5986       else if (shCount == 9)
5987         {
5988           shiftRLong (left, MSB16, result, sign);
5989         }
5990       else
5991         {
5992           loadRegFromAop (hc08_reg_xa, AOP (left), 1);
5993           XAccRsh (shCount-8, FALSE);
5994           storeRegToAop (hc08_reg_xa, AOP (result), 0);
5995           loadRegFromAop (hc08_reg_x, AOP (left), 3);
5996           loadRegFromConst (hc08_reg_a, zero);
5997           XAccRsh (shCount-8, sign);
5998           accopWithAop ("ora", AOP (result), 1);
5999           storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6000         }
6001     }
6002   else
6003     {                           /* 1 <= shCount <= 7 */
6004       if (shCount == 1)
6005         {
6006           shiftRLong (left, LSB, result, sign);
6007         }
6008       else
6009         {
6010           loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6011           XAccRsh (shCount, FALSE);
6012           storeRegToAop (hc08_reg_xa, AOP (result), 0);
6013           loadRegFromAop (hc08_reg_a, AOP (left), 2);
6014           AccLsh (8-shCount);
6015           accopWithAop ("ora", AOP (result), 1);
6016           storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6017           loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6018           XAccRsh (shCount, sign);
6019           storeRegToAop (hc08_reg_xa, AOP (result), 2);
6020         }
6021     }
6022 }
6023
6024 /*-----------------------------------------------------------------*/
6025 /* genRightShiftLiteral - right shifting by known count            */
6026 /*-----------------------------------------------------------------*/
6027 static void
6028 genRightShiftLiteral (operand * left,
6029                       operand * right,
6030                       operand * result,
6031                       iCode * ic,
6032                       int sign)
6033 {
6034   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6035   int size;
6036
6037   D(emitcode (";     genRightShiftLiteral",""));
6038
6039   freeAsmop (right, NULL, ic, TRUE);
6040
6041   aopOp (left, ic, FALSE);
6042   aopOp (result, ic, FALSE);
6043
6044 #if VIEW_SIZE
6045   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6046             AOP_SIZE (left));
6047 #endif
6048
6049   size = getDataSize (left);
6050   /* test the LEFT size !!! */
6051
6052   /* I suppose that the left size >= result size */
6053   if (shCount == 0)
6054     {
6055       size = getDataSize (result);
6056       while (size--)
6057         transferAopAop (AOP (left), size, AOP(result), size);
6058     }
6059   else if (shCount >= (size * 8))
6060     {
6061       if (sign) {
6062         /* get sign in acc.7 */
6063         loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6064       }
6065       addSign (result, LSB, sign);
6066     }
6067   else
6068     {
6069       switch (size)
6070         {
6071         case 1:
6072           genrshOne (result, left, shCount, sign);
6073           break;
6074
6075         case 2:
6076           genrshTwo (result, left, shCount, sign);
6077           break;
6078
6079         case 4:
6080           genrshFour (result, left, shCount, sign);
6081           break;
6082         default:
6083           break;
6084         }
6085     }
6086   freeAsmop (left, NULL, ic, TRUE);
6087   freeAsmop (result, NULL, ic, TRUE);
6088 }
6089
6090
6091 /*-----------------------------------------------------------------*/
6092 /* genRightShift - generate code for right shifting                */
6093 /*-----------------------------------------------------------------*/
6094 static void
6095 genRightShift (iCode * ic)
6096 {
6097   operand *right, *left, *result;
6098   sym_link *retype;
6099   int size, offset;
6100 //  char *l;
6101   symbol *tlbl, *tlbl1;
6102   char *shift;
6103   bool sign;
6104   
6105   D(emitcode (";     genRightShift",""));
6106
6107   /* if signed then we do it the hard way preserve the
6108      sign bit moving it inwards */
6109   retype = getSpec (operandType (IC_RESULT (ic)));
6110   sign = !SPEC_USIGN (retype);
6111
6112   /* signed & unsigned types are treated the same : i.e. the
6113      signed is NOT propagated inwards : quoting from the
6114      ANSI - standard : "for E1 >> E2, is equivalent to division
6115      by 2**E2 if unsigned or if it has a non-negative value,
6116      otherwise the result is implementation defined ", MY definition
6117      is that the sign does not get propagated */
6118
6119   right = IC_RIGHT (ic);
6120   left = IC_LEFT (ic);
6121   result = IC_RESULT (ic);
6122
6123   aopOp (right, ic, FALSE);
6124
6125   /* if the shift count is known then do it
6126      as efficiently as possible */
6127   if (AOP_TYPE (right) == AOP_LIT)
6128     {
6129       genRightShiftLiteral (left, right, result, ic, sign);
6130       return;
6131     }
6132
6133   /* shift count is unknown then we have to form
6134      a loop get the loop count in X : Note: we take
6135      only the lower order byte since shifting
6136      more that 32 bits make no sense anyway, ( the
6137      largest size of an object can be only 32 bits ) */
6138
6139   aopOp (left, ic, FALSE);
6140   aopOp (result, ic, FALSE);
6141
6142   if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6143     AOP (result) = forceStackedAop (AOP (result));
6144   
6145   size = AOP_SIZE (result); 
6146   offset = size-1;
6147   while (size--)
6148     {
6149       transferAopAop (AOP (left), offset, AOP (result), offset);
6150       offset--;
6151     }
6152   
6153   tlbl = newiTempLabel (NULL);
6154   size = AOP_SIZE (result);
6155   offset = 0;
6156   tlbl1 = newiTempLabel (NULL);
6157
6158   loadRegFromAop (hc08_reg_x, AOP (right), 0);
6159   emitcode ("tstx", "");
6160   emitcode ("beq", "%05d$", tlbl1->key + 100);
6161   emitcode ("", "%05d$:", tlbl->key + 100);
6162   shift= sign ? "asr" : "lsr";
6163   for (offset=size-1;offset>=0;offset--)
6164     {
6165       rmwWithAop (shift, AOP (result), offset);
6166       shift="ror";
6167     }
6168   rmwWithReg ("dec", hc08_reg_x);
6169   emitcode ("bne","%05d$", tlbl->key + 100);
6170   emitcode ("", "%05d$:", tlbl1->key + 100);
6171   
6172   freeAsmop (result, NULL, ic, TRUE);
6173   freeAsmop (left, NULL, ic, TRUE);
6174   freeAsmop (right, NULL, ic, TRUE);
6175 }
6176
6177 /*-----------------------------------------------------------------*/
6178 /* genUnpackBits - generates code for unpacking bits               */
6179 /*-----------------------------------------------------------------*/
6180 static void
6181 genUnpackBits (operand * result)
6182 {
6183   int offset = 0;       /* result byte offset */
6184   int rsize;            /* result size */
6185   int rlen = 0;         /* remaining bitfield length */
6186   sym_link *etype;      /* bitfield type information */
6187   int blen;             /* bitfield length */
6188   int bstr;             /* bitfield starting bit within byte */
6189
6190   D(emitcode (";     genUnpackBits",""));
6191
6192   etype = getSpec (operandType (result));
6193   rsize = getSize (operandType (result));
6194   blen = SPEC_BLEN (etype);
6195   bstr = SPEC_BSTR (etype);
6196
6197   /* If the bitfield length is less than a byte */
6198   if (blen < 8)
6199     {
6200       emitcode ("lda", ",x");
6201       hc08_dirtyReg (hc08_reg_a, FALSE);
6202       AccRsh (bstr, FALSE);
6203       emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6204       storeRegToAop (hc08_reg_a, AOP (result), offset++);
6205       goto finish;
6206     }
6207
6208   /* Bit field did not fit in a byte. Copy all
6209      but the partial byte at the end.  */
6210   for (rlen=blen;rlen>=8;rlen-=8)
6211     {
6212       emitcode ("lda", ",x");
6213       hc08_dirtyReg (hc08_reg_a, FALSE);
6214       storeRegToAop (hc08_reg_a, AOP (result), offset++);
6215       if (rlen>8)
6216         emitcode ("aix", "#1");
6217     }
6218
6219   /* Handle the partial byte at the end */
6220   if (rlen)
6221     {
6222       emitcode ("lda", ",x");
6223       emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6224       storeRegToAop (hc08_reg_a, AOP (result), offset++);
6225     }
6226
6227 finish:
6228   if (offset < rsize)
6229     {
6230       rsize -= offset;
6231       while (rsize--)
6232         storeConstToAop (zero, AOP (result), offset++);
6233     }
6234 }
6235
6236
6237 /*-----------------------------------------------------------------*/
6238 /* genDataPointerGet - generates code when ptr offset is known     */
6239 /*-----------------------------------------------------------------*/
6240 static void
6241 genDataPointerGet (operand * left,
6242                    operand * result,
6243                    iCode * ic)
6244 {
6245   int size, offset = 0;
6246   asmop *derefaop;
6247   
6248   D(emitcode (";     genDataPointerGet",""));
6249
6250   aopOp (result, ic, TRUE);
6251   size = AOP_SIZE (result);
6252
6253   derefaop = aopDerefAop (AOP (left));
6254   freeAsmop (left, NULL, ic, TRUE);
6255   derefaop->size = size;
6256   
6257   while (size--)
6258     {
6259       transferAopAop(derefaop, offset, AOP (result), offset);
6260       offset++;
6261     }
6262
6263   freeAsmop (NULL, derefaop, ic, TRUE);
6264   freeAsmop (result, NULL, ic, TRUE);
6265 }
6266
6267 #if 0
6268 /*-----------------------------------------------------------------*/
6269 /* genNearPointerGet - emitcode for near pointer fetch             */
6270 /*-----------------------------------------------------------------*/
6271 static void
6272 genNearPointerGet (operand * left,
6273                    operand * result,
6274                    iCode * ic,
6275                    iCode * pi)
6276 {
6277   int size, offset;
6278   sym_link *retype = getSpec (operandType (result));
6279
6280   D(emitcode (";     genNearPointerGet",""));
6281
6282   aopOp (left, ic, FALSE);
6283
6284   /* if left is rematerialisable and
6285      result is not bit variable type and
6286      the left is pointer to data space i.e
6287      lower 128 bytes of space */
6288   if ((AOP_TYPE (left) == AOP_IMMD)
6289       || (AOP_TYPE (left) == AOP_LIT) 
6290       /* !IS_BITVAR (retype) */
6291       /* && DCL_TYPE (ltype) == POINTER */ )
6292     {
6293       genDataPointerGet (left, result, ic);
6294       return;
6295     }
6296
6297   /* if the operand is already in hx
6298      then we do nothing else we move the value to hx */
6299   if (AOP_TYPE (left) != AOP_STR)
6300     {
6301       /* if this is remateriazable */
6302       loadRegFromAop (hc08_reg_x, AOP (left), 0);
6303       loadRegFromConst (hc08_reg_h, zero);
6304     }
6305
6306   /* so hx now contains the address */
6307   aopOp (result, ic, FALSE);
6308
6309   /* if bit then unpack */
6310   if (IS_BITVAR (retype))
6311     genUnpackBits (result);
6312   else
6313     {
6314       size = AOP_SIZE (result);
6315       offset = size-1;
6316
6317       while (size--)
6318         {
6319           accopWithMisc ("lda", ",x");
6320           if (size || pi)
6321             {
6322               rmwWithReg ("inc", hc08_reg_x);
6323             }
6324           storeRegToAop (hc08_reg_a, AOP (result), offset--);
6325           hc08_freeReg (hc08_reg_a);
6326         }
6327     }
6328
6329   freeAsmop (left, NULL, ic, TRUE);
6330   freeAsmop (result, NULL, ic, TRUE);
6331   
6332   if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6333     aopOp (IC_RESULT (pi), pi, FALSE);
6334     storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6335     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6336     pi->generated = 1;
6337   }
6338
6339   hc08_freeReg (hc08_reg_hx);
6340 }
6341 #endif
6342
6343 /*-----------------------------------------------------------------*/
6344 /* genFarPointerGet - get value from far space                     */
6345 /*-----------------------------------------------------------------*/
6346 static void
6347 genFarPointerGet (operand * left,
6348                   operand * result, iCode * ic, iCode * pi)
6349 {
6350   int size, offset;
6351   sym_link *retype = getSpec (operandType (result));
6352
6353   D(emitcode (";     genFarPointerGet",""));
6354
6355   aopOp (left, ic, FALSE);
6356
6357   /* if left is rematerialisable and
6358      result is not bit variable type and
6359      the left is pointer to data space i.e
6360      lower 128 bytes of space */
6361   if (AOP_TYPE (left) == AOP_IMMD &&
6362       !IS_BITVAR (retype)
6363       /* && DCL_TYPE (ltype) == POINTER */ )
6364     {
6365       genDataPointerGet (left, result, ic);
6366       return;
6367     }
6368
6369   /* if the operand is already in hx
6370      then we do nothing else we move the value to hx */
6371   if (AOP_TYPE (left) != AOP_STR)
6372     {
6373       /* if this is remateriazable */
6374       loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6375     }
6376
6377   /* so hx now contains the address */
6378   aopOp (result, ic, FALSE);
6379
6380   /* if bit then unpack */
6381   if (IS_BITVAR (retype))
6382     genUnpackBits (result);
6383   else
6384     {
6385       size = AOP_SIZE (result);
6386       offset = size-1;
6387
6388       while (size--)
6389         {
6390           accopWithMisc ("lda", ",x");
6391           if (size || pi)
6392             {
6393               emitcode ("aix", "#1");
6394               hc08_dirtyReg (hc08_reg_hx, FALSE);
6395             }
6396           storeRegToAop (hc08_reg_a, AOP (result), offset--);
6397           hc08_freeReg (hc08_reg_a);
6398         }
6399     }
6400
6401   freeAsmop (left, NULL, ic, TRUE);
6402   freeAsmop (result, NULL, ic, TRUE);
6403   
6404   if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6405     aopOp (IC_RESULT (pi), pi, FALSE);
6406     storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6407     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6408     pi->generated = 1;
6409   }
6410
6411   hc08_freeReg (hc08_reg_hx);
6412   
6413 }
6414
6415
6416
6417 /*-----------------------------------------------------------------*/
6418 /* genPointerGet - generate code for pointer get                   */
6419 /*-----------------------------------------------------------------*/
6420 static void
6421 genPointerGet (iCode * ic, iCode *pi)
6422 {
6423   operand *left, *result;
6424   sym_link *type, *etype;
6425   int p_type;
6426
6427   D(emitcode (";     genPointerGet",""));
6428
6429   left = IC_LEFT (ic);
6430   result = IC_RESULT (ic);
6431
6432   /* depending on the type of pointer we need to
6433      move it to the correct pointer register */
6434   type = operandType (left);
6435   etype = getSpec (type);
6436   /* if left is of type of pointer then it is simple */
6437   if (IS_PTR (type) && !IS_FUNC (type->next))
6438     p_type = DCL_TYPE (type);
6439   else
6440     {
6441       /* we have to go by the storage class */
6442       p_type = PTR_TYPE (SPEC_OCLS (etype));
6443     }
6444
6445   /* special case when cast remat */
6446   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
6447       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6448           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6449           type = operandType (left);
6450           p_type = DCL_TYPE (type);
6451   }
6452   /* now that we have the pointer type we assign
6453      the pointer values */
6454   switch (p_type)
6455     {
6456
6457     case POINTER:
6458     case IPOINTER:
6459 #if 0
6460       genNearPointerGet (left, result, ic, pi);
6461       break;
6462 #endif
6463     case GPOINTER:
6464     case CPOINTER:
6465     case FPOINTER:
6466       genFarPointerGet (left, result, ic, pi);
6467       break;
6468
6469     }
6470
6471 }
6472
6473 /*-----------------------------------------------------------------*/
6474 /* genPackBits - generates code for packed bit storage             */
6475 /*-----------------------------------------------------------------*/
6476 static void
6477 genPackBits (sym_link * etype,
6478              operand * right)
6479 {
6480   int offset = 0;       /* source byte offset */
6481   int rlen = 0;         /* remaining bitfield length */
6482   int blen;             /* bitfield length */
6483   int bstr;             /* bitfield starting bit within byte */
6484   int litval;           /* source literal value (if AOP_LIT) */
6485   unsigned char mask;   /* bitmask within current byte */
6486
6487   D(emitcode (";     genPackBits",""));
6488
6489   blen = SPEC_BLEN (etype);
6490   bstr = SPEC_BSTR (etype);
6491   
6492   /* If the bitfield length is less than a byte */
6493   if (blen < 8)
6494     {
6495       mask = ((unsigned char) (0xFF << (blen + bstr)) |
6496               (unsigned char) (0xFF >> (8 - bstr)));
6497
6498       if (AOP_TYPE (right) == AOP_LIT)
6499         {
6500           /* Case with a bitfield length <8 and literal source
6501           */
6502           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6503           litval <<= bstr;
6504           litval &= (~mask) & 0xff;
6505
6506           emitcode ("lda", ",x");
6507           if ((mask|litval)!=0xff)
6508             emitcode ("and","#0x%02x", mask);
6509           if (litval)
6510             emitcode ("ora","#0x%02x", litval);
6511           hc08_dirtyReg (hc08_reg_a, FALSE);
6512           emitcode ("sta", ",x");
6513           
6514           hc08_freeReg (hc08_reg_a);
6515           return;
6516         }
6517           
6518       /* Case with a bitfield length < 8 and arbitrary source
6519       */
6520       loadRegFromAop (hc08_reg_a, AOP (right), 0);
6521       /* shift and mask source value */
6522       AccLsh (bstr);
6523       emitcode ("and", "#0x%02x", (~mask) & 0xff);
6524       hc08_dirtyReg (hc08_reg_a, FALSE);
6525       pushReg (hc08_reg_a, TRUE);
6526
6527       emitcode ("lda", ",x");
6528       emitcode ("and", "#0x%02x", mask);
6529       emitcode ("ora", "1,s");
6530       emitcode ("sta", ",x");
6531       pullReg (hc08_reg_a);
6532      
6533       hc08_freeReg (hc08_reg_a);
6534       return;
6535     }
6536
6537   /* Bit length is greater than 7 bits. In this case, copy  */
6538   /* all except the partial byte at the end                 */
6539   for (rlen=blen;rlen>=8;rlen-=8)
6540     {
6541       if (AOP (right)->type == AOP_DIR)
6542         {
6543           emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6544         }
6545       else
6546         {
6547           loadRegFromAop (hc08_reg_a, AOP (right), offset);
6548           emitcode ("sta", "%d,x", offset);
6549         }
6550       offset++;
6551     }
6552
6553   /* If there was a partial byte at the end */
6554   if (rlen)
6555     {
6556       mask = (((unsigned char) -1 << rlen) & 0xff);
6557       
6558       if (AOP_TYPE (right) == AOP_LIT)
6559         {
6560           /* Case with partial byte and literal source
6561           */
6562           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6563           litval >>= (blen-rlen);
6564           litval &= (~mask) & 0xff;
6565           emitcode ("lda", "%d,x", offset);
6566           hc08_dirtyReg (hc08_reg_a, FALSE);
6567           if ((mask|litval)!=0xff)
6568             emitcode ("and","#0x%02x", mask);
6569           if (litval)
6570             emitcode ("ora","#0x%02x", litval);
6571           emitcode ("sta", "%d,x", offset);
6572           hc08_dirtyReg (hc08_reg_a, FALSE);
6573           hc08_freeReg (hc08_reg_a);
6574           return;
6575         }
6576       
6577       /* Case with partial byte and arbitrary source
6578       */
6579       loadRegFromAop (hc08_reg_a, AOP (right), offset++);
6580       emitcode ("and", "#0x%02x", (~mask) & 0xff);
6581       hc08_dirtyReg (hc08_reg_a, FALSE);
6582       pushReg (hc08_reg_a, TRUE);
6583
6584       emitcode ("lda", ",x");
6585       emitcode ("and", "#0x%02x", mask);
6586       emitcode ("ora", "1,s");
6587       emitcode ("sta", ",x");
6588     }
6589
6590   hc08_freeReg (hc08_reg_a);
6591 }
6592
6593 /*-----------------------------------------------------------------*/
6594 /* genDataPointerSet - remat pointer to data space                 */
6595 /*-----------------------------------------------------------------*/
6596 static void
6597 genDataPointerSet (operand * right,
6598                    operand * result,
6599                    iCode * ic)
6600 {
6601   int size, offset = 0;
6602   asmop *derefaop;
6603
6604   D(emitcode (";     genDataPointerSet",""));
6605
6606   aopOp (right, ic, FALSE);
6607   size = AOP_SIZE (right);
6608
6609   derefaop = aopDerefAop (AOP (result));
6610   freeAsmop (result, NULL, ic, TRUE);
6611   derefaop->size = size;
6612   
6613   while (size--)
6614     {
6615       transferAopAop (AOP (right), offset, derefaop, offset);
6616       offset++;
6617     }
6618
6619   freeAsmop (right, NULL, ic, TRUE);
6620   freeAsmop (NULL, derefaop, ic, TRUE);
6621 }
6622
6623 #if 0
6624 /*-----------------------------------------------------------------*/
6625 /* genNearPointerSet - emitcode for near pointer put                */
6626 /*-----------------------------------------------------------------*/
6627 static void
6628 genNearPointerSet (operand * right,
6629                    operand * result,
6630                    iCode * ic,
6631                    iCode * pi)
6632 {
6633   int size, offset;
6634   sym_link *retype = getSpec (operandType (right));
6635   sym_link *letype = getSpec (operandType (result));
6636
6637   D(emitcode (";     genNearPointerSet",""));
6638
6639   aopOp (result, ic, FALSE);
6640
6641   /* if the result is rematerializable &
6642      in data space & not a bit variable */
6643   if (AOP_TYPE (result) == AOP_IMMD &&
6644       /* DCL_TYPE (ptype) == POINTER && */
6645       !IS_BITVAR (retype) &&
6646       !IS_BITVAR (letype))
6647     {
6648       genDataPointerSet (right, result, ic);
6649       return;
6650     }
6651
6652   /* if the operand is already in hx
6653      then we do nothing else we move the value to hx */
6654   if (AOP_TYPE (result) != AOP_STR)
6655     {
6656       loadRegFromAop (hc08_reg_x, AOP (result), 0);
6657       loadRegFromConst (hc08_reg_h, zero);
6658     }
6659   /* so hx now contains the address */
6660   aopOp (right, ic, FALSE);
6661
6662   /* if bit then unpack */
6663   if (IS_BITVAR (retype) || IS_BITVAR (letype))
6664     genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6665   else
6666     {
6667       size = AOP_SIZE (right);
6668       offset = size-1;
6669
6670       while (size--)
6671         {
6672           loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6673           accopWithMisc ("sta", ",x");
6674           if (size || pi)
6675             {
6676               rmwWithReg ("inc", hc08_reg_x);
6677             }
6678           hc08_freeReg (hc08_reg_a);
6679         }
6680     }
6681
6682   freeAsmop (result, NULL, ic, TRUE);
6683   freeAsmop (right, NULL, ic, TRUE);
6684
6685   if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6686     aopOp (IC_RESULT (pi), pi, FALSE);
6687     storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6688     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6689     pi->generated=1;
6690   }
6691
6692   hc08_freeReg (hc08_reg_hx);
6693   
6694 }
6695 #endif
6696
6697 /*-----------------------------------------------------------------*/
6698 /* genFarPointerSet - set value from far space                     */
6699 /*-----------------------------------------------------------------*/
6700 static void
6701 genFarPointerSet (operand * right,
6702                   operand * result, iCode * ic, iCode * pi)
6703 {
6704   int size, offset;
6705   sym_link *retype = getSpec (operandType (right));
6706   sym_link *letype = getSpec (operandType (result));
6707
6708   D(emitcode (";     genFarPointerSet",""));
6709
6710   aopOp (result, ic, FALSE);
6711
6712   /* if the result is rematerializable &
6713      in data space & not a bit variable */
6714   if (AOP_TYPE (result) == AOP_IMMD &&
6715       /* DCL_TYPE (ptype) == POINTER && */
6716       !IS_BITVAR (retype) &&
6717       !IS_BITVAR (letype))
6718     {
6719       genDataPointerSet (right, result, ic);
6720       return;
6721     }
6722
6723   /* if the operand is already in hx
6724      then we do nothing else we move the value to hx */
6725   if (AOP_TYPE (result) != AOP_STR)
6726     {
6727       loadRegFromAop (hc08_reg_hx, AOP (result), 0);
6728     }
6729   /* so hx now contains the address */
6730   aopOp (right, ic, FALSE);
6731
6732   /* if bit then unpack */
6733   if (IS_BITVAR (retype) || IS_BITVAR (letype))
6734     genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6735   else
6736     {
6737       size = AOP_SIZE (right);
6738       offset = size-1;
6739
6740       while (size--)
6741         {
6742           loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6743           accopWithMisc ("sta", ",x");
6744           if (size || pi)
6745             {
6746               emitcode ("aix", "#1");
6747             }
6748           hc08_freeReg (hc08_reg_a);
6749         }
6750     }
6751
6752   freeAsmop (result, NULL, ic, TRUE);
6753   freeAsmop (right, NULL, ic, TRUE);
6754
6755   if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD  */) {
6756     aopOp (IC_RESULT (pi), pi, FALSE);
6757     storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6758     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6759     pi->generated=1;
6760   }
6761
6762   hc08_freeReg (hc08_reg_hx);
6763   
6764
6765 }
6766
6767
6768 /*-----------------------------------------------------------------*/
6769 /* genPointerSet - stores the value into a pointer location        */
6770 /*-----------------------------------------------------------------*/
6771 static void
6772 genPointerSet (iCode * ic, iCode *pi)
6773 {
6774   operand *right, *result;
6775   sym_link *type, *etype;
6776   int p_type;
6777
6778   D(emitcode (";     genPointerSet",""));
6779
6780   right = IC_RIGHT (ic);
6781   result = IC_RESULT (ic);
6782
6783   /* depending on the type of pointer we need to
6784      move it to the correct pointer register */
6785   type = operandType (result);
6786   etype = getSpec (type);
6787   /* if left is of type of pointer then it is simple */
6788   if (IS_PTR (type) && !IS_FUNC (type->next))
6789     {
6790       p_type = DCL_TYPE (type);
6791     }
6792   else
6793     {
6794       /* we have to go by the storage class */
6795       p_type = PTR_TYPE (SPEC_OCLS (etype));
6796     }
6797
6798   /* special case when cast remat */
6799   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
6800       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
6801           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
6802           type = operandType (result);
6803           p_type = DCL_TYPE (type);
6804   }
6805   /* now that we have the pointer type we assign
6806      the pointer values */
6807   switch (p_type)
6808     {
6809
6810     case POINTER:
6811     case IPOINTER:
6812 #if 0
6813       genNearPointerSet (right, result, ic, pi);
6814       break;
6815 #endif
6816
6817     case GPOINTER:
6818     case FPOINTER:
6819       genFarPointerSet (right, result, ic, pi);
6820       break;
6821
6822     default:
6823       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
6824               "genPointerSet: illegal pointer type");
6825     }
6826
6827 }
6828
6829 /*-----------------------------------------------------------------*/
6830 /* genIfx - generate code for Ifx statement                        */
6831 /*-----------------------------------------------------------------*/
6832 static void
6833 genIfx (iCode * ic, iCode * popIc)
6834 {
6835   operand *cond = IC_COND (ic);
6836   int isbit = 0;
6837
6838   D(emitcode (";     genIfx",""));
6839
6840   aopOp (cond, ic, FALSE);
6841
6842   /* get the value into acc */
6843   if (AOP_TYPE (cond) != AOP_CRY)
6844     asmopToBool (AOP (cond), FALSE);
6845   else
6846     isbit = 1;
6847   /* the result is now in the accumulator */
6848   freeAsmop (cond, NULL, ic, TRUE);
6849
6850   /* if there was something to be popped then do it */
6851   if (popIc)
6852     genIpop (popIc);
6853
6854   /* if the condition is  a bit variable */
6855   if (isbit && IS_ITEMP (cond) &&
6856       SPIL_LOC (cond))
6857     genIfxJump (ic, SPIL_LOC (cond)->rname);
6858   else if (isbit && !IS_ITEMP (cond))
6859     genIfxJump (ic, OP_SYMBOL (cond)->rname);
6860   else
6861     genIfxJump (ic, "a");
6862
6863   ic->generated = 1;
6864 }
6865
6866 /*-----------------------------------------------------------------*/
6867 /* genAddrOf - generates code for address of                       */
6868 /*-----------------------------------------------------------------*/
6869 static void
6870 genAddrOf (iCode * ic)
6871 {
6872   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
6873   int size, offset;
6874
6875   D(emitcode (";     genAddrOf",""));
6876
6877   aopOp (IC_RESULT (ic), ic, FALSE);
6878
6879   /* if the operand is on the stack then we
6880      need to get the stack offset of this
6881      variable */
6882   if (sym->onStack)
6883     {
6884       /* if it has an offset then we need to compute
6885          it */
6886       hc08_useReg (hc08_reg_hx);
6887       emitcode ("tsx", "");
6888       emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
6889       storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
6890       hc08_freeReg (hc08_reg_hx);
6891
6892       goto release;
6893     }
6894
6895   /* object not on stack then we need the name */
6896   size = AOP_SIZE (IC_RESULT (ic));
6897   offset = 0;
6898
6899   while (size--)
6900     {
6901       char s[SDCC_NAME_MAX+10];
6902       switch (offset) {
6903         case 0:
6904           sprintf (s, "#%s", sym->rname);
6905           break;
6906         case 1:
6907           sprintf (s, "#>%s", sym->rname);
6908           break;
6909         default:
6910           sprintf (s, "#(%s >> %d)",
6911                    sym->rname,
6912                    offset * 8);
6913       }
6914       storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
6915     }
6916
6917 release:
6918   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
6919
6920 }
6921
6922 /*-----------------------------------------------------------------*/
6923 /* genAssign - generate code for assignment                        */
6924 /*-----------------------------------------------------------------*/
6925 static void
6926 genAssign (iCode * ic)
6927 {
6928   operand *result, *right;
6929   int size, offset;
6930 //  unsigned long lit = 0L;
6931
6932   D(emitcode(";     genAssign",""));
6933
6934   result = IC_RESULT (ic);
6935   right = IC_RIGHT (ic);
6936
6937   /* if they are the same */
6938   if (operandsEqu (result, right)) {
6939     return;
6940   }
6941
6942   aopOp (right, ic, FALSE);
6943   aopOp (result, ic, TRUE);
6944
6945   /* if they are the same registers */
6946   if (sameRegs (AOP (right), AOP (result)))
6947     goto release;
6948
6949   if ((AOP_TYPE (right) == AOP_LIT)
6950       && (IS_AOP_HX(AOP(result))))
6951     {
6952       loadRegFromAop(hc08_reg_hx, AOP (right), 0);
6953       goto release;
6954     }
6955     
6956   /* general case */
6957   size = AOP_SIZE (result);
6958   offset = 0;
6959
6960   while (size--)
6961     {
6962       transferAopAop (AOP (right), offset, AOP (result), offset);
6963       offset++;
6964     }
6965
6966 release:
6967   freeAsmop (right, NULL, ic, TRUE);
6968   freeAsmop (result, NULL, ic, TRUE);
6969 }
6970
6971 /*-----------------------------------------------------------------*/
6972 /* genJumpTab - genrates code for jump table                       */
6973 /*-----------------------------------------------------------------*/
6974 static void
6975 genJumpTab (iCode * ic)
6976 {
6977   symbol *jtab;
6978 //  char *l;
6979
6980   D(emitcode (";     genJumpTab",""));
6981
6982   aopOp (IC_JTCOND (ic), ic, FALSE);
6983   /* get the condition into accumulator */
6984   loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
6985   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
6986   /* multiply by three */
6987   pushReg (hc08_reg_a, FALSE);
6988   emitcode ("lsla", "");
6989   emitcode ("add","1,s");
6990   transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
6991   loadRegFromConst (hc08_reg_h, zero);
6992
6993   jtab = newiTempLabel (NULL);
6994   emitcode ("jmp", "%05d$,x", jtab->key + 100);
6995   emitcode ("", "%05d$:", jtab->key + 100);
6996   /* now generate the jump labels */
6997   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
6998        jtab = setNextItem (IC_JTLABELS (ic)))
6999     emitcode ("jmp", "%05d$", jtab->key + 100);
7000
7001   hc08_dirtyReg (hc08_reg_a, TRUE);
7002   hc08_dirtyReg (hc08_reg_hx, TRUE);
7003 }
7004
7005 /*-----------------------------------------------------------------*/
7006 /* genCast - gen code for casting                                  */
7007 /*-----------------------------------------------------------------*/
7008 static void
7009 genCast (iCode * ic)
7010 {
7011   operand *result = IC_RESULT (ic);
7012   sym_link *ctype = operandType (IC_LEFT (ic));
7013   sym_link *rtype = operandType (IC_RIGHT (ic));
7014   operand *right = IC_RIGHT (ic);
7015   int size, offset;
7016
7017   D(emitcode(";     genCast",""));
7018
7019   /* if they are equivalent then do nothing */
7020   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7021     return;
7022
7023   aopOp (right, ic, FALSE);
7024   aopOp (result, ic, FALSE);
7025
7026
7027   /* if they are the same size : or less */
7028   if (AOP_SIZE (result) <= AOP_SIZE (right))
7029     {
7030
7031       /* if they are in the same place */
7032       #if 0
7033       if (sameRegs (AOP (right), AOP (result)))
7034         goto release;
7035       #endif
7036
7037       /* if they in different places then copy */
7038       size = AOP_SIZE (result);
7039       offset = 0;
7040       while (size--)
7041         {
7042           transferAopAop(AOP (right), offset, AOP (result), offset);
7043           offset++;
7044         }
7045       goto release;
7046     }
7047
7048
7049   /* if the result is of type pointer */
7050   if (IS_PTR (ctype))
7051     {
7052
7053       int p_type;
7054       sym_link *type = operandType (right);
7055       sym_link *etype = getSpec (type);
7056
7057       /* pointer to generic pointer */
7058       if (IS_GENPTR (ctype))
7059         {
7060           if (IS_PTR (type))
7061             p_type = DCL_TYPE (type);
7062           else
7063             {
7064               if (SPEC_SCLS(etype)==S_REGISTER) {
7065                 // let's assume it is a generic pointer
7066                 p_type=GPOINTER;
7067               } else {
7068                 /* we have to go by the storage class */
7069                 p_type = PTR_TYPE (SPEC_OCLS (etype));
7070               }
7071             }
7072
7073           /* the first two bytes are known */
7074           size = GPTRSIZE - 1;
7075           offset = 0;
7076           while (size--)
7077             {
7078               transferAopAop(AOP (right), offset, AOP (result), offset);
7079               offset++;
7080             }
7081           /* the last byte depending on type */
7082 #if 0
7083             {
7084                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7085                 char gpValStr[10];
7086             
7087                 if (gpVal == -1)
7088                 {
7089                     // pointerTypeToGPByte will have bitched.
7090                     exit(1);
7091                 }
7092             
7093                 sprintf(gpValStr, "#0x%d", gpVal);
7094                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7095             }       
7096 #endif
7097           goto release;
7098         }
7099
7100       /* just copy the pointers */
7101       size = AOP_SIZE (result);
7102       offset = 0;
7103       while (size--)
7104         {
7105           transferAopAop(AOP (right), offset, AOP (result), offset);
7106           offset++;
7107         }
7108       goto release;
7109     }
7110
7111   /* so we now know that the size of destination is greater
7112      than the size of the source */
7113   /* we move to result for the size of source */
7114   size = AOP_SIZE (right);
7115   offset = 0;
7116   while (size--)
7117     {
7118       transferAopAop(AOP (right), offset, AOP (result), offset);
7119       offset++;
7120     }
7121
7122   /* now depending on the sign of the source && destination */
7123   size = AOP_SIZE (result) - AOP_SIZE (right);
7124   /* if unsigned or not an integral type */
7125   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7126     {
7127       while (size--)
7128         storeConstToAop (zero, AOP (result), offset++); 
7129     }
7130   else
7131     {
7132       /* we need to extend the sign :{ */
7133       loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7134       accopWithMisc ("rola", "");
7135       accopWithMisc ("clra", "");
7136       accopWithMisc ("sbc", zero);
7137       while (size--)
7138         storeRegToAop (hc08_reg_a, AOP (result), offset++);
7139     }
7140
7141   /* we are done hurray !!!! */
7142
7143 release:
7144   freeAsmop (right, NULL, ic, TRUE);
7145   freeAsmop (result, NULL, ic, TRUE);
7146
7147 }
7148
7149 /*-----------------------------------------------------------------*/
7150 /* genDjnz - generate decrement & jump if not zero instrucion      */
7151 /*-----------------------------------------------------------------*/
7152 static int
7153 genDjnz (iCode * ic, iCode * ifx)
7154 {
7155   symbol *lbl, *lbl1;
7156   if (!ifx)
7157     return 0;
7158
7159   D(emitcode (";     genDjnz",""));
7160
7161   /* if the if condition has a false label
7162      then we cannot save */
7163   if (IC_FALSE (ifx))
7164     return 0;
7165
7166   /* if the minus is not of the form
7167      a = a - 1 */
7168   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7169       !IS_OP_LITERAL (IC_RIGHT (ic)))
7170     return 0;
7171
7172   if (operandLitValue (IC_RIGHT (ic)) != 1)
7173     return 0;
7174
7175   /* if the size of this greater than one then no
7176      saving */
7177 //  if (getSize (operandType (IC_RESULT (ic))) > 1)
7178 //    return 0;
7179   aopOp (IC_RESULT (ic), ic, FALSE);
7180   if (AOP_SIZE (IC_RESULT (ic))>1)
7181     {
7182       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7183       return 0;
7184     }
7185
7186   /* otherwise we can save BIG */
7187   lbl = newiTempLabel (NULL);
7188   lbl1 = newiTempLabel (NULL);
7189
7190
7191   emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7192                 lbl->key + 100);
7193  
7194   emitBranch ("bra", lbl1);
7195   emitLabel (lbl);
7196   emitBranch ("jmp", IC_TRUE (ifx));
7197   emitLabel (lbl1);
7198
7199   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7200   ifx->generated = 1;
7201   return 1;
7202 }
7203
7204 /*-----------------------------------------------------------------*/
7205 /* genReceive - generate code for a receive iCode                  */
7206 /*-----------------------------------------------------------------*/
7207 static void
7208 genReceive (iCode * ic)
7209 {
7210   int size;
7211   int offset;
7212   D(emitcode (";     genReceive",""));
7213
7214   aopOp (IC_RESULT (ic), ic, FALSE);
7215   size = AOP_SIZE (IC_RESULT (ic));
7216   offset = 0;
7217   
7218   if (ic->argreg) {
7219       while (size--) {
7220           transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7221                           AOP (IC_RESULT (ic)), offset);
7222           if (hc08_aop_pass[offset]->type == AOP_REG)
7223             hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7224           offset++;
7225       }
7226   }       
7227
7228   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7229 }
7230
7231 /*-----------------------------------------------------------------*/
7232 /* genDummyRead - generate code for dummy read of volatiles        */
7233 /*-----------------------------------------------------------------*/
7234 static void
7235 genDummyRead (iCode * ic)
7236 {
7237   operand *right;
7238   int size, offset;
7239
7240   D(emitcode(";     genDummyRead",""));
7241
7242   right = IC_RIGHT (ic);
7243
7244   aopOp (right, ic, FALSE);
7245
7246   /* bit variables done */
7247   /* general case */
7248   size = AOP_SIZE (right);
7249   offset = 0;
7250
7251   while (size--)
7252     {
7253       loadRegFromAop (hc08_reg_a, AOP (right), offset);
7254       hc08_freeReg (hc08_reg_a);
7255       offset++;
7256     }
7257
7258   freeAsmop (right, NULL, ic, TRUE);
7259 }
7260
7261 /*-----------------------------------------------------------------*/
7262 /* genCritical - generate code for start of a critical sequence    */
7263 /*-----------------------------------------------------------------*/
7264 static void
7265 genCritical (iCode *ic)
7266 {
7267   D(emitcode(";     genCritical",""));
7268   
7269   if (IC_RESULT (ic))
7270     aopOp (IC_RESULT (ic), ic, TRUE);
7271
7272   emitcode ("tpa", "");
7273   hc08_dirtyReg (hc08_reg_a, FALSE);
7274   emitcode ("sei", "");
7275
7276   if (IC_RESULT (ic))
7277     storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7278   else
7279     pushReg (hc08_reg_a, FALSE);
7280
7281   hc08_freeReg (hc08_reg_a);
7282   if (IC_RESULT (ic))
7283     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7284 }
7285
7286 /*-----------------------------------------------------------------*/
7287 /* genEndCritical - generate code for end of a critical sequence   */
7288 /*-----------------------------------------------------------------*/
7289 static void
7290 genEndCritical (iCode *ic)
7291 {
7292   D(emitcode(";     genEndCritical",""));
7293   
7294   if (IC_RIGHT (ic))
7295     {
7296       aopOp (IC_RIGHT (ic), ic, FALSE);
7297       loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7298       emitcode ("tap", "");
7299       hc08_freeReg (hc08_reg_a);
7300       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7301     }
7302   else
7303     {
7304       pullReg (hc08_reg_a);
7305       emitcode ("tap", "");
7306     }
7307 }
7308
7309
7310 /*-----------------------------------------------------------------*/
7311 /* genhc08Code - generate code for HC08 based controllers          */
7312 /*-----------------------------------------------------------------*/
7313 void
7314 genhc08Code (iCode * lic)
7315 {
7316   iCode *ic;
7317   int cln = 0;
7318
7319   lineHead = lineCurr = NULL;
7320
7321   /* print the allocation information */
7322   if (allocInfo && currFunc)
7323     printAllocInfo (currFunc, codeOutFile);
7324   /* if debug information required */
7325   if (options.debug && currFunc)
7326     {
7327       debugFile->writeFunction(currFunc);
7328       _G.debugLine = 1;
7329       if (IS_STATIC (currFunc->etype))
7330         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7331       else
7332         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7333       _G.debugLine = 0;
7334     }
7335   /* stack pointer name */
7336   if (options.useXstack)
7337     spname = "_spx";
7338   else
7339     spname = "sp";
7340
7341   hc08_aop_pass[0] = newAsmop (AOP_REG);
7342   hc08_aop_pass[0]->size=1;
7343   hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7344   hc08_aop_pass[1] = newAsmop (AOP_REG);
7345   hc08_aop_pass[1]->size=1;
7346   hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7347   hc08_aop_pass[2] = newAsmop (AOP_DIR);
7348   hc08_aop_pass[2]->size=1;
7349   hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7350   hc08_aop_pass[3] = newAsmop (AOP_DIR);
7351   hc08_aop_pass[3]->size=1;
7352   hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7353
7354   for (ic = lic; ic; ic = ic->next)
7355     {
7356
7357       if (ic->lineno && cln != ic->lineno)
7358         {
7359           if (options.debug)
7360             {
7361               _G.debugLine = 1;
7362               emitcode ("", "C$%s$%d$%d$%d ==.",
7363                         FileBaseName (ic->filename), ic->lineno,
7364                         ic->level, ic->block);
7365               _G.debugLine = 0;
7366             }
7367           if (!options.noCcodeInAsm) {
7368             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, 
7369                       printCLine(ic->filename, ic->lineno));
7370           }
7371           cln = ic->lineno;
7372         }
7373       if (options.iCodeInAsm) {
7374         char regsInUse[80];
7375         int i;
7376
7377         for (i=0; i<6; i++) {
7378           sprintf (&regsInUse[i],
7379                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); 
7380         }
7381         regsInUse[i]=0;
7382         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7383       }
7384       /* if the result is marked as
7385          spilt and rematerializable or code for
7386          this has already been generated then
7387          do nothing */
7388       if (resultRemat (ic) || ic->generated)
7389         continue;
7390
7391       {
7392         int i;
7393         regs *reg;
7394         symbol *sym;
7395         
7396         for (i=A_IDX;i<=XA_IDX;i++)
7397           {
7398             reg = hc08_regWithIdx(i);
7399             if (reg->aop)
7400               emitcode("","; %s = %s offset %d", reg->name,
7401                        aopName(reg->aop), reg->aopofs);
7402             reg->isFree = TRUE;
7403           }
7404         if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7405           {
7406             sym = OP_SYMBOL (IC_LEFT (ic));
7407             if (sym->accuse == ACCUSE_HX)
7408               {
7409                 hc08_reg_h->isFree = FALSE;
7410                 hc08_reg_x->isFree = FALSE;
7411               }
7412             else if (sym->accuse == ACCUSE_XA)
7413               {
7414                 hc08_reg_a->isFree = FALSE;
7415                 if (sym->nRegs>1)
7416                   hc08_reg_x->isFree = FALSE;
7417               }
7418           }
7419         if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7420           {
7421             sym = OP_SYMBOL (IC_RIGHT (ic));
7422             if (sym->accuse == ACCUSE_HX)
7423               {
7424                 hc08_reg_h->isFree = FALSE;
7425                 hc08_reg_x->isFree = FALSE;
7426               }
7427             else if (sym->accuse == ACCUSE_XA)
7428               {
7429                 hc08_reg_a->isFree = FALSE;
7430                 if (sym->nRegs>1)
7431                   hc08_reg_x->isFree = FALSE;
7432               }
7433           }
7434       }
7435       
7436       /* depending on the operation */
7437       switch (ic->op)
7438         {
7439         case '!':
7440           genNot (ic);
7441           break;
7442
7443         case '~':
7444           genCpl (ic);
7445           break;
7446
7447         case UNARYMINUS:
7448           genUminus (ic);
7449           break;
7450
7451         case IPUSH:
7452           genIpush (ic);
7453           break;
7454
7455         case IPOP:
7456           /* IPOP happens only when trying to restore a
7457              spilt live range, if there is an ifx statement
7458              following this pop then the if statement might
7459              be using some of the registers being popped which
7460              would destory the contents of the register so
7461              we need to check for this condition and handle it */
7462           if (ic->next &&
7463               ic->next->op == IFX &&
7464               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7465             genIfx (ic->next, ic);
7466           else
7467             genIpop (ic);
7468           break;
7469
7470         case CALL:
7471           genCall (ic);
7472           break;
7473
7474         case PCALL:
7475           genPcall (ic);
7476           break;
7477
7478         case FUNCTION:
7479           genFunction (ic);
7480           break;
7481
7482         case ENDFUNCTION:
7483           genEndFunction (ic);
7484           break;
7485
7486         case RETURN:
7487           genRet (ic);
7488           break;
7489
7490         case LABEL:
7491           genLabel (ic);
7492           break;
7493
7494         case GOTO:
7495           genGoto (ic);
7496           break;
7497
7498         case '+':
7499           if (!genPointerGetSetOfs (ic))
7500             genPlus (ic);
7501           break;
7502
7503         case '-':
7504           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7505             genMinus (ic);
7506           break;
7507
7508         case '*':
7509           genMult (ic);
7510           break;
7511
7512         case '/':
7513           genDiv (ic);
7514           break;
7515
7516         case '%':
7517           genMod (ic);
7518           break;
7519
7520         case '>':
7521           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7522           break;
7523
7524         case '<':
7525           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7526           break;
7527
7528         case LE_OP:
7529         case GE_OP:
7530         case NE_OP:
7531
7532           /* note these two are xlated by algebraic equivalence
7533              during parsing SDCC.y */
7534           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7535                   "got '>=' or '<=' shouldn't have come here");
7536           break;
7537
7538         case EQ_OP:
7539           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7540           break;
7541
7542         case AND_OP:
7543           genAndOp (ic);
7544           break;
7545
7546         case OR_OP:
7547           genOrOp (ic);
7548           break;
7549
7550         case '^':
7551           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7552           break;
7553
7554         case '|':
7555           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7556           break;
7557
7558         case BITWISEAND:
7559           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7560           break;
7561
7562         case INLINEASM:
7563           genInline (ic);
7564           break;
7565
7566         case RRC:
7567           genRRC (ic);
7568           break;
7569
7570         case RLC:
7571           genRLC (ic);
7572           break;
7573
7574         case GETHBIT:
7575           genGetHbit (ic);
7576           break;
7577
7578         case LEFT_OP:
7579           genLeftShift (ic);
7580           break;
7581
7582         case RIGHT_OP:
7583           genRightShift (ic);
7584           break;
7585
7586         case GET_VALUE_AT_ADDRESS:
7587           genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7588           break;
7589
7590         case '=':
7591           if (POINTER_SET (ic))
7592             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7593           else
7594             genAssign (ic);
7595           break;
7596
7597         case IFX:
7598           genIfx (ic, NULL);
7599           break;
7600
7601         case ADDRESS_OF:
7602           genAddrOf (ic);
7603           break;
7604
7605         case JUMPTABLE:
7606           genJumpTab (ic);
7607           break;
7608
7609         case CAST:
7610           genCast (ic);
7611           break;
7612
7613         case RECEIVE:
7614           genReceive (ic);
7615           break;
7616
7617         case SEND:
7618           addSet (&_G.sendSet, ic);
7619           break;
7620
7621         case DUMMY_READ_VOLATILE:
7622           genDummyRead (ic);
7623           break;
7624
7625         case CRITICAL:
7626           genCritical (ic);
7627           break;
7628
7629         case ENDCRITICAL:
7630           genEndCritical (ic);
7631           break;
7632
7633         default:
7634           ic = ic;
7635         }
7636
7637       if (!hc08_reg_a->isFree)
7638         emitcode("","; forgot to free a");
7639       if (!hc08_reg_x->isFree)
7640         emitcode("","; forgot to free x");
7641       if (!hc08_reg_h->isFree)
7642         emitcode("","; forgot to free h");
7643       if (!hc08_reg_hx->isFree)
7644         emitcode("","; forgot to free hx");
7645       if (!hc08_reg_xa->isFree)
7646         emitcode("","; forgot to free xa");
7647     }
7648
7649
7650   /* now we are ready to call the
7651      peep hole optimizer */
7652   if (!options.nopeep)
7653     peepHole (&lineHead);
7654
7655   /* now do the actual printing */
7656   printLine (lineHead, codeOutFile);
7657   return;
7658 }