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