f799360b5a302291ffa2ed501ab45a6a361427ea
[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       accopWithMisc ("nsa", "");
5644       accopWithMisc ("and", "#0xf0");
5645       /* total: 5 cycles, 3 bytes */
5646       return;
5647     case 5:
5648       accopWithMisc ("nsa", "");
5649       accopWithMisc ("and", "#0xf0");
5650       accopWithMisc ("lsla", "");
5651       /* total: 6 cycles, 4 bytes */
5652       return;
5653     case 6:
5654       accopWithMisc ("rora", "");
5655       accopWithMisc ("rora", "");
5656       accopWithMisc ("rora", "");
5657       accopWithMisc ("and", "#0xc0");
5658       /* total: 5 cycles, 5 bytes */
5659       return;
5660     case 7:
5661       accopWithMisc ("rora", "");
5662       accopWithMisc ("clra", "");
5663       accopWithMisc ("rora", "");
5664       /* total: 3 cycles, 3 bytes */
5665       return;
5666     }
5667
5668     /* lsla is only 1 cycle and byte, so an unrolled loop is often  */
5669     /* the fastest (shCount<6) and shortest (shCount<4).            */
5670     for (i=0;i<shCount;i++)
5671       accopWithMisc ("lsla", "");
5672 }
5673
5674
5675 /*-----------------------------------------------------------------*/
5676 /* AccSRsh - signed right shift accumulator by known count         */
5677 /*-----------------------------------------------------------------*/
5678 static void
5679 AccSRsh (int shCount)
5680 {
5681   int i;
5682   
5683   shCount &= 0x0007;            // shCount : 0..7
5684
5685   if (shCount == 7)
5686     {
5687       accopWithMisc ("rola", "");
5688       accopWithMisc ("clra", "");
5689       accopWithMisc ("sbc", zero);
5690       /* total: 4 cycles, 4 bytes */
5691       return;
5692     }
5693
5694     for (i=0;i<shCount;i++)
5695       accopWithMisc ("asra", "");
5696 }
5697
5698 /*-----------------------------------------------------------------*/
5699 /* AccRsh - right shift accumulator by known count                 */
5700 /*-----------------------------------------------------------------*/
5701 static void
5702 AccRsh (int shCount, bool sign)
5703 {
5704   int i;
5705   
5706   if (sign)
5707     {
5708       AccSRsh (shCount);
5709       return;
5710     }
5711   
5712   shCount &= 0x0007;            // shCount : 0..7
5713
5714   /* Shift counts of 4 and 5 are currently optimized for code size.        */
5715   /* Falling through to the unrolled loop would be optimal for code speed. */
5716   /* For shift counts of 6 and 7, the unrolled loop is never optimal.      */
5717   switch (shCount)
5718     {
5719     case 4:
5720       accopWithMisc ("nsa", "");
5721       accopWithMisc ("and", "#0x0f");
5722       /* total: 5 cycles, 3 bytes */
5723       return;
5724     case 5:
5725       accopWithMisc ("nsa", "");
5726       accopWithMisc ("and", "#0x0f");
5727       accopWithMisc ("lsra", "");
5728       /* total: 6 cycles, 4 bytes */
5729       return;
5730     case 6:
5731       accopWithMisc ("rola", "");
5732       accopWithMisc ("rola", "");
5733       accopWithMisc ("rola", "");
5734       accopWithMisc ("and", "#0x03");
5735       /* total: 5 cycles, 5 bytes */
5736       return;
5737     case 7:
5738       accopWithMisc ("rola", "");
5739       accopWithMisc ("clra", "");
5740       accopWithMisc ("rola", "");
5741       /* total: 3 cycles, 3 bytes */
5742       return;
5743     }
5744
5745     /* lsra is only 1 cycle and byte, so an unrolled loop is often  */
5746     /* the fastest (shCount<6) and shortest (shCount<4).            */
5747     for (i=0;i<shCount;i++)
5748       accopWithMisc ("lsra", "");
5749 }
5750
5751
5752 /*-----------------------------------------------------------------*/
5753 /* XAccLsh - left shift register pair XA by known count            */
5754 /*-----------------------------------------------------------------*/
5755 static void
5756 XAccLsh (int shCount)
5757 {
5758   int i;
5759   
5760   shCount &= 0x000f;            // shCount : 0..15
5761
5762   if (shCount>=8)
5763     {
5764       AccLsh (shCount-8);
5765       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5766       loadRegFromConst (hc08_reg_a, zero);
5767       return;
5768     }
5769
5770   /* if we can beat 2n cycles or bytes for some special case, do it here */
5771   switch (shCount)
5772     {
5773     case 7:
5774       /*          bytes  cycles     reg x      reg a   carry
5775       **                          abcd efgh  ijkl mnop   ?
5776       **   lsrx       1  1        0abc defg  ijkl mnop   h
5777       **   rora       1  1        0abc defg  hijk lmno   p
5778       **   tax        1  1        hijk lmno  hijk lmno   p
5779       **   clra       1  1        hijk lmno  0000 0000   p
5780       **   rora       1  1        hijk lmno  p000 0000   0
5781       ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5782       */
5783       rmwWithReg ("lsr", hc08_reg_x);
5784       rmwWithReg ("ror", hc08_reg_a);
5785       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5786       loadRegFromConst (hc08_reg_a, zero);
5787       rmwWithReg ("ror", hc08_reg_a);
5788       return;
5789
5790     default:
5791       ;
5792     }
5793
5794   /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often  */
5795   /* the fastest and shortest.                                           */
5796   for (i=0;i<shCount;i++)
5797     {
5798       rmwWithReg ("lsl", hc08_reg_a);
5799       rmwWithReg ("rol", hc08_reg_x);
5800     }
5801 }
5802
5803 /*-----------------------------------------------------------------*/
5804 /* XAccSRsh - signed right shift register pair XA by known count   */
5805 /*-----------------------------------------------------------------*/
5806 static void
5807 XAccSRsh (int shCount)
5808 {
5809   int i;
5810   
5811   shCount &= 0x000f;            // shCount : 0..7
5812
5813   /* if we can beat 2n cycles or bytes for some special case, do it here */
5814   switch (shCount)
5815     {
5816     case 15:
5817       /*          bytes  cycles     reg x      reg a   carry
5818       **                          abcd efgh  ijkl mnop   ?
5819       **   lslx       1  1        bcde fgh0  ijkl mnop   a
5820       **   clra       1  1        bcde fgh0  0000 0000   a
5821       **   rola       1  1        bcde fgh0  0000 000a   0
5822       **   nega       1  1        bcde fgh0  aaaa aaaa   a
5823       **   tax        1  1        aaaa aaaa  aaaa aaaa   a
5824       ** total: 5 cycles, 5 bytes
5825       */
5826       rmwWithReg ("lsl", hc08_reg_x);
5827       loadRegFromConst (hc08_reg_a, zero);
5828       rmwWithReg ("rol", hc08_reg_a);
5829       rmwWithReg ("neg", hc08_reg_a);
5830       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5831       return;
5832
5833     case 14:
5834     case 13:
5835     case 12:
5836     case 11:
5837     case 10:
5838     case 9:
5839     case 8:
5840       /*          bytes  cycles     reg x      reg a   carry
5841       **                          abcd efgh  ijkl mnop   ?
5842       **   txa        1  1        abcd efgh  abcd efgh   ?
5843       **   (AccSRsh) <8 <8        abcd efgh  LSBresult   ?
5844       **   lsla       1  1        abcd efgh  ???? ????   a
5845       **   clrx       1  1        0000 0000  ???? ????   a
5846       **   rolx       1  1        0000 000a  ???? ????   0
5847       **   negx       1  1        aaaa aaaa  ???? ????   a
5848       **   rora       1  1        aaaa aaaa  LSBresult   0
5849       ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5850       */
5851       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5852       AccSRsh (shCount-8);
5853       rmwWithReg ("lsl", hc08_reg_a);
5854       loadRegFromConst (hc08_reg_x, zero);
5855       rmwWithReg ("rol", hc08_reg_x);
5856       rmwWithReg ("neg", hc08_reg_x);
5857       rmwWithReg ("ror", hc08_reg_a);
5858       return;
5859
5860     default:
5861       ;
5862     }
5863
5864   /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often  */
5865   /* the fastest and shortest.                                           */
5866   for (i=0;i<shCount;i++)
5867     {
5868       rmwWithReg ("asr", hc08_reg_x);
5869       rmwWithReg ("ror", hc08_reg_a);
5870     }
5871 }
5872
5873 /*-----------------------------------------------------------------*/
5874 /* XAccRsh - right shift register pair XA by known count           */
5875 /*-----------------------------------------------------------------*/
5876 static void
5877 XAccRsh (int shCount, bool sign)
5878 {
5879   int i;
5880   
5881   if (sign)
5882     {
5883       XAccSRsh (shCount);
5884       return;
5885     }
5886   
5887   shCount &= 0x000f;            // shCount : 0..f
5888
5889   /* if we can beat 2n cycles or bytes for some special case, do it here */
5890   switch (shCount)
5891     {
5892     case 15:
5893       /*          bytes  cycles     reg x      reg a   carry
5894       **                          abcd efgh  ijkl mnop   ?
5895       **   clra       1  1        abcd efgh  0000 0000   a
5896       **   lslx       1  1        bcde fgh0  0000 0000   a
5897       **   rola       1  1        bcde fgh0  0000 000a   0
5898       **   clrx       1  1        0000 0000  0000 000a   0
5899       ** total: 4 cycles, 4 bytes
5900       */
5901       loadRegFromConst (hc08_reg_x, zero);
5902       rmwWithReg ("lsl", hc08_reg_x);
5903       rmwWithReg ("rol", hc08_reg_a);
5904       loadRegFromConst (hc08_reg_a, zero);
5905       return;
5906
5907     case 14:
5908       /*          bytes  cycles     reg x      reg a   carry
5909       **                          abcd efgh  ijkl mnop   ?
5910       **   clra       1  1        abcd efgh  0000 0000   a
5911       **   lslx       1  1        bcde fgh0  0000 0000   a
5912       **   rola       1  1        bcde fgh0  0000 000a   0
5913       **   lslx       1  1        cdef gh00  0000 000a   b
5914       **   rola       1  1        cdef gh00  0000 00ab   0
5915       **   clrx       1  1        0000 0000  0000 00ab   0
5916       ** total: 6 cycles, 6 bytes
5917       */
5918       loadRegFromConst (hc08_reg_x, zero);
5919       rmwWithReg ("lsl", hc08_reg_x);
5920       rmwWithReg ("rol", hc08_reg_a);
5921       rmwWithReg ("lsl", hc08_reg_x);
5922       rmwWithReg ("rol", hc08_reg_a);
5923       loadRegFromConst (hc08_reg_a, zero);
5924       return;
5925
5926     case 13:
5927     case 12:
5928     case 11:
5929     case 10:
5930     case 9:
5931     case 8:
5932       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5933       AccRsh (shCount-8, FALSE);
5934       loadRegFromConst (hc08_reg_x, zero);
5935       return;
5936
5937     case 7:
5938       /*          bytes  cycles     reg x      reg a   carry
5939       **                          abcd efgh  ijkl mnop   ?
5940       **   lsla       1  1        abcd efgh  jklm nop0   i
5941       **   txa        1  1        abcd efgh  abcd efgh   i
5942       **   rola       1  1        abcd efgh  bcde fghi   a
5943       **   clrx       1  1        0000 0000  bcde fghi   a
5944       **   rolx       1  1        0000 000a  bcde fghi   0
5945       ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5946       */
5947       rmwWithReg ("lsl", hc08_reg_a);
5948       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5949       rmwWithReg ("rol", hc08_reg_a);
5950       loadRegFromConst (hc08_reg_x, zero);
5951       rmwWithReg ("rol", hc08_reg_x);
5952       return;
5953     case 6:
5954       /*          bytes  cycles     reg x      reg a   carry
5955       **                          abcd efgh  ijkl mnop   ?
5956       **   lsla       1  1        abcd efgh  jklm nop0   i
5957       **   rolx       1  1        bcde fghi  jklm nop0   a
5958       **   rola       1  1        bcde fghi  klmn op0a   j
5959       **   rolx       1  1        cdef ghij  klmn op0a   b
5960       **   rola       1  1        cdef ghij  lmno p0ab   k
5961       **   and #3     2  2        cdef ghij  0000 00ab   k
5962       **   psha       1  2        cdef ghij  0000 00ab   k
5963       **   txa        1  1        cdef ghij  cdef ghij   k
5964       **   pula       1  2        0000 00ab  cdef ghij   k
5965       ** total: 12 cycles, 10 bytes (beats 12 bytes)
5966       */
5967     default:
5968       ;
5969     }
5970
5971   /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often  */
5972   /* the fastest and shortest.                                           */
5973   for (i=0;i<shCount;i++)
5974     {
5975       rmwWithReg ("lsr", hc08_reg_x);
5976       rmwWithReg ("ror", hc08_reg_a);
5977     }
5978
5979 }
5980
5981
5982 #if 0
5983 /*-----------------------------------------------------------------*/
5984 /* shiftR1Left2Result - shift right one byte from left to result   */
5985 /*-----------------------------------------------------------------*/
5986 static void
5987 shiftR1Left2Result (operand * left, int offl,
5988                     operand * result, int offr,
5989                     int shCount, int sign)
5990 {
5991   loadRegFromAop (hc08_reg_a, AOP (left), offl);
5992   /* shift right accumulator */
5993   AccRsh (shCount, sign);
5994   storeRegToAop (hc08_reg_a, AOP (result), offr);
5995 }
5996 #endif
5997
5998 /*-----------------------------------------------------------------*/
5999 /* shiftL1Left2Result - shift left one byte from left to result    */
6000 /*-----------------------------------------------------------------*/
6001 static void
6002 shiftL1Left2Result (operand * left, int offl,
6003                     operand * result, int offr, int shCount)
6004 {
6005   loadRegFromAop (hc08_reg_a, AOP (left), offl);
6006   /* shift left accumulator */
6007   AccLsh (shCount);
6008   storeRegToAop (hc08_reg_a, AOP (result), offr);
6009 }
6010
6011 /*-----------------------------------------------------------------*/
6012 /* movLeft2Result - move byte from left to result                  */
6013 /*-----------------------------------------------------------------*/
6014 static void
6015 movLeft2Result (operand * left, int offl,
6016                 operand * result, int offr, int sign)
6017 {
6018   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6019     {
6020       transferAopAop (AOP (left), offl, AOP (result), offr);
6021     }
6022 }
6023
6024
6025 /*-----------------------------------------------------------------*/
6026 /* shiftL2Left2Result - shift left two bytes from left to result   */
6027 /*-----------------------------------------------------------------*/
6028 static void
6029 shiftL2Left2Result (operand * left, int offl,
6030                     operand * result, int offr, int shCount)
6031 {
6032   int i;
6033   bool needpula = FALSE;
6034   bool needpulx = FALSE;
6035
6036   if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6037     needpula = pushRegIfUsed (hc08_reg_a);
6038   else
6039     needpula = FALSE;
6040   if (!IS_AOP_XA (AOP (left)))
6041     needpulx = pushRegIfUsed (hc08_reg_x);
6042   else
6043     needpulx = FALSE;
6044
6045   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6046
6047   switch (shCount)
6048     {
6049       case 7:
6050         rmwWithReg ("lsr", hc08_reg_x);
6051         rmwWithReg ("ror", hc08_reg_a);
6052         transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6053         rmwWithReg ("clr", hc08_reg_a);
6054         rmwWithReg ("ror", hc08_reg_a);
6055         break;
6056       default:
6057         for (i=0; i<shCount; i++)
6058           {
6059             rmwWithReg ("lsl", hc08_reg_a);
6060             rmwWithReg ("rol", hc08_reg_x);
6061           }
6062     }
6063   storeRegToAop (hc08_reg_xa, AOP (result), offr);
6064
6065   pullOrFreeReg (hc08_reg_x, needpulx);
6066   pullOrFreeReg (hc08_reg_a, needpula);
6067
6068 }
6069
6070
6071 #if 0
6072 /*-----------------------------------------------------------------*/
6073 /* shiftR2Left2Result - shift right two bytes from left to result  */
6074 /*-----------------------------------------------------------------*/
6075 static void
6076 shiftR2Left2Result (operand * left, int offl,
6077                     operand * result, int offr,
6078                     int shCount, int sign)
6079 {
6080   int i;
6081   bool needpula = FALSE;
6082   bool needpulx = FALSE;
6083   
6084   needpula = pushRegIfUsed (hc08_reg_a);
6085   needpulx = pushRegIfUsed (hc08_reg_x);
6086
6087   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6088   for (i=0; i<shCount; i++)
6089     {
6090       if (sign)
6091         rmwWithReg ("asr", hc08_reg_x);
6092       else
6093         rmwWithReg ("lsr", hc08_reg_x);
6094       rmwWithReg ("ror", hc08_reg_a);
6095     }
6096   storeRegToAop (hc08_reg_xa, AOP (result), offl);
6097
6098   pullOrFreeReg (hc08_reg_x, needpulx);
6099   pullOrFreeReg (hc08_reg_a, needpula);
6100 }
6101 #endif
6102
6103 #if 0
6104 /*-----------------------------------------------------------------*/
6105 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6106 /*-----------------------------------------------------------------*/
6107 static void
6108 shiftLLeftOrResult (operand * left, int offl,
6109                     operand * result, int offr, int shCount)
6110 {
6111   loadRegFromAop (hc08_reg_a, AOP (left), offl);
6112   /* shift left accumulator */
6113   AccLsh (shCount);
6114   /* or with result */
6115   accopWithAop ("ora", AOP (result), offr);
6116   /* back to result */
6117   storeRegToAop (hc08_reg_a, AOP (result), offr);
6118   hc08_freeReg (hc08_reg_a);
6119 }
6120 #endif
6121
6122 /*-----------------------------------------------------------------*/
6123 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6124 /*-----------------------------------------------------------------*/
6125 static void
6126 shiftRLeftOrResult (operand * left, int offl,
6127                     operand * result, int offr, int shCount)
6128 {
6129   loadRegFromAop (hc08_reg_a, AOP (left), offl);
6130   /* shift left accumulator */
6131   AccRsh (shCount, FALSE);
6132   /* or with result */
6133   accopWithAop ("ora", AOP (result), offr);
6134   /* back to result */
6135   storeRegToAop (hc08_reg_a, AOP (result), offr);
6136   hc08_freeReg (hc08_reg_a);
6137 }
6138
6139 /*-----------------------------------------------------------------*/
6140 /* genlshOne - left shift a one byte quantity by known count       */
6141 /*-----------------------------------------------------------------*/
6142 static void
6143 genlshOne (operand * result, operand * left, int shCount)
6144 {
6145   D(emitcode (";     genlshOne",""));
6146
6147   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6148 }
6149
6150 /*-----------------------------------------------------------------*/
6151 /* genlshTwo - left shift two bytes by known amount != 0           */
6152 /*-----------------------------------------------------------------*/
6153 static void
6154 genlshTwo (operand * result, operand * left, int shCount)
6155 {
6156   int size;
6157
6158   D(emitcode (";     genlshTwo",""));
6159
6160   
6161   size = getDataSize (result);
6162
6163   /* if shCount >= 8 */
6164   if (shCount >= 8)
6165     {
6166       shCount -= 8;
6167
6168       if (size > 1)
6169         {
6170           loadRegFromAop (hc08_reg_a, AOP (left), 0);
6171           AccLsh (shCount);
6172           storeRegToAop (hc08_reg_a, AOP (result), 1);
6173         }
6174       storeConstToAop(zero, AOP (result), LSB);
6175     }
6176
6177   /*  1 <= shCount <= 7 */
6178   else
6179     {
6180       loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6181       XAccLsh (shCount);
6182       storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6183     }
6184 }
6185
6186 /*-----------------------------------------------------------------*/
6187 /* shiftLLong - shift left one long from left to result            */
6188 /* offl = LSB or MSB16                                             */
6189 /*-----------------------------------------------------------------*/
6190 static void
6191 shiftLLong (operand * left, operand * result, int offr)
6192 {
6193 //  char *l;
6194 //  int size = AOP_SIZE (result);
6195
6196   bool needpula = FALSE;
6197   bool needpulx = FALSE;
6198
6199   needpula = pushRegIfUsed (hc08_reg_a);
6200   needpulx = pushRegIfUsed (hc08_reg_x);
6201
6202   loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6203   rmwWithReg ("lsl", hc08_reg_a);
6204   rmwWithReg ("rol", hc08_reg_x);
6205   storeRegToAop (hc08_reg_xa, AOP (result), offr);
6206
6207   if (offr==LSB)
6208     {
6209       loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6210       rmwWithReg ("rol", hc08_reg_a);
6211       rmwWithReg ("rol", hc08_reg_x);
6212       storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6213     }
6214   else if (offr==MSB16)
6215     {
6216       loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6217       rmwWithReg ("rol", hc08_reg_a);
6218       storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6219     }
6220
6221   pullOrFreeReg (hc08_reg_x, needpulx);
6222   pullOrFreeReg (hc08_reg_a, needpula);
6223 }
6224
6225 /*-----------------------------------------------------------------*/
6226 /* genlshFour - shift four byte by a known amount != 0             */
6227 /*-----------------------------------------------------------------*/
6228 static void
6229 genlshFour (operand * result, operand * left, int shCount)
6230 {
6231   int size;
6232
6233   D(emitcode (";     genlshFour",""));
6234
6235   size = AOP_SIZE (result);
6236
6237   /* TODO: deal with the &result == &left case */
6238
6239   /* if shifting more that 3 bytes */
6240   if (shCount >= 24)
6241     {
6242       shCount -= 24;
6243       if (shCount)
6244         /* lowest order of left goes to the highest
6245            order of the destination */
6246         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6247       else
6248         movLeft2Result (left, LSB, result, MSB32, 0);
6249       storeConstToAop (zero, AOP (result), LSB);
6250       storeConstToAop (zero, AOP (result), MSB16);
6251       storeConstToAop (zero, AOP (result), MSB24);
6252       return;
6253     }
6254
6255   /* more than two bytes */
6256   else if (shCount >= 16)
6257     {
6258       /* lower order two bytes goes to higher order two bytes */
6259       shCount -= 16;
6260       /* if some more remaining */
6261       if (shCount)
6262         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6263       else
6264         {
6265           movLeft2Result (left, MSB16, result, MSB32, 0);
6266           movLeft2Result (left, LSB, result, MSB24, 0);
6267         }
6268       storeConstToAop (zero, AOP (result), LSB);
6269       storeConstToAop (zero, AOP (result), MSB16);
6270       return;
6271     }
6272
6273   /* if more than 1 byte */
6274   else if (shCount >= 8)
6275     {
6276       /* lower order three bytes goes to higher order  three bytes */
6277       shCount -= 8;
6278       if (size == 2)
6279         {
6280           if (shCount)
6281             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6282           else
6283             movLeft2Result (left, LSB, result, MSB16, 0);
6284         }
6285       else
6286         {                       /* size = 4 */
6287           if (shCount == 0)
6288             {
6289               movLeft2Result (left, MSB24, result, MSB32, 0);
6290               movLeft2Result (left, MSB16, result, MSB24, 0);
6291               movLeft2Result (left, LSB, result, MSB16, 0);
6292               storeConstToAop (zero, AOP (result), LSB);
6293             }
6294           else if (shCount == 1)
6295             shiftLLong (left, result, MSB16);
6296           else
6297             {
6298               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6299               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6300               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6301               storeConstToAop (zero, AOP (result), LSB);
6302             }
6303         }
6304     }
6305
6306   /* 1 <= shCount <= 7 */
6307   else if (shCount <= 2)
6308     {
6309       shiftLLong (left, result, LSB);
6310       if (shCount == 2)
6311         shiftLLong (result, result, LSB);
6312     }
6313   /* 3 <= shCount <= 7, optimize */
6314   else
6315     {
6316       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6317       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6318       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6319     }
6320 }
6321
6322 /*-----------------------------------------------------------------*/
6323 /* genLeftShiftLiteral - left shifting by known count              */
6324 /*-----------------------------------------------------------------*/
6325 static void
6326 genLeftShiftLiteral (operand * left,
6327                      operand * right,
6328                      operand * result,
6329                      iCode * ic)
6330 {
6331   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6332   int size;
6333
6334   D(emitcode (";     genLeftShiftLiteral",""));
6335
6336   freeAsmop (right, NULL, ic, TRUE);
6337
6338   aopOp (left, ic, FALSE);
6339   aopOp (result, ic, FALSE);
6340
6341 //  size = getSize (operandType (result));
6342   size = AOP_SIZE (result);
6343
6344 #if VIEW_SIZE
6345   D(emitcode ("; shift left ", "result %d, left %d", size,
6346             AOP_SIZE (left)));
6347 #endif
6348
6349   if (shCount == 0)
6350     {
6351       while (size--)
6352         transferAopAop( AOP(left), size, AOP(result), size);
6353     }
6354   else if (shCount >= (size * 8))
6355     {
6356       while (size--)
6357         storeConstToAop (zero, AOP (result), size);
6358     }
6359   else
6360     {
6361       switch (size)
6362         {
6363         case 1:
6364           genlshOne (result, left, shCount);
6365           break;
6366
6367         case 2:
6368           genlshTwo (result, left, shCount);
6369           break;
6370
6371         case 4:
6372           genlshFour (result, left, shCount);
6373           break;
6374         default:
6375           werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
6376                   "*** ack! mystery literal shift!\n");
6377           break;
6378         }
6379     }
6380   freeAsmop (left, NULL, ic, TRUE);
6381   freeAsmop (result, NULL, ic, TRUE);
6382 }
6383
6384 /*-----------------------------------------------------------------*/
6385 /* genLeftShift - generates code for left shifting                 */
6386 /*-----------------------------------------------------------------*/
6387 static void
6388 genLeftShift (iCode * ic)
6389 {
6390   operand *left, *right, *result;
6391   int size, offset;
6392   symbol *tlbl, *tlbl1;
6393 //  int i;
6394   char *shift;
6395   regs *reg;
6396
6397   D(emitcode (";     genLeftShift",""));
6398
6399   right = IC_RIGHT (ic);
6400   left = IC_LEFT (ic);
6401   result = IC_RESULT (ic);
6402
6403   aopOp (right, ic, FALSE);
6404
6405   /* if the shift count is known then do it
6406      as efficiently as possible */
6407   if (AOP_TYPE (right) == AOP_LIT)
6408     {
6409       genLeftShiftLiteral (left, right, result, ic);
6410       return;
6411     }
6412
6413   /* shift count is unknown then we have to form
6414      a loop get the loop count in A : Note: we take
6415      only the lower order byte since shifting
6416      more that 32 bits make no sense anyway, ( the
6417      largest size of an object can be only 32 bits ) */
6418
6419   aopOp (left, ic, FALSE);
6420   aopOp (result, ic, FALSE);
6421
6422   /* now move the left to the result if they are not the
6423      same */
6424   if (!sameRegs (AOP (left), AOP (result)))
6425     {
6426
6427       size = AOP_SIZE (result);
6428       offset = 0;
6429       while (size--)
6430         {
6431           transferAopAop (AOP (left), offset, AOP (result), offset);
6432           offset++;
6433         }
6434     }
6435   freeAsmop (left, NULL, ic, TRUE);
6436   
6437   tlbl = newiTempLabel (NULL);
6438   size = AOP_SIZE (result);
6439   offset = 0;
6440   tlbl1 = newiTempLabel (NULL);
6441
6442   reg = hc08_reg_a;
6443
6444   loadRegFromAop (reg, AOP (right), 0);
6445   freeAsmop (right, NULL, ic, TRUE);
6446   emitBranch ("beq", tlbl1);
6447   emitLabel (tlbl);
6448   
6449   shift="lsl";
6450   for (offset=0;offset<size;offset++)
6451     {
6452       rmwWithAop (shift, AOP (result), offset);  
6453       shift="rol";
6454     }
6455   rmwWithReg ("dec", reg);
6456   emitBranch ("bne", tlbl);
6457   emitLabel (tlbl1);
6458   hc08_freeReg (reg);
6459   
6460   freeAsmop (result, NULL, ic, TRUE);
6461 }
6462
6463 /*-----------------------------------------------------------------*/
6464 /* genrshOne - right shift a one byte quantity by known count      */
6465 /*-----------------------------------------------------------------*/
6466 static void
6467 genrshOne (operand * result, operand * left,
6468            int shCount, int sign)
6469 {
6470   D(emitcode (";     genrshOne",""));
6471
6472   loadRegFromAop (hc08_reg_a, AOP (left), 0);
6473   AccRsh (shCount, sign);
6474   storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6475 }
6476
6477 /*-----------------------------------------------------------------*/
6478 /* genrshTwo - right shift two bytes by known amount != 0          */
6479 /*-----------------------------------------------------------------*/
6480 static void
6481 genrshTwo (operand * result, operand * left,
6482            int shCount, int sign)
6483 {
6484   D(emitcode (";     genrshTwo",""));
6485
6486   /* if shCount >= 8 */
6487   if (shCount >= 8)
6488     {
6489       if (shCount || sign)
6490         {
6491           loadRegFromAop (hc08_reg_a, AOP (left), 1);
6492           AccRsh (shCount-8, sign);
6493           storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6494         }
6495       else
6496         {
6497           transferAopAop (AOP (left), 1, AOP (result), 0);
6498           storeConstToAop (zero, AOP (result), 1);
6499         }
6500     }
6501
6502   /*  1 <= shCount <= 7 */
6503   else
6504     {
6505       loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6506       XAccRsh (shCount, sign);
6507       storeRegToAop (hc08_reg_xa, AOP (result), 0);
6508     }
6509 }
6510
6511 /*-----------------------------------------------------------------*/
6512 /* shiftRLong - shift right one long from left to result           */
6513 /* offl = LSB or MSB16                                             */
6514 /*-----------------------------------------------------------------*/
6515 static void
6516 shiftRLong (operand * left, int offl,
6517             operand * result, int sign)
6518 {
6519 //  char *l;
6520  // int size = AOP_SIZE (result);
6521
6522   bool needpula = FALSE;
6523   bool needpulx = FALSE;
6524
6525   needpula = pushRegIfUsed (hc08_reg_a);
6526   needpulx = pushRegIfUsed (hc08_reg_x);
6527
6528   if (offl==LSB)
6529     {
6530       loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6531       if (sign)
6532         rmwWithReg ("asr", hc08_reg_x);
6533       else
6534         rmwWithReg ("lsr", hc08_reg_x);
6535       rmwWithReg ("ror", hc08_reg_a);
6536       storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6537     }
6538   else if (offl==MSB16)
6539     {
6540       loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6541       if (sign)
6542         rmwWithReg ("asr", hc08_reg_a);
6543       else
6544         rmwWithReg ("lsr", hc08_reg_a);
6545       storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6546     }
6547
6548   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6549   rmwWithReg ("ror", hc08_reg_x);
6550   rmwWithReg ("ror", hc08_reg_a);
6551   storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6552
6553
6554   pullOrFreeReg (hc08_reg_x, needpulx);
6555   pullOrFreeReg (hc08_reg_a, needpula);
6556 }
6557
6558 /*-----------------------------------------------------------------*/
6559 /* genrshFour - shift four byte by a known amount != 0             */
6560 /*-----------------------------------------------------------------*/
6561 static void
6562 genrshFour (operand * result, operand * left,
6563             int shCount, int sign)
6564 {
6565   /* TODO: handle cases where left == result */
6566   
6567   D(emitcode (";     genrshFour",""));
6568
6569   /* if shifting more that 3 bytes */
6570   if (shCount >= 24)
6571     {
6572       loadRegFromAop (hc08_reg_a, AOP (left), 3);
6573       AccRsh (shCount-24, sign);
6574       storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6575       return;
6576     }
6577   else if (shCount >= 16)
6578     {
6579       loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6580       XAccRsh (shCount-16, sign);
6581       storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6582       return;
6583     }
6584   else if (shCount >= 8)
6585     {
6586       if (shCount == 1)
6587         shiftRLong (left, MSB16, result, sign);
6588       else if (shCount == 8)
6589         {
6590           transferAopAop (AOP (left), 1, AOP (result), 0);
6591           transferAopAop (AOP (left), 2, AOP (result), 1);
6592           loadRegFromAop (hc08_reg_a, AOP (left), 3);
6593           storeRegToAop (hc08_reg_a, AOP (result), 2);
6594           storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6595         }
6596       else if (shCount == 9)
6597         {
6598           shiftRLong (left, MSB16, result, sign);
6599         }
6600       else
6601         {
6602           loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6603           XAccRsh (shCount-8, FALSE);
6604           storeRegToAop (hc08_reg_xa, AOP (result), 0);
6605           loadRegFromAop (hc08_reg_x, AOP (left), 3);
6606           loadRegFromConst (hc08_reg_a, zero);
6607           XAccRsh (shCount-8, sign);
6608           accopWithAop ("ora", AOP (result), 1);
6609           storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6610         }
6611     }
6612   else
6613     {                           /* 1 <= shCount <= 7 */
6614       if (shCount == 1)
6615         {
6616           shiftRLong (left, LSB, result, sign);
6617         }
6618       else
6619         {
6620           loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6621           XAccRsh (shCount, FALSE);
6622           storeRegToAop (hc08_reg_xa, AOP (result), 0);
6623           loadRegFromAop (hc08_reg_a, AOP (left), 2);
6624           AccLsh (8-shCount);
6625           accopWithAop ("ora", AOP (result), 1);
6626           storeRegToAop (hc08_reg_a, AOP (result), 1);
6627           loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6628           XAccRsh (shCount, sign);
6629           storeRegToAop (hc08_reg_xa, AOP (result), 2);
6630         }
6631     }
6632 }
6633
6634 /*-----------------------------------------------------------------*/
6635 /* genRightShiftLiteral - right shifting by known count            */
6636 /*-----------------------------------------------------------------*/
6637 static void
6638 genRightShiftLiteral (operand * left,
6639                       operand * right,
6640                       operand * result,
6641                       iCode * ic,
6642                       int sign)
6643 {
6644   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6645   int size;
6646
6647   D(emitcode (";     genRightShiftLiteral",""));
6648
6649   freeAsmop (right, NULL, ic, TRUE);
6650
6651   aopOp (left, ic, FALSE);
6652   aopOp (result, ic, FALSE);
6653
6654 #if VIEW_SIZE
6655   D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6656             AOP_SIZE (left)));
6657 #endif
6658
6659   size = getDataSize (left);
6660   /* test the LEFT size !!! */
6661
6662   /* I suppose that the left size >= result size */
6663   if (shCount == 0)
6664     {
6665       size = getDataSize (result);
6666       while (size--)
6667         transferAopAop (AOP (left), size, AOP(result), size);
6668     }
6669   else if (shCount >= (size * 8))
6670     {
6671       if (sign) {
6672         /* get sign in acc.7 */
6673         loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6674       }
6675       addSign (result, LSB, sign);
6676     }
6677   else
6678     {
6679       switch (size)
6680         {
6681         case 1:
6682           genrshOne (result, left, shCount, sign);
6683           break;
6684
6685         case 2:
6686           genrshTwo (result, left, shCount, sign);
6687           break;
6688
6689         case 4:
6690           genrshFour (result, left, shCount, sign);
6691           break;
6692         default:
6693           break;
6694         }
6695     }
6696   freeAsmop (left, NULL, ic, TRUE);
6697   freeAsmop (result, NULL, ic, TRUE);
6698 }
6699
6700
6701 /*-----------------------------------------------------------------*/
6702 /* genRightShift - generate code for right shifting                */
6703 /*-----------------------------------------------------------------*/
6704 static void
6705 genRightShift (iCode * ic)
6706 {
6707   operand *right, *left, *result;
6708   sym_link *retype;
6709   int size, offset;
6710 //  char *l;
6711   symbol *tlbl, *tlbl1;
6712   char *shift;
6713   bool sign;
6714   
6715   D(emitcode (";     genRightShift",""));
6716
6717   /* if signed then we do it the hard way preserve the
6718      sign bit moving it inwards */
6719   retype = getSpec (operandType (IC_RESULT (ic)));
6720   sign = !SPEC_USIGN (retype);
6721
6722   /* signed & unsigned types are treated the same : i.e. the
6723      signed is NOT propagated inwards : quoting from the
6724      ANSI - standard : "for E1 >> E2, is equivalent to division
6725      by 2**E2 if unsigned or if it has a non-negative value,
6726      otherwise the result is implementation defined ", MY definition
6727      is that the sign does not get propagated */
6728
6729   right = IC_RIGHT (ic);
6730   left = IC_LEFT (ic);
6731   result = IC_RESULT (ic);
6732
6733   aopOp (right, ic, FALSE);
6734
6735   /* if the shift count is known then do it
6736      as efficiently as possible */
6737   if (AOP_TYPE (right) == AOP_LIT)
6738     {
6739       genRightShiftLiteral (left, right, result, ic, sign);
6740       return;
6741     }
6742
6743   /* shift count is unknown then we have to form
6744      a loop get the loop count in X : Note: we take
6745      only the lower order byte since shifting
6746      more that 32 bits make no sense anyway, ( the
6747      largest size of an object can be only 32 bits ) */
6748
6749   aopOp (left, ic, FALSE);
6750   aopOp (result, ic, FALSE);
6751
6752   if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6753     AOP (result) = forceStackedAop (AOP (result));
6754   
6755   size = AOP_SIZE (result); 
6756   offset = size-1;
6757   while (size--)
6758     {
6759       transferAopAop (AOP (left), offset, AOP (result), offset);
6760       offset--;
6761     }
6762   
6763   tlbl = newiTempLabel (NULL);
6764   size = AOP_SIZE (result);
6765   offset = 0;
6766   tlbl1 = newiTempLabel (NULL);
6767
6768   loadRegFromAop (hc08_reg_x, AOP (right), 0);
6769   emitcode ("tstx", "");
6770   emitcode ("beq", "%05d$", tlbl1->key + 100);
6771   emitcode ("", "%05d$:", tlbl->key + 100);
6772   shift= sign ? "asr" : "lsr";
6773   for (offset=size-1;offset>=0;offset--)
6774     {
6775       rmwWithAop (shift, AOP (result), offset);
6776       shift="ror";
6777     }
6778   rmwWithReg ("dec", hc08_reg_x);
6779   emitcode ("bne","%05d$", tlbl->key + 100);
6780   emitcode ("", "%05d$:", tlbl1->key + 100);
6781   
6782   freeAsmop (result, NULL, ic, TRUE);
6783   freeAsmop (left, NULL, ic, TRUE);
6784   freeAsmop (right, NULL, ic, TRUE);
6785 }
6786
6787
6788 /*-----------------------------------------------------------------*/
6789 /* genUnpackBits - generates code for unpacking bits               */
6790 /*-----------------------------------------------------------------*/
6791 static void
6792 genUnpackBits (operand * result, iCode *ifx)
6793 {
6794   int offset = 0;       /* result byte offset */
6795   int rsize;            /* result size */
6796   int rlen = 0;         /* remaining bitfield length */
6797   sym_link *etype;      /* bitfield type information */
6798   int blen;             /* bitfield length */
6799   int bstr;             /* bitfield starting bit within byte */
6800
6801   D(emitcode (";     genUnpackBits",""));
6802
6803   etype = getSpec (operandType (result));
6804   rsize = getSize (operandType (result));
6805   blen = SPEC_BLEN (etype);
6806   bstr = SPEC_BSTR (etype);
6807
6808   /* If the bitfield length is less than a byte */
6809   if (blen < 8)
6810     {
6811       emitcode ("lda", ",x");
6812       hc08_dirtyReg (hc08_reg_a, FALSE);
6813       if (!ifx)
6814         {
6815           AccRsh (bstr, FALSE);
6816           emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6817           storeRegToAop (hc08_reg_a, AOP (result), offset++);
6818         }
6819       else
6820         {
6821           emitcode ("and", "#0x%02x",
6822                     (((unsigned char) -1) >> (8 - blen)) << bstr);
6823         }
6824       goto finish;
6825     }
6826
6827   /* Bit field did not fit in a byte. Copy all
6828      but the partial byte at the end.  */
6829   for (rlen=blen;rlen>=8;rlen-=8)
6830     {
6831       emitcode ("lda", ",x");
6832       hc08_dirtyReg (hc08_reg_a, FALSE);
6833       if (!ifx)
6834         storeRegToAop (hc08_reg_a, AOP (result), offset);
6835       offset++;
6836       if (rlen>8)
6837         emitcode ("aix", "#1");
6838     }
6839
6840   /* Handle the partial byte at the end */
6841   if (rlen)
6842     {
6843       emitcode ("lda", ",x");
6844       emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6845       storeRegToAop (hc08_reg_a, AOP (result), offset++);
6846     }
6847
6848 finish:
6849   if (offset < rsize)
6850     {
6851       rsize -= offset;
6852       while (rsize--)
6853         storeConstToAop (zero, AOP (result), offset++);
6854     }
6855   
6856   if (ifx && !ifx->generated)
6857     {
6858       genIfxJump (ifx, "a");
6859     }
6860 }
6861
6862
6863 /*-----------------------------------------------------------------*/
6864 /* genUnpackBitsImmed - generates code for unpacking bits          */
6865 /*-----------------------------------------------------------------*/
6866 static void
6867 genUnpackBitsImmed (operand * left,
6868                     operand * result,
6869                     iCode *ic,
6870                     iCode *ifx)
6871 {
6872   int size;
6873   int offset = 0;       /* result byte offset */
6874   int rsize;            /* result size */
6875   int rlen = 0;         /* remaining bitfield length */
6876   sym_link *etype;      /* bitfield type information */
6877   int blen;             /* bitfield length */
6878   int bstr;             /* bitfield starting bit within byte */
6879   asmop *derefaop;
6880   
6881   D(emitcode (";     genUnpackBitsImmed",""));
6882
6883   aopOp (result, ic, TRUE);
6884   size = AOP_SIZE (result);
6885
6886   derefaop = aopDerefAop (AOP (left));
6887   freeAsmop (left, NULL, ic, TRUE);
6888   derefaop->size = size;
6889   
6890   etype = getSpec (operandType (result));
6891   rsize = getSize (operandType (result));
6892   blen = SPEC_BLEN (etype);
6893   bstr = SPEC_BSTR (etype);
6894
6895   /* if the bitfield is a single bit in the direct page */
6896   if (blen == 1 && derefaop->type == AOP_DIR)
6897     {
6898       if (!ifx && bstr)
6899         {
6900           symbol *tlbl = newiTempLabel (NULL);
6901           
6902           loadRegFromConst (hc08_reg_a, zero);
6903           emitcode ("brclr", "#%d,%s,%05d$",
6904                     bstr, aopAdrStr (derefaop, 0, FALSE),
6905                     (tlbl->key + 100));
6906           rmwWithReg ("inc", hc08_reg_a);
6907           emitLabel (tlbl);
6908           storeRegToAop (hc08_reg_a, AOP (result), offset);
6909           hc08_freeReg (hc08_reg_a);
6910           offset++;
6911           goto finish;
6912         }
6913       else if (ifx)
6914         {
6915           symbol *tlbl = newiTempLabel (NULL);
6916           symbol *jlbl;
6917           char * inst;
6918           
6919           if (IC_TRUE (ifx))
6920             {
6921               jlbl = IC_TRUE (ifx);
6922               inst = "brclr";
6923             }
6924           else
6925             {
6926               jlbl = IC_FALSE (ifx);
6927               inst = "brset";
6928             }
6929           emitcode (inst, "#%d,%s,%05d$",
6930                     bstr, aopAdrStr (derefaop, 0, FALSE),
6931                     (tlbl->key + 100));
6932           emitBranch ("jmp", jlbl);
6933           emitLabel (tlbl);
6934           ifx->generated = 1;
6935           offset++;
6936           goto finish;
6937         }
6938     }
6939
6940   /* If the bitfield length is less than a byte */
6941   if (blen < 8)
6942     {
6943       loadRegFromAop (hc08_reg_a, derefaop, 0);
6944       if (!ifx)
6945         {
6946           AccRsh (bstr, FALSE);
6947           emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6948           hc08_dirtyReg (hc08_reg_a, FALSE);
6949           storeRegToAop (hc08_reg_a, AOP (result), offset);
6950         }
6951       else
6952         {
6953           emitcode ("and", "#0x%02x",
6954                     (((unsigned char) -1) >> (8 - blen)) << bstr);
6955           hc08_dirtyReg (hc08_reg_a, FALSE);
6956         }
6957       offset++;
6958       goto finish;
6959     }
6960
6961   /* Bit field did not fit in a byte. Copy all
6962      but the partial byte at the end.  */
6963   for (rlen=blen;rlen>=8;rlen-=8)
6964     {
6965       loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6966       if (!ifx)
6967         storeRegToAop (hc08_reg_a, AOP (result), offset);
6968       else
6969         emitcode ("tsta", "");
6970       offset++;
6971     }
6972
6973   /* Handle the partial byte at the end */
6974   if (rlen)
6975     {
6976       loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6977       emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6978       storeRegToAop (hc08_reg_a, AOP (result), offset++);
6979     }
6980
6981 finish:
6982   if (offset < rsize)
6983     {
6984       rsize -= offset;
6985       while (rsize--)
6986         storeConstToAop (zero, AOP (result), offset++);
6987     }
6988   
6989   freeAsmop (NULL, derefaop, ic, TRUE);
6990   freeAsmop (result, NULL, ic, TRUE);
6991   
6992   if (ifx && !ifx->generated)
6993     {
6994       genIfxJump (ifx, "a");
6995     }
6996 }
6997
6998
6999 /*-----------------------------------------------------------------*/
7000 /* genDataPointerGet - generates code when ptr offset is known     */
7001 /*-----------------------------------------------------------------*/
7002 static void
7003 genDataPointerGet (operand * left,
7004                    operand * result,
7005                    iCode * ic,
7006                    iCode * ifx)
7007 {
7008   int size, offset = 0;
7009   asmop *derefaop;
7010   
7011   D(emitcode (";     genDataPointerGet",""));
7012
7013   aopOp (result, ic, TRUE);
7014   size = AOP_SIZE (result);
7015
7016   derefaop = aopDerefAop (AOP (left));
7017   freeAsmop (left, NULL, ic, TRUE);
7018   derefaop->size = size;
7019   
7020   while (size--)
7021     {
7022       if (!ifx)
7023         transferAopAop (derefaop, offset, AOP (result), offset);
7024       else
7025         loadRegFromAop (hc08_reg_a, derefaop, offset);
7026       offset++;
7027     }
7028
7029   freeAsmop (NULL, derefaop, ic, TRUE);
7030   freeAsmop (result, NULL, ic, TRUE);
7031   
7032   if (ifx && !ifx->generated)
7033     {
7034       genIfxJump (ifx, "a");
7035     }
7036 }
7037
7038
7039 /*-----------------------------------------------------------------*/
7040 /* genPointerGet - generate code for pointer get                   */
7041 /*-----------------------------------------------------------------*/
7042 static void
7043 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7044 {
7045   operand *left = IC_LEFT (ic);
7046   operand *result = IC_RESULT (ic);
7047   int size, offset;
7048   sym_link *retype = getSpec (operandType (result));
7049
7050   D(emitcode (";     genPointerGet",""));
7051
7052   if (getSize (operandType (result))>1)
7053     ifx = NULL;
7054   
7055   aopOp (left, ic, FALSE);
7056
7057   /* if left is rematerialisable and
7058      result is not bit variable type */
7059   if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7060     {
7061       if (!IS_BITVAR (retype))
7062         {
7063           genDataPointerGet (left, result, ic, ifx);
7064           return;
7065         }
7066       else
7067         {
7068           genUnpackBitsImmed (left, result, ic, ifx);
7069           return;
7070         }
7071     }
7072
7073   /* if the operand is already in hx
7074      then we do nothing else we move the value to hx */
7075   if (AOP_TYPE (left) != AOP_STR)
7076     {
7077       /* if this is remateriazable */
7078       loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7079     }
7080
7081   /* so hx now contains the address */
7082   aopOp (result, ic, FALSE);
7083
7084   /* if bit then unpack */
7085   if (IS_BITVAR (retype))
7086     genUnpackBits (result, ifx);
7087   else
7088     {
7089       size = AOP_SIZE (result);
7090       offset = size-1;
7091
7092       while (size--)
7093         {
7094           accopWithMisc ("lda", ",x");
7095           if (size || pi)
7096             {
7097               emitcode ("aix", "#1");
7098               hc08_dirtyReg (hc08_reg_hx, FALSE);
7099             }
7100           if (!ifx)
7101             storeRegToAop (hc08_reg_a, AOP (result), offset);
7102           offset--;
7103           hc08_freeReg (hc08_reg_a);
7104         }
7105     }
7106
7107   freeAsmop (left, NULL, ic, TRUE);
7108   freeAsmop (result, NULL, ic, TRUE);
7109   
7110   if (pi) {
7111     aopOp (IC_RESULT (pi), pi, FALSE);
7112     storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7113     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7114     pi->generated = 1;
7115   }
7116   
7117   if (ifx && !ifx->generated)
7118     {
7119       genIfxJump (ifx, "a");
7120     }
7121
7122   hc08_freeReg (hc08_reg_hx);
7123   
7124 }
7125
7126 /*-----------------------------------------------------------------*/
7127 /* genPackBits - generates code for packed bit storage             */
7128 /*-----------------------------------------------------------------*/
7129 static void
7130 genPackBits (sym_link * etype,
7131              operand * right)
7132 {
7133   int offset = 0;       /* source byte offset */
7134   int rlen = 0;         /* remaining bitfield length */
7135   int blen;             /* bitfield length */
7136   int bstr;             /* bitfield starting bit within byte */
7137   int litval;           /* source literal value (if AOP_LIT) */
7138   unsigned char mask;   /* bitmask within current byte */
7139   int xoffset = 0;
7140
7141   D(emitcode (";     genPackBits",""));
7142
7143   blen = SPEC_BLEN (etype);
7144   bstr = SPEC_BSTR (etype);
7145
7146   /* If the bitfield length is less than a byte */
7147   if (blen < 8)
7148     {
7149       mask = ((unsigned char) (0xFF << (blen + bstr)) |
7150               (unsigned char) (0xFF >> (8 - bstr)));
7151
7152       if (AOP_TYPE (right) == AOP_LIT)
7153         {
7154           /* Case with a bitfield length <8 and literal source
7155           */
7156           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7157           litval <<= bstr;
7158           litval &= (~mask) & 0xff;
7159
7160           emitcode ("lda", ",x");
7161           if ((mask|litval)!=0xff)
7162             emitcode ("and","#0x%02x", mask);
7163           if (litval)
7164             emitcode ("ora","#0x%02x", litval);
7165           hc08_dirtyReg (hc08_reg_a, FALSE);
7166           emitcode ("sta", ",x");
7167           
7168           hc08_freeReg (hc08_reg_a);
7169           return;
7170         }
7171           
7172       /* Case with a bitfield length < 8 and arbitrary source
7173       */
7174       loadRegFromAop (hc08_reg_a, AOP (right), 0);
7175       /* shift and mask source value */
7176       AccLsh (bstr);
7177       emitcode ("and", "#0x%02x", (~mask) & 0xff);
7178       hc08_dirtyReg (hc08_reg_a, FALSE);
7179       pushReg (hc08_reg_a, TRUE);
7180
7181       emitcode ("lda", ",x");
7182       emitcode ("and", "#0x%02x", mask);
7183       emitcode ("ora", "1,s");
7184       emitcode ("sta", ",x");
7185       pullReg (hc08_reg_a);
7186      
7187       hc08_freeReg (hc08_reg_a);
7188       return;
7189     }
7190
7191   /* Bit length is greater than 7 bits. In this case, copy  */
7192   /* all except the partial byte at the end                 */
7193   for (rlen=blen;rlen>=8;rlen-=8)
7194     {
7195       if (AOP (right)->type == AOP_DIR)
7196         {
7197           emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7198           xoffset++;
7199         }
7200       else
7201         {
7202           loadRegFromAop (hc08_reg_a, AOP (right), offset);
7203           emitcode ("sta", "%d,x", offset);
7204         }
7205       offset++;
7206     }
7207
7208   /* If there was a partial byte at the end */
7209   if (rlen)
7210     {
7211       mask = (((unsigned char) -1 << rlen) & 0xff);
7212       
7213       if (AOP_TYPE (right) == AOP_LIT)
7214         {
7215           /* Case with partial byte and literal source
7216           */
7217           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7218           litval >>= (blen-rlen);
7219           litval &= (~mask) & 0xff;
7220           emitcode ("lda", "%d,x", offset - xoffset);
7221           hc08_dirtyReg (hc08_reg_a, FALSE);
7222           if ((mask|litval)!=0xff)
7223             emitcode ("and","#0x%02x", mask);
7224           if (litval)
7225             emitcode ("ora","#0x%02x", litval);
7226           emitcode ("sta", "%d,x", offset - xoffset);
7227           hc08_dirtyReg (hc08_reg_a, FALSE);
7228           hc08_freeReg (hc08_reg_a);
7229           return;
7230         }
7231       
7232       /* Case with partial byte and arbitrary source
7233       */
7234       loadRegFromAop (hc08_reg_a, AOP (right), offset);
7235       emitcode ("and", "#0x%02x", (~mask) & 0xff);
7236       hc08_dirtyReg (hc08_reg_a, FALSE);
7237       pushReg (hc08_reg_a, TRUE);
7238
7239       emitcode ("lda", "%d,x", offset - xoffset);
7240       emitcode ("and", "#0x%02x", mask);
7241       emitcode ("ora", "1,s");
7242       emitcode ("sta", "%d,x", offset - xoffset);
7243       pullReg (hc08_reg_a);
7244     }
7245
7246   hc08_freeReg (hc08_reg_a);
7247 }
7248
7249 /*-----------------------------------------------------------------*/
7250 /* genPackBitsImmed - generates code for packed bit storage        */
7251 /*-----------------------------------------------------------------*/
7252 static void
7253 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7254 {
7255   asmop *derefaop;
7256   int size;
7257   int offset = 0;       /* source byte offset */
7258   int rlen = 0;         /* remaining bitfield length */
7259   int blen;             /* bitfield length */
7260   int bstr;             /* bitfield starting bit within byte */
7261   int litval;           /* source literal value (if AOP_LIT) */
7262   unsigned char mask;   /* bitmask within current byte */
7263
7264   D(emitcode (";     genPackBitsImmed",""));
7265
7266   blen = SPEC_BLEN (etype);
7267   bstr = SPEC_BSTR (etype);
7268
7269   aopOp (right, ic, FALSE);
7270   size = AOP_SIZE (right);
7271
7272   derefaop = aopDerefAop (AOP (result));
7273   freeAsmop (result, NULL, ic, TRUE);
7274   derefaop->size = size;
7275
7276   /* if the bitfield is a single bit in the direct page */
7277   if (blen == 1 && derefaop->type == AOP_DIR)
7278     {
7279       if (AOP_TYPE (right) == AOP_LIT)
7280         {
7281           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7282       
7283           emitcode ((litval & 1) ? "bset" : "bclr", 
7284                     "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7285         }
7286       else
7287         {
7288           symbol *tlbl1 = newiTempLabel (NULL);
7289           symbol *tlbl2 = newiTempLabel (NULL);
7290           
7291           loadRegFromAop (hc08_reg_a, AOP (right), 0);
7292           emitcode ("bit", "#1");
7293           emitBranch ("bne", tlbl1);
7294           emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7295           emitBranch ("bra", tlbl2);
7296           emitLabel (tlbl1);
7297           emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7298           emitLabel (tlbl2);
7299           hc08_freeReg (hc08_reg_a);
7300         }
7301       goto release;
7302     }
7303     
7304   /* If the bitfield length is less than a byte */
7305   if (blen < 8)
7306     {
7307       mask = ((unsigned char) (0xFF << (blen + bstr)) |
7308               (unsigned char) (0xFF >> (8 - bstr)));
7309
7310       if (AOP_TYPE (right) == AOP_LIT)
7311         {
7312           /* Case with a bitfield length <8 and literal source
7313           */
7314           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7315           litval <<= bstr;
7316           litval &= (~mask) & 0xff;
7317
7318           loadRegFromAop (hc08_reg_a, derefaop, 0);
7319           if ((mask|litval)!=0xff)
7320             emitcode ("and","#0x%02x", mask);
7321           if (litval)
7322             emitcode ("ora","#0x%02x", litval);
7323           hc08_dirtyReg (hc08_reg_a, FALSE);
7324           storeRegToAop (hc08_reg_a, derefaop, 0);
7325           
7326           hc08_freeReg (hc08_reg_a);
7327           goto release;
7328         }
7329           
7330       /* Case with a bitfield length < 8 and arbitrary source
7331       */
7332       loadRegFromAop (hc08_reg_a, AOP (right), 0);
7333       /* shift and mask source value */
7334       AccLsh (bstr);
7335       emitcode ("and", "#0x%02x", (~mask) & 0xff);
7336       hc08_dirtyReg (hc08_reg_a, FALSE);
7337       pushReg (hc08_reg_a, TRUE);
7338
7339       loadRegFromAop (hc08_reg_a, derefaop, 0);
7340       emitcode ("and", "#0x%02x", mask);
7341       emitcode ("ora", "1,s");
7342       storeRegToAop (hc08_reg_a, derefaop, 0);
7343       pullReg (hc08_reg_a);
7344      
7345       hc08_freeReg (hc08_reg_a);
7346       goto release;
7347     }
7348
7349   /* Bit length is greater than 7 bits. In this case, copy  */
7350   /* all except the partial byte at the end                 */
7351   for (rlen=blen;rlen>=8;rlen-=8)
7352     {
7353       transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7354       offset++;
7355     }
7356
7357   /* If there was a partial byte at the end */
7358   if (rlen)
7359     {
7360       mask = (((unsigned char) -1 << rlen) & 0xff);
7361       
7362       if (AOP_TYPE (right) == AOP_LIT)
7363         {
7364           /* Case with partial byte and literal source
7365           */
7366           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7367           litval >>= (blen-rlen);
7368           litval &= (~mask) & 0xff;
7369           loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7370           if ((mask|litval)!=0xff)
7371             emitcode ("and","#0x%02x", mask);
7372           if (litval)
7373             emitcode ("ora","#0x%02x", litval);
7374           hc08_dirtyReg (hc08_reg_a, FALSE);
7375           storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7376           hc08_dirtyReg (hc08_reg_a, FALSE);
7377           hc08_freeReg (hc08_reg_a);
7378           goto release;
7379         }
7380       
7381       /* Case with partial byte and arbitrary source
7382       */
7383       loadRegFromAop (hc08_reg_a, AOP (right), offset);
7384       emitcode ("and", "#0x%02x", (~mask) & 0xff);
7385       hc08_dirtyReg (hc08_reg_a, FALSE);
7386       pushReg (hc08_reg_a, TRUE);
7387
7388       loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7389       emitcode ("and", "#0x%02x", mask);
7390       emitcode ("ora", "1,s");
7391       storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7392       pullReg (hc08_reg_a);
7393     }
7394
7395   hc08_freeReg (hc08_reg_a);
7396
7397 release:  
7398   freeAsmop (right, NULL, ic, TRUE);
7399   freeAsmop (NULL, derefaop, ic, TRUE);
7400 }
7401
7402 /*-----------------------------------------------------------------*/
7403 /* genDataPointerSet - remat pointer to data space                 */
7404 /*-----------------------------------------------------------------*/
7405 static void
7406 genDataPointerSet (operand * right,
7407                    operand * result,
7408                    iCode * ic)
7409 {
7410   int size, offset = 0;
7411   asmop *derefaop;
7412
7413   D(emitcode (";     genDataPointerSet",""));
7414
7415   aopOp (right, ic, FALSE);
7416   size = AOP_SIZE (right);
7417
7418   derefaop = aopDerefAop (AOP (result));
7419   freeAsmop (result, NULL, ic, TRUE);
7420   derefaop->size = size;
7421   
7422   while (size--)
7423     {
7424       transferAopAop (AOP (right), offset, derefaop, offset);
7425       offset++;
7426     }
7427
7428   freeAsmop (right, NULL, ic, TRUE);
7429   freeAsmop (NULL, derefaop, ic, TRUE);
7430 }
7431
7432
7433 /*-----------------------------------------------------------------*/
7434 /* genPointerSet - stores the value into a pointer location        */
7435 /*-----------------------------------------------------------------*/
7436 static void
7437 genPointerSet (iCode * ic, iCode *pi)
7438 {
7439   operand *right = IC_RIGHT (ic);
7440   operand *result = IC_RESULT (ic);
7441   sym_link *type, *etype;
7442   int size, offset;
7443   sym_link *retype = getSpec (operandType (right));
7444   sym_link *letype = getSpec (operandType (result));
7445
7446   D(emitcode (";     genPointerSet",""));
7447
7448   type = operandType (result);
7449   etype = getSpec (type);
7450   
7451   aopOp (result, ic, FALSE);
7452
7453   /* if the result is rematerializable */
7454   if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7455     {
7456       if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7457         {
7458           genDataPointerSet (right, result, ic);
7459           return;
7460         }
7461       else
7462         {
7463           genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7464           return;
7465         }
7466     }
7467
7468   /* if the operand is already in hx
7469      then we do nothing else we move the value to hx */
7470   if (AOP_TYPE (result) != AOP_STR)
7471     {
7472       loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7473     }
7474   /* so hx now contains the address */
7475   aopOp (right, ic, FALSE);
7476
7477   /* if bit then unpack */
7478   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7479     genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7480   else
7481     {
7482       size = AOP_SIZE (right);
7483       offset = size-1;
7484
7485       while (size--)
7486         {
7487           loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7488           accopWithMisc ("sta", ",x");
7489           if (size || pi)
7490             {
7491               emitcode ("aix", "#1");
7492             }
7493           hc08_freeReg (hc08_reg_a);
7494         }
7495     }
7496
7497   freeAsmop (result, NULL, ic, TRUE);
7498   freeAsmop (right, NULL, ic, TRUE);
7499
7500   if (pi) {
7501     aopOp (IC_RESULT (pi), pi, FALSE);
7502     storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7503     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7504     pi->generated=1;
7505   }
7506
7507   hc08_freeReg (hc08_reg_hx);
7508
7509 }
7510
7511 /*-----------------------------------------------------------------*/
7512 /* genIfx - generate code for Ifx statement                        */
7513 /*-----------------------------------------------------------------*/
7514 static void
7515 genIfx (iCode * ic, iCode * popIc)
7516 {
7517   operand *cond = IC_COND (ic);
7518   int isbit = 0;
7519
7520   D(emitcode (";     genIfx",""));
7521
7522   aopOp (cond, ic, FALSE);
7523
7524   /* get the value into acc */
7525   if (AOP_TYPE (cond) != AOP_CRY)
7526     asmopToBool (AOP (cond), FALSE);
7527   else
7528     isbit = 1;
7529   /* the result is now in the accumulator */
7530   freeAsmop (cond, NULL, ic, TRUE);
7531
7532   /* if there was something to be popped then do it */
7533   if (popIc)
7534     genIpop (popIc);
7535
7536   /* if the condition is  a bit variable */
7537   if (isbit && IS_ITEMP (cond) &&
7538       SPIL_LOC (cond))
7539     genIfxJump (ic, SPIL_LOC (cond)->rname);
7540   else if (isbit && !IS_ITEMP (cond))
7541     genIfxJump (ic, OP_SYMBOL (cond)->rname);
7542   else
7543     genIfxJump (ic, "a");
7544
7545   ic->generated = 1;
7546 }
7547
7548 /*-----------------------------------------------------------------*/
7549 /* genAddrOf - generates code for address of                       */
7550 /*-----------------------------------------------------------------*/
7551 static void
7552 genAddrOf (iCode * ic)
7553 {
7554   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7555   int size, offset;
7556
7557   D(emitcode (";     genAddrOf",""));
7558
7559   aopOp (IC_RESULT (ic), ic, FALSE);
7560
7561   /* if the operand is on the stack then we
7562      need to get the stack offset of this
7563      variable */
7564   if (sym->onStack)
7565     {
7566       /* if it has an offset then we need to compute
7567          it */
7568       hc08_useReg (hc08_reg_hx);
7569       emitcode ("tsx", "");
7570       emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7571       storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7572       hc08_freeReg (hc08_reg_hx);
7573
7574       goto release;
7575     }
7576
7577   /* object not on stack then we need the name */
7578   size = AOP_SIZE (IC_RESULT (ic));
7579   offset = 0;
7580
7581   while (size--)
7582     {
7583       char s[SDCC_NAME_MAX+10];
7584       switch (offset) {
7585         case 0:
7586           sprintf (s, "#%s", sym->rname);
7587           break;
7588         case 1:
7589           sprintf (s, "#>%s", sym->rname);
7590           break;
7591         default:
7592           sprintf (s, "#(%s >> %d)",
7593                    sym->rname,
7594                    offset * 8);
7595       }
7596       storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7597     }
7598
7599 release:
7600   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7601
7602 }
7603
7604 /*-----------------------------------------------------------------*/
7605 /* genAssign - generate code for assignment                        */
7606 /*-----------------------------------------------------------------*/
7607 static void
7608 genAssign (iCode * ic)
7609 {
7610   operand *result, *right;
7611   int size, offset;
7612 //  unsigned long lit = 0L;
7613
7614   D(emitcode(";     genAssign",""));
7615
7616   result = IC_RESULT (ic);
7617   right = IC_RIGHT (ic);
7618
7619   /* if they are the same */
7620   if (operandsEqu (result, right)) {
7621     return;
7622   }
7623
7624   aopOp (right, ic, FALSE);
7625   aopOp (result, ic, TRUE);
7626
7627   /* if they are the same registers */
7628   if (sameRegs (AOP (right), AOP (result)))
7629     goto release;
7630
7631   if ((AOP_TYPE (right) == AOP_LIT)
7632       && (IS_AOP_HX(AOP(result))))
7633     {
7634       loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7635       goto release;
7636     }
7637     
7638   /* general case */
7639   size = AOP_SIZE (result);
7640   offset = 0;
7641
7642   while (size--)
7643     {
7644       transferAopAop (AOP (right), offset, AOP (result), offset);
7645       offset++;
7646     }
7647
7648 release:
7649   freeAsmop (right, NULL, ic, TRUE);
7650   freeAsmop (result, NULL, ic, TRUE);
7651 }
7652
7653 /*-----------------------------------------------------------------*/
7654 /* genJumpTab - genrates code for jump table                       */
7655 /*-----------------------------------------------------------------*/
7656 static void
7657 genJumpTab (iCode * ic)
7658 {
7659   symbol *jtab;
7660 //  char *l;
7661
7662   D(emitcode (";     genJumpTab",""));
7663
7664   aopOp (IC_JTCOND (ic), ic, FALSE);
7665   /* get the condition into accumulator */
7666   loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7667   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7668   /* multiply by three */
7669   pushReg (hc08_reg_a, FALSE);
7670   emitcode ("lsla", "");
7671   emitcode ("add","1,s");
7672   transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7673   loadRegFromConst (hc08_reg_h, zero);
7674   pullReg (hc08_reg_a);
7675
7676   jtab = newiTempLabel (NULL);
7677   emitcode ("jmp", "%05d$,x", jtab->key + 100);
7678   emitcode ("", "%05d$:", jtab->key + 100);
7679   /* now generate the jump labels */
7680   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7681        jtab = setNextItem (IC_JTLABELS (ic)))
7682     emitcode ("jmp", "%05d$", jtab->key + 100);
7683
7684   hc08_dirtyReg (hc08_reg_a, TRUE);
7685   hc08_dirtyReg (hc08_reg_hx, TRUE);
7686 }
7687
7688 /*-----------------------------------------------------------------*/
7689 /* genCast - gen code for casting                                  */
7690 /*-----------------------------------------------------------------*/
7691 static void
7692 genCast (iCode * ic)
7693 {
7694   operand *result = IC_RESULT (ic);
7695   sym_link *ctype = operandType (IC_LEFT (ic));
7696   sym_link *rtype = operandType (IC_RIGHT (ic));
7697   operand *right = IC_RIGHT (ic);
7698   int size, offset;
7699
7700   D(emitcode(";     genCast",""));
7701
7702   /* if they are equivalent then do nothing */
7703   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7704     return;
7705
7706   aopOp (right, ic, FALSE);
7707   aopOp (result, ic, FALSE);
7708
7709
7710   /* if they are the same size : or less */
7711   if (AOP_SIZE (result) <= AOP_SIZE (right))
7712     {
7713
7714       /* if they are in the same place */
7715       #if 0
7716       if (sameRegs (AOP (right), AOP (result)))
7717         goto release;
7718       #endif
7719
7720       /* if they in different places then copy */
7721       size = AOP_SIZE (result);
7722       offset = 0;
7723       while (size--)
7724         {
7725           transferAopAop(AOP (right), offset, AOP (result), offset);
7726           offset++;
7727         }
7728       goto release;
7729     }
7730
7731
7732   /* if the result is of type pointer */
7733   if (IS_PTR (ctype))
7734     {
7735
7736       int p_type;
7737       sym_link *type = operandType (right);
7738       sym_link *etype = getSpec (type);
7739
7740       /* pointer to generic pointer */
7741       if (IS_GENPTR (ctype))
7742         {
7743           if (IS_PTR (type))
7744             p_type = DCL_TYPE (type);
7745           else
7746             {
7747               if (SPEC_SCLS(etype)==S_REGISTER) {
7748                 // let's assume it is a generic pointer
7749                 p_type=GPOINTER;
7750               } else {
7751                 /* we have to go by the storage class */
7752                 p_type = PTR_TYPE (SPEC_OCLS (etype));
7753               }
7754             }
7755
7756           /* the first two bytes are known */
7757           size = GPTRSIZE - 1;
7758           offset = 0;
7759           while (size--)
7760             {
7761               transferAopAop(AOP (right), offset, AOP (result), offset);
7762               offset++;
7763             }
7764           /* the last byte depending on type */
7765 #if 0
7766             {
7767                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7768                 char gpValStr[10];
7769             
7770                 if (gpVal == -1)
7771                 {
7772                     // pointerTypeToGPByte will have bitched.
7773                     exit(1);
7774                 }
7775             
7776                 sprintf(gpValStr, "#0x%d", gpVal);
7777                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7778             }       
7779 #endif
7780           goto release;
7781         }
7782
7783       /* just copy the pointers */
7784       size = AOP_SIZE (result);
7785       offset = 0;
7786       while (size--)
7787         {
7788           transferAopAop(AOP (right), offset, AOP (result), offset);
7789           offset++;
7790         }
7791       goto release;
7792     }
7793
7794   /* so we now know that the size of destination is greater
7795      than the size of the source */
7796   /* we move to result for the size of source */
7797   size = AOP_SIZE (right);
7798   offset = 0;
7799   while (size--)
7800     {
7801       transferAopAop(AOP (right), offset, AOP (result), offset);
7802       offset++;
7803     }
7804
7805   /* now depending on the sign of the source && destination */
7806   size = AOP_SIZE (result) - AOP_SIZE (right);
7807   /* if unsigned or not an integral type */
7808   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7809     {
7810       while (size--)
7811         storeConstToAop (zero, AOP (result), offset++); 
7812     }
7813   else
7814     {
7815       /* we need to extend the sign :{ */
7816       loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7817       accopWithMisc ("rola", "");
7818       accopWithMisc ("clra", "");
7819       accopWithMisc ("sbc", zero);
7820       while (size--)
7821         storeRegToAop (hc08_reg_a, AOP (result), offset++);
7822     }
7823
7824   /* we are done hurray !!!! */
7825
7826 release:
7827   freeAsmop (right, NULL, ic, TRUE);
7828   freeAsmop (result, NULL, ic, TRUE);
7829
7830 }
7831
7832 /*-----------------------------------------------------------------*/
7833 /* genDjnz - generate decrement & jump if not zero instrucion      */
7834 /*-----------------------------------------------------------------*/
7835 static int
7836 genDjnz (iCode * ic, iCode * ifx)
7837 {
7838   symbol *lbl, *lbl1;
7839   if (!ifx)
7840     return 0;
7841
7842   D(emitcode (";     genDjnz",""));
7843
7844   /* if the if condition has a false label
7845      then we cannot save */
7846   if (IC_FALSE (ifx))
7847     return 0;
7848
7849   /* if the minus is not of the form
7850      a = a - 1 */
7851   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7852       !IS_OP_LITERAL (IC_RIGHT (ic)))
7853     return 0;
7854
7855   if (operandLitValue (IC_RIGHT (ic)) != 1)
7856     return 0;
7857
7858   /* dbnz doesn't support extended mode */
7859   if (isOperandInFarSpace (IC_RESULT (ic)))
7860     return 0;
7861
7862   /* if the size of this greater than one then no
7863      saving */
7864 //  if (getSize (operandType (IC_RESULT (ic))) > 1)
7865 //    return 0;
7866   aopOp (IC_RESULT (ic), ic, FALSE);
7867   if (AOP_SIZE (IC_RESULT (ic))>1)
7868     {
7869       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7870       return 0;
7871     }
7872
7873   /* otherwise we can save BIG */
7874   lbl = newiTempLabel (NULL);
7875   lbl1 = newiTempLabel (NULL);
7876
7877
7878   emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7879                 lbl->key + 100);
7880  
7881   emitBranch ("bra", lbl1);
7882   emitLabel (lbl);
7883   emitBranch ("jmp", IC_TRUE (ifx));
7884   emitLabel (lbl1);
7885
7886   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7887   ifx->generated = 1;
7888   return 1;
7889 }
7890
7891 /*-----------------------------------------------------------------*/
7892 /* genReceive - generate code for a receive iCode                  */
7893 /*-----------------------------------------------------------------*/
7894 static void
7895 genReceive (iCode * ic)
7896 {
7897   int size;
7898   int offset;
7899   D(emitcode (";     genReceive",""));
7900
7901   aopOp (IC_RESULT (ic), ic, FALSE);
7902   size = AOP_SIZE (IC_RESULT (ic));
7903   offset = 0;
7904   
7905   if (ic->argreg) {
7906       while (size--) {
7907           transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7908                           AOP (IC_RESULT (ic)), offset);
7909           if (hc08_aop_pass[offset]->type == AOP_REG)
7910             hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7911           offset++;
7912       }
7913   }       
7914
7915   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7916 }
7917
7918 /*-----------------------------------------------------------------*/
7919 /* genDummyRead - generate code for dummy read of volatiles        */
7920 /*-----------------------------------------------------------------*/
7921 static void
7922 genDummyRead (iCode * ic)
7923 {
7924   operand *op;
7925   int size, offset;
7926
7927   D(emitcode(";     genDummyRead",""));
7928
7929   op = IC_RIGHT (ic);
7930   if (op && IS_SYMOP (op))
7931     {
7932
7933       aopOp (op, ic, FALSE);
7934
7935       size = AOP_SIZE (op);
7936       offset = 0;
7937
7938       while (size--)
7939         {
7940           loadRegFromAop (hc08_reg_a, AOP (op), offset);
7941           hc08_freeReg (hc08_reg_a);
7942           offset++;
7943         }
7944
7945       freeAsmop (op, NULL, ic, TRUE);
7946    }
7947   op = IC_LEFT (ic);
7948   if (op && IS_SYMOP (op))
7949     {
7950
7951       aopOp (op, ic, FALSE);
7952
7953       size = AOP_SIZE (op);
7954       offset = 0;
7955
7956       while (size--)
7957         {
7958           loadRegFromAop (hc08_reg_a, AOP (op), offset);
7959           hc08_freeReg (hc08_reg_a);
7960           offset++;
7961         }
7962
7963       freeAsmop (op, NULL, ic, TRUE);
7964    }
7965 }
7966
7967 /*-----------------------------------------------------------------*/
7968 /* genCritical - generate code for start of a critical sequence    */
7969 /*-----------------------------------------------------------------*/
7970 static void
7971 genCritical (iCode *ic)
7972 {
7973   D(emitcode(";     genCritical",""));
7974   
7975   if (IC_RESULT (ic))
7976     aopOp (IC_RESULT (ic), ic, TRUE);
7977
7978   emitcode ("tpa", "");
7979   hc08_dirtyReg (hc08_reg_a, FALSE);
7980   emitcode ("sei", "");
7981
7982   if (IC_RESULT (ic))
7983     storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7984   else
7985     pushReg (hc08_reg_a, FALSE);
7986
7987   hc08_freeReg (hc08_reg_a);
7988   if (IC_RESULT (ic))
7989     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7990 }
7991
7992 /*-----------------------------------------------------------------*/
7993 /* genEndCritical - generate code for end of a critical sequence   */
7994 /*-----------------------------------------------------------------*/
7995 static void
7996 genEndCritical (iCode *ic)
7997 {
7998   D(emitcode(";     genEndCritical",""));
7999   
8000   if (IC_RIGHT (ic))
8001     {
8002       aopOp (IC_RIGHT (ic), ic, FALSE);
8003       loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8004       emitcode ("tap", "");
8005       hc08_freeReg (hc08_reg_a);
8006       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8007     }
8008   else
8009     {
8010       pullReg (hc08_reg_a);
8011       emitcode ("tap", "");
8012     }
8013 }
8014
8015
8016
8017 /*-----------------------------------------------------------------*/
8018 /* genhc08Code - generate code for HC08 based controllers          */
8019 /*-----------------------------------------------------------------*/
8020 void
8021 genhc08Code (iCode * lic)
8022 {
8023   iCode *ic;
8024   int cln = 0;
8025   int clevel = 0;
8026   int cblock = 0;
8027
8028   lineHead = lineCurr = NULL;
8029
8030   /* print the allocation information */
8031   if (allocInfo && currFunc)
8032     printAllocInfo (currFunc, codeOutFile);
8033   /* if debug information required */
8034   if (options.debug && currFunc)
8035     {
8036       debugFile->writeFunction (currFunc, lic);
8037       #if 0
8038       _G.debugLine = 1;
8039       if (IS_STATIC (currFunc->etype))
8040         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8041       else
8042         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8043       _G.debugLine = 0;
8044       #endif
8045     }
8046   /* stack pointer name */
8047   if (options.useXstack)
8048     spname = "_spx";
8049   else
8050     spname = "sp";
8051   
8052   debugFile->writeFrameAddress (NULL, NULL, 0);  /* have no idea where frame is now */
8053
8054   hc08_aop_pass[0] = newAsmop (AOP_REG);
8055   hc08_aop_pass[0]->size=1;
8056   hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8057   hc08_aop_pass[1] = newAsmop (AOP_REG);
8058   hc08_aop_pass[1]->size=1;
8059   hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8060   hc08_aop_pass[2] = newAsmop (AOP_DIR);
8061   hc08_aop_pass[2]->size=1;
8062   hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8063   hc08_aop_pass[3] = newAsmop (AOP_DIR);
8064   hc08_aop_pass[3]->size=1;
8065   hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8066
8067   for (ic = lic; ic; ic = ic->next)
8068     {
8069       
8070       _G.current_iCode = ic;
8071       
8072       if (ic->level != clevel || ic->block != cblock)
8073         {
8074           if (options.debug)
8075             {
8076               debugFile->writeScope(ic);
8077             }
8078           clevel = ic->level;
8079           cblock = ic->block;
8080         }
8081         
8082       if (ic->lineno && cln != ic->lineno)
8083         {
8084           if (options.debug)
8085             {
8086               debugFile->writeCLine(ic);
8087               #if 0
8088               _G.debugLine = 1;
8089               emitcode ("", "C$%s$%d$%d$%d ==.",
8090                         FileBaseName (ic->filename), ic->lineno,
8091                         ic->level, ic->block);
8092               _G.debugLine = 0;
8093               #endif
8094             }
8095           if (!options.noCcodeInAsm) {
8096             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, 
8097                       printCLine(ic->filename, ic->lineno));
8098           }
8099           cln = ic->lineno;
8100         }
8101       if (options.iCodeInAsm) {
8102         char regsInUse[80];
8103         int i;
8104
8105         for (i=0; i<6; i++) {
8106           sprintf (&regsInUse[i],
8107                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); 
8108         }
8109         regsInUse[i]=0;
8110         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8111       }
8112       /* if the result is marked as
8113          spilt and rematerializable or code for
8114          this has already been generated then
8115          do nothing */
8116       if (resultRemat (ic) || ic->generated)
8117         continue;
8118
8119       {
8120         int i;
8121         regs *reg;
8122         symbol *sym;
8123         
8124         for (i=A_IDX;i<=XA_IDX;i++)
8125           {
8126             reg = hc08_regWithIdx(i);
8127             if (reg->aop)
8128               emitcode("","; %s = %s offset %d", reg->name,
8129                        aopName(reg->aop), reg->aopofs);
8130             reg->isFree = TRUE;
8131           }
8132         if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8133           {
8134             sym = OP_SYMBOL (IC_LEFT (ic));
8135             if (sym->accuse == ACCUSE_HX)
8136               {
8137                 hc08_reg_h->isFree = FALSE;
8138                 hc08_reg_x->isFree = FALSE;
8139               }
8140             else if (sym->accuse == ACCUSE_XA)
8141               {
8142                 hc08_reg_a->isFree = FALSE;
8143                 if (sym->nRegs>1)
8144                   hc08_reg_x->isFree = FALSE;
8145               }
8146           }
8147         if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8148           {
8149             sym = OP_SYMBOL (IC_RIGHT (ic));
8150             if (sym->accuse == ACCUSE_HX)
8151               {
8152                 hc08_reg_h->isFree = FALSE;
8153                 hc08_reg_x->isFree = FALSE;
8154               }
8155             else if (sym->accuse == ACCUSE_XA)
8156               {
8157                 hc08_reg_a->isFree = FALSE;
8158                 if (sym->nRegs>1)
8159                   hc08_reg_x->isFree = FALSE;
8160               }
8161           }
8162       }
8163       
8164       /* depending on the operation */
8165       switch (ic->op)
8166         {
8167         case '!':
8168           genNot (ic);
8169           break;
8170
8171         case '~':
8172           genCpl (ic);
8173           break;
8174
8175         case UNARYMINUS:
8176           genUminus (ic);
8177           break;
8178
8179         case IPUSH:
8180           genIpush (ic);
8181           break;
8182
8183         case IPOP:
8184           /* IPOP happens only when trying to restore a
8185              spilt live range, if there is an ifx statement
8186              following this pop then the if statement might
8187              be using some of the registers being popped which
8188              would destory the contents of the register so
8189              we need to check for this condition and handle it */
8190           if (ic->next &&
8191               ic->next->op == IFX &&
8192               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8193             genIfx (ic->next, ic);
8194           else
8195             genIpop (ic);
8196           break;
8197
8198         case CALL:
8199           genCall (ic);
8200           break;
8201
8202         case PCALL:
8203           genPcall (ic);
8204           break;
8205
8206         case FUNCTION:
8207           genFunction (ic);
8208           break;
8209
8210         case ENDFUNCTION:
8211           genEndFunction (ic);
8212           break;
8213
8214         case RETURN:
8215           genRet (ic);
8216           break;
8217
8218         case LABEL:
8219           genLabel (ic);
8220           break;
8221
8222         case GOTO:
8223           genGoto (ic);
8224           break;
8225
8226         case '+':
8227           if (!genPointerGetSetOfs (ic))
8228             genPlus (ic);
8229           break;
8230
8231         case '-':
8232           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8233             genMinus (ic);
8234           break;
8235
8236         case '*':
8237           genMult (ic);
8238           break;
8239
8240         case '/':
8241           genDiv (ic);
8242           break;
8243
8244         case '%':
8245           genMod (ic);
8246           break;
8247
8248         case '>':
8249           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8250           break;
8251
8252         case '<':
8253           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8254           break;
8255
8256         case LE_OP:
8257         case GE_OP:
8258         case NE_OP:
8259
8260           /* note these two are xlated by algebraic equivalence
8261              during parsing SDCC.y */
8262           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8263                   "got '>=' or '<=' shouldn't have come here");
8264           break;
8265
8266         case EQ_OP:
8267           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8268           break;
8269
8270         case AND_OP:
8271           genAndOp (ic);
8272           break;
8273
8274         case OR_OP:
8275           genOrOp (ic);
8276           break;
8277
8278         case '^':
8279           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8280           break;
8281
8282         case '|':
8283           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8284           break;
8285
8286         case BITWISEAND:
8287           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8288           break;
8289
8290         case INLINEASM:
8291           genInline (ic);
8292           break;
8293
8294         case RRC:
8295           genRRC (ic);
8296           break;
8297
8298         case RLC:
8299           genRLC (ic);
8300           break;
8301
8302         case GETHBIT:
8303           genGetHbit (ic);
8304           break;
8305
8306         case LEFT_OP:
8307           genLeftShift (ic);
8308           break;
8309
8310         case RIGHT_OP:
8311           genRightShift (ic);
8312           break;
8313
8314         case GET_VALUE_AT_ADDRESS:
8315           genPointerGet (ic,
8316                          hasInc (IC_LEFT (ic), ic,
8317                                  getSize (operandType (IC_RESULT (ic)))),
8318                          ifxForOp (IC_RESULT (ic), ic) );
8319           break;
8320
8321         case '=':
8322           if (POINTER_SET (ic))
8323             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8324           else
8325             genAssign (ic);
8326           break;
8327
8328         case IFX:
8329           genIfx (ic, NULL);
8330           break;
8331
8332         case ADDRESS_OF:
8333           genAddrOf (ic);
8334           break;
8335
8336         case JUMPTABLE:
8337           genJumpTab (ic);
8338           break;
8339
8340         case CAST:
8341           genCast (ic);
8342           break;
8343
8344         case RECEIVE:
8345           genReceive (ic);
8346           break;
8347
8348         case SEND:
8349           addSet (&_G.sendSet, ic);
8350           break;
8351
8352         case DUMMY_READ_VOLATILE:
8353           genDummyRead (ic);
8354           break;
8355
8356         case CRITICAL:
8357           genCritical (ic);
8358           break;
8359
8360         case ENDCRITICAL:
8361           genEndCritical (ic);
8362           break;
8363         
8364         case SWAP:
8365           genSwap (ic);
8366           break;
8367
8368         default:
8369           ic = ic;
8370         }
8371
8372       if (!hc08_reg_a->isFree)
8373         D(emitcode("","; forgot to free a"));
8374       if (!hc08_reg_x->isFree)
8375         D(emitcode("","; forgot to free x"));
8376       if (!hc08_reg_h->isFree)
8377         D(emitcode("","; forgot to free h"));
8378       if (!hc08_reg_hx->isFree)
8379         D(emitcode("","; forgot to free hx"));
8380       if (!hc08_reg_xa->isFree)
8381         D(emitcode("","; forgot to free xa"));
8382     }
8383
8384   debugFile->writeFrameAddress (NULL, NULL, 0);  /* have no idea where frame is now */
8385     
8386
8387   /* now we are ready to call the
8388      peep hole optimizer */
8389   if (!options.nopeep)
8390     peepHole (&lineHead);
8391
8392   /* now do the actual printing */
8393   printLine (lineHead, codeOutFile);
8394   return;
8395 }