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