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