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 ("pulh", "");
417 emitcode ("pulx", "");
422 emitcode ("pulx", "");
425 emitcode ("pula", "");
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 dstaop. */
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 then 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));
3221 unsigned int offset;
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) || 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->level && !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 if (optimize.codeSpeed)
5645 accopWithMisc ("nsa", "");
5646 accopWithMisc ("and", "#0xf0");
5647 /* total: 5 cycles, 3 bytes */
5650 if (optimize.codeSpeed)
5652 accopWithMisc ("nsa", "");
5653 accopWithMisc ("and", "#0xf0");
5654 accopWithMisc ("lsla", "");
5655 /* total: 6 cycles, 4 bytes */
5658 accopWithMisc ("rora", "");
5659 accopWithMisc ("rora", "");
5660 accopWithMisc ("rora", "");
5661 accopWithMisc ("and", "#0xc0");
5662 /* total: 5 cycles, 5 bytes */
5665 accopWithMisc ("rora", "");
5666 accopWithMisc ("clra", "");
5667 accopWithMisc ("rora", "");
5668 /* total: 3 cycles, 3 bytes */
5672 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5673 /* the fastest (shCount<6) and shortest (shCount<4). */
5674 for (i=0;i<shCount;i++)
5675 accopWithMisc ("lsla", "");
5679 /*-----------------------------------------------------------------*/
5680 /* AccSRsh - signed right shift accumulator by known count */
5681 /*-----------------------------------------------------------------*/
5683 AccSRsh (int shCount)
5687 shCount &= 0x0007; // shCount : 0..7
5691 accopWithMisc ("rola", "");
5692 accopWithMisc ("clra", "");
5693 accopWithMisc ("sbc", zero);
5694 /* total: 4 cycles, 4 bytes */
5698 for (i=0;i<shCount;i++)
5699 accopWithMisc ("asra", "");
5702 /*-----------------------------------------------------------------*/
5703 /* AccRsh - right shift accumulator by known count */
5704 /*-----------------------------------------------------------------*/
5706 AccRsh (int shCount, bool sign)
5716 shCount &= 0x0007; // shCount : 0..7
5718 /* Shift counts of 4 and 5 are currently optimized for code size. */
5719 /* Falling through to the unrolled loop would be optimal for code speed. */
5720 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5724 if (optimize.codeSpeed)
5726 accopWithMisc ("nsa", "");
5727 accopWithMisc ("and", "#0x0f");
5728 /* total: 5 cycles, 3 bytes */
5731 if (optimize.codeSpeed)
5733 accopWithMisc ("nsa", "");
5734 accopWithMisc ("and", "#0x0f");
5735 accopWithMisc ("lsra", "");
5736 /* total: 6 cycles, 4 bytes */
5739 accopWithMisc ("rola", "");
5740 accopWithMisc ("rola", "");
5741 accopWithMisc ("rola", "");
5742 accopWithMisc ("and", "#0x03");
5743 /* total: 5 cycles, 5 bytes */
5746 accopWithMisc ("rola", "");
5747 accopWithMisc ("clra", "");
5748 accopWithMisc ("rola", "");
5749 /* total: 3 cycles, 3 bytes */
5753 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5754 /* the fastest (shCount<6) and shortest (shCount<4). */
5755 for (i=0;i<shCount;i++)
5756 accopWithMisc ("lsra", "");
5760 /*-----------------------------------------------------------------*/
5761 /* XAccLsh - left shift register pair XA by known count */
5762 /*-----------------------------------------------------------------*/
5764 XAccLsh (int shCount)
5768 shCount &= 0x000f; // shCount : 0..15
5773 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5774 loadRegFromConst (hc08_reg_a, zero);
5778 /* if we can beat 2n cycles or bytes for some special case, do it here */
5782 /* bytes cycles reg x reg a carry
5783 ** abcd efgh ijkl mnop ?
5784 ** lsrx 1 1 0abc defg ijkl mnop h
5785 ** rora 1 1 0abc defg hijk lmno p
5786 ** tax 1 1 hijk lmno hijk lmno p
5787 ** clra 1 1 hijk lmno 0000 0000 p
5788 ** rora 1 1 hijk lmno p000 0000 0
5789 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5791 rmwWithReg ("lsr", hc08_reg_x);
5792 rmwWithReg ("ror", hc08_reg_a);
5793 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5794 loadRegFromConst (hc08_reg_a, zero);
5795 rmwWithReg ("ror", hc08_reg_a);
5802 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5803 /* the fastest and shortest. */
5804 for (i=0;i<shCount;i++)
5806 rmwWithReg ("lsl", hc08_reg_a);
5807 rmwWithReg ("rol", hc08_reg_x);
5811 /*-----------------------------------------------------------------*/
5812 /* XAccSRsh - signed right shift register pair XA by known count */
5813 /*-----------------------------------------------------------------*/
5815 XAccSRsh (int shCount)
5819 shCount &= 0x000f; // shCount : 0..7
5821 /* if we can beat 2n cycles or bytes for some special case, do it here */
5825 /* bytes cycles reg x reg a carry
5826 ** abcd efgh ijkl mnop ?
5827 ** lslx 1 1 bcde fgh0 ijkl mnop a
5828 ** clra 1 1 bcde fgh0 0000 0000 a
5829 ** rola 1 1 bcde fgh0 0000 000a 0
5830 ** nega 1 1 bcde fgh0 aaaa aaaa a
5831 ** tax 1 1 aaaa aaaa aaaa aaaa a
5832 ** total: 5 cycles, 5 bytes
5834 rmwWithReg ("lsl", hc08_reg_x);
5835 loadRegFromConst (hc08_reg_a, zero);
5836 rmwWithReg ("rol", hc08_reg_a);
5837 rmwWithReg ("neg", hc08_reg_a);
5838 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5848 /* bytes cycles reg x reg a carry
5849 ** abcd efgh ijkl mnop ?
5850 ** txa 1 1 abcd efgh abcd efgh ?
5851 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5852 ** lsla 1 1 abcd efgh ???? ???? a
5853 ** clrx 1 1 0000 0000 ???? ???? a
5854 ** rolx 1 1 0000 000a ???? ???? 0
5855 ** negx 1 1 aaaa aaaa ???? ???? a
5856 ** rora 1 1 aaaa aaaa LSBresult 0
5857 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5859 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5860 AccSRsh (shCount-8);
5861 rmwWithReg ("lsl", hc08_reg_a);
5862 loadRegFromConst (hc08_reg_x, zero);
5863 rmwWithReg ("rol", hc08_reg_x);
5864 rmwWithReg ("neg", hc08_reg_x);
5865 rmwWithReg ("ror", hc08_reg_a);
5872 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5873 /* the fastest and shortest. */
5874 for (i=0;i<shCount;i++)
5876 rmwWithReg ("asr", hc08_reg_x);
5877 rmwWithReg ("ror", hc08_reg_a);
5881 /*-----------------------------------------------------------------*/
5882 /* XAccRsh - right shift register pair XA by known count */
5883 /*-----------------------------------------------------------------*/
5885 XAccRsh (int shCount, bool sign)
5895 shCount &= 0x000f; // shCount : 0..f
5897 /* if we can beat 2n cycles or bytes for some special case, do it here */
5901 /* bytes cycles reg x reg a carry
5902 ** abcd efgh ijkl mnop ?
5903 ** clra 1 1 abcd efgh 0000 0000 a
5904 ** lslx 1 1 bcde fgh0 0000 0000 a
5905 ** rola 1 1 bcde fgh0 0000 000a 0
5906 ** clrx 1 1 0000 0000 0000 000a 0
5907 ** total: 4 cycles, 4 bytes
5909 loadRegFromConst (hc08_reg_x, zero);
5910 rmwWithReg ("lsl", hc08_reg_x);
5911 rmwWithReg ("rol", hc08_reg_a);
5912 loadRegFromConst (hc08_reg_a, zero);
5916 /* bytes cycles reg x reg a carry
5917 ** abcd efgh ijkl mnop ?
5918 ** clra 1 1 abcd efgh 0000 0000 a
5919 ** lslx 1 1 bcde fgh0 0000 0000 a
5920 ** rola 1 1 bcde fgh0 0000 000a 0
5921 ** lslx 1 1 cdef gh00 0000 000a b
5922 ** rola 1 1 cdef gh00 0000 00ab 0
5923 ** clrx 1 1 0000 0000 0000 00ab 0
5924 ** total: 6 cycles, 6 bytes
5926 loadRegFromConst (hc08_reg_x, zero);
5927 rmwWithReg ("lsl", hc08_reg_x);
5928 rmwWithReg ("rol", hc08_reg_a);
5929 rmwWithReg ("lsl", hc08_reg_x);
5930 rmwWithReg ("rol", hc08_reg_a);
5931 loadRegFromConst (hc08_reg_a, zero);
5940 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5941 AccRsh (shCount-8, FALSE);
5942 loadRegFromConst (hc08_reg_x, zero);
5946 /* bytes cycles reg x reg a carry
5947 ** abcd efgh ijkl mnop ?
5948 ** lsla 1 1 abcd efgh jklm nop0 i
5949 ** txa 1 1 abcd efgh abcd efgh i
5950 ** rola 1 1 abcd efgh bcde fghi a
5951 ** clrx 1 1 0000 0000 bcde fghi a
5952 ** rolx 1 1 0000 000a bcde fghi 0
5953 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5955 rmwWithReg ("lsl", hc08_reg_a);
5956 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5957 rmwWithReg ("rol", hc08_reg_a);
5958 loadRegFromConst (hc08_reg_x, zero);
5959 rmwWithReg ("rol", hc08_reg_x);
5962 /* bytes cycles reg x reg a carry
5963 ** abcd efgh ijkl mnop ?
5964 ** lsla 1 1 abcd efgh jklm nop0 i
5965 ** rolx 1 1 bcde fghi jklm nop0 a
5966 ** rola 1 1 bcde fghi klmn op0a j
5967 ** rolx 1 1 cdef ghij klmn op0a b
5968 ** rola 1 1 cdef ghij lmno p0ab k
5969 ** and #3 2 2 cdef ghij 0000 00ab k
5970 ** psha 1 2 cdef ghij 0000 00ab k
5971 ** txa 1 1 cdef ghij cdef ghij k
5972 ** pula 1 2 0000 00ab cdef ghij k
5973 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5979 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5980 /* the fastest and shortest. */
5981 for (i=0;i<shCount;i++)
5983 rmwWithReg ("lsr", hc08_reg_x);
5984 rmwWithReg ("ror", hc08_reg_a);
5991 /*-----------------------------------------------------------------*/
5992 /* shiftR1Left2Result - shift right one byte from left to result */
5993 /*-----------------------------------------------------------------*/
5995 shiftR1Left2Result (operand * left, int offl,
5996 operand * result, int offr,
5997 int shCount, int sign)
5999 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6000 /* shift right accumulator */
6001 AccRsh (shCount, sign);
6002 storeRegToAop (hc08_reg_a, AOP (result), offr);
6006 /*-----------------------------------------------------------------*/
6007 /* shiftL1Left2Result - shift left one byte from left to result */
6008 /*-----------------------------------------------------------------*/
6010 shiftL1Left2Result (operand * left, int offl,
6011 operand * result, int offr, int shCount)
6013 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6014 /* shift left accumulator */
6016 storeRegToAop (hc08_reg_a, AOP (result), offr);
6019 /*-----------------------------------------------------------------*/
6020 /* movLeft2Result - move byte from left to result */
6021 /*-----------------------------------------------------------------*/
6023 movLeft2Result (operand * left, int offl,
6024 operand * result, int offr, int sign)
6026 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6028 transferAopAop (AOP (left), offl, AOP (result), offr);
6033 /*-----------------------------------------------------------------*/
6034 /* shiftL2Left2Result - shift left two bytes from left to result */
6035 /*-----------------------------------------------------------------*/
6037 shiftL2Left2Result (operand * left, int offl,
6038 operand * result, int offr, int shCount)
6041 bool needpula = FALSE;
6042 bool needpulx = FALSE;
6044 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6045 needpula = pushRegIfUsed (hc08_reg_a);
6048 if (!IS_AOP_XA (AOP (left)))
6049 needpulx = pushRegIfUsed (hc08_reg_x);
6053 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6058 rmwWithReg ("lsr", hc08_reg_x);
6059 rmwWithReg ("ror", hc08_reg_a);
6060 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6061 rmwWithReg ("clr", hc08_reg_a);
6062 rmwWithReg ("ror", hc08_reg_a);
6065 for (i=0; i<shCount; i++)
6067 rmwWithReg ("lsl", hc08_reg_a);
6068 rmwWithReg ("rol", hc08_reg_x);
6071 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6073 pullOrFreeReg (hc08_reg_x, needpulx);
6074 pullOrFreeReg (hc08_reg_a, needpula);
6080 /*-----------------------------------------------------------------*/
6081 /* shiftR2Left2Result - shift right two bytes from left to result */
6082 /*-----------------------------------------------------------------*/
6084 shiftR2Left2Result (operand * left, int offl,
6085 operand * result, int offr,
6086 int shCount, int sign)
6089 bool needpula = FALSE;
6090 bool needpulx = FALSE;
6092 needpula = pushRegIfUsed (hc08_reg_a);
6093 needpulx = pushRegIfUsed (hc08_reg_x);
6095 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6096 for (i=0; i<shCount; i++)
6099 rmwWithReg ("asr", hc08_reg_x);
6101 rmwWithReg ("lsr", hc08_reg_x);
6102 rmwWithReg ("ror", hc08_reg_a);
6104 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6106 pullOrFreeReg (hc08_reg_x, needpulx);
6107 pullOrFreeReg (hc08_reg_a, needpula);
6112 /*-----------------------------------------------------------------*/
6113 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6114 /*-----------------------------------------------------------------*/
6116 shiftLLeftOrResult (operand * left, int offl,
6117 operand * result, int offr, int shCount)
6119 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6120 /* shift left accumulator */
6122 /* or with result */
6123 accopWithAop ("ora", AOP (result), offr);
6124 /* back to result */
6125 storeRegToAop (hc08_reg_a, AOP (result), offr);
6126 hc08_freeReg (hc08_reg_a);
6130 /*-----------------------------------------------------------------*/
6131 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6132 /*-----------------------------------------------------------------*/
6134 shiftRLeftOrResult (operand * left, int offl,
6135 operand * result, int offr, int shCount)
6137 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6138 /* shift left accumulator */
6139 AccRsh (shCount, FALSE);
6140 /* or with result */
6141 accopWithAop ("ora", AOP (result), offr);
6142 /* back to result */
6143 storeRegToAop (hc08_reg_a, AOP (result), offr);
6144 hc08_freeReg (hc08_reg_a);
6147 /*-----------------------------------------------------------------*/
6148 /* genlshOne - left shift a one byte quantity by known count */
6149 /*-----------------------------------------------------------------*/
6151 genlshOne (operand * result, operand * left, int shCount)
6153 D(emitcode ("; genlshOne",""));
6155 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6158 /*-----------------------------------------------------------------*/
6159 /* genlshTwo - left shift two bytes by known amount != 0 */
6160 /*-----------------------------------------------------------------*/
6162 genlshTwo (operand * result, operand * left, int shCount)
6166 D(emitcode ("; genlshTwo",""));
6169 size = getDataSize (result);
6171 /* if shCount >= 8 */
6178 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6180 storeRegToAop (hc08_reg_a, AOP (result), 1);
6182 storeConstToAop(zero, AOP (result), LSB);
6185 /* 1 <= shCount <= 7 */
6188 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6190 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6194 /*-----------------------------------------------------------------*/
6195 /* shiftLLong - shift left one long from left to result */
6196 /* offl = LSB or MSB16 */
6197 /*-----------------------------------------------------------------*/
6199 shiftLLong (operand * left, operand * result, int offr)
6202 // int size = AOP_SIZE (result);
6204 bool needpula = FALSE;
6205 bool needpulx = FALSE;
6207 needpula = pushRegIfUsed (hc08_reg_a);
6208 needpulx = pushRegIfUsed (hc08_reg_x);
6210 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6211 rmwWithReg ("lsl", hc08_reg_a);
6212 rmwWithReg ("rol", hc08_reg_x);
6213 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6217 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6218 rmwWithReg ("rol", hc08_reg_a);
6219 rmwWithReg ("rol", hc08_reg_x);
6220 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6222 else if (offr==MSB16)
6224 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6225 rmwWithReg ("rol", hc08_reg_a);
6226 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6229 pullOrFreeReg (hc08_reg_x, needpulx);
6230 pullOrFreeReg (hc08_reg_a, needpula);
6233 /*-----------------------------------------------------------------*/
6234 /* genlshFour - shift four byte by a known amount != 0 */
6235 /*-----------------------------------------------------------------*/
6237 genlshFour (operand * result, operand * left, int shCount)
6241 D(emitcode ("; genlshFour",""));
6243 size = AOP_SIZE (result);
6245 /* TODO: deal with the &result == &left case */
6247 /* if shifting more that 3 bytes */
6252 /* lowest order of left goes to the highest
6253 order of the destination */
6254 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6256 movLeft2Result (left, LSB, result, MSB32, 0);
6257 storeConstToAop (zero, AOP (result), LSB);
6258 storeConstToAop (zero, AOP (result), MSB16);
6259 storeConstToAop (zero, AOP (result), MSB24);
6263 /* more than two bytes */
6264 else if (shCount >= 16)
6266 /* lower order two bytes goes to higher order two bytes */
6268 /* if some more remaining */
6270 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6273 movLeft2Result (left, MSB16, result, MSB32, 0);
6274 movLeft2Result (left, LSB, result, MSB24, 0);
6276 storeConstToAop (zero, AOP (result), LSB);
6277 storeConstToAop (zero, AOP (result), MSB16);
6281 /* if more than 1 byte */
6282 else if (shCount >= 8)
6284 /* lower order three bytes goes to higher order three bytes */
6289 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6291 movLeft2Result (left, LSB, result, MSB16, 0);
6297 movLeft2Result (left, MSB24, result, MSB32, 0);
6298 movLeft2Result (left, MSB16, result, MSB24, 0);
6299 movLeft2Result (left, LSB, result, MSB16, 0);
6300 storeConstToAop (zero, AOP (result), LSB);
6302 else if (shCount == 1)
6303 shiftLLong (left, result, MSB16);
6306 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6307 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6308 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6309 storeConstToAop (zero, AOP (result), LSB);
6314 /* 1 <= shCount <= 7 */
6315 else if (shCount <= 2)
6317 shiftLLong (left, result, LSB);
6319 shiftLLong (result, result, LSB);
6321 /* 3 <= shCount <= 7, optimize */
6324 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6325 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6326 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6330 /*-----------------------------------------------------------------*/
6331 /* genLeftShiftLiteral - left shifting by known count */
6332 /*-----------------------------------------------------------------*/
6334 genLeftShiftLiteral (operand * left,
6339 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6342 D(emitcode ("; genLeftShiftLiteral",""));
6344 freeAsmop (right, NULL, ic, TRUE);
6346 aopOp (left, ic, FALSE);
6347 aopOp (result, ic, FALSE);
6349 // size = getSize (operandType (result));
6350 size = AOP_SIZE (result);
6353 D(emitcode ("; shift left ", "result %d, left %d", size,
6360 transferAopAop( AOP(left), size, AOP(result), size);
6362 else if (shCount >= (size * 8))
6365 storeConstToAop (zero, AOP (result), size);
6372 genlshOne (result, left, shCount);
6376 genlshTwo (result, left, shCount);
6380 genlshFour (result, left, shCount);
6383 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6384 "*** ack! mystery literal shift!\n");
6388 freeAsmop (left, NULL, ic, TRUE);
6389 freeAsmop (result, NULL, ic, TRUE);
6392 /*-----------------------------------------------------------------*/
6393 /* genLeftShift - generates code for left shifting */
6394 /*-----------------------------------------------------------------*/
6396 genLeftShift (iCode * ic)
6398 operand *left, *right, *result;
6400 symbol *tlbl, *tlbl1;
6405 D(emitcode ("; genLeftShift",""));
6407 right = IC_RIGHT (ic);
6408 left = IC_LEFT (ic);
6409 result = IC_RESULT (ic);
6411 aopOp (right, ic, FALSE);
6413 /* if the shift count is known then do it
6414 as efficiently as possible */
6415 if (AOP_TYPE (right) == AOP_LIT)
6417 genLeftShiftLiteral (left, right, result, ic);
6421 /* shift count is unknown then we have to form
6422 a loop get the loop count in A : Note: we take
6423 only the lower order byte since shifting
6424 more that 32 bits make no sense anyway, ( the
6425 largest size of an object can be only 32 bits ) */
6427 aopOp (left, ic, FALSE);
6428 aopOp (result, ic, FALSE);
6430 /* now move the left to the result if they are not the
6432 if (!sameRegs (AOP (left), AOP (result)))
6435 size = AOP_SIZE (result);
6439 transferAopAop (AOP (left), offset, AOP (result), offset);
6443 freeAsmop (left, NULL, ic, TRUE);
6445 tlbl = newiTempLabel (NULL);
6446 size = AOP_SIZE (result);
6448 tlbl1 = newiTempLabel (NULL);
6452 loadRegFromAop (reg, AOP (right), 0);
6453 freeAsmop (right, NULL, ic, TRUE);
6454 emitBranch ("beq", tlbl1);
6458 for (offset=0;offset<size;offset++)
6460 rmwWithAop (shift, AOP (result), offset);
6463 rmwWithReg ("dec", reg);
6464 emitBranch ("bne", tlbl);
6468 freeAsmop (result, NULL, ic, TRUE);
6471 /*-----------------------------------------------------------------*/
6472 /* genrshOne - right shift a one byte quantity by known count */
6473 /*-----------------------------------------------------------------*/
6475 genrshOne (operand * result, operand * left,
6476 int shCount, int sign)
6478 D(emitcode ("; genrshOne",""));
6480 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6481 AccRsh (shCount, sign);
6482 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6485 /*-----------------------------------------------------------------*/
6486 /* genrshTwo - right shift two bytes by known amount != 0 */
6487 /*-----------------------------------------------------------------*/
6489 genrshTwo (operand * result, operand * left,
6490 int shCount, int sign)
6492 D(emitcode ("; genrshTwo",""));
6494 /* if shCount >= 8 */
6497 if (shCount || sign)
6499 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6500 AccRsh (shCount-8, sign);
6501 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6505 transferAopAop (AOP (left), 1, AOP (result), 0);
6506 storeConstToAop (zero, AOP (result), 1);
6510 /* 1 <= shCount <= 7 */
6513 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6514 XAccRsh (shCount, sign);
6515 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6519 /*-----------------------------------------------------------------*/
6520 /* shiftRLong - shift right one long from left to result */
6521 /* offl = LSB or MSB16 */
6522 /*-----------------------------------------------------------------*/
6524 shiftRLong (operand * left, int offl,
6525 operand * result, int sign)
6528 // int size = AOP_SIZE (result);
6530 bool needpula = FALSE;
6531 bool needpulx = FALSE;
6533 needpula = pushRegIfUsed (hc08_reg_a);
6534 needpulx = pushRegIfUsed (hc08_reg_x);
6538 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6540 rmwWithReg ("asr", hc08_reg_x);
6542 rmwWithReg ("lsr", hc08_reg_x);
6543 rmwWithReg ("ror", hc08_reg_a);
6544 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6546 else if (offl==MSB16)
6548 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6550 rmwWithReg ("asr", hc08_reg_a);
6552 rmwWithReg ("lsr", hc08_reg_a);
6553 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6556 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6557 rmwWithReg ("ror", hc08_reg_x);
6558 rmwWithReg ("ror", hc08_reg_a);
6559 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6562 pullOrFreeReg (hc08_reg_x, needpulx);
6563 pullOrFreeReg (hc08_reg_a, needpula);
6566 /*-----------------------------------------------------------------*/
6567 /* genrshFour - shift four byte by a known amount != 0 */
6568 /*-----------------------------------------------------------------*/
6570 genrshFour (operand * result, operand * left,
6571 int shCount, int sign)
6573 /* TODO: handle cases where left == result */
6575 D(emitcode ("; genrshFour",""));
6577 /* if shifting more that 3 bytes */
6580 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6581 AccRsh (shCount-24, sign);
6582 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6585 else if (shCount >= 16)
6587 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6588 XAccRsh (shCount-16, sign);
6589 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6592 else if (shCount >= 8)
6595 shiftRLong (left, MSB16, result, sign);
6596 else if (shCount == 8)
6598 transferAopAop (AOP (left), 1, AOP (result), 0);
6599 transferAopAop (AOP (left), 2, AOP (result), 1);
6600 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6601 storeRegToAop (hc08_reg_a, AOP (result), 2);
6602 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6604 else if (shCount == 9)
6606 shiftRLong (left, MSB16, result, sign);
6610 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6611 XAccRsh (shCount-8, FALSE);
6612 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6613 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6614 loadRegFromConst (hc08_reg_a, zero);
6615 XAccRsh (shCount-8, sign);
6616 accopWithAop ("ora", AOP (result), 1);
6617 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6621 { /* 1 <= shCount <= 7 */
6624 shiftRLong (left, LSB, result, sign);
6628 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6629 XAccRsh (shCount, FALSE);
6630 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6631 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6633 accopWithAop ("ora", AOP (result), 1);
6634 storeRegToAop (hc08_reg_a, AOP (result), 1);
6635 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6636 XAccRsh (shCount, sign);
6637 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6642 /*-----------------------------------------------------------------*/
6643 /* genRightShiftLiteral - right shifting by known count */
6644 /*-----------------------------------------------------------------*/
6646 genRightShiftLiteral (operand * left,
6652 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6655 D(emitcode ("; genRightShiftLiteral",""));
6657 freeAsmop (right, NULL, ic, TRUE);
6659 aopOp (left, ic, FALSE);
6660 aopOp (result, ic, FALSE);
6663 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6667 size = getDataSize (left);
6668 /* test the LEFT size !!! */
6670 /* I suppose that the left size >= result size */
6673 size = getDataSize (result);
6675 transferAopAop (AOP (left), size, AOP(result), size);
6677 else if (shCount >= (size * 8))
6680 /* get sign in acc.7 */
6681 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6683 addSign (result, LSB, sign);
6690 genrshOne (result, left, shCount, sign);
6694 genrshTwo (result, left, shCount, sign);
6698 genrshFour (result, left, shCount, sign);
6704 freeAsmop (left, NULL, ic, TRUE);
6705 freeAsmop (result, NULL, ic, TRUE);
6709 /*-----------------------------------------------------------------*/
6710 /* genRightShift - generate code for right shifting */
6711 /*-----------------------------------------------------------------*/
6713 genRightShift (iCode * ic)
6715 operand *right, *left, *result;
6719 symbol *tlbl, *tlbl1;
6723 D(emitcode ("; genRightShift",""));
6725 /* if signed then we do it the hard way preserve the
6726 sign bit moving it inwards */
6727 retype = getSpec (operandType (IC_RESULT (ic)));
6728 sign = !SPEC_USIGN (retype);
6730 /* signed & unsigned types are treated the same : i.e. the
6731 signed is NOT propagated inwards : quoting from the
6732 ANSI - standard : "for E1 >> E2, is equivalent to division
6733 by 2**E2 if unsigned or if it has a non-negative value,
6734 otherwise the result is implementation defined ", MY definition
6735 is that the sign does not get propagated */
6737 right = IC_RIGHT (ic);
6738 left = IC_LEFT (ic);
6739 result = IC_RESULT (ic);
6741 aopOp (right, ic, FALSE);
6743 /* if the shift count is known then do it
6744 as efficiently as possible */
6745 if (AOP_TYPE (right) == AOP_LIT)
6747 genRightShiftLiteral (left, right, result, ic, sign);
6751 /* shift count is unknown then we have to form
6752 a loop get the loop count in X : Note: we take
6753 only the lower order byte since shifting
6754 more that 32 bits make no sense anyway, ( the
6755 largest size of an object can be only 32 bits ) */
6757 aopOp (left, ic, FALSE);
6758 aopOp (result, ic, FALSE);
6760 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6761 AOP (result) = forceStackedAop (AOP (result));
6763 size = AOP_SIZE (result);
6767 transferAopAop (AOP (left), offset, AOP (result), offset);
6771 tlbl = newiTempLabel (NULL);
6772 size = AOP_SIZE (result);
6774 tlbl1 = newiTempLabel (NULL);
6776 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6777 emitcode ("tstx", "");
6778 emitcode ("beq", "%05d$", tlbl1->key + 100);
6779 emitcode ("", "%05d$:", tlbl->key + 100);
6780 shift= sign ? "asr" : "lsr";
6781 for (offset=size-1;offset>=0;offset--)
6783 rmwWithAop (shift, AOP (result), offset);
6786 rmwWithReg ("dec", hc08_reg_x);
6787 emitcode ("bne","%05d$", tlbl->key + 100);
6788 emitcode ("", "%05d$:", tlbl1->key + 100);
6790 freeAsmop (result, NULL, ic, TRUE);
6791 freeAsmop (left, NULL, ic, TRUE);
6792 freeAsmop (right, NULL, ic, TRUE);
6796 /*-----------------------------------------------------------------*/
6797 /* genUnpackBits - generates code for unpacking bits */
6798 /*-----------------------------------------------------------------*/
6800 genUnpackBits (operand * result, iCode *ifx)
6802 int offset = 0; /* result byte offset */
6803 int rsize; /* result size */
6804 int rlen = 0; /* remaining bitfield length */
6805 sym_link *etype; /* bitfield type information */
6806 int blen; /* bitfield length */
6807 int bstr; /* bitfield starting bit within byte */
6809 D(emitcode ("; genUnpackBits",""));
6811 etype = getSpec (operandType (result));
6812 rsize = getSize (operandType (result));
6813 blen = SPEC_BLEN (etype);
6814 bstr = SPEC_BSTR (etype);
6816 /* If the bitfield length is less than a byte */
6819 emitcode ("lda", ",x");
6820 hc08_dirtyReg (hc08_reg_a, FALSE);
6823 AccRsh (bstr, FALSE);
6824 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6825 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6829 emitcode ("and", "#0x%02x",
6830 (((unsigned char) -1) >> (8 - blen)) << bstr);
6835 /* Bit field did not fit in a byte. Copy all
6836 but the partial byte at the end. */
6837 for (rlen=blen;rlen>=8;rlen-=8)
6839 emitcode ("lda", ",x");
6840 hc08_dirtyReg (hc08_reg_a, FALSE);
6842 storeRegToAop (hc08_reg_a, AOP (result), offset);
6845 emitcode ("aix", "#1");
6848 /* Handle the partial byte at the end */
6851 emitcode ("lda", ",x");
6852 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6853 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6861 storeConstToAop (zero, AOP (result), offset++);
6864 if (ifx && !ifx->generated)
6866 genIfxJump (ifx, "a");
6871 /*-----------------------------------------------------------------*/
6872 /* genUnpackBitsImmed - generates code for unpacking bits */
6873 /*-----------------------------------------------------------------*/
6875 genUnpackBitsImmed (operand * left,
6881 int offset = 0; /* result byte offset */
6882 int rsize; /* result size */
6883 int rlen = 0; /* remaining bitfield length */
6884 sym_link *etype; /* bitfield type information */
6885 int blen; /* bitfield length */
6886 int bstr; /* bitfield starting bit within byte */
6889 D(emitcode ("; genUnpackBitsImmed",""));
6891 aopOp (result, ic, TRUE);
6892 size = AOP_SIZE (result);
6894 derefaop = aopDerefAop (AOP (left));
6895 freeAsmop (left, NULL, ic, TRUE);
6896 derefaop->size = size;
6898 etype = getSpec (operandType (result));
6899 rsize = getSize (operandType (result));
6900 blen = SPEC_BLEN (etype);
6901 bstr = SPEC_BSTR (etype);
6903 /* if the bitfield is a single bit in the direct page */
6904 if (blen == 1 && derefaop->type == AOP_DIR)
6908 symbol *tlbl = newiTempLabel (NULL);
6910 loadRegFromConst (hc08_reg_a, zero);
6911 emitcode ("brclr", "#%d,%s,%05d$",
6912 bstr, aopAdrStr (derefaop, 0, FALSE),
6914 rmwWithReg ("inc", hc08_reg_a);
6916 storeRegToAop (hc08_reg_a, AOP (result), offset);
6917 hc08_freeReg (hc08_reg_a);
6923 symbol *tlbl = newiTempLabel (NULL);
6929 jlbl = IC_TRUE (ifx);
6934 jlbl = IC_FALSE (ifx);
6937 emitcode (inst, "#%d,%s,%05d$",
6938 bstr, aopAdrStr (derefaop, 0, FALSE),
6940 emitBranch ("jmp", jlbl);
6948 /* If the bitfield length is less than a byte */
6951 loadRegFromAop (hc08_reg_a, derefaop, 0);
6954 AccRsh (bstr, FALSE);
6955 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6956 hc08_dirtyReg (hc08_reg_a, FALSE);
6957 storeRegToAop (hc08_reg_a, AOP (result), offset);
6961 emitcode ("and", "#0x%02x",
6962 (((unsigned char) -1) >> (8 - blen)) << bstr);
6963 hc08_dirtyReg (hc08_reg_a, FALSE);
6969 /* Bit field did not fit in a byte. Copy all
6970 but the partial byte at the end. */
6971 for (rlen=blen;rlen>=8;rlen-=8)
6973 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6975 storeRegToAop (hc08_reg_a, AOP (result), offset);
6977 emitcode ("tsta", "");
6981 /* Handle the partial byte at the end */
6984 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6985 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6986 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6994 storeConstToAop (zero, AOP (result), offset++);
6997 freeAsmop (NULL, derefaop, ic, TRUE);
6998 freeAsmop (result, NULL, ic, TRUE);
7000 if (ifx && !ifx->generated)
7002 genIfxJump (ifx, "a");
7007 /*-----------------------------------------------------------------*/
7008 /* genDataPointerGet - generates code when ptr offset is known */
7009 /*-----------------------------------------------------------------*/
7011 genDataPointerGet (operand * left,
7016 int size, offset = 0;
7019 D(emitcode ("; genDataPointerGet",""));
7021 aopOp (result, ic, TRUE);
7022 size = AOP_SIZE (result);
7024 derefaop = aopDerefAop (AOP (left));
7025 freeAsmop (left, NULL, ic, TRUE);
7026 derefaop->size = size;
7031 transferAopAop (derefaop, offset, AOP (result), offset);
7033 loadRegFromAop (hc08_reg_a, derefaop, offset);
7037 freeAsmop (NULL, derefaop, ic, TRUE);
7038 freeAsmop (result, NULL, ic, TRUE);
7040 if (ifx && !ifx->generated)
7042 genIfxJump (ifx, "a");
7047 /*-----------------------------------------------------------------*/
7048 /* genPointerGet - generate code for pointer get */
7049 /*-----------------------------------------------------------------*/
7051 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7053 operand *left = IC_LEFT (ic);
7054 operand *result = IC_RESULT (ic);
7056 sym_link *retype = getSpec (operandType (result));
7058 D(emitcode ("; genPointerGet",""));
7060 if (getSize (operandType (result))>1)
7063 aopOp (left, ic, FALSE);
7065 /* if left is rematerialisable and
7066 result is not bit variable type */
7067 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7069 if (!IS_BITVAR (retype))
7071 genDataPointerGet (left, result, ic, ifx);
7076 genUnpackBitsImmed (left, result, ic, ifx);
7081 /* if the operand is already in hx
7082 then we do nothing else we move the value to hx */
7083 if (AOP_TYPE (left) != AOP_STR)
7085 /* if this is remateriazable */
7086 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7089 /* so hx now contains the address */
7090 aopOp (result, ic, FALSE);
7092 /* if bit then unpack */
7093 if (IS_BITVAR (retype))
7094 genUnpackBits (result, ifx);
7097 size = AOP_SIZE (result);
7102 accopWithMisc ("lda", ",x");
7105 emitcode ("aix", "#1");
7106 hc08_dirtyReg (hc08_reg_hx, FALSE);
7109 storeRegToAop (hc08_reg_a, AOP (result), offset);
7111 hc08_freeReg (hc08_reg_a);
7115 freeAsmop (left, NULL, ic, TRUE);
7116 freeAsmop (result, NULL, ic, TRUE);
7119 aopOp (IC_RESULT (pi), pi, FALSE);
7120 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7121 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7125 if (ifx && !ifx->generated)
7127 genIfxJump (ifx, "a");
7130 hc08_freeReg (hc08_reg_hx);
7134 /*-----------------------------------------------------------------*/
7135 /* genPackBits - generates code for packed bit storage */
7136 /*-----------------------------------------------------------------*/
7138 genPackBits (sym_link * etype,
7141 int offset = 0; /* source byte offset */
7142 int rlen = 0; /* remaining bitfield length */
7143 int blen; /* bitfield length */
7144 int bstr; /* bitfield starting bit within byte */
7145 int litval; /* source literal value (if AOP_LIT) */
7146 unsigned char mask; /* bitmask within current byte */
7149 D(emitcode ("; genPackBits",""));
7151 blen = SPEC_BLEN (etype);
7152 bstr = SPEC_BSTR (etype);
7154 /* If the bitfield length is less than a byte */
7157 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7158 (unsigned char) (0xFF >> (8 - bstr)));
7160 if (AOP_TYPE (right) == AOP_LIT)
7162 /* Case with a bitfield length <8 and literal source
7164 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7166 litval &= (~mask) & 0xff;
7168 emitcode ("lda", ",x");
7169 if ((mask|litval)!=0xff)
7170 emitcode ("and","#0x%02x", mask);
7172 emitcode ("ora","#0x%02x", litval);
7173 hc08_dirtyReg (hc08_reg_a, FALSE);
7174 emitcode ("sta", ",x");
7176 hc08_freeReg (hc08_reg_a);
7180 /* Case with a bitfield length < 8 and arbitrary source
7182 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7183 /* shift and mask source value */
7185 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7186 hc08_dirtyReg (hc08_reg_a, FALSE);
7187 pushReg (hc08_reg_a, TRUE);
7189 emitcode ("lda", ",x");
7190 emitcode ("and", "#0x%02x", mask);
7191 emitcode ("ora", "1,s");
7192 emitcode ("sta", ",x");
7193 pullReg (hc08_reg_a);
7195 hc08_freeReg (hc08_reg_a);
7199 /* Bit length is greater than 7 bits. In this case, copy */
7200 /* all except the partial byte at the end */
7201 for (rlen=blen;rlen>=8;rlen-=8)
7203 if (AOP (right)->type == AOP_DIR)
7205 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7210 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7211 emitcode ("sta", "%d,x", offset);
7216 /* If there was a partial byte at the end */
7219 mask = (((unsigned char) -1 << rlen) & 0xff);
7221 if (AOP_TYPE (right) == AOP_LIT)
7223 /* Case with partial byte and literal source
7225 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7226 litval >>= (blen-rlen);
7227 litval &= (~mask) & 0xff;
7228 emitcode ("lda", "%d,x", offset - xoffset);
7229 hc08_dirtyReg (hc08_reg_a, FALSE);
7230 if ((mask|litval)!=0xff)
7231 emitcode ("and","#0x%02x", mask);
7233 emitcode ("ora","#0x%02x", litval);
7234 emitcode ("sta", "%d,x", offset - xoffset);
7235 hc08_dirtyReg (hc08_reg_a, FALSE);
7236 hc08_freeReg (hc08_reg_a);
7240 /* Case with partial byte and arbitrary source
7242 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7243 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7244 hc08_dirtyReg (hc08_reg_a, FALSE);
7245 pushReg (hc08_reg_a, TRUE);
7247 emitcode ("lda", "%d,x", offset - xoffset);
7248 emitcode ("and", "#0x%02x", mask);
7249 emitcode ("ora", "1,s");
7250 emitcode ("sta", "%d,x", offset - xoffset);
7251 pullReg (hc08_reg_a);
7254 hc08_freeReg (hc08_reg_a);
7257 /*-----------------------------------------------------------------*/
7258 /* genPackBitsImmed - generates code for packed bit storage */
7259 /*-----------------------------------------------------------------*/
7261 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7265 int offset = 0; /* source byte offset */
7266 int rlen = 0; /* remaining bitfield length */
7267 int blen; /* bitfield length */
7268 int bstr; /* bitfield starting bit within byte */
7269 int litval; /* source literal value (if AOP_LIT) */
7270 unsigned char mask; /* bitmask within current byte */
7272 D(emitcode ("; genPackBitsImmed",""));
7274 blen = SPEC_BLEN (etype);
7275 bstr = SPEC_BSTR (etype);
7277 aopOp (right, ic, FALSE);
7278 size = AOP_SIZE (right);
7280 derefaop = aopDerefAop (AOP (result));
7281 freeAsmop (result, NULL, ic, TRUE);
7282 derefaop->size = size;
7284 /* if the bitfield is a single bit in the direct page */
7285 if (blen == 1 && derefaop->type == AOP_DIR)
7287 if (AOP_TYPE (right) == AOP_LIT)
7289 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7291 emitcode ((litval & 1) ? "bset" : "bclr",
7292 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7296 symbol *tlbl1 = newiTempLabel (NULL);
7297 symbol *tlbl2 = newiTempLabel (NULL);
7299 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7300 emitcode ("bit", "#1");
7301 emitBranch ("bne", tlbl1);
7302 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7303 emitBranch ("bra", tlbl2);
7305 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7307 hc08_freeReg (hc08_reg_a);
7312 /* If the bitfield length is less than a byte */
7315 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7316 (unsigned char) (0xFF >> (8 - bstr)));
7318 if (AOP_TYPE (right) == AOP_LIT)
7320 /* Case with a bitfield length <8 and literal source
7322 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7324 litval &= (~mask) & 0xff;
7326 loadRegFromAop (hc08_reg_a, derefaop, 0);
7327 if ((mask|litval)!=0xff)
7328 emitcode ("and","#0x%02x", mask);
7330 emitcode ("ora","#0x%02x", litval);
7331 hc08_dirtyReg (hc08_reg_a, FALSE);
7332 storeRegToAop (hc08_reg_a, derefaop, 0);
7334 hc08_freeReg (hc08_reg_a);
7338 /* Case with a bitfield length < 8 and arbitrary source
7340 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7341 /* shift and mask source value */
7343 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7344 hc08_dirtyReg (hc08_reg_a, FALSE);
7345 pushReg (hc08_reg_a, TRUE);
7347 loadRegFromAop (hc08_reg_a, derefaop, 0);
7348 emitcode ("and", "#0x%02x", mask);
7349 emitcode ("ora", "1,s");
7350 storeRegToAop (hc08_reg_a, derefaop, 0);
7351 pullReg (hc08_reg_a);
7353 hc08_freeReg (hc08_reg_a);
7357 /* Bit length is greater than 7 bits. In this case, copy */
7358 /* all except the partial byte at the end */
7359 for (rlen=blen;rlen>=8;rlen-=8)
7361 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7365 /* If there was a partial byte at the end */
7368 mask = (((unsigned char) -1 << rlen) & 0xff);
7370 if (AOP_TYPE (right) == AOP_LIT)
7372 /* Case with partial byte and literal source
7374 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7375 litval >>= (blen-rlen);
7376 litval &= (~mask) & 0xff;
7377 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7378 if ((mask|litval)!=0xff)
7379 emitcode ("and","#0x%02x", mask);
7381 emitcode ("ora","#0x%02x", litval);
7382 hc08_dirtyReg (hc08_reg_a, FALSE);
7383 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7384 hc08_dirtyReg (hc08_reg_a, FALSE);
7385 hc08_freeReg (hc08_reg_a);
7389 /* Case with partial byte and arbitrary source
7391 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7392 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7393 hc08_dirtyReg (hc08_reg_a, FALSE);
7394 pushReg (hc08_reg_a, TRUE);
7396 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7397 emitcode ("and", "#0x%02x", mask);
7398 emitcode ("ora", "1,s");
7399 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7400 pullReg (hc08_reg_a);
7403 hc08_freeReg (hc08_reg_a);
7406 freeAsmop (right, NULL, ic, TRUE);
7407 freeAsmop (NULL, derefaop, ic, TRUE);
7410 /*-----------------------------------------------------------------*/
7411 /* genDataPointerSet - remat pointer to data space */
7412 /*-----------------------------------------------------------------*/
7414 genDataPointerSet (operand * right,
7418 int size, offset = 0;
7421 D(emitcode ("; genDataPointerSet",""));
7423 aopOp (right, ic, FALSE);
7424 size = AOP_SIZE (right);
7426 derefaop = aopDerefAop (AOP (result));
7427 freeAsmop (result, NULL, ic, TRUE);
7428 derefaop->size = size;
7432 transferAopAop (AOP (right), offset, derefaop, offset);
7436 freeAsmop (right, NULL, ic, TRUE);
7437 freeAsmop (NULL, derefaop, ic, TRUE);
7441 /*-----------------------------------------------------------------*/
7442 /* genPointerSet - stores the value into a pointer location */
7443 /*-----------------------------------------------------------------*/
7445 genPointerSet (iCode * ic, iCode *pi)
7447 operand *right = IC_RIGHT (ic);
7448 operand *result = IC_RESULT (ic);
7449 sym_link *type, *etype;
7451 sym_link *retype = getSpec (operandType (right));
7452 sym_link *letype = getSpec (operandType (result));
7454 D(emitcode ("; genPointerSet",""));
7456 type = operandType (result);
7457 etype = getSpec (type);
7459 aopOp (result, ic, FALSE);
7461 /* if the result is rematerializable */
7462 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7464 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7466 genDataPointerSet (right, result, ic);
7471 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7476 /* if the operand is already in hx
7477 then we do nothing else we move the value to hx */
7478 if (AOP_TYPE (result) != AOP_STR)
7480 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7482 /* so hx now contains the address */
7483 aopOp (right, ic, FALSE);
7485 /* if bit then unpack */
7486 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7487 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7490 size = AOP_SIZE (right);
7495 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7496 accopWithMisc ("sta", ",x");
7499 emitcode ("aix", "#1");
7501 hc08_freeReg (hc08_reg_a);
7505 freeAsmop (result, NULL, ic, TRUE);
7506 freeAsmop (right, NULL, ic, TRUE);
7509 aopOp (IC_RESULT (pi), pi, FALSE);
7510 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7511 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7515 hc08_freeReg (hc08_reg_hx);
7519 /*-----------------------------------------------------------------*/
7520 /* genIfx - generate code for Ifx statement */
7521 /*-----------------------------------------------------------------*/
7523 genIfx (iCode * ic, iCode * popIc)
7525 operand *cond = IC_COND (ic);
7528 D(emitcode ("; genIfx",""));
7530 aopOp (cond, ic, FALSE);
7532 /* get the value into acc */
7533 if (AOP_TYPE (cond) != AOP_CRY)
7534 asmopToBool (AOP (cond), FALSE);
7537 /* the result is now in the accumulator */
7538 freeAsmop (cond, NULL, ic, TRUE);
7540 /* if there was something to be popped then do it */
7544 /* if the condition is a bit variable */
7545 if (isbit && IS_ITEMP (cond) &&
7547 genIfxJump (ic, SPIL_LOC (cond)->rname);
7548 else if (isbit && !IS_ITEMP (cond))
7549 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7551 genIfxJump (ic, "a");
7556 /*-----------------------------------------------------------------*/
7557 /* genAddrOf - generates code for address of */
7558 /*-----------------------------------------------------------------*/
7560 genAddrOf (iCode * ic)
7562 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7565 D(emitcode ("; genAddrOf",""));
7567 aopOp (IC_RESULT (ic), ic, FALSE);
7569 /* if the operand is on the stack then we
7570 need to get the stack offset of this
7574 /* if it has an offset then we need to compute
7576 hc08_useReg (hc08_reg_hx);
7577 emitcode ("tsx", "");
7578 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7579 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7580 hc08_freeReg (hc08_reg_hx);
7585 /* object not on stack then we need the name */
7586 size = AOP_SIZE (IC_RESULT (ic));
7591 char s[SDCC_NAME_MAX+10];
7594 sprintf (s, "#%s", sym->rname);
7597 sprintf (s, "#>%s", sym->rname);
7600 sprintf (s, "#(%s >> %d)",
7604 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7608 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7612 /*-----------------------------------------------------------------*/
7613 /* genAssign - generate code for assignment */
7614 /*-----------------------------------------------------------------*/
7616 genAssign (iCode * ic)
7618 operand *result, *right;
7620 // unsigned long lit = 0L;
7622 D(emitcode("; genAssign",""));
7624 result = IC_RESULT (ic);
7625 right = IC_RIGHT (ic);
7627 /* if they are the same */
7628 if (operandsEqu (result, right)) {
7632 aopOp (right, ic, FALSE);
7633 aopOp (result, ic, TRUE);
7635 /* if they are the same registers */
7636 if (sameRegs (AOP (right), AOP (result)))
7639 if ((AOP_TYPE (right) == AOP_LIT)
7640 && (IS_AOP_HX(AOP(result))))
7642 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7647 size = AOP_SIZE (result);
7652 transferAopAop (AOP (right), offset, AOP (result), offset);
7657 freeAsmop (right, NULL, ic, TRUE);
7658 freeAsmop (result, NULL, ic, TRUE);
7661 /*-----------------------------------------------------------------*/
7662 /* genJumpTab - genrates code for jump table */
7663 /*-----------------------------------------------------------------*/
7665 genJumpTab (iCode * ic)
7668 symbol *jtablo = newiTempLabel (NULL);
7669 symbol *jtabhi = newiTempLabel (NULL);
7671 D(emitcode ("; genJumpTab",""));
7673 aopOp (IC_JTCOND (ic), ic, FALSE);
7675 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7677 /* get the condition into x */
7678 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7679 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7680 loadRegFromConst (hc08_reg_h, zero);
7682 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7683 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7684 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7685 emitcode ("jmp", ",x");
7687 hc08_dirtyReg (hc08_reg_a, TRUE);
7688 hc08_dirtyReg (hc08_reg_hx, TRUE);
7693 pushReg(hc08_reg_hx, TRUE);
7695 /* get the condition into x */
7696 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7697 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7698 loadRegFromConst (hc08_reg_h, zero);
7700 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7701 emitcode ("sta", "3,s");
7702 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7703 emitcode ("sta", "4,s");
7705 pullReg(hc08_reg_hx);
7706 emitcode ("rts", "");
7707 _G.stackPushes += 2;
7711 /* now generate the jump labels */
7713 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7714 jtab = setNextItem (IC_JTLABELS (ic)))
7715 emitcode (".db", "%05d$", jtab->key + 100);
7717 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7718 jtab = setNextItem (IC_JTLABELS (ic)))
7719 emitcode (".db", ">%05d$", jtab->key + 100);
7723 /*-----------------------------------------------------------------*/
7724 /* genCast - gen code for casting */
7725 /*-----------------------------------------------------------------*/
7727 genCast (iCode * ic)
7729 operand *result = IC_RESULT (ic);
7730 sym_link *ctype = operandType (IC_LEFT (ic));
7731 sym_link *rtype = operandType (IC_RIGHT (ic));
7732 operand *right = IC_RIGHT (ic);
7735 D(emitcode("; genCast",""));
7737 /* if they are equivalent then do nothing */
7738 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7741 aopOp (right, ic, FALSE);
7742 aopOp (result, ic, FALSE);
7745 /* if they are the same size : or less */
7746 if (AOP_SIZE (result) <= AOP_SIZE (right))
7749 /* if they are in the same place */
7751 if (sameRegs (AOP (right), AOP (result)))
7755 /* if they in different places then copy */
7756 size = AOP_SIZE (result);
7760 transferAopAop(AOP (right), offset, AOP (result), offset);
7767 /* if the result is of type pointer */
7772 sym_link *type = operandType (right);
7773 sym_link *etype = getSpec (type);
7775 /* pointer to generic pointer */
7776 if (IS_GENPTR (ctype))
7779 p_type = DCL_TYPE (type);
7782 if (SPEC_SCLS(etype)==S_REGISTER) {
7783 // let's assume it is a generic pointer
7786 /* we have to go by the storage class */
7787 p_type = PTR_TYPE (SPEC_OCLS (etype));
7791 /* the first two bytes are known */
7792 size = GPTRSIZE - 1;
7796 transferAopAop(AOP (right), offset, AOP (result), offset);
7799 /* the last byte depending on type */
7802 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7807 // pointerTypeToGPByte will have bitched.
7811 sprintf(gpValStr, "#0x%d", gpVal);
7812 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7818 /* just copy the pointers */
7819 size = AOP_SIZE (result);
7823 transferAopAop(AOP (right), offset, AOP (result), offset);
7829 /* so we now know that the size of destination is greater
7830 than the size of the source */
7831 /* we move to result for the size of source */
7832 size = AOP_SIZE (right);
7836 transferAopAop(AOP (right), offset, AOP (result), offset);
7840 /* now depending on the sign of the source && destination */
7841 size = AOP_SIZE (result) - AOP_SIZE (right);
7842 /* if unsigned or not an integral type */
7843 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7846 storeConstToAop (zero, AOP (result), offset++);
7850 /* we need to extend the sign :{ */
7851 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7852 accopWithMisc ("rola", "");
7853 accopWithMisc ("clra", "");
7854 accopWithMisc ("sbc", zero);
7856 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7859 /* we are done hurray !!!! */
7862 freeAsmop (right, NULL, ic, TRUE);
7863 freeAsmop (result, NULL, ic, TRUE);
7867 /*-----------------------------------------------------------------*/
7868 /* genDjnz - generate decrement & jump if not zero instrucion */
7869 /*-----------------------------------------------------------------*/
7871 genDjnz (iCode * ic, iCode * ifx)
7877 D(emitcode ("; genDjnz",""));
7879 /* if the if condition has a false label
7880 then we cannot save */
7884 /* if the minus is not of the form
7886 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7887 !IS_OP_LITERAL (IC_RIGHT (ic)))
7890 if (operandLitValue (IC_RIGHT (ic)) != 1)
7893 /* dbnz doesn't support extended mode */
7894 if (isOperandInFarSpace (IC_RESULT (ic)))
7897 /* if the size of this greater than one then no
7899 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7901 aopOp (IC_RESULT (ic), ic, FALSE);
7902 if (AOP_SIZE (IC_RESULT (ic))>1)
7904 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7908 /* otherwise we can save BIG */
7909 lbl = newiTempLabel (NULL);
7910 lbl1 = newiTempLabel (NULL);
7913 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7916 emitBranch ("bra", lbl1);
7918 emitBranch ("jmp", IC_TRUE (ifx));
7921 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7926 /*-----------------------------------------------------------------*/
7927 /* genReceive - generate code for a receive iCode */
7928 /*-----------------------------------------------------------------*/
7930 genReceive (iCode * ic)
7934 D(emitcode ("; genReceive",""));
7936 aopOp (IC_RESULT (ic), ic, FALSE);
7937 size = AOP_SIZE (IC_RESULT (ic));
7942 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7943 AOP (IC_RESULT (ic)), offset);
7944 if (hc08_aop_pass[offset]->type == AOP_REG)
7945 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7950 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7953 /*-----------------------------------------------------------------*/
7954 /* genDummyRead - generate code for dummy read of volatiles */
7955 /*-----------------------------------------------------------------*/
7957 genDummyRead (iCode * ic)
7962 D(emitcode("; genDummyRead",""));
7965 if (op && IS_SYMOP (op))
7968 aopOp (op, ic, FALSE);
7970 size = AOP_SIZE (op);
7975 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7976 hc08_freeReg (hc08_reg_a);
7980 freeAsmop (op, NULL, ic, TRUE);
7983 if (op && IS_SYMOP (op))
7986 aopOp (op, ic, FALSE);
7988 size = AOP_SIZE (op);
7993 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7994 hc08_freeReg (hc08_reg_a);
7998 freeAsmop (op, NULL, ic, TRUE);
8002 /*-----------------------------------------------------------------*/
8003 /* genCritical - generate code for start of a critical sequence */
8004 /*-----------------------------------------------------------------*/
8006 genCritical (iCode *ic)
8008 D(emitcode("; genCritical",""));
8011 aopOp (IC_RESULT (ic), ic, TRUE);
8013 emitcode ("tpa", "");
8014 hc08_dirtyReg (hc08_reg_a, FALSE);
8015 emitcode ("sei", "");
8018 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8020 pushReg (hc08_reg_a, FALSE);
8022 hc08_freeReg (hc08_reg_a);
8024 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8027 /*-----------------------------------------------------------------*/
8028 /* genEndCritical - generate code for end of a critical sequence */
8029 /*-----------------------------------------------------------------*/
8031 genEndCritical (iCode *ic)
8033 D(emitcode("; genEndCritical",""));
8037 aopOp (IC_RIGHT (ic), ic, FALSE);
8038 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8039 emitcode ("tap", "");
8040 hc08_freeReg (hc08_reg_a);
8041 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8045 pullReg (hc08_reg_a);
8046 emitcode ("tap", "");
8052 /*-----------------------------------------------------------------*/
8053 /* genhc08Code - generate code for HC08 based controllers */
8054 /*-----------------------------------------------------------------*/
8056 genhc08Code (iCode * lic)
8063 lineHead = lineCurr = NULL;
8065 /* print the allocation information */
8066 if (allocInfo && currFunc)
8067 printAllocInfo (currFunc, codeOutFile);
8068 /* if debug information required */
8069 if (options.debug && currFunc)
8071 debugFile->writeFunction (currFunc, lic);
8074 if (IS_STATIC (currFunc->etype))
8075 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8077 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8081 /* stack pointer name */
8082 if (options.useXstack)
8087 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8089 hc08_aop_pass[0] = newAsmop (AOP_REG);
8090 hc08_aop_pass[0]->size=1;
8091 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8092 hc08_aop_pass[1] = newAsmop (AOP_REG);
8093 hc08_aop_pass[1]->size=1;
8094 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8095 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8096 hc08_aop_pass[2]->size=1;
8097 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8098 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8099 hc08_aop_pass[3]->size=1;
8100 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8102 for (ic = lic; ic; ic = ic->next)
8105 _G.current_iCode = ic;
8107 if (ic->level != clevel || ic->block != cblock)
8111 debugFile->writeScope(ic);
8117 if (ic->lineno && cln != ic->lineno)
8121 debugFile->writeCLine(ic);
8124 emitcode ("", "C$%s$%d$%d$%d ==.",
8125 FileBaseName (ic->filename), ic->lineno,
8126 ic->level, ic->block);
8130 if (!options.noCcodeInAsm) {
8131 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8132 printCLine(ic->filename, ic->lineno));
8136 if (options.iCodeInAsm) {
8140 for (i=0; i<6; i++) {
8141 sprintf (®sInUse[i],
8142 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8145 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8147 /* if the result is marked as
8148 spilt and rematerializable or code for
8149 this has already been generated then
8151 if (resultRemat (ic) || ic->generated)
8159 for (i=A_IDX;i<=XA_IDX;i++)
8161 reg = hc08_regWithIdx(i);
8163 emitcode("","; %s = %s offset %d", reg->name,
8164 aopName(reg->aop), reg->aopofs);
8167 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8169 sym = OP_SYMBOL (IC_LEFT (ic));
8170 if (sym->accuse == ACCUSE_HX)
8172 hc08_reg_h->isFree = FALSE;
8173 hc08_reg_x->isFree = FALSE;
8175 else if (sym->accuse == ACCUSE_XA)
8177 hc08_reg_a->isFree = FALSE;
8179 hc08_reg_x->isFree = FALSE;
8182 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8184 sym = OP_SYMBOL (IC_RIGHT (ic));
8185 if (sym->accuse == ACCUSE_HX)
8187 hc08_reg_h->isFree = FALSE;
8188 hc08_reg_x->isFree = FALSE;
8190 else if (sym->accuse == ACCUSE_XA)
8192 hc08_reg_a->isFree = FALSE;
8194 hc08_reg_x->isFree = FALSE;
8199 /* depending on the operation */
8219 /* IPOP happens only when trying to restore a
8220 spilt live range, if there is an ifx statement
8221 following this pop then the if statement might
8222 be using some of the registers being popped which
8223 would destory the contents of the register so
8224 we need to check for this condition and handle it */
8226 ic->next->op == IFX &&
8227 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8228 genIfx (ic->next, ic);
8246 genEndFunction (ic);
8262 if (!genPointerGetSetOfs (ic))
8267 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8284 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8288 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8295 /* note these two are xlated by algebraic equivalence
8296 during parsing SDCC.y */
8297 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8298 "got '>=' or '<=' shouldn't have come here");
8302 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8314 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8318 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8322 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8349 case GET_VALUE_AT_ADDRESS:
8351 hasInc (IC_LEFT (ic), ic,
8352 getSize (operandType (IC_RESULT (ic)))),
8353 ifxForOp (IC_RESULT (ic), ic) );
8357 if (POINTER_SET (ic))
8358 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8384 addSet (&_G.sendSet, ic);
8387 case DUMMY_READ_VOLATILE:
8396 genEndCritical (ic);
8407 if (!hc08_reg_a->isFree)
8408 D(emitcode("","; forgot to free a"));
8409 if (!hc08_reg_x->isFree)
8410 D(emitcode("","; forgot to free x"));
8411 if (!hc08_reg_h->isFree)
8412 D(emitcode("","; forgot to free h"));
8413 if (!hc08_reg_hx->isFree)
8414 D(emitcode("","; forgot to free hx"));
8415 if (!hc08_reg_xa->isFree)
8416 D(emitcode("","; forgot to free xa"));
8419 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8422 /* now we are ready to call the
8423 peep hole optimizer */
8424 if (!options.nopeep)
8425 peepHole (&lineHead);
8427 /* now do the actual printing */
8428 printLine (lineHead, codeOutFile);