* src/hc08/gen.c (genPcall): fix for bug #1601032
[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   _G.stackPushes += 2; /* account for the bsr return address now on stack */
2739   updateCFA();
2740
2741   /* Push the function's address */
2742   aopOp (IC_LEFT (ic), ic, FALSE);
2743   pushSide (IC_LEFT (ic), FPTRSIZE);
2744   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2745
2746   /* if send set is not empty the assign */
2747   if (_G.sendSet)
2748     {
2749         genSend(reverseSet(_G.sendSet));
2750         _G.sendSet = NULL;
2751     }
2752
2753
2754   /* make the call */
2755   emitcode ("rts", "");
2756
2757   emitLabel (rlbl);
2758   _G.stackPushes -= 4; /* account for rts here & in called function */
2759   updateCFA();
2760
2761
2762   /* if we need assign a result value */
2763   if ((IS_ITEMP (IC_RESULT (ic)) &&
2764        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2765         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2766       IS_TRUE_SYMOP (IC_RESULT (ic)))
2767     {
2768
2769       _G.accInUse++;
2770       aopOp (IC_RESULT (ic), ic, FALSE);
2771       _G.accInUse--;
2772
2773       assignResultValue (IC_RESULT (ic));
2774
2775       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2776     }
2777
2778   /* adjust the stack for parameters if
2779      required */
2780   if (ic->parmBytes)
2781     {
2782       pullNull (ic->parmBytes);
2783     }
2784
2785   /* if we hade saved some registers then
2786      unsave them */
2787   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2788     unsaveRegisters (ic);
2789 }
2790
2791 /*-----------------------------------------------------------------*/
2792 /* resultRemat - result  is rematerializable                       */
2793 /*-----------------------------------------------------------------*/
2794 static int
2795 resultRemat (iCode * ic)
2796 {
2797   if (SKIP_IC (ic) || ic->op == IFX)
2798     return 0;
2799
2800   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2801     {
2802       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2803       if (sym->remat && !POINTER_SET (ic))
2804         return 1;
2805     }
2806
2807   return 0;
2808 }
2809
2810 #if defined(__BORLANDC__) || defined(_MSC_VER)
2811 #define STRCASECMP stricmp
2812 #else
2813 #define STRCASECMP strcasecmp
2814 #endif
2815
2816 /*-----------------------------------------------------------------*/
2817 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2818 /*-----------------------------------------------------------------*/
2819 static int
2820 regsCmp(void *p1, void *p2)
2821 {
2822   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2823 }
2824
2825 static bool
2826 inExcludeList (char *s)
2827 {
2828   const char *p = setFirstItem(options.excludeRegsSet);
2829
2830   if (p == NULL || STRCASECMP(p, "none") == 0)
2831     return FALSE;
2832
2833
2834   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2835 }
2836
2837 /*-----------------------------------------------------------------*/
2838 /* genFunction - generated code for function entry                 */
2839 /*-----------------------------------------------------------------*/
2840 static void
2841 genFunction (iCode * ic)
2842 {
2843   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2844   sym_link *ftype;
2845   iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2846   int stackAdjust = sym->stack;
2847   int accIsFree = sym->recvSize == 0;
2848
2849   _G.nRegsSaved = 0;
2850   _G.stackPushes = 0;
2851   /* create the function header */
2852   emitcode (";", "-----------------------------------------");
2853   emitcode (";", " function %s", sym->name);
2854   emitcode (";", "-----------------------------------------");
2855
2856   emitcode ("", "%s:", sym->rname);
2857   ftype = operandType (IC_LEFT (ic));
2858   
2859   _G.stackOfs = 0;
2860   _G.stackPushes = 0;
2861   debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2862
2863   if (IFFUNC_ISNAKED(ftype))
2864   {
2865       emitcode(";", "naked function: no prologue.");
2866       return;
2867   }
2868
2869   /* if this is an interrupt service routine then
2870      save h  */
2871   if (IFFUNC_ISISR (sym->type))
2872     {
2873
2874       if (!inExcludeList ("h"))
2875         pushReg (hc08_reg_h, FALSE);
2876     }
2877
2878   /* For some cases it is worthwhile to perform a RECEIVE iCode */
2879   /* before setting up the stack frame completely. */
2880   while (ric && ric->next && ric->next->op == RECEIVE)
2881     ric = ric->next;
2882   while (ric && IC_RESULT (ric))
2883     {
2884       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2885       int rsymSize = rsym ? getSize(rsym->type) : 0;
2886
2887       if (rsym->isitmp)
2888         {
2889           if (rsym && rsym->regType == REG_CND)
2890             rsym = NULL;
2891           if (rsym && (rsym->accuse || rsym->ruonly))
2892             rsym = NULL;
2893           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2894             rsym = rsym->usl.spillLoc;
2895         }
2896
2897       /* If the RECEIVE operand immediately spills to the first entry on the  */
2898       /* stack, we can push it directly rather than use an sp relative store. */
2899       if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2900         {
2901           int ofs;
2902
2903           _G.current_iCode = ric;
2904           D(emitcode (";     genReceive",""));
2905           for (ofs=0; ofs < rsymSize; ofs++)
2906             {
2907               regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2908               pushReg (reg, TRUE);
2909               if (reg->rIdx == A_IDX)
2910                 accIsFree = 1;
2911               stackAdjust--;
2912             }
2913           _G.current_iCode = ic;
2914           ric->generated = 1;
2915         }
2916       ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2917     }
2918
2919   /* adjust the stack for the function */
2920   if (stackAdjust)
2921     {
2922       adjustStack (-stackAdjust);
2923     }
2924   _G.stackOfs = sym->stack;
2925   _G.stackPushes = 0;
2926   
2927   /* if critical function then turn interrupts off */
2928   if (IFFUNC_ISCRITICAL (ftype))
2929     {
2930       if (!accIsFree)
2931         {
2932           /* Function was passed parameters, so make sure A is preserved */
2933           pushReg (hc08_reg_a, FALSE);
2934           pushReg (hc08_reg_a, FALSE);
2935           emitcode ("tpa", "");
2936           emitcode ("sta", "2,s");
2937           emitcode ("sei", "");
2938           pullReg (hc08_reg_a);
2939         }
2940       else
2941         {
2942           /* No passed parameters, so A can be freely modified */
2943           emitcode ("tpa", "");
2944           pushReg (hc08_reg_a, TRUE);
2945           emitcode ("sei", "");
2946         }
2947     }
2948
2949 }
2950
2951 /*-----------------------------------------------------------------*/
2952 /* genEndFunction - generates epilogue for functions               */
2953 /*-----------------------------------------------------------------*/
2954 static void
2955 genEndFunction (iCode * ic)
2956 {
2957   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2958
2959   if (IFFUNC_ISNAKED(sym->type))
2960   {
2961       emitcode(";", "naked function: no epilogue.");
2962       if (options.debug && currFunc)
2963         debugFile->writeEndFunction (currFunc, ic, 0);
2964       return;
2965   }
2966
2967   if (IFFUNC_ISCRITICAL (sym->type))
2968     {
2969       if (!IS_VOID(sym->type->next))
2970         {
2971           /* Function has return value, so make sure A is preserved */
2972           pushReg (hc08_reg_a, FALSE);
2973           emitcode ("lda", "2,s");
2974           emitcode ("tap", "");
2975           pullReg (hc08_reg_a);
2976           pullNull (1);
2977         }
2978       else
2979         {
2980           /* Function returns void, so A can be freely modified */
2981           pullReg (hc08_reg_a);
2982           emitcode ("tap", "");
2983         }
2984     }
2985
2986   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2987     {
2988     }
2989
2990   if (sym->stack)
2991     {
2992       _G.stackPushes += sym->stack;
2993       adjustStack (sym->stack);
2994     }
2995
2996
2997   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2998     {
2999     }
3000
3001   if (IFFUNC_ISISR (sym->type))
3002     {
3003
3004       if (!inExcludeList ("h"))
3005         pullReg (hc08_reg_h);
3006
3007
3008       /* if debug then send end of function */
3009       if (options.debug && currFunc)
3010         {
3011           debugFile->writeEndFunction (currFunc, ic, 1);
3012         }
3013
3014       emitcode ("rti", "");
3015     }
3016   else
3017     {
3018       if (IFFUNC_CALLEESAVES(sym->type))
3019         {
3020           int i;
3021
3022           /* if any registers used */
3023           if (sym->regsUsed)
3024             {
3025               /* save the registers used */
3026               for (i = sym->regsUsed->size; i >= 0; i--)
3027                 {
3028                   if (bitVectBitValue (sym->regsUsed, i) ||
3029                       (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3030                     emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3031                 }
3032             }
3033
3034         }
3035
3036       /* if debug then send end of function */
3037       if (options.debug && currFunc)
3038         {
3039           debugFile->writeEndFunction (currFunc, ic, 1);
3040         }
3041
3042       emitcode ("rts", "");
3043     }
3044
3045 }
3046
3047 /*-----------------------------------------------------------------*/
3048 /* genRet - generate code for return statement                     */
3049 /*-----------------------------------------------------------------*/
3050 static void
3051 genRet (iCode * ic)
3052 {
3053   int size, offset = 0;
3054 //  int pushed = 0;
3055
3056   D(emitcode (";     genRet",""));
3057
3058   /* if we have no return value then
3059      just generate the "ret" */
3060   if (!IC_LEFT (ic))
3061     goto jumpret;
3062
3063   /* we have something to return then
3064      move the return value into place */
3065   aopOp (IC_LEFT (ic), ic, FALSE);
3066   size = AOP_SIZE (IC_LEFT (ic));
3067
3068 #if 1
3069    offset = size - 1;
3070    while (size--)
3071      {
3072        transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3073        offset--;
3074      }
3075 #else
3076   switch (size)
3077     {
3078       case 4:
3079         /* 4 byte return: store value in the global return variable */
3080         offset = size-1;
3081         while (size--)
3082           {
3083             loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3084             STA (fReturn2[offset--], FALSE);
3085             hc08_freeReg (hc08_reg_a);
3086           }
3087         break;
3088       case 2:
3089         /* 2 byte return: store value in x:a */
3090         loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3091         hc08_freeReg (hc08_reg_xa);
3092         break;
3093       case 1:
3094         /* 1 byte return: store value in a */
3095         loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3096         hc08_freeReg (hc08_reg_a);
3097         break;
3098     }
3099 #endif
3100
3101   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3102
3103 jumpret:
3104   /* generate a jump to the return label
3105      if the next is not the return statement */
3106   if (!(ic->next && ic->next->op == LABEL &&
3107         IC_LABEL (ic->next) == returnLabel))
3108
3109     emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3110
3111 }
3112
3113 /*-----------------------------------------------------------------*/
3114 /* genLabel - generates a label                                    */
3115 /*-----------------------------------------------------------------*/
3116 static void
3117 genLabel (iCode * ic)
3118 {
3119   int i;
3120   regs *reg;
3121   
3122   /* For the high level labels we cannot depend on any */
3123   /* register's contents. Amnesia time.                */
3124   for (i=A_IDX;i<=XA_IDX;i++)
3125     {
3126       reg = hc08_regWithIdx(i);
3127       if (reg)
3128         reg->aop = NULL;
3129     }
3130
3131   /* special case never generate */
3132   if (IC_LABEL (ic) == entryLabel)
3133     return;
3134           
3135   debugFile->writeLabel(IC_LABEL (ic), ic);
3136
3137   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3138
3139 }
3140
3141 /*-----------------------------------------------------------------*/
3142 /* genGoto - generates a jmp                                      */
3143 /*-----------------------------------------------------------------*/
3144 static void
3145 genGoto (iCode * ic)
3146 {
3147   emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3148 }
3149
3150 #if 0
3151 /*-----------------------------------------------------------------*/
3152 /* findLabelBackwards: walks back through the iCode chain looking  */
3153 /* for the given label. Returns number of iCode instructions     */
3154 /* between that label and given ic.          */
3155 /* Returns zero if label not found.          */
3156 /*-----------------------------------------------------------------*/
3157 static int
3158 findLabelBackwards (iCode * ic, int key)
3159 {
3160   int count = 0;
3161
3162   while (ic->prev)
3163     {
3164       ic = ic->prev;
3165       count++;
3166
3167       /* If we have any pushes or pops, we cannot predict the distance.
3168          I don't like this at all, this should be dealt with in the 
3169          back-end */
3170       if (ic->op == IPUSH || ic->op == IPOP) {
3171         return 0;
3172       }
3173
3174       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3175         {
3176           return count;
3177         }
3178     }
3179
3180   return 0;
3181 }
3182 #endif
3183
3184 /*-----------------------------------------------------------------*/
3185 /* genPlusIncr :- does addition with increment if possible         */
3186 /*-----------------------------------------------------------------*/
3187 static bool
3188 genPlusIncr (iCode * ic)
3189 {
3190   int icount;
3191   operand *left;
3192   operand *result;
3193   bool needpulx;
3194   bool needpulh;
3195   bool needpula;
3196   unsigned int size = getDataSize (IC_RESULT (ic));
3197   unsigned int offset;
3198   symbol *tlbl = NULL;
3199   
3200   left = IC_LEFT (ic);
3201   result = IC_RESULT (ic);
3202
3203   /* will try to generate an increment */
3204   /* if the right side is not a literal
3205      we cannot */
3206   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3207     return FALSE;
3208
3209   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3210
3211   D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3212   
3213   if ((IS_AOP_HX (AOP (left)) ||
3214        ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3215       )
3216       && (icount>=-128) && (icount<=127) && (size==2))
3217     {
3218       if (!IS_AOP_HX (AOP (left)))
3219         {
3220           needpulx = pushRegIfUsed (hc08_reg_x);
3221           needpulh = pushRegIfUsed (hc08_reg_h);
3222         }
3223       else
3224         {
3225           needpulx = FALSE;
3226           needpulh = FALSE;
3227         }
3228       loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3229       emitcode ("aix","#%d", icount);
3230       hc08_dirtyReg (hc08_reg_hx, FALSE);
3231       storeRegToAop (hc08_reg_hx, AOP(result), 0);
3232       pullOrFreeReg (hc08_reg_h, needpulh);
3233       pullOrFreeReg (hc08_reg_x, needpulx);
3234       return TRUE;
3235     }
3236
3237   D(emitcode ("", "; icount = %d, sameRegs=%d", icount, 
3238             sameRegs (AOP (left), AOP (result))));
3239   
3240   if ((icount > 255) || (icount<0))
3241     return FALSE;
3242
3243   if (!sameRegs (AOP (left), AOP (result)))
3244     return FALSE;
3245
3246   D(emitcode (";     genPlusIncr",""));
3247
3248   if (size>1)
3249     tlbl = newiTempLabel (NULL);
3250
3251   if (icount==1)
3252     {
3253       needpula = FALSE;
3254       rmwWithAop ("inc", AOP (result), 0);
3255       if (1<size)
3256         emitBranch ("bne", tlbl);
3257     }
3258   else
3259     {
3260       if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3261         needpula = pushRegIfUsed (hc08_reg_a);
3262       else
3263         needpula = FALSE;
3264       loadRegFromAop (hc08_reg_a, AOP (result), 0);
3265       accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3266       hc08_useReg (hc08_reg_a);
3267       storeRegToAop (hc08_reg_a, AOP (result), 0);
3268       hc08_freeReg (hc08_reg_a);
3269       if (1<size)
3270         emitBranch ("bcc", tlbl);
3271     }
3272   for (offset=1; offset<size; offset++)
3273     {
3274       rmwWithAop ("inc", AOP (result), offset);
3275       if ((offset+1)<size)
3276         emitBranch ("bne", tlbl);
3277     }
3278
3279   if (size>1)
3280     emitLabel (tlbl);
3281   
3282   pullOrFreeReg (hc08_reg_a, needpula);
3283       
3284   return TRUE;
3285 }
3286
3287
3288
3289 /*-----------------------------------------------------------------*/
3290 /* genPlus - generates code for addition                           */
3291 /*-----------------------------------------------------------------*/
3292 static void
3293 genPlus (iCode * ic)
3294 {
3295   int size, offset = 0;
3296   char *add;
3297   asmop *leftOp, *rightOp;
3298
3299   /* special cases :- */
3300
3301   D(emitcode (";     genPlus",""));
3302
3303   aopOp (IC_LEFT (ic), ic, FALSE);
3304   aopOp (IC_RIGHT (ic), ic, FALSE);
3305   aopOp (IC_RESULT (ic), ic, TRUE);
3306
3307   /* we want registers on the left and literals on the right */
3308   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3309       (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3310     {
3311       operand *t = IC_RIGHT (ic);
3312       IC_RIGHT (ic) = IC_LEFT (ic);
3313       IC_LEFT (ic) = t;
3314     }
3315
3316
3317   /* if I can do an increment instead
3318      of add then GOOD for ME */
3319   if (genPlusIncr (ic) == TRUE)
3320     goto release;
3321
3322   D(emitcode("",";  left size = %d", getDataSize (IC_LEFT(ic))));
3323   D(emitcode("",";  right size = %d", getDataSize (IC_RIGHT(ic))));
3324   D(emitcode("",";  result size = %d", getDataSize (IC_RESULT(ic))));
3325   
3326   size = getDataSize (IC_RESULT (ic));
3327
3328   leftOp = AOP(IC_LEFT(ic));
3329   rightOp = AOP(IC_RIGHT(ic));
3330   add = "add";
3331
3332   offset = 0;
3333   while (size--)
3334     {
3335       loadRegFromAop (hc08_reg_a, leftOp, offset);
3336       accopWithAop(add, rightOp, offset);
3337       storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3338       hc08_freeReg (hc08_reg_a);
3339       add = "adc";  /* further adds must propagate carry */
3340     }
3341
3342
3343 //  adjustArithmeticResult (ic);
3344
3345 release:
3346   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3347   freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3348   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3349 }
3350
3351 /*-----------------------------------------------------------------*/
3352 /* genMinusDec :- does subtraction with decrement if possible      */
3353 /*-----------------------------------------------------------------*/
3354 static bool
3355 genMinusDec (iCode * ic)
3356 {
3357   unsigned int icount;
3358   operand *left;
3359   operand *result;
3360   bool needpulx;
3361   bool needpulh;
3362   unsigned int size = getDataSize (IC_RESULT (ic));
3363 //  int offset;
3364 //  symbol *tlbl;
3365   
3366   left = IC_LEFT (ic);
3367   result = IC_RESULT (ic);
3368
3369   /* will try to generate an increment */
3370   /* if the right side is not a literal
3371      we cannot */
3372   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3373     return FALSE;
3374
3375   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3376
3377   if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3378       && (icount>=-127) && (icount<=128) && (size==2))
3379     {
3380       if (!IS_AOP_HX (AOP (left)))
3381         {
3382           needpulx = pushRegIfUsed (hc08_reg_x);
3383           needpulh = pushRegIfUsed (hc08_reg_h);
3384         }
3385       else
3386         {
3387           needpulx = FALSE;
3388           needpulh = FALSE;
3389         }
3390       loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3391       emitcode ("aix","#%d", -icount);
3392       hc08_dirtyReg (hc08_reg_hx, FALSE);
3393       storeRegToAop (hc08_reg_hx, AOP(result), 0);
3394       pullOrFreeReg (hc08_reg_h, needpulh);
3395       pullOrFreeReg (hc08_reg_x, needpulx);
3396       return TRUE;
3397     }
3398   
3399   if ((icount > 1) || (icount<0))
3400     return FALSE;
3401
3402   if (!sameRegs (AOP (left), AOP (result)))
3403     return FALSE;
3404
3405   if (size!=1)
3406     return FALSE;
3407
3408   D(emitcode (";     genMinusDec",""));
3409
3410   rmwWithAop ("dec", AOP (result), 0);
3411   
3412   return TRUE;
3413 }
3414
3415 /*-----------------------------------------------------------------*/
3416 /* addSign - complete with sign                                    */
3417 /*-----------------------------------------------------------------*/
3418 static void
3419 addSign (operand * result, int offset, int sign)
3420 {
3421   int size = (getDataSize (result) - offset);
3422   if (size > 0)
3423     {
3424       if (sign)
3425         {
3426           emitcode ("rola", "");
3427           emitcode ("clra", "");
3428           emitcode ("sbc", zero);
3429           while (size--)
3430             storeRegToAop (hc08_reg_a, AOP (result), offset++);
3431         }
3432       else
3433         while (size--)
3434           storeConstToAop (zero, AOP (result), offset++);
3435     }
3436 }
3437
3438
3439 /*-----------------------------------------------------------------*/
3440 /* genMinus - generates code for subtraction                       */
3441 /*-----------------------------------------------------------------*/
3442 static void
3443 genMinus (iCode * ic)
3444 {
3445   char *sub;
3446   int size, offset = 0;
3447   
3448   asmop *leftOp, *rightOp;
3449
3450   D(emitcode (";     genMinus",""));
3451
3452   aopOp (IC_LEFT (ic), ic, FALSE);
3453   aopOp (IC_RIGHT (ic), ic, FALSE);
3454   aopOp (IC_RESULT (ic), ic, TRUE);
3455
3456   /* special cases :- */
3457   /* if I can do an decrement instead
3458      of subtract then GOOD for ME */
3459   if (genMinusDec (ic) == TRUE)
3460     goto release;
3461
3462   size = getDataSize (IC_RESULT (ic));
3463
3464
3465   leftOp = AOP(IC_LEFT(ic));
3466   rightOp = AOP(IC_RIGHT(ic));
3467   sub = "sub";
3468   offset = 0;
3469
3470   if (IS_AOP_A (rightOp))
3471     {
3472       loadRegFromAop ( hc08_reg_a, rightOp, offset);
3473       accopWithAop (sub, leftOp, offset);
3474       accopWithMisc ("nega", "");
3475       storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3476       goto release;
3477     }
3478
3479   while (size--)
3480     {
3481       loadRegFromAop ( hc08_reg_a, leftOp, offset);
3482       accopWithAop (sub, rightOp, offset);
3483       storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3484       sub = "sbc";
3485     }
3486   
3487   
3488 //  adjustArithmeticResult (ic);
3489
3490 release:
3491   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3492   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3493   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3494 }
3495
3496
3497
3498 /*-----------------------------------------------------------------*/
3499 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3500 /*-----------------------------------------------------------------*/
3501 static void
3502 genMultOneByte (operand * left,
3503                 operand * right,
3504                 operand * result)
3505 {
3506   /* sym_link *opetype = operandType (result); */
3507   symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3508   int size=AOP_SIZE(result);
3509   bool negLiteral = FALSE;
3510   bool lUnsigned, rUnsigned;
3511
3512   D(emitcode (";     genMultOneByte",""));
3513
3514   if (size<1 || size>2) {
3515     // this should never happen
3516       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3517                AOP_SIZE(result), __FILE__, lineno);
3518       exit (1);
3519   }
3520
3521   /* (if two literals: the value is computed before) */
3522   /* if one literal, literal on the right */
3523   if (AOP_TYPE (left) == AOP_LIT)
3524     {
3525       operand *t = right;
3526       right = left;
3527       left = t;
3528     }
3529   /* if an operand is in A, make sure it is on the left */
3530   if (IS_AOP_A (AOP (right)))
3531     {
3532       operand *t = right;
3533       right = left;
3534       left = t;
3535     }
3536
3537   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3538   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3539   
3540   /* lUnsigned  rUnsigned  negLiteral  negate     case */
3541   /* false      false      false       odd        3    */
3542   /* false      false      true        even       3    */
3543   /* false      true       false       odd        3    */
3544   /* false      true       true        impossible      */
3545   /* true       false      false       odd        3    */
3546   /* true       false      true        always     2    */
3547   /* true       true       false       never      1    */
3548   /* true       true       true        impossible      */
3549
3550   /* case 1 */
3551   if (size == 1
3552       || (lUnsigned && rUnsigned))
3553     {
3554       // just an unsigned 8*8=8/16 multiply
3555       //D(emitcode (";","unsigned"));
3556
3557       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3558       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3559       emitcode ("mul", "");
3560       hc08_dirtyReg (hc08_reg_xa, FALSE);
3561       storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3562       hc08_freeReg (hc08_reg_xa);
3563       
3564       return;
3565     }
3566
3567   // we have to do a signed multiply
3568
3569   /* case 2 */
3570   /* left unsigned, right signed literal -- literal determines sign handling */
3571   if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3572     {
3573       signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3574       
3575       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3576       if (val < 0)
3577         emitcode ("ldx", "#0x%02x", -val);
3578       else
3579         emitcode ("ldx", "#0x%02x", val);
3580           
3581       emitcode ("mul", "");
3582           
3583       if (val < 0)
3584         {
3585           rmwWithReg ("neg", hc08_reg_a);
3586           tlbl4 = newiTempLabel (NULL);
3587           emitBranch ("bcc", tlbl4);
3588           rmwWithReg ("inc", hc08_reg_x);
3589           emitLabel (tlbl4);
3590           rmwWithReg ("neg", hc08_reg_x);
3591         }
3592       
3593       hc08_dirtyReg (hc08_reg_xa, FALSE);
3594       storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3595       hc08_freeReg (hc08_reg_xa);
3596       return;
3597     }
3598   
3599
3600   /* case 3 */
3601   adjustStack (-1);
3602   emitcode ("clr", "1,s");
3603
3604   loadRegFromAop (hc08_reg_a, AOP (left), 0);
3605   if (!lUnsigned)
3606     {
3607       tlbl1 = newiTempLabel (NULL);
3608       emitcode ("tsta","");
3609       emitBranch ("bpl", tlbl1);
3610       emitcode ("inc", "1,s");
3611       rmwWithReg ("neg", hc08_reg_a);
3612       emitLabel (tlbl1);
3613     }
3614
3615   if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3616     {
3617       signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3618       /* AND literal negative */
3619       if (val < 0) {
3620         emitcode ("ldx", "#0x%02x", -val);
3621         negLiteral = TRUE;
3622       } else {
3623         emitcode ("ldx", "#0x%02x", val);
3624       }
3625       hc08_useReg (hc08_reg_x);
3626     }
3627   else
3628     {
3629       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3630       if (!rUnsigned)
3631         {
3632           tlbl2 = newiTempLabel (NULL);
3633           emitcode ("tstx", "");
3634           emitBranch ("bpl", tlbl2);
3635           emitcode ("inc", "1,s");
3636           rmwWithReg ("neg", hc08_reg_x);
3637           emitLabel (tlbl2);
3638         }
3639     }
3640
3641   emitcode ("mul", "");
3642   hc08_dirtyReg (hc08_reg_xa, FALSE);
3643
3644   tlbl3 = newiTempLabel (NULL);
3645   emitcode ("dec", "1,s");
3646   if (!lUnsigned && !rUnsigned && negLiteral)
3647     emitBranch ("beq", tlbl3);
3648   else
3649     emitBranch ("bne", tlbl3);
3650
3651   rmwWithReg ("neg", hc08_reg_a);
3652   tlbl4 = newiTempLabel (NULL);
3653   emitBranch ("bcc", tlbl4);
3654   rmwWithReg ("inc", hc08_reg_x);
3655   emitLabel (tlbl4);
3656   rmwWithReg ("neg", hc08_reg_x);
3657
3658   emitLabel (tlbl3);
3659   adjustStack (1);
3660   storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3661   hc08_freeReg (hc08_reg_xa);
3662
3663 }
3664
3665 /*-----------------------------------------------------------------*/
3666 /* genMult - generates code for multiplication                     */
3667 /*-----------------------------------------------------------------*/
3668 static void
3669 genMult (iCode * ic)
3670 {
3671   operand *left = IC_LEFT (ic);
3672   operand *right = IC_RIGHT (ic);
3673   operand *result = IC_RESULT (ic);
3674
3675   D(emitcode (";     genMult",""));
3676
3677   /* assign the amsops */
3678   aopOp (left, ic, FALSE);
3679   aopOp (right, ic, FALSE);
3680   aopOp (result, ic, TRUE);
3681
3682   /* special cases first */
3683   /* if both are of size == 1 */
3684 //  if (getSize(operandType(left)) == 1 && 
3685 //      getSize(operandType(right)) == 1)
3686   if (AOP_SIZE (left) == 1 && 
3687       AOP_SIZE (right) == 1)
3688     {
3689       genMultOneByte (left, right, result);
3690       goto release;
3691     }
3692
3693   /* should have been converted to function call */
3694     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3695              getSize(OP_SYMBOL(right)->type));
3696     fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3697              AOP_SIZE (right));
3698   assert (0);
3699
3700 release:
3701   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3702   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3703   freeAsmop (result, NULL, ic, TRUE);
3704 }
3705
3706 /*-----------------------------------------------------------------*/
3707 /* genDivOneByte : 8 bit division                                  */
3708 /*-----------------------------------------------------------------*/
3709 static void
3710 genDivOneByte (operand * left,
3711                operand * right,
3712                operand * result)
3713 {
3714   symbol *tlbl1, *tlbl2, *tlbl3;
3715   int size;
3716   int offset = 0;
3717   bool lUnsigned, rUnsigned;
3718   bool runtimeSign, compiletimeSign;
3719   
3720   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3721   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3722
3723   D(emitcode (";     genDivOneByte",""));
3724
3725   size = AOP_SIZE (result);
3726   /* signed or unsigned */
3727   if (lUnsigned && rUnsigned)
3728     {
3729       /* unsigned is easy */
3730       loadRegFromAop (hc08_reg_h, AOP (left), 1);
3731       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3732       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3733       emitcode ("div", "");
3734       hc08_dirtyReg (hc08_reg_a, FALSE);
3735       hc08_dirtyReg (hc08_reg_h, FALSE);
3736       storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3737       hc08_freeReg (hc08_reg_a);
3738       hc08_freeReg (hc08_reg_x);
3739       hc08_freeReg (hc08_reg_h);
3740       return;
3741     }
3742
3743   /* signed is a little bit more difficult */
3744
3745   /* now sign adjust for both left & right */
3746
3747   /* let's see what's needed: */
3748   /* apply negative sign during runtime */
3749   runtimeSign = FALSE;
3750   /* negative sign from literals */
3751   compiletimeSign = FALSE;
3752
3753   if (!lUnsigned)
3754     {
3755       if (AOP_TYPE(left) == AOP_LIT)
3756         {
3757           /* signed literal */
3758           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3759           if (val < 0)
3760             compiletimeSign = TRUE;
3761         }
3762       else
3763         /* signed but not literal */
3764         runtimeSign = TRUE;
3765     }
3766
3767   if (!rUnsigned)
3768     {
3769       if (AOP_TYPE(right) == AOP_LIT)
3770         {
3771           /* signed literal */
3772           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3773           if (val < 0)
3774             compiletimeSign ^= TRUE;
3775         }
3776       else
3777         /* signed but not literal */
3778         runtimeSign = TRUE;
3779     }
3780
3781   /* initialize the runtime sign */
3782   if (runtimeSign)
3783     {
3784       if (compiletimeSign)
3785         loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3786       else
3787         loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3788       pushReg (hc08_reg_x, TRUE);
3789     }
3790
3791   /* save the signs of the operands */
3792   if (AOP_TYPE(right) == AOP_LIT)
3793     {
3794       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3795
3796       if (!rUnsigned && val < 0)
3797         emitcode ("ldx", "#0x%02x", -val);
3798       else
3799         emitcode ("ldx", "#0x%02x", (unsigned char) val);
3800     }
3801   else /* ! literal */
3802     {
3803       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3804       if (!rUnsigned)
3805         {
3806           tlbl1 = newiTempLabel (NULL);
3807           emitcode ("tstx", "");
3808           emitBranch ("bpl", tlbl1);
3809           emitcode ("inc", "1,s");
3810           rmwWithReg ("neg", hc08_reg_x);
3811           emitLabel (tlbl1);
3812         }
3813     }
3814
3815   if (AOP_TYPE(left) == AOP_LIT)
3816     {
3817       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3818
3819       if (!lUnsigned && val < 0)
3820         emitcode ("lda", "#0x%02x", -val);
3821       else
3822         emitcode ("lda", "#0x%02x", (unsigned char) val);
3823     }
3824   else /* ! literal */
3825     {
3826       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3827       if (!lUnsigned)
3828         {
3829           tlbl2 = newiTempLabel (NULL);
3830           emitcode ("tsta", "");
3831           emitBranch ("bpl", tlbl2);
3832           emitcode ("inc", "1,s");
3833           rmwWithReg ("neg", hc08_reg_a);
3834           emitLabel (tlbl2);
3835         }
3836     }
3837     
3838   loadRegFromConst (hc08_reg_h, zero);
3839   emitcode ("div", "");
3840   hc08_dirtyReg (hc08_reg_x, FALSE);
3841   hc08_dirtyReg (hc08_reg_a, FALSE);
3842   hc08_dirtyReg (hc08_reg_h, FALSE);
3843   
3844   if (runtimeSign || compiletimeSign)
3845     {
3846       tlbl3 = newiTempLabel (NULL);
3847       if (runtimeSign)
3848         {
3849           pullReg (hc08_reg_x);
3850           rmwWithReg ("lsr", hc08_reg_x);
3851           rmwWithReg ("ror", hc08_reg_x);
3852           emitBranch ("bpl", tlbl3);
3853         }
3854      
3855       rmwWithReg ("neg", hc08_reg_a);
3856       if (runtimeSign)
3857         emitLabel (tlbl3);
3858       
3859       storeRegToAop (hc08_reg_a, AOP (result), 0);
3860       
3861       if (size > 1)
3862         {
3863           /* msb is 0x00 or 0xff depending on the sign */
3864           if (runtimeSign)
3865             {
3866               rmwWithReg ("lsl", hc08_reg_x);
3867               emitcode ("clra", "");
3868               emitcode ("sbc", "#0");
3869               while (--size)
3870                 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3871             }
3872           else /* compiletimeSign */
3873             while (--size)
3874               storeConstToAop ("#0xff", AOP (result), ++offset);
3875         }
3876     }
3877   else
3878     {
3879       storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3880     }
3881
3882   hc08_freeReg (hc08_reg_a);
3883   hc08_freeReg (hc08_reg_x);
3884   hc08_freeReg (hc08_reg_h);
3885 }
3886
3887 /*-----------------------------------------------------------------*/
3888 /* genDiv - generates code for division                            */
3889 /*-----------------------------------------------------------------*/
3890 static void
3891 genDiv (iCode * ic)
3892 {
3893   operand *left = IC_LEFT (ic);
3894   operand *right = IC_RIGHT (ic);
3895   operand *result = IC_RESULT (ic);
3896
3897   D(emitcode (";     genDiv",""));
3898
3899   /* assign the amsops */
3900   aopOp (left, ic, FALSE);
3901   aopOp (right, ic, FALSE);
3902   aopOp (result, ic, TRUE);
3903
3904   /* special cases first */
3905   /* if both are of size == 1 */
3906   if (AOP_SIZE (left) <= 2 &&
3907       AOP_SIZE (right) == 1)
3908     {
3909       genDivOneByte (left, right, result);
3910       goto release;
3911     }
3912
3913   /* should have been converted to function call */
3914   assert (0);
3915 release:
3916   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3917   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3918   freeAsmop (result, NULL, ic, TRUE);
3919 }
3920
3921 /*-----------------------------------------------------------------*/
3922 /* genModOneByte : 8 bit modulus                                   */
3923 /*-----------------------------------------------------------------*/
3924 static void
3925 genModOneByte (operand * left,
3926                operand * right,
3927                operand * result)
3928 {
3929   symbol *tlbl1, *tlbl2, *tlbl3;
3930   int size;
3931   int offset = 0;
3932   bool lUnsigned, rUnsigned;
3933   bool runtimeSign, compiletimeSign;
3934   
3935   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3936   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3937
3938   D(emitcode (";     genModOneByte",""));
3939
3940   size = AOP_SIZE (result);
3941   
3942   if (lUnsigned && rUnsigned)
3943     {
3944       /* unsigned is easy */
3945       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3946       loadRegFromAop (hc08_reg_h, AOP (left), 1);
3947       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3948       emitcode ("div", "");
3949       hc08_freeReg (hc08_reg_a);
3950       hc08_freeReg (hc08_reg_x);
3951       hc08_dirtyReg (hc08_reg_h, FALSE);
3952       storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3953       hc08_freeReg (hc08_reg_h);
3954       return;
3955     }
3956
3957   /* signed is a little bit more difficult */
3958   
3959   if (AOP_TYPE(right) == AOP_LIT)
3960     {
3961       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3962
3963       if (!rUnsigned && val < 0)
3964         emitcode ("ldx", "#0x%02x", -val);
3965       else
3966         emitcode ("ldx", "#0x%02x", (unsigned char) val);
3967     }
3968   else /* ! literal */
3969     {
3970       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3971       if (!rUnsigned)
3972         {
3973           tlbl1 = newiTempLabel (NULL);
3974           emitcode ("tstx", "");
3975           emitBranch ("bpl", tlbl1);
3976           rmwWithReg ("neg", hc08_reg_x);
3977           emitLabel (tlbl1);
3978         }
3979     }
3980   
3981   /* let's see what's needed: */
3982   /* apply negative sign during runtime */
3983   runtimeSign = FALSE;
3984   /* negative sign from literals */
3985   compiletimeSign = FALSE;
3986
3987   /* sign adjust left side */
3988   if (AOP_TYPE(left) == AOP_LIT)
3989     {
3990       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3991
3992       if (!lUnsigned && val < 0)
3993         {
3994           compiletimeSign = TRUE; /* set sign flag */
3995           emitcode ("lda", "#0x%02x", -val);
3996         }
3997       else
3998         emitcode ("lda", "#0x%02x", (unsigned char) val);
3999     }
4000   else /* ! literal */
4001     {
4002       if (lUnsigned)
4003         loadRegFromAop (hc08_reg_a, AOP (left), 0);
4004       else
4005         {
4006           runtimeSign = TRUE;
4007           adjustStack (-1);
4008           emitcode ("clr", "1,s");
4009           
4010           loadRegFromAop (hc08_reg_a, AOP (left), 0);
4011           tlbl2 = newiTempLabel (NULL);
4012           emitcode ("tsta", "");
4013           emitBranch ("bpl", tlbl2);
4014           emitcode ("inc", "1,s");
4015           rmwWithReg ("neg", hc08_reg_a);
4016           emitLabel (tlbl2);
4017         }
4018     }
4019   
4020   loadRegFromConst (hc08_reg_h, zero);
4021   emitcode ("div", "");
4022   hc08_freeReg (hc08_reg_a);
4023   hc08_freeReg (hc08_reg_x);
4024   hc08_dirtyReg (hc08_reg_h, FALSE);
4025
4026   if (runtimeSign || compiletimeSign)
4027     {
4028       transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4029       tlbl3 = newiTempLabel (NULL);
4030       if (runtimeSign)
4031         {
4032           pullReg (hc08_reg_x);
4033           rmwWithReg ("lsr", hc08_reg_x);
4034           rmwWithReg ("ror", hc08_reg_x);
4035           emitBranch ("bpl", tlbl3);
4036         }
4037      
4038       rmwWithReg ("neg", hc08_reg_a);
4039       if (runtimeSign)
4040         emitLabel (tlbl3);
4041       
4042       storeRegToAop (hc08_reg_a, AOP (result), 0);
4043       
4044       if (size > 1)
4045         {
4046           /* msb is 0x00 or 0xff depending on the sign */
4047           if (runtimeSign)
4048             {
4049               rmwWithReg ("lsl", hc08_reg_x);
4050               emitcode ("clra", "");
4051               emitcode ("sbc", "#0");
4052               while (--size)
4053                 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4054             }
4055           else /* compiletimeSign */
4056             while (--size)
4057               storeConstToAop ("#0xff", AOP (result), ++offset);
4058         }
4059     }
4060   else
4061     {
4062       storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4063     }
4064   
4065   hc08_freeReg (hc08_reg_a);
4066   hc08_freeReg (hc08_reg_x);
4067   hc08_freeReg (hc08_reg_h);
4068 }
4069
4070 /*-----------------------------------------------------------------*/
4071 /* genMod - generates code for division                            */
4072 /*-----------------------------------------------------------------*/
4073 static void
4074 genMod (iCode * ic)
4075 {
4076   operand *left = IC_LEFT (ic);
4077   operand *right = IC_RIGHT (ic);
4078   operand *result = IC_RESULT (ic);
4079
4080   D(emitcode (";     genMod",""));
4081
4082   /* assign the amsops */
4083   aopOp (left, ic, FALSE);
4084   aopOp (right, ic, FALSE);
4085   aopOp (result, ic, TRUE);
4086
4087   /* special cases first */
4088   /* if both are of size == 1 */
4089   if (AOP_SIZE (left) <= 2 &&
4090       AOP_SIZE (right) == 1)
4091     {
4092       genModOneByte (left, right, result);
4093       goto release;
4094     }
4095
4096   /* should have been converted to function call */
4097   assert (0);
4098
4099 release:
4100   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4101   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4102   freeAsmop (result, NULL, ic, TRUE);
4103 }
4104
4105 /*-----------------------------------------------------------------*/
4106 /* genIfxJump :- will create a jump depending on the ifx           */
4107 /*-----------------------------------------------------------------*/
4108 static void
4109 genIfxJump (iCode * ic, char *jval)
4110 {
4111   symbol *jlbl;
4112   symbol *tlbl = newiTempLabel (NULL);
4113   char *inst;
4114
4115   D(emitcode (";     genIfxJump",""));
4116
4117   /* if true label then we jump if condition
4118      supplied is true */
4119   if (IC_TRUE (ic))
4120     {
4121       jlbl = IC_TRUE (ic);
4122       if (!strcmp (jval, "a"))
4123         inst = "beq";
4124       else if (!strcmp (jval, "c"))
4125         inst = "bcc";
4126       else
4127         inst = "bge";
4128     }
4129   else
4130     {
4131       /* false label is present */
4132       jlbl = IC_FALSE (ic);
4133       if (!strcmp (jval, "a"))
4134         inst = "bne";
4135       else if (!strcmp (jval, "c"))
4136         inst = "bcs";
4137       else
4138         inst = "blt";
4139     }
4140   emitBranch (inst, tlbl);
4141   emitBranch ("jmp", jlbl);
4142   emitLabel (tlbl);
4143
4144   /* mark the icode as generated */
4145   ic->generated = 1;
4146 }
4147
4148
4149 /*-----------------------------------------------------------------*/
4150 /* exchangedCmp : returns the opcode need if the two operands are  */
4151 /*                exchanged in a comparison                        */
4152 /*-----------------------------------------------------------------*/
4153 static int
4154 exchangedCmp (int opcode)
4155 {
4156   switch (opcode)
4157     {
4158     case '<':
4159       return '>';
4160     case '>':
4161       return '<';
4162     case LE_OP:
4163       return GE_OP;
4164     case GE_OP:
4165       return LE_OP;
4166     case NE_OP:
4167       return NE_OP;
4168     case EQ_OP:
4169       return EQ_OP;
4170     default:
4171       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4172                   "opcode not a comparison");
4173     }
4174   return EQ_OP; /* shouldn't happen, but need to return something */
4175 }
4176
4177 /*------------------------------------------------------------------*/
4178 /* negatedCmp : returns the equivalent opcode for when a comparison */
4179 /*              if not true                                         */
4180 /*------------------------------------------------------------------*/
4181 static int
4182 negatedCmp (int opcode)
4183 {
4184   switch (opcode)
4185     {
4186     case '<':
4187       return GE_OP;
4188     case '>':
4189       return LE_OP;
4190     case LE_OP:
4191       return '>';
4192     case GE_OP:
4193       return '<';
4194     case NE_OP:
4195       return EQ_OP;
4196     case EQ_OP:
4197       return NE_OP;
4198     default:
4199       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4200                   "opcode not a comparison");
4201     }
4202   return EQ_OP; /* shouldn't happen, but need to return something */
4203 }
4204
4205 /* compile only if the debugging macro D is enabled */
4206 #if (D(1) -0)
4207 static char *
4208 nameCmp (int opcode)
4209 {
4210   switch (opcode)
4211     {
4212     case '<':
4213       return "<";
4214     case '>':
4215       return ">";
4216     case LE_OP:
4217       return "<=";
4218     case GE_OP:
4219       return ">=";
4220     case NE_OP:
4221       return "!=";
4222     case EQ_OP:
4223       return "==";
4224     default:
4225       return "invalid";
4226     }
4227 }
4228 #endif
4229
4230 /*------------------------------------------------------------------*/
4231 /* branchInstCmp : returns the conditional branch instruction that  */
4232 /*                 will branch if the comparison is true            */
4233 /*------------------------------------------------------------------*/
4234 static char *
4235 branchInstCmp (int opcode, int sign)
4236 {
4237   switch (opcode)
4238     {
4239     case '<':
4240       if (sign)
4241         return "blt";
4242       else
4243         return "bcs";   /* same as blo */
4244     case '>':
4245       if (sign)
4246         return "bgt";
4247       else
4248         return "bhi";
4249     case LE_OP:
4250       if (sign)
4251         return "ble";
4252       else
4253         return "bls";
4254     case GE_OP:
4255       if (sign)
4256         return "bge";
4257       else
4258         return "bcc";   /* same as bhs */
4259     case NE_OP:
4260       return "bne";
4261     case EQ_OP:
4262       return "beq";
4263     default:
4264       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4265                   "opcode not a comparison");
4266     }
4267   return "brn";
4268 }
4269
4270
4271 /*------------------------------------------------------------------*/
4272 /* genCmp :- greater or less than (and maybe with equal) comparison */
4273 /*------------------------------------------------------------------*/
4274 static void
4275 genCmp (iCode * ic, iCode * ifx)
4276 {  
4277   operand *left, *right, *result;
4278   sym_link *letype, *retype;
4279   int sign, opcode;
4280   int size, offset = 0;
4281   unsigned long lit = 0L;
4282   char *sub;
4283   symbol *jlbl = NULL;
4284
4285   opcode = ic->op;
4286
4287   D(emitcode (";     genCmp", "(%s)",nameCmp (opcode)));
4288
4289   result = IC_RESULT (ic);
4290   left = IC_LEFT (ic);
4291   right = IC_RIGHT (ic);
4292
4293   letype = getSpec (operandType (left));
4294   retype = getSpec (operandType (right));
4295   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4296   /* assign the amsops */
4297   aopOp (left, ic, FALSE);
4298   aopOp (right, ic, FALSE);
4299   aopOp (result, ic, TRUE);
4300
4301   /* need register operand on left, prefer literal operand on right */
4302   if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4303     {
4304       operand *temp = left;
4305       left = right;
4306       right = temp;
4307       opcode = exchangedCmp (opcode);
4308     }
4309
4310   if (ifx)
4311     {
4312       if (IC_TRUE (ifx))
4313         {
4314           jlbl = IC_TRUE (ifx);
4315           opcode = negatedCmp (opcode);
4316         }
4317       else
4318         {
4319           /* false label is present */
4320           jlbl = IC_FALSE (ifx);
4321         }
4322     }
4323       
4324   size = max (AOP_SIZE (left), AOP_SIZE (right));
4325   
4326   if ((size == 2)
4327       && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4328       && ((AOP_TYPE (right) == AOP_LIT) || 
4329           ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4330       && hc08_reg_hx->isFree)
4331     {
4332       loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4333       emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4334       hc08_freeReg (hc08_reg_hx);
4335     }
4336   else
4337     {
4338       offset = 0;
4339       if (size == 1)
4340         sub = "cmp";
4341       else
4342         {
4343           sub = "sub";
4344         
4345           /* These conditions depend on the Z flag bit, but Z is */
4346           /* only valid for the last byte of the comparison, not */
4347           /* the whole value. So exchange the operands to get a  */
4348           /* comparison that doesn't depend on Z. (This is safe  */
4349           /* to do here since ralloc won't assign multi-byte     */
4350           /* operands to registers for comparisons)              */
4351           if ((opcode == '>') || (opcode == LE_OP))
4352             {
4353               operand *temp = left;
4354               left = right;
4355               right = temp;
4356               opcode = exchangedCmp (opcode);
4357             }
4358           
4359           if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4360             {
4361               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4362               while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4363                 {
4364                   offset++;
4365                   size--;
4366                 }
4367             }
4368         }
4369       while (size--)
4370         {
4371           loadRegFromAop (hc08_reg_a, AOP (left), offset);
4372           accopWithAop (sub, AOP (right), offset);
4373           hc08_freeReg (hc08_reg_a);
4374           offset++;
4375           sub = "sbc";
4376         }
4377     }
4378   freeAsmop (right, NULL, ic, FALSE);
4379   freeAsmop (left, NULL, ic, FALSE);
4380
4381   if (ifx)
4382     {
4383       symbol *tlbl = newiTempLabel (NULL);
4384       char *inst;
4385
4386       freeAsmop (result, NULL, ic, TRUE);      
4387       
4388       inst = branchInstCmp (opcode, sign);
4389       emitBranch (inst, tlbl);
4390       emitBranch ("jmp", jlbl);
4391       emitLabel (tlbl);
4392
4393       /* mark the icode as generated */
4394       ifx->generated = 1;
4395     }
4396   else
4397     {
4398       symbol *tlbl1 = newiTempLabel (NULL);
4399       symbol *tlbl2 = newiTempLabel (NULL);
4400       
4401       emitBranch (branchInstCmp (opcode, sign), tlbl1);
4402       loadRegFromConst (hc08_reg_a, zero);
4403       emitBranch ("bra", tlbl2);
4404       emitLabel (tlbl1);
4405       loadRegFromConst (hc08_reg_a, one);
4406       emitLabel (tlbl2);
4407       storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4408       freeAsmop (result, NULL, ic, TRUE);      
4409     }
4410         
4411 }
4412
4413 /*-----------------------------------------------------------------*/
4414 /* genCmpEQorNE - equal or not equal comparison                    */
4415 /*-----------------------------------------------------------------*/
4416 static void
4417 genCmpEQorNE (iCode * ic, iCode * ifx)
4418 {  
4419   operand *left, *right, *result;
4420   sym_link *letype, *retype;
4421   int sign, opcode;
4422   int size, offset = 0;
4423   char *sub;
4424   symbol *jlbl = NULL;
4425   symbol *tlbl_NE = NULL;
4426   symbol *tlbl_EQ = NULL;
4427  
4428   opcode = ic->op;
4429
4430   D(emitcode (";     genCmpEQorNE", "(%s)",nameCmp (opcode)));
4431
4432   result = IC_RESULT (ic);
4433   left = IC_LEFT (ic);
4434   right = IC_RIGHT (ic);
4435
4436   letype = getSpec (operandType (left));
4437   retype = getSpec (operandType (right));
4438   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4439   /* assign the amsops */
4440   aopOp (left, ic, FALSE);
4441   aopOp (right, ic, FALSE);
4442   aopOp (result, ic, TRUE);
4443   
4444   /* need register operand on left, prefer literal operand on right */
4445   if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4446     {
4447       operand *temp = left;
4448       left = right;
4449       right = temp;
4450       opcode = exchangedCmp (opcode);
4451     }
4452
4453   if (ifx)
4454     {
4455       if (IC_TRUE (ifx))
4456         {
4457           jlbl = IC_TRUE (ifx);
4458           opcode = negatedCmp (opcode);
4459         }
4460       else
4461         {
4462           /* false label is present */
4463           jlbl = IC_FALSE (ifx);
4464         }
4465     }
4466       
4467   size = max (AOP_SIZE (left), AOP_SIZE (right));
4468   
4469   if ((size == 2)
4470       && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4471       && ((AOP_TYPE (right) == AOP_LIT) || 
4472           ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4473       && hc08_reg_hx->isFree)
4474     {
4475       loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4476       emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4477       hc08_freeReg (hc08_reg_hx);
4478     }
4479   else
4480     {
4481       offset = 0;
4482       sub = "cmp";
4483       while (size--)
4484         {
4485           loadRegFromAop (hc08_reg_a, AOP (left), offset);
4486           accopWithAop (sub, AOP (right), offset);
4487           if (size)
4488             {
4489               if (!tlbl_NE)
4490                 tlbl_NE = newiTempLabel (NULL);
4491               emitBranch ("bne", tlbl_NE);
4492             }
4493           hc08_freeReg (hc08_reg_a);
4494           offset++;
4495         }
4496     }
4497   freeAsmop (right, NULL, ic, FALSE);
4498   freeAsmop (left, NULL, ic, FALSE);
4499
4500   if (ifx)
4501     {
4502       freeAsmop (result, NULL, ic, TRUE);      
4503       
4504       if (opcode == EQ_OP)
4505         {
4506           if (!tlbl_EQ)
4507             tlbl_EQ = newiTempLabel (NULL);
4508           emitBranch ("beq", tlbl_EQ);
4509           if (tlbl_NE)
4510             emitLabel (tlbl_NE);
4511           emitBranch ("jmp", jlbl);
4512           emitLabel (tlbl_EQ);
4513         }
4514       else
4515         {
4516           if (!tlbl_NE)
4517             tlbl_NE = newiTempLabel (NULL);
4518           emitBranch ("bne", tlbl_NE);
4519           emitBranch ("jmp", jlbl);
4520           emitLabel (tlbl_NE);
4521         }
4522
4523       /* mark the icode as generated */
4524       ifx->generated = 1;
4525     }
4526   else
4527     {
4528       symbol *tlbl = newiTempLabel (NULL);
4529       
4530       if (opcode == EQ_OP)
4531         {
4532           if (!tlbl_EQ)
4533             tlbl_EQ = newiTempLabel (NULL);
4534           emitBranch ("beq", tlbl_EQ);
4535           if (tlbl_NE)
4536             emitLabel (tlbl_NE);
4537           loadRegFromConst (hc08_reg_a, zero);
4538           emitBranch ("bra", tlbl);
4539           emitLabel (tlbl_EQ);
4540           loadRegFromConst (hc08_reg_a, one);
4541         }
4542       else
4543         {
4544           if (!tlbl_NE)
4545             tlbl_NE = newiTempLabel (NULL);
4546           emitBranch ("bne", tlbl_NE);
4547           loadRegFromConst (hc08_reg_a, zero);
4548           emitBranch ("bra", tlbl);
4549           emitLabel (tlbl_NE);
4550           loadRegFromConst (hc08_reg_a, one);
4551         }
4552       
4553       emitLabel (tlbl);
4554       storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4555       freeAsmop (result, NULL, ic, TRUE);      
4556     }
4557         
4558 }
4559
4560
4561 /*-----------------------------------------------------------------*/
4562 /* ifxForOp - returns the icode containing the ifx for operand     */
4563 /*-----------------------------------------------------------------*/
4564 static iCode *
4565 ifxForOp (operand * op, iCode * ic)
4566 {
4567   /* if true symbol then needs to be assigned */
4568   if (IS_TRUE_SYMOP (op))
4569     return NULL;
4570
4571   /* if this has register type condition and
4572      the next instruction is ifx with the same operand
4573      and live to of the operand is upto the ifx only then */
4574   if (ic->next &&
4575       ic->next->op == IFX &&
4576       IC_COND (ic->next)->key == op->key &&
4577       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4578     return ic->next;
4579
4580   return NULL;
4581 }
4582
4583 static bool
4584 genPointerGetSetOfs (iCode *ic)
4585 {
4586   iCode *lic = ic->next;
4587   bool pset, pget;
4588   int size;
4589   symbol *sym;
4590   asmop *derefaop;
4591
4592   /* Make sure we have a next iCode */
4593   D(emitcode("","; checking lic"));
4594   if (!lic)
4595     return FALSE;
4596
4597   /* Make sure the result of the addition is an iCode */
4598   D(emitcode("","; checking IS_ITEMP"));
4599   if (!IS_ITEMP (IC_RESULT (ic)))
4600     return FALSE;
4601
4602   /* Make sure the next iCode is a pointer set or get */
4603   pset = POINTER_SET(lic);
4604   pget = POINTER_GET(lic);
4605   D(emitcode("","; pset=%d, pget=%d",pset,pget));
4606   if (!pset && !pget)
4607     return FALSE;
4608
4609   /* Make sure this is the only use of the pointer */
4610   if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4611     return FALSE;
4612     
4613   D(emitcode("", "; checking pset operandsEqu"));
4614   if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4615     return FALSE;
4616
4617   D(emitcode("", "; checking pget operandsEqu"));
4618   if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4619     return FALSE;
4620
4621   D(emitcode("", "; checking IS_SYMOP"));
4622   if (!IS_SYMOP (IC_LEFT (ic)))
4623     return FALSE;
4624
4625   D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4626   if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4627     return FALSE;
4628
4629   sym = OP_SYMBOL (IC_LEFT (ic));
4630   
4631   D(emitcode("", "; checking remat"));
4632   if (!sym->remat)
4633     return FALSE;
4634     
4635   
4636   if (pget)
4637     {
4638       D(emitcode (";     genPointerGetOfs",""));
4639       aopOp (IC_LEFT(ic), ic, FALSE);
4640       derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4641       freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4642       
4643       aopOp (IC_RIGHT(ic), ic, FALSE);
4644       aopOp (IC_RESULT(lic), lic, FALSE);
4645
4646       if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4647         {
4648           if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4649             {
4650               loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4651               loadRegFromConst (hc08_reg_h, zero);
4652             }
4653           else
4654             {
4655               loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4656               transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4657               emitcode ("rola","");
4658               emitcode ("clra","");
4659               emitcode ("sbc", "#0");
4660               hc08_useReg (hc08_reg_a);
4661               transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4662            }
4663         }
4664       else
4665         loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4666       size = AOP_SIZE (IC_RESULT(lic));
4667       derefaop->size = size;
4668       
4669       while (size--)
4670         {
4671           emitcode ("lda", "%s,x",
4672                     aopAdrStr (derefaop, size, TRUE));
4673           hc08_useReg (hc08_reg_a);
4674           storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4675           hc08_freeReg (hc08_reg_a);
4676         }
4677
4678       lic->generated = 1;
4679       hc08_freeReg (hc08_reg_hx);
4680
4681       freeAsmop (NULL, derefaop, ic, TRUE);
4682       freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4683       freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4684       
4685       return TRUE;
4686     }
4687
4688   if (pset)
4689     {
4690       D(emitcode (";     genPointerSetOfs",""));
4691       aopOp (IC_LEFT(ic), ic, FALSE);
4692       derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4693       freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4694
4695       aopOp (IC_RIGHT(ic), ic, FALSE);
4696       aopOp (IC_RIGHT(lic), lic, FALSE);
4697       
4698       if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4699         {
4700           if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4701             {
4702               loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4703               loadRegFromConst (hc08_reg_h, zero);
4704             }
4705           else
4706             {
4707               loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4708               transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4709               emitcode ("rola","");
4710               emitcode ("clra","");
4711               emitcode ("sbc", "#0");
4712               hc08_useReg (hc08_reg_a);
4713               transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4714            }
4715         }
4716       else
4717         loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4718       size = AOP_SIZE (IC_RIGHT(lic));
4719       derefaop->size = size;
4720       
4721       while (size--)
4722         {
4723           loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4724           emitcode ("sta", "%s,x",
4725                     aopAdrStr (derefaop, size, TRUE));
4726           hc08_freeReg (hc08_reg_a);
4727         }
4728
4729       lic->generated = 1;
4730       hc08_freeReg (hc08_reg_hx);
4731
4732       freeAsmop (NULL, derefaop, ic, TRUE);
4733       freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4734       freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4735       
4736       return TRUE;
4737     }
4738     
4739   return FALSE;
4740 }
4741
4742
4743 /*-----------------------------------------------------------------*/
4744 /* hasInc - operand is incremented before any other use            */
4745 /*-----------------------------------------------------------------*/
4746 static iCode *
4747 hasInc (operand *op, iCode *ic,int osize)
4748 {
4749   sym_link *type = operandType(op);
4750   sym_link *retype = getSpec (type);
4751   iCode *lic = ic->next;
4752   int isize ;
4753   
4754   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4755   if (!IS_SYMOP(op)) return NULL;
4756
4757   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4758   if (IS_AGGREGATE(type->next)) return NULL;
4759   if (osize != (isize = getSize(type->next))) return NULL;
4760
4761   while (lic) {
4762     /* if operand of the form op = op + <sizeof *op> */
4763     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4764         isOperandEqual(IC_RESULT(lic),op) && 
4765         isOperandLiteral(IC_RIGHT(lic)) &&
4766         operandLitValue(IC_RIGHT(lic)) == isize) {
4767       return lic;
4768     }
4769     /* if the operand used or deffed */
4770     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4771       return NULL;
4772     }
4773     /* if GOTO or IFX */
4774     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4775     lic = lic->next;
4776   }
4777   return NULL;
4778 }
4779
4780 /*-----------------------------------------------------------------*/
4781 /* genAndOp - for && operation                                     */
4782 /*-----------------------------------------------------------------*/
4783 static void
4784 genAndOp (iCode * ic)
4785 {
4786   operand *left, *right, *result;
4787   symbol *tlbl, *tlbl0;
4788
4789   D(emitcode (";     genAndOp",""));
4790
4791   /* note here that && operations that are in an
4792      if statement are taken away by backPatchLabels
4793      only those used in arthmetic operations remain */
4794   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4795   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4796   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4797
4798   tlbl = newiTempLabel (NULL);
4799   tlbl0 = newiTempLabel (NULL);
4800   
4801   asmopToBool (AOP (left), FALSE);
4802   emitBranch ("beq", tlbl0);
4803   asmopToBool (AOP (right), FALSE);
4804   emitBranch ("beq", tlbl0);
4805   loadRegFromConst (hc08_reg_a,one);
4806   emitBranch ("bra", tlbl);
4807   emitLabel (tlbl0);
4808   loadRegFromConst (hc08_reg_a,zero);
4809   emitLabel (tlbl);
4810
4811   hc08_useReg (hc08_reg_a);
4812   hc08_freeReg (hc08_reg_a);
4813   
4814   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4815
4816   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4817   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4818   freeAsmop (result, NULL, ic, TRUE);
4819 }
4820
4821
4822 /*-----------------------------------------------------------------*/
4823 /* genOrOp - for || operation                                      */
4824 /*-----------------------------------------------------------------*/
4825 static void
4826 genOrOp (iCode * ic)
4827 {
4828   operand *left, *right, *result;
4829   symbol *tlbl, *tlbl0;
4830
4831   D(emitcode (";     genOrOp",""));
4832
4833   /* note here that || operations that are in an
4834      if statement are taken away by backPatchLabels
4835      only those used in arthmetic operations remain */
4836   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4837   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4838   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4839
4840   tlbl = newiTempLabel (NULL);
4841   tlbl0 = newiTempLabel (NULL);
4842   
4843   asmopToBool (AOP (left), FALSE);
4844   emitBranch ("bne", tlbl0);
4845   asmopToBool (AOP (right), FALSE);
4846   emitBranch ("bne", tlbl0);
4847   loadRegFromConst (hc08_reg_a,zero);
4848   emitBranch ("bra", tlbl);
4849   emitLabel (tlbl0);
4850   loadRegFromConst (hc08_reg_a,one);
4851   emitLabel (tlbl);
4852
4853   hc08_useReg (hc08_reg_a);
4854   hc08_freeReg (hc08_reg_a);
4855   
4856   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4857
4858
4859   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4860   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4861   freeAsmop (result, NULL, ic, TRUE);
4862 }
4863
4864 /*-----------------------------------------------------------------*/
4865 /* isLiteralBit - test if lit == 2^n                               */
4866 /*-----------------------------------------------------------------*/
4867 static int
4868 isLiteralBit (unsigned long lit)
4869 {
4870   unsigned long pw[32] =
4871   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4872    0x100L, 0x200L, 0x400L, 0x800L,
4873    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4874    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4875    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4876    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4877    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4878   int idx;
4879
4880   for (idx = 0; idx < 32; idx++)
4881     if (lit == pw[idx])
4882       return idx + 1;
4883   return 0;
4884 }
4885
4886 #if 0
4887 /*-----------------------------------------------------------------*/
4888 /* continueIfTrue -                                                */
4889 /*-----------------------------------------------------------------*/
4890 static void
4891 continueIfTrue (iCode * ic)
4892 {
4893   if (IC_TRUE (ic))
4894     emitBranch ("jmp", IC_TRUE (ic));
4895   ic->generated = 1;
4896 }
4897
4898 /*-----------------------------------------------------------------*/
4899 /* jmpIfTrue -                                                     */
4900 /*-----------------------------------------------------------------*/
4901 static void
4902 jumpIfTrue (iCode * ic)
4903 {
4904   if (!IC_TRUE (ic))
4905     emitBranch ("jmp", IC_FALSE (ic));
4906   ic->generated = 1;
4907 }
4908
4909 /*-----------------------------------------------------------------*/
4910 /* jmpTrueOrFalse -                                                */
4911 /*-----------------------------------------------------------------*/
4912 static void
4913 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4914 {
4915   // ugly but optimized by peephole
4916   if (IC_TRUE (ic))
4917     {
4918       symbol *nlbl = newiTempLabel (NULL);
4919       emitBranch ("bra", nlbl);
4920       emitLabel (tlbl);
4921       emitBranch ("jmp", IC_TRUE (ic));
4922       emitLabel (nlbl);
4923     }
4924   else
4925     {
4926       emitBranch ("jmp", IC_FALSE (ic));
4927       emitLabel (tlbl);
4928     }
4929   ic->generated = 1;
4930 }
4931 #endif
4932
4933 /*-----------------------------------------------------------------*/
4934 /* genAnd  - code for and                                          */
4935 /*-----------------------------------------------------------------*/
4936 static void
4937 genAnd (iCode * ic, iCode * ifx)
4938 {
4939   operand *left, *right, *result;
4940   int size, offset = 0;
4941   unsigned long lit = 0L;
4942   unsigned long litinv;
4943   unsigned char bytemask;
4944
4945   
4946 //  int bytelit = 0;
4947 //  char buffer[10];
4948
4949   D(emitcode (";     genAnd",""));
4950
4951   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4952   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4953   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4954
4955 #ifdef DEBUG_TYPE
4956   D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4957             AOP_TYPE (result),
4958             AOP_TYPE (left), AOP_TYPE (right)));
4959   D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4960             AOP_SIZE (result),
4961             AOP_SIZE (left), AOP_SIZE (right)));
4962 #endif
4963
4964   /* if left is a literal & right is not then exchange them */
4965   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4966     {
4967       operand *tmp = right;
4968       right = left;
4969       left = tmp;
4970     }
4971
4972   /* if right is accumulator & left is not then exchange them */
4973   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4974     {
4975       operand *tmp = right;
4976       right = left;
4977       left = tmp;
4978     }
4979
4980   if (AOP_TYPE (right) == AOP_LIT)
4981     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4982       
4983   size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4984   
4985   if (AOP_TYPE (result) == AOP_CRY
4986       && size > 1
4987       && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
4988     {
4989       /* this generates ugly code, but meets volatility requirements */
4990       loadRegFromConst (hc08_reg_a, zero);
4991       pushReg (hc08_reg_a, TRUE);
4992       
4993       offset = 0;
4994       while (size--)
4995         {
4996           loadRegFromAop (hc08_reg_a, AOP (left), offset);
4997           accopWithAop ("and", AOP (right), offset);
4998           emitcode ("ora", "1,s");
4999           emitcode ("sta", "1,s");
5000           offset++;
5001         }
5002       
5003       pullReg (hc08_reg_a);
5004       emitcode ("tsta", "");
5005       genIfxJump (ifx, "a");
5006       goto release;
5007     }
5008   
5009   if (AOP_TYPE (result) == AOP_CRY)
5010     {
5011       symbol *tlbl = NULL;
5012       wassertl (ifx, "AOP_CRY result without ifx");
5013       
5014       offset = 0;
5015       while (size--)
5016         {
5017           bytemask = (lit >> (offset*8)) & 0xff;
5018           
5019           if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5020             {
5021               /* do nothing */
5022             }
5023           else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5024             {
5025               rmwWithAop ("tst", AOP (left), offset);
5026               if (size)
5027                 {
5028                   if (!tlbl)
5029                     tlbl = newiTempLabel (NULL);
5030                   emitBranch ("bne", tlbl);
5031                 }
5032             }
5033           else
5034             {
5035               loadRegFromAop (hc08_reg_a, AOP (left), offset);
5036               accopWithAop ("and", AOP (right), offset);
5037               hc08_freeReg( hc08_reg_a);
5038               if (size)
5039                 {
5040                   if (!tlbl)
5041                     tlbl = newiTempLabel (NULL);
5042                   emitBranch ("bne", tlbl);
5043                 }
5044             }
5045           offset++;
5046         }
5047         if (tlbl)
5048           emitLabel (tlbl);
5049         genIfxJump (ifx, "a");
5050         goto release;
5051     }
5052   
5053   size = AOP_SIZE (result);
5054
5055   if (AOP_TYPE (right) == AOP_LIT)
5056     {
5057       litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5058       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5059           (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5060         {
5061           int bitpos = isLiteralBit(litinv)-1;
5062           emitcode ("bclr","#%d,%s",bitpos & 7,
5063                     aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5064           goto release;
5065         }
5066     }
5067     
5068   offset = 0;
5069   while (size--)
5070     {
5071       bytemask = (lit >> (offset*8)) & 0xff;
5072       
5073       if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5074         {
5075           if (isOperandVolatile (left, FALSE))
5076             {
5077               loadRegFromAop (hc08_reg_a, AOP (left), offset);
5078               hc08_freeReg( hc08_reg_a);      
5079             }
5080           storeConstToAop (zero, AOP (result), offset);
5081         }
5082       else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5083         {
5084           transferAopAop (AOP (left), offset, AOP (result), offset);
5085         }
5086       else
5087         {
5088           loadRegFromAop (hc08_reg_a, AOP (left), offset);
5089           accopWithAop ("and", AOP (right), offset);
5090           storeRegToAop (hc08_reg_a, AOP (result), offset);
5091           hc08_freeReg (hc08_reg_a);      
5092         }
5093       offset++;
5094     }
5095
5096 release:
5097   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5098   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5099   freeAsmop (result, NULL, ic, TRUE);
5100 }
5101
5102 /*-----------------------------------------------------------------*/
5103 /* genOr  - code for or                                            */
5104 /*-----------------------------------------------------------------*/
5105 static void
5106 genOr (iCode * ic, iCode * ifx)
5107 {
5108   operand *left, *right, *result;
5109   int size, offset = 0;
5110   unsigned long lit = 0L;
5111   unsigned char bytemask;
5112
5113   D(emitcode (";     genOr",""));
5114
5115   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5116   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5117   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5118
5119 #ifdef DEBUG_TYPE
5120   D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5121             AOP_TYPE (result),
5122             AOP_TYPE (left), AOP_TYPE (right)));
5123   D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5124             AOP_SIZE (result),
5125             AOP_SIZE (left), AOP_SIZE (right)));
5126 #endif
5127
5128   /* if left is a literal & right is not then exchange them */
5129   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5130     {
5131       operand *tmp = right;
5132       right = left;
5133       left = tmp;
5134     }
5135
5136   /* if left is accumulator & right is not then exchange them */
5137   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5138     {
5139       operand *tmp = right;
5140       right = left;
5141       left = tmp;
5142     }
5143
5144   if (AOP_TYPE (right) == AOP_LIT)
5145     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5146       
5147   size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5148   
5149   if (AOP_TYPE (result) == AOP_CRY
5150       && size > 1
5151       && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5152     {
5153       /* this generates ugly code, but meets volatility requirements */
5154       loadRegFromConst (hc08_reg_a, zero);
5155       pushReg (hc08_reg_a, TRUE);
5156       
5157       offset = 0;
5158       while (size--)
5159         {
5160           loadRegFromAop (hc08_reg_a, AOP (left), offset);
5161           accopWithAop ("ora", AOP (right), offset);
5162           emitcode ("ora", "1,s");
5163           emitcode ("sta", "1,s");
5164           offset++;
5165         }
5166       
5167       pullReg (hc08_reg_a);
5168       emitcode ("tsta", "");
5169       genIfxJump (ifx, "a");
5170       goto release;
5171     }
5172   
5173   if (AOP_TYPE (result) == AOP_CRY)
5174     {
5175       symbol *tlbl = NULL;
5176       wassertl (ifx, "AOP_CRY result without ifx");
5177       
5178       offset = 0;
5179       while (size--)
5180         {
5181           bytemask = (lit >> (offset*8)) & 0xff;
5182           
5183           if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5184             {
5185               rmwWithAop ("tst", AOP (left), offset);
5186               if (size)
5187                 {
5188                   if (!tlbl)
5189                     tlbl = newiTempLabel (NULL);
5190                   emitBranch ("bne", tlbl);
5191                 }
5192             }
5193           else
5194             {
5195               loadRegFromAop (hc08_reg_a, AOP (left), offset);
5196               accopWithAop ("ora", AOP (right), offset);
5197               hc08_freeReg( hc08_reg_a);
5198               if (size)
5199                 {
5200                   if (!tlbl)
5201                     tlbl = newiTempLabel (NULL);
5202                   emitBranch ("bne", tlbl);
5203                 }
5204             }
5205           offset++;
5206         }
5207         if (tlbl)
5208           emitLabel (tlbl);
5209         genIfxJump (ifx, "a");
5210     }
5211   
5212   if (AOP_TYPE (right) == AOP_LIT)
5213     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5214
5215   size = AOP_SIZE (result);
5216
5217   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5218       (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5219       (AOP_TYPE (left) == AOP_DIR))
5220     {
5221       int bitpos = isLiteralBit(lit)-1;
5222       emitcode ("bset","#%d,%s",bitpos & 7,
5223                 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5224       goto release;
5225     }
5226     
5227   offset = 0;
5228   while (size--)
5229     {
5230       bytemask = (lit >> (offset*8)) & 0xff;
5231       
5232       if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5233         {
5234           if (isOperandVolatile (left, FALSE))
5235             {
5236               loadRegFromAop (hc08_reg_a, AOP (left), offset);
5237               hc08_freeReg( hc08_reg_a);      
5238             }
5239           transferAopAop (AOP (right), offset, AOP (result), offset);
5240         }
5241       else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5242         {
5243           transferAopAop (AOP (left), offset, AOP (result), offset);
5244         }
5245       else
5246         {
5247           loadRegFromAop (hc08_reg_a, AOP (left), offset);
5248           accopWithAop ("ora", AOP (right), offset);
5249           storeRegToAop (hc08_reg_a, AOP (result), offset);
5250           hc08_freeReg (hc08_reg_a);      
5251         }
5252       offset++;
5253     }
5254
5255
5256 release:
5257   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5258   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5259   freeAsmop (result, NULL, ic, TRUE);
5260 }
5261
5262 /*-----------------------------------------------------------------*/
5263 /* genXor - code for xclusive or                                   */
5264 /*-----------------------------------------------------------------*/
5265 static void
5266 genXor (iCode * ic, iCode * ifx)
5267 {
5268   operand *left, *right, *result;
5269   int size, offset = 0;
5270   unsigned long lit = 0L;
5271
5272   D(emitcode (";     genXor",""));
5273
5274   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5275   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5276   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5277
5278 #ifdef DEBUG_TYPE
5279   D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5280             AOP_TYPE (result),
5281             AOP_TYPE (left), AOP_TYPE (right)));
5282   D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5283             AOP_SIZE (result),
5284             AOP_SIZE (left), AOP_SIZE (right)));
5285 #endif
5286
5287   /* if left is a literal & right is not ||
5288      if left needs acc & right does not */
5289   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5290     {
5291       operand *tmp = right;
5292       right = left;
5293       left = tmp;
5294     }
5295
5296   /* if left is accumulator & right is not then exchange them */
5297   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5298     {
5299       operand *tmp = right;
5300       right = left;
5301       left = tmp;
5302     }
5303
5304   if (AOP_TYPE (result) == AOP_CRY)
5305     {
5306       symbol *tlbl;
5307       wassertl (ifx, "AOP_CPY result without ifx");
5308       
5309       tlbl = newiTempLabel (NULL);
5310       size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5311       offset = 0;
5312       while (size--)
5313         {
5314           loadRegFromAop (hc08_reg_a, AOP (left), offset);
5315           if ((AOP_TYPE (right) == AOP_LIT)
5316               && (((lit >> (offset*8)) & 0xff) == 0))
5317             emitcode ("tsta","");
5318           else
5319             accopWithAop ("eor", AOP (right), offset);
5320           hc08_freeReg( hc08_reg_a);      
5321           if (size)
5322             emitBranch ("bne", tlbl);
5323           else
5324             {
5325               emitLabel (tlbl);
5326               genIfxJump (ifx, "a");
5327             }
5328           offset++;
5329         }
5330     }
5331     
5332   if (AOP_TYPE (right) == AOP_LIT)
5333     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5334
5335   size = AOP_SIZE (result);
5336   offset = 0;
5337   while (size--)
5338     {
5339       loadRegFromAop (hc08_reg_a, AOP (left), offset);
5340       accopWithAop ("eor", AOP (right), offset);
5341       storeRegToAop (hc08_reg_a, AOP (result), offset++);
5342       hc08_freeReg( hc08_reg_a);      
5343     }
5344
5345 //release:
5346   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5347   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5348   freeAsmop (result, NULL, ic, TRUE);
5349 }
5350
5351 static void
5352 emitinline (iCode * ic, char *inlin)
5353 {
5354   char buffer[512];
5355   char *symname;
5356   char c;
5357   char *bp=buffer;
5358   symbol *sym, *tempsym;
5359   asmop *aop;
5360   char *l;
5361   
5362   while (*inlin)
5363     {
5364       if (*inlin == '_')
5365         {
5366           symname = ++inlin;
5367           while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5368             inlin++;
5369           c = *inlin;
5370           *inlin = '\0';
5371           //printf("Found possible symbol '%s'\n",symname);
5372           tempsym = newSymbol (symname, ic->level);
5373           tempsym->block = ic->block;
5374           sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5375           *inlin = c;
5376           if (!sym)
5377             {
5378               *bp++ = '_';
5379               inlin = symname;
5380             }
5381           else
5382             {
5383               aop = aopForSym (ic, sym, FALSE);
5384               l = aopAdrStr (aop, aop->size - 1, TRUE);
5385               if (*l=='#')
5386                 l++;
5387               sym->isref = 1;
5388               if (sym->level && !sym->allocreq && !sym->ismyparm)
5389                 {
5390                   werror (E_ID_UNDEF, sym->name);
5391                   werror (W_CONTINUE,
5392                           "  Add 'volatile' to the variable declaration so that it\n"
5393                           "  can be referenced within inline assembly");
5394                 }
5395               //printf("Replacing with '%s'\n",l);
5396               while (*l)
5397                 {
5398                   *bp++ = *l++;
5399                   if ((2+bp-buffer)>sizeof(buffer))
5400                     goto endofline;
5401                 }
5402             }
5403         }
5404       else
5405         {
5406           *bp++ = *inlin++;
5407         }
5408       if ((2+bp-buffer)>sizeof(buffer))
5409         goto endofline;
5410     }
5411
5412 endofline:
5413   *bp = '\0';
5414
5415   if ((2+bp-buffer)>sizeof(buffer))
5416     fprintf(stderr, "Inline assembly buffer overflow\n");
5417   
5418   //printf("%s\n",buffer);
5419   emitcode (buffer,"");
5420 }
5421
5422
5423 /*-----------------------------------------------------------------*/
5424 /* genInline - write the inline code out                           */
5425 /*-----------------------------------------------------------------*/
5426 static void
5427 genInline (iCode * ic)
5428 {
5429   char *buffer, *bp, *bp1;
5430
5431   D(emitcode (";     genInline",""));
5432
5433   _G.inLine += (!options.asmpeep);
5434
5435   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5436   strcpy (buffer, IC_INLINE (ic));
5437
5438   /* emit each line as a code */
5439   while (*bp)
5440     {
5441       if (*bp == '\n')
5442         {
5443           *bp++ = '\0';
5444           /* emitcode (bp1, ""); */
5445           emitinline (ic, bp1);
5446           bp1 = bp;
5447         }
5448       else
5449         {
5450           if (*bp == ':')
5451             {
5452               bp++;
5453               *bp = '\0';
5454               bp++;
5455               emitcode (bp1, "");
5456               bp1 = bp;
5457             }
5458           else
5459             bp++;
5460         }
5461     }
5462   if (bp1 != bp)
5463     {
5464       /* emitcode (bp1, ""); */
5465       emitinline (ic, bp1);
5466     }
5467   /*     emitcode("",buffer); */
5468   _G.inLine -= (!options.asmpeep);
5469 }
5470
5471 /*-----------------------------------------------------------------*/
5472 /* genRRC - rotate right with carry                                */
5473 /*-----------------------------------------------------------------*/
5474 static void
5475 genRRC (iCode * ic)
5476 {
5477   operand *left, *result;
5478   int size, offset = 0;
5479   bool needpula = FALSE;
5480   bool resultInA = FALSE;
5481   char *shift;
5482
5483   D(emitcode (";     genRRC",""));
5484
5485   /* rotate right with carry */
5486   left = IC_LEFT (ic);
5487   result = IC_RESULT (ic);
5488   aopOp (left, ic, FALSE);
5489   aopOp (result, ic, FALSE);
5490
5491   if ((AOP_TYPE (result) == AOP_REG)
5492       && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5493    resultInA = TRUE;
5494
5495   size = AOP_SIZE (result);
5496   offset = size-1;
5497
5498   shift="lsr";
5499   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5500     {
5501       while (size--)
5502         {
5503           rmwWithAop (shift, AOP (result), offset--);
5504           shift="ror";
5505         }
5506     }
5507   else
5508     {
5509       while (size--)
5510         {
5511           loadRegFromAop (hc08_reg_a, AOP (left), offset);
5512           rmwWithReg (shift, hc08_reg_a);
5513           storeRegToAop (hc08_reg_a, AOP (result), offset--);
5514           hc08_freeReg (hc08_reg_a);
5515           shift="ror";
5516         }
5517     }
5518
5519   if ((!hc08_reg_a->isFree) || resultInA)
5520     {
5521       pushReg (hc08_reg_a, TRUE);
5522       needpula = TRUE;
5523     }
5524
5525   /* now we need to put the carry into the
5526      highest order byte of the result */
5527   offset = AOP_SIZE (result) - 1;
5528   emitcode ("clra","");
5529   emitcode ("rora","");
5530   hc08_dirtyReg (hc08_reg_a, FALSE);
5531   if (resultInA)
5532     {
5533       emitcode ("ora", "1,s");
5534       emitcode ("ais", "#1");
5535       hc08_dirtyReg (hc08_reg_a, FALSE);
5536       needpula = FALSE;
5537     }
5538   else
5539     accopWithAop ("ora", AOP (result), offset);
5540   storeRegToAop (hc08_reg_a, AOP (result), offset);
5541
5542   pullOrFreeReg (hc08_reg_a, needpula);
5543
5544   freeAsmop (left, NULL, ic, TRUE);
5545   freeAsmop (result, NULL, ic, TRUE);
5546 }
5547
5548 /*-----------------------------------------------------------------*/
5549 /* genRLC - generate code for rotate left with carry               */
5550 /*-----------------------------------------------------------------*/
5551 static void
5552 genRLC (iCode * ic)
5553 {
5554   operand *left, *result;
5555   int size, offset = 0;
5556   char *shift;
5557   bool resultInA = FALSE;
5558   bool needpula = FALSE;
5559
5560   D(emitcode (";     genRLC",""));
5561
5562   /* rotate right with carry */
5563   left = IC_LEFT (ic);
5564   result = IC_RESULT (ic);
5565   aopOp (left, ic, FALSE);
5566   aopOp (result, ic, FALSE);
5567
5568   if ((AOP_TYPE (result) == AOP_REG)
5569       && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5570    resultInA = TRUE;
5571
5572   size = AOP_SIZE (result);
5573   offset = 0;
5574
5575   shift="lsl";
5576   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5577     {
5578       while (size--)
5579         {
5580           rmwWithAop (shift, AOP (result), offset--);
5581           shift="rol";
5582         }
5583     }
5584   else
5585     {
5586       while (size--)
5587         {
5588           loadRegFromAop (hc08_reg_a, AOP (left), offset);
5589           rmwWithReg (shift, hc08_reg_a);
5590           storeRegToAop (hc08_reg_a, AOP (result), offset++);
5591           hc08_freeReg (hc08_reg_a);
5592           shift="rol";
5593         }
5594     }
5595
5596   if ((!hc08_reg_a->isFree) || resultInA)
5597     {
5598       pushReg (hc08_reg_a, TRUE);
5599       needpula = TRUE;
5600     }
5601
5602   /* now we need to put the carry into the
5603      lowest order byte of the result */
5604   offset = 0;
5605   emitcode ("clra","");
5606   emitcode ("rola","");
5607   hc08_dirtyReg (hc08_reg_a, FALSE);
5608   if (resultInA)
5609     {
5610       emitcode ("ora", "1,s");
5611       emitcode ("ais", "#1");
5612       hc08_dirtyReg (hc08_reg_a, FALSE);
5613       needpula = FALSE;
5614     }
5615   else
5616     accopWithAop ("ora", AOP (result), offset);
5617   storeRegToAop (hc08_reg_a, AOP (result), offset);
5618
5619   pullOrFreeReg (hc08_reg_a, needpula);
5620
5621   freeAsmop (left, NULL, ic, TRUE);
5622   freeAsmop (result, NULL, ic, TRUE);
5623 }
5624
5625 /*-----------------------------------------------------------------*/
5626 /* genGetHbit - generates code get highest order bit               */
5627 /*-----------------------------------------------------------------*/
5628 static void
5629 genGetHbit (iCode * ic)
5630 {
5631   operand *left, *result;
5632
5633   D(emitcode (";     genGetHbit",""));
5634
5635   left = IC_LEFT (ic);
5636   result = IC_RESULT (ic);
5637   aopOp (left, ic, FALSE);
5638   aopOp (result, ic, FALSE);
5639
5640   /* get the highest order byte into a */
5641   loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5642   emitcode ("rola", "");
5643   emitcode ("clra", "");
5644   emitcode ("rola", "");
5645   hc08_dirtyReg (hc08_reg_a, FALSE);
5646   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5647   hc08_freeReg (hc08_reg_a);
5648   
5649   freeAsmop (left, NULL, ic, TRUE);
5650   freeAsmop (result, NULL, ic, TRUE);
5651 }
5652
5653 /*-----------------------------------------------------------------*/
5654 /* genSwap - generates code to swap nibbles or bytes               */
5655 /*-----------------------------------------------------------------*/
5656 static void
5657 genSwap (iCode * ic)
5658 {
5659   operand *left, *result;
5660
5661   D(emitcode (";     genSwap",""));
5662
5663   left = IC_LEFT (ic);
5664   result = IC_RESULT (ic);
5665   aopOp (left, ic, FALSE);
5666   aopOp (result, ic, FALSE);
5667   
5668   switch (AOP_SIZE (left))
5669     {
5670     case 1: /* swap nibbles in byte */
5671       loadRegFromAop (hc08_reg_a, AOP (left), 0);
5672       emitcode ("nsa", "");
5673       hc08_dirtyReg (hc08_reg_a, FALSE);
5674       storeRegToAop (hc08_reg_a, AOP (result), 0);
5675       hc08_freeReg (hc08_reg_a);
5676       break;
5677     case 2: /* swap bytes in a word */
5678       if (operandsEqu (left, result))
5679         {
5680           loadRegFromAop (hc08_reg_a, AOP (left), 0);
5681           hc08_useReg (hc08_reg_a);
5682           transferAopAop (AOP (left), 1, AOP (result), 0);
5683           storeRegToAop (hc08_reg_a, AOP (result), 1);
5684           hc08_freeReg (hc08_reg_a);
5685         }
5686       else
5687         {
5688           transferAopAop (AOP (left), 0, AOP (result), 1);
5689           transferAopAop (AOP (left), 1, AOP (result), 0);
5690         }
5691       break;
5692     default:
5693       wassertl(FALSE, "unsupported SWAP operand size");
5694     }
5695     
5696   freeAsmop (left, NULL, ic, TRUE);
5697   freeAsmop (result, NULL, ic, TRUE);
5698 }
5699
5700 #if 0
5701 /*-----------------------------------------------------------------*/
5702 /* AccRol - rotate left accumulator by known count                 */
5703 /*-----------------------------------------------------------------*/
5704 static void
5705 AccRol (int shCount)
5706 {
5707   shCount &= 0x0007;            // shCount : 0..7
5708
5709   switch (shCount)
5710     {
5711     case 0:
5712       break;
5713     case 1:
5714       emitcode ("rola", "");    /* 1 cycle */
5715       break;
5716     case 2:
5717       emitcode ("rola", "");    /* 1 cycle */
5718       emitcode ("rola", "");    /* 1 cycle */
5719       break;
5720     case 3:
5721       emitcode ("nsa", "");
5722       emitcode ("rora", "");
5723       break;
5724     case 4:
5725       emitcode ("nsa", "");     /* 3 cycles */
5726       break;
5727     case 5:
5728       emitcode ("nsa", "");     /* 3 cycles */
5729       emitcode ("rola", "");    /* 1 cycle */
5730       break;
5731     case 6:
5732       emitcode ("nsa", "");     /* 3 cycles */
5733       emitcode ("rola", "");    /* 1 cycle */
5734       emitcode ("rola", "");    /* 1 cycle */
5735       break;
5736     case 7:
5737       emitcode ("nsa", "");     /* 3 cycles */
5738       emitcode ("rola", "");    /* 1 cycle */
5739       emitcode ("rola", "");    /* 1 cycle */
5740       emitcode ("rola", "");    /* 1 cycle */
5741       break;
5742     }
5743 }
5744 #endif
5745
5746
5747 /*-----------------------------------------------------------------*/
5748 /* AccLsh - left shift accumulator by known count                  */
5749 /*-----------------------------------------------------------------*/
5750 static void
5751 AccLsh (int shCount)
5752 {
5753   int i;
5754   
5755   shCount &= 0x0007;            // shCount : 0..7
5756
5757   /* Shift counts of 4 and 5 are currently optimized for code size.        */
5758   /* Falling through to the unrolled loop would be optimal for code speed. */
5759   /* For shift counts of 6 and 7, the unrolled loop is never optimal.      */
5760   switch (shCount)
5761     {
5762     case 4:
5763       if (optimize.codeSpeed)
5764         break;
5765       accopWithMisc ("nsa", "");
5766       accopWithMisc ("and", "#0xf0");
5767       /* total: 5 cycles, 3 bytes */
5768       return;
5769     case 5:
5770       if (optimize.codeSpeed)
5771         break;
5772       accopWithMisc ("nsa", "");
5773       accopWithMisc ("and", "#0xf0");
5774       accopWithMisc ("lsla", "");
5775       /* total: 6 cycles, 4 bytes */
5776       return;
5777     case 6:
5778       accopWithMisc ("rora", "");
5779       accopWithMisc ("rora", "");
5780       accopWithMisc ("rora", "");
5781       accopWithMisc ("and", "#0xc0");
5782       /* total: 5 cycles, 5 bytes */
5783       return;
5784     case 7:
5785       accopWithMisc ("rora", "");
5786       accopWithMisc ("clra", "");
5787       accopWithMisc ("rora", "");
5788       /* total: 3 cycles, 3 bytes */
5789       return;
5790     }
5791
5792     /* lsla is only 1 cycle and byte, so an unrolled loop is often  */
5793     /* the fastest (shCount<6) and shortest (shCount<4).            */
5794     for (i=0;i<shCount;i++)
5795       accopWithMisc ("lsla", "");
5796 }
5797
5798
5799 /*-----------------------------------------------------------------*/
5800 /* AccSRsh - signed right shift accumulator by known count         */
5801 /*-----------------------------------------------------------------*/
5802 static void
5803 AccSRsh (int shCount)
5804 {
5805   int i;
5806   
5807   shCount &= 0x0007;            // shCount : 0..7
5808
5809   if (shCount == 7)
5810     {
5811       accopWithMisc ("rola", "");
5812       accopWithMisc ("clra", "");
5813       accopWithMisc ("sbc", zero);
5814       /* total: 4 cycles, 4 bytes */
5815       return;
5816     }
5817
5818     for (i=0;i<shCount;i++)
5819       accopWithMisc ("asra", "");
5820 }
5821
5822 /*-----------------------------------------------------------------*/
5823 /* AccRsh - right shift accumulator by known count                 */
5824 /*-----------------------------------------------------------------*/
5825 static void
5826 AccRsh (int shCount, bool sign)
5827 {
5828   int i;
5829   
5830   if (sign)
5831     {
5832       AccSRsh (shCount);
5833       return;
5834     }
5835   
5836   shCount &= 0x0007;            // shCount : 0..7
5837
5838   /* Shift counts of 4 and 5 are currently optimized for code size.        */
5839   /* Falling through to the unrolled loop would be optimal for code speed. */
5840   /* For shift counts of 6 and 7, the unrolled loop is never optimal.      */
5841   switch (shCount)
5842     {
5843     case 4:
5844       if (optimize.codeSpeed)
5845         break;
5846       accopWithMisc ("nsa", "");
5847       accopWithMisc ("and", "#0x0f");
5848       /* total: 5 cycles, 3 bytes */
5849       return;
5850     case 5:
5851       if (optimize.codeSpeed)
5852         break;
5853       accopWithMisc ("nsa", "");
5854       accopWithMisc ("and", "#0x0f");
5855       accopWithMisc ("lsra", "");
5856       /* total: 6 cycles, 4 bytes */
5857       return;
5858     case 6:
5859       accopWithMisc ("rola", "");
5860       accopWithMisc ("rola", "");
5861       accopWithMisc ("rola", "");
5862       accopWithMisc ("and", "#0x03");
5863       /* total: 5 cycles, 5 bytes */
5864       return;
5865     case 7:
5866       accopWithMisc ("rola", "");
5867       accopWithMisc ("clra", "");
5868       accopWithMisc ("rola", "");
5869       /* total: 3 cycles, 3 bytes */
5870       return;
5871     }
5872
5873     /* lsra is only 1 cycle and byte, so an unrolled loop is often  */
5874     /* the fastest (shCount<6) and shortest (shCount<4).            */
5875     for (i=0;i<shCount;i++)
5876       accopWithMisc ("lsra", "");
5877 }
5878
5879
5880 /*-----------------------------------------------------------------*/
5881 /* XAccLsh - left shift register pair XA by known count            */
5882 /*-----------------------------------------------------------------*/
5883 static void
5884 XAccLsh (int shCount)
5885 {
5886   int i;
5887   
5888   shCount &= 0x000f;            // shCount : 0..15
5889
5890   if (shCount>=8)
5891     {
5892       AccLsh (shCount-8);
5893       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5894       loadRegFromConst (hc08_reg_a, zero);
5895       return;
5896     }
5897
5898   /* if we can beat 2n cycles or bytes for some special case, do it here */
5899   switch (shCount)
5900     {
5901     case 7:
5902       /*          bytes  cycles     reg x      reg a   carry
5903       **                          abcd efgh  ijkl mnop   ?
5904       **   lsrx       1  1        0abc defg  ijkl mnop   h
5905       **   rora       1  1        0abc defg  hijk lmno   p
5906       **   tax        1  1        hijk lmno  hijk lmno   p
5907       **   clra       1  1        hijk lmno  0000 0000   p
5908       **   rora       1  1        hijk lmno  p000 0000   0
5909       ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5910       */
5911       rmwWithReg ("lsr", hc08_reg_x);
5912       rmwWithReg ("ror", hc08_reg_a);
5913       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5914       loadRegFromConst (hc08_reg_a, zero);
5915       rmwWithReg ("ror", hc08_reg_a);
5916       return;
5917
5918     default:
5919       ;
5920     }
5921
5922   /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often  */
5923   /* the fastest and shortest.                                           */
5924   for (i=0;i<shCount;i++)
5925     {
5926       rmwWithReg ("lsl", hc08_reg_a);
5927       rmwWithReg ("rol", hc08_reg_x);
5928     }
5929 }
5930
5931 /*-----------------------------------------------------------------*/
5932 /* XAccSRsh - signed right shift register pair XA by known count   */
5933 /*-----------------------------------------------------------------*/
5934 static void
5935 XAccSRsh (int shCount)
5936 {
5937   int i;
5938   
5939   shCount &= 0x000f;            // shCount : 0..7
5940
5941   /* if we can beat 2n cycles or bytes for some special case, do it here */
5942   switch (shCount)
5943     {
5944     case 15:
5945       /*          bytes  cycles     reg x      reg a   carry
5946       **                          abcd efgh  ijkl mnop   ?
5947       **   lslx       1  1        bcde fgh0  ijkl mnop   a
5948       **   clra       1  1        bcde fgh0  0000 0000   a
5949       **   rola       1  1        bcde fgh0  0000 000a   0
5950       **   nega       1  1        bcde fgh0  aaaa aaaa   a
5951       **   tax        1  1        aaaa aaaa  aaaa aaaa   a
5952       ** total: 5 cycles, 5 bytes
5953       */
5954       rmwWithReg ("lsl", hc08_reg_x);
5955       loadRegFromConst (hc08_reg_a, zero);
5956       rmwWithReg ("rol", hc08_reg_a);
5957       rmwWithReg ("neg", hc08_reg_a);
5958       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5959       return;
5960
5961     case 14:
5962     case 13:
5963     case 12:
5964     case 11:
5965     case 10:
5966     case 9:
5967     case 8:
5968       /*          bytes  cycles     reg x      reg a   carry
5969       **                          abcd efgh  ijkl mnop   ?
5970       **   txa        1  1        abcd efgh  abcd efgh   ?
5971       **   (AccSRsh) <8 <8        abcd efgh  LSBresult   ?
5972       **   lsla       1  1        abcd efgh  ???? ????   a
5973       **   clrx       1  1        0000 0000  ???? ????   a
5974       **   rolx       1  1        0000 000a  ???? ????   0
5975       **   negx       1  1        aaaa aaaa  ???? ????   a
5976       **   rora       1  1        aaaa aaaa  LSBresult   0
5977       ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5978       */
5979       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5980       AccSRsh (shCount-8);
5981       rmwWithReg ("lsl", hc08_reg_a);
5982       loadRegFromConst (hc08_reg_x, zero);
5983       rmwWithReg ("rol", hc08_reg_x);
5984       rmwWithReg ("neg", hc08_reg_x);
5985       rmwWithReg ("ror", hc08_reg_a);
5986       return;
5987
5988     default:
5989       ;
5990     }
5991
5992   /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often  */
5993   /* the fastest and shortest.                                           */
5994   for (i=0;i<shCount;i++)
5995     {
5996       rmwWithReg ("asr", hc08_reg_x);
5997       rmwWithReg ("ror", hc08_reg_a);
5998     }
5999 }
6000
6001 /*-----------------------------------------------------------------*/
6002 /* XAccRsh - right shift register pair XA by known count           */
6003 /*-----------------------------------------------------------------*/
6004 static void
6005 XAccRsh (int shCount, bool sign)
6006 {
6007   int i;
6008   
6009   if (sign)
6010     {
6011       XAccSRsh (shCount);
6012       return;
6013     }
6014   
6015   shCount &= 0x000f;            // shCount : 0..f
6016
6017   /* if we can beat 2n cycles or bytes for some special case, do it here */
6018   switch (shCount)
6019     {
6020     case 15:
6021       /*          bytes  cycles     reg x      reg a   carry
6022       **                          abcd efgh  ijkl mnop   ?
6023       **   clra       1  1        abcd efgh  0000 0000   a
6024       **   lslx       1  1        bcde fgh0  0000 0000   a
6025       **   rola       1  1        bcde fgh0  0000 000a   0
6026       **   clrx       1  1        0000 0000  0000 000a   0
6027       ** total: 4 cycles, 4 bytes
6028       */
6029       loadRegFromConst (hc08_reg_x, zero);
6030       rmwWithReg ("lsl", hc08_reg_x);
6031       rmwWithReg ("rol", hc08_reg_a);
6032       loadRegFromConst (hc08_reg_a, zero);
6033       return;
6034
6035     case 14:
6036       /*          bytes  cycles     reg x      reg a   carry
6037       **                          abcd efgh  ijkl mnop   ?
6038       **   clra       1  1        abcd efgh  0000 0000   a
6039       **   lslx       1  1        bcde fgh0  0000 0000   a
6040       **   rola       1  1        bcde fgh0  0000 000a   0
6041       **   lslx       1  1        cdef gh00  0000 000a   b
6042       **   rola       1  1        cdef gh00  0000 00ab   0
6043       **   clrx       1  1        0000 0000  0000 00ab   0
6044       ** total: 6 cycles, 6 bytes
6045       */
6046       loadRegFromConst (hc08_reg_x, zero);
6047       rmwWithReg ("lsl", hc08_reg_x);
6048       rmwWithReg ("rol", hc08_reg_a);
6049       rmwWithReg ("lsl", hc08_reg_x);
6050       rmwWithReg ("rol", hc08_reg_a);
6051       loadRegFromConst (hc08_reg_a, zero);
6052       return;
6053
6054     case 13:
6055     case 12:
6056     case 11:
6057     case 10:
6058     case 9:
6059     case 8:
6060       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6061       AccRsh (shCount-8, FALSE);
6062       loadRegFromConst (hc08_reg_x, zero);
6063       return;
6064
6065     case 7:
6066       /*          bytes  cycles     reg x      reg a   carry
6067       **                          abcd efgh  ijkl mnop   ?
6068       **   lsla       1  1        abcd efgh  jklm nop0   i
6069       **   txa        1  1        abcd efgh  abcd efgh   i
6070       **   rola       1  1        abcd efgh  bcde fghi   a
6071       **   clrx       1  1        0000 0000  bcde fghi   a
6072       **   rolx       1  1        0000 000a  bcde fghi   0
6073       ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6074       */
6075       rmwWithReg ("lsl", hc08_reg_a);
6076       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6077       rmwWithReg ("rol", hc08_reg_a);
6078       loadRegFromConst (hc08_reg_x, zero);
6079       rmwWithReg ("rol", hc08_reg_x);
6080       return;
6081     case 6:
6082       /*          bytes  cycles     reg x      reg a   carry
6083       **                          abcd efgh  ijkl mnop   ?
6084       **   lsla       1  1        abcd efgh  jklm nop0   i
6085       **   rolx       1  1        bcde fghi  jklm nop0   a
6086       **   rola       1  1        bcde fghi  klmn op0a   j
6087       **   rolx       1  1        cdef ghij  klmn op0a   b
6088       **   rola       1  1        cdef ghij  lmno p0ab   k
6089       **   and #3     2  2        cdef ghij  0000 00ab   k
6090       **   psha       1  2        cdef ghij  0000 00ab   k
6091       **   txa        1  1        cdef ghij  cdef ghij   k
6092       **   pula       1  2        0000 00ab  cdef ghij   k
6093       ** total: 12 cycles, 10 bytes (beats 12 bytes)
6094       */
6095     default:
6096       ;
6097     }
6098
6099   /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often  */
6100   /* the fastest and shortest.                                           */
6101   for (i=0;i<shCount;i++)
6102     {
6103       rmwWithReg ("lsr", hc08_reg_x);
6104       rmwWithReg ("ror", hc08_reg_a);
6105     }
6106
6107 }
6108
6109
6110 #if 0
6111 /*-----------------------------------------------------------------*/
6112 /* shiftR1Left2Result - shift right one byte from left to result   */
6113 /*-----------------------------------------------------------------*/
6114 static void
6115 shiftR1Left2Result (operand * left, int offl,
6116                     operand * result, int offr,
6117                     int shCount, int sign)
6118 {
6119   loadRegFromAop (hc08_reg_a, AOP (left), offl);
6120   /* shift right accumulator */
6121   AccRsh (shCount, sign);
6122   storeRegToAop (hc08_reg_a, AOP (result), offr);
6123 }
6124 #endif
6125
6126 /*-----------------------------------------------------------------*/
6127 /* shiftL1Left2Result - shift left one byte from left to result    */
6128 /*-----------------------------------------------------------------*/
6129 static void
6130 shiftL1Left2Result (operand * left, int offl,
6131                     operand * result, int offr, int shCount)
6132 {
6133   loadRegFromAop (hc08_reg_a, AOP (left), offl);
6134   /* shift left accumulator */
6135   AccLsh (shCount);
6136   storeRegToAop (hc08_reg_a, AOP (result), offr);
6137 }
6138
6139 /*-----------------------------------------------------------------*/
6140 /* movLeft2Result - move byte from left to result                  */
6141 /*-----------------------------------------------------------------*/
6142 static void
6143 movLeft2Result (operand * left, int offl,
6144                 operand * result, int offr, int sign)
6145 {
6146   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6147     {
6148       transferAopAop (AOP (left), offl, AOP (result), offr);
6149     }
6150 }
6151
6152
6153 /*-----------------------------------------------------------------*/
6154 /* shiftL2Left2Result - shift left two bytes from left to result   */
6155 /*-----------------------------------------------------------------*/
6156 static void
6157 shiftL2Left2Result (operand * left, int offl,
6158                     operand * result, int offr, int shCount)
6159 {
6160   int i;
6161   bool needpula = FALSE;
6162   bool needpulx = FALSE;
6163
6164   if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6165     needpula = pushRegIfUsed (hc08_reg_a);
6166   else
6167     needpula = FALSE;
6168   if (!IS_AOP_XA (AOP (left)))
6169     needpulx = pushRegIfUsed (hc08_reg_x);
6170   else
6171     needpulx = FALSE;
6172
6173   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6174
6175   switch (shCount)
6176     {
6177       case 7:
6178         rmwWithReg ("lsr", hc08_reg_x);
6179         rmwWithReg ("ror", hc08_reg_a);
6180         transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6181         rmwWithReg ("clr", hc08_reg_a);
6182         rmwWithReg ("ror", hc08_reg_a);
6183         break;
6184       default:
6185         for (i=0; i<shCount; i++)
6186           {
6187             rmwWithReg ("lsl", hc08_reg_a);
6188             rmwWithReg ("rol", hc08_reg_x);
6189           }
6190     }
6191   storeRegToAop (hc08_reg_xa, AOP (result), offr);
6192
6193   pullOrFreeReg (hc08_reg_x, needpulx);
6194   pullOrFreeReg (hc08_reg_a, needpula);
6195
6196 }
6197
6198
6199 #if 0
6200 /*-----------------------------------------------------------------*/
6201 /* shiftR2Left2Result - shift right two bytes from left to result  */
6202 /*-----------------------------------------------------------------*/
6203 static void
6204 shiftR2Left2Result (operand * left, int offl,
6205                     operand * result, int offr,
6206                     int shCount, int sign)
6207 {
6208   int i;
6209   bool needpula = FALSE;
6210   bool needpulx = FALSE;
6211   
6212   needpula = pushRegIfUsed (hc08_reg_a);
6213   needpulx = pushRegIfUsed (hc08_reg_x);
6214
6215   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6216   for (i=0; i<shCount; i++)
6217     {
6218       if (sign)
6219         rmwWithReg ("asr", hc08_reg_x);
6220       else
6221         rmwWithReg ("lsr", hc08_reg_x);
6222       rmwWithReg ("ror", hc08_reg_a);
6223     }
6224   storeRegToAop (hc08_reg_xa, AOP (result), offl);
6225
6226   pullOrFreeReg (hc08_reg_x, needpulx);
6227   pullOrFreeReg (hc08_reg_a, needpula);
6228 }
6229 #endif
6230
6231 #if 0
6232 /*-----------------------------------------------------------------*/
6233 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6234 /*-----------------------------------------------------------------*/
6235 static void
6236 shiftLLeftOrResult (operand * left, int offl,
6237                     operand * result, int offr, int shCount)
6238 {
6239   loadRegFromAop (hc08_reg_a, AOP (left), offl);
6240   /* shift left accumulator */
6241   AccLsh (shCount);
6242   /* or with result */
6243   accopWithAop ("ora", AOP (result), offr);
6244   /* back to result */
6245   storeRegToAop (hc08_reg_a, AOP (result), offr);
6246   hc08_freeReg (hc08_reg_a);
6247 }
6248 #endif
6249
6250 /*-----------------------------------------------------------------*/
6251 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6252 /*-----------------------------------------------------------------*/
6253 static void
6254 shiftRLeftOrResult (operand * left, int offl,
6255                     operand * result, int offr, int shCount)
6256 {
6257   loadRegFromAop (hc08_reg_a, AOP (left), offl);
6258   /* shift left accumulator */
6259   AccRsh (shCount, FALSE);
6260   /* or with result */
6261   accopWithAop ("ora", AOP (result), offr);
6262   /* back to result */
6263   storeRegToAop (hc08_reg_a, AOP (result), offr);
6264   hc08_freeReg (hc08_reg_a);
6265 }
6266
6267 /*-----------------------------------------------------------------*/
6268 /* genlshOne - left shift a one byte quantity by known count       */
6269 /*-----------------------------------------------------------------*/
6270 static void
6271 genlshOne (operand * result, operand * left, int shCount)
6272 {
6273   D(emitcode (";     genlshOne",""));
6274
6275   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6276 }
6277
6278 /*-----------------------------------------------------------------*/
6279 /* genlshTwo - left shift two bytes by known amount != 0           */
6280 /*-----------------------------------------------------------------*/
6281 static void
6282 genlshTwo (operand * result, operand * left, int shCount)
6283 {
6284   int size;
6285
6286   D(emitcode (";     genlshTwo",""));
6287
6288   
6289   size = getDataSize (result);
6290
6291   /* if shCount >= 8 */
6292   if (shCount >= 8)
6293     {
6294       shCount -= 8;
6295
6296       if (size > 1)
6297         {
6298           loadRegFromAop (hc08_reg_a, AOP (left), 0);
6299           AccLsh (shCount);
6300           storeRegToAop (hc08_reg_a, AOP (result), 1);
6301         }
6302       storeConstToAop(zero, AOP (result), LSB);
6303     }
6304
6305   /*  1 <= shCount <= 7 */
6306   else
6307     {
6308       loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6309       XAccLsh (shCount);
6310       storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6311     }
6312 }
6313
6314 /*-----------------------------------------------------------------*/
6315 /* shiftLLong - shift left one long from left to result            */
6316 /* offr = LSB or MSB16                                             */
6317 /*-----------------------------------------------------------------*/
6318 static void
6319 shiftLLong (operand * left, operand * result, int offr)
6320 {
6321 //  char *l;
6322 //  int size = AOP_SIZE (result);
6323
6324   bool needpula = FALSE;
6325   bool needpulx = FALSE;
6326
6327   needpula = pushRegIfUsed (hc08_reg_a);
6328   needpulx = pushRegIfUsed (hc08_reg_x);
6329
6330   loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6331   rmwWithReg ("lsl", hc08_reg_a);
6332   rmwWithReg ("rol", hc08_reg_x);
6333
6334   if (offr==LSB)
6335     {
6336       storeRegToAop (hc08_reg_xa, AOP (result), offr);
6337       loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6338       rmwWithReg ("rol", hc08_reg_a);
6339       rmwWithReg ("rol", hc08_reg_x);
6340       storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6341     }
6342   else if (offr==MSB16)
6343     {
6344       storeRegToAop (hc08_reg_a, AOP (result), offr);
6345       loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6346       storeRegToAop (hc08_reg_x, AOP (result), offr+1);
6347       rmwWithReg ("rol", hc08_reg_a);
6348       storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6349       storeConstToAop (zero, AOP (result), 0);
6350     }
6351
6352   pullOrFreeReg (hc08_reg_x, needpulx);
6353   pullOrFreeReg (hc08_reg_a, needpula);
6354 }
6355
6356 /*-----------------------------------------------------------------*/
6357 /* genlshFour - shift four byte by a known amount != 0             */
6358 /*-----------------------------------------------------------------*/
6359 static void
6360 genlshFour (operand * result, operand * left, int shCount)
6361 {
6362   int size;
6363
6364   D(emitcode (";     genlshFour",""));
6365
6366   size = AOP_SIZE (result);
6367
6368   /* TODO: deal with the &result == &left case */
6369
6370   /* if shifting more that 3 bytes */
6371   if (shCount >= 24)
6372     {
6373       shCount -= 24;
6374       if (shCount)
6375         /* lowest order of left goes to the highest
6376            order of the destination */
6377         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6378       else
6379         movLeft2Result (left, LSB, result, MSB32, 0);
6380       storeConstToAop (zero, AOP (result), LSB);
6381       storeConstToAop (zero, AOP (result), MSB16);
6382       storeConstToAop (zero, AOP (result), MSB24);
6383       return;
6384     }
6385
6386   /* more than two bytes */
6387   else if (shCount >= 16)
6388     {
6389       /* lower order two bytes goes to higher order two bytes */
6390       shCount -= 16;
6391       /* if some more remaining */
6392       if (shCount)
6393         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6394       else
6395         {
6396           movLeft2Result (left, MSB16, result, MSB32, 0);
6397           movLeft2Result (left, LSB, result, MSB24, 0);
6398         }
6399       storeConstToAop (zero, AOP (result), LSB);
6400       storeConstToAop (zero, AOP (result), MSB16);
6401       return;
6402     }
6403
6404   /* if more than 1 byte */
6405   else if (shCount >= 8)
6406     {
6407       /* lower order three bytes goes to higher order  three bytes */
6408       shCount -= 8;
6409       if (size == 2)
6410         {
6411           if (shCount)
6412             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6413           else
6414             movLeft2Result (left, LSB, result, MSB16, 0);
6415         }
6416       else
6417         {                       /* size = 4 */
6418           if (shCount == 0)
6419             {
6420               movLeft2Result (left, MSB24, result, MSB32, 0);
6421               movLeft2Result (left, MSB16, result, MSB24, 0);
6422               movLeft2Result (left, LSB, result, MSB16, 0);
6423               storeConstToAop (zero, AOP (result), LSB);
6424             }
6425           else if (shCount == 1)
6426             shiftLLong (left, result, MSB16);
6427           else
6428             {
6429               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6430               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6431               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6432               storeConstToAop (zero, AOP (result), LSB);
6433             }
6434         }
6435     }
6436
6437   /* 1 <= shCount <= 7 */
6438   else if (shCount <= 2)
6439     {
6440       shiftLLong (left, result, LSB);
6441       if (shCount == 2)
6442         shiftLLong (result, result, LSB);
6443     }
6444   /* 3 <= shCount <= 7, optimize */
6445   else
6446     {
6447       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6448       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6449       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6450     }
6451 }
6452
6453 /*-----------------------------------------------------------------*/
6454 /* genLeftShiftLiteral - left shifting by known count              */
6455 /*-----------------------------------------------------------------*/
6456 static void
6457 genLeftShiftLiteral (operand * left,
6458                      operand * right,
6459                      operand * result,
6460                      iCode * ic)
6461 {
6462   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6463   int size;
6464
6465   D(emitcode (";     genLeftShiftLiteral",""));
6466
6467   freeAsmop (right, NULL, ic, TRUE);
6468
6469   aopOp (left, ic, FALSE);
6470   aopOp (result, ic, FALSE);
6471
6472 //  size = getSize (operandType (result));
6473   size = AOP_SIZE (result);
6474
6475 #if VIEW_SIZE
6476   D(emitcode ("; shift left ", "result %d, left %d", size,
6477             AOP_SIZE (left)));
6478 #endif
6479
6480   if (shCount == 0)
6481     {
6482       while (size--)
6483         transferAopAop( AOP(left), size, AOP(result), size);
6484     }
6485   else if (shCount >= (size * 8))
6486     {
6487       while (size--)
6488         storeConstToAop (zero, AOP (result), size);
6489     }
6490   else
6491     {
6492       switch (size)
6493         {
6494         case 1:
6495           genlshOne (result, left, shCount);
6496           break;
6497
6498         case 2:
6499           genlshTwo (result, left, shCount);
6500           break;
6501
6502         case 4:
6503           genlshFour (result, left, shCount);
6504           break;
6505         default:
6506           werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
6507                   "*** ack! mystery literal shift!\n");
6508           break;
6509         }
6510     }
6511   freeAsmop (left, NULL, ic, TRUE);
6512   freeAsmop (result, NULL, ic, TRUE);
6513 }
6514
6515 /*-----------------------------------------------------------------*/
6516 /* genLeftShift - generates code for left shifting                 */
6517 /*-----------------------------------------------------------------*/
6518 static void
6519 genLeftShift (iCode * ic)
6520 {
6521   operand *left, *right, *result;
6522   int size, offset;
6523   symbol *tlbl, *tlbl1;
6524   char *shift;
6525
6526   D(emitcode (";     genLeftShift",""));
6527
6528   right = IC_RIGHT (ic);
6529   left = IC_LEFT (ic);
6530   result = IC_RESULT (ic);
6531
6532   aopOp (right, ic, FALSE);
6533
6534   /* if the shift count is known then do it
6535      as efficiently as possible */
6536   if (AOP_TYPE (right) == AOP_LIT)
6537     {
6538       genLeftShiftLiteral (left, right, result, ic);
6539       return;
6540     }
6541
6542   /* shift count is unknown then we have to form
6543      a loop get the loop count in A : Note: we take
6544      only the lower order byte since shifting
6545      more that 32 bits make no sense anyway, ( the
6546      largest size of an object can be only 32 bits ) */
6547
6548   aopOp (result, ic, FALSE);
6549   aopOp (left, ic, FALSE);
6550
6551   if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6552     AOP (result) = forceStackedAop (AOP (result));
6553
6554   /* now move the left to the result if they are not the
6555      same */
6556   if (!sameRegs (AOP (left), AOP (result)))
6557     {
6558       size = AOP_SIZE (result);
6559       offset = 0;
6560       while (size--)
6561         {
6562           transferAopAop (AOP (left), offset, AOP (result), offset);
6563           offset++;
6564         }
6565     }
6566   freeAsmop (left, NULL, ic, TRUE);
6567   
6568   tlbl = newiTempLabel (NULL);
6569   size = AOP_SIZE (result);
6570   offset = 0;
6571   tlbl1 = newiTempLabel (NULL);
6572
6573   loadRegFromAop (hc08_reg_x, AOP (right), 0);
6574   emitcode ("tstx", "");
6575   emitBranch ("beq", tlbl1);
6576   emitLabel (tlbl);
6577   
6578   shift="lsl";
6579   for (offset=0;offset<size;offset++)
6580     {
6581       rmwWithAop (shift, AOP (result), offset);  
6582       shift="rol";
6583     }
6584   rmwWithReg ("dec", hc08_reg_x);
6585   emitBranch ("bne", tlbl);
6586   emitLabel (tlbl1);
6587   hc08_freeReg (hc08_reg_x);
6588   
6589   freeAsmop (result, NULL, ic, TRUE);
6590   freeAsmop (right, NULL, ic, TRUE);
6591 }
6592
6593 /*-----------------------------------------------------------------*/
6594 /* genrshOne - right shift a one byte quantity by known count      */
6595 /*-----------------------------------------------------------------*/
6596 static void
6597 genrshOne (operand * result, operand * left,
6598            int shCount, int sign)
6599 {
6600   D(emitcode (";     genrshOne",""));
6601
6602   loadRegFromAop (hc08_reg_a, AOP (left), 0);
6603   AccRsh (shCount, sign);
6604   storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6605 }
6606
6607 /*-----------------------------------------------------------------*/
6608 /* genrshTwo - right shift two bytes by known amount != 0          */
6609 /*-----------------------------------------------------------------*/
6610 static void
6611 genrshTwo (operand * result, operand * left,
6612            int shCount, int sign)
6613 {
6614   D(emitcode (";     genrshTwo",""));
6615
6616   /* if shCount >= 8 */
6617   if (shCount >= 8)
6618     {
6619       if (shCount || sign)
6620         {
6621           loadRegFromAop (hc08_reg_a, AOP (left), 1);
6622           AccRsh (shCount-8, sign);
6623           storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6624         }
6625       else
6626         {
6627           transferAopAop (AOP (left), 1, AOP (result), 0);
6628           storeConstToAop (zero, AOP (result), 1);
6629         }
6630     }
6631
6632   /*  1 <= shCount <= 7 */
6633   else
6634     {
6635       loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6636       XAccRsh (shCount, sign);
6637       storeRegToAop (hc08_reg_xa, AOP (result), 0);
6638     }
6639 }
6640
6641 /*-----------------------------------------------------------------*/
6642 /* shiftRLong - shift right one long from left to result           */
6643 /* offl = LSB or MSB16                                             */
6644 /*-----------------------------------------------------------------*/
6645 static void
6646 shiftRLong (operand * left, int offl,
6647             operand * result, int sign)
6648 {
6649 //  char *l;
6650  // int size = AOP_SIZE (result);
6651
6652   bool needpula = FALSE;
6653   bool needpulx = FALSE;
6654
6655   needpula = pushRegIfUsed (hc08_reg_a);
6656   needpulx = pushRegIfUsed (hc08_reg_x);
6657
6658   if (offl==LSB)
6659     {
6660       loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6661       if (sign)
6662         rmwWithReg ("asr", hc08_reg_x);
6663       else
6664         rmwWithReg ("lsr", hc08_reg_x);
6665       rmwWithReg ("ror", hc08_reg_a);
6666       storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6667       loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6668     }
6669   else if (offl==MSB16)
6670     {
6671       loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6672       if (sign)
6673         rmwWithReg ("asr", hc08_reg_a);
6674       else
6675         rmwWithReg ("lsr", hc08_reg_a);
6676       loadRegFromAop (hc08_reg_x, AOP (left), MSB24);
6677       storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6678       loadRegFromAop (hc08_reg_a, AOP (left), MSB16);
6679     }
6680
6681   rmwWithReg ("ror", hc08_reg_x);
6682   rmwWithReg ("ror", hc08_reg_a);
6683   storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6684
6685   if (offl==MSB16)
6686     {
6687       if (sign)
6688         {
6689           loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6690           storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6691         }
6692       else
6693         {
6694           storeConstToAop (zero, AOP (result), MSB32);
6695         }
6696     }
6697
6698   pullOrFreeReg (hc08_reg_x, needpulx);
6699   pullOrFreeReg (hc08_reg_a, needpula);
6700 }
6701
6702 /*-----------------------------------------------------------------*/
6703 /* genrshFour - shift four byte by a known amount != 0             */
6704 /*-----------------------------------------------------------------*/
6705 static void
6706 genrshFour (operand * result, operand * left,
6707             int shCount, int sign)
6708 {
6709   /* TODO: handle cases where left == result */
6710   
6711   D(emitcode (";     genrshFour",""));
6712
6713   /* if shifting more that 3 bytes */
6714   if (shCount >= 24)
6715     {
6716       loadRegFromAop (hc08_reg_a, AOP (left), 3);
6717       AccRsh (shCount-24, sign);
6718       storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6719       return;
6720     }
6721   else if (shCount >= 16)
6722     {
6723       loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6724       XAccRsh (shCount-16, sign);
6725       storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6726       return;
6727     }
6728   else if (shCount >= 8)
6729     {
6730       if (shCount == 1)
6731         shiftRLong (left, MSB16, result, sign);
6732       else if (shCount == 8)
6733         {
6734           transferAopAop (AOP (left), 1, AOP (result), 0);
6735           transferAopAop (AOP (left), 2, AOP (result), 1);
6736           loadRegFromAop (hc08_reg_a, AOP (left), 3);
6737           storeRegToAop (hc08_reg_a, AOP (result), 2);
6738           storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6739         }
6740       else if (shCount == 9)
6741         {
6742           shiftRLong (left, MSB16, result, sign);
6743         }
6744       else
6745         {
6746           loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6747           XAccRsh (shCount-8, FALSE);
6748           storeRegToAop (hc08_reg_xa, AOP (result), 0);
6749           loadRegFromAop (hc08_reg_x, AOP (left), 3);
6750           loadRegFromConst (hc08_reg_a, zero);
6751           XAccRsh (shCount-8, sign);
6752           accopWithAop ("ora", AOP (result), 1);
6753           storeRegToAop (hc08_reg_xa, AOP (result), 1);
6754           storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6755         }
6756     }
6757   else
6758     {                           /* 1 <= shCount <= 7 */
6759       if (shCount == 1)
6760         {
6761           shiftRLong (left, LSB, result, sign);
6762         }
6763       else
6764         {
6765           loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6766           XAccRsh (shCount, FALSE);
6767           storeRegToAop (hc08_reg_xa, AOP (result), 0);
6768           loadRegFromAop (hc08_reg_a, AOP (left), 2);
6769           AccLsh (8-shCount);
6770           accopWithAop ("ora", AOP (result), 1);
6771           storeRegToAop (hc08_reg_a, AOP (result), 1);
6772           loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6773           XAccRsh (shCount, sign);
6774           storeRegToAop (hc08_reg_xa, AOP (result), 2);
6775         }
6776     }
6777 }
6778
6779 /*-----------------------------------------------------------------*/
6780 /* genRightShiftLiteral - right shifting by known count            */
6781 /*-----------------------------------------------------------------*/
6782 static void
6783 genRightShiftLiteral (operand * left,
6784                       operand * right,
6785                       operand * result,
6786                       iCode * ic,
6787                       int sign)
6788 {
6789   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6790   int size;
6791
6792   D(emitcode (";     genRightShiftLiteral",""));
6793
6794   freeAsmop (right, NULL, ic, TRUE);
6795
6796   aopOp (left, ic, FALSE);
6797   aopOp (result, ic, FALSE);
6798
6799 #if VIEW_SIZE
6800   D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6801             AOP_SIZE (left)));
6802 #endif
6803
6804   size = getDataSize (left);
6805   /* test the LEFT size !!! */
6806
6807   /* I suppose that the left size >= result size */
6808   if (shCount == 0)
6809     {
6810       size = getDataSize (result);
6811       while (size--)
6812         transferAopAop (AOP (left), size, AOP(result), size);
6813     }
6814   else if (shCount >= (size * 8))
6815     {
6816       if (sign) {
6817         /* get sign in acc.7 */
6818         loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6819       }
6820       addSign (result, LSB, sign);
6821     }
6822   else
6823     {
6824       switch (size)
6825         {
6826         case 1:
6827           genrshOne (result, left, shCount, sign);
6828           break;
6829
6830         case 2:
6831           genrshTwo (result, left, shCount, sign);
6832           break;
6833
6834         case 4:
6835           genrshFour (result, left, shCount, sign);
6836           break;
6837         default:
6838           break;
6839         }
6840     }
6841   freeAsmop (left, NULL, ic, TRUE);
6842   freeAsmop (result, NULL, ic, TRUE);
6843 }
6844
6845
6846 /*-----------------------------------------------------------------*/
6847 /* genRightShift - generate code for right shifting                */
6848 /*-----------------------------------------------------------------*/
6849 static void
6850 genRightShift (iCode * ic)
6851 {
6852   operand *right, *left, *result;
6853   sym_link *retype;
6854   int size, offset;
6855   symbol *tlbl, *tlbl1;
6856   char *shift;
6857   bool sign;
6858   
6859   D(emitcode (";     genRightShift",""));
6860
6861   /* if signed then we do it the hard way preserve the
6862      sign bit moving it inwards */
6863   retype = getSpec (operandType (IC_RESULT (ic)));
6864   sign = !SPEC_USIGN (retype);
6865
6866   /* signed & unsigned types are treated the same : i.e. the
6867      signed is NOT propagated inwards : quoting from the
6868      ANSI - standard : "for E1 >> E2, is equivalent to division
6869      by 2**E2 if unsigned or if it has a non-negative value,
6870      otherwise the result is implementation defined ", MY definition
6871      is that the sign does not get propagated */
6872
6873   right = IC_RIGHT (ic);
6874   left = IC_LEFT (ic);
6875   result = IC_RESULT (ic);
6876
6877   aopOp (right, ic, FALSE);
6878
6879   /* if the shift count is known then do it
6880      as efficiently as possible */
6881   if (AOP_TYPE (right) == AOP_LIT)
6882     {
6883       genRightShiftLiteral (left, right, result, ic, sign);
6884       return;
6885     }
6886
6887   /* shift count is unknown then we have to form
6888      a loop get the loop count in X : Note: we take
6889      only the lower order byte since shifting
6890      more that 32 bits make no sense anyway, ( the
6891      largest size of an object can be only 32 bits ) */
6892
6893   aopOp (result, ic, FALSE);
6894   aopOp (left, ic, FALSE);
6895
6896   if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6897     AOP (result) = forceStackedAop (AOP (result));
6898   
6899   /* now move the left to the result if they are not the
6900      same */
6901   if (!sameRegs (AOP (left), AOP (result)))
6902     {
6903       size = AOP_SIZE (result); 
6904       offset = 0;
6905       while (size--)
6906         {
6907           transferAopAop (AOP (left), offset, AOP (result), offset);
6908           offset++;
6909         }
6910     }
6911   freeAsmop (left, NULL, ic, TRUE);
6912   
6913   tlbl = newiTempLabel (NULL);
6914   size = AOP_SIZE (result);
6915   offset = 0;
6916   tlbl1 = newiTempLabel (NULL);
6917
6918   loadRegFromAop (hc08_reg_x, AOP (right), 0);
6919   emitcode ("tstx", "");
6920   emitBranch ("beq", tlbl1);
6921   emitLabel (tlbl);
6922
6923   shift= sign ? "asr" : "lsr";
6924   for (offset=size-1;offset>=0;offset--)
6925     {
6926       rmwWithAop (shift, AOP (result), offset);
6927       shift="ror";
6928     }
6929   rmwWithReg ("dec", hc08_reg_x);
6930   emitBranch ("bne", tlbl);
6931   emitLabel (tlbl1);
6932   hc08_freeReg (hc08_reg_x);
6933   
6934   freeAsmop (result, NULL, ic, TRUE);
6935   freeAsmop (right, NULL, ic, TRUE);
6936 }
6937
6938
6939 /*-----------------------------------------------------------------*/
6940 /* genUnpackBits - generates code for unpacking bits               */
6941 /*-----------------------------------------------------------------*/
6942 static void
6943 genUnpackBits (operand * result, iCode *ifx)
6944 {
6945   int offset = 0;       /* result byte offset */
6946   int rsize;            /* result size */
6947   int rlen = 0;         /* remaining bitfield length */
6948   sym_link *etype;      /* bitfield type information */
6949   int blen;             /* bitfield length */
6950   int bstr;             /* bitfield starting bit within byte */
6951
6952   D(emitcode (";     genUnpackBits",""));
6953
6954   etype = getSpec (operandType (result));
6955   rsize = getSize (operandType (result));
6956   blen = SPEC_BLEN (etype);
6957   bstr = SPEC_BSTR (etype);
6958
6959   if (ifx && blen <= 8)
6960     {
6961       emitcode ("lda", ",x");
6962       hc08_dirtyReg (hc08_reg_a, FALSE);
6963       if (blen < 8)
6964         {
6965           emitcode ("and", "#0x%02x",
6966                     (((unsigned char) -1) >> (8 - blen)) << bstr);
6967         }
6968       genIfxJump (ifx, "a");
6969       return;
6970     }
6971   wassert (!ifx);
6972
6973   /* If the bitfield length is less than a byte */
6974   if (blen < 8)
6975     {
6976       emitcode ("lda", ",x");
6977       hc08_dirtyReg (hc08_reg_a, FALSE);
6978       AccRsh (bstr, FALSE);
6979       emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6980       if (!SPEC_USIGN (etype))
6981         {
6982           /* signed bitfield */
6983           symbol *tlbl = newiTempLabel (NULL);
6984
6985           emitcode ("bit", "#0x%02x", 1<<(blen - 1));
6986           emitcode ("beq", "%05d$", tlbl->key + 100);
6987           emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
6988           emitLabel (tlbl);
6989         }
6990       storeRegToAop (hc08_reg_a, AOP (result), offset++);
6991       goto finish;
6992     }
6993
6994   /* Bit field did not fit in a byte. Copy all
6995      but the partial byte at the end.  */
6996   for (rlen=blen;rlen>=8;rlen-=8)
6997     {
6998       emitcode ("lda", ",x");
6999       hc08_dirtyReg (hc08_reg_a, FALSE);
7000       storeRegToAop (hc08_reg_a, AOP (result), offset);
7001       offset++;
7002       if (rlen>8)
7003         emitcode ("aix", "#1");
7004     }
7005
7006   /* Handle the partial byte at the end */
7007   if (rlen)
7008     {
7009       emitcode ("lda", ",x");
7010       emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7011       if (!SPEC_USIGN (etype))
7012         {
7013           /* signed bitfield */
7014           symbol *tlbl = newiTempLabel (NULL);
7015
7016           emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7017           emitcode ("beq", "%05d$", tlbl->key + 100);
7018           emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7019           emitLabel (tlbl);
7020         }
7021       storeRegToAop (hc08_reg_a, AOP (result), offset++);
7022     }
7023
7024 finish:
7025   if (offset < rsize)
7026     {
7027       rsize -= offset;
7028       if (SPEC_USIGN (etype))
7029         {
7030           while (rsize--)
7031             storeConstToAop (zero, AOP (result), offset++);
7032         }
7033       else
7034         {
7035           /* signed bitfield: sign extension with 0x00 or 0xff */
7036           emitcode ("rola", "");
7037           emitcode ("clra", "");
7038           emitcode ("sbc", zero);
7039   
7040           while (rsize--)
7041             storeRegToAop (hc08_reg_a, AOP (result), offset++);
7042         }
7043     }
7044 }
7045
7046
7047 /*-----------------------------------------------------------------*/
7048 /* genUnpackBitsImmed - generates code for unpacking bits          */
7049 /*-----------------------------------------------------------------*/
7050 static void
7051 genUnpackBitsImmed (operand * left,
7052                     operand * result,
7053                     iCode *ic,
7054                     iCode *ifx)
7055 {
7056   int size;
7057   int offset = 0;       /* result byte offset */
7058   int rsize;            /* result size */
7059   int rlen = 0;         /* remaining bitfield length */
7060   sym_link *etype;      /* bitfield type information */
7061   int blen;             /* bitfield length */
7062   int bstr;             /* bitfield starting bit within byte */
7063   asmop *derefaop;
7064   
7065   D(emitcode (";     genUnpackBitsImmed",""));
7066
7067   aopOp (result, ic, TRUE);
7068   size = AOP_SIZE (result);
7069
7070   derefaop = aopDerefAop (AOP (left));
7071   freeAsmop (left, NULL, ic, TRUE);
7072   derefaop->size = size;
7073   
7074   etype = getSpec (operandType (result));
7075   rsize = getSize (operandType (result));
7076   blen = SPEC_BLEN (etype);
7077   bstr = SPEC_BSTR (etype);
7078
7079   /* if the bitfield is a single bit in the direct page */
7080   if (blen == 1 && derefaop->type == AOP_DIR)
7081     {
7082       if (!ifx && bstr)
7083         {
7084           symbol *tlbl = newiTempLabel (NULL);
7085           
7086           loadRegFromConst (hc08_reg_a, zero);
7087           emitcode ("brclr", "#%d,%s,%05d$",
7088                     bstr, aopAdrStr (derefaop, 0, FALSE),
7089                     (tlbl->key + 100));
7090           if (SPEC_USIGN (etype))
7091             rmwWithReg ("inc", hc08_reg_a);
7092           else
7093             rmwWithReg ("dec", hc08_reg_a);
7094           emitLabel (tlbl);
7095           storeRegToAop (hc08_reg_a, AOP (result), offset);
7096           hc08_freeReg (hc08_reg_a);
7097           offset++;
7098           goto finish;
7099         }
7100       else if (ifx)
7101         {
7102           symbol *tlbl = newiTempLabel (NULL);
7103           symbol *jlbl;
7104           char * inst;
7105           
7106           if (IC_TRUE (ifx))
7107             {
7108               jlbl = IC_TRUE (ifx);
7109               inst = "brclr";
7110             }
7111           else
7112             {
7113               jlbl = IC_FALSE (ifx);
7114               inst = "brset";
7115             }
7116           emitcode (inst, "#%d,%s,%05d$",
7117                     bstr, aopAdrStr (derefaop, 0, FALSE),
7118                     (tlbl->key + 100));
7119           emitBranch ("jmp", jlbl);
7120           emitLabel (tlbl);
7121           ifx->generated = 1;
7122           offset++;
7123           goto finish;
7124         }
7125     }
7126
7127   /* If the bitfield length is less than a byte */
7128   if (blen < 8)
7129     {
7130       loadRegFromAop (hc08_reg_a, derefaop, 0);
7131       if (!ifx)
7132         {
7133           AccRsh (bstr, FALSE);
7134           emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7135           hc08_dirtyReg (hc08_reg_a, FALSE);
7136           if (!SPEC_USIGN (etype))
7137             {
7138               /* signed bitfield */
7139               symbol *tlbl = newiTempLabel (NULL);
7140
7141               emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7142               emitcode ("beq", "%05d$", tlbl->key + 100);
7143               emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7144               emitLabel (tlbl);
7145             }
7146           storeRegToAop (hc08_reg_a, AOP (result), offset);
7147         }
7148       else
7149         {
7150           emitcode ("and", "#0x%02x",
7151                     (((unsigned char) -1) >> (8 - blen)) << bstr);
7152           hc08_dirtyReg (hc08_reg_a, FALSE);
7153         }
7154       offset++;
7155       goto finish;
7156     }
7157
7158   /* Bit field did not fit in a byte. Copy all
7159      but the partial byte at the end.  */
7160   for (rlen=blen;rlen>=8;rlen-=8)
7161     {
7162       loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7163       if (!ifx)
7164         storeRegToAop (hc08_reg_a, AOP (result), offset);
7165       else
7166         emitcode ("tsta", "");
7167       offset++;
7168     }
7169
7170   /* Handle the partial byte at the end */
7171   if (rlen)
7172     {
7173       loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7174       emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7175       if (!SPEC_USIGN (etype))
7176         {
7177           /* signed bitfield */
7178           symbol *tlbl = newiTempLabel (NULL);
7179
7180           emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7181           emitcode ("beq", "%05d$", tlbl->key + 100);
7182           emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7183           emitLabel (tlbl);
7184         }
7185       storeRegToAop (hc08_reg_a, AOP (result), offset++);
7186     }
7187
7188 finish:
7189   if (offset < rsize)
7190     {
7191       rsize -= offset;
7192       if (SPEC_USIGN (etype))
7193         {
7194           while (rsize--)
7195             storeConstToAop (zero, AOP (result), offset++);
7196         }
7197       else
7198         {
7199           /* signed bitfield: sign extension with 0x00 or 0xff */
7200           emitcode ("rola", "");
7201           emitcode ("clra", "");
7202           emitcode ("sbc", zero);
7203
7204           while (rsize--)
7205             storeRegToAop (hc08_reg_a, AOP (result), offset++);
7206         }
7207     }
7208   
7209   freeAsmop (NULL, derefaop, ic, TRUE);
7210   freeAsmop (result, NULL, ic, TRUE);
7211   
7212   if (ifx && !ifx->generated)
7213     {
7214       genIfxJump (ifx, "a");
7215     }
7216 }
7217
7218
7219 /*-----------------------------------------------------------------*/
7220 /* genDataPointerGet - generates code when ptr offset is known     */
7221 /*-----------------------------------------------------------------*/
7222 static void
7223 genDataPointerGet (operand * left,
7224                    operand * result,
7225                    iCode * ic,
7226                    iCode * ifx)
7227 {
7228   int size;
7229   asmop *derefaop;
7230   
7231   D(emitcode (";     genDataPointerGet",""));
7232
7233   aopOp (result, ic, TRUE);
7234   size = AOP_SIZE (result);
7235
7236   derefaop = aopDerefAop (AOP (left));
7237   freeAsmop (left, NULL, ic, TRUE);
7238   derefaop->size = size;
7239   
7240   while (size--)
7241     {
7242       if (!ifx)
7243         transferAopAop (derefaop, size, AOP (result), size);
7244       else
7245         loadRegFromAop (hc08_reg_a, derefaop, size);
7246     }
7247
7248   freeAsmop (NULL, derefaop, ic, TRUE);
7249   freeAsmop (result, NULL, ic, TRUE);
7250   
7251   if (ifx && !ifx->generated)
7252     {
7253       genIfxJump (ifx, "a");
7254     }
7255 }
7256
7257
7258 /*-----------------------------------------------------------------*/
7259 /* genPointerGet - generate code for pointer get                   */
7260 /*-----------------------------------------------------------------*/
7261 static void
7262 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7263 {
7264   operand *left = IC_LEFT (ic);
7265   operand *result = IC_RESULT (ic);
7266   int size, offset;
7267   sym_link *retype = getSpec (operandType (result));
7268
7269   D(emitcode (";     genPointerGet",""));
7270
7271   if (getSize (operandType (result))>1)
7272     ifx = NULL;
7273   
7274   aopOp (left, ic, FALSE);
7275
7276   /* if left is rematerialisable and
7277      result is not bit variable type */
7278   if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7279     {
7280       if (!IS_BITVAR (retype))
7281         {
7282           genDataPointerGet (left, result, ic, ifx);
7283           return;
7284         }
7285       else
7286         {
7287           genUnpackBitsImmed (left, result, ic, ifx);
7288           return;
7289         }
7290     }
7291
7292   /* if the operand is already in hx
7293      then we do nothing else we move the value to hx */
7294   if (AOP_TYPE (left) != AOP_STR)
7295     {
7296       /* if this is remateriazable */
7297       loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7298     }
7299
7300   /* so hx now contains the address */
7301   aopOp (result, ic, FALSE);
7302
7303   /* if bit then unpack */
7304   if (IS_BITVAR (retype))
7305     genUnpackBits (result, ifx);
7306   else
7307     {
7308       size = AOP_SIZE (result);
7309       offset = size-1;
7310
7311       while (size--)
7312         {
7313           accopWithMisc ("lda", ",x");
7314           if (size || pi)
7315             {
7316               emitcode ("aix", "#1");
7317               hc08_dirtyReg (hc08_reg_hx, FALSE);
7318             }
7319           if (!ifx)
7320             storeRegToAop (hc08_reg_a, AOP (result), offset);
7321           offset--;
7322           hc08_freeReg (hc08_reg_a);
7323         }
7324     }
7325
7326   freeAsmop (left, NULL, ic, TRUE);
7327   freeAsmop (result, NULL, ic, TRUE);
7328   
7329   if (pi) {
7330     aopOp (IC_RESULT (pi), pi, FALSE);
7331     storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7332     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7333     pi->generated = 1;
7334   }
7335   
7336   if (ifx && !ifx->generated)
7337     {
7338       genIfxJump (ifx, "a");
7339     }
7340
7341   hc08_freeReg (hc08_reg_hx);
7342   
7343 }
7344
7345 /*-----------------------------------------------------------------*/
7346 /* genPackBits - generates code for packed bit storage             */
7347 /*-----------------------------------------------------------------*/
7348 static void
7349 genPackBits (sym_link * etype,
7350              operand * right)
7351 {
7352   int offset = 0;       /* source byte offset */
7353   int rlen = 0;         /* remaining bitfield length */
7354   int blen;             /* bitfield length */
7355   int bstr;             /* bitfield starting bit within byte */
7356   int litval;           /* source literal value (if AOP_LIT) */
7357   unsigned char mask;   /* bitmask within current byte */
7358   int xoffset = 0;
7359
7360   D(emitcode (";     genPackBits",""));
7361
7362   blen = SPEC_BLEN (etype);
7363   bstr = SPEC_BSTR (etype);
7364
7365   /* If the bitfield length is less than a byte */
7366   if (blen < 8)
7367     {
7368       mask = ((unsigned char) (0xFF << (blen + bstr)) |
7369               (unsigned char) (0xFF >> (8 - bstr)));
7370
7371       if (AOP_TYPE (right) == AOP_LIT)
7372         {
7373           /* Case with a bitfield length <8 and literal source
7374           */
7375           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7376           litval <<= bstr;
7377           litval &= (~mask) & 0xff;
7378
7379           emitcode ("lda", ",x");
7380           if ((mask|litval)!=0xff)
7381             emitcode ("and","#0x%02x", mask);
7382           if (litval)
7383             emitcode ("ora","#0x%02x", litval);
7384           hc08_dirtyReg (hc08_reg_a, FALSE);
7385           emitcode ("sta", ",x");
7386           
7387           hc08_freeReg (hc08_reg_a);
7388           return;
7389         }
7390           
7391       /* Case with a bitfield length < 8 and arbitrary source
7392       */
7393       loadRegFromAop (hc08_reg_a, AOP (right), 0);
7394       /* shift and mask source value */
7395       AccLsh (bstr);
7396       emitcode ("and", "#0x%02x", (~mask) & 0xff);
7397       hc08_dirtyReg (hc08_reg_a, FALSE);
7398       pushReg (hc08_reg_a, TRUE);
7399
7400       emitcode ("lda", ",x");
7401       emitcode ("and", "#0x%02x", mask);
7402       emitcode ("ora", "1,s");
7403       emitcode ("sta", ",x");
7404       pullReg (hc08_reg_a);
7405      
7406       hc08_freeReg (hc08_reg_a);
7407       return;
7408     }
7409
7410   /* Bit length is greater than 7 bits. In this case, copy  */
7411   /* all except the partial byte at the end                 */
7412   for (rlen=blen;rlen>=8;rlen-=8)
7413     {
7414       if (AOP (right)->type == AOP_DIR)
7415         {
7416           emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7417           xoffset++;
7418         }
7419       else
7420         {
7421           loadRegFromAop (hc08_reg_a, AOP (right), offset);
7422           emitcode ("sta", "%d,x", offset);
7423         }
7424       offset++;
7425     }
7426
7427   /* If there was a partial byte at the end */
7428   if (rlen)
7429     {
7430       mask = (((unsigned char) -1 << rlen) & 0xff);
7431       
7432       if (AOP_TYPE (right) == AOP_LIT)
7433         {
7434           /* Case with partial byte and literal source
7435           */
7436           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7437           litval >>= (blen-rlen);
7438           litval &= (~mask) & 0xff;
7439           emitcode ("lda", "%d,x", offset - xoffset);
7440           hc08_dirtyReg (hc08_reg_a, FALSE);
7441           if ((mask|litval)!=0xff)
7442             emitcode ("and","#0x%02x", mask);
7443           if (litval)
7444             emitcode ("ora","#0x%02x", litval);
7445           emitcode ("sta", "%d,x", offset - xoffset);
7446           hc08_dirtyReg (hc08_reg_a, FALSE);
7447           hc08_freeReg (hc08_reg_a);
7448           return;
7449         }
7450       
7451       /* Case with partial byte and arbitrary source
7452       */
7453       loadRegFromAop (hc08_reg_a, AOP (right), offset);
7454       emitcode ("and", "#0x%02x", (~mask) & 0xff);
7455       hc08_dirtyReg (hc08_reg_a, FALSE);
7456       pushReg (hc08_reg_a, TRUE);
7457
7458       emitcode ("lda", "%d,x", offset - xoffset);
7459       emitcode ("and", "#0x%02x", mask);
7460       emitcode ("ora", "1,s");
7461       emitcode ("sta", "%d,x", offset - xoffset);
7462       pullReg (hc08_reg_a);
7463     }
7464
7465   hc08_freeReg (hc08_reg_a);
7466 }
7467
7468 /*-----------------------------------------------------------------*/
7469 /* genPackBitsImmed - generates code for packed bit storage        */
7470 /*-----------------------------------------------------------------*/
7471 static void
7472 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7473 {
7474   asmop *derefaop;
7475   int size;
7476   int offset = 0;       /* source byte offset */
7477   int rlen = 0;         /* remaining bitfield length */
7478   int blen;             /* bitfield length */
7479   int bstr;             /* bitfield starting bit within byte */
7480   int litval;           /* source literal value (if AOP_LIT) */
7481   unsigned char mask;   /* bitmask within current byte */
7482
7483   D(emitcode (";     genPackBitsImmed",""));
7484
7485   blen = SPEC_BLEN (etype);
7486   bstr = SPEC_BSTR (etype);
7487
7488   aopOp (right, ic, FALSE);
7489   size = AOP_SIZE (right);
7490
7491   derefaop = aopDerefAop (AOP (result));
7492   freeAsmop (result, NULL, ic, TRUE);
7493   derefaop->size = size;
7494
7495   /* if the bitfield is a single bit in the direct page */
7496   if (blen == 1 && derefaop->type == AOP_DIR)
7497     {
7498       if (AOP_TYPE (right) == AOP_LIT)
7499         {
7500           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7501       
7502           emitcode ((litval & 1) ? "bset" : "bclr", 
7503                     "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7504         }
7505       else
7506         {
7507           symbol *tlbl1 = newiTempLabel (NULL);
7508           symbol *tlbl2 = newiTempLabel (NULL);
7509           
7510           loadRegFromAop (hc08_reg_a, AOP (right), 0);
7511           emitcode ("bit", "#1");
7512           emitBranch ("bne", tlbl1);
7513           emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7514           emitBranch ("bra", tlbl2);
7515           emitLabel (tlbl1);
7516           emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7517           emitLabel (tlbl2);
7518           hc08_freeReg (hc08_reg_a);
7519         }
7520       goto release;
7521     }
7522     
7523   /* If the bitfield length is less than a byte */
7524   if (blen < 8)
7525     {
7526       mask = ((unsigned char) (0xFF << (blen + bstr)) |
7527               (unsigned char) (0xFF >> (8 - bstr)));
7528
7529       if (AOP_TYPE (right) == AOP_LIT)
7530         {
7531           /* Case with a bitfield length <8 and literal source
7532           */
7533           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7534           litval <<= bstr;
7535           litval &= (~mask) & 0xff;
7536
7537           loadRegFromAop (hc08_reg_a, derefaop, 0);
7538           if ((mask|litval)!=0xff)
7539             emitcode ("and","#0x%02x", mask);
7540           if (litval)
7541             emitcode ("ora","#0x%02x", litval);
7542           hc08_dirtyReg (hc08_reg_a, FALSE);
7543           storeRegToAop (hc08_reg_a, derefaop, 0);
7544           
7545           hc08_freeReg (hc08_reg_a);
7546           goto release;
7547         }
7548           
7549       /* Case with a bitfield length < 8 and arbitrary source
7550       */
7551       loadRegFromAop (hc08_reg_a, AOP (right), 0);
7552       /* shift and mask source value */
7553       AccLsh (bstr);
7554       emitcode ("and", "#0x%02x", (~mask) & 0xff);
7555       hc08_dirtyReg (hc08_reg_a, FALSE);
7556       pushReg (hc08_reg_a, TRUE);
7557
7558       loadRegFromAop (hc08_reg_a, derefaop, 0);
7559       emitcode ("and", "#0x%02x", mask);
7560       emitcode ("ora", "1,s");
7561       storeRegToAop (hc08_reg_a, derefaop, 0);
7562       pullReg (hc08_reg_a);
7563      
7564       hc08_freeReg (hc08_reg_a);
7565       goto release;
7566     }
7567
7568   /* Bit length is greater than 7 bits. In this case, copy  */
7569   /* all except the partial byte at the end                 */
7570   for (rlen=blen;rlen>=8;rlen-=8)
7571     {
7572       transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7573       offset++;
7574     }
7575
7576   /* If there was a partial byte at the end */
7577   if (rlen)
7578     {
7579       mask = (((unsigned char) -1 << rlen) & 0xff);
7580       
7581       if (AOP_TYPE (right) == AOP_LIT)
7582         {
7583           /* Case with partial byte and literal source
7584           */
7585           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7586           litval >>= (blen-rlen);
7587           litval &= (~mask) & 0xff;
7588           loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7589           if ((mask|litval)!=0xff)
7590             emitcode ("and","#0x%02x", mask);
7591           if (litval)
7592             emitcode ("ora","#0x%02x", litval);
7593           hc08_dirtyReg (hc08_reg_a, FALSE);
7594           storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7595           hc08_dirtyReg (hc08_reg_a, FALSE);
7596           hc08_freeReg (hc08_reg_a);
7597           goto release;
7598         }
7599       
7600       /* Case with partial byte and arbitrary source
7601       */
7602       loadRegFromAop (hc08_reg_a, AOP (right), offset);
7603       emitcode ("and", "#0x%02x", (~mask) & 0xff);
7604       hc08_dirtyReg (hc08_reg_a, FALSE);
7605       pushReg (hc08_reg_a, TRUE);
7606
7607       loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7608       emitcode ("and", "#0x%02x", mask);
7609       emitcode ("ora", "1,s");
7610       storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7611       pullReg (hc08_reg_a);
7612     }
7613
7614   hc08_freeReg (hc08_reg_a);
7615
7616 release:  
7617   freeAsmop (right, NULL, ic, TRUE);
7618   freeAsmop (NULL, derefaop, ic, TRUE);
7619 }
7620
7621 /*-----------------------------------------------------------------*/
7622 /* genDataPointerSet - remat pointer to data space                 */
7623 /*-----------------------------------------------------------------*/
7624 static void
7625 genDataPointerSet (operand * right,
7626                    operand * result,
7627                    iCode * ic)
7628 {
7629   int size;
7630   asmop *derefaop;
7631
7632   D(emitcode (";     genDataPointerSet",""));
7633
7634   aopOp (right, ic, FALSE);
7635   size = AOP_SIZE (right);
7636
7637   derefaop = aopDerefAop (AOP (result));
7638   freeAsmop (result, NULL, ic, TRUE);
7639   derefaop->size = size;
7640   
7641   while (size--)
7642     {
7643       transferAopAop (AOP (right), size, derefaop, size);
7644     }
7645
7646   freeAsmop (right, NULL, ic, TRUE);
7647   freeAsmop (NULL, derefaop, ic, TRUE);
7648 }
7649
7650
7651 /*-----------------------------------------------------------------*/
7652 /* genPointerSet - stores the value into a pointer location        */
7653 /*-----------------------------------------------------------------*/
7654 static void
7655 genPointerSet (iCode * ic, iCode *pi)
7656 {
7657   operand *right = IC_RIGHT (ic);
7658   operand *result = IC_RESULT (ic);
7659   sym_link *type, *etype;
7660   int size, offset;
7661   sym_link *retype = getSpec (operandType (right));
7662   sym_link *letype = getSpec (operandType (result));
7663
7664   D(emitcode (";     genPointerSet",""));
7665
7666   type = operandType (result);
7667   etype = getSpec (type);
7668   
7669   aopOp (result, ic, FALSE);
7670
7671   /* if the result is rematerializable */
7672   if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7673     {
7674       if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7675         {
7676           genDataPointerSet (right, result, ic);
7677           return;
7678         }
7679       else
7680         {
7681           genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7682           return;
7683         }
7684     }
7685
7686   /* if the operand is already in hx
7687      then we do nothing else we move the value to hx */
7688   if (AOP_TYPE (result) != AOP_STR)
7689     {
7690       loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7691     }
7692   /* so hx now contains the address */
7693   aopOp (right, ic, FALSE);
7694
7695   /* if bit then unpack */
7696   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7697     genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7698   else
7699     {
7700       size = AOP_SIZE (right);
7701       offset = size-1;
7702
7703       while (size--)
7704         {
7705           loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7706           accopWithMisc ("sta", ",x");
7707           if (size || pi)
7708             {
7709               emitcode ("aix", "#1");
7710             }
7711           hc08_freeReg (hc08_reg_a);
7712         }
7713     }
7714
7715   freeAsmop (result, NULL, ic, TRUE);
7716   freeAsmop (right, NULL, ic, TRUE);
7717
7718   if (pi) {
7719     aopOp (IC_RESULT (pi), pi, FALSE);
7720     storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7721     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7722     pi->generated=1;
7723   }
7724
7725   hc08_freeReg (hc08_reg_hx);
7726
7727 }
7728
7729 /*-----------------------------------------------------------------*/
7730 /* genIfx - generate code for Ifx statement                        */
7731 /*-----------------------------------------------------------------*/
7732 static void
7733 genIfx (iCode * ic, iCode * popIc)
7734 {
7735   operand *cond = IC_COND (ic);
7736   int isbit = 0;
7737
7738   D(emitcode (";     genIfx",""));
7739
7740   aopOp (cond, ic, FALSE);
7741
7742   /* If the condition is a literal, we can just do an unconditional */
7743   /* branch or no branch */
7744   if (AOP_TYPE (cond) == AOP_LIT)
7745     {
7746       unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit);
7747       freeAsmop (cond, NULL, ic, TRUE);
7748
7749       /* if there was something to be popped then do it */
7750       if (popIc)
7751         genIpop (popIc);
7752       if (lit)
7753         {
7754           if (IC_TRUE (ic))
7755             emitBranch ("jmp", IC_TRUE (ic));
7756         }
7757       else
7758         {
7759           if (IC_FALSE (ic))
7760             emitBranch ("jmp", IC_FALSE (ic));
7761         }
7762       ic->generated = 1;
7763       return;
7764     }
7765
7766   /* get the value into acc */
7767   if (AOP_TYPE (cond) != AOP_CRY)
7768     asmopToBool (AOP (cond), FALSE);
7769   else
7770     isbit = 1;
7771   /* the result is now in the accumulator */
7772   freeAsmop (cond, NULL, ic, TRUE);
7773
7774   /* if there was something to be popped then do it */
7775   if (popIc)
7776     genIpop (popIc);
7777
7778   /* if the condition is  a bit variable */
7779   if (isbit && IS_ITEMP (cond) &&
7780       SPIL_LOC (cond))
7781     genIfxJump (ic, SPIL_LOC (cond)->rname);
7782   else if (isbit && !IS_ITEMP (cond))
7783     genIfxJump (ic, OP_SYMBOL (cond)->rname);
7784   else
7785     genIfxJump (ic, "a");
7786
7787   ic->generated = 1;
7788 }
7789
7790 /*-----------------------------------------------------------------*/
7791 /* genAddrOf - generates code for address of                       */
7792 /*-----------------------------------------------------------------*/
7793 static void
7794 genAddrOf (iCode * ic)
7795 {
7796   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7797   int size, offset;
7798
7799   D(emitcode (";     genAddrOf",""));
7800
7801   aopOp (IC_RESULT (ic), ic, FALSE);
7802
7803   /* if the operand is on the stack then we
7804      need to get the stack offset of this
7805      variable */
7806   if (sym->onStack)
7807     {
7808       /* if it has an offset then we need to compute it */
7809       offset = _G.stackOfs + _G.stackPushes + sym->stack;
7810       hc08_useReg (hc08_reg_hx);
7811       emitcode ("tsx", "");
7812       while (offset > 127)
7813         {
7814           emitcode ("aix", "#127");
7815           offset -= 127;
7816         }
7817       while (offset < -128)
7818         {
7819           emitcode ("aix", "#-128");
7820           offset += 128;
7821         }
7822       emitcode ("aix", "#%d", offset);
7823       storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7824       hc08_freeReg (hc08_reg_hx);
7825
7826       goto release;
7827     }
7828
7829   /* object not on stack then we need the name */
7830   size = AOP_SIZE (IC_RESULT (ic));
7831   offset = 0;
7832
7833   while (size--)
7834     {
7835       char s[SDCC_NAME_MAX+10];
7836       switch (offset) {
7837         case 0:
7838           sprintf (s, "#%s", sym->rname);
7839           break;
7840         case 1:
7841           sprintf (s, "#>%s", sym->rname);
7842           break;
7843         default:
7844           sprintf (s, "#(%s >> %d)",
7845                    sym->rname,
7846                    offset * 8);
7847       }
7848       storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7849     }
7850
7851 release:
7852   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7853
7854 }
7855
7856 /*-----------------------------------------------------------------*/
7857 /* genAssign - generate code for assignment                        */
7858 /*-----------------------------------------------------------------*/
7859 static void
7860 genAssign (iCode * ic)
7861 {
7862   operand *result, *right;
7863   int size;
7864 //  unsigned long lit = 0L;
7865
7866   D(emitcode(";     genAssign",""));
7867
7868   result = IC_RESULT (ic);
7869   right = IC_RIGHT (ic);
7870
7871   /* if they are the same */
7872   if (operandsEqu (result, right)) {
7873     return;
7874   }
7875
7876   aopOp (right, ic, FALSE);
7877   aopOp (result, ic, TRUE);
7878
7879   /* if they are the same registers */
7880   if (sameRegs (AOP (right), AOP (result)))
7881     goto release;
7882
7883   if ((AOP_TYPE (right) == AOP_LIT)
7884       && (IS_AOP_HX(AOP(result))))
7885     {
7886       loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7887       goto release;
7888     }
7889     
7890   /* general case */
7891   size = AOP_SIZE (result);
7892   while (size--)
7893     {
7894       transferAopAop (AOP (right), size, AOP (result), size);
7895     }
7896
7897 release:
7898   freeAsmop (right, NULL, ic, TRUE);
7899   freeAsmop (result, NULL, ic, TRUE);
7900 }
7901
7902 /*-----------------------------------------------------------------*/
7903 /* genJumpTab - generates code for jump table                       */
7904 /*-----------------------------------------------------------------*/
7905 static void
7906 genJumpTab (iCode * ic)
7907 {
7908   symbol *jtab;
7909   symbol *jtablo = newiTempLabel (NULL);
7910   symbol *jtabhi = newiTempLabel (NULL);
7911   
7912   D(emitcode (";     genJumpTab",""));
7913
7914   aopOp (IC_JTCOND (ic), ic, FALSE);
7915   
7916   if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7917     {
7918       /* get the condition into x */
7919       loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7920       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7921       loadRegFromConst (hc08_reg_h, zero);
7922
7923       emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7924       emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7925       transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7926       emitcode ("jmp", ",x");
7927
7928       hc08_dirtyReg (hc08_reg_a, TRUE);
7929       hc08_dirtyReg (hc08_reg_hx, TRUE);
7930     }
7931   else
7932     {
7933       adjustStack(-2);
7934       pushReg(hc08_reg_hx, TRUE);
7935       
7936       /* get the condition into x */
7937       loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7938       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7939       loadRegFromConst (hc08_reg_h, zero);
7940
7941       emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7942       emitcode ("sta", "3,s");
7943       emitcode ("lda", "%05d$,x", jtablo->key + 100);
7944       emitcode ("sta", "4,s");
7945       
7946       pullReg(hc08_reg_hx);
7947       emitcode ("rts", "");
7948       _G.stackPushes += 2;
7949       updateCFA();
7950     }
7951
7952   /* now generate the jump labels */
7953   emitLabel (jtablo);
7954   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7955        jtab = setNextItem (IC_JTLABELS (ic)))
7956     emitcode (".db", "%05d$", jtab->key + 100);
7957   emitLabel (jtabhi);
7958   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7959        jtab = setNextItem (IC_JTLABELS (ic)))
7960     emitcode (".db", ">%05d$", jtab->key + 100);
7961
7962 }
7963
7964 /*-----------------------------------------------------------------*/
7965 /* genCast - gen code for casting                                  */
7966 /*-----------------------------------------------------------------*/
7967 static void
7968 genCast (iCode * ic)
7969 {
7970   operand *result = IC_RESULT (ic);
7971   sym_link *ctype = operandType (IC_LEFT (ic));
7972   sym_link *rtype = operandType (IC_RIGHT (ic));
7973   operand *right = IC_RIGHT (ic);
7974   int size, offset;
7975
7976   D(emitcode(";     genCast",""));
7977
7978   /* if they are equivalent then do nothing */
7979   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7980     return;
7981
7982   aopOp (right, ic, FALSE);
7983   aopOp (result, ic, FALSE);
7984
7985
7986   /* if they are the same size : or less */
7987   if (AOP_SIZE (result) <= AOP_SIZE (right))
7988     {
7989
7990       /* if they are in the same place */
7991       #if 0
7992       if (sameRegs (AOP (right), AOP (result)))
7993         goto release;
7994       #endif
7995
7996       /* if they in different places then copy */
7997       size = AOP_SIZE (result);
7998       offset = 0;
7999       while (size--)
8000         {
8001           transferAopAop(AOP (right), offset, AOP (result), offset);
8002           offset++;
8003         }
8004       goto release;
8005     }
8006
8007
8008   /* if the result is of type pointer */
8009   if (IS_PTR (ctype))
8010     {
8011
8012       int p_type;
8013       sym_link *type = operandType (right);
8014       sym_link *etype = getSpec (type);
8015
8016       /* pointer to generic pointer */
8017       if (IS_GENPTR (ctype))
8018         {
8019           if (IS_PTR (type))
8020             p_type = DCL_TYPE (type);
8021           else
8022             {
8023               if (SPEC_SCLS(etype)==S_REGISTER) {
8024                 // let's assume it is a generic pointer
8025                 p_type=GPOINTER;
8026               } else {
8027                 /* we have to go by the storage class */
8028                 p_type = PTR_TYPE (SPEC_OCLS (etype));
8029               }
8030             }
8031
8032           /* the first two bytes are known */
8033           size = GPTRSIZE - 1;
8034           offset = 0;
8035           while (size--)
8036             {
8037               transferAopAop(AOP (right), offset, AOP (result), offset);
8038               offset++;
8039             }
8040           /* the last byte depending on type */
8041 #if 0
8042             {
8043                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8044                 char gpValStr[10];
8045             
8046                 if (gpVal == -1)
8047                 {
8048                     // pointerTypeToGPByte will have bitched.
8049                     exit(1);
8050                 }
8051             
8052                 sprintf(gpValStr, "#0x%x", gpVal);
8053                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8054             }       
8055 #endif
8056           goto release;
8057         }
8058
8059       /* just copy the pointers */
8060       size = AOP_SIZE (result);
8061       offset = 0;
8062       while (size--)
8063         {
8064           transferAopAop(AOP (right), offset, AOP (result), offset);
8065           offset++;
8066         }
8067       goto release;
8068     }
8069
8070   /* so we now know that the size of destination is greater
8071      than the size of the source */
8072   /* we move to result for the size of source */
8073   size = AOP_SIZE (right);
8074   offset = 0;
8075   while (size--)
8076     {
8077       transferAopAop(AOP (right), offset, AOP (result), offset);
8078       offset++;
8079     }
8080
8081   /* now depending on the sign of the source && destination */
8082   size = AOP_SIZE (result) - AOP_SIZE (right);
8083   /* if unsigned or not an integral type */
8084   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8085     {
8086       while (size--)
8087         storeConstToAop (zero, AOP (result), offset++); 
8088     }
8089   else
8090     {
8091       /* we need to extend the sign :{ */
8092       loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8093       accopWithMisc ("rola", "");
8094       accopWithMisc ("clra", "");
8095       accopWithMisc ("sbc", zero);
8096       while (size--)
8097         storeRegToAop (hc08_reg_a, AOP (result), offset++);
8098     }
8099
8100   /* we are done hurray !!!! */
8101
8102 release:
8103   freeAsmop (right, NULL, ic, TRUE);
8104   freeAsmop (result, NULL, ic, TRUE);
8105
8106 }
8107
8108 /*-----------------------------------------------------------------*/
8109 /* genDjnz - generate decrement & jump if not zero instrucion      */
8110 /*-----------------------------------------------------------------*/
8111 static int
8112 genDjnz (iCode * ic, iCode * ifx)
8113 {
8114   symbol *lbl, *lbl1;
8115   if (!ifx)
8116     return 0;
8117
8118   D(emitcode (";     genDjnz",""));
8119
8120   /* if the if condition has a false label
8121      then we cannot save */
8122   if (IC_FALSE (ifx))
8123     return 0;
8124
8125   /* if the minus is not of the form
8126      a = a - 1 */
8127   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8128       !IS_OP_LITERAL (IC_RIGHT (ic)))
8129     return 0;
8130
8131   if (operandLitValue (IC_RIGHT (ic)) != 1)
8132     return 0;
8133
8134   /* dbnz doesn't support extended mode */
8135   if (isOperandInFarSpace (IC_RESULT (ic)))
8136     return 0;
8137
8138   /* if the size of this greater than one then no
8139      saving */
8140 //  if (getSize (operandType (IC_RESULT (ic))) > 1)
8141 //    return 0;
8142   aopOp (IC_RESULT (ic), ic, FALSE);
8143   if (AOP_SIZE (IC_RESULT (ic))>1)
8144     {
8145       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8146       return 0;
8147     }
8148
8149   /* otherwise we can save BIG */
8150   lbl = newiTempLabel (NULL);
8151   lbl1 = newiTempLabel (NULL);
8152
8153
8154   emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8155                 lbl->key + 100);
8156  
8157   emitBranch ("bra", lbl1);
8158   emitLabel (lbl);
8159   emitBranch ("jmp", IC_TRUE (ifx));
8160   emitLabel (lbl1);
8161
8162   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8163   ifx->generated = 1;
8164   return 1;
8165 }
8166
8167 /*-----------------------------------------------------------------*/
8168 /* genReceive - generate code for a receive iCode                  */
8169 /*-----------------------------------------------------------------*/
8170 static void
8171 genReceive (iCode * ic)
8172 {
8173   int size;
8174   int offset;
8175   D(emitcode (";     genReceive",""));
8176
8177   aopOp (IC_RESULT (ic), ic, FALSE);
8178   size = AOP_SIZE (IC_RESULT (ic));
8179   offset = 0;
8180   
8181   if (ic->argreg) {
8182       while (size--) {
8183           transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8184                           AOP (IC_RESULT (ic)), offset);
8185           if (hc08_aop_pass[offset]->type == AOP_REG)
8186             hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8187           offset++;
8188       }
8189   }       
8190
8191   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8192 }
8193
8194 /*-----------------------------------------------------------------*/
8195 /* genDummyRead - generate code for dummy read of volatiles        */
8196 /*-----------------------------------------------------------------*/
8197 static void
8198 genDummyRead (iCode * ic)
8199 {
8200   operand *op;
8201   int size, offset;
8202
8203   D(emitcode(";     genDummyRead",""));
8204
8205   op = IC_RIGHT (ic);
8206   if (op && IS_SYMOP (op))
8207     {
8208
8209       aopOp (op, ic, FALSE);
8210
8211       size = AOP_SIZE (op);
8212       offset = 0;
8213
8214       while (size--)
8215         {
8216           loadRegFromAop (hc08_reg_a, AOP (op), offset);
8217           hc08_freeReg (hc08_reg_a);
8218           offset++;
8219         }
8220
8221       freeAsmop (op, NULL, ic, TRUE);
8222    }
8223   op = IC_LEFT (ic);
8224   if (op && IS_SYMOP (op))
8225     {
8226
8227       aopOp (op, ic, FALSE);
8228
8229       size = AOP_SIZE (op);
8230       offset = 0;
8231
8232       while (size--)
8233         {
8234           loadRegFromAop (hc08_reg_a, AOP (op), offset);
8235           hc08_freeReg (hc08_reg_a);
8236           offset++;
8237         }
8238
8239       freeAsmop (op, NULL, ic, TRUE);
8240    }
8241 }
8242
8243 /*-----------------------------------------------------------------*/
8244 /* genCritical - generate code for start of a critical sequence    */
8245 /*-----------------------------------------------------------------*/
8246 static void
8247 genCritical (iCode *ic)
8248 {
8249   D(emitcode(";     genCritical",""));
8250   
8251   if (IC_RESULT (ic))
8252     aopOp (IC_RESULT (ic), ic, TRUE);
8253
8254   emitcode ("tpa", "");
8255   hc08_dirtyReg (hc08_reg_a, FALSE);
8256   emitcode ("sei", "");
8257
8258   if (IC_RESULT (ic))
8259     storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8260   else
8261     pushReg (hc08_reg_a, FALSE);
8262
8263   hc08_freeReg (hc08_reg_a);
8264   if (IC_RESULT (ic))
8265     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8266 }
8267
8268 /*-----------------------------------------------------------------*/
8269 /* genEndCritical - generate code for end of a critical sequence   */
8270 /*-----------------------------------------------------------------*/
8271 static void
8272 genEndCritical (iCode *ic)
8273 {
8274   D(emitcode(";     genEndCritical",""));
8275   
8276   if (IC_RIGHT (ic))
8277     {
8278       aopOp (IC_RIGHT (ic), ic, FALSE);
8279       loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8280       emitcode ("tap", "");
8281       hc08_freeReg (hc08_reg_a);
8282       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8283     }
8284   else
8285     {
8286       pullReg (hc08_reg_a);
8287       emitcode ("tap", "");
8288     }
8289 }
8290
8291
8292
8293 /*-----------------------------------------------------------------*/
8294 /* genhc08Code - generate code for HC08 based controllers          */
8295 /*-----------------------------------------------------------------*/
8296 void
8297 genhc08Code (iCode * lic)
8298 {
8299   iCode *ic;
8300   int cln = 0;
8301   int clevel = 0;
8302   int cblock = 0;
8303
8304   lineHead = lineCurr = NULL;
8305
8306   /* print the allocation information */
8307   if (allocInfo && currFunc)
8308     printAllocInfo (currFunc, codeOutFile);
8309   /* if debug information required */
8310   if (options.debug && currFunc)
8311     {
8312       debugFile->writeFunction (currFunc, lic);
8313       #if 0
8314       _G.debugLine = 1;
8315       if (IS_STATIC (currFunc->etype))
8316         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8317       else
8318         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8319       _G.debugLine = 0;
8320       #endif
8321     }
8322   /* stack pointer name */
8323   if (options.useXstack)
8324     spname = "_spx";
8325   else
8326     spname = "sp";
8327   
8328   debugFile->writeFrameAddress (NULL, NULL, 0);  /* have no idea where frame is now */
8329
8330   hc08_aop_pass[0] = newAsmop (AOP_REG);
8331   hc08_aop_pass[0]->size=1;
8332   hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8333   hc08_aop_pass[1] = newAsmop (AOP_REG);
8334   hc08_aop_pass[1]->size=1;
8335   hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8336   hc08_aop_pass[2] = newAsmop (AOP_DIR);
8337   hc08_aop_pass[2]->size=1;
8338   hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8339   hc08_aop_pass[3] = newAsmop (AOP_DIR);
8340   hc08_aop_pass[3]->size=1;
8341   hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8342
8343   for (ic = lic; ic; ic = ic->next)
8344     {
8345       
8346       _G.current_iCode = ic;
8347       
8348       if (ic->level != clevel || ic->block != cblock)
8349         {
8350           if (options.debug)
8351             {
8352               debugFile->writeScope(ic);
8353             }
8354           clevel = ic->level;
8355           cblock = ic->block;
8356         }
8357         
8358       if (ic->lineno && cln != ic->lineno)
8359         {
8360           if (options.debug)
8361             {
8362               debugFile->writeCLine(ic);
8363               #if 0
8364               _G.debugLine = 1;
8365               emitcode ("", "C$%s$%d$%d$%d ==.",
8366                         FileBaseName (ic->filename), ic->lineno,
8367                         ic->level, ic->block);
8368               _G.debugLine = 0;
8369               #endif
8370             }
8371           if (!options.noCcodeInAsm) {
8372             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, 
8373                       printCLine(ic->filename, ic->lineno));
8374           }
8375           cln = ic->lineno;
8376         }
8377       if (options.iCodeInAsm) {
8378         char regsInUse[80];
8379         int i;
8380
8381         for (i=0; i<6; i++) {
8382           sprintf (&regsInUse[i],
8383                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); 
8384         }
8385         regsInUse[i]=0;
8386         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8387       }
8388       /* if the result is marked as
8389          spilt and rematerializable or code for
8390          this has already been generated then
8391          do nothing */
8392       if (resultRemat (ic) || ic->generated)
8393         continue;
8394
8395       {
8396         int i;
8397         regs *reg;
8398         symbol *sym;
8399         
8400         for (i=A_IDX;i<=XA_IDX;i++)
8401           {
8402             reg = hc08_regWithIdx(i);
8403             if (reg->aop)
8404               emitcode("","; %s = %s offset %d", reg->name,
8405                        aopName(reg->aop), reg->aopofs);
8406             reg->isFree = TRUE;
8407           }
8408         if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8409           {
8410             sym = OP_SYMBOL (IC_LEFT (ic));
8411             if (sym->accuse == ACCUSE_HX)
8412               {
8413                 hc08_reg_h->isFree = FALSE;
8414                 hc08_reg_x->isFree = FALSE;
8415               }
8416             else if (sym->accuse == ACCUSE_XA)
8417               {
8418                 hc08_reg_a->isFree = FALSE;
8419                 if (sym->nRegs>1)
8420                   hc08_reg_x->isFree = FALSE;
8421               }
8422           }
8423         if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8424           {
8425             sym = OP_SYMBOL (IC_RIGHT (ic));
8426             if (sym->accuse == ACCUSE_HX)
8427               {
8428                 hc08_reg_h->isFree = FALSE;
8429                 hc08_reg_x->isFree = FALSE;
8430               }
8431             else if (sym->accuse == ACCUSE_XA)
8432               {
8433                 hc08_reg_a->isFree = FALSE;
8434                 if (sym->nRegs>1)
8435                   hc08_reg_x->isFree = FALSE;
8436               }
8437           }
8438       }
8439       
8440       /* depending on the operation */
8441       switch (ic->op)
8442         {
8443         case '!':
8444           genNot (ic);
8445           break;
8446
8447         case '~':
8448           genCpl (ic);
8449           break;
8450
8451         case UNARYMINUS:
8452           genUminus (ic);
8453           break;
8454
8455         case IPUSH:
8456           genIpush (ic);
8457           break;
8458
8459         case IPOP:
8460           /* IPOP happens only when trying to restore a
8461              spilt live range, if there is an ifx statement
8462              following this pop then the if statement might
8463              be using some of the registers being popped which
8464              would destory the contents of the register so
8465              we need to check for this condition and handle it */
8466           if (ic->next &&
8467               ic->next->op == IFX &&
8468               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8469             genIfx (ic->next, ic);
8470           else
8471             genIpop (ic);
8472           break;
8473
8474         case CALL:
8475           genCall (ic);
8476           break;
8477
8478         case PCALL:
8479           genPcall (ic);
8480           break;
8481
8482         case FUNCTION:
8483           genFunction (ic);
8484           break;
8485
8486         case ENDFUNCTION:
8487           genEndFunction (ic);
8488           break;
8489
8490         case RETURN:
8491           genRet (ic);
8492           break;
8493
8494         case LABEL:
8495           genLabel (ic);
8496           break;
8497
8498         case GOTO:
8499           genGoto (ic);
8500           break;
8501
8502         case '+':
8503           if (!genPointerGetSetOfs (ic))
8504             genPlus (ic);
8505           break;
8506
8507         case '-':
8508           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8509             genMinus (ic);
8510           break;
8511
8512         case '*':
8513           genMult (ic);
8514           break;
8515
8516         case '/':
8517           genDiv (ic);
8518           break;
8519
8520         case '%':
8521           genMod (ic);
8522           break;
8523
8524         case '>':
8525         case '<':
8526         case LE_OP:
8527         case GE_OP:
8528           genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8529           break;
8530
8531         case NE_OP:
8532         case EQ_OP:
8533           genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8534           break;
8535
8536         case AND_OP:
8537           genAndOp (ic);
8538           break;
8539
8540         case OR_OP:
8541           genOrOp (ic);
8542           break;
8543
8544         case '^':
8545           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8546           break;
8547
8548         case '|':
8549           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8550           break;
8551
8552         case BITWISEAND:
8553           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8554           break;
8555
8556         case INLINEASM:
8557           genInline (ic);
8558           break;
8559
8560         case RRC:
8561           genRRC (ic);
8562           break;
8563
8564         case RLC:
8565           genRLC (ic);
8566           break;
8567
8568         case GETHBIT:
8569           genGetHbit (ic);
8570           break;
8571
8572         case LEFT_OP:
8573           genLeftShift (ic);
8574           break;
8575
8576         case RIGHT_OP:
8577           genRightShift (ic);
8578           break;
8579
8580         case GET_VALUE_AT_ADDRESS:
8581           genPointerGet (ic,
8582                          hasInc (IC_LEFT (ic), ic,
8583                                  getSize (operandType (IC_RESULT (ic)))),
8584                          ifxForOp (IC_RESULT (ic), ic) );
8585           break;
8586
8587         case '=':
8588           if (POINTER_SET (ic))
8589             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8590           else
8591             genAssign (ic);
8592           break;
8593
8594         case IFX:
8595           genIfx (ic, NULL);
8596           break;
8597
8598         case ADDRESS_OF:
8599           genAddrOf (ic);
8600           break;
8601
8602         case JUMPTABLE:
8603           genJumpTab (ic);
8604           break;
8605
8606         case CAST:
8607           genCast (ic);
8608           break;
8609
8610         case RECEIVE:
8611           genReceive (ic);
8612           break;
8613
8614         case SEND:
8615           addSet (&_G.sendSet, ic);
8616           break;
8617
8618         case DUMMY_READ_VOLATILE:
8619           genDummyRead (ic);
8620           break;
8621
8622         case CRITICAL:
8623           genCritical (ic);
8624           break;
8625
8626         case ENDCRITICAL:
8627           genEndCritical (ic);
8628           break;
8629         
8630         case SWAP:
8631           genSwap (ic);
8632           break;
8633
8634         default:
8635           ic = ic;
8636         }
8637
8638       if (!hc08_reg_a->isFree)
8639         D(emitcode("","; forgot to free a"));
8640       if (!hc08_reg_x->isFree)
8641         D(emitcode("","; forgot to free x"));
8642       if (!hc08_reg_h->isFree)
8643         D(emitcode("","; forgot to free h"));
8644       if (!hc08_reg_hx->isFree)
8645         D(emitcode("","; forgot to free hx"));
8646       if (!hc08_reg_xa->isFree)
8647         D(emitcode("","; forgot to free xa"));
8648     }
8649
8650   debugFile->writeFrameAddress (NULL, NULL, 0);  /* have no idea where frame is now */
8651     
8652
8653   /* now we are ready to call the
8654      peep hole optimizer */
8655   if (!options.nopeep)
8656     peepHole (&lineHead);
8657
8658   /* now do the actual printing */
8659   printLine (lineHead, codeOutFile);
8660   return;
8661 }