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