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