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