1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for the 68HC08
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)
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
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.
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.
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!
28 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
45 char *aopLiteral (value * val, int offset);
46 char *aopLiteralLong (value * val, int offset, int size);
48 static int pushReg (regs *reg, bool freereg);
49 static void pullReg (regs *reg);
51 static char *zero = "#0x00";
52 static char *one = "#0x01";
56 {"a", "x", "_ret2", "_ret3"};
57 unsigned fReturnSizeHC08 = 4; /* shared with ralloc.c */
58 char **fReturn2 = fReturnhc08;
77 static asmop *hc08_aop_pass[4];
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 )
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) )
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) )
102 #define IS_AOP_A(x) \
103 (((x)->type == AOP_REG) \
104 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
105 && ((x)->size == 1) )
107 #define IS_AOP_X(x) \
108 (((x)->type == AOP_REG) \
109 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
110 && ((x)->size == 1) )
112 #define IS_AOP_H(x) \
113 (((x)->type == AOP_REG) \
114 && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
115 && ((x)->size == 1) )
117 #define CLRC emitcode("clc","")
119 static lineNode *lineHead = NULL;
120 static lineNode *lineCurr = NULL;
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};
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
142 /*-----------------------------------------------------------------*/
143 /* emitcode - writes the code into a file : for now it is simple */
144 /*-----------------------------------------------------------------*/
146 emitcode (char *inst, char *fmt,...)
149 char lb[INITIAL_INLINEASM];
157 sprintf (lb, "%s\t", inst);
159 sprintf (lb, "%s", inst);
160 vsprintf (lb + (strlen (lb)), fmt, ap);
163 vsprintf (lb, fmt, ap);
165 while (isspace (*lbp))
169 lineCurr = (lineCurr ?
170 connectLine (lineCurr, newLineNode (lb)) :
171 (lineHead = newLineNode (lb)));
172 lineCurr->isInline = _G.inLine;
173 lineCurr->isDebug = _G.debugLine;
174 lineCurr->ic = _G.current_iCode;
175 lineCurr->isComment = (*lbp==';');
177 //printf("%s\n", lb);
182 emitBranch (char *branchop, symbol *tlbl)
184 emitcode (branchop, "%05d$", (tlbl->key + 100));
188 emitLabel (symbol *tlbl)
190 emitcode ("", "%05d$:", (tlbl->key +100));
193 /*-----------------------------------------------------------------*/
194 /* hc08_emitDebuggerSymbol - associate the current code location */
195 /* with a debugger symbol */
196 /*-----------------------------------------------------------------*/
198 hc08_emitDebuggerSymbol (char * debugSym)
201 emitcode ("", "%s ==.", debugSym);
206 /*--------------------------------------------------------------------------*/
207 /* transferRegReg - Transfer from register(s) sreg to register(s) dreg. If */
208 /* freesrc is true, sreg is marked free and available for */
209 /* reuse. sreg and dreg must be of equal size */
210 /*--------------------------------------------------------------------------*/
212 transferRegReg (regs *sreg, regs *dreg, bool freesrc)
218 /* Nothing to do if no destination. */
222 /* But it's definately an error if there's no source. */
225 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
226 "NULL sreg in transferRegReg");
230 D(emitcode ("", "; transferRegReg(%s,%s)",
231 sreg->name, dreg->name));
244 case H_IDX: /* H to A */
245 pushReg (hc08_reg_h, FALSE);
246 pullReg (hc08_reg_a);
248 case X_IDX: /* X to A */
249 emitcode ("txa", "");
258 case A_IDX: /* A to H */
259 pushReg (hc08_reg_a, FALSE);
260 pullReg (hc08_reg_h);
262 case X_IDX: /* X to H */
263 pushReg (hc08_reg_x, FALSE);
264 pullReg (hc08_reg_h);
273 case A_IDX: /* A to X */
274 emitcode ("tax", "");
276 case H_IDX: /* H to X */
277 pushReg (hc08_reg_h, FALSE);
278 pullReg (hc08_reg_x);
287 case XA_IDX: /* XA to HX */
288 pushReg (hc08_reg_x, FALSE);
289 pullReg (hc08_reg_h);
290 emitcode ("tax", "");
299 case HX_IDX: /* HX to XA */
300 emitcode ("txa", "");
301 pushReg (hc08_reg_h, FALSE);
302 pullReg (hc08_reg_x);
312 wassertl (!error, "bad combo in transferRegReg");
317 dreg->aop = sreg->aop;
318 dreg->aopofs = sreg->aopofs;
319 dreg->isFree = FALSE;
323 /*--------------------------------------------------------------------------*/
324 /* updateCFA - update the debugger information to reflect the current */
325 /* connonical frame address relative to the stack pointer */
326 /*--------------------------------------------------------------------------*/
330 /* there is no frame unless there is a function */
334 debugFile->writeFrameAddress (NULL, hc08_reg_sp,
335 1 + _G.stackOfs + _G.stackPushes);
338 /*--------------------------------------------------------------------------*/
339 /* pushReg - Push register reg onto the stack. If freereg is true, reg is */
340 /* marked free and available for reuse. */
341 /*--------------------------------------------------------------------------*/
343 pushReg (regs *reg, bool freereg)
345 int regidx = reg->rIdx;
350 emitcode ("psha", "");
355 emitcode ("pshx", "");
360 emitcode ("pshh", "");
365 emitcode ("pshx", "");
368 emitcode ("pshh", "");
373 emitcode ("psha", "");
376 emitcode ("pshx", "");
385 return -_G.stackOfs-_G.stackPushes;
388 /*--------------------------------------------------------------------------*/
389 /* pullReg - Pull register reg off the stack. */
390 /*--------------------------------------------------------------------------*/
394 int regidx = reg->rIdx;
399 emitcode ("pula", "");
404 emitcode ("pulx", "");
409 emitcode ("pulh", "");
414 emitcode ("pulx", "");
417 emitcode ("pulh", "");
422 emitcode ("pula", "");
425 emitcode ("pulx", "");
433 hc08_dirtyReg(reg, FALSE);
436 /*--------------------------------------------------------------------------*/
437 /* pullNull - Discard n bytes off the top of the stack */
438 /*--------------------------------------------------------------------------*/
444 emitcode("ais","#%d",n);
450 /*--------------------------------------------------------------------------*/
451 /* pushRegIfUsed - Push register reg if marked in use. Returns true if the */
452 /* push was performed, false otherwise. */
453 /*--------------------------------------------------------------------------*/
455 pushRegIfUsed (regs *reg)
466 /*--------------------------------------------------------------------------*/
467 /* pullOrFreeReg - If needpull is true, register reg is pulled from the */
468 /* stack. Otherwise register reg is marked as free. */
469 /*--------------------------------------------------------------------------*/
471 pullOrFreeReg (regs *reg, bool needpull)
479 /*--------------------------------------------------------------------------*/
480 /* adjustStack - Adjust the stack pointer by n bytes. */
481 /*--------------------------------------------------------------------------*/
489 emitcode ("ais","#127");
491 _G.stackPushes -= 127;
496 emitcode ("ais","#-128");
498 _G.stackPushes += 128;
503 emitcode ("ais", "#%d", n);
512 /*--------------------------------------------------------------------------*/
513 /* aopName - Return a string with debugging information about an asmop. */
514 /*--------------------------------------------------------------------------*/
518 static char buffer[256];
522 return "(asmop*)NULL";
527 sprintf (buf,"IMMD(%s)", aop->aopu.aop_immd.aop_immd1);
530 sprintf (buf,"LIT(%s)", aopLiteral (aop->aopu.aop_lit, 0));
533 sprintf (buf,"DIR(%s)", aop->aopu.aop_dir);
536 sprintf (buf,"EXT(%s)", aop->aopu.aop_dir);
539 sprintf (buf,"SOF(%s)", OP_SYMBOL (aop->op)->name);
542 sprintf (buf, "REG(%s,%s,%s,%s)",
543 aop->aopu.aop_reg[3] ? aop->aopu.aop_reg[3]->name : "-",
544 aop->aopu.aop_reg[2] ? aop->aopu.aop_reg[2]->name : "-",
545 aop->aopu.aop_reg[1] ? aop->aopu.aop_reg[1]->name : "-",
546 aop->aopu.aop_reg[0] ? aop->aopu.aop_reg[0]->name : "-");
553 sprintf (buf,"?%d", aop->type);
561 /*--------------------------------------------------------------------------*/
562 /* loadRegFromAop - Load register reg from logical offset loffset of aop. */
563 /*--------------------------------------------------------------------------*/
565 loadRegFromAop (regs *reg, asmop *aop, int loffset)
567 int regidx = reg->rIdx;
569 if (aop->stacked && aop->stk_aop[loffset])
571 loadRegFromAop (reg, aop->stk_aop[loffset], 0);
576 printf("loadRegFromAop called\n");
579 printf(" reg = NULL\n");
582 printf(" reg = %s\n", reg->name);
585 printf(" aop = NULL\n");
588 printf(" aop->type = %d\n", aop->type);
589 printf(" loffset = %d\n", loffset);
592 printf(" aop has operand link\n");
594 printf(" aop missing operand link\n");
596 printf(" reg has operand link\n");
598 printf(" reg missing operand link\n");
601 D(emitcode ("", "; loadRegFromAop (%s, %s, %d)",
602 reg->name, aopName (aop), loffset));
604 /* If operand is volatile, we cannot optimize. */
605 if (!aop->op || isOperandVolatile (aop->op, FALSE))
609 /* If this register already has this offset of the operand
610 then we need only mark it as in use. */
611 if (reg->aop && reg->aop->op && aop->op
612 && operandsEqu(reg->aop->op,aop->op)
613 && (reg->aopofs == loffset))
616 D(emitcode ("","; already had correct value for %s", reg->name));
620 /* TODO: check to see if we can transfer from another register */
622 if (hc08_reg_h->aop && hc08_reg_h->aop->op && aop->op
623 && operandsEqu(hc08_reg_h->aop->op,aop->op)
624 && (hc08_reg_h->aopofs == loffset))
626 D(emitcode ("","; found correct value for %s in h", reg->name));
627 transferRegReg (hc08_reg_h, reg, FALSE);
633 if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op
634 && operandsEqu(hc08_reg_x->aop->op,aop->op)
635 && (hc08_reg_x->aopofs == loffset))
637 D(emitcode ("","; found correct value for %s in x", reg->name));
638 transferRegReg (hc08_reg_x, reg, FALSE);
643 if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op
644 && operandsEqu(hc08_reg_a->aop->op,aop->op)
645 && (hc08_reg_a->aopofs == loffset))
647 D(emitcode ("","; found correct value for %s in a", reg->name));
648 transferRegReg (hc08_reg_a, reg, FALSE);
658 if (aop->type == AOP_REG)
660 if (loffset < aop->size)
661 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
663 emitcode ("clra", ""); /* TODO: handle sign extension */
667 char * l = aopAdrStr (aop, loffset, FALSE);
668 if (!strcmp (l, zero))
669 emitcode ("clra", "");
671 emitcode ("lda", "%s", l);
675 if (aop->type == AOP_REG)
677 if (loffset < aop->size)
678 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
680 emitcode ("clrx", ""); /* TODO: handle sign extension */
684 char * l = aopAdrStr (aop, loffset, FALSE);
685 if (!strcmp (l, zero))
686 emitcode ("clrx", "");
688 emitcode ("ldx", "%s", l);
692 if (hc08_reg_a->isFree)
694 loadRegFromAop (hc08_reg_a, aop, loffset);
695 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
697 else if (hc08_reg_x->isFree)
699 loadRegFromAop (hc08_reg_x, aop, loffset);
700 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
704 pushReg (hc08_reg_a, TRUE);
705 loadRegFromAop (hc08_reg_a, aop, loffset);
706 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
707 pullReg (hc08_reg_a);
713 else if (IS_AOP_XA(aop))
714 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
715 else if ((aop->type == AOP_DIR))
717 if (aop->size>(loffset+1))
718 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
721 loadRegFromAop (hc08_reg_x, aop, loffset);
722 loadRegFromConst (hc08_reg_h, zero);
725 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
727 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
732 needpula = pushRegIfUsed (hc08_reg_a);
733 loadRegFromAop (hc08_reg_a, aop, loffset+1);
734 loadRegFromAop (hc08_reg_x, aop, loffset);
735 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
736 pullOrFreeReg (hc08_reg_a, needpula);
742 else if (IS_AOP_HX(aop))
743 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
746 loadRegFromAop (hc08_reg_a, aop, loffset);
747 loadRegFromAop (hc08_reg_x, aop, loffset+1);
752 // ignore caching for now
755 reg->aopofs = loffset;
760 /*--------------------------------------------------------------------------*/
761 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
762 /* freeAsmop is called with aop, the stacked data will */
763 /* be copied to the original aop location and */
764 /*--------------------------------------------------------------------------*/
766 forceStackedAop (asmop *aop)
769 asmop *newaop = newAsmop (aop->type);
770 memcpy (newaop, aop, sizeof(*newaop));
772 D(emitcode("", "; forcedStackAop %s", aopName(aop)));
773 for (loffset=0; loffset < newaop->size; loffset++)
775 asmop *aopsof = newAsmop (AOP_SOF);
777 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
778 aopsof->op = aop->op;
779 newaop->stk_aop[loffset] = aopsof;
786 /*--------------------------------------------------------------------------*/
787 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
788 /*--------------------------------------------------------------------------*/
790 storeRegToAop (regs *reg, asmop *aop, int loffset)
792 int regidx = reg->rIdx;
798 D(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
799 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
801 if ((reg->rIdx == HX_IDX) && aop->stacked
802 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
804 storeRegToAop (hc08_reg_h, aop, loffset+1);
805 storeRegToAop (hc08_reg_x, aop, loffset);
809 if ((reg->rIdx == XA_IDX) && aop->stacked
810 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
812 storeRegToAop (hc08_reg_x, aop, loffset+1);
813 storeRegToAop (hc08_reg_a, aop, loffset);
817 if (aop->stacked && aop->stk_aop[loffset])
819 storeRegToAop (reg, aop->stk_aop[loffset], 0);
823 if (aop->type == AOP_STR)
826 transferRegReg (reg, hc08_reg_x, FALSE);
828 transferRegReg (reg, hc08_reg_h, FALSE);
832 if (aop->type == AOP_DUMMY)
838 if ((aop->type == AOP_REG) && (loffset < aop->size))
839 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
841 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
844 if ((aop->type == AOP_REG) && (loffset < aop->size))
845 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
847 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
850 if (hc08_reg_a->isFree)
852 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
853 storeRegToAop (hc08_reg_a, aop, loffset);
854 hc08_freeReg (hc08_reg_a);
856 else if (hc08_reg_x->isFree)
858 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
859 storeRegToAop (hc08_reg_x, aop, loffset);
860 hc08_freeReg (hc08_reg_x);
864 pushReg (hc08_reg_a, TRUE);
865 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
866 storeRegToAop (hc08_reg_a, aop, loffset);
867 pullReg (hc08_reg_a);
871 if ((aop->type == AOP_DIR) )
873 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
875 else if (IS_AOP_XA(aop))
876 transferRegReg(reg, hc08_reg_xa, FALSE);
877 else if (IS_AOP_HX(aop))
882 needpula = pushRegIfUsed (hc08_reg_a);
883 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
884 storeRegToAop (hc08_reg_a, aop, loffset+1);
885 storeRegToAop (hc08_reg_x, aop, loffset);
886 pullOrFreeReg (hc08_reg_a, needpula);
891 transferRegReg(reg, hc08_reg_hx, FALSE);
892 else if (IS_AOP_XA(aop))
896 storeRegToAop (hc08_reg_a, aop, loffset);
897 storeRegToAop (hc08_reg_x, aop, loffset+1);
902 /* Disable the register tracking for now */
904 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
907 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
909 otherreg=hc08_regWithIdx(otheridx);
910 if (otherreg && otherreg->aop
911 && otherreg->aop->op && aop->op
912 && operandsEqu(otherreg->aop->op,aop->op)
913 && (otherreg->aopofs == loffset))
915 D(emitcode("","; marking %s stale", otherreg->name));
919 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
921 hc08_reg_hx->aop = NULL;
922 D(emitcode("","; marking hx stale"));
924 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
926 hc08_reg_xa->aop = NULL;
927 D(emitcode("","; marking xa stale"));
931 reg->aopofs = loffset;
936 /*--------------------------------------------------------------------------*/
937 /* loadRegFromConst - Load register reg from constant c. */
938 /*--------------------------------------------------------------------------*/
940 loadRegFromConst (regs *reg, char *c)
946 emitcode ("clra", "");
948 emitcode ("lda", "%s", c);
952 emitcode ("clrx", "");
954 emitcode ("ldx", "%s", c);
958 emitcode ("clrh", "");
959 else if (hc08_reg_a->isFree)
961 loadRegFromConst (hc08_reg_a, c);
962 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
964 else if (hc08_reg_x->isFree)
966 loadRegFromConst (hc08_reg_x, c);
967 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
971 pushReg (hc08_reg_a, TRUE);
972 loadRegFromConst (hc08_reg_a, c);
973 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
974 pullReg (hc08_reg_a);
978 emitcode ("ldhx", "%s", c);
981 emitcode ("lda", "%s", c);
982 emitcode ("ldx", "%s >> 8", c);
985 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
986 "Bad rIdx in loadRegFromConst");
993 /*--------------------------------------------------------------------------*/
994 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
995 /*--------------------------------------------------------------------------*/
997 storeConstToAop (char *c, asmop *aop, int loffset)
999 if (aop->stacked && aop->stk_aop[loffset])
1001 storeConstToAop (c, aop->stk_aop[loffset], 0);
1008 if (!strcmp(c,zero))
1009 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
1011 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
1014 if (loffset>(aop->size-1))
1016 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
1021 if (hc08_reg_a->isFree)
1023 loadRegFromConst (hc08_reg_a, c);
1024 storeRegToAop( hc08_reg_a, aop, loffset);
1025 hc08_freeReg (hc08_reg_a);
1027 else if (hc08_reg_x->isFree)
1029 loadRegFromConst (hc08_reg_x, c);
1030 storeRegToAop( hc08_reg_x, aop, loffset);
1031 hc08_freeReg (hc08_reg_x);
1035 pushReg (hc08_reg_a, TRUE);
1036 loadRegFromConst (hc08_reg_a, c);
1037 storeRegToAop( hc08_reg_a, aop, loffset);
1038 pullReg (hc08_reg_a);
1044 /*--------------------------------------------------------------------------*/
1045 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
1046 /* reg is extended to fill logical offsets loffset */
1047 /* and above of asmop aop. Otherwise, logical */
1048 /* offsets loffset and above of asmop aop are */
1049 /* zeroed. reg must be an 8-bit register. */
1050 /*--------------------------------------------------------------------------*/
1052 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
1054 // int regidx = reg->rIdx;
1055 int size = aop->size;
1063 while (loffset<size)
1064 storeConstToAop(zero, aop, loffset++);
1069 transferRegReg (reg, hc08_reg_a, FALSE);
1070 emitcode ("rola","");
1071 emitcode ("clra","");
1072 emitcode ("sbc", "#0");
1073 hc08_useReg (hc08_reg_a);
1074 while (loffset<size)
1075 storeRegToAop (hc08_reg_a, aop, loffset++);
1076 hc08_freeReg (hc08_reg_a);
1080 /*--------------------------------------------------------------------------*/
1081 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1082 /* padding and/or truncation as needed. If isSigned is */
1083 /* true, sign extension will take place in the padding. */
1084 /*--------------------------------------------------------------------------*/
1086 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1088 int regidx = reg->rIdx;
1089 int size = aop->size;
1096 storeRegToAop (reg, aop, 0);
1097 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1102 storeRegToAop (hc08_reg_x, aop, 0);
1106 storeRegToAop (reg, aop, 0);
1107 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1113 storeRegToAop (hc08_reg_a, aop, 0);
1117 storeRegToAop (reg, aop, 0);
1118 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1124 /*--------------------------------------------------------------------------*/
1125 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1126 /* srcaop to logical offset dstofs of asmop dstofs. */
1127 /*--------------------------------------------------------------------------*/
1129 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1131 bool needpula = FALSE;
1134 bool keepreg = FALSE;
1136 /* ignore transfers at the same byte, unless its volatile */
1137 if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
1138 && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
1139 && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs)
1142 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1144 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1148 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1150 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1154 // D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1155 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1156 // D(emitcode ("", "; srcaop->type = %d", srcaop->type));
1157 // D(emitcode ("", "; dstaop->type = %d", dstaop->type));
1159 if (dstofs >= dstaop->size)
1162 if ((dstaop->type == AOP_DIR)
1163 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1165 if (srcaop->type == AOP_LIT)
1168 unsigned char bytemask;
1170 lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
1171 bytemask = (lit >> (srcofs*8)) & 0xff;
1175 emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
1180 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1181 aopAdrStr(dstaop, dstofs, FALSE));
1185 if (dstaop->type == AOP_REG)
1187 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1188 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1190 reg = dstaop->aopu.aop_reg[dstofs];
1195 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1197 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1198 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1200 reg = srcaop->aopu.aop_reg[srcofs];
1207 if (hc08_reg_a->isFree)
1209 else if (hc08_reg_x->isFree)
1213 pushReg (hc08_reg_a, TRUE);
1219 loadRegFromAop (reg, srcaop, srcofs);
1220 storeRegToAop (reg, dstaop, dstofs);
1223 pullOrFreeReg (hc08_reg_a, needpula);
1227 /*--------------------------------------------------------------------------*/
1228 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1229 /* parameter param. */
1230 /*--------------------------------------------------------------------------*/
1232 accopWithMisc (char *accop, char *param)
1234 emitcode (accop, "%s", param);
1235 hc08_dirtyReg (hc08_reg_a, FALSE);
1238 /*--------------------------------------------------------------------------*/
1239 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1240 /* byte at logical offset loffset of asmop aop. */
1241 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1242 /*--------------------------------------------------------------------------*/
1244 accopWithAop (char *accop, asmop *aop, int loffset)
1246 if (aop->stacked && aop->stk_aop[loffset])
1248 accopWithAop (accop, aop->stk_aop[loffset], 0);
1252 if (aop->type == AOP_DUMMY)
1255 if (aop->type == AOP_REG)
1257 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1258 emitcode (accop, "1,s");
1262 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1264 hc08_dirtyReg (hc08_reg_a, FALSE);
1268 /*--------------------------------------------------------------------------*/
1269 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1270 /* byte at logical offset loffset of asmop aop. Register reg */
1271 /* must be 8-bit. */
1272 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1273 /*--------------------------------------------------------------------------*/
1275 rmwWithReg (char *rmwop, regs *reg)
1278 char *rmwaop = rmwbuf;
1280 if (reg->rIdx == A_IDX)
1282 sprintf(rmwaop,"%sa", rmwop);
1283 emitcode (rmwaop, "");
1284 hc08_dirtyReg (hc08_reg_a, FALSE);
1286 else if (reg->rIdx == X_IDX)
1288 sprintf(rmwaop,"%sx", rmwop);
1289 emitcode (rmwaop, "");
1290 hc08_dirtyReg (hc08_reg_a, FALSE);
1292 else if (hc08_reg_a->isFree)
1294 transferRegReg(reg, hc08_reg_a, FALSE);
1295 sprintf(rmwaop,"%sa", rmwop);
1296 emitcode (rmwaop, "");
1297 hc08_dirtyReg (hc08_reg_a, FALSE);
1298 transferRegReg(hc08_reg_a, reg, TRUE);
1302 pushReg (reg, FALSE);
1303 emitcode (rmwop, "1,s");
1305 hc08_dirtyReg (reg, FALSE);
1309 /*--------------------------------------------------------------------------*/
1310 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1311 /* logical offset loffset of asmop aop. */
1312 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
1313 /*--------------------------------------------------------------------------*/
1315 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1317 bool needpula = FALSE;
1319 if (aop->stacked && aop->stk_aop[loffset])
1321 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1328 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1331 needpula = pushRegIfUsed (hc08_reg_a);
1332 loadRegFromAop (hc08_reg_a, aop, loffset);
1333 rmwWithReg (rmwop, hc08_reg_a);
1334 if (strcmp ("tst", rmwop))
1335 storeRegToAop (hc08_reg_a, aop, loffset);
1336 pullOrFreeReg (hc08_reg_a, needpula);
1341 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1347 /*-----------------------------------------------------------------*/
1348 /* newAsmop - creates a new asmOp */
1349 /*-----------------------------------------------------------------*/
1351 newAsmop (short type)
1355 aop = Safe_calloc (1, sizeof (asmop));
1362 /*-----------------------------------------------------------------*/
1363 /* pointerCode - returns the code for a pointer type */
1364 /*-----------------------------------------------------------------*/
1366 pointerCode (sym_link * etype)
1369 return PTR_TYPE (SPEC_OCLS (etype));
1374 /*-----------------------------------------------------------------*/
1375 /* aopForSym - for a true symbol */
1376 /*-----------------------------------------------------------------*/
1378 aopForSym (iCode * ic, symbol * sym, bool result)
1383 wassertl (ic != NULL, "Got a null iCode");
1384 wassertl (sym != NULL, "Got a null symbol");
1386 // printf("in aopForSym for symbol %s\n", sym->name);
1388 space = SPEC_OCLS (sym->etype);
1390 /* if already has one */
1396 /* special case for a function */
1397 if (IS_FUNC (sym->type))
1399 sym->aop = aop = newAsmop (AOP_IMMD);
1400 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1401 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1402 aop->size = FPTRSIZE;
1406 /* if it is in direct space */
1407 if (IN_DIRSPACE (space))
1409 sym->aop = aop = newAsmop (AOP_DIR);
1410 aop->aopu.aop_dir = sym->rname;
1411 aop->size = getSize (sym->type);
1415 /* if it is in far space */
1416 if (IN_FARSPACE (space))
1418 sym->aop = aop = newAsmop (AOP_EXT);
1419 aop->aopu.aop_dir = sym->rname;
1420 aop->size = getSize (sym->type);
1424 if (IN_STACK (sym->etype))
1426 sym->aop = aop = newAsmop (AOP_SOF);
1427 aop->aopu.aop_dir = sym->rname;
1428 aop->size = getSize (sym->type);
1429 aop->aopu.aop_stk = sym->stack;
1435 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1436 "aopForSym should never reach here");
1440 /* if it is in code space */
1441 if (IN_CODESPACE (space))
1447 /*-----------------------------------------------------------------*/
1448 /* aopForRemat - rematerialzes an object */
1449 /*-----------------------------------------------------------------*/
1451 aopForRemat (symbol * sym)
1453 iCode *ic = sym->rematiCode;
1461 val += (int) operandLitValue (IC_RIGHT (ic));
1462 else if (ic->op == '-')
1463 val -= (int) operandLitValue (IC_RIGHT (ic));
1464 else if (IS_CAST_ICODE(ic)) {
1465 sym_link *from_type = operandType(IC_RIGHT(ic));
1466 aop->aopu.aop_immd.from_cast_remat = 1;
1467 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1468 ptr_type = DCL_TYPE(from_type);
1469 if (ptr_type == IPOINTER) {
1476 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1479 if (ic->op == ADDRESS_OF)
1482 sprintf (buffer, "(%s %c 0x%04x)",
1483 OP_SYMBOL (IC_LEFT (ic))->rname,
1484 val >= 0 ? '+' : '-',
1485 abs (val) & 0xffff);
1487 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1489 aop = newAsmop (AOP_IMMD);
1490 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1491 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1492 /* set immd2 field if required */
1493 if (aop->aopu.aop_immd.from_cast_remat)
1495 sprintf(buffer,"#0x%02x",ptr_type);
1496 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1497 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1500 else if (ic->op == '=')
1502 val += (int) operandLitValue (IC_RIGHT (ic));
1504 sprintf (buffer, "0x%04x", val);
1505 aop = newAsmop (AOP_LIT);
1506 aop->aopu.aop_lit = constVal (buffer);
1509 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1510 "unexpected rematerialization");
1517 /*-----------------------------------------------------------------*/
1518 /* regsInCommon - two operands have some registers in common */
1519 /*-----------------------------------------------------------------*/
1521 regsInCommon (operand * op1, operand * op2)
1523 symbol *sym1, *sym2;
1526 /* if they have registers in common */
1527 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1530 sym1 = OP_SYMBOL (op1);
1531 sym2 = OP_SYMBOL (op2);
1533 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1536 for (i = 0; i < sym1->nRegs; i++)
1542 for (j = 0; j < sym2->nRegs; j++)
1547 if (sym2->regs[j] == sym1->regs[i])
1555 /*-----------------------------------------------------------------*/
1556 /* operandsEqu - equivalent */
1557 /*-----------------------------------------------------------------*/
1559 operandsEqu (operand * op1, operand * op2)
1561 symbol *sym1, *sym2;
1563 /* if they not symbols */
1564 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1567 sym1 = OP_SYMBOL (op1);
1568 sym2 = OP_SYMBOL (op2);
1570 /* if both are itemps & one is spilt
1571 and the other is not then false */
1572 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1573 sym1->isspilt != sym2->isspilt)
1576 /* if they are the same */
1580 if (sym1->rname[0] && sym2->rname[0]
1581 && strcmp (sym1->rname, sym2->rname) == 0)
1584 /* if left is a tmp & right is not */
1585 if (IS_ITEMP (op1) &&
1588 (sym1->usl.spillLoc == sym2))
1591 if (IS_ITEMP (op2) &&
1595 (sym2->usl.spillLoc == sym1))
1601 /*-----------------------------------------------------------------*/
1602 /* sameRegs - two asmops have the same registers */
1603 /*-----------------------------------------------------------------*/
1605 sameRegs (asmop * aop1, asmop * aop2)
1612 // if (aop1->size != aop2->size)
1615 if (aop1->type == aop2->type)
1620 for (i = 0; i < aop1->size; i++)
1621 if (aop1->aopu.aop_reg[i] !=
1622 aop2->aopu.aop_reg[i])
1626 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1629 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1636 /*-----------------------------------------------------------------*/
1637 /* aopOp - allocates an asmop for an operand : */
1638 /*-----------------------------------------------------------------*/
1640 aopOp (operand * op, iCode * ic, bool result)
1649 // Is this a pointer set result?
1651 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1655 // printf("checking literal\n");
1656 /* if this a literal */
1657 if (IS_OP_LITERAL (op))
1659 op->aop = aop = newAsmop (AOP_LIT);
1660 aop->aopu.aop_lit = op->operand.valOperand;
1661 aop->size = getSize (operandType (op));
1663 aop->isaddr = op->isaddr;
1667 // printf("checking pre-existing\n");
1668 /* if already has a asmop then continue */
1672 op->aop->isaddr = op->isaddr;
1676 // printf("checking underlying sym\n");
1677 /* if the underlying symbol has a aop */
1678 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1680 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1681 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1682 //op->aop = aop = OP_SYMBOL (op)->aop;
1683 aop->size = getSize( operandType (op));
1684 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1685 //printf (" with size = %d\n", aop->size);
1688 aop->isaddr = op->isaddr;
1689 /* if (aop->isaddr & IS_ITEMP (op))
1691 aop->psize=aop->size;
1692 aop->size = getSize( operandType (op)->next);
1697 // printf("checking true sym\n");
1698 /* if this is a true symbol */
1699 if (IS_TRUE_SYMOP (op))
1701 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1703 aop->isaddr = op->isaddr;
1704 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1705 //printf (" with size = %d\n", aop->size);
1709 /* this is a temporary : this has
1715 e) can be a return use only */
1717 sym = OP_SYMBOL (op);
1719 // printf("checking conditional\n");
1720 /* if the type is a conditional */
1721 if (sym->regType == REG_CND)
1723 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1726 aop->isaddr = op->isaddr;
1730 // printf("checking spilt\n");
1731 /* if it is spilt then two situations
1733 b) has a spill location */
1734 if (sym->isspilt || sym->nRegs == 0)
1737 // printf("checking remat\n");
1738 /* rematerialize it NOW */
1741 sym->aop = op->aop = aop =
1743 aop->size = getSize (sym->type);
1745 aop->isaddr = op->isaddr;
1746 /* if (aop->isaddr & IS_ITEMP (op))
1748 aop->psize=aop->size;
1749 aop->size = getSize( operandType (op)->next);
1754 // printf("checking accuse\n");
1757 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1758 aop->size = getSize (sym->type);
1759 switch (sym->accuse)
1762 aop->aopu.aop_reg[0] = hc08_reg_a;
1763 aop->aopu.aop_reg[1] = hc08_reg_x;
1766 aop->aopu.aop_reg[0] = hc08_reg_x;
1767 aop->aopu.aop_reg[1] = hc08_reg_h;
1771 aop->isaddr = op->isaddr;
1775 // printf("checking ruonly\n");
1781 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1782 aop->size = getSize (sym->type);
1783 for (i = 0; i < fReturnSizeHC08; i++)
1784 aop->aopu.aop_str[i] = fReturn2[i];
1786 aop->isaddr = op->isaddr;
1790 /* else spill location */
1791 if (sym->usl.spillLoc)
1793 if (sym->usl.spillLoc->aop
1794 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1796 /* force a new aop if sizes differ */
1797 sym->usl.spillLoc->aop = NULL;
1798 //printf ("forcing new aop\n");
1800 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1801 aop->size = getSize (sym->type);
1803 aop->isaddr = op->isaddr;
1804 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1805 //printf (" with size = %d\n", aop->size);
1809 /* else must be a dummy iTemp */
1810 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1811 aop->size = getSize (sym->type);
1815 // printf("assuming register\n");
1816 /* must be in a register */
1817 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1818 aop->size = sym->nRegs;
1819 for (i = 0; i < sym->nRegs; i++)
1820 aop->aopu.aop_reg[i] = sym->regs[i];
1822 aop->isaddr = op->isaddr;
1826 /*-----------------------------------------------------------------*/
1827 /* freeAsmop - free up the asmop given to an operand */
1828 /*----------------------------------------------------------------*/
1830 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1852 D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1855 for (loffset=0; loffset<aop->size; loffset++)
1856 if (aop->stk_aop[loffset])
1858 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1861 pullNull (stackAdjust);
1865 /* all other cases just dealloc */
1871 OP_SYMBOL (op)->aop = NULL;
1872 /* if the symbol has a spill */
1874 SPIL_LOC (op)->aop = NULL;
1880 /*-----------------------------------------------------------------*/
1881 /* aopDerefAop - treating the aop parameter as a pointer, return */
1882 /* an asmop for the object it references */
1883 /*-----------------------------------------------------------------*/
1885 aopDerefAop (asmop *aop)
1890 asmop *newaop = NULL;
1891 sym_link *type, *etype;
1894 D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1898 type = operandType (aop->op);
1899 etype = getSpec (type);
1900 /* if op is of type of pointer then it is simple */
1901 if (IS_PTR (type) && !IS_FUNC (type->next))
1902 p_type = DCL_TYPE (type);
1905 /* we have to go by the storage class */
1906 p_type = PTR_TYPE (SPEC_OCLS (etype));
1915 if (p_type == POINTER)
1916 newaop = newAsmop (AOP_DIR);
1918 newaop = newAsmop (AOP_EXT);
1919 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1922 adr = (int) floatFromVal (aop->aopu.aop_lit);
1923 if (p_type == POINTER)
1928 newaop = newAsmop (AOP_DIR);
1929 sprintf (s, "0x%02x",adr);
1933 newaop = newAsmop (AOP_EXT);
1934 sprintf (s, "0x%04x",adr);
1936 rs = Safe_calloc (1, strlen (s) + 1);
1938 newaop->aopu.aop_dir = rs;
1941 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1942 "unsupported asmop");
1952 /*-----------------------------------------------------------------*/
1953 /* aopAdrStr - for referencing the address of the aop */
1954 /*-----------------------------------------------------------------*/
1956 aopAdrStr (asmop * aop, int loffset, bool bit16)
1960 int offset = aop->size - 1 - loffset;
1963 /* offset is greater than
1965 if (loffset > (aop->size - 1) &&
1966 aop->type != AOP_LIT)
1969 /* depending on type */
1977 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1978 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1980 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1984 sprintf (s, "#(%s >> %d)",
1985 aop->aopu.aop_immd.aop_immd1,
1989 aop->aopu.aop_immd.aop_immd1);
1993 aop->aopu.aop_immd.aop_immd1);
1994 rs = Safe_calloc (1, strlen (s) + 1);
2000 sprintf (s, "*(%s + %d)",
2004 sprintf (s, "*%s", aop->aopu.aop_dir);
2005 rs = Safe_calloc (1, strlen (s) + 1);
2011 sprintf (s, "(%s + %d)",
2015 sprintf (s, "%s", aop->aopu.aop_dir);
2016 rs = Safe_calloc (1, strlen (s) + 1);
2021 return aop->aopu.aop_reg[loffset]->name;
2025 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2027 return aopLiteral (aop->aopu.aop_lit, loffset);
2031 return aop->aopu.aop_str[loffset];
2034 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2036 rs = Safe_calloc (1, strlen (s) + 1);
2042 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2043 "aopAdrStr got unsupported aop->type");
2052 /*-----------------------------------------------------------------*/
2053 /* opIsGptr: returns non-zero if the passed operand is */
2054 /* a generic pointer type. */
2055 /*-----------------------------------------------------------------*/
2057 opIsGptr (operand * op)
2059 sym_link *type = operandType (op);
2061 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2069 /*-----------------------------------------------------------------*/
2070 /* getDataSize - get the operand data size */
2071 /*-----------------------------------------------------------------*/
2073 getDataSize (operand * op)
2076 size = AOP_SIZE (op);
2080 /*-----------------------------------------------------------------*/
2081 /* outAcc - output Acc */
2082 /*-----------------------------------------------------------------*/
2084 outAcc (operand * result)
2087 size = getDataSize (result);
2090 storeRegToAop (hc08_reg_a, AOP (result), 0);
2093 /* unsigned or positive */
2096 storeConstToAop (zero, AOP (result), offset++);
2101 /*-----------------------------------------------------------------*/
2102 /* outBitC - output a bit C */
2103 /*-----------------------------------------------------------------*/
2105 outBitC (operand * result)
2109 /* if the result is bit */
2110 if (AOP_TYPE (result) == AOP_CRY)
2111 aopPut (AOP (result), "c", 0);
2115 emitcode ("clra", "");
2116 emitcode ("rola", "");
2121 /*-----------------------------------------------------------------*/
2122 /* outBitNV - output a bit N^V */
2123 /*-----------------------------------------------------------------*/
2125 outBitNV (operand * result)
2127 symbol *tlbl, *tlbl1;
2129 tlbl = newiTempLabel (NULL);
2130 tlbl1 = newiTempLabel (NULL);
2132 emitBranch ("blt", tlbl);
2133 loadRegFromConst (hc08_reg_a, zero);
2134 emitBranch ("bra", tlbl1);
2136 loadRegFromConst (hc08_reg_a, one);
2142 /*-----------------------------------------------------------------*/
2143 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2144 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2145 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2146 /*-----------------------------------------------------------------*/
2148 asmopToBool (asmop *aop, bool resultInA)
2150 symbol *tlbl, *tlbl1;
2151 int size = aop->size;
2152 bool needpula = FALSE;
2153 bool flagsonly = TRUE;
2158 hc08_freeReg(hc08_reg_a);
2165 emitcode ("tsta", "");
2168 else if (IS_AOP_X(aop))
2169 emitcode ("tstx", "");
2170 else if (IS_AOP_H(aop))
2172 if (hc08_reg_a->isFree)
2174 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2175 emitcode ("tsta", "");
2177 hc08_freeReg(hc08_reg_a);
2179 else if (hc08_reg_x->isFree)
2181 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2182 emitcode ("tstx", "");
2183 hc08_freeReg(hc08_reg_x);
2187 emitcode ("pshh", "");
2188 emitcode ("tst", "1,s");
2189 emitcode ("ais", "#1");
2192 else if (IS_AOP_HX(aop))
2193 emitcode ("cphx", zero);
2194 else if (IS_AOP_XA(aop))
2196 symbol *tlbl = newiTempLabel (NULL);
2197 emitcode ("tsta", "");
2198 emitcode ("bne", "%05d$", (tlbl->key + 100));
2199 emitcode ("tstx", "");
2200 emitcode ("", "%05d$:", (tlbl->key + 100));
2204 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2205 "Bad rIdx in asmToBool");
2213 needpula = pushRegIfUsed (hc08_reg_a);
2214 loadRegFromAop (hc08_reg_a, aop, 0);
2215 for (offset=1; offset<size; offset++)
2216 accopWithAop ("ora", aop, offset);
2218 pullReg (hc08_reg_a);
2221 hc08_freeReg (hc08_reg_a);
2230 loadRegFromAop (hc08_reg_a, aop, 0);
2231 hc08_freeReg (hc08_reg_a);
2235 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2240 if (hc08_reg_a->isFree)
2242 loadRegFromAop (hc08_reg_a, aop, 0);
2243 accopWithAop ("ora", aop, 1);
2244 hc08_freeReg (hc08_reg_a);
2249 tlbl = newiTempLabel (NULL);
2250 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2251 emitcode ("bne", "%05d$", (tlbl->key + 100));
2252 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2253 emitcode ("", "%05d$:", (tlbl->key + 100));
2259 needpula = pushRegIfUsed (hc08_reg_a);
2260 loadRegFromAop (hc08_reg_a, aop, 0);
2261 for (offset=1; offset<size; offset++)
2262 accopWithAop ("ora", aop, offset);
2264 pullReg (hc08_reg_a);
2267 hc08_freeReg (hc08_reg_a);
2275 tlbl = newiTempLabel (NULL);
2279 tlbl1 = newiTempLabel (NULL);
2280 emitBranch ("bne", tlbl1);
2281 loadRegFromConst (hc08_reg_a, zero);
2282 emitBranch ("bra", tlbl);
2284 loadRegFromConst (hc08_reg_a, one);
2288 emitBranch ("beq", tlbl);
2289 loadRegFromConst (hc08_reg_a, one);
2292 hc08_useReg (hc08_reg_a);
2298 /*-----------------------------------------------------------------*/
2299 /* genNot - generate code for ! operation */
2300 /*-----------------------------------------------------------------*/
2304 D(emitcode ("; genNot",""));
2306 /* assign asmOps to operand & result */
2307 aopOp (IC_LEFT (ic), ic, FALSE);
2308 aopOp (IC_RESULT (ic), ic, TRUE);
2310 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2311 emitcode ("eor", one);
2312 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2314 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2315 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2319 /*-----------------------------------------------------------------*/
2320 /* genCpl - generate code for complement */
2321 /*-----------------------------------------------------------------*/
2327 regs* reg = hc08_reg_a;
2331 D(emitcode ("; genCpl",""));
2333 /* assign asmOps to operand & result */
2334 aopOp (IC_LEFT (ic), ic, FALSE);
2335 aopOp (IC_RESULT (ic), ic, TRUE);
2337 size = AOP_SIZE (IC_RESULT (ic));
2340 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2341 rmwWithReg ("com", reg);
2343 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2348 /* release the aops */
2349 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2350 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2353 /*-----------------------------------------------------------------*/
2354 /* genUminusFloat - unary minus for floating points */
2355 /*-----------------------------------------------------------------*/
2357 genUminusFloat (operand * op, operand * result)
2359 int size, offset = 0;
2362 D(emitcode ("; genUminusFloat",""));
2364 /* for this we just copy and then flip the bit */
2366 size = AOP_SIZE (op) - 1;
2370 transferAopAop (AOP (op), offset, AOP (result), offset);
2374 needpula = pushRegIfUsed (hc08_reg_a);
2375 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2376 emitcode ("eor", "#0x80");
2377 hc08_useReg (hc08_reg_a);
2378 storeRegToAop (hc08_reg_a, AOP (result), offset);
2379 pullOrFreeReg (hc08_reg_a, needpula);
2382 /*-----------------------------------------------------------------*/
2383 /* genUminus - unary minus code generation */
2384 /*-----------------------------------------------------------------*/
2386 genUminus (iCode * ic)
2389 sym_link *optype, *rtype;
2394 D(emitcode ("; genUminus",""));
2397 aopOp (IC_LEFT (ic), ic, FALSE);
2398 aopOp (IC_RESULT (ic), ic, TRUE);
2400 optype = operandType (IC_LEFT (ic));
2401 rtype = operandType (IC_RESULT (ic));
2403 /* if float then do float stuff */
2404 if (IS_FLOAT (optype))
2406 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2410 /* otherwise subtract from zero */
2411 size = AOP_SIZE (IC_LEFT (ic));
2416 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2417 needpula = pushRegIfUsed (hc08_reg_a);
2420 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2421 emitcode ("nega", "");
2422 hc08_freeReg (hc08_reg_a);
2423 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2424 SPEC_USIGN (operandType (IC_LEFT (ic))));
2425 pullOrFreeReg (hc08_reg_a, needpula);
2429 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2430 result = forceStackedAop (AOP (IC_RESULT (ic)));
2432 result = AOP (IC_RESULT (ic));
2434 needpula = pushRegIfUsed (hc08_reg_a);
2438 loadRegFromConst (hc08_reg_a, zero);
2439 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2440 storeRegToAop (hc08_reg_a, result, offset++);
2443 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2444 SPEC_USIGN (operandType (IC_LEFT (ic))));
2445 pullOrFreeReg (hc08_reg_a, needpula);
2447 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2448 freeAsmop (NULL, result, ic, TRUE);
2454 /* release the aops */
2455 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2456 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2459 /*-----------------------------------------------------------------*/
2460 /* saveRegisters - will look for a call and save the registers */
2461 /*-----------------------------------------------------------------*/
2463 saveRegisters (iCode * lic)
2470 for (ic = lic; ic; ic = ic->next)
2471 if (ic->op == CALL || ic->op == PCALL)
2476 fprintf (stderr, "found parameter push with no function call\n");
2480 /* if the registers have been saved already or don't need to be then
2484 if (IS_SYMOP(IC_LEFT(ic)) &&
2485 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2486 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2489 /* safe the registers in use at this time but skip the
2490 ones for the result */
2491 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2492 hc08_rUmaskForOp (IC_RESULT(ic)));
2495 for (i = 0; i < hc08_nRegs; i++)
2497 if (bitVectBitValue (rsave, i))
2498 pushReg ( hc08_regWithIdx (i), FALSE);
2502 /*-----------------------------------------------------------------*/
2503 /* unsaveRegisters - pop the pushed registers */
2504 /*-----------------------------------------------------------------*/
2506 unsaveRegisters (iCode * ic)
2511 /* restore the registers in use at this time but skip the
2512 ones for the result */
2513 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2514 hc08_rUmaskForOp (IC_RESULT(ic)));
2516 for (i = hc08_nRegs; i >= 0; i--)
2518 if (bitVectBitValue (rsave, i))
2519 pullReg ( hc08_regWithIdx (i));
2525 /*-----------------------------------------------------------------*/
2527 /*-----------------------------------------------------------------*/
2529 pushSide (operand * oper, int size)
2534 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2535 pushReg ( hc08_reg_a, TRUE);
2539 /*-----------------------------------------------------------------*/
2540 /* assignResultValue - */
2541 /*-----------------------------------------------------------------*/
2543 assignResultValue (operand * oper)
2545 int size = AOP_SIZE (oper);
2549 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2550 if (hc08_aop_pass[offset]->type == AOP_REG)
2551 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2558 /*-----------------------------------------------------------------*/
2559 /* genIpush - genrate code for pushing this gets a little complex */
2560 /*-----------------------------------------------------------------*/
2562 genIpush (iCode * ic)
2564 int size, offset = 0;
2567 D(emitcode ("; genIpush",""));
2569 /* if this is not a parm push : ie. it is spill push
2570 and spill push is always done on the local stack */
2574 /* and the item is spilt then do nothing */
2575 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2578 aopOp (IC_LEFT (ic), ic, FALSE);
2579 size = AOP_SIZE (IC_LEFT (ic));
2581 /* push it on the stack */
2584 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2585 pushReg ( hc08_reg_a, TRUE);
2591 /* this is a paramter push: in this case we call
2592 the routine to find the call and save those
2593 registers that need to be saved */
2596 /* then do the push */
2597 aopOp (IC_LEFT (ic), ic, FALSE);
2600 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2601 size = AOP_SIZE (IC_LEFT (ic));
2604 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2605 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2607 if ((size==2) && hc08_reg_hx->isFree)
2609 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2610 pushReg (hc08_reg_hx, TRUE);
2617 // printf("loading %d\n", offset);
2618 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2619 // printf("pushing \n");
2620 pushReg (hc08_reg_a, TRUE);
2624 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2627 /*-----------------------------------------------------------------*/
2628 /* genIpop - recover the registers: can happen only for spilling */
2629 /*-----------------------------------------------------------------*/
2631 genIpop (iCode * ic)
2635 D(emitcode ("; genIpop",""));
2637 /* if the temp was not pushed then */
2638 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2641 aopOp (IC_LEFT (ic), ic, FALSE);
2642 size = AOP_SIZE (IC_LEFT (ic));
2646 pullReg (hc08_reg_a);
2647 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2649 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2653 /*-----------------------------------------------------------------*/
2654 /* genSend - gen code for SEND */
2655 /*-----------------------------------------------------------------*/
2656 static void genSend(set *sendSet)
2660 for (sic = setFirstItem (sendSet); sic;
2661 sic = setNextItem (sendSet)) {
2662 int size, offset = 0;
2663 aopOp (IC_LEFT (sic), sic, FALSE);
2664 size = AOP_SIZE (IC_LEFT (sic));
2669 transferAopAop( AOP (IC_LEFT (sic)), offset,
2670 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2674 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2678 /*-----------------------------------------------------------------*/
2679 /* genCall - generates a call statement */
2680 /*-----------------------------------------------------------------*/
2682 genCall (iCode * ic)
2685 // bool restoreBank = FALSE;
2686 // bool swapBanks = FALSE;
2688 D(emitcode("; genCall",""));
2690 dtype = operandType (IC_LEFT (ic));
2691 /* if send set is not empty the assign */
2694 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2695 genSend(reverseSet(_G.sendSet));
2697 genSend(_G.sendSet);
2703 /* if caller saves & we have not saved then */
2709 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2710 OP_SYMBOL (IC_LEFT (ic))->rname :
2711 OP_SYMBOL (IC_LEFT (ic))->name));
2714 /* if we need assign a result value */
2715 if ((IS_ITEMP (IC_RESULT (ic)) &&
2716 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2717 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2718 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2719 IS_TRUE_SYMOP (IC_RESULT (ic)))
2723 aopOp (IC_RESULT (ic), ic, FALSE);
2726 assignResultValue (IC_RESULT (ic));
2728 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2731 /* adjust the stack for parameters if
2735 pullNull (ic->parmBytes);
2738 /* if we had saved some registers then unsave them */
2739 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2740 unsaveRegisters (ic);
2744 /*-----------------------------------------------------------------*/
2745 /* -10l - generates a call by pointer statement */
2746 /*-----------------------------------------------------------------*/
2748 genPcall (iCode * ic)
2751 symbol *rlbl = newiTempLabel (NULL);
2752 symbol *tlbl = newiTempLabel (NULL);
2753 // bool restoreBank=FALSE;
2754 // bool swapBanks = FALSE;
2756 D(emitcode("; genPCall",""));
2758 /* if caller saves & we have not saved then */
2762 /* if we are calling a not _naked function that is not using
2763 the same register bank then we need to save the
2764 destination registers on the stack */
2765 dtype = operandType (IC_LEFT (ic))->next;
2767 /* now push the calling address */
2768 emitBranch ("bsr", tlbl);
2769 emitBranch ("bra", rlbl);
2772 /* Push the function's address */
2773 aopOp (IC_LEFT (ic), ic, FALSE);
2774 pushSide (IC_LEFT (ic), FPTRSIZE);
2775 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2777 /* if send set is not empty the assign */
2780 genSend(reverseSet(_G.sendSet));
2786 emitcode ("rts", "");
2791 /* if we need assign a result value */
2792 if ((IS_ITEMP (IC_RESULT (ic)) &&
2793 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2794 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2795 IS_TRUE_SYMOP (IC_RESULT (ic)))
2799 aopOp (IC_RESULT (ic), ic, FALSE);
2802 assignResultValue (IC_RESULT (ic));
2804 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2807 /* adjust the stack for parameters if
2811 pullNull (ic->parmBytes);
2814 /* if we hade saved some registers then
2816 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2817 unsaveRegisters (ic);
2820 /*-----------------------------------------------------------------*/
2821 /* resultRemat - result is rematerializable */
2822 /*-----------------------------------------------------------------*/
2824 resultRemat (iCode * ic)
2826 if (SKIP_IC (ic) || ic->op == IFX)
2829 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2831 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2832 if (sym->remat && !POINTER_SET (ic))
2839 #if defined(__BORLANDC__) || defined(_MSC_VER)
2840 #define STRCASECMP stricmp
2842 #define STRCASECMP strcasecmp
2845 /*-----------------------------------------------------------------*/
2846 /* inExcludeList - return 1 if the string is in exclude Reg list */
2847 /*-----------------------------------------------------------------*/
2849 regsCmp(void *p1, void *p2)
2851 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2855 inExcludeList (char *s)
2857 const char *p = setFirstItem(options.excludeRegsSet);
2859 if (p == NULL || STRCASECMP(p, "none") == 0)
2863 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2866 /*-----------------------------------------------------------------*/
2867 /* genFunction - generated code for function entry */
2868 /*-----------------------------------------------------------------*/
2870 genFunction (iCode * ic)
2874 int calleesaves_saved_register = -1;
2878 /* create the function header */
2879 emitcode (";", "-----------------------------------------");
2880 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2881 emitcode (";", "-----------------------------------------");
2883 emitcode ("", "%s:", sym->rname);
2884 ftype = operandType (IC_LEFT (ic));
2888 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2890 if (IFFUNC_ISNAKED(ftype))
2892 emitcode(";", "naked function: no prologue.");
2898 /* if this is an interrupt service routine then
2900 if (IFFUNC_ISISR (sym->type))
2903 if (!inExcludeList ("h"))
2904 pushReg (hc08_reg_h, FALSE);
2908 /* if callee-save to be used for this function
2909 then save the registers being used in this function */
2910 if (IFFUNC_CALLEESAVES(sym->type))
2914 /* if any registers used */
2917 /* save the registers used */
2918 for (i = 0; i < sym->regsUsed->size; i++)
2920 if (bitVectBitValue (sym->regsUsed, i))
2922 /* remember one saved register for later usage */
2923 if (calleesaves_saved_register < 0)
2924 calleesaves_saved_register = i;
2925 pushReg (hc08_regWithIdx (i), FALSE);
2933 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2938 /* adjust the stack for the function */
2944 // werror (W_STACK_OVERFLOW, sym->name);
2948 _G.stackOfs = sym->stack;
2951 /* if critical function then turn interrupts off */
2952 if (IFFUNC_ISCRITICAL (ftype))
2954 if (IFFUNC_ARGS (ftype))
2956 /* Function was passed parameters, so make sure A is preserved */
2957 pushReg (hc08_reg_a, FALSE);
2958 pushReg (hc08_reg_a, FALSE);
2959 emitcode ("tpa", "");
2960 emitcode ("sta", "2,s");
2961 emitcode ("sei", "");
2962 pullReg (hc08_reg_a);
2966 /* No passed parameters, so A can be freely modified */
2967 emitcode ("tpa", "");
2968 pushReg (hc08_reg_a, TRUE);
2969 emitcode ("sei", "");
2975 /*-----------------------------------------------------------------*/
2976 /* genEndFunction - generates epilogue for functions */
2977 /*-----------------------------------------------------------------*/
2979 genEndFunction (iCode * ic)
2981 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2983 if (IFFUNC_ISNAKED(sym->type))
2985 emitcode(";", "naked function: no epilogue.");
2986 if (options.debug && currFunc)
2987 debugFile->writeEndFunction (currFunc, ic, 0);
2991 if (IFFUNC_ISCRITICAL (sym->type))
2993 if (!IS_VOID(sym->type->next))
2995 /* Function has return value, so make sure A is preserved */
2996 pushReg (hc08_reg_a, FALSE);
2997 emitcode ("lda", "2,s");
2998 emitcode ("tap", "");
2999 pullReg (hc08_reg_a);
3004 /* Function returns void, so A can be freely modified */
3005 pullReg (hc08_reg_a);
3006 emitcode ("tap", "");
3010 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
3016 _G.stackPushes += sym->stack;
3017 adjustStack (sym->stack);
3021 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3025 if (IFFUNC_ISISR (sym->type))
3028 if (!inExcludeList ("h"))
3029 pullReg (hc08_reg_h);
3032 /* if debug then send end of function */
3033 if (options.debug && currFunc)
3035 debugFile->writeEndFunction (currFunc, ic, 1);
3038 emitcode ("rti", "");
3042 if (IFFUNC_CALLEESAVES(sym->type))
3046 /* if any registers used */
3049 /* save the registers used */
3050 for (i = sym->regsUsed->size; i >= 0; i--)
3052 if (bitVectBitValue (sym->regsUsed, i) ||
3053 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3054 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3060 /* if debug then send end of function */
3061 if (options.debug && currFunc)
3063 debugFile->writeEndFunction (currFunc, ic, 1);
3066 emitcode ("rts", "");
3071 /*-----------------------------------------------------------------*/
3072 /* genRet - generate code for return statement */
3073 /*-----------------------------------------------------------------*/
3077 int size, offset = 0;
3080 D(emitcode ("; genRet",""));
3082 /* if we have no return value then
3083 just generate the "ret" */
3087 /* we have something to return then
3088 move the return value into place */
3089 aopOp (IC_LEFT (ic), ic, FALSE);
3090 size = AOP_SIZE (IC_LEFT (ic));
3096 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3103 /* 4 byte return: store value in the global return variable */
3107 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3108 STA (fReturn2[offset--], FALSE);
3109 hc08_freeReg (hc08_reg_a);
3113 /* 2 byte return: store value in x:a */
3114 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3115 hc08_freeReg (hc08_reg_xa);
3118 /* 1 byte return: store value in a */
3119 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3120 hc08_freeReg (hc08_reg_a);
3125 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3128 /* generate a jump to the return label
3129 if the next is not the return statement */
3130 if (!(ic->next && ic->next->op == LABEL &&
3131 IC_LABEL (ic->next) == returnLabel))
3133 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3137 /*-----------------------------------------------------------------*/
3138 /* genLabel - generates a label */
3139 /*-----------------------------------------------------------------*/
3141 genLabel (iCode * ic)
3146 /* For the high level labels we cannot depend on any */
3147 /* register's contents. Amnesia time. */
3148 for (i=A_IDX;i<=XA_IDX;i++)
3150 reg = hc08_regWithIdx(i);
3155 /* special case never generate */
3156 if (IC_LABEL (ic) == entryLabel)
3159 debugFile->writeLabel(IC_LABEL (ic), ic);
3161 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3165 /*-----------------------------------------------------------------*/
3166 /* genGoto - generates a jmp */
3167 /*-----------------------------------------------------------------*/
3169 genGoto (iCode * ic)
3171 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3175 /*-----------------------------------------------------------------*/
3176 /* findLabelBackwards: walks back through the iCode chain looking */
3177 /* for the given label. Returns number of iCode instructions */
3178 /* between that label and given ic. */
3179 /* Returns zero if label not found. */
3180 /*-----------------------------------------------------------------*/
3182 findLabelBackwards (iCode * ic, int key)
3191 /* If we have any pushes or pops, we cannot predict the distance.
3192 I don't like this at all, this should be dealt with in the
3194 if (ic->op == IPUSH || ic->op == IPOP) {
3198 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3208 /*-----------------------------------------------------------------*/
3209 /* genPlusIncr :- does addition with increment if possible */
3210 /*-----------------------------------------------------------------*/
3212 genPlusIncr (iCode * ic)
3220 unsigned int size = getDataSize (IC_RESULT (ic));
3222 symbol *tlbl = NULL;
3224 left = IC_LEFT (ic);
3225 result = IC_RESULT (ic);
3227 /* will try to generate an increment */
3228 /* if the right side is not a literal
3230 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3233 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3235 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3237 if ((IS_AOP_HX (AOP (left)) ||
3238 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3240 && (icount>=-128) && (icount<=127) && (size==2))
3242 if (!IS_AOP_HX (AOP (left)))
3244 needpulx = pushRegIfUsed (hc08_reg_x);
3245 needpulh = pushRegIfUsed (hc08_reg_h);
3252 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3253 emitcode ("aix","#%d", icount);
3254 hc08_dirtyReg (hc08_reg_hx, FALSE);
3255 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3256 pullOrFreeReg (hc08_reg_h, needpulh);
3257 pullOrFreeReg (hc08_reg_x, needpulx);
3261 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3262 sameRegs (AOP (left), AOP (result))));
3264 if ((icount > 255) || (icount<0))
3267 if (!sameRegs (AOP (left), AOP (result)))
3270 D(emitcode ("; genPlusIncr",""));
3273 tlbl = newiTempLabel (NULL);
3278 rmwWithAop ("inc", AOP (result), 0);
3280 emitBranch ("bne", tlbl);
3284 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3285 needpula = pushRegIfUsed (hc08_reg_a);
3288 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3289 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3290 hc08_useReg (hc08_reg_a);
3291 storeRegToAop (hc08_reg_a, AOP (result), 0);
3292 hc08_freeReg (hc08_reg_a);
3294 emitBranch ("bcc", tlbl);
3296 for (offset=1; offset<size; offset++)
3298 rmwWithAop ("inc", AOP (result), offset);
3299 if ((offset+1)<size)
3300 emitBranch ("bne", tlbl);
3306 pullOrFreeReg (hc08_reg_a, needpula);
3313 /*-----------------------------------------------------------------*/
3314 /* genPlus - generates code for addition */
3315 /*-----------------------------------------------------------------*/
3317 genPlus (iCode * ic)
3319 int size, offset = 0;
3321 asmop *leftOp, *rightOp;
3323 /* special cases :- */
3325 D(emitcode ("; genPlus",""));
3327 aopOp (IC_LEFT (ic), ic, FALSE);
3328 aopOp (IC_RIGHT (ic), ic, FALSE);
3329 aopOp (IC_RESULT (ic), ic, TRUE);
3331 /* we want registers on the left and literals on the right */
3332 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3333 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3335 operand *t = IC_RIGHT (ic);
3336 IC_RIGHT (ic) = IC_LEFT (ic);
3341 /* if I can do an increment instead
3342 of add then GOOD for ME */
3343 if (genPlusIncr (ic) == TRUE)
3346 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3347 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3348 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3350 size = getDataSize (IC_RESULT (ic));
3352 leftOp = AOP(IC_LEFT(ic));
3353 rightOp = AOP(IC_RIGHT(ic));
3359 loadRegFromAop (hc08_reg_a, leftOp, offset);
3360 accopWithAop(add, rightOp, offset);
3361 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3362 hc08_freeReg (hc08_reg_a);
3363 add = "adc"; /* further adds must propagate carry */
3367 // adjustArithmeticResult (ic);
3370 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3371 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3372 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3375 /*-----------------------------------------------------------------*/
3376 /* genMinusDec :- does subtraction with deccrement if possible */
3377 /*-----------------------------------------------------------------*/
3379 genMinusDec (iCode * ic)
3381 unsigned int icount;
3386 unsigned int size = getDataSize (IC_RESULT (ic));
3390 left = IC_LEFT (ic);
3391 result = IC_RESULT (ic);
3393 /* will try to generate an increment */
3394 /* if the right side is not a literal
3396 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3399 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3401 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3402 && (icount>=-127) && (icount<=128) && (size==2))
3404 if (!IS_AOP_HX (AOP (left)))
3406 needpulx = pushRegIfUsed (hc08_reg_x);
3407 needpulh = pushRegIfUsed (hc08_reg_h);
3414 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3415 emitcode ("aix","#%d", -icount);
3416 hc08_dirtyReg (hc08_reg_hx, FALSE);
3417 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3418 pullOrFreeReg (hc08_reg_h, needpulh);
3419 pullOrFreeReg (hc08_reg_x, needpulx);
3423 if ((icount > 1) || (icount<0))
3426 if (!sameRegs (AOP (left), AOP (result)))
3432 D(emitcode ("; genMinusDec",""));
3434 rmwWithAop ("dec", AOP (result), 0);
3439 /*-----------------------------------------------------------------*/
3440 /* addSign - complete with sign */
3441 /*-----------------------------------------------------------------*/
3443 addSign (operand * result, int offset, int sign)
3445 int size = (getDataSize (result) - offset);
3450 emitcode ("rola", "");
3451 emitcode ("clra", "");
3452 emitcode ("sbc", zero);
3454 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3458 storeConstToAop (zero, AOP (result), offset++);
3463 /*-----------------------------------------------------------------*/
3464 /* genMinus - generates code for subtraction */
3465 /*-----------------------------------------------------------------*/
3467 genMinus (iCode * ic)
3470 int size, offset = 0;
3472 asmop *leftOp, *rightOp;
3474 D(emitcode ("; genMinus",""));
3476 aopOp (IC_LEFT (ic), ic, FALSE);
3477 aopOp (IC_RIGHT (ic), ic, FALSE);
3478 aopOp (IC_RESULT (ic), ic, TRUE);
3480 /* special cases :- */
3481 /* if I can do an decrement instead
3482 of subtract then GOOD for ME */
3483 if (genMinusDec (ic) == TRUE)
3486 size = getDataSize (IC_RESULT (ic));
3489 leftOp = AOP(IC_LEFT(ic));
3490 rightOp = AOP(IC_RIGHT(ic));
3496 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3497 accopWithAop(sub, rightOp, offset);
3498 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3503 // adjustArithmeticResult (ic);
3506 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3507 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3508 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3513 /*-----------------------------------------------------------------*/
3514 /* genMultOneByte : 8*8=8/16 bit multiplication */
3515 /*-----------------------------------------------------------------*/
3517 genMultOneByte (operand * left,
3521 /* sym_link *opetype = operandType (result); */
3522 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3523 int size=AOP_SIZE(result);
3524 bool negLiteral = FALSE;
3525 bool lUnsigned, rUnsigned;
3527 D(emitcode ("; genMultOneByte",""));
3529 if (size<1 || size>2) {
3530 // this should never happen
3531 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3532 AOP_SIZE(result), __FILE__, lineno);
3536 /* (if two literals: the value is computed before) */
3537 /* if one literal, literal on the right */
3538 if (AOP_TYPE (left) == AOP_LIT)
3544 /* if an operand is in A, make sure it is on the left */
3545 if (IS_AOP_A (AOP (right)))
3552 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3553 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3555 /* lUnsigned rUnsigned negLiteral negate case */
3556 /* false false false odd 3 */
3557 /* false false true even 3 */
3558 /* false true false odd 3 */
3559 /* false true true impossible */
3560 /* true false false odd 3 */
3561 /* true false true always 2 */
3562 /* true true false never 1 */
3563 /* true true true impossible */
3567 || (lUnsigned && rUnsigned))
3569 // just an unsigned 8*8=8/16 multiply
3570 //D(emitcode (";","unsigned"));
3572 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3573 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3574 emitcode ("mul", "");
3575 hc08_dirtyReg (hc08_reg_xa, FALSE);
3576 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3577 hc08_freeReg (hc08_reg_xa);
3582 // we have to do a signed multiply
3585 /* left unsigned, right signed literal -- literal determines sign handling */
3586 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3588 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3590 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3592 emitcode ("ldx", "#0x%02x", -val);
3594 emitcode ("ldx", "#0x%02x", val);
3596 emitcode ("mul", "");
3600 rmwWithReg ("neg", hc08_reg_a);
3601 tlbl4 = newiTempLabel (NULL);
3602 emitBranch ("bcc", tlbl4);
3603 rmwWithReg ("inc", hc08_reg_x);
3605 rmwWithReg ("neg", hc08_reg_x);
3608 hc08_dirtyReg (hc08_reg_xa, FALSE);
3609 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3610 hc08_freeReg (hc08_reg_xa);
3617 emitcode ("clr", "1,s");
3619 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3622 tlbl1 = newiTempLabel (NULL);
3623 emitcode ("tsta","");
3624 emitBranch ("bpl", tlbl1);
3625 emitcode ("inc", "1,s");
3626 rmwWithReg ("neg", hc08_reg_a);
3630 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3632 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3633 /* AND literal negative */
3635 emitcode ("ldx", "#0x%02x", -val);
3638 emitcode ("ldx", "#0x%02x", val);
3640 hc08_useReg (hc08_reg_x);
3644 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3647 tlbl2 = newiTempLabel (NULL);
3648 emitcode ("tstx", "");
3649 emitBranch ("bpl", tlbl2);
3650 emitcode ("inc", "1,s");
3651 rmwWithReg ("neg", hc08_reg_x);
3656 emitcode ("mul", "");
3657 hc08_dirtyReg (hc08_reg_xa, FALSE);
3659 tlbl3 = newiTempLabel (NULL);
3660 emitcode ("dec", "1,s");
3661 if (!lUnsigned && !rUnsigned && negLiteral)
3662 emitBranch ("beq", tlbl3);
3664 emitBranch ("bne", tlbl3);
3666 rmwWithReg ("neg", hc08_reg_a);
3667 tlbl4 = newiTempLabel (NULL);
3668 emitBranch ("bcc", tlbl4);
3669 rmwWithReg ("inc", hc08_reg_x);
3671 rmwWithReg ("neg", hc08_reg_x);
3675 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3676 hc08_freeReg (hc08_reg_xa);
3680 /*-----------------------------------------------------------------*/
3681 /* genMult - generates code for multiplication */
3682 /*-----------------------------------------------------------------*/
3684 genMult (iCode * ic)
3686 operand *left = IC_LEFT (ic);
3687 operand *right = IC_RIGHT (ic);
3688 operand *result = IC_RESULT (ic);
3690 D(emitcode ("; genMult",""));
3692 /* assign the amsops */
3693 aopOp (left, ic, FALSE);
3694 aopOp (right, ic, FALSE);
3695 aopOp (result, ic, TRUE);
3697 /* special cases first */
3698 /* if both are of size == 1 */
3699 // if (getSize(operandType(left)) == 1 &&
3700 // getSize(operandType(right)) == 1)
3701 if (AOP_SIZE (left) == 1 &&
3702 AOP_SIZE (right) == 1)
3704 genMultOneByte (left, right, result);
3708 /* should have been converted to function call */
3709 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3710 getSize(OP_SYMBOL(right)->type));
3711 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3716 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3717 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3718 freeAsmop (result, NULL, ic, TRUE);
3721 /*-----------------------------------------------------------------*/
3722 /* genDivOneByte : 8 bit division */
3723 /*-----------------------------------------------------------------*/
3725 genDivOneByte (operand * left,
3729 symbol *tlbl1, *tlbl2, *tlbl3;
3732 bool lUnsigned, rUnsigned;
3733 bool runtimeSign, compiletimeSign;
3735 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3736 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3738 D(emitcode ("; genDivOneByte",""));
3740 size = AOP_SIZE (result);
3741 /* signed or unsigned */
3742 if (lUnsigned && rUnsigned)
3744 /* unsigned is easy */
3745 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3746 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3747 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3748 emitcode ("div", "");
3749 hc08_dirtyReg (hc08_reg_a, FALSE);
3750 hc08_dirtyReg (hc08_reg_h, FALSE);
3751 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3752 hc08_freeReg (hc08_reg_a);
3753 hc08_freeReg (hc08_reg_x);
3754 hc08_freeReg (hc08_reg_h);
3758 /* signed is a little bit more difficult */
3760 /* now sign adjust for both left & right */
3762 /* let's see what's needed: */
3763 /* apply negative sign during runtime */
3764 runtimeSign = FALSE;
3765 /* negative sign from literals */
3766 compiletimeSign = FALSE;
3770 if (AOP_TYPE(left) == AOP_LIT)
3772 /* signed literal */
3773 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3775 compiletimeSign = TRUE;
3778 /* signed but not literal */
3784 if (AOP_TYPE(right) == AOP_LIT)
3786 /* signed literal */
3787 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3789 compiletimeSign ^= TRUE;
3792 /* signed but not literal */
3796 /* initialize the runtime sign */
3799 if (compiletimeSign)
3800 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3802 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3803 pushReg (hc08_reg_x, TRUE);
3806 /* save the signs of the operands */
3807 if (AOP_TYPE(right) == AOP_LIT)
3809 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3811 if (!rUnsigned && val < 0)
3812 emitcode ("ldx", "#0x%02x", -val);
3814 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3816 else /* ! literal */
3818 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3821 tlbl1 = newiTempLabel (NULL);
3822 emitcode ("tstx", "");
3823 emitBranch ("bpl", tlbl1);
3824 emitcode ("inc", "1,s");
3825 rmwWithReg ("neg", hc08_reg_x);
3830 if (AOP_TYPE(left) == AOP_LIT)
3832 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3834 if (!lUnsigned && val < 0)
3835 emitcode ("lda", "#0x%02x", -val);
3837 emitcode ("lda", "#0x%02x", (unsigned char) val);
3839 else /* ! literal */
3841 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3844 tlbl2 = newiTempLabel (NULL);
3845 emitcode ("tsta", "");
3846 emitBranch ("bpl", tlbl2);
3847 emitcode ("inc", "1,s");
3848 rmwWithReg ("neg", hc08_reg_a);
3853 loadRegFromConst (hc08_reg_h, zero);
3854 emitcode ("div", "");
3855 hc08_dirtyReg (hc08_reg_x, FALSE);
3856 hc08_dirtyReg (hc08_reg_a, FALSE);
3857 hc08_dirtyReg (hc08_reg_h, FALSE);
3859 if (runtimeSign || compiletimeSign)
3861 tlbl3 = newiTempLabel (NULL);
3864 pullReg (hc08_reg_x);
3865 rmwWithReg ("lsr", hc08_reg_x);
3866 rmwWithReg ("ror", hc08_reg_x);
3867 emitBranch ("bpl", tlbl3);
3870 rmwWithReg ("neg", hc08_reg_a);
3874 storeRegToAop (hc08_reg_a, AOP (result), 0);
3878 /* msb is 0x00 or 0xff depending on the sign */
3881 rmwWithReg ("lsl", hc08_reg_x);
3882 emitcode ("clra", "");
3883 emitcode ("sbc", "#0");
3885 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3887 else /* compiletimeSign */
3889 storeConstToAop ("#0xff", AOP (result), ++offset);
3894 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3897 hc08_freeReg (hc08_reg_a);
3898 hc08_freeReg (hc08_reg_x);
3899 hc08_freeReg (hc08_reg_h);
3902 /*-----------------------------------------------------------------*/
3903 /* genDiv - generates code for division */
3904 /*-----------------------------------------------------------------*/
3908 operand *left = IC_LEFT (ic);
3909 operand *right = IC_RIGHT (ic);
3910 operand *result = IC_RESULT (ic);
3912 D(emitcode ("; genDiv",""));
3914 /* assign the amsops */
3915 aopOp (left, ic, FALSE);
3916 aopOp (right, ic, FALSE);
3917 aopOp (result, ic, TRUE);
3919 /* special cases first */
3920 /* if both are of size == 1 */
3921 if (AOP_SIZE (left) <= 2 &&
3922 AOP_SIZE (right) == 1)
3924 genDivOneByte (left, right, result);
3928 /* should have been converted to function call */
3931 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3932 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3933 freeAsmop (result, NULL, ic, TRUE);
3936 /*-----------------------------------------------------------------*/
3937 /* genModOneByte : 8 bit modulus */
3938 /*-----------------------------------------------------------------*/
3940 genModOneByte (operand * left,
3944 symbol *tlbl1, *tlbl2, *tlbl3;
3947 bool lUnsigned, rUnsigned;
3948 bool runtimeSign, compiletimeSign;
3950 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3951 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3953 D(emitcode ("; genModOneByte",""));
3955 size = AOP_SIZE (result);
3957 if (lUnsigned && rUnsigned)
3959 /* unsigned is easy */
3960 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3961 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3962 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3963 emitcode ("div", "");
3964 hc08_dirtyReg (hc08_reg_a, FALSE);
3965 hc08_dirtyReg (hc08_reg_h, FALSE);
3966 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3967 hc08_freeReg (hc08_reg_a);
3968 hc08_freeReg (hc08_reg_x);
3969 hc08_freeReg (hc08_reg_h);
3973 /* signed is a little bit more difficult */
3975 if (AOP_TYPE(right) == AOP_LIT)
3977 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3979 if (!rUnsigned && val < 0)
3980 emitcode ("ldx", "#0x%02x", -val);
3982 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3984 else /* ! literal */
3986 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3989 tlbl1 = newiTempLabel (NULL);
3990 emitcode ("tstx", "");
3991 emitBranch ("bpl", tlbl1);
3992 rmwWithReg ("neg", hc08_reg_x);
3997 /* let's see what's needed: */
3998 /* apply negative sign during runtime */
3999 runtimeSign = FALSE;
4000 /* negative sign from literals */
4001 compiletimeSign = FALSE;
4003 /* sign adjust left side */
4004 if (AOP_TYPE(left) == AOP_LIT)
4006 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4008 if (!lUnsigned && val < 0)
4010 compiletimeSign = TRUE; /* set sign flag */
4011 emitcode ("lda", "#0x%02x", -val);
4014 emitcode ("lda", "#0x%02x", (unsigned char) val);
4016 else /* ! literal */
4019 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4024 emitcode ("clr", "1,s");
4026 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4027 tlbl2 = newiTempLabel (NULL);
4028 emitcode ("tsta", "");
4029 emitBranch ("bpl", tlbl2);
4030 emitcode ("inc", "1,s");
4031 rmwWithReg ("neg", hc08_reg_a);
4036 loadRegFromConst (hc08_reg_h, zero);
4037 emitcode ("div", "");
4038 hc08_dirtyReg (hc08_reg_x, FALSE);
4039 hc08_dirtyReg (hc08_reg_a, FALSE);
4040 hc08_dirtyReg (hc08_reg_h, FALSE);
4042 if (runtimeSign || compiletimeSign)
4044 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4045 tlbl3 = newiTempLabel (NULL);
4048 pullReg (hc08_reg_x);
4049 rmwWithReg ("lsr", hc08_reg_x);
4050 rmwWithReg ("ror", hc08_reg_x);
4051 emitBranch ("bpl", tlbl3);
4054 rmwWithReg ("neg", hc08_reg_a);
4058 storeRegToAop (hc08_reg_a, AOP (result), 0);
4062 /* msb is 0x00 or 0xff depending on the sign */
4065 rmwWithReg ("lsl", hc08_reg_x);
4066 emitcode ("clra", "");
4067 emitcode ("sbc", "#0");
4069 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4071 else /* compiletimeSign */
4073 storeConstToAop ("#0xff", AOP (result), ++offset);
4078 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4081 hc08_freeReg (hc08_reg_a);
4082 hc08_freeReg (hc08_reg_x);
4083 hc08_freeReg (hc08_reg_h);
4086 /*-----------------------------------------------------------------*/
4087 /* genMod - generates code for division */
4088 /*-----------------------------------------------------------------*/
4092 operand *left = IC_LEFT (ic);
4093 operand *right = IC_RIGHT (ic);
4094 operand *result = IC_RESULT (ic);
4096 D(emitcode ("; genMod",""));
4098 /* assign the amsops */
4099 aopOp (left, ic, FALSE);
4100 aopOp (right, ic, FALSE);
4101 aopOp (result, ic, TRUE);
4103 /* special cases first */
4104 /* if both are of size == 1 */
4105 if (AOP_SIZE (left) <= 2 &&
4106 AOP_SIZE (right) == 1)
4108 genModOneByte (left, right, result);
4112 /* should have been converted to function call */
4116 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4117 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4118 freeAsmop (result, NULL, ic, TRUE);
4121 /*-----------------------------------------------------------------*/
4122 /* genIfxJump :- will create a jump depending on the ifx */
4123 /*-----------------------------------------------------------------*/
4125 genIfxJump (iCode * ic, char *jval)
4128 symbol *tlbl = newiTempLabel (NULL);
4131 D(emitcode ("; genIfxJump",""));
4133 /* if true label then we jump if condition
4137 jlbl = IC_TRUE (ic);
4138 if (!strcmp (jval, "a"))
4140 else if (!strcmp (jval, "c"))
4147 /* false label is present */
4148 jlbl = IC_FALSE (ic);
4149 if (!strcmp (jval, "a"))
4151 else if (!strcmp (jval, "c"))
4156 emitBranch (inst, tlbl);
4157 emitBranch ("jmp", jlbl);
4160 /* mark the icode as generated */
4164 /*-----------------------------------------------------------------*/
4165 /* genCmp :- greater or less than comparison */
4166 /*-----------------------------------------------------------------*/
4168 genCmp (operand * left, operand * right,
4169 operand * result, iCode * ifx, int sign, iCode *ic)
4171 int size, offset = 0;
4172 unsigned long lit = 0L;
4174 bool needpula = FALSE;
4176 D(emitcode ("; genCmp",""));
4178 /* subtract right from left if at the
4179 end the carry flag is set then we know that
4180 left is greater than right */
4181 size = max (AOP_SIZE (left), AOP_SIZE (right));
4183 if (AOP_TYPE (right) == AOP_LIT)
4185 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4186 /* optimize if(x < 0) or if(x >= 0) */
4195 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
4196 emitcode ("rola", "");
4197 hc08_useReg (hc08_reg_a);
4205 && ((AOP_TYPE (right) == AOP_LIT) ||
4206 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4207 && hc08_reg_hx->isFree)
4209 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4210 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4211 hc08_freeReg (hc08_reg_hx);
4222 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4223 accopWithAop (sub, AOP (right), offset);
4224 hc08_freeReg (hc08_reg_a);
4230 freeAsmop (right, NULL, ic, TRUE);
4231 freeAsmop (left, NULL, ic, TRUE);
4232 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4238 /* if the result is used in the next
4239 ifx conditional branch then generate
4240 code a little differently */
4243 pullOrFreeReg(hc08_reg_a,needpula);
4244 genIfxJump (ifx, sign ? "s" : "c");
4251 pullOrFreeReg(hc08_reg_a,needpula);
4255 /*-----------------------------------------------------------------*/
4256 /* genCmpGt :- greater than comparison */
4257 /*-----------------------------------------------------------------*/
4259 genCmpGt (iCode * ic, iCode * ifx)
4261 operand *left, *right, *result;
4262 sym_link *letype, *retype;
4265 D(emitcode ("; genCmpGt",""));
4267 result = IC_RESULT (ic);
4268 left = IC_LEFT (ic);
4269 right = IC_RIGHT (ic);
4271 letype = getSpec (operandType (left));
4272 retype = getSpec (operandType (right));
4273 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4274 /* assign the amsops */
4275 aopOp (left, ic, FALSE);
4276 aopOp (right, ic, FALSE);
4277 aopOp (result, ic, TRUE);
4279 genCmp (right, left, result, ifx, sign,ic);
4281 freeAsmop (result, NULL, ic, TRUE);
4284 /*-----------------------------------------------------------------*/
4285 /* genCmpLt - less than comparisons */
4286 /*-----------------------------------------------------------------*/
4288 genCmpLt (iCode * ic, iCode * ifx)
4290 operand *left, *right, *result;
4291 sym_link *letype, *retype;
4294 D(emitcode ("; genCmpLt",""));
4296 result = IC_RESULT (ic);
4297 left = IC_LEFT (ic);
4298 right = IC_RIGHT (ic);
4300 letype = getSpec (operandType (left));
4301 retype = getSpec (operandType (right));
4302 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4304 /* assign the amsops */
4305 aopOp (left, ic, FALSE);
4306 aopOp (right, ic, FALSE);
4307 aopOp (result, ic, TRUE);
4309 genCmp (left, right, result, ifx, sign,ic);
4311 freeAsmop (result, NULL, ic, TRUE);
4314 /*-----------------------------------------------------------------*/
4315 /* - compare and branch if not equal */
4316 /*-----------------------------------------------------------------*/
4318 gencbneshort (operand * left, operand * right, symbol * lbl)
4320 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4322 unsigned long lit = 0L;
4324 /* if the left side is a literal or
4325 if the right is in a pointer register and left
4327 if (AOP_TYPE (left) == AOP_LIT)
4333 if (AOP_TYPE (right) == AOP_LIT)
4334 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4338 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4339 accopWithAop ("cmp", AOP (right), offset);
4340 hc08_useReg (hc08_reg_a);
4341 hc08_freeReg (hc08_reg_a);
4342 emitBranch ("bne", lbl);
4348 /*-----------------------------------------------------------------*/
4349 /* gencjne - compare and jump if not equal */
4350 /*-----------------------------------------------------------------*/
4352 gencjne (operand * left, operand * right, symbol * lbl)
4354 symbol *tlbl = newiTempLabel (NULL);
4356 gencbneshort (left, right, lbl);
4358 loadRegFromConst (hc08_reg_a, one);
4359 emitBranch ("bra", tlbl);
4361 loadRegFromConst (hc08_reg_a, zero);
4364 hc08_useReg(hc08_reg_a);
4365 hc08_freeReg(hc08_reg_a);
4368 /*-----------------------------------------------------------------*/
4369 /* genCmpEq - generates code for equal to */
4370 /*-----------------------------------------------------------------*/
4372 genCmpEq (iCode * ic, iCode * ifx)
4374 operand *left, *right, *result;
4376 D(emitcode ("; genCmpEq",""));
4378 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4379 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4380 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4382 /* if literal, literal on the right or
4383 if the right is in a pointer register and left
4385 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4387 operand *t = IC_RIGHT (ic);
4388 IC_RIGHT (ic) = IC_LEFT (ic);
4392 if (ifx && !AOP_SIZE (result))
4395 tlbl = newiTempLabel (NULL);
4396 gencbneshort (left, right, tlbl);
4399 emitBranch ("jmp", IC_TRUE (ifx));
4404 symbol *lbl = newiTempLabel (NULL);
4405 emitBranch ("bra", lbl);
4407 emitBranch ("jmp", IC_FALSE (ifx));
4411 /* mark the icode as generated */
4416 gencjne (left, right, newiTempLabel (NULL));
4417 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4419 storeRegToAop (hc08_reg_a, AOP (result), 0);
4424 genIfxJump (ifx, "a");
4427 /* if the result is used in an arithmetic operation
4428 then put the result in place */
4429 if (AOP_TYPE (result) != AOP_CRY)
4433 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4434 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4435 freeAsmop (result, NULL, ic, TRUE);
4438 /*-----------------------------------------------------------------*/
4439 /* ifxForOp - returns the icode containing the ifx for operand */
4440 /*-----------------------------------------------------------------*/
4442 ifxForOp (operand * op, iCode * ic)
4444 /* if true symbol then needs to be assigned */
4445 if (IS_TRUE_SYMOP (op))
4448 /* if this has register type condition and
4449 the next instruction is ifx with the same operand
4450 and live to of the operand is upto the ifx only then */
4452 ic->next->op == IFX &&
4453 IC_COND (ic->next)->key == op->key &&
4454 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4461 genPointerGetSetOfs (iCode *ic)
4463 iCode *lic = ic->next;
4469 /* Make sure we have a next iCode */
4470 D(emitcode("","; checking lic"));
4474 /* Make sure the result of the addition is an iCode */
4475 D(emitcode("","; checking IS_ITEMP"));
4476 if (!IS_ITEMP (IC_RESULT (ic)))
4479 /* Make sure the next iCode is a pointer set or get */
4480 pset = POINTER_SET(lic);
4481 pget = POINTER_GET(lic);
4482 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4486 /* Make sure this is the only use of the pointer */
4487 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4490 D(emitcode("", "; checking pset operandsEqu"));
4491 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4494 D(emitcode("", "; checking pget operandsEqu"));
4495 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4498 D(emitcode("", "; checking IS_SYMOP"));
4499 if (!IS_SYMOP (IC_LEFT (ic)))
4502 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4503 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4506 sym = OP_SYMBOL (IC_LEFT (ic));
4508 D(emitcode("", "; checking remat"));
4515 D(emitcode ("; genPointerGetOfs",""));
4516 aopOp (IC_LEFT(ic), ic, FALSE);
4517 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4518 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4520 aopOp (IC_RIGHT(ic), ic, FALSE);
4521 aopOp (IC_RESULT(lic), lic, FALSE);
4523 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4525 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4527 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4528 loadRegFromConst (hc08_reg_h, zero);
4532 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4533 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4534 emitcode ("rola","");
4535 emitcode ("clra","");
4536 emitcode ("sbc", "#0");
4537 hc08_useReg (hc08_reg_a);
4538 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4542 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4543 size = AOP_SIZE (IC_RESULT(lic));
4544 derefaop->size = size;
4549 emitcode ("lda", "%s,x",
4550 aopAdrStr (derefaop, offset, TRUE));
4551 hc08_useReg (hc08_reg_a);
4552 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4553 hc08_freeReg (hc08_reg_a);
4557 hc08_freeReg (hc08_reg_hx);
4559 freeAsmop (NULL, derefaop, ic, TRUE);
4560 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4561 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4568 D(emitcode ("; genPointerSetOfs",""));
4569 aopOp (IC_LEFT(ic), ic, FALSE);
4570 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4571 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4573 aopOp (IC_RIGHT(ic), ic, FALSE);
4574 aopOp (IC_RIGHT(lic), lic, FALSE);
4576 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4578 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4580 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4581 loadRegFromConst (hc08_reg_h, zero);
4585 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4586 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4587 emitcode ("rola","");
4588 emitcode ("clra","");
4589 emitcode ("sbc", "#0");
4590 hc08_useReg (hc08_reg_a);
4591 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4595 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4596 size = AOP_SIZE (IC_RIGHT(lic));
4597 derefaop->size = size;
4602 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4603 emitcode ("sta", "%s,x",
4604 aopAdrStr (derefaop, offset, TRUE));
4605 hc08_freeReg (hc08_reg_a);
4610 hc08_freeReg (hc08_reg_hx);
4612 freeAsmop (NULL, derefaop, ic, TRUE);
4613 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4614 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4623 /*-----------------------------------------------------------------*/
4624 /* hasInc - operand is incremented before any other use */
4625 /*-----------------------------------------------------------------*/
4627 hasInc (operand *op, iCode *ic,int osize)
4629 sym_link *type = operandType(op);
4630 sym_link *retype = getSpec (type);
4631 iCode *lic = ic->next;
4634 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4635 if (!IS_SYMOP(op)) return NULL;
4637 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4638 if (IS_AGGREGATE(type->next)) return NULL;
4639 if (osize != (isize = getSize(type->next))) return NULL;
4642 /* if operand of the form op = op + <sizeof *op> */
4643 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4644 isOperandEqual(IC_RESULT(lic),op) &&
4645 isOperandLiteral(IC_RIGHT(lic)) &&
4646 operandLitValue(IC_RIGHT(lic)) == isize) {
4649 /* if the operand used or deffed */
4650 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4653 /* if GOTO or IFX */
4654 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4660 /*-----------------------------------------------------------------*/
4661 /* genAndOp - for && operation */
4662 /*-----------------------------------------------------------------*/
4664 genAndOp (iCode * ic)
4666 operand *left, *right, *result;
4667 symbol *tlbl, *tlbl0;
4669 D(emitcode ("; genAndOp",""));
4671 /* note here that && operations that are in an
4672 if statement are taken away by backPatchLabels
4673 only those used in arthmetic operations remain */
4674 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4675 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4676 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4678 tlbl = newiTempLabel (NULL);
4679 tlbl0 = newiTempLabel (NULL);
4681 asmopToBool (AOP (left), FALSE);
4682 emitBranch ("beq", tlbl0);
4683 asmopToBool (AOP (right), FALSE);
4684 emitBranch ("beq", tlbl0);
4685 loadRegFromConst (hc08_reg_a,one);
4686 emitBranch ("bra", tlbl);
4688 loadRegFromConst (hc08_reg_a,zero);
4691 hc08_useReg (hc08_reg_a);
4692 hc08_freeReg (hc08_reg_a);
4694 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4696 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4697 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4698 freeAsmop (result, NULL, ic, TRUE);
4702 /*-----------------------------------------------------------------*/
4703 /* genOrOp - for || operation */
4704 /*-----------------------------------------------------------------*/
4706 genOrOp (iCode * ic)
4708 operand *left, *right, *result;
4709 symbol *tlbl, *tlbl0;
4711 D(emitcode ("; genOrOp",""));
4713 /* note here that || operations that are in an
4714 if statement are taken away by backPatchLabels
4715 only those used in arthmetic operations remain */
4716 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4717 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4718 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4720 tlbl = newiTempLabel (NULL);
4721 tlbl0 = newiTempLabel (NULL);
4723 asmopToBool (AOP (left), FALSE);
4724 emitBranch ("bne", tlbl0);
4725 asmopToBool (AOP (right), FALSE);
4726 emitBranch ("bne", tlbl0);
4727 loadRegFromConst (hc08_reg_a,zero);
4728 emitBranch ("bra", tlbl);
4730 loadRegFromConst (hc08_reg_a,one);
4733 hc08_useReg (hc08_reg_a);
4734 hc08_freeReg (hc08_reg_a);
4736 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4739 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4740 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4741 freeAsmop (result, NULL, ic, TRUE);
4744 /*-----------------------------------------------------------------*/
4745 /* isLiteralBit - test if lit == 2^n */
4746 /*-----------------------------------------------------------------*/
4748 isLiteralBit (unsigned long lit)
4750 unsigned long pw[32] =
4751 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4752 0x100L, 0x200L, 0x400L, 0x800L,
4753 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4754 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4755 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4756 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4757 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4760 for (idx = 0; idx < 32; idx++)
4767 /*-----------------------------------------------------------------*/
4768 /* continueIfTrue - */
4769 /*-----------------------------------------------------------------*/
4771 continueIfTrue (iCode * ic)
4774 emitBranch ("jmp", IC_TRUE (ic));
4778 /*-----------------------------------------------------------------*/
4780 /*-----------------------------------------------------------------*/
4782 jumpIfTrue (iCode * ic)
4785 emitBranch ("jmp", IC_FALSE (ic));
4789 /*-----------------------------------------------------------------*/
4790 /* jmpTrueOrFalse - */
4791 /*-----------------------------------------------------------------*/
4793 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4795 // ugly but optimized by peephole
4798 symbol *nlbl = newiTempLabel (NULL);
4799 emitBranch ("bra", nlbl);
4801 emitBranch ("jmp", IC_TRUE (ic));
4806 emitBranch ("jmp", IC_FALSE (ic));
4813 /*-----------------------------------------------------------------*/
4814 /* genAnd - code for and */
4815 /*-----------------------------------------------------------------*/
4817 genAnd (iCode * ic, iCode * ifx)
4819 operand *left, *right, *result;
4820 int size, offset = 0;
4821 unsigned long lit = 0L;
4822 unsigned long litinv;
4823 unsigned char bytemask;
4829 D(emitcode ("; genAnd",""));
4831 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4832 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4833 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4836 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4838 AOP_TYPE (left), AOP_TYPE (right)));
4839 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4841 AOP_SIZE (left), AOP_SIZE (right)));
4844 /* if left is a literal & right is not then exchange them */
4845 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4847 operand *tmp = right;
4852 /* if right is accumulator & left is not then exchange them */
4853 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4855 operand *tmp = right;
4860 if (AOP_TYPE (right) == AOP_LIT)
4861 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4863 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4865 if (AOP_TYPE (result) == AOP_CRY
4867 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
4869 /* this generates ugly code, but meets volatility requirements */
4870 loadRegFromConst (hc08_reg_a, zero);
4871 pushReg (hc08_reg_a, TRUE);
4876 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4877 accopWithAop ("and", AOP (right), offset);
4878 emitcode ("ora", "1,s");
4879 emitcode ("sta", "1,s");
4883 pullReg (hc08_reg_a);
4884 emitcode ("tsta", "");
4885 genIfxJump (ifx, "a");
4889 if (AOP_TYPE (result) == AOP_CRY)
4891 symbol *tlbl = NULL;
4892 wassertl (ifx, "AOP_CRY result without ifx");
4897 bytemask = (lit >> (offset*8)) & 0xff;
4899 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
4903 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
4905 rmwWithAop ("tst", AOP (left), offset);
4909 tlbl = newiTempLabel (NULL);
4910 emitBranch ("bne", tlbl);
4915 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4916 accopWithAop ("and", AOP (right), offset);
4917 hc08_freeReg( hc08_reg_a);
4921 tlbl = newiTempLabel (NULL);
4922 emitBranch ("bne", tlbl);
4929 genIfxJump (ifx, "a");
4933 size = AOP_SIZE (result);
4935 if (AOP_TYPE (right) == AOP_LIT)
4937 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4938 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4939 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4941 int bitpos = isLiteralBit(litinv)-1;
4942 emitcode ("bclr","#%d,%s",bitpos & 7,
4943 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4951 bytemask = (lit >> (offset*8)) & 0xff;
4953 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
4955 if (isOperandVolatile (left, FALSE))
4957 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4958 hc08_freeReg( hc08_reg_a);
4960 storeConstToAop (zero, AOP (result), offset);
4962 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
4964 transferAopAop (AOP (left), offset, AOP (result), offset);
4968 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4969 accopWithAop ("and", AOP (right), offset);
4970 storeRegToAop (hc08_reg_a, AOP (result), offset);
4971 hc08_freeReg (hc08_reg_a);
4977 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4978 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4979 freeAsmop (result, NULL, ic, TRUE);
4982 /*-----------------------------------------------------------------*/
4983 /* genOr - code for or */
4984 /*-----------------------------------------------------------------*/
4986 genOr (iCode * ic, iCode * ifx)
4988 operand *left, *right, *result;
4989 int size, offset = 0;
4990 unsigned long lit = 0L;
4991 unsigned char bytemask;
4993 D(emitcode ("; genOr",""));
4995 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4996 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4997 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5000 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5002 AOP_TYPE (left), AOP_TYPE (right)));
5003 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5005 AOP_SIZE (left), AOP_SIZE (right)));
5008 /* if left is a literal & right is not then exchange them */
5009 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5011 operand *tmp = right;
5016 /* if left is accumulator & right is not then exchange them */
5017 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5019 operand *tmp = right;
5024 if (AOP_TYPE (right) == AOP_LIT)
5025 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5027 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5029 if (AOP_TYPE (result) == AOP_CRY
5031 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5033 /* this generates ugly code, but meets volatility requirements */
5034 loadRegFromConst (hc08_reg_a, zero);
5035 pushReg (hc08_reg_a, TRUE);
5040 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5041 accopWithAop ("ora", AOP (right), offset);
5042 emitcode ("ora", "1,s");
5043 emitcode ("sta", "1,s");
5047 pullReg (hc08_reg_a);
5048 emitcode ("tsta", "");
5049 genIfxJump (ifx, "a");
5053 if (AOP_TYPE (result) == AOP_CRY)
5055 symbol *tlbl = NULL;
5056 wassertl (ifx, "AOP_CRY result without ifx");
5061 bytemask = (lit >> (offset*8)) & 0xff;
5063 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5065 rmwWithAop ("tst", AOP (left), offset);
5069 tlbl = newiTempLabel (NULL);
5070 emitBranch ("bne", tlbl);
5075 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5076 accopWithAop ("ora", AOP (right), offset);
5077 hc08_freeReg( hc08_reg_a);
5081 tlbl = newiTempLabel (NULL);
5082 emitBranch ("bne", tlbl);
5089 genIfxJump (ifx, "a");
5092 if (AOP_TYPE (right) == AOP_LIT)
5093 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5095 size = AOP_SIZE (result);
5097 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5098 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5099 (AOP_TYPE (left) == AOP_DIR))
5101 int bitpos = isLiteralBit(lit)-1;
5102 emitcode ("bset","#%d,%s",bitpos & 7,
5103 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5110 bytemask = (lit >> (offset*8)) & 0xff;
5112 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5114 if (isOperandVolatile (left, FALSE))
5116 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5117 hc08_freeReg( hc08_reg_a);
5119 transferAopAop (AOP (right), offset, AOP (result), offset);
5121 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5123 transferAopAop (AOP (left), offset, AOP (result), offset);
5127 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5128 accopWithAop ("ora", AOP (right), offset);
5129 storeRegToAop (hc08_reg_a, AOP (result), offset);
5130 hc08_freeReg (hc08_reg_a);
5137 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5138 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5139 freeAsmop (result, NULL, ic, TRUE);
5142 /*-----------------------------------------------------------------*/
5143 /* genXor - code for xclusive or */
5144 /*-----------------------------------------------------------------*/
5146 genXor (iCode * ic, iCode * ifx)
5148 operand *left, *right, *result;
5149 int size, offset = 0;
5150 unsigned long lit = 0L;
5152 D(emitcode ("; genXor",""));
5154 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5155 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5156 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5159 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5161 AOP_TYPE (left), AOP_TYPE (right)));
5162 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5164 AOP_SIZE (left), AOP_SIZE (right)));
5167 /* if left is a literal & right is not ||
5168 if left needs acc & right does not */
5169 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5171 operand *tmp = right;
5176 /* if left is accumulator & right is not then exchange them */
5177 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5179 operand *tmp = right;
5184 if (AOP_TYPE (result) == AOP_CRY)
5187 wassertl (ifx, "AOP_CPY result without ifx");
5189 tlbl = newiTempLabel (NULL);
5190 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5194 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5195 if ((AOP_TYPE (right) == AOP_LIT)
5196 && (((lit >> (offset*8)) & 0xff) == 0))
5197 emitcode ("tsta","");
5199 accopWithAop ("eor", AOP (right), offset);
5200 hc08_freeReg( hc08_reg_a);
5202 emitBranch ("bne", tlbl);
5206 genIfxJump (ifx, "a");
5212 if (AOP_TYPE (right) == AOP_LIT)
5213 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5215 size = AOP_SIZE (result);
5219 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5220 accopWithAop ("eor", AOP (right), offset);
5221 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5222 hc08_freeReg( hc08_reg_a);
5226 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5227 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5228 freeAsmop (result, NULL, ic, TRUE);
5232 emitinline (iCode * ic, char *inlin)
5238 symbol *sym, *tempsym;
5247 while (isalnum(*inlin) || (*inlin == '_'))
5251 //printf("Found possible symbol '%s'\n",symname);
5252 tempsym = newSymbol (symname, ic->level);
5253 tempsym->block = ic->block;
5254 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5263 aop = aopForSym (ic, sym, FALSE);
5264 l = aopAdrStr (aop, aop->size - 1, TRUE);
5268 if (!sym->allocreq && !sym->ismyparm)
5270 werror (E_ID_UNDEF, sym->name);
5272 " Add 'volatile' to the variable declaration so that it\n"
5273 " can be referenced within inline assembly");
5275 //printf("Replacing with '%s'\n",l);
5279 if ((2+bp-buffer)>sizeof(buffer))
5288 if ((2+bp-buffer)>sizeof(buffer))
5295 if ((2+bp-buffer)>sizeof(buffer))
5296 fprintf(stderr, "Inline assembly buffer overflow\n");
5298 //printf("%s\n",buffer);
5299 emitcode (buffer,"");
5303 /*-----------------------------------------------------------------*/
5304 /* genInline - write the inline code out */
5305 /*-----------------------------------------------------------------*/
5307 genInline (iCode * ic)
5309 char *buffer, *bp, *bp1;
5311 D(emitcode ("; genInline",""));
5313 _G.inLine += (!options.asmpeep);
5315 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5316 strcpy (buffer, IC_INLINE (ic));
5318 /* emit each line as a code */
5324 /* emitcode (bp1, ""); */
5325 emitinline (ic, bp1);
5344 /* emitcode (bp1, ""); */
5345 emitinline (ic, bp1);
5347 /* emitcode("",buffer); */
5348 _G.inLine -= (!options.asmpeep);
5351 /*-----------------------------------------------------------------*/
5352 /* genRRC - rotate right with carry */
5353 /*-----------------------------------------------------------------*/
5357 operand *left, *result;
5358 int size, offset = 0;
5359 bool needpula = FALSE;
5360 bool resultInA = FALSE;
5363 D(emitcode ("; genRRC",""));
5365 /* rotate right with carry */
5366 left = IC_LEFT (ic);
5367 result = IC_RESULT (ic);
5368 aopOp (left, ic, FALSE);
5369 aopOp (result, ic, FALSE);
5371 if ((AOP_TYPE (result) == AOP_REG)
5372 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5375 size = AOP_SIZE (result);
5379 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5383 rmwWithAop (shift, AOP (result), offset--);
5391 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5392 rmwWithReg (shift, hc08_reg_a);
5393 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5394 hc08_freeReg (hc08_reg_a);
5399 if ((!hc08_reg_a->isFree) || resultInA)
5401 pushReg (hc08_reg_a, TRUE);
5405 /* now we need to put the carry into the
5406 highest order byte of the result */
5407 offset = AOP_SIZE (result) - 1;
5408 emitcode ("clra","");
5409 emitcode ("rora","");
5410 hc08_dirtyReg (hc08_reg_a, FALSE);
5413 emitcode ("ora", "1,s");
5414 emitcode ("ais", "#1");
5415 hc08_dirtyReg (hc08_reg_a, FALSE);
5419 accopWithAop ("ora", AOP (result), offset);
5420 storeRegToAop (hc08_reg_a, AOP (result), offset);
5422 pullOrFreeReg (hc08_reg_a, needpula);
5424 freeAsmop (left, NULL, ic, TRUE);
5425 freeAsmop (result, NULL, ic, TRUE);
5428 /*-----------------------------------------------------------------*/
5429 /* genRLC - generate code for rotate left with carry */
5430 /*-----------------------------------------------------------------*/
5434 operand *left, *result;
5435 int size, offset = 0;
5437 bool resultInA = FALSE;
5438 bool needpula = FALSE;
5440 D(emitcode ("; genRLC",""));
5442 /* rotate right with carry */
5443 left = IC_LEFT (ic);
5444 result = IC_RESULT (ic);
5445 aopOp (left, ic, FALSE);
5446 aopOp (result, ic, FALSE);
5448 if ((AOP_TYPE (result) == AOP_REG)
5449 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5452 size = AOP_SIZE (result);
5456 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5460 rmwWithAop (shift, AOP (result), offset--);
5468 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5469 rmwWithReg (shift, hc08_reg_a);
5470 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5471 hc08_freeReg (hc08_reg_a);
5476 if ((!hc08_reg_a->isFree) || resultInA)
5478 pushReg (hc08_reg_a, TRUE);
5482 /* now we need to put the carry into the
5483 lowest order byte of the result */
5485 emitcode ("clra","");
5486 emitcode ("rola","");
5487 hc08_dirtyReg (hc08_reg_a, FALSE);
5490 emitcode ("ora", "1,s");
5491 emitcode ("ais", "#1");
5492 hc08_dirtyReg (hc08_reg_a, FALSE);
5496 accopWithAop ("ora", AOP (result), offset);
5497 storeRegToAop (hc08_reg_a, AOP (result), offset);
5499 pullOrFreeReg (hc08_reg_a, needpula);
5501 freeAsmop (left, NULL, ic, TRUE);
5502 freeAsmop (result, NULL, ic, TRUE);
5505 /*-----------------------------------------------------------------*/
5506 /* genGetHbit - generates code get highest order bit */
5507 /*-----------------------------------------------------------------*/
5509 genGetHbit (iCode * ic)
5511 operand *left, *result;
5513 D(emitcode ("; genGetHbit",""));
5515 left = IC_LEFT (ic);
5516 result = IC_RESULT (ic);
5517 aopOp (left, ic, FALSE);
5518 aopOp (result, ic, FALSE);
5520 /* get the highest order byte into a */
5521 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5522 emitcode ("rola", "");
5523 emitcode ("clra", "");
5524 emitcode ("rola", "");
5525 hc08_dirtyReg (hc08_reg_a, FALSE);
5526 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5527 hc08_freeReg (hc08_reg_a);
5529 freeAsmop (left, NULL, ic, TRUE);
5530 freeAsmop (result, NULL, ic, TRUE);
5533 /*-----------------------------------------------------------------*/
5534 /* genSwap - generates code to swap nibbles or bytes */
5535 /*-----------------------------------------------------------------*/
5537 genSwap (iCode * ic)
5539 operand *left, *result;
5541 D(emitcode ("; genSwap",""));
5543 left = IC_LEFT (ic);
5544 result = IC_RESULT (ic);
5545 aopOp (left, ic, FALSE);
5546 aopOp (result, ic, FALSE);
5548 switch (AOP_SIZE (left))
5550 case 1: /* swap nibbles in byte */
5551 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5552 emitcode ("nsa", "");
5553 hc08_dirtyReg (hc08_reg_a, FALSE);
5554 storeRegToAop (hc08_reg_a, AOP (result), 0);
5555 hc08_freeReg (hc08_reg_a);
5557 case 2: /* swap bytes in a word */
5558 if (operandsEqu (left, result))
5560 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5561 hc08_useReg (hc08_reg_a);
5562 transferAopAop (AOP (left), 1, AOP (result), 0);
5563 storeRegToAop (hc08_reg_a, AOP (result), 1);
5564 hc08_freeReg (hc08_reg_a);
5568 transferAopAop (AOP (left), 0, AOP (result), 1);
5569 transferAopAop (AOP (left), 1, AOP (result), 0);
5573 wassertl(FALSE, "unsupported SWAP operand size");
5576 freeAsmop (left, NULL, ic, TRUE);
5577 freeAsmop (result, NULL, ic, TRUE);
5581 /*-----------------------------------------------------------------*/
5582 /* AccRol - rotate left accumulator by known count */
5583 /*-----------------------------------------------------------------*/
5585 AccRol (int shCount)
5587 shCount &= 0x0007; // shCount : 0..7
5594 emitcode ("rola", ""); /* 1 cycle */
5597 emitcode ("rola", ""); /* 1 cycle */
5598 emitcode ("rola", ""); /* 1 cycle */
5601 emitcode ("nsa", "");
5602 emitcode ("rora", "");
5605 emitcode ("nsa", ""); /* 3 cycles */
5608 emitcode ("nsa", ""); /* 3 cycles */
5609 emitcode ("rola", ""); /* 1 cycle */
5612 emitcode ("nsa", ""); /* 3 cycles */
5613 emitcode ("rola", ""); /* 1 cycle */
5614 emitcode ("rola", ""); /* 1 cycle */
5617 emitcode ("nsa", ""); /* 3 cycles */
5618 emitcode ("rola", ""); /* 1 cycle */
5619 emitcode ("rola", ""); /* 1 cycle */
5620 emitcode ("rola", ""); /* 1 cycle */
5627 /*-----------------------------------------------------------------*/
5628 /* AccLsh - left shift accumulator by known count */
5629 /*-----------------------------------------------------------------*/
5631 AccLsh (int shCount)
5635 shCount &= 0x0007; // shCount : 0..7
5637 /* Shift counts of 4 and 5 are currently optimized for code size. */
5638 /* Falling through to the unrolled loop would be optimal for code speed. */
5639 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5643 accopWithMisc ("nsa", "");
5644 accopWithMisc ("and", "#0xf0");
5645 /* total: 5 cycles, 3 bytes */
5648 accopWithMisc ("nsa", "");
5649 accopWithMisc ("and", "#0xf0");
5650 accopWithMisc ("lsla", "");
5651 /* total: 6 cycles, 4 bytes */
5654 accopWithMisc ("rora", "");
5655 accopWithMisc ("rora", "");
5656 accopWithMisc ("rora", "");
5657 accopWithMisc ("and", "#0xc0");
5658 /* total: 5 cycles, 5 bytes */
5661 accopWithMisc ("rora", "");
5662 accopWithMisc ("clra", "");
5663 accopWithMisc ("rora", "");
5664 /* total: 3 cycles, 3 bytes */
5668 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5669 /* the fastest (shCount<6) and shortest (shCount<4). */
5670 for (i=0;i<shCount;i++)
5671 accopWithMisc ("lsla", "");
5675 /*-----------------------------------------------------------------*/
5676 /* AccSRsh - signed right shift accumulator by known count */
5677 /*-----------------------------------------------------------------*/
5679 AccSRsh (int shCount)
5683 shCount &= 0x0007; // shCount : 0..7
5687 accopWithMisc ("rola", "");
5688 accopWithMisc ("clra", "");
5689 accopWithMisc ("sbc", zero);
5690 /* total: 4 cycles, 4 bytes */
5694 for (i=0;i<shCount;i++)
5695 accopWithMisc ("asra", "");
5698 /*-----------------------------------------------------------------*/
5699 /* AccRsh - right shift accumulator by known count */
5700 /*-----------------------------------------------------------------*/
5702 AccRsh (int shCount, bool sign)
5712 shCount &= 0x0007; // shCount : 0..7
5714 /* Shift counts of 4 and 5 are currently optimized for code size. */
5715 /* Falling through to the unrolled loop would be optimal for code speed. */
5716 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5720 accopWithMisc ("nsa", "");
5721 accopWithMisc ("and", "#0x0f");
5722 /* total: 5 cycles, 3 bytes */
5725 accopWithMisc ("nsa", "");
5726 accopWithMisc ("and", "#0x0f");
5727 accopWithMisc ("lsra", "");
5728 /* total: 6 cycles, 4 bytes */
5731 accopWithMisc ("rola", "");
5732 accopWithMisc ("rola", "");
5733 accopWithMisc ("rola", "");
5734 accopWithMisc ("and", "#0x03");
5735 /* total: 5 cycles, 5 bytes */
5738 accopWithMisc ("rola", "");
5739 accopWithMisc ("clra", "");
5740 accopWithMisc ("rola", "");
5741 /* total: 3 cycles, 3 bytes */
5745 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5746 /* the fastest (shCount<6) and shortest (shCount<4). */
5747 for (i=0;i<shCount;i++)
5748 accopWithMisc ("lsra", "");
5752 /*-----------------------------------------------------------------*/
5753 /* XAccLsh - left shift register pair XA by known count */
5754 /*-----------------------------------------------------------------*/
5756 XAccLsh (int shCount)
5760 shCount &= 0x000f; // shCount : 0..15
5765 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5766 loadRegFromConst (hc08_reg_a, zero);
5770 /* if we can beat 2n cycles or bytes for some special case, do it here */
5774 /* bytes cycles reg x reg a carry
5775 ** abcd efgh ijkl mnop ?
5776 ** lsrx 1 1 0abc defg ijkl mnop h
5777 ** rora 1 1 0abc defg hijk lmno p
5778 ** tax 1 1 hijk lmno hijk lmno p
5779 ** clra 1 1 hijk lmno 0000 0000 p
5780 ** rora 1 1 hijk lmno p000 0000 0
5781 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5783 rmwWithReg ("lsr", hc08_reg_x);
5784 rmwWithReg ("ror", hc08_reg_a);
5785 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5786 loadRegFromConst (hc08_reg_a, zero);
5787 rmwWithReg ("ror", hc08_reg_a);
5794 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5795 /* the fastest and shortest. */
5796 for (i=0;i<shCount;i++)
5798 rmwWithReg ("lsl", hc08_reg_a);
5799 rmwWithReg ("rol", hc08_reg_x);
5803 /*-----------------------------------------------------------------*/
5804 /* XAccSRsh - signed right shift register pair XA by known count */
5805 /*-----------------------------------------------------------------*/
5807 XAccSRsh (int shCount)
5811 shCount &= 0x000f; // shCount : 0..7
5813 /* if we can beat 2n cycles or bytes for some special case, do it here */
5817 /* bytes cycles reg x reg a carry
5818 ** abcd efgh ijkl mnop ?
5819 ** lslx 1 1 bcde fgh0 ijkl mnop a
5820 ** clra 1 1 bcde fgh0 0000 0000 a
5821 ** rola 1 1 bcde fgh0 0000 000a 0
5822 ** nega 1 1 bcde fgh0 aaaa aaaa a
5823 ** tax 1 1 aaaa aaaa aaaa aaaa a
5824 ** total: 5 cycles, 5 bytes
5826 rmwWithReg ("lsl", hc08_reg_x);
5827 loadRegFromConst (hc08_reg_a, zero);
5828 rmwWithReg ("rol", hc08_reg_a);
5829 rmwWithReg ("neg", hc08_reg_a);
5830 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5840 /* bytes cycles reg x reg a carry
5841 ** abcd efgh ijkl mnop ?
5842 ** txa 1 1 abcd efgh abcd efgh ?
5843 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5844 ** lsla 1 1 abcd efgh ???? ???? a
5845 ** clrx 1 1 0000 0000 ???? ???? a
5846 ** rolx 1 1 0000 000a ???? ???? 0
5847 ** negx 1 1 aaaa aaaa ???? ???? a
5848 ** rora 1 1 aaaa aaaa LSBresult 0
5849 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5851 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5852 AccSRsh (shCount-8);
5853 rmwWithReg ("lsl", hc08_reg_a);
5854 loadRegFromConst (hc08_reg_x, zero);
5855 rmwWithReg ("rol", hc08_reg_x);
5856 rmwWithReg ("neg", hc08_reg_x);
5857 rmwWithReg ("ror", hc08_reg_a);
5864 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5865 /* the fastest and shortest. */
5866 for (i=0;i<shCount;i++)
5868 rmwWithReg ("asr", hc08_reg_x);
5869 rmwWithReg ("ror", hc08_reg_a);
5873 /*-----------------------------------------------------------------*/
5874 /* XAccRsh - right shift register pair XA by known count */
5875 /*-----------------------------------------------------------------*/
5877 XAccRsh (int shCount, bool sign)
5887 shCount &= 0x000f; // shCount : 0..f
5889 /* if we can beat 2n cycles or bytes for some special case, do it here */
5893 /* bytes cycles reg x reg a carry
5894 ** abcd efgh ijkl mnop ?
5895 ** clra 1 1 abcd efgh 0000 0000 a
5896 ** lslx 1 1 bcde fgh0 0000 0000 a
5897 ** rola 1 1 bcde fgh0 0000 000a 0
5898 ** clrx 1 1 0000 0000 0000 000a 0
5899 ** total: 4 cycles, 4 bytes
5901 loadRegFromConst (hc08_reg_x, zero);
5902 rmwWithReg ("lsl", hc08_reg_x);
5903 rmwWithReg ("rol", hc08_reg_a);
5904 loadRegFromConst (hc08_reg_a, zero);
5908 /* bytes cycles reg x reg a carry
5909 ** abcd efgh ijkl mnop ?
5910 ** clra 1 1 abcd efgh 0000 0000 a
5911 ** lslx 1 1 bcde fgh0 0000 0000 a
5912 ** rola 1 1 bcde fgh0 0000 000a 0
5913 ** lslx 1 1 cdef gh00 0000 000a b
5914 ** rola 1 1 cdef gh00 0000 00ab 0
5915 ** clrx 1 1 0000 0000 0000 00ab 0
5916 ** total: 6 cycles, 6 bytes
5918 loadRegFromConst (hc08_reg_x, zero);
5919 rmwWithReg ("lsl", hc08_reg_x);
5920 rmwWithReg ("rol", hc08_reg_a);
5921 rmwWithReg ("lsl", hc08_reg_x);
5922 rmwWithReg ("rol", hc08_reg_a);
5923 loadRegFromConst (hc08_reg_a, zero);
5932 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5933 AccRsh (shCount-8, FALSE);
5934 loadRegFromConst (hc08_reg_x, zero);
5938 /* bytes cycles reg x reg a carry
5939 ** abcd efgh ijkl mnop ?
5940 ** lsla 1 1 abcd efgh jklm nop0 i
5941 ** txa 1 1 abcd efgh abcd efgh i
5942 ** rola 1 1 abcd efgh bcde fghi a
5943 ** clrx 1 1 0000 0000 bcde fghi a
5944 ** rolx 1 1 0000 000a bcde fghi 0
5945 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5947 rmwWithReg ("lsl", hc08_reg_a);
5948 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5949 rmwWithReg ("rol", hc08_reg_a);
5950 loadRegFromConst (hc08_reg_x, zero);
5951 rmwWithReg ("rol", hc08_reg_x);
5954 /* bytes cycles reg x reg a carry
5955 ** abcd efgh ijkl mnop ?
5956 ** lsla 1 1 abcd efgh jklm nop0 i
5957 ** rolx 1 1 bcde fghi jklm nop0 a
5958 ** rola 1 1 bcde fghi klmn op0a j
5959 ** rolx 1 1 cdef ghij klmn op0a b
5960 ** rola 1 1 cdef ghij lmno p0ab k
5961 ** and #3 2 2 cdef ghij 0000 00ab k
5962 ** psha 1 2 cdef ghij 0000 00ab k
5963 ** txa 1 1 cdef ghij cdef ghij k
5964 ** pula 1 2 0000 00ab cdef ghij k
5965 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5971 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5972 /* the fastest and shortest. */
5973 for (i=0;i<shCount;i++)
5975 rmwWithReg ("lsr", hc08_reg_x);
5976 rmwWithReg ("ror", hc08_reg_a);
5983 /*-----------------------------------------------------------------*/
5984 /* shiftR1Left2Result - shift right one byte from left to result */
5985 /*-----------------------------------------------------------------*/
5987 shiftR1Left2Result (operand * left, int offl,
5988 operand * result, int offr,
5989 int shCount, int sign)
5991 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5992 /* shift right accumulator */
5993 AccRsh (shCount, sign);
5994 storeRegToAop (hc08_reg_a, AOP (result), offr);
5998 /*-----------------------------------------------------------------*/
5999 /* shiftL1Left2Result - shift left one byte from left to result */
6000 /*-----------------------------------------------------------------*/
6002 shiftL1Left2Result (operand * left, int offl,
6003 operand * result, int offr, int shCount)
6005 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6006 /* shift left accumulator */
6008 storeRegToAop (hc08_reg_a, AOP (result), offr);
6011 /*-----------------------------------------------------------------*/
6012 /* movLeft2Result - move byte from left to result */
6013 /*-----------------------------------------------------------------*/
6015 movLeft2Result (operand * left, int offl,
6016 operand * result, int offr, int sign)
6018 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6020 transferAopAop (AOP (left), offl, AOP (result), offr);
6025 /*-----------------------------------------------------------------*/
6026 /* shiftL2Left2Result - shift left two bytes from left to result */
6027 /*-----------------------------------------------------------------*/
6029 shiftL2Left2Result (operand * left, int offl,
6030 operand * result, int offr, int shCount)
6033 bool needpula = FALSE;
6034 bool needpulx = FALSE;
6036 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6037 needpula = pushRegIfUsed (hc08_reg_a);
6040 if (!IS_AOP_XA (AOP (left)))
6041 needpulx = pushRegIfUsed (hc08_reg_x);
6045 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6050 rmwWithReg ("lsr", hc08_reg_x);
6051 rmwWithReg ("ror", hc08_reg_a);
6052 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6053 rmwWithReg ("clr", hc08_reg_a);
6054 rmwWithReg ("ror", hc08_reg_a);
6057 for (i=0; i<shCount; i++)
6059 rmwWithReg ("lsl", hc08_reg_a);
6060 rmwWithReg ("rol", hc08_reg_x);
6063 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6065 pullOrFreeReg (hc08_reg_x, needpulx);
6066 pullOrFreeReg (hc08_reg_a, needpula);
6072 /*-----------------------------------------------------------------*/
6073 /* shiftR2Left2Result - shift right two bytes from left to result */
6074 /*-----------------------------------------------------------------*/
6076 shiftR2Left2Result (operand * left, int offl,
6077 operand * result, int offr,
6078 int shCount, int sign)
6081 bool needpula = FALSE;
6082 bool needpulx = FALSE;
6084 needpula = pushRegIfUsed (hc08_reg_a);
6085 needpulx = pushRegIfUsed (hc08_reg_x);
6087 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6088 for (i=0; i<shCount; i++)
6091 rmwWithReg ("asr", hc08_reg_x);
6093 rmwWithReg ("lsr", hc08_reg_x);
6094 rmwWithReg ("ror", hc08_reg_a);
6096 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6098 pullOrFreeReg (hc08_reg_x, needpulx);
6099 pullOrFreeReg (hc08_reg_a, needpula);
6104 /*-----------------------------------------------------------------*/
6105 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6106 /*-----------------------------------------------------------------*/
6108 shiftLLeftOrResult (operand * left, int offl,
6109 operand * result, int offr, int shCount)
6111 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6112 /* shift left accumulator */
6114 /* or with result */
6115 accopWithAop ("ora", AOP (result), offr);
6116 /* back to result */
6117 storeRegToAop (hc08_reg_a, AOP (result), offr);
6118 hc08_freeReg (hc08_reg_a);
6122 /*-----------------------------------------------------------------*/
6123 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6124 /*-----------------------------------------------------------------*/
6126 shiftRLeftOrResult (operand * left, int offl,
6127 operand * result, int offr, int shCount)
6129 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6130 /* shift left accumulator */
6131 AccRsh (shCount, FALSE);
6132 /* or with result */
6133 accopWithAop ("ora", AOP (result), offr);
6134 /* back to result */
6135 storeRegToAop (hc08_reg_a, AOP (result), offr);
6136 hc08_freeReg (hc08_reg_a);
6139 /*-----------------------------------------------------------------*/
6140 /* genlshOne - left shift a one byte quantity by known count */
6141 /*-----------------------------------------------------------------*/
6143 genlshOne (operand * result, operand * left, int shCount)
6145 D(emitcode ("; genlshOne",""));
6147 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6150 /*-----------------------------------------------------------------*/
6151 /* genlshTwo - left shift two bytes by known amount != 0 */
6152 /*-----------------------------------------------------------------*/
6154 genlshTwo (operand * result, operand * left, int shCount)
6158 D(emitcode ("; genlshTwo",""));
6161 size = getDataSize (result);
6163 /* if shCount >= 8 */
6170 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6172 storeRegToAop (hc08_reg_a, AOP (result), 1);
6174 storeConstToAop(zero, AOP (result), LSB);
6177 /* 1 <= shCount <= 7 */
6180 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6182 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6186 /*-----------------------------------------------------------------*/
6187 /* shiftLLong - shift left one long from left to result */
6188 /* offl = LSB or MSB16 */
6189 /*-----------------------------------------------------------------*/
6191 shiftLLong (operand * left, operand * result, int offr)
6194 // int size = AOP_SIZE (result);
6196 bool needpula = FALSE;
6197 bool needpulx = FALSE;
6199 needpula = pushRegIfUsed (hc08_reg_a);
6200 needpulx = pushRegIfUsed (hc08_reg_x);
6202 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6203 rmwWithReg ("lsl", hc08_reg_a);
6204 rmwWithReg ("rol", hc08_reg_x);
6205 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6209 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6210 rmwWithReg ("rol", hc08_reg_a);
6211 rmwWithReg ("rol", hc08_reg_x);
6212 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6214 else if (offr==MSB16)
6216 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6217 rmwWithReg ("rol", hc08_reg_a);
6218 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6221 pullOrFreeReg (hc08_reg_x, needpulx);
6222 pullOrFreeReg (hc08_reg_a, needpula);
6225 /*-----------------------------------------------------------------*/
6226 /* genlshFour - shift four byte by a known amount != 0 */
6227 /*-----------------------------------------------------------------*/
6229 genlshFour (operand * result, operand * left, int shCount)
6233 D(emitcode ("; genlshFour",""));
6235 size = AOP_SIZE (result);
6237 /* TODO: deal with the &result == &left case */
6239 /* if shifting more that 3 bytes */
6244 /* lowest order of left goes to the highest
6245 order of the destination */
6246 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6248 movLeft2Result (left, LSB, result, MSB32, 0);
6249 storeConstToAop (zero, AOP (result), LSB);
6250 storeConstToAop (zero, AOP (result), MSB16);
6251 storeConstToAop (zero, AOP (result), MSB24);
6255 /* more than two bytes */
6256 else if (shCount >= 16)
6258 /* lower order two bytes goes to higher order two bytes */
6260 /* if some more remaining */
6262 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6265 movLeft2Result (left, MSB16, result, MSB32, 0);
6266 movLeft2Result (left, LSB, result, MSB24, 0);
6268 storeConstToAop (zero, AOP (result), LSB);
6269 storeConstToAop (zero, AOP (result), MSB16);
6273 /* if more than 1 byte */
6274 else if (shCount >= 8)
6276 /* lower order three bytes goes to higher order three bytes */
6281 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6283 movLeft2Result (left, LSB, result, MSB16, 0);
6289 movLeft2Result (left, MSB24, result, MSB32, 0);
6290 movLeft2Result (left, MSB16, result, MSB24, 0);
6291 movLeft2Result (left, LSB, result, MSB16, 0);
6292 storeConstToAop (zero, AOP (result), LSB);
6294 else if (shCount == 1)
6295 shiftLLong (left, result, MSB16);
6298 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6299 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6300 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6301 storeConstToAop (zero, AOP (result), LSB);
6306 /* 1 <= shCount <= 7 */
6307 else if (shCount <= 2)
6309 shiftLLong (left, result, LSB);
6311 shiftLLong (result, result, LSB);
6313 /* 3 <= shCount <= 7, optimize */
6316 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6317 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6318 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6322 /*-----------------------------------------------------------------*/
6323 /* genLeftShiftLiteral - left shifting by known count */
6324 /*-----------------------------------------------------------------*/
6326 genLeftShiftLiteral (operand * left,
6331 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6334 D(emitcode ("; genLeftShiftLiteral",""));
6336 freeAsmop (right, NULL, ic, TRUE);
6338 aopOp (left, ic, FALSE);
6339 aopOp (result, ic, FALSE);
6341 // size = getSize (operandType (result));
6342 size = AOP_SIZE (result);
6345 D(emitcode ("; shift left ", "result %d, left %d", size,
6352 transferAopAop( AOP(left), size, AOP(result), size);
6354 else if (shCount >= (size * 8))
6357 storeConstToAop (zero, AOP (result), size);
6364 genlshOne (result, left, shCount);
6368 genlshTwo (result, left, shCount);
6372 genlshFour (result, left, shCount);
6375 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6376 "*** ack! mystery literal shift!\n");
6380 freeAsmop (left, NULL, ic, TRUE);
6381 freeAsmop (result, NULL, ic, TRUE);
6384 /*-----------------------------------------------------------------*/
6385 /* genLeftShift - generates code for left shifting */
6386 /*-----------------------------------------------------------------*/
6388 genLeftShift (iCode * ic)
6390 operand *left, *right, *result;
6392 symbol *tlbl, *tlbl1;
6397 D(emitcode ("; genLeftShift",""));
6399 right = IC_RIGHT (ic);
6400 left = IC_LEFT (ic);
6401 result = IC_RESULT (ic);
6403 aopOp (right, ic, FALSE);
6405 /* if the shift count is known then do it
6406 as efficiently as possible */
6407 if (AOP_TYPE (right) == AOP_LIT)
6409 genLeftShiftLiteral (left, right, result, ic);
6413 /* shift count is unknown then we have to form
6414 a loop get the loop count in A : Note: we take
6415 only the lower order byte since shifting
6416 more that 32 bits make no sense anyway, ( the
6417 largest size of an object can be only 32 bits ) */
6419 aopOp (left, ic, FALSE);
6420 aopOp (result, ic, FALSE);
6422 /* now move the left to the result if they are not the
6424 if (!sameRegs (AOP (left), AOP (result)))
6427 size = AOP_SIZE (result);
6431 transferAopAop (AOP (left), offset, AOP (result), offset);
6435 freeAsmop (left, NULL, ic, TRUE);
6437 tlbl = newiTempLabel (NULL);
6438 size = AOP_SIZE (result);
6440 tlbl1 = newiTempLabel (NULL);
6444 loadRegFromAop (reg, AOP (right), 0);
6445 freeAsmop (right, NULL, ic, TRUE);
6446 emitBranch ("beq", tlbl1);
6450 for (offset=0;offset<size;offset++)
6452 rmwWithAop (shift, AOP (result), offset);
6455 rmwWithReg ("dec", reg);
6456 emitBranch ("bne", tlbl);
6460 freeAsmop (result, NULL, ic, TRUE);
6463 /*-----------------------------------------------------------------*/
6464 /* genrshOne - right shift a one byte quantity by known count */
6465 /*-----------------------------------------------------------------*/
6467 genrshOne (operand * result, operand * left,
6468 int shCount, int sign)
6470 D(emitcode ("; genrshOne",""));
6472 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6473 AccRsh (shCount, sign);
6474 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6477 /*-----------------------------------------------------------------*/
6478 /* genrshTwo - right shift two bytes by known amount != 0 */
6479 /*-----------------------------------------------------------------*/
6481 genrshTwo (operand * result, operand * left,
6482 int shCount, int sign)
6484 D(emitcode ("; genrshTwo",""));
6486 /* if shCount >= 8 */
6489 if (shCount || sign)
6491 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6492 AccRsh (shCount-8, sign);
6493 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6497 transferAopAop (AOP (left), 1, AOP (result), 0);
6498 storeConstToAop (zero, AOP (result), 1);
6502 /* 1 <= shCount <= 7 */
6505 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6506 XAccRsh (shCount, sign);
6507 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6511 /*-----------------------------------------------------------------*/
6512 /* shiftRLong - shift right one long from left to result */
6513 /* offl = LSB or MSB16 */
6514 /*-----------------------------------------------------------------*/
6516 shiftRLong (operand * left, int offl,
6517 operand * result, int sign)
6520 // int size = AOP_SIZE (result);
6522 bool needpula = FALSE;
6523 bool needpulx = FALSE;
6525 needpula = pushRegIfUsed (hc08_reg_a);
6526 needpulx = pushRegIfUsed (hc08_reg_x);
6530 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6532 rmwWithReg ("asr", hc08_reg_x);
6534 rmwWithReg ("lsr", hc08_reg_x);
6535 rmwWithReg ("ror", hc08_reg_a);
6536 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6538 else if (offl==MSB16)
6540 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6542 rmwWithReg ("asr", hc08_reg_a);
6544 rmwWithReg ("lsr", hc08_reg_a);
6545 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6548 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6549 rmwWithReg ("ror", hc08_reg_x);
6550 rmwWithReg ("ror", hc08_reg_a);
6551 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6554 pullOrFreeReg (hc08_reg_x, needpulx);
6555 pullOrFreeReg (hc08_reg_a, needpula);
6558 /*-----------------------------------------------------------------*/
6559 /* genrshFour - shift four byte by a known amount != 0 */
6560 /*-----------------------------------------------------------------*/
6562 genrshFour (operand * result, operand * left,
6563 int shCount, int sign)
6565 /* TODO: handle cases where left == result */
6567 D(emitcode ("; genrshFour",""));
6569 /* if shifting more that 3 bytes */
6572 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6573 AccRsh (shCount-24, sign);
6574 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6577 else if (shCount >= 16)
6579 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6580 XAccRsh (shCount-16, sign);
6581 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6584 else if (shCount >= 8)
6587 shiftRLong (left, MSB16, result, sign);
6588 else if (shCount == 8)
6590 transferAopAop (AOP (left), 1, AOP (result), 0);
6591 transferAopAop (AOP (left), 2, AOP (result), 1);
6592 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6593 storeRegToAop (hc08_reg_a, AOP (result), 2);
6594 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6596 else if (shCount == 9)
6598 shiftRLong (left, MSB16, result, sign);
6602 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6603 XAccRsh (shCount-8, FALSE);
6604 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6605 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6606 loadRegFromConst (hc08_reg_a, zero);
6607 XAccRsh (shCount-8, sign);
6608 accopWithAop ("ora", AOP (result), 1);
6609 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6613 { /* 1 <= shCount <= 7 */
6616 shiftRLong (left, LSB, result, sign);
6620 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6621 XAccRsh (shCount, FALSE);
6622 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6623 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6625 accopWithAop ("ora", AOP (result), 1);
6626 storeRegToAop (hc08_reg_a, AOP (result), 1);
6627 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6628 XAccRsh (shCount, sign);
6629 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6634 /*-----------------------------------------------------------------*/
6635 /* genRightShiftLiteral - right shifting by known count */
6636 /*-----------------------------------------------------------------*/
6638 genRightShiftLiteral (operand * left,
6644 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6647 D(emitcode ("; genRightShiftLiteral",""));
6649 freeAsmop (right, NULL, ic, TRUE);
6651 aopOp (left, ic, FALSE);
6652 aopOp (result, ic, FALSE);
6655 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6659 size = getDataSize (left);
6660 /* test the LEFT size !!! */
6662 /* I suppose that the left size >= result size */
6665 size = getDataSize (result);
6667 transferAopAop (AOP (left), size, AOP(result), size);
6669 else if (shCount >= (size * 8))
6672 /* get sign in acc.7 */
6673 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6675 addSign (result, LSB, sign);
6682 genrshOne (result, left, shCount, sign);
6686 genrshTwo (result, left, shCount, sign);
6690 genrshFour (result, left, shCount, sign);
6696 freeAsmop (left, NULL, ic, TRUE);
6697 freeAsmop (result, NULL, ic, TRUE);
6701 /*-----------------------------------------------------------------*/
6702 /* genRightShift - generate code for right shifting */
6703 /*-----------------------------------------------------------------*/
6705 genRightShift (iCode * ic)
6707 operand *right, *left, *result;
6711 symbol *tlbl, *tlbl1;
6715 D(emitcode ("; genRightShift",""));
6717 /* if signed then we do it the hard way preserve the
6718 sign bit moving it inwards */
6719 retype = getSpec (operandType (IC_RESULT (ic)));
6720 sign = !SPEC_USIGN (retype);
6722 /* signed & unsigned types are treated the same : i.e. the
6723 signed is NOT propagated inwards : quoting from the
6724 ANSI - standard : "for E1 >> E2, is equivalent to division
6725 by 2**E2 if unsigned or if it has a non-negative value,
6726 otherwise the result is implementation defined ", MY definition
6727 is that the sign does not get propagated */
6729 right = IC_RIGHT (ic);
6730 left = IC_LEFT (ic);
6731 result = IC_RESULT (ic);
6733 aopOp (right, ic, FALSE);
6735 /* if the shift count is known then do it
6736 as efficiently as possible */
6737 if (AOP_TYPE (right) == AOP_LIT)
6739 genRightShiftLiteral (left, right, result, ic, sign);
6743 /* shift count is unknown then we have to form
6744 a loop get the loop count in X : Note: we take
6745 only the lower order byte since shifting
6746 more that 32 bits make no sense anyway, ( the
6747 largest size of an object can be only 32 bits ) */
6749 aopOp (left, ic, FALSE);
6750 aopOp (result, ic, FALSE);
6752 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6753 AOP (result) = forceStackedAop (AOP (result));
6755 size = AOP_SIZE (result);
6759 transferAopAop (AOP (left), offset, AOP (result), offset);
6763 tlbl = newiTempLabel (NULL);
6764 size = AOP_SIZE (result);
6766 tlbl1 = newiTempLabel (NULL);
6768 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6769 emitcode ("tstx", "");
6770 emitcode ("beq", "%05d$", tlbl1->key + 100);
6771 emitcode ("", "%05d$:", tlbl->key + 100);
6772 shift= sign ? "asr" : "lsr";
6773 for (offset=size-1;offset>=0;offset--)
6775 rmwWithAop (shift, AOP (result), offset);
6778 rmwWithReg ("dec", hc08_reg_x);
6779 emitcode ("bne","%05d$", tlbl->key + 100);
6780 emitcode ("", "%05d$:", tlbl1->key + 100);
6782 freeAsmop (result, NULL, ic, TRUE);
6783 freeAsmop (left, NULL, ic, TRUE);
6784 freeAsmop (right, NULL, ic, TRUE);
6788 /*-----------------------------------------------------------------*/
6789 /* genUnpackBits - generates code for unpacking bits */
6790 /*-----------------------------------------------------------------*/
6792 genUnpackBits (operand * result, iCode *ifx)
6794 int offset = 0; /* result byte offset */
6795 int rsize; /* result size */
6796 int rlen = 0; /* remaining bitfield length */
6797 sym_link *etype; /* bitfield type information */
6798 int blen; /* bitfield length */
6799 int bstr; /* bitfield starting bit within byte */
6801 D(emitcode ("; genUnpackBits",""));
6803 etype = getSpec (operandType (result));
6804 rsize = getSize (operandType (result));
6805 blen = SPEC_BLEN (etype);
6806 bstr = SPEC_BSTR (etype);
6808 /* If the bitfield length is less than a byte */
6811 emitcode ("lda", ",x");
6812 hc08_dirtyReg (hc08_reg_a, FALSE);
6815 AccRsh (bstr, FALSE);
6816 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6817 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6821 emitcode ("and", "#0x%02x",
6822 (((unsigned char) -1) >> (8 - blen)) << bstr);
6827 /* Bit field did not fit in a byte. Copy all
6828 but the partial byte at the end. */
6829 for (rlen=blen;rlen>=8;rlen-=8)
6831 emitcode ("lda", ",x");
6832 hc08_dirtyReg (hc08_reg_a, FALSE);
6834 storeRegToAop (hc08_reg_a, AOP (result), offset);
6837 emitcode ("aix", "#1");
6840 /* Handle the partial byte at the end */
6843 emitcode ("lda", ",x");
6844 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6845 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6853 storeConstToAop (zero, AOP (result), offset++);
6856 if (ifx && !ifx->generated)
6858 genIfxJump (ifx, "a");
6863 /*-----------------------------------------------------------------*/
6864 /* genUnpackBitsImmed - generates code for unpacking bits */
6865 /*-----------------------------------------------------------------*/
6867 genUnpackBitsImmed (operand * left,
6873 int offset = 0; /* result byte offset */
6874 int rsize; /* result size */
6875 int rlen = 0; /* remaining bitfield length */
6876 sym_link *etype; /* bitfield type information */
6877 int blen; /* bitfield length */
6878 int bstr; /* bitfield starting bit within byte */
6881 D(emitcode ("; genUnpackBitsImmed",""));
6883 aopOp (result, ic, TRUE);
6884 size = AOP_SIZE (result);
6886 derefaop = aopDerefAop (AOP (left));
6887 freeAsmop (left, NULL, ic, TRUE);
6888 derefaop->size = size;
6890 etype = getSpec (operandType (result));
6891 rsize = getSize (operandType (result));
6892 blen = SPEC_BLEN (etype);
6893 bstr = SPEC_BSTR (etype);
6895 /* if the bitfield is a single bit in the direct page */
6896 if (blen == 1 && derefaop->type == AOP_DIR)
6900 symbol *tlbl = newiTempLabel (NULL);
6902 loadRegFromConst (hc08_reg_a, zero);
6903 emitcode ("brclr", "#%d,%s,%05d$",
6904 bstr, aopAdrStr (derefaop, 0, FALSE),
6906 rmwWithReg ("inc", hc08_reg_a);
6908 storeRegToAop (hc08_reg_a, AOP (result), offset);
6909 hc08_freeReg (hc08_reg_a);
6915 symbol *tlbl = newiTempLabel (NULL);
6921 jlbl = IC_TRUE (ifx);
6926 jlbl = IC_FALSE (ifx);
6929 emitcode (inst, "#%d,%s,%05d$",
6930 bstr, aopAdrStr (derefaop, 0, FALSE),
6932 emitBranch ("jmp", jlbl);
6940 /* If the bitfield length is less than a byte */
6943 loadRegFromAop (hc08_reg_a, derefaop, 0);
6946 AccRsh (bstr, FALSE);
6947 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6948 hc08_dirtyReg (hc08_reg_a, FALSE);
6949 storeRegToAop (hc08_reg_a, AOP (result), offset);
6953 emitcode ("and", "#0x%02x",
6954 (((unsigned char) -1) >> (8 - blen)) << bstr);
6955 hc08_dirtyReg (hc08_reg_a, FALSE);
6961 /* Bit field did not fit in a byte. Copy all
6962 but the partial byte at the end. */
6963 for (rlen=blen;rlen>=8;rlen-=8)
6965 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6967 storeRegToAop (hc08_reg_a, AOP (result), offset);
6969 emitcode ("tsta", "");
6973 /* Handle the partial byte at the end */
6976 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6977 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6978 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6986 storeConstToAop (zero, AOP (result), offset++);
6989 freeAsmop (NULL, derefaop, ic, TRUE);
6990 freeAsmop (result, NULL, ic, TRUE);
6992 if (ifx && !ifx->generated)
6994 genIfxJump (ifx, "a");
6999 /*-----------------------------------------------------------------*/
7000 /* genDataPointerGet - generates code when ptr offset is known */
7001 /*-----------------------------------------------------------------*/
7003 genDataPointerGet (operand * left,
7008 int size, offset = 0;
7011 D(emitcode ("; genDataPointerGet",""));
7013 aopOp (result, ic, TRUE);
7014 size = AOP_SIZE (result);
7016 derefaop = aopDerefAop (AOP (left));
7017 freeAsmop (left, NULL, ic, TRUE);
7018 derefaop->size = size;
7023 transferAopAop (derefaop, offset, AOP (result), offset);
7025 loadRegFromAop (hc08_reg_a, derefaop, offset);
7029 freeAsmop (NULL, derefaop, ic, TRUE);
7030 freeAsmop (result, NULL, ic, TRUE);
7032 if (ifx && !ifx->generated)
7034 genIfxJump (ifx, "a");
7039 /*-----------------------------------------------------------------*/
7040 /* genPointerGet - generate code for pointer get */
7041 /*-----------------------------------------------------------------*/
7043 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7045 operand *left = IC_LEFT (ic);
7046 operand *result = IC_RESULT (ic);
7048 sym_link *retype = getSpec (operandType (result));
7050 D(emitcode ("; genPointerGet",""));
7052 if (getSize (operandType (result))>1)
7055 aopOp (left, ic, FALSE);
7057 /* if left is rematerialisable and
7058 result is not bit variable type */
7059 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7061 if (!IS_BITVAR (retype))
7063 genDataPointerGet (left, result, ic, ifx);
7068 genUnpackBitsImmed (left, result, ic, ifx);
7073 /* if the operand is already in hx
7074 then we do nothing else we move the value to hx */
7075 if (AOP_TYPE (left) != AOP_STR)
7077 /* if this is remateriazable */
7078 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7081 /* so hx now contains the address */
7082 aopOp (result, ic, FALSE);
7084 /* if bit then unpack */
7085 if (IS_BITVAR (retype))
7086 genUnpackBits (result, ifx);
7089 size = AOP_SIZE (result);
7094 accopWithMisc ("lda", ",x");
7097 emitcode ("aix", "#1");
7098 hc08_dirtyReg (hc08_reg_hx, FALSE);
7101 storeRegToAop (hc08_reg_a, AOP (result), offset);
7103 hc08_freeReg (hc08_reg_a);
7107 freeAsmop (left, NULL, ic, TRUE);
7108 freeAsmop (result, NULL, ic, TRUE);
7111 aopOp (IC_RESULT (pi), pi, FALSE);
7112 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7113 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7117 if (ifx && !ifx->generated)
7119 genIfxJump (ifx, "a");
7122 hc08_freeReg (hc08_reg_hx);
7126 /*-----------------------------------------------------------------*/
7127 /* genPackBits - generates code for packed bit storage */
7128 /*-----------------------------------------------------------------*/
7130 genPackBits (sym_link * etype,
7133 int offset = 0; /* source byte offset */
7134 int rlen = 0; /* remaining bitfield length */
7135 int blen; /* bitfield length */
7136 int bstr; /* bitfield starting bit within byte */
7137 int litval; /* source literal value (if AOP_LIT) */
7138 unsigned char mask; /* bitmask within current byte */
7141 D(emitcode ("; genPackBits",""));
7143 blen = SPEC_BLEN (etype);
7144 bstr = SPEC_BSTR (etype);
7146 /* If the bitfield length is less than a byte */
7149 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7150 (unsigned char) (0xFF >> (8 - bstr)));
7152 if (AOP_TYPE (right) == AOP_LIT)
7154 /* Case with a bitfield length <8 and literal source
7156 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7158 litval &= (~mask) & 0xff;
7160 emitcode ("lda", ",x");
7161 if ((mask|litval)!=0xff)
7162 emitcode ("and","#0x%02x", mask);
7164 emitcode ("ora","#0x%02x", litval);
7165 hc08_dirtyReg (hc08_reg_a, FALSE);
7166 emitcode ("sta", ",x");
7168 hc08_freeReg (hc08_reg_a);
7172 /* Case with a bitfield length < 8 and arbitrary source
7174 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7175 /* shift and mask source value */
7177 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7178 hc08_dirtyReg (hc08_reg_a, FALSE);
7179 pushReg (hc08_reg_a, TRUE);
7181 emitcode ("lda", ",x");
7182 emitcode ("and", "#0x%02x", mask);
7183 emitcode ("ora", "1,s");
7184 emitcode ("sta", ",x");
7185 pullReg (hc08_reg_a);
7187 hc08_freeReg (hc08_reg_a);
7191 /* Bit length is greater than 7 bits. In this case, copy */
7192 /* all except the partial byte at the end */
7193 for (rlen=blen;rlen>=8;rlen-=8)
7195 if (AOP (right)->type == AOP_DIR)
7197 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7202 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7203 emitcode ("sta", "%d,x", offset);
7208 /* If there was a partial byte at the end */
7211 mask = (((unsigned char) -1 << rlen) & 0xff);
7213 if (AOP_TYPE (right) == AOP_LIT)
7215 /* Case with partial byte and literal source
7217 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7218 litval >>= (blen-rlen);
7219 litval &= (~mask) & 0xff;
7220 emitcode ("lda", "%d,x", offset - xoffset);
7221 hc08_dirtyReg (hc08_reg_a, FALSE);
7222 if ((mask|litval)!=0xff)
7223 emitcode ("and","#0x%02x", mask);
7225 emitcode ("ora","#0x%02x", litval);
7226 emitcode ("sta", "%d,x", offset - xoffset);
7227 hc08_dirtyReg (hc08_reg_a, FALSE);
7228 hc08_freeReg (hc08_reg_a);
7232 /* Case with partial byte and arbitrary source
7234 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7235 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7236 hc08_dirtyReg (hc08_reg_a, FALSE);
7237 pushReg (hc08_reg_a, TRUE);
7239 emitcode ("lda", "%d,x", offset - xoffset);
7240 emitcode ("and", "#0x%02x", mask);
7241 emitcode ("ora", "1,s");
7242 emitcode ("sta", "%d,x", offset - xoffset);
7243 pullReg (hc08_reg_a);
7246 hc08_freeReg (hc08_reg_a);
7249 /*-----------------------------------------------------------------*/
7250 /* genPackBitsImmed - generates code for packed bit storage */
7251 /*-----------------------------------------------------------------*/
7253 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7257 int offset = 0; /* source byte offset */
7258 int rlen = 0; /* remaining bitfield length */
7259 int blen; /* bitfield length */
7260 int bstr; /* bitfield starting bit within byte */
7261 int litval; /* source literal value (if AOP_LIT) */
7262 unsigned char mask; /* bitmask within current byte */
7264 D(emitcode ("; genPackBitsImmed",""));
7266 blen = SPEC_BLEN (etype);
7267 bstr = SPEC_BSTR (etype);
7269 aopOp (right, ic, FALSE);
7270 size = AOP_SIZE (right);
7272 derefaop = aopDerefAop (AOP (result));
7273 freeAsmop (result, NULL, ic, TRUE);
7274 derefaop->size = size;
7276 /* if the bitfield is a single bit in the direct page */
7277 if (blen == 1 && derefaop->type == AOP_DIR)
7279 if (AOP_TYPE (right) == AOP_LIT)
7281 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7283 emitcode ((litval & 1) ? "bset" : "bclr",
7284 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7288 symbol *tlbl1 = newiTempLabel (NULL);
7289 symbol *tlbl2 = newiTempLabel (NULL);
7291 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7292 emitcode ("bit", "#1");
7293 emitBranch ("bne", tlbl1);
7294 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7295 emitBranch ("bra", tlbl2);
7297 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7299 hc08_freeReg (hc08_reg_a);
7304 /* If the bitfield length is less than a byte */
7307 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7308 (unsigned char) (0xFF >> (8 - bstr)));
7310 if (AOP_TYPE (right) == AOP_LIT)
7312 /* Case with a bitfield length <8 and literal source
7314 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7316 litval &= (~mask) & 0xff;
7318 loadRegFromAop (hc08_reg_a, derefaop, 0);
7319 if ((mask|litval)!=0xff)
7320 emitcode ("and","#0x%02x", mask);
7322 emitcode ("ora","#0x%02x", litval);
7323 hc08_dirtyReg (hc08_reg_a, FALSE);
7324 storeRegToAop (hc08_reg_a, derefaop, 0);
7326 hc08_freeReg (hc08_reg_a);
7330 /* Case with a bitfield length < 8 and arbitrary source
7332 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7333 /* shift and mask source value */
7335 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7336 hc08_dirtyReg (hc08_reg_a, FALSE);
7337 pushReg (hc08_reg_a, TRUE);
7339 loadRegFromAop (hc08_reg_a, derefaop, 0);
7340 emitcode ("and", "#0x%02x", mask);
7341 emitcode ("ora", "1,s");
7342 storeRegToAop (hc08_reg_a, derefaop, 0);
7343 pullReg (hc08_reg_a);
7345 hc08_freeReg (hc08_reg_a);
7349 /* Bit length is greater than 7 bits. In this case, copy */
7350 /* all except the partial byte at the end */
7351 for (rlen=blen;rlen>=8;rlen-=8)
7353 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7357 /* If there was a partial byte at the end */
7360 mask = (((unsigned char) -1 << rlen) & 0xff);
7362 if (AOP_TYPE (right) == AOP_LIT)
7364 /* Case with partial byte and literal source
7366 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7367 litval >>= (blen-rlen);
7368 litval &= (~mask) & 0xff;
7369 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7370 if ((mask|litval)!=0xff)
7371 emitcode ("and","#0x%02x", mask);
7373 emitcode ("ora","#0x%02x", litval);
7374 hc08_dirtyReg (hc08_reg_a, FALSE);
7375 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7376 hc08_dirtyReg (hc08_reg_a, FALSE);
7377 hc08_freeReg (hc08_reg_a);
7381 /* Case with partial byte and arbitrary source
7383 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7384 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7385 hc08_dirtyReg (hc08_reg_a, FALSE);
7386 pushReg (hc08_reg_a, TRUE);
7388 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7389 emitcode ("and", "#0x%02x", mask);
7390 emitcode ("ora", "1,s");
7391 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7392 pullReg (hc08_reg_a);
7395 hc08_freeReg (hc08_reg_a);
7398 freeAsmop (right, NULL, ic, TRUE);
7399 freeAsmop (NULL, derefaop, ic, TRUE);
7402 /*-----------------------------------------------------------------*/
7403 /* genDataPointerSet - remat pointer to data space */
7404 /*-----------------------------------------------------------------*/
7406 genDataPointerSet (operand * right,
7410 int size, offset = 0;
7413 D(emitcode ("; genDataPointerSet",""));
7415 aopOp (right, ic, FALSE);
7416 size = AOP_SIZE (right);
7418 derefaop = aopDerefAop (AOP (result));
7419 freeAsmop (result, NULL, ic, TRUE);
7420 derefaop->size = size;
7424 transferAopAop (AOP (right), offset, derefaop, offset);
7428 freeAsmop (right, NULL, ic, TRUE);
7429 freeAsmop (NULL, derefaop, ic, TRUE);
7433 /*-----------------------------------------------------------------*/
7434 /* genPointerSet - stores the value into a pointer location */
7435 /*-----------------------------------------------------------------*/
7437 genPointerSet (iCode * ic, iCode *pi)
7439 operand *right = IC_RIGHT (ic);
7440 operand *result = IC_RESULT (ic);
7441 sym_link *type, *etype;
7443 sym_link *retype = getSpec (operandType (right));
7444 sym_link *letype = getSpec (operandType (result));
7446 D(emitcode ("; genPointerSet",""));
7448 type = operandType (result);
7449 etype = getSpec (type);
7451 aopOp (result, ic, FALSE);
7453 /* if the result is rematerializable */
7454 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7456 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7458 genDataPointerSet (right, result, ic);
7463 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7468 /* if the operand is already in hx
7469 then we do nothing else we move the value to hx */
7470 if (AOP_TYPE (result) != AOP_STR)
7472 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7474 /* so hx now contains the address */
7475 aopOp (right, ic, FALSE);
7477 /* if bit then unpack */
7478 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7479 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7482 size = AOP_SIZE (right);
7487 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7488 accopWithMisc ("sta", ",x");
7491 emitcode ("aix", "#1");
7493 hc08_freeReg (hc08_reg_a);
7497 freeAsmop (result, NULL, ic, TRUE);
7498 freeAsmop (right, NULL, ic, TRUE);
7501 aopOp (IC_RESULT (pi), pi, FALSE);
7502 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7503 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7507 hc08_freeReg (hc08_reg_hx);
7511 /*-----------------------------------------------------------------*/
7512 /* genIfx - generate code for Ifx statement */
7513 /*-----------------------------------------------------------------*/
7515 genIfx (iCode * ic, iCode * popIc)
7517 operand *cond = IC_COND (ic);
7520 D(emitcode ("; genIfx",""));
7522 aopOp (cond, ic, FALSE);
7524 /* get the value into acc */
7525 if (AOP_TYPE (cond) != AOP_CRY)
7526 asmopToBool (AOP (cond), FALSE);
7529 /* the result is now in the accumulator */
7530 freeAsmop (cond, NULL, ic, TRUE);
7532 /* if there was something to be popped then do it */
7536 /* if the condition is a bit variable */
7537 if (isbit && IS_ITEMP (cond) &&
7539 genIfxJump (ic, SPIL_LOC (cond)->rname);
7540 else if (isbit && !IS_ITEMP (cond))
7541 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7543 genIfxJump (ic, "a");
7548 /*-----------------------------------------------------------------*/
7549 /* genAddrOf - generates code for address of */
7550 /*-----------------------------------------------------------------*/
7552 genAddrOf (iCode * ic)
7554 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7557 D(emitcode ("; genAddrOf",""));
7559 aopOp (IC_RESULT (ic), ic, FALSE);
7561 /* if the operand is on the stack then we
7562 need to get the stack offset of this
7566 /* if it has an offset then we need to compute
7568 hc08_useReg (hc08_reg_hx);
7569 emitcode ("tsx", "");
7570 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7571 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7572 hc08_freeReg (hc08_reg_hx);
7577 /* object not on stack then we need the name */
7578 size = AOP_SIZE (IC_RESULT (ic));
7583 char s[SDCC_NAME_MAX+10];
7586 sprintf (s, "#%s", sym->rname);
7589 sprintf (s, "#>%s", sym->rname);
7592 sprintf (s, "#(%s >> %d)",
7596 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7600 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7604 /*-----------------------------------------------------------------*/
7605 /* genAssign - generate code for assignment */
7606 /*-----------------------------------------------------------------*/
7608 genAssign (iCode * ic)
7610 operand *result, *right;
7612 // unsigned long lit = 0L;
7614 D(emitcode("; genAssign",""));
7616 result = IC_RESULT (ic);
7617 right = IC_RIGHT (ic);
7619 /* if they are the same */
7620 if (operandsEqu (result, right)) {
7624 aopOp (right, ic, FALSE);
7625 aopOp (result, ic, TRUE);
7627 /* if they are the same registers */
7628 if (sameRegs (AOP (right), AOP (result)))
7631 if ((AOP_TYPE (right) == AOP_LIT)
7632 && (IS_AOP_HX(AOP(result))))
7634 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7639 size = AOP_SIZE (result);
7644 transferAopAop (AOP (right), offset, AOP (result), offset);
7649 freeAsmop (right, NULL, ic, TRUE);
7650 freeAsmop (result, NULL, ic, TRUE);
7653 /*-----------------------------------------------------------------*/
7654 /* genJumpTab - genrates code for jump table */
7655 /*-----------------------------------------------------------------*/
7657 genJumpTab (iCode * ic)
7662 D(emitcode ("; genJumpTab",""));
7664 aopOp (IC_JTCOND (ic), ic, FALSE);
7665 /* get the condition into accumulator */
7666 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7667 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7668 /* multiply by three */
7669 pushReg (hc08_reg_a, FALSE);
7670 emitcode ("lsla", "");
7671 emitcode ("add","1,s");
7672 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7673 loadRegFromConst (hc08_reg_h, zero);
7674 pullReg (hc08_reg_a);
7676 jtab = newiTempLabel (NULL);
7677 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7678 emitcode ("", "%05d$:", jtab->key + 100);
7679 /* now generate the jump labels */
7680 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7681 jtab = setNextItem (IC_JTLABELS (ic)))
7682 emitcode ("jmp", "%05d$", jtab->key + 100);
7684 hc08_dirtyReg (hc08_reg_a, TRUE);
7685 hc08_dirtyReg (hc08_reg_hx, TRUE);
7688 /*-----------------------------------------------------------------*/
7689 /* genCast - gen code for casting */
7690 /*-----------------------------------------------------------------*/
7692 genCast (iCode * ic)
7694 operand *result = IC_RESULT (ic);
7695 sym_link *ctype = operandType (IC_LEFT (ic));
7696 sym_link *rtype = operandType (IC_RIGHT (ic));
7697 operand *right = IC_RIGHT (ic);
7700 D(emitcode("; genCast",""));
7702 /* if they are equivalent then do nothing */
7703 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7706 aopOp (right, ic, FALSE);
7707 aopOp (result, ic, FALSE);
7710 /* if they are the same size : or less */
7711 if (AOP_SIZE (result) <= AOP_SIZE (right))
7714 /* if they are in the same place */
7716 if (sameRegs (AOP (right), AOP (result)))
7720 /* if they in different places then copy */
7721 size = AOP_SIZE (result);
7725 transferAopAop(AOP (right), offset, AOP (result), offset);
7732 /* if the result is of type pointer */
7737 sym_link *type = operandType (right);
7738 sym_link *etype = getSpec (type);
7740 /* pointer to generic pointer */
7741 if (IS_GENPTR (ctype))
7744 p_type = DCL_TYPE (type);
7747 if (SPEC_SCLS(etype)==S_REGISTER) {
7748 // let's assume it is a generic pointer
7751 /* we have to go by the storage class */
7752 p_type = PTR_TYPE (SPEC_OCLS (etype));
7756 /* the first two bytes are known */
7757 size = GPTRSIZE - 1;
7761 transferAopAop(AOP (right), offset, AOP (result), offset);
7764 /* the last byte depending on type */
7767 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7772 // pointerTypeToGPByte will have bitched.
7776 sprintf(gpValStr, "#0x%d", gpVal);
7777 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7783 /* just copy the pointers */
7784 size = AOP_SIZE (result);
7788 transferAopAop(AOP (right), offset, AOP (result), offset);
7794 /* so we now know that the size of destination is greater
7795 than the size of the source */
7796 /* we move to result for the size of source */
7797 size = AOP_SIZE (right);
7801 transferAopAop(AOP (right), offset, AOP (result), offset);
7805 /* now depending on the sign of the source && destination */
7806 size = AOP_SIZE (result) - AOP_SIZE (right);
7807 /* if unsigned or not an integral type */
7808 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7811 storeConstToAop (zero, AOP (result), offset++);
7815 /* we need to extend the sign :{ */
7816 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7817 accopWithMisc ("rola", "");
7818 accopWithMisc ("clra", "");
7819 accopWithMisc ("sbc", zero);
7821 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7824 /* we are done hurray !!!! */
7827 freeAsmop (right, NULL, ic, TRUE);
7828 freeAsmop (result, NULL, ic, TRUE);
7832 /*-----------------------------------------------------------------*/
7833 /* genDjnz - generate decrement & jump if not zero instrucion */
7834 /*-----------------------------------------------------------------*/
7836 genDjnz (iCode * ic, iCode * ifx)
7842 D(emitcode ("; genDjnz",""));
7844 /* if the if condition has a false label
7845 then we cannot save */
7849 /* if the minus is not of the form
7851 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7852 !IS_OP_LITERAL (IC_RIGHT (ic)))
7855 if (operandLitValue (IC_RIGHT (ic)) != 1)
7858 /* dbnz doesn't support extended mode */
7859 if (isOperandInFarSpace (IC_RESULT (ic)))
7862 /* if the size of this greater than one then no
7864 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7866 aopOp (IC_RESULT (ic), ic, FALSE);
7867 if (AOP_SIZE (IC_RESULT (ic))>1)
7869 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7873 /* otherwise we can save BIG */
7874 lbl = newiTempLabel (NULL);
7875 lbl1 = newiTempLabel (NULL);
7878 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7881 emitBranch ("bra", lbl1);
7883 emitBranch ("jmp", IC_TRUE (ifx));
7886 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7891 /*-----------------------------------------------------------------*/
7892 /* genReceive - generate code for a receive iCode */
7893 /*-----------------------------------------------------------------*/
7895 genReceive (iCode * ic)
7899 D(emitcode ("; genReceive",""));
7901 aopOp (IC_RESULT (ic), ic, FALSE);
7902 size = AOP_SIZE (IC_RESULT (ic));
7907 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7908 AOP (IC_RESULT (ic)), offset);
7909 if (hc08_aop_pass[offset]->type == AOP_REG)
7910 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7915 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7918 /*-----------------------------------------------------------------*/
7919 /* genDummyRead - generate code for dummy read of volatiles */
7920 /*-----------------------------------------------------------------*/
7922 genDummyRead (iCode * ic)
7927 D(emitcode("; genDummyRead",""));
7930 if (op && IS_SYMOP (op))
7933 aopOp (op, ic, FALSE);
7935 size = AOP_SIZE (op);
7940 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7941 hc08_freeReg (hc08_reg_a);
7945 freeAsmop (op, NULL, ic, TRUE);
7948 if (op && IS_SYMOP (op))
7951 aopOp (op, ic, FALSE);
7953 size = AOP_SIZE (op);
7958 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7959 hc08_freeReg (hc08_reg_a);
7963 freeAsmop (op, NULL, ic, TRUE);
7967 /*-----------------------------------------------------------------*/
7968 /* genCritical - generate code for start of a critical sequence */
7969 /*-----------------------------------------------------------------*/
7971 genCritical (iCode *ic)
7973 D(emitcode("; genCritical",""));
7976 aopOp (IC_RESULT (ic), ic, TRUE);
7978 emitcode ("tpa", "");
7979 hc08_dirtyReg (hc08_reg_a, FALSE);
7980 emitcode ("sei", "");
7983 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7985 pushReg (hc08_reg_a, FALSE);
7987 hc08_freeReg (hc08_reg_a);
7989 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7992 /*-----------------------------------------------------------------*/
7993 /* genEndCritical - generate code for end of a critical sequence */
7994 /*-----------------------------------------------------------------*/
7996 genEndCritical (iCode *ic)
7998 D(emitcode("; genEndCritical",""));
8002 aopOp (IC_RIGHT (ic), ic, FALSE);
8003 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8004 emitcode ("tap", "");
8005 hc08_freeReg (hc08_reg_a);
8006 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8010 pullReg (hc08_reg_a);
8011 emitcode ("tap", "");
8017 /*-----------------------------------------------------------------*/
8018 /* genhc08Code - generate code for HC08 based controllers */
8019 /*-----------------------------------------------------------------*/
8021 genhc08Code (iCode * lic)
8028 lineHead = lineCurr = NULL;
8030 /* print the allocation information */
8031 if (allocInfo && currFunc)
8032 printAllocInfo (currFunc, codeOutFile);
8033 /* if debug information required */
8034 if (options.debug && currFunc)
8036 debugFile->writeFunction (currFunc, lic);
8039 if (IS_STATIC (currFunc->etype))
8040 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8042 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8046 /* stack pointer name */
8047 if (options.useXstack)
8052 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8054 hc08_aop_pass[0] = newAsmop (AOP_REG);
8055 hc08_aop_pass[0]->size=1;
8056 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8057 hc08_aop_pass[1] = newAsmop (AOP_REG);
8058 hc08_aop_pass[1]->size=1;
8059 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8060 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8061 hc08_aop_pass[2]->size=1;
8062 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8063 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8064 hc08_aop_pass[3]->size=1;
8065 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8067 for (ic = lic; ic; ic = ic->next)
8070 _G.current_iCode = ic;
8072 if (ic->level != clevel || ic->block != cblock)
8076 debugFile->writeScope(ic);
8082 if (ic->lineno && cln != ic->lineno)
8086 debugFile->writeCLine(ic);
8089 emitcode ("", "C$%s$%d$%d$%d ==.",
8090 FileBaseName (ic->filename), ic->lineno,
8091 ic->level, ic->block);
8095 if (!options.noCcodeInAsm) {
8096 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8097 printCLine(ic->filename, ic->lineno));
8101 if (options.iCodeInAsm) {
8105 for (i=0; i<6; i++) {
8106 sprintf (®sInUse[i],
8107 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8110 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8112 /* if the result is marked as
8113 spilt and rematerializable or code for
8114 this has already been generated then
8116 if (resultRemat (ic) || ic->generated)
8124 for (i=A_IDX;i<=XA_IDX;i++)
8126 reg = hc08_regWithIdx(i);
8128 emitcode("","; %s = %s offset %d", reg->name,
8129 aopName(reg->aop), reg->aopofs);
8132 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8134 sym = OP_SYMBOL (IC_LEFT (ic));
8135 if (sym->accuse == ACCUSE_HX)
8137 hc08_reg_h->isFree = FALSE;
8138 hc08_reg_x->isFree = FALSE;
8140 else if (sym->accuse == ACCUSE_XA)
8142 hc08_reg_a->isFree = FALSE;
8144 hc08_reg_x->isFree = FALSE;
8147 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8149 sym = OP_SYMBOL (IC_RIGHT (ic));
8150 if (sym->accuse == ACCUSE_HX)
8152 hc08_reg_h->isFree = FALSE;
8153 hc08_reg_x->isFree = FALSE;
8155 else if (sym->accuse == ACCUSE_XA)
8157 hc08_reg_a->isFree = FALSE;
8159 hc08_reg_x->isFree = FALSE;
8164 /* depending on the operation */
8184 /* IPOP happens only when trying to restore a
8185 spilt live range, if there is an ifx statement
8186 following this pop then the if statement might
8187 be using some of the registers being popped which
8188 would destory the contents of the register so
8189 we need to check for this condition and handle it */
8191 ic->next->op == IFX &&
8192 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8193 genIfx (ic->next, ic);
8211 genEndFunction (ic);
8227 if (!genPointerGetSetOfs (ic))
8232 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8249 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8253 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8260 /* note these two are xlated by algebraic equivalence
8261 during parsing SDCC.y */
8262 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8263 "got '>=' or '<=' shouldn't have come here");
8267 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8279 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8283 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8287 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8314 case GET_VALUE_AT_ADDRESS:
8316 hasInc (IC_LEFT (ic), ic,
8317 getSize (operandType (IC_RESULT (ic)))),
8318 ifxForOp (IC_RESULT (ic), ic) );
8322 if (POINTER_SET (ic))
8323 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8349 addSet (&_G.sendSet, ic);
8352 case DUMMY_READ_VOLATILE:
8361 genEndCritical (ic);
8372 if (!hc08_reg_a->isFree)
8373 D(emitcode("","; forgot to free a"));
8374 if (!hc08_reg_x->isFree)
8375 D(emitcode("","; forgot to free x"));
8376 if (!hc08_reg_h->isFree)
8377 D(emitcode("","; forgot to free h"));
8378 if (!hc08_reg_hx->isFree)
8379 D(emitcode("","; forgot to free hx"));
8380 if (!hc08_reg_xa->isFree)
8381 D(emitcode("","; forgot to free xa"));
8384 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8387 /* now we are ready to call the
8388 peep hole optimizer */
8389 if (!options.nopeep)
8390 peepHole (&lineHead);
8392 /* now do the actual printing */
8393 printLine (lineHead, codeOutFile);