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