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);
693 char * l = aopAdrStr (aop, loffset, FALSE);
694 if (!strcmp (l, zero))
696 emitcode ("clrh", "");
700 if (hc08_reg_a->isFree)
702 loadRegFromAop (hc08_reg_a, aop, loffset);
703 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
705 else if (hc08_reg_x->isFree)
707 loadRegFromAop (hc08_reg_x, aop, loffset);
708 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
712 pushReg (hc08_reg_a, TRUE);
713 loadRegFromAop (hc08_reg_a, aop, loffset);
714 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
715 pullReg (hc08_reg_a);
721 else if (IS_AOP_XA(aop))
722 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
723 else if ((aop->type == AOP_DIR))
725 if (aop->size>(loffset+1))
726 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
729 loadRegFromAop (hc08_reg_x, aop, loffset);
730 loadRegFromConst (hc08_reg_h, zero);
733 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
735 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
740 needpula = pushRegIfUsed (hc08_reg_a);
741 loadRegFromAop (hc08_reg_a, aop, loffset+1);
742 loadRegFromAop (hc08_reg_x, aop, loffset);
743 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
744 pullOrFreeReg (hc08_reg_a, needpula);
750 else if (IS_AOP_HX(aop))
751 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
754 loadRegFromAop (hc08_reg_a, aop, loffset);
755 loadRegFromAop (hc08_reg_x, aop, loffset+1);
760 // ignore caching for now
763 reg->aopofs = loffset;
768 /*--------------------------------------------------------------------------*/
769 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
770 /* freeAsmop is called with aop, the stacked data will */
771 /* be copied to the original aop location and */
772 /*--------------------------------------------------------------------------*/
774 forceStackedAop (asmop *aop)
777 asmop *newaop = newAsmop (aop->type);
778 memcpy (newaop, aop, sizeof(*newaop));
780 D(emitcode("", "; forcedStackAop %s", aopName(aop)));
781 for (loffset=0; loffset < newaop->size; loffset++)
783 asmop *aopsof = newAsmop (AOP_SOF);
785 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
786 aopsof->op = aop->op;
787 newaop->stk_aop[loffset] = aopsof;
794 /*--------------------------------------------------------------------------*/
795 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
796 /*--------------------------------------------------------------------------*/
798 storeRegToAop (regs *reg, asmop *aop, int loffset)
800 int regidx = reg->rIdx;
806 D(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
807 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
809 if ((reg->rIdx == HX_IDX) && aop->stacked
810 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
812 storeRegToAop (hc08_reg_h, aop, loffset+1);
813 storeRegToAop (hc08_reg_x, aop, loffset);
817 if ((reg->rIdx == XA_IDX) && aop->stacked
818 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
820 storeRegToAop (hc08_reg_x, aop, loffset+1);
821 storeRegToAop (hc08_reg_a, aop, loffset);
825 if (aop->stacked && aop->stk_aop[loffset])
827 storeRegToAop (reg, aop->stk_aop[loffset], 0);
831 if (aop->type == AOP_STR)
834 transferRegReg (reg, hc08_reg_x, FALSE);
836 transferRegReg (reg, hc08_reg_h, FALSE);
840 if (aop->type == AOP_DUMMY)
846 if ((aop->type == AOP_REG) && (loffset < aop->size))
847 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
849 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
852 if ((aop->type == AOP_REG) && (loffset < aop->size))
853 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
855 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
858 if (hc08_reg_a->isFree)
860 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
861 storeRegToAop (hc08_reg_a, aop, loffset);
862 hc08_freeReg (hc08_reg_a);
864 else if (hc08_reg_x->isFree)
866 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
867 storeRegToAop (hc08_reg_x, aop, loffset);
868 hc08_freeReg (hc08_reg_x);
872 pushReg (hc08_reg_a, TRUE);
873 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
874 storeRegToAop (hc08_reg_a, aop, loffset);
875 pullReg (hc08_reg_a);
879 if ((aop->type == AOP_DIR) )
881 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
883 else if (IS_AOP_XA(aop))
884 transferRegReg(reg, hc08_reg_xa, FALSE);
885 else if (IS_AOP_HX(aop))
890 needpula = pushRegIfUsed (hc08_reg_a);
891 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
892 storeRegToAop (hc08_reg_a, aop, loffset+1);
893 storeRegToAop (hc08_reg_x, aop, loffset);
894 pullOrFreeReg (hc08_reg_a, needpula);
899 transferRegReg(reg, hc08_reg_hx, FALSE);
900 else if (IS_AOP_XA(aop))
904 storeRegToAop (hc08_reg_a, aop, loffset);
905 storeRegToAop (hc08_reg_x, aop, loffset+1);
910 /* Disable the register tracking for now */
912 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
915 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
917 otherreg=hc08_regWithIdx(otheridx);
918 if (otherreg && otherreg->aop
919 && otherreg->aop->op && aop->op
920 && operandsEqu(otherreg->aop->op,aop->op)
921 && (otherreg->aopofs == loffset))
923 D(emitcode("","; marking %s stale", otherreg->name));
927 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
929 hc08_reg_hx->aop = NULL;
930 D(emitcode("","; marking hx stale"));
932 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
934 hc08_reg_xa->aop = NULL;
935 D(emitcode("","; marking xa stale"));
939 reg->aopofs = loffset;
944 /*--------------------------------------------------------------------------*/
945 /* loadRegFromConst - Load register reg from constant c. */
946 /*--------------------------------------------------------------------------*/
948 loadRegFromConst (regs *reg, char *c)
954 emitcode ("clra", "");
956 emitcode ("lda", "%s", c);
960 emitcode ("clrx", "");
962 emitcode ("ldx", "%s", c);
966 emitcode ("clrh", "");
967 else if (hc08_reg_a->isFree)
969 loadRegFromConst (hc08_reg_a, c);
970 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
972 else if (hc08_reg_x->isFree)
974 loadRegFromConst (hc08_reg_x, c);
975 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
979 pushReg (hc08_reg_a, TRUE);
980 loadRegFromConst (hc08_reg_a, c);
981 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
982 pullReg (hc08_reg_a);
986 emitcode ("ldhx", "%s", c);
989 emitcode ("lda", "%s", c);
990 emitcode ("ldx", "%s >> 8", c);
993 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
994 "Bad rIdx in loadRegFromConst");
1001 /*--------------------------------------------------------------------------*/
1002 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
1003 /*--------------------------------------------------------------------------*/
1005 storeConstToAop (char *c, asmop *aop, int loffset)
1007 if (aop->stacked && aop->stk_aop[loffset])
1009 storeConstToAop (c, aop->stk_aop[loffset], 0);
1016 if (!strcmp(c,zero))
1017 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
1019 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
1022 if (loffset>(aop->size-1))
1024 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
1029 if (hc08_reg_a->isFree)
1031 loadRegFromConst (hc08_reg_a, c);
1032 storeRegToAop( hc08_reg_a, aop, loffset);
1033 hc08_freeReg (hc08_reg_a);
1035 else if (hc08_reg_x->isFree)
1037 loadRegFromConst (hc08_reg_x, c);
1038 storeRegToAop( hc08_reg_x, aop, loffset);
1039 hc08_freeReg (hc08_reg_x);
1043 pushReg (hc08_reg_a, TRUE);
1044 loadRegFromConst (hc08_reg_a, c);
1045 storeRegToAop( hc08_reg_a, aop, loffset);
1046 pullReg (hc08_reg_a);
1052 /*--------------------------------------------------------------------------*/
1053 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
1054 /* reg is extended to fill logical offsets loffset */
1055 /* and above of asmop aop. Otherwise, logical */
1056 /* offsets loffset and above of asmop aop are */
1057 /* zeroed. reg must be an 8-bit register. */
1058 /*--------------------------------------------------------------------------*/
1060 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
1062 // int regidx = reg->rIdx;
1063 int size = aop->size;
1071 while (loffset<size)
1072 storeConstToAop(zero, aop, loffset++);
1077 transferRegReg (reg, hc08_reg_a, FALSE);
1078 emitcode ("rola","");
1079 emitcode ("clra","");
1080 emitcode ("sbc", "#0");
1081 hc08_useReg (hc08_reg_a);
1082 while (loffset<size)
1083 storeRegToAop (hc08_reg_a, aop, loffset++);
1084 hc08_freeReg (hc08_reg_a);
1088 /*--------------------------------------------------------------------------*/
1089 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1090 /* padding and/or truncation as needed. If isSigned is */
1091 /* true, sign extension will take place in the padding. */
1092 /*--------------------------------------------------------------------------*/
1094 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1096 int regidx = reg->rIdx;
1097 int size = aop->size;
1104 storeRegToAop (reg, aop, 0);
1105 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1110 storeRegToAop (hc08_reg_x, aop, 0);
1114 storeRegToAop (reg, aop, 0);
1115 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1121 storeRegToAop (hc08_reg_a, aop, 0);
1125 storeRegToAop (reg, aop, 0);
1126 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1132 /*--------------------------------------------------------------------------*/
1133 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1134 /* srcaop to logical offset dstofs of asmop dstaop. */
1135 /*--------------------------------------------------------------------------*/
1137 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1139 bool needpula = FALSE;
1142 bool keepreg = FALSE;
1144 /* ignore transfers at the same byte, unless its volatile */
1145 if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
1146 && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
1147 && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs)
1150 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1152 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1156 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1158 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1162 // D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1163 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1164 // D(emitcode ("", "; srcaop->type = %d", srcaop->type));
1165 // D(emitcode ("", "; dstaop->type = %d", dstaop->type));
1167 if (dstofs >= dstaop->size)
1170 if ((dstaop->type == AOP_DIR)
1171 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1173 if (srcaop->type == AOP_LIT)
1176 unsigned char bytemask;
1178 lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
1179 bytemask = (lit >> (srcofs*8)) & 0xff;
1183 emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
1188 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1189 aopAdrStr(dstaop, dstofs, FALSE));
1193 if (dstaop->type == AOP_REG)
1195 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1196 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1198 reg = dstaop->aopu.aop_reg[dstofs];
1203 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1205 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1206 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1208 reg = srcaop->aopu.aop_reg[srcofs];
1215 if (hc08_reg_a->isFree)
1217 else if (hc08_reg_x->isFree)
1221 pushReg (hc08_reg_a, TRUE);
1227 loadRegFromAop (reg, srcaop, srcofs);
1228 storeRegToAop (reg, dstaop, dstofs);
1231 pullOrFreeReg (hc08_reg_a, needpula);
1235 /*--------------------------------------------------------------------------*/
1236 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1237 /* parameter param. */
1238 /*--------------------------------------------------------------------------*/
1240 accopWithMisc (char *accop, char *param)
1242 emitcode (accop, "%s", param);
1243 hc08_dirtyReg (hc08_reg_a, FALSE);
1246 /*--------------------------------------------------------------------------*/
1247 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1248 /* byte at logical offset loffset of asmop aop. */
1249 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1250 /*--------------------------------------------------------------------------*/
1252 accopWithAop (char *accop, asmop *aop, int loffset)
1254 if (aop->stacked && aop->stk_aop[loffset])
1256 accopWithAop (accop, aop->stk_aop[loffset], 0);
1260 if (aop->type == AOP_DUMMY)
1263 if (aop->type == AOP_REG)
1265 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1266 emitcode (accop, "1,s");
1270 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1272 hc08_dirtyReg (hc08_reg_a, FALSE);
1276 /*--------------------------------------------------------------------------*/
1277 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1278 /* byte at logical offset loffset of asmop aop. Register reg */
1279 /* must be 8-bit. */
1280 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1281 /*--------------------------------------------------------------------------*/
1283 rmwWithReg (char *rmwop, regs *reg)
1286 char *rmwaop = rmwbuf;
1288 if (reg->rIdx == A_IDX)
1290 sprintf(rmwaop,"%sa", rmwop);
1291 emitcode (rmwaop, "");
1292 hc08_dirtyReg (hc08_reg_a, FALSE);
1294 else if (reg->rIdx == X_IDX)
1296 sprintf(rmwaop,"%sx", rmwop);
1297 emitcode (rmwaop, "");
1298 hc08_dirtyReg (hc08_reg_a, FALSE);
1300 else if (hc08_reg_a->isFree)
1302 transferRegReg(reg, hc08_reg_a, FALSE);
1303 sprintf(rmwaop,"%sa", rmwop);
1304 emitcode (rmwaop, "");
1305 hc08_dirtyReg (hc08_reg_a, FALSE);
1306 transferRegReg(hc08_reg_a, reg, TRUE);
1310 pushReg (reg, FALSE);
1311 emitcode (rmwop, "1,s");
1313 hc08_dirtyReg (reg, FALSE);
1317 /*--------------------------------------------------------------------------*/
1318 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1319 /* logical offset loffset of asmop aop. */
1320 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
1321 /*--------------------------------------------------------------------------*/
1323 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1325 bool needpula = FALSE;
1327 if (aop->stacked && aop->stk_aop[loffset])
1329 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1336 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1339 needpula = pushRegIfUsed (hc08_reg_a);
1340 loadRegFromAop (hc08_reg_a, aop, loffset);
1341 rmwWithReg (rmwop, hc08_reg_a);
1342 if (strcmp ("tst", rmwop))
1343 storeRegToAop (hc08_reg_a, aop, loffset);
1344 pullOrFreeReg (hc08_reg_a, needpula);
1349 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1355 /*-----------------------------------------------------------------*/
1356 /* newAsmop - creates a new asmOp */
1357 /*-----------------------------------------------------------------*/
1359 newAsmop (short type)
1363 aop = Safe_calloc (1, sizeof (asmop));
1370 /*-----------------------------------------------------------------*/
1371 /* pointerCode - returns the code for a pointer type */
1372 /*-----------------------------------------------------------------*/
1374 pointerCode (sym_link * etype)
1377 return PTR_TYPE (SPEC_OCLS (etype));
1382 /*-----------------------------------------------------------------*/
1383 /* aopForSym - for a true symbol */
1384 /*-----------------------------------------------------------------*/
1386 aopForSym (iCode * ic, symbol * sym, bool result)
1391 wassertl (ic != NULL, "Got a null iCode");
1392 wassertl (sym != NULL, "Got a null symbol");
1394 // printf("in aopForSym for symbol %s\n", sym->name);
1396 space = SPEC_OCLS (sym->etype);
1398 /* if already has one */
1404 /* special case for a function */
1405 if (IS_FUNC (sym->type))
1407 sym->aop = aop = newAsmop (AOP_IMMD);
1408 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1409 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1410 aop->size = FPTRSIZE;
1414 /* if it is in direct space */
1415 if (IN_DIRSPACE (space))
1417 sym->aop = aop = newAsmop (AOP_DIR);
1418 aop->aopu.aop_dir = sym->rname;
1419 aop->size = getSize (sym->type);
1423 /* if it is in far space */
1424 if (IN_FARSPACE (space))
1426 sym->aop = aop = newAsmop (AOP_EXT);
1427 aop->aopu.aop_dir = sym->rname;
1428 aop->size = getSize (sym->type);
1432 if (IN_STACK (sym->etype))
1434 sym->aop = aop = newAsmop (AOP_SOF);
1435 aop->aopu.aop_dir = sym->rname;
1436 aop->size = getSize (sym->type);
1437 aop->aopu.aop_stk = sym->stack;
1443 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1444 "aopForSym should never reach here");
1448 /* if it is in code space */
1449 if (IN_CODESPACE (space))
1455 /*-----------------------------------------------------------------*/
1456 /* aopForRemat - rematerialzes an object */
1457 /*-----------------------------------------------------------------*/
1459 aopForRemat (symbol * sym)
1461 iCode *ic = sym->rematiCode;
1469 val += (int) operandLitValue (IC_RIGHT (ic));
1470 else if (ic->op == '-')
1471 val -= (int) operandLitValue (IC_RIGHT (ic));
1472 else if (IS_CAST_ICODE(ic)) {
1473 sym_link *from_type = operandType(IC_RIGHT(ic));
1474 aop->aopu.aop_immd.from_cast_remat = 1;
1475 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1476 ptr_type = DCL_TYPE(from_type);
1477 if (ptr_type == IPOINTER) {
1484 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1487 if (ic->op == ADDRESS_OF)
1490 sprintf (buffer, "(%s %c 0x%04x)",
1491 OP_SYMBOL (IC_LEFT (ic))->rname,
1492 val >= 0 ? '+' : '-',
1493 abs (val) & 0xffff);
1495 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1497 aop = newAsmop (AOP_IMMD);
1498 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1499 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1500 /* set immd2 field if required */
1501 if (aop->aopu.aop_immd.from_cast_remat)
1503 sprintf(buffer,"#0x%02x",ptr_type);
1504 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1505 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1508 else if (ic->op == '=')
1510 val += (int) operandLitValue (IC_RIGHT (ic));
1512 sprintf (buffer, "0x%04x", val);
1513 aop = newAsmop (AOP_LIT);
1514 aop->aopu.aop_lit = constVal (buffer);
1517 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1518 "unexpected rematerialization");
1525 /*-----------------------------------------------------------------*/
1526 /* regsInCommon - two operands have some registers in common */
1527 /*-----------------------------------------------------------------*/
1529 regsInCommon (operand * op1, operand * op2)
1531 symbol *sym1, *sym2;
1534 /* if they have registers in common */
1535 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1538 sym1 = OP_SYMBOL (op1);
1539 sym2 = OP_SYMBOL (op2);
1541 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1544 for (i = 0; i < sym1->nRegs; i++)
1550 for (j = 0; j < sym2->nRegs; j++)
1555 if (sym2->regs[j] == sym1->regs[i])
1563 /*-----------------------------------------------------------------*/
1564 /* operandsEqu - equivalent */
1565 /*-----------------------------------------------------------------*/
1567 operandsEqu (operand * op1, operand * op2)
1569 symbol *sym1, *sym2;
1571 /* if they not symbols */
1572 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1575 sym1 = OP_SYMBOL (op1);
1576 sym2 = OP_SYMBOL (op2);
1578 /* if both are itemps & one is spilt
1579 and the other is not then false */
1580 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1581 sym1->isspilt != sym2->isspilt)
1584 /* if they are the same */
1588 if (sym1->rname[0] && sym2->rname[0]
1589 && strcmp (sym1->rname, sym2->rname) == 0)
1592 /* if left is a tmp & right is not */
1593 if (IS_ITEMP (op1) &&
1596 (sym1->usl.spillLoc == sym2))
1599 if (IS_ITEMP (op2) &&
1603 (sym2->usl.spillLoc == sym1))
1609 /*-----------------------------------------------------------------*/
1610 /* sameRegs - two asmops have the same registers */
1611 /*-----------------------------------------------------------------*/
1613 sameRegs (asmop * aop1, asmop * aop2)
1620 // if (aop1->size != aop2->size)
1623 if (aop1->type == aop2->type)
1628 for (i = 0; i < aop1->size; i++)
1629 if (aop1->aopu.aop_reg[i] !=
1630 aop2->aopu.aop_reg[i])
1634 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1637 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1644 /*-----------------------------------------------------------------*/
1645 /* aopOp - allocates an asmop for an operand : */
1646 /*-----------------------------------------------------------------*/
1648 aopOp (operand * op, iCode * ic, bool result)
1657 // Is this a pointer set result?
1659 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1663 // printf("checking literal\n");
1664 /* if this a literal */
1665 if (IS_OP_LITERAL (op))
1667 op->aop = aop = newAsmop (AOP_LIT);
1668 aop->aopu.aop_lit = op->operand.valOperand;
1669 aop->size = getSize (operandType (op));
1671 aop->isaddr = op->isaddr;
1675 // printf("checking pre-existing\n");
1676 /* if already has a asmop then continue */
1680 op->aop->isaddr = op->isaddr;
1684 // printf("checking underlying sym\n");
1685 /* if the underlying symbol has a aop */
1686 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1688 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1689 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1690 //op->aop = aop = OP_SYMBOL (op)->aop;
1691 aop->size = getSize( operandType (op));
1692 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1693 //printf (" with size = %d\n", aop->size);
1696 aop->isaddr = op->isaddr;
1697 /* if (aop->isaddr & IS_ITEMP (op))
1699 aop->psize=aop->size;
1700 aop->size = getSize( operandType (op)->next);
1705 // printf("checking true sym\n");
1706 /* if this is a true symbol */
1707 if (IS_TRUE_SYMOP (op))
1709 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1711 aop->isaddr = op->isaddr;
1712 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1713 //printf (" with size = %d\n", aop->size);
1717 /* this is a temporary : this has
1723 e) can be a return use only */
1725 sym = OP_SYMBOL (op);
1727 // printf("checking conditional\n");
1728 /* if the type is a conditional */
1729 if (sym->regType == REG_CND)
1731 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1734 aop->isaddr = op->isaddr;
1738 // printf("checking spilt\n");
1739 /* if it is spilt then two situations
1741 b) has a spill location */
1742 if (sym->isspilt || sym->nRegs == 0)
1745 // printf("checking remat\n");
1746 /* rematerialize it NOW */
1749 sym->aop = op->aop = aop =
1751 aop->size = getSize (sym->type);
1753 aop->isaddr = op->isaddr;
1754 /* if (aop->isaddr & IS_ITEMP (op))
1756 aop->psize=aop->size;
1757 aop->size = getSize( operandType (op)->next);
1762 // printf("checking accuse\n");
1765 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1766 aop->size = getSize (sym->type);
1767 switch (sym->accuse)
1770 aop->aopu.aop_reg[0] = hc08_reg_a;
1771 aop->aopu.aop_reg[1] = hc08_reg_x;
1774 aop->aopu.aop_reg[0] = hc08_reg_x;
1775 aop->aopu.aop_reg[1] = hc08_reg_h;
1779 aop->isaddr = op->isaddr;
1783 // printf("checking ruonly\n");
1789 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1790 aop->size = getSize (sym->type);
1791 for (i = 0; i < fReturnSizeHC08; i++)
1792 aop->aopu.aop_str[i] = fReturn2[i];
1794 aop->isaddr = op->isaddr;
1798 /* else spill location */
1799 if (sym->usl.spillLoc)
1801 if (sym->usl.spillLoc->aop
1802 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1804 /* force a new aop if sizes differ */
1805 sym->usl.spillLoc->aop = NULL;
1806 //printf ("forcing new aop\n");
1808 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1809 aop->size = getSize (sym->type);
1811 aop->isaddr = op->isaddr;
1812 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1813 //printf (" with size = %d\n", aop->size);
1817 /* else must be a dummy iTemp */
1818 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1819 aop->size = getSize (sym->type);
1823 // printf("assuming register\n");
1824 /* must be in a register */
1825 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1826 aop->size = sym->nRegs;
1827 for (i = 0; i < sym->nRegs; i++)
1828 aop->aopu.aop_reg[i] = sym->regs[i];
1830 aop->isaddr = op->isaddr;
1834 /*-----------------------------------------------------------------*/
1835 /* freeAsmop - free up the asmop given to an operand */
1836 /*----------------------------------------------------------------*/
1838 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1860 D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1863 for (loffset=0; loffset<aop->size; loffset++)
1864 if (aop->stk_aop[loffset])
1866 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1869 pullNull (stackAdjust);
1873 /* all other cases just dealloc */
1879 OP_SYMBOL (op)->aop = NULL;
1880 /* if the symbol has a spill */
1882 SPIL_LOC (op)->aop = NULL;
1888 /*-----------------------------------------------------------------*/
1889 /* aopDerefAop - treating the aop parameter as a pointer, return */
1890 /* an asmop for the object it references */
1891 /*-----------------------------------------------------------------*/
1893 aopDerefAop (asmop *aop)
1898 asmop *newaop = NULL;
1899 sym_link *type, *etype;
1902 D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1906 type = operandType (aop->op);
1907 etype = getSpec (type);
1908 /* if op is of type of pointer then it is simple */
1909 if (IS_PTR (type) && !IS_FUNC (type->next))
1910 p_type = DCL_TYPE (type);
1913 /* we have to go by the storage class */
1914 p_type = PTR_TYPE (SPEC_OCLS (etype));
1923 if (p_type == POINTER)
1924 newaop = newAsmop (AOP_DIR);
1926 newaop = newAsmop (AOP_EXT);
1927 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1930 adr = (int) floatFromVal (aop->aopu.aop_lit);
1931 if (p_type == POINTER)
1936 newaop = newAsmop (AOP_DIR);
1937 sprintf (s, "0x%02x",adr);
1941 newaop = newAsmop (AOP_EXT);
1942 sprintf (s, "0x%04x",adr);
1944 rs = Safe_calloc (1, strlen (s) + 1);
1946 newaop->aopu.aop_dir = rs;
1949 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1950 "unsupported asmop");
1960 /*-----------------------------------------------------------------*/
1961 /* aopAdrStr - for referencing the address of the aop */
1962 /*-----------------------------------------------------------------*/
1964 aopAdrStr (asmop * aop, int loffset, bool bit16)
1968 int offset = aop->size - 1 - loffset;
1971 /* offset is greater than
1973 if (loffset > (aop->size - 1) &&
1974 aop->type != AOP_LIT)
1977 /* depending on type */
1985 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1986 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1988 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1992 sprintf (s, "#(%s >> %d)",
1993 aop->aopu.aop_immd.aop_immd1,
1997 aop->aopu.aop_immd.aop_immd1);
2001 aop->aopu.aop_immd.aop_immd1);
2002 rs = Safe_calloc (1, strlen (s) + 1);
2008 sprintf (s, "*(%s + %d)",
2012 sprintf (s, "*%s", aop->aopu.aop_dir);
2013 rs = Safe_calloc (1, strlen (s) + 1);
2019 sprintf (s, "(%s + %d)",
2023 sprintf (s, "%s", aop->aopu.aop_dir);
2024 rs = Safe_calloc (1, strlen (s) + 1);
2029 return aop->aopu.aop_reg[loffset]->name;
2033 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2035 return aopLiteral (aop->aopu.aop_lit, loffset);
2039 return aop->aopu.aop_str[loffset];
2042 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2044 rs = Safe_calloc (1, strlen (s) + 1);
2050 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2051 "aopAdrStr got unsupported aop->type");
2060 /*-----------------------------------------------------------------*/
2061 /* opIsGptr: returns non-zero if the passed operand is */
2062 /* a generic pointer type. */
2063 /*-----------------------------------------------------------------*/
2065 opIsGptr (operand * op)
2067 sym_link *type = operandType (op);
2069 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2077 /*-----------------------------------------------------------------*/
2078 /* getDataSize - get the operand data size */
2079 /*-----------------------------------------------------------------*/
2081 getDataSize (operand * op)
2084 size = AOP_SIZE (op);
2088 /*-----------------------------------------------------------------*/
2089 /* outAcc - output Acc */
2090 /*-----------------------------------------------------------------*/
2092 outAcc (operand * result)
2095 size = getDataSize (result);
2098 storeRegToAop (hc08_reg_a, AOP (result), 0);
2101 /* unsigned or positive */
2104 storeConstToAop (zero, AOP (result), offset++);
2109 /*-----------------------------------------------------------------*/
2110 /* outBitC - output a bit C */
2111 /*-----------------------------------------------------------------*/
2113 outBitC (operand * result)
2117 /* if the result is bit */
2118 if (AOP_TYPE (result) == AOP_CRY)
2119 aopPut (AOP (result), "c", 0);
2123 emitcode ("clra", "");
2124 emitcode ("rola", "");
2129 /*-----------------------------------------------------------------*/
2130 /* outBitNV - output a bit N^V */
2131 /*-----------------------------------------------------------------*/
2133 outBitNV (operand * result)
2135 symbol *tlbl, *tlbl1;
2137 tlbl = newiTempLabel (NULL);
2138 tlbl1 = newiTempLabel (NULL);
2140 emitBranch ("blt", tlbl);
2141 loadRegFromConst (hc08_reg_a, zero);
2142 emitBranch ("bra", tlbl1);
2144 loadRegFromConst (hc08_reg_a, one);
2150 /*-----------------------------------------------------------------*/
2151 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2152 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2153 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2154 /*-----------------------------------------------------------------*/
2156 asmopToBool (asmop *aop, bool resultInA)
2158 symbol *tlbl, *tlbl1;
2159 int size = aop->size;
2160 bool needpula = FALSE;
2161 bool flagsonly = TRUE;
2166 hc08_freeReg(hc08_reg_a);
2173 emitcode ("tsta", "");
2176 else if (IS_AOP_X(aop))
2177 emitcode ("tstx", "");
2178 else if (IS_AOP_H(aop))
2180 if (hc08_reg_a->isFree)
2182 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2183 emitcode ("tsta", "");
2185 hc08_freeReg(hc08_reg_a);
2187 else if (hc08_reg_x->isFree)
2189 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2190 emitcode ("tstx", "");
2191 hc08_freeReg(hc08_reg_x);
2195 emitcode ("pshh", "");
2196 emitcode ("tst", "1,s");
2197 emitcode ("ais", "#1");
2200 else if (IS_AOP_HX(aop))
2201 emitcode ("cphx", zero);
2202 else if (IS_AOP_XA(aop))
2204 symbol *tlbl = newiTempLabel (NULL);
2205 emitcode ("tsta", "");
2206 emitcode ("bne", "%05d$", (tlbl->key + 100));
2207 emitcode ("tstx", "");
2208 emitcode ("", "%05d$:", (tlbl->key + 100));
2212 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2213 "Bad rIdx in asmToBool");
2221 needpula = pushRegIfUsed (hc08_reg_a);
2222 loadRegFromAop (hc08_reg_a, aop, 0);
2223 for (offset=1; offset<size; offset++)
2224 accopWithAop ("ora", aop, offset);
2226 pullReg (hc08_reg_a);
2229 hc08_freeReg (hc08_reg_a);
2238 loadRegFromAop (hc08_reg_a, aop, 0);
2239 hc08_freeReg (hc08_reg_a);
2243 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2248 if (hc08_reg_a->isFree)
2250 loadRegFromAop (hc08_reg_a, aop, 0);
2251 accopWithAop ("ora", aop, 1);
2252 hc08_freeReg (hc08_reg_a);
2257 tlbl = newiTempLabel (NULL);
2258 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2259 emitcode ("bne", "%05d$", (tlbl->key + 100));
2260 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2261 emitcode ("", "%05d$:", (tlbl->key + 100));
2267 needpula = pushRegIfUsed (hc08_reg_a);
2268 loadRegFromAop (hc08_reg_a, aop, 0);
2269 for (offset=1; offset<size; offset++)
2270 accopWithAop ("ora", aop, offset);
2272 pullReg (hc08_reg_a);
2275 hc08_freeReg (hc08_reg_a);
2283 tlbl = newiTempLabel (NULL);
2287 tlbl1 = newiTempLabel (NULL);
2288 emitBranch ("bne", tlbl1);
2289 loadRegFromConst (hc08_reg_a, zero);
2290 emitBranch ("bra", tlbl);
2292 loadRegFromConst (hc08_reg_a, one);
2296 emitBranch ("beq", tlbl);
2297 loadRegFromConst (hc08_reg_a, one);
2300 hc08_useReg (hc08_reg_a);
2306 /*-----------------------------------------------------------------*/
2307 /* genNot - generate code for ! operation */
2308 /*-----------------------------------------------------------------*/
2312 D(emitcode ("; genNot",""));
2314 /* assign asmOps to operand & result */
2315 aopOp (IC_LEFT (ic), ic, FALSE);
2316 aopOp (IC_RESULT (ic), ic, TRUE);
2318 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2319 emitcode ("eor", one);
2320 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2322 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2323 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2327 /*-----------------------------------------------------------------*/
2328 /* genCpl - generate code for complement */
2329 /*-----------------------------------------------------------------*/
2335 regs* reg = hc08_reg_a;
2339 D(emitcode ("; genCpl",""));
2341 /* assign asmOps to operand & result */
2342 aopOp (IC_LEFT (ic), ic, FALSE);
2343 aopOp (IC_RESULT (ic), ic, TRUE);
2345 size = AOP_SIZE (IC_RESULT (ic));
2348 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2349 rmwWithReg ("com", reg);
2351 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2356 /* release the aops */
2357 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2358 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2361 /*-----------------------------------------------------------------*/
2362 /* genUminusFloat - unary minus for floating points */
2363 /*-----------------------------------------------------------------*/
2365 genUminusFloat (operand * op, operand * result)
2367 int size, offset = 0;
2370 D(emitcode ("; genUminusFloat",""));
2372 /* for this we just copy and then flip the bit */
2374 size = AOP_SIZE (op) - 1;
2378 transferAopAop (AOP (op), offset, AOP (result), offset);
2382 needpula = pushRegIfUsed (hc08_reg_a);
2383 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2384 emitcode ("eor", "#0x80");
2385 hc08_useReg (hc08_reg_a);
2386 storeRegToAop (hc08_reg_a, AOP (result), offset);
2387 pullOrFreeReg (hc08_reg_a, needpula);
2390 /*-----------------------------------------------------------------*/
2391 /* genUminus - unary minus code generation */
2392 /*-----------------------------------------------------------------*/
2394 genUminus (iCode * ic)
2397 sym_link *optype, *rtype;
2402 D(emitcode ("; genUminus",""));
2405 aopOp (IC_LEFT (ic), ic, FALSE);
2406 aopOp (IC_RESULT (ic), ic, TRUE);
2408 optype = operandType (IC_LEFT (ic));
2409 rtype = operandType (IC_RESULT (ic));
2411 /* if float then do float stuff */
2412 if (IS_FLOAT (optype))
2414 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2418 /* otherwise subtract from zero */
2419 size = AOP_SIZE (IC_LEFT (ic));
2424 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2425 needpula = pushRegIfUsed (hc08_reg_a);
2428 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2429 emitcode ("nega", "");
2430 hc08_freeReg (hc08_reg_a);
2431 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2432 SPEC_USIGN (operandType (IC_LEFT (ic))));
2433 pullOrFreeReg (hc08_reg_a, needpula);
2437 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2438 result = forceStackedAop (AOP (IC_RESULT (ic)));
2440 result = AOP (IC_RESULT (ic));
2442 needpula = pushRegIfUsed (hc08_reg_a);
2446 loadRegFromConst (hc08_reg_a, zero);
2447 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2448 storeRegToAop (hc08_reg_a, result, offset++);
2451 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2452 SPEC_USIGN (operandType (IC_LEFT (ic))));
2453 pullOrFreeReg (hc08_reg_a, needpula);
2455 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2456 freeAsmop (NULL, result, ic, TRUE);
2462 /* release the aops */
2463 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2464 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2467 /*-----------------------------------------------------------------*/
2468 /* saveRegisters - will look for a call and save the registers */
2469 /*-----------------------------------------------------------------*/
2471 saveRegisters (iCode * lic)
2478 for (ic = lic; ic; ic = ic->next)
2479 if (ic->op == CALL || ic->op == PCALL)
2484 fprintf (stderr, "found parameter push with no function call\n");
2488 /* if the registers have been saved already or don't need to be then
2492 if (IS_SYMOP(IC_LEFT(ic)) &&
2493 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2494 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2497 /* safe the registers in use at this time but skip the
2498 ones for the result */
2499 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2500 hc08_rUmaskForOp (IC_RESULT(ic)));
2503 for (i = 0; i < hc08_nRegs; i++)
2505 if (bitVectBitValue (rsave, i))
2506 pushReg ( hc08_regWithIdx (i), FALSE);
2510 /*-----------------------------------------------------------------*/
2511 /* unsaveRegisters - pop the pushed registers */
2512 /*-----------------------------------------------------------------*/
2514 unsaveRegisters (iCode * ic)
2519 /* restore the registers in use at this time but skip the
2520 ones for the result */
2521 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2522 hc08_rUmaskForOp (IC_RESULT(ic)));
2524 for (i = hc08_nRegs; i >= 0; i--)
2526 if (bitVectBitValue (rsave, i))
2527 pullReg ( hc08_regWithIdx (i));
2533 /*-----------------------------------------------------------------*/
2535 /*-----------------------------------------------------------------*/
2537 pushSide (operand * oper, int size)
2542 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2543 pushReg ( hc08_reg_a, TRUE);
2547 /*-----------------------------------------------------------------*/
2548 /* assignResultValue - */
2549 /*-----------------------------------------------------------------*/
2551 assignResultValue (operand * oper)
2553 int size = AOP_SIZE (oper);
2557 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2558 if (hc08_aop_pass[offset]->type == AOP_REG)
2559 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2566 /*-----------------------------------------------------------------*/
2567 /* genIpush - genrate code for pushing this gets a little complex */
2568 /*-----------------------------------------------------------------*/
2570 genIpush (iCode * ic)
2572 int size, offset = 0;
2575 D(emitcode ("; genIpush",""));
2577 /* if this is not a parm push : ie. it is spill push
2578 and spill push is always done on the local stack */
2582 /* and the item is spilt then do nothing */
2583 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2586 aopOp (IC_LEFT (ic), ic, FALSE);
2587 size = AOP_SIZE (IC_LEFT (ic));
2589 /* push it on the stack */
2592 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2593 pushReg ( hc08_reg_a, TRUE);
2599 /* this is a paramter push: in this case we call
2600 the routine to find the call and save those
2601 registers that need to be saved */
2604 /* then do the push */
2605 aopOp (IC_LEFT (ic), ic, FALSE);
2608 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2609 size = AOP_SIZE (IC_LEFT (ic));
2612 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2613 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2615 if ((size==2) && hc08_reg_hx->isFree)
2617 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2618 pushReg (hc08_reg_hx, TRUE);
2625 // printf("loading %d\n", offset);
2626 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2627 // printf("pushing \n");
2628 pushReg (hc08_reg_a, TRUE);
2632 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2635 /*-----------------------------------------------------------------*/
2636 /* genIpop - recover the registers: can happen only for spilling */
2637 /*-----------------------------------------------------------------*/
2639 genIpop (iCode * ic)
2643 D(emitcode ("; genIpop",""));
2645 /* if the temp was not pushed then */
2646 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2649 aopOp (IC_LEFT (ic), ic, FALSE);
2650 size = AOP_SIZE (IC_LEFT (ic));
2654 pullReg (hc08_reg_a);
2655 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2657 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2661 /*-----------------------------------------------------------------*/
2662 /* genSend - gen code for SEND */
2663 /*-----------------------------------------------------------------*/
2664 static void genSend(set *sendSet)
2668 for (sic = setFirstItem (sendSet); sic;
2669 sic = setNextItem (sendSet)) {
2670 int size, offset = 0;
2671 aopOp (IC_LEFT (sic), sic, FALSE);
2672 size = AOP_SIZE (IC_LEFT (sic));
2677 transferAopAop( AOP (IC_LEFT (sic)), offset,
2678 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2682 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2686 /*-----------------------------------------------------------------*/
2687 /* genCall - generates a call statement */
2688 /*-----------------------------------------------------------------*/
2690 genCall (iCode * ic)
2693 // bool restoreBank = FALSE;
2694 // bool swapBanks = FALSE;
2696 D(emitcode("; genCall",""));
2698 dtype = operandType (IC_LEFT (ic));
2699 /* if send set is not empty then assign */
2702 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2703 genSend(reverseSet(_G.sendSet));
2705 genSend(_G.sendSet);
2711 /* if caller saves & we have not saved then */
2717 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2718 OP_SYMBOL (IC_LEFT (ic))->rname :
2719 OP_SYMBOL (IC_LEFT (ic))->name));
2722 /* if we need assign a result value */
2723 if ((IS_ITEMP (IC_RESULT (ic)) &&
2724 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2725 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2726 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2727 IS_TRUE_SYMOP (IC_RESULT (ic)))
2731 aopOp (IC_RESULT (ic), ic, FALSE);
2734 assignResultValue (IC_RESULT (ic));
2736 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2739 /* adjust the stack for parameters if
2743 pullNull (ic->parmBytes);
2746 /* if we had saved some registers then unsave them */
2747 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2748 unsaveRegisters (ic);
2752 /*-----------------------------------------------------------------*/
2753 /* -10l - generates a call by pointer statement */
2754 /*-----------------------------------------------------------------*/
2756 genPcall (iCode * ic)
2759 symbol *rlbl = newiTempLabel (NULL);
2760 symbol *tlbl = newiTempLabel (NULL);
2761 // bool restoreBank=FALSE;
2762 // bool swapBanks = FALSE;
2764 D(emitcode("; genPCall",""));
2766 /* if caller saves & we have not saved then */
2770 /* if we are calling a not _naked function that is not using
2771 the same register bank then we need to save the
2772 destination registers on the stack */
2773 dtype = operandType (IC_LEFT (ic))->next;
2775 /* now push the calling address */
2776 emitBranch ("bsr", tlbl);
2777 emitBranch ("bra", rlbl);
2780 /* Push the function's address */
2781 aopOp (IC_LEFT (ic), ic, FALSE);
2782 pushSide (IC_LEFT (ic), FPTRSIZE);
2783 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2785 /* if send set is not empty the assign */
2788 genSend(reverseSet(_G.sendSet));
2794 emitcode ("rts", "");
2799 /* if we need assign a result value */
2800 if ((IS_ITEMP (IC_RESULT (ic)) &&
2801 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2802 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2803 IS_TRUE_SYMOP (IC_RESULT (ic)))
2807 aopOp (IC_RESULT (ic), ic, FALSE);
2810 assignResultValue (IC_RESULT (ic));
2812 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2815 /* adjust the stack for parameters if
2819 pullNull (ic->parmBytes);
2822 /* if we hade saved some registers then
2824 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2825 unsaveRegisters (ic);
2828 /*-----------------------------------------------------------------*/
2829 /* resultRemat - result is rematerializable */
2830 /*-----------------------------------------------------------------*/
2832 resultRemat (iCode * ic)
2834 if (SKIP_IC (ic) || ic->op == IFX)
2837 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2839 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2840 if (sym->remat && !POINTER_SET (ic))
2847 #if defined(__BORLANDC__) || defined(_MSC_VER)
2848 #define STRCASECMP stricmp
2850 #define STRCASECMP strcasecmp
2853 /*-----------------------------------------------------------------*/
2854 /* inExcludeList - return 1 if the string is in exclude Reg list */
2855 /*-----------------------------------------------------------------*/
2857 regsCmp(void *p1, void *p2)
2859 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2863 inExcludeList (char *s)
2865 const char *p = setFirstItem(options.excludeRegsSet);
2867 if (p == NULL || STRCASECMP(p, "none") == 0)
2871 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2874 /*-----------------------------------------------------------------*/
2875 /* genFunction - generated code for function entry */
2876 /*-----------------------------------------------------------------*/
2878 genFunction (iCode * ic)
2880 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2882 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2883 int stackAdjust = sym->stack;
2884 int accIsFree = sym->recvSize != 0;
2888 /* create the function header */
2889 emitcode (";", "-----------------------------------------");
2890 emitcode (";", " function %s", sym->name);
2891 emitcode (";", "-----------------------------------------");
2893 emitcode ("", "%s:", sym->rname);
2894 ftype = operandType (IC_LEFT (ic));
2898 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2900 if (IFFUNC_ISNAKED(ftype))
2902 emitcode(";", "naked function: no prologue.");
2906 /* if this is an interrupt service routine then
2908 if (IFFUNC_ISISR (sym->type))
2911 if (!inExcludeList ("h"))
2912 pushReg (hc08_reg_h, FALSE);
2915 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2916 /* before setting up the stack frame completely. */
2917 while (ric && ric->next && ric->next->op == RECEIVE)
2919 while (ric && IC_RESULT (ric))
2921 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2922 int rsymSize = rsym ? getSize(rsym->type) : 0;
2926 if (rsym && rsym->regType == REG_CND)
2928 if (rsym && (rsym->accuse || rsym->ruonly))
2930 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2931 rsym = rsym->usl.spillLoc;
2934 /* If the RECEIVE operand immediately spills to the first entry on the */
2935 /* stack, we can push it directly rather than use an sp relative store. */
2936 if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2940 _G.current_iCode = ric;
2941 D(emitcode ("; genReceive",""));
2942 for (ofs=0; ofs < rsymSize; ofs++)
2944 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2945 pushReg (reg, TRUE);
2946 if (reg->rIdx == A_IDX)
2950 _G.current_iCode = ic;
2953 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2956 /* adjust the stack for the function */
2959 adjustStack (-stackAdjust);
2961 _G.stackOfs = sym->stack;
2964 /* if critical function then turn interrupts off */
2965 if (IFFUNC_ISCRITICAL (ftype))
2969 /* Function was passed parameters, so make sure A is preserved */
2970 pushReg (hc08_reg_a, FALSE);
2971 pushReg (hc08_reg_a, FALSE);
2972 emitcode ("tpa", "");
2973 emitcode ("sta", "2,s");
2974 emitcode ("sei", "");
2975 pullReg (hc08_reg_a);
2979 /* No passed parameters, so A can be freely modified */
2980 emitcode ("tpa", "");
2981 pushReg (hc08_reg_a, TRUE);
2982 emitcode ("sei", "");
2988 /*-----------------------------------------------------------------*/
2989 /* genEndFunction - generates epilogue for functions */
2990 /*-----------------------------------------------------------------*/
2992 genEndFunction (iCode * ic)
2994 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2996 if (IFFUNC_ISNAKED(sym->type))
2998 emitcode(";", "naked function: no epilogue.");
2999 if (options.debug && currFunc)
3000 debugFile->writeEndFunction (currFunc, ic, 0);
3004 if (IFFUNC_ISCRITICAL (sym->type))
3006 if (!IS_VOID(sym->type->next))
3008 /* Function has return value, so make sure A is preserved */
3009 pushReg (hc08_reg_a, FALSE);
3010 emitcode ("lda", "2,s");
3011 emitcode ("tap", "");
3012 pullReg (hc08_reg_a);
3017 /* Function returns void, so A can be freely modified */
3018 pullReg (hc08_reg_a);
3019 emitcode ("tap", "");
3023 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
3029 _G.stackPushes += sym->stack;
3030 adjustStack (sym->stack);
3034 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3038 if (IFFUNC_ISISR (sym->type))
3041 if (!inExcludeList ("h"))
3042 pullReg (hc08_reg_h);
3045 /* if debug then send end of function */
3046 if (options.debug && currFunc)
3048 debugFile->writeEndFunction (currFunc, ic, 1);
3051 emitcode ("rti", "");
3055 if (IFFUNC_CALLEESAVES(sym->type))
3059 /* if any registers used */
3062 /* save the registers used */
3063 for (i = sym->regsUsed->size; i >= 0; i--)
3065 if (bitVectBitValue (sym->regsUsed, i) ||
3066 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3067 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3073 /* if debug then send end of function */
3074 if (options.debug && currFunc)
3076 debugFile->writeEndFunction (currFunc, ic, 1);
3079 emitcode ("rts", "");
3084 /*-----------------------------------------------------------------*/
3085 /* genRet - generate code for return statement */
3086 /*-----------------------------------------------------------------*/
3090 int size, offset = 0;
3093 D(emitcode ("; genRet",""));
3095 /* if we have no return value then
3096 just generate the "ret" */
3100 /* we have something to return then
3101 move the return value into place */
3102 aopOp (IC_LEFT (ic), ic, FALSE);
3103 size = AOP_SIZE (IC_LEFT (ic));
3109 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3116 /* 4 byte return: store value in the global return variable */
3120 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3121 STA (fReturn2[offset--], FALSE);
3122 hc08_freeReg (hc08_reg_a);
3126 /* 2 byte return: store value in x:a */
3127 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3128 hc08_freeReg (hc08_reg_xa);
3131 /* 1 byte return: store value in a */
3132 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3133 hc08_freeReg (hc08_reg_a);
3138 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3141 /* generate a jump to the return label
3142 if the next is not the return statement */
3143 if (!(ic->next && ic->next->op == LABEL &&
3144 IC_LABEL (ic->next) == returnLabel))
3146 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3150 /*-----------------------------------------------------------------*/
3151 /* genLabel - generates a label */
3152 /*-----------------------------------------------------------------*/
3154 genLabel (iCode * ic)
3159 /* For the high level labels we cannot depend on any */
3160 /* register's contents. Amnesia time. */
3161 for (i=A_IDX;i<=XA_IDX;i++)
3163 reg = hc08_regWithIdx(i);
3168 /* special case never generate */
3169 if (IC_LABEL (ic) == entryLabel)
3172 debugFile->writeLabel(IC_LABEL (ic), ic);
3174 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3178 /*-----------------------------------------------------------------*/
3179 /* genGoto - generates a jmp */
3180 /*-----------------------------------------------------------------*/
3182 genGoto (iCode * ic)
3184 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3188 /*-----------------------------------------------------------------*/
3189 /* findLabelBackwards: walks back through the iCode chain looking */
3190 /* for the given label. Returns number of iCode instructions */
3191 /* between that label and given ic. */
3192 /* Returns zero if label not found. */
3193 /*-----------------------------------------------------------------*/
3195 findLabelBackwards (iCode * ic, int key)
3204 /* If we have any pushes or pops, we cannot predict the distance.
3205 I don't like this at all, this should be dealt with in the
3207 if (ic->op == IPUSH || ic->op == IPOP) {
3211 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3221 /*-----------------------------------------------------------------*/
3222 /* genPlusIncr :- does addition with increment if possible */
3223 /*-----------------------------------------------------------------*/
3225 genPlusIncr (iCode * ic)
3233 unsigned int size = getDataSize (IC_RESULT (ic));
3234 unsigned int offset;
3235 symbol *tlbl = NULL;
3237 left = IC_LEFT (ic);
3238 result = IC_RESULT (ic);
3240 /* will try to generate an increment */
3241 /* if the right side is not a literal
3243 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3246 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3248 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3250 if ((IS_AOP_HX (AOP (left)) ||
3251 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3253 && (icount>=-128) && (icount<=127) && (size==2))
3255 if (!IS_AOP_HX (AOP (left)))
3257 needpulx = pushRegIfUsed (hc08_reg_x);
3258 needpulh = pushRegIfUsed (hc08_reg_h);
3265 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3266 emitcode ("aix","#%d", icount);
3267 hc08_dirtyReg (hc08_reg_hx, FALSE);
3268 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3269 pullOrFreeReg (hc08_reg_h, needpulh);
3270 pullOrFreeReg (hc08_reg_x, needpulx);
3274 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3275 sameRegs (AOP (left), AOP (result))));
3277 if ((icount > 255) || (icount<0))
3280 if (!sameRegs (AOP (left), AOP (result)))
3283 D(emitcode ("; genPlusIncr",""));
3286 tlbl = newiTempLabel (NULL);
3291 rmwWithAop ("inc", AOP (result), 0);
3293 emitBranch ("bne", tlbl);
3297 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3298 needpula = pushRegIfUsed (hc08_reg_a);
3301 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3302 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3303 hc08_useReg (hc08_reg_a);
3304 storeRegToAop (hc08_reg_a, AOP (result), 0);
3305 hc08_freeReg (hc08_reg_a);
3307 emitBranch ("bcc", tlbl);
3309 for (offset=1; offset<size; offset++)
3311 rmwWithAop ("inc", AOP (result), offset);
3312 if ((offset+1)<size)
3313 emitBranch ("bne", tlbl);
3319 pullOrFreeReg (hc08_reg_a, needpula);
3326 /*-----------------------------------------------------------------*/
3327 /* genPlus - generates code for addition */
3328 /*-----------------------------------------------------------------*/
3330 genPlus (iCode * ic)
3332 int size, offset = 0;
3334 asmop *leftOp, *rightOp;
3336 /* special cases :- */
3338 D(emitcode ("; genPlus",""));
3340 aopOp (IC_LEFT (ic), ic, FALSE);
3341 aopOp (IC_RIGHT (ic), ic, FALSE);
3342 aopOp (IC_RESULT (ic), ic, TRUE);
3344 /* we want registers on the left and literals on the right */
3345 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3346 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3348 operand *t = IC_RIGHT (ic);
3349 IC_RIGHT (ic) = IC_LEFT (ic);
3354 /* if I can do an increment instead
3355 of add then GOOD for ME */
3356 if (genPlusIncr (ic) == TRUE)
3359 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3360 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3361 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3363 size = getDataSize (IC_RESULT (ic));
3365 leftOp = AOP(IC_LEFT(ic));
3366 rightOp = AOP(IC_RIGHT(ic));
3372 loadRegFromAop (hc08_reg_a, leftOp, offset);
3373 accopWithAop(add, rightOp, offset);
3374 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3375 hc08_freeReg (hc08_reg_a);
3376 add = "adc"; /* further adds must propagate carry */
3380 // adjustArithmeticResult (ic);
3383 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3384 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3385 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3388 /*-----------------------------------------------------------------*/
3389 /* genMinusDec :- does subtraction with deccrement if possible */
3390 /*-----------------------------------------------------------------*/
3392 genMinusDec (iCode * ic)
3394 unsigned int icount;
3399 unsigned int size = getDataSize (IC_RESULT (ic));
3403 left = IC_LEFT (ic);
3404 result = IC_RESULT (ic);
3406 /* will try to generate an increment */
3407 /* if the right side is not a literal
3409 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3412 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3414 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3415 && (icount>=-127) && (icount<=128) && (size==2))
3417 if (!IS_AOP_HX (AOP (left)))
3419 needpulx = pushRegIfUsed (hc08_reg_x);
3420 needpulh = pushRegIfUsed (hc08_reg_h);
3427 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3428 emitcode ("aix","#%d", -icount);
3429 hc08_dirtyReg (hc08_reg_hx, FALSE);
3430 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3431 pullOrFreeReg (hc08_reg_h, needpulh);
3432 pullOrFreeReg (hc08_reg_x, needpulx);
3436 if ((icount > 1) || (icount<0))
3439 if (!sameRegs (AOP (left), AOP (result)))
3445 D(emitcode ("; genMinusDec",""));
3447 rmwWithAop ("dec", AOP (result), 0);
3452 /*-----------------------------------------------------------------*/
3453 /* addSign - complete with sign */
3454 /*-----------------------------------------------------------------*/
3456 addSign (operand * result, int offset, int sign)
3458 int size = (getDataSize (result) - offset);
3463 emitcode ("rola", "");
3464 emitcode ("clra", "");
3465 emitcode ("sbc", zero);
3467 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3471 storeConstToAop (zero, AOP (result), offset++);
3476 /*-----------------------------------------------------------------*/
3477 /* genMinus - generates code for subtraction */
3478 /*-----------------------------------------------------------------*/
3480 genMinus (iCode * ic)
3483 int size, offset = 0;
3485 asmop *leftOp, *rightOp;
3487 D(emitcode ("; genMinus",""));
3489 aopOp (IC_LEFT (ic), ic, FALSE);
3490 aopOp (IC_RIGHT (ic), ic, FALSE);
3491 aopOp (IC_RESULT (ic), ic, TRUE);
3493 /* special cases :- */
3494 /* if I can do an decrement instead
3495 of subtract then GOOD for ME */
3496 if (genMinusDec (ic) == TRUE)
3499 size = getDataSize (IC_RESULT (ic));
3502 leftOp = AOP(IC_LEFT(ic));
3503 rightOp = AOP(IC_RIGHT(ic));
3509 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3510 accopWithAop(sub, rightOp, offset);
3511 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3516 // adjustArithmeticResult (ic);
3519 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3520 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3521 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3526 /*-----------------------------------------------------------------*/
3527 /* genMultOneByte : 8*8=8/16 bit multiplication */
3528 /*-----------------------------------------------------------------*/
3530 genMultOneByte (operand * left,
3534 /* sym_link *opetype = operandType (result); */
3535 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3536 int size=AOP_SIZE(result);
3537 bool negLiteral = FALSE;
3538 bool lUnsigned, rUnsigned;
3540 D(emitcode ("; genMultOneByte",""));
3542 if (size<1 || size>2) {
3543 // this should never happen
3544 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3545 AOP_SIZE(result), __FILE__, lineno);
3549 /* (if two literals: the value is computed before) */
3550 /* if one literal, literal on the right */
3551 if (AOP_TYPE (left) == AOP_LIT)
3557 /* if an operand is in A, make sure it is on the left */
3558 if (IS_AOP_A (AOP (right)))
3565 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3566 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3568 /* lUnsigned rUnsigned negLiteral negate case */
3569 /* false false false odd 3 */
3570 /* false false true even 3 */
3571 /* false true false odd 3 */
3572 /* false true true impossible */
3573 /* true false false odd 3 */
3574 /* true false true always 2 */
3575 /* true true false never 1 */
3576 /* true true true impossible */
3580 || (lUnsigned && rUnsigned))
3582 // just an unsigned 8*8=8/16 multiply
3583 //D(emitcode (";","unsigned"));
3585 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3586 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3587 emitcode ("mul", "");
3588 hc08_dirtyReg (hc08_reg_xa, FALSE);
3589 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3590 hc08_freeReg (hc08_reg_xa);
3595 // we have to do a signed multiply
3598 /* left unsigned, right signed literal -- literal determines sign handling */
3599 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3601 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3603 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3605 emitcode ("ldx", "#0x%02x", -val);
3607 emitcode ("ldx", "#0x%02x", val);
3609 emitcode ("mul", "");
3613 rmwWithReg ("neg", hc08_reg_a);
3614 tlbl4 = newiTempLabel (NULL);
3615 emitBranch ("bcc", tlbl4);
3616 rmwWithReg ("inc", hc08_reg_x);
3618 rmwWithReg ("neg", hc08_reg_x);
3621 hc08_dirtyReg (hc08_reg_xa, FALSE);
3622 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3623 hc08_freeReg (hc08_reg_xa);
3630 emitcode ("clr", "1,s");
3632 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3635 tlbl1 = newiTempLabel (NULL);
3636 emitcode ("tsta","");
3637 emitBranch ("bpl", tlbl1);
3638 emitcode ("inc", "1,s");
3639 rmwWithReg ("neg", hc08_reg_a);
3643 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3645 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3646 /* AND literal negative */
3648 emitcode ("ldx", "#0x%02x", -val);
3651 emitcode ("ldx", "#0x%02x", val);
3653 hc08_useReg (hc08_reg_x);
3657 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3660 tlbl2 = newiTempLabel (NULL);
3661 emitcode ("tstx", "");
3662 emitBranch ("bpl", tlbl2);
3663 emitcode ("inc", "1,s");
3664 rmwWithReg ("neg", hc08_reg_x);
3669 emitcode ("mul", "");
3670 hc08_dirtyReg (hc08_reg_xa, FALSE);
3672 tlbl3 = newiTempLabel (NULL);
3673 emitcode ("dec", "1,s");
3674 if (!lUnsigned && !rUnsigned && negLiteral)
3675 emitBranch ("beq", tlbl3);
3677 emitBranch ("bne", tlbl3);
3679 rmwWithReg ("neg", hc08_reg_a);
3680 tlbl4 = newiTempLabel (NULL);
3681 emitBranch ("bcc", tlbl4);
3682 rmwWithReg ("inc", hc08_reg_x);
3684 rmwWithReg ("neg", hc08_reg_x);
3688 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3689 hc08_freeReg (hc08_reg_xa);
3693 /*-----------------------------------------------------------------*/
3694 /* genMult - generates code for multiplication */
3695 /*-----------------------------------------------------------------*/
3697 genMult (iCode * ic)
3699 operand *left = IC_LEFT (ic);
3700 operand *right = IC_RIGHT (ic);
3701 operand *result = IC_RESULT (ic);
3703 D(emitcode ("; genMult",""));
3705 /* assign the amsops */
3706 aopOp (left, ic, FALSE);
3707 aopOp (right, ic, FALSE);
3708 aopOp (result, ic, TRUE);
3710 /* special cases first */
3711 /* if both are of size == 1 */
3712 // if (getSize(operandType(left)) == 1 &&
3713 // getSize(operandType(right)) == 1)
3714 if (AOP_SIZE (left) == 1 &&
3715 AOP_SIZE (right) == 1)
3717 genMultOneByte (left, right, result);
3721 /* should have been converted to function call */
3722 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3723 getSize(OP_SYMBOL(right)->type));
3724 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3729 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3730 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3731 freeAsmop (result, NULL, ic, TRUE);
3734 /*-----------------------------------------------------------------*/
3735 /* genDivOneByte : 8 bit division */
3736 /*-----------------------------------------------------------------*/
3738 genDivOneByte (operand * left,
3742 symbol *tlbl1, *tlbl2, *tlbl3;
3745 bool lUnsigned, rUnsigned;
3746 bool runtimeSign, compiletimeSign;
3748 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3749 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3751 D(emitcode ("; genDivOneByte",""));
3753 size = AOP_SIZE (result);
3754 /* signed or unsigned */
3755 if (lUnsigned && rUnsigned)
3757 /* unsigned is easy */
3758 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3759 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3760 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3761 emitcode ("div", "");
3762 hc08_dirtyReg (hc08_reg_a, FALSE);
3763 hc08_dirtyReg (hc08_reg_h, FALSE);
3764 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3765 hc08_freeReg (hc08_reg_a);
3766 hc08_freeReg (hc08_reg_x);
3767 hc08_freeReg (hc08_reg_h);
3771 /* signed is a little bit more difficult */
3773 /* now sign adjust for both left & right */
3775 /* let's see what's needed: */
3776 /* apply negative sign during runtime */
3777 runtimeSign = FALSE;
3778 /* negative sign from literals */
3779 compiletimeSign = FALSE;
3783 if (AOP_TYPE(left) == AOP_LIT)
3785 /* signed literal */
3786 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3788 compiletimeSign = TRUE;
3791 /* signed but not literal */
3797 if (AOP_TYPE(right) == AOP_LIT)
3799 /* signed literal */
3800 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3802 compiletimeSign ^= TRUE;
3805 /* signed but not literal */
3809 /* initialize the runtime sign */
3812 if (compiletimeSign)
3813 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3815 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3816 pushReg (hc08_reg_x, TRUE);
3819 /* save the signs of the operands */
3820 if (AOP_TYPE(right) == AOP_LIT)
3822 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3824 if (!rUnsigned && val < 0)
3825 emitcode ("ldx", "#0x%02x", -val);
3827 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3829 else /* ! literal */
3831 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3834 tlbl1 = newiTempLabel (NULL);
3835 emitcode ("tstx", "");
3836 emitBranch ("bpl", tlbl1);
3837 emitcode ("inc", "1,s");
3838 rmwWithReg ("neg", hc08_reg_x);
3843 if (AOP_TYPE(left) == AOP_LIT)
3845 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3847 if (!lUnsigned && val < 0)
3848 emitcode ("lda", "#0x%02x", -val);
3850 emitcode ("lda", "#0x%02x", (unsigned char) val);
3852 else /* ! literal */
3854 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3857 tlbl2 = newiTempLabel (NULL);
3858 emitcode ("tsta", "");
3859 emitBranch ("bpl", tlbl2);
3860 emitcode ("inc", "1,s");
3861 rmwWithReg ("neg", hc08_reg_a);
3866 loadRegFromConst (hc08_reg_h, zero);
3867 emitcode ("div", "");
3868 hc08_dirtyReg (hc08_reg_x, FALSE);
3869 hc08_dirtyReg (hc08_reg_a, FALSE);
3870 hc08_dirtyReg (hc08_reg_h, FALSE);
3872 if (runtimeSign || compiletimeSign)
3874 tlbl3 = newiTempLabel (NULL);
3877 pullReg (hc08_reg_x);
3878 rmwWithReg ("lsr", hc08_reg_x);
3879 rmwWithReg ("ror", hc08_reg_x);
3880 emitBranch ("bpl", tlbl3);
3883 rmwWithReg ("neg", hc08_reg_a);
3887 storeRegToAop (hc08_reg_a, AOP (result), 0);
3891 /* msb is 0x00 or 0xff depending on the sign */
3894 rmwWithReg ("lsl", hc08_reg_x);
3895 emitcode ("clra", "");
3896 emitcode ("sbc", "#0");
3898 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3900 else /* compiletimeSign */
3902 storeConstToAop ("#0xff", AOP (result), ++offset);
3907 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3910 hc08_freeReg (hc08_reg_a);
3911 hc08_freeReg (hc08_reg_x);
3912 hc08_freeReg (hc08_reg_h);
3915 /*-----------------------------------------------------------------*/
3916 /* genDiv - generates code for division */
3917 /*-----------------------------------------------------------------*/
3921 operand *left = IC_LEFT (ic);
3922 operand *right = IC_RIGHT (ic);
3923 operand *result = IC_RESULT (ic);
3925 D(emitcode ("; genDiv",""));
3927 /* assign the amsops */
3928 aopOp (left, ic, FALSE);
3929 aopOp (right, ic, FALSE);
3930 aopOp (result, ic, TRUE);
3932 /* special cases first */
3933 /* if both are of size == 1 */
3934 if (AOP_SIZE (left) <= 2 &&
3935 AOP_SIZE (right) == 1)
3937 genDivOneByte (left, right, result);
3941 /* should have been converted to function call */
3944 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3945 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3946 freeAsmop (result, NULL, ic, TRUE);
3949 /*-----------------------------------------------------------------*/
3950 /* genModOneByte : 8 bit modulus */
3951 /*-----------------------------------------------------------------*/
3953 genModOneByte (operand * left,
3957 symbol *tlbl1, *tlbl2, *tlbl3;
3960 bool lUnsigned, rUnsigned;
3961 bool runtimeSign, compiletimeSign;
3963 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3964 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3966 D(emitcode ("; genModOneByte",""));
3968 size = AOP_SIZE (result);
3970 if (lUnsigned && rUnsigned)
3972 /* unsigned is easy */
3973 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3974 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3975 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3976 emitcode ("div", "");
3977 hc08_dirtyReg (hc08_reg_a, FALSE);
3978 hc08_dirtyReg (hc08_reg_h, FALSE);
3979 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3980 hc08_freeReg (hc08_reg_a);
3981 hc08_freeReg (hc08_reg_x);
3982 hc08_freeReg (hc08_reg_h);
3986 /* signed is a little bit more difficult */
3988 if (AOP_TYPE(right) == AOP_LIT)
3990 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3992 if (!rUnsigned && val < 0)
3993 emitcode ("ldx", "#0x%02x", -val);
3995 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3997 else /* ! literal */
3999 loadRegFromAop (hc08_reg_x, AOP (right), 0);
4002 tlbl1 = newiTempLabel (NULL);
4003 emitcode ("tstx", "");
4004 emitBranch ("bpl", tlbl1);
4005 rmwWithReg ("neg", hc08_reg_x);
4010 /* let's see what's needed: */
4011 /* apply negative sign during runtime */
4012 runtimeSign = FALSE;
4013 /* negative sign from literals */
4014 compiletimeSign = FALSE;
4016 /* sign adjust left side */
4017 if (AOP_TYPE(left) == AOP_LIT)
4019 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4021 if (!lUnsigned && val < 0)
4023 compiletimeSign = TRUE; /* set sign flag */
4024 emitcode ("lda", "#0x%02x", -val);
4027 emitcode ("lda", "#0x%02x", (unsigned char) val);
4029 else /* ! literal */
4032 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4037 emitcode ("clr", "1,s");
4039 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4040 tlbl2 = newiTempLabel (NULL);
4041 emitcode ("tsta", "");
4042 emitBranch ("bpl", tlbl2);
4043 emitcode ("inc", "1,s");
4044 rmwWithReg ("neg", hc08_reg_a);
4049 loadRegFromConst (hc08_reg_h, zero);
4050 emitcode ("div", "");
4051 hc08_dirtyReg (hc08_reg_x, FALSE);
4052 hc08_dirtyReg (hc08_reg_a, FALSE);
4053 hc08_dirtyReg (hc08_reg_h, FALSE);
4055 if (runtimeSign || compiletimeSign)
4057 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4058 tlbl3 = newiTempLabel (NULL);
4061 pullReg (hc08_reg_x);
4062 rmwWithReg ("lsr", hc08_reg_x);
4063 rmwWithReg ("ror", hc08_reg_x);
4064 emitBranch ("bpl", tlbl3);
4067 rmwWithReg ("neg", hc08_reg_a);
4071 storeRegToAop (hc08_reg_a, AOP (result), 0);
4075 /* msb is 0x00 or 0xff depending on the sign */
4078 rmwWithReg ("lsl", hc08_reg_x);
4079 emitcode ("clra", "");
4080 emitcode ("sbc", "#0");
4082 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4084 else /* compiletimeSign */
4086 storeConstToAop ("#0xff", AOP (result), ++offset);
4091 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4094 hc08_freeReg (hc08_reg_a);
4095 hc08_freeReg (hc08_reg_x);
4096 hc08_freeReg (hc08_reg_h);
4099 /*-----------------------------------------------------------------*/
4100 /* genMod - generates code for division */
4101 /*-----------------------------------------------------------------*/
4105 operand *left = IC_LEFT (ic);
4106 operand *right = IC_RIGHT (ic);
4107 operand *result = IC_RESULT (ic);
4109 D(emitcode ("; genMod",""));
4111 /* assign the amsops */
4112 aopOp (left, ic, FALSE);
4113 aopOp (right, ic, FALSE);
4114 aopOp (result, ic, TRUE);
4116 /* special cases first */
4117 /* if both are of size == 1 */
4118 if (AOP_SIZE (left) <= 2 &&
4119 AOP_SIZE (right) == 1)
4121 genModOneByte (left, right, result);
4125 /* should have been converted to function call */
4129 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4130 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4131 freeAsmop (result, NULL, ic, TRUE);
4134 /*-----------------------------------------------------------------*/
4135 /* genIfxJump :- will create a jump depending on the ifx */
4136 /*-----------------------------------------------------------------*/
4138 genIfxJump (iCode * ic, char *jval)
4141 symbol *tlbl = newiTempLabel (NULL);
4144 D(emitcode ("; genIfxJump",""));
4146 /* if true label then we jump if condition
4150 jlbl = IC_TRUE (ic);
4151 if (!strcmp (jval, "a"))
4153 else if (!strcmp (jval, "c"))
4160 /* false label is present */
4161 jlbl = IC_FALSE (ic);
4162 if (!strcmp (jval, "a"))
4164 else if (!strcmp (jval, "c"))
4169 emitBranch (inst, tlbl);
4170 emitBranch ("jmp", jlbl);
4173 /* mark the icode as generated */
4177 /*-----------------------------------------------------------------*/
4178 /* genCmp :- greater or less than comparison */
4179 /*-----------------------------------------------------------------*/
4181 genCmp (operand * left, operand * right,
4182 operand * result, iCode * ifx, int sign, iCode *ic)
4184 int size, offset = 0;
4185 unsigned long lit = 0L;
4187 bool needpula = FALSE;
4189 D(emitcode ("; genCmp",""));
4191 /* subtract right from left if at the
4192 end the carry flag is set then we know that
4193 left is greater than right */
4194 size = max (AOP_SIZE (left), AOP_SIZE (right));
4196 if (AOP_TYPE (right) == AOP_LIT)
4198 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4199 /* optimize if(x < 0) or if(x >= 0) */
4208 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
4209 emitcode ("rola", "");
4210 hc08_useReg (hc08_reg_a);
4218 && ((AOP_TYPE (right) == AOP_LIT) ||
4219 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4220 && hc08_reg_hx->isFree)
4222 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4223 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4224 hc08_freeReg (hc08_reg_hx);
4235 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4236 accopWithAop (sub, AOP (right), offset);
4237 hc08_freeReg (hc08_reg_a);
4243 freeAsmop (right, NULL, ic, TRUE);
4244 freeAsmop (left, NULL, ic, TRUE);
4245 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4251 /* if the result is used in the next
4252 ifx conditional branch then generate
4253 code a little differently */
4256 pullOrFreeReg(hc08_reg_a,needpula);
4257 genIfxJump (ifx, sign ? "s" : "c");
4264 pullOrFreeReg(hc08_reg_a,needpula);
4268 /*-----------------------------------------------------------------*/
4269 /* genCmpGt :- greater than comparison */
4270 /*-----------------------------------------------------------------*/
4272 genCmpGt (iCode * ic, iCode * ifx)
4274 operand *left, *right, *result;
4275 sym_link *letype, *retype;
4278 D(emitcode ("; genCmpGt",""));
4280 result = IC_RESULT (ic);
4281 left = IC_LEFT (ic);
4282 right = IC_RIGHT (ic);
4284 letype = getSpec (operandType (left));
4285 retype = getSpec (operandType (right));
4286 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4287 /* assign the amsops */
4288 aopOp (left, ic, FALSE);
4289 aopOp (right, ic, FALSE);
4290 aopOp (result, ic, TRUE);
4292 genCmp (right, left, result, ifx, sign,ic);
4294 freeAsmop (result, NULL, ic, TRUE);
4297 /*-----------------------------------------------------------------*/
4298 /* genCmpLt - less than comparisons */
4299 /*-----------------------------------------------------------------*/
4301 genCmpLt (iCode * ic, iCode * ifx)
4303 operand *left, *right, *result;
4304 sym_link *letype, *retype;
4307 D(emitcode ("; genCmpLt",""));
4309 result = IC_RESULT (ic);
4310 left = IC_LEFT (ic);
4311 right = IC_RIGHT (ic);
4313 letype = getSpec (operandType (left));
4314 retype = getSpec (operandType (right));
4315 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4317 /* assign the amsops */
4318 aopOp (left, ic, FALSE);
4319 aopOp (right, ic, FALSE);
4320 aopOp (result, ic, TRUE);
4322 genCmp (left, right, result, ifx, sign,ic);
4324 freeAsmop (result, NULL, ic, TRUE);
4327 /*-----------------------------------------------------------------*/
4328 /* - compare and branch if not equal */
4329 /*-----------------------------------------------------------------*/
4331 gencbneshort (operand * left, operand * right, symbol * lbl)
4333 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4335 unsigned long lit = 0L;
4337 /* if the left side is a literal or
4338 if the right is in a pointer register and left
4340 if (AOP_TYPE (left) == AOP_LIT)
4346 if (AOP_TYPE (right) == AOP_LIT)
4347 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4351 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4352 accopWithAop ("cmp", AOP (right), offset);
4353 hc08_useReg (hc08_reg_a);
4354 hc08_freeReg (hc08_reg_a);
4355 emitBranch ("bne", lbl);
4361 /*-----------------------------------------------------------------*/
4362 /* gencjne - compare and jump if not equal */
4363 /*-----------------------------------------------------------------*/
4365 gencjne (operand * left, operand * right, symbol * lbl)
4367 symbol *tlbl = newiTempLabel (NULL);
4369 gencbneshort (left, right, lbl);
4371 loadRegFromConst (hc08_reg_a, one);
4372 emitBranch ("bra", tlbl);
4374 loadRegFromConst (hc08_reg_a, zero);
4377 hc08_useReg(hc08_reg_a);
4378 hc08_freeReg(hc08_reg_a);
4381 /*-----------------------------------------------------------------*/
4382 /* genCmpEq - generates code for equal to */
4383 /*-----------------------------------------------------------------*/
4385 genCmpEq (iCode * ic, iCode * ifx)
4387 operand *left, *right, *result;
4389 D(emitcode ("; genCmpEq",""));
4391 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4392 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4393 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4395 /* if literal, literal on the right or
4396 if the right is in a pointer register and left
4398 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4400 operand *t = IC_RIGHT (ic);
4401 IC_RIGHT (ic) = IC_LEFT (ic);
4405 if (ifx && !AOP_SIZE (result))
4408 tlbl = newiTempLabel (NULL);
4409 gencbneshort (left, right, tlbl);
4412 emitBranch ("jmp", IC_TRUE (ifx));
4417 symbol *lbl = newiTempLabel (NULL);
4418 emitBranch ("bra", lbl);
4420 emitBranch ("jmp", IC_FALSE (ifx));
4424 /* mark the icode as generated */
4429 gencjne (left, right, newiTempLabel (NULL));
4430 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4432 storeRegToAop (hc08_reg_a, AOP (result), 0);
4437 genIfxJump (ifx, "a");
4440 /* if the result is used in an arithmetic operation
4441 then put the result in place */
4442 if (AOP_TYPE (result) != AOP_CRY)
4446 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4447 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4448 freeAsmop (result, NULL, ic, TRUE);
4451 /*-----------------------------------------------------------------*/
4452 /* ifxForOp - returns the icode containing the ifx for operand */
4453 /*-----------------------------------------------------------------*/
4455 ifxForOp (operand * op, iCode * ic)
4457 /* if true symbol then needs to be assigned */
4458 if (IS_TRUE_SYMOP (op))
4461 /* if this has register type condition and
4462 the next instruction is ifx with the same operand
4463 and live to of the operand is upto the ifx only then */
4465 ic->next->op == IFX &&
4466 IC_COND (ic->next)->key == op->key &&
4467 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4474 genPointerGetSetOfs (iCode *ic)
4476 iCode *lic = ic->next;
4482 /* Make sure we have a next iCode */
4483 D(emitcode("","; checking lic"));
4487 /* Make sure the result of the addition is an iCode */
4488 D(emitcode("","; checking IS_ITEMP"));
4489 if (!IS_ITEMP (IC_RESULT (ic)))
4492 /* Make sure the next iCode is a pointer set or get */
4493 pset = POINTER_SET(lic);
4494 pget = POINTER_GET(lic);
4495 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4499 /* Make sure this is the only use of the pointer */
4500 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4503 D(emitcode("", "; checking pset operandsEqu"));
4504 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4507 D(emitcode("", "; checking pget operandsEqu"));
4508 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4511 D(emitcode("", "; checking IS_SYMOP"));
4512 if (!IS_SYMOP (IC_LEFT (ic)))
4515 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4516 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4519 sym = OP_SYMBOL (IC_LEFT (ic));
4521 D(emitcode("", "; checking remat"));
4528 D(emitcode ("; genPointerGetOfs",""));
4529 aopOp (IC_LEFT(ic), ic, FALSE);
4530 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4531 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4533 aopOp (IC_RIGHT(ic), ic, FALSE);
4534 aopOp (IC_RESULT(lic), lic, FALSE);
4536 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4538 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4540 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4541 loadRegFromConst (hc08_reg_h, zero);
4545 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4546 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4547 emitcode ("rola","");
4548 emitcode ("clra","");
4549 emitcode ("sbc", "#0");
4550 hc08_useReg (hc08_reg_a);
4551 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4555 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4556 size = AOP_SIZE (IC_RESULT(lic));
4557 derefaop->size = size;
4561 emitcode ("lda", "%s,x",
4562 aopAdrStr (derefaop, size, TRUE));
4563 hc08_useReg (hc08_reg_a);
4564 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4565 hc08_freeReg (hc08_reg_a);
4569 hc08_freeReg (hc08_reg_hx);
4571 freeAsmop (NULL, derefaop, ic, TRUE);
4572 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4573 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4580 D(emitcode ("; genPointerSetOfs",""));
4581 aopOp (IC_LEFT(ic), ic, FALSE);
4582 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4583 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4585 aopOp (IC_RIGHT(ic), ic, FALSE);
4586 aopOp (IC_RIGHT(lic), lic, FALSE);
4588 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4590 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4592 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4593 loadRegFromConst (hc08_reg_h, zero);
4597 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4598 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4599 emitcode ("rola","");
4600 emitcode ("clra","");
4601 emitcode ("sbc", "#0");
4602 hc08_useReg (hc08_reg_a);
4603 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4607 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4608 size = AOP_SIZE (IC_RIGHT(lic));
4609 derefaop->size = size;
4613 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4614 emitcode ("sta", "%s,x",
4615 aopAdrStr (derefaop, size, TRUE));
4616 hc08_freeReg (hc08_reg_a);
4620 hc08_freeReg (hc08_reg_hx);
4622 freeAsmop (NULL, derefaop, ic, TRUE);
4623 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4624 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4633 /*-----------------------------------------------------------------*/
4634 /* hasInc - operand is incremented before any other use */
4635 /*-----------------------------------------------------------------*/
4637 hasInc (operand *op, iCode *ic,int osize)
4639 sym_link *type = operandType(op);
4640 sym_link *retype = getSpec (type);
4641 iCode *lic = ic->next;
4644 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4645 if (!IS_SYMOP(op)) return NULL;
4647 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4648 if (IS_AGGREGATE(type->next)) return NULL;
4649 if (osize != (isize = getSize(type->next))) return NULL;
4652 /* if operand of the form op = op + <sizeof *op> */
4653 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4654 isOperandEqual(IC_RESULT(lic),op) &&
4655 isOperandLiteral(IC_RIGHT(lic)) &&
4656 operandLitValue(IC_RIGHT(lic)) == isize) {
4659 /* if the operand used or deffed */
4660 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4663 /* if GOTO or IFX */
4664 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4670 /*-----------------------------------------------------------------*/
4671 /* genAndOp - for && operation */
4672 /*-----------------------------------------------------------------*/
4674 genAndOp (iCode * ic)
4676 operand *left, *right, *result;
4677 symbol *tlbl, *tlbl0;
4679 D(emitcode ("; genAndOp",""));
4681 /* note here that && operations that are in an
4682 if statement are taken away by backPatchLabels
4683 only those used in arthmetic operations remain */
4684 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4685 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4686 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4688 tlbl = newiTempLabel (NULL);
4689 tlbl0 = newiTempLabel (NULL);
4691 asmopToBool (AOP (left), FALSE);
4692 emitBranch ("beq", tlbl0);
4693 asmopToBool (AOP (right), FALSE);
4694 emitBranch ("beq", tlbl0);
4695 loadRegFromConst (hc08_reg_a,one);
4696 emitBranch ("bra", tlbl);
4698 loadRegFromConst (hc08_reg_a,zero);
4701 hc08_useReg (hc08_reg_a);
4702 hc08_freeReg (hc08_reg_a);
4704 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4706 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4707 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4708 freeAsmop (result, NULL, ic, TRUE);
4712 /*-----------------------------------------------------------------*/
4713 /* genOrOp - for || operation */
4714 /*-----------------------------------------------------------------*/
4716 genOrOp (iCode * ic)
4718 operand *left, *right, *result;
4719 symbol *tlbl, *tlbl0;
4721 D(emitcode ("; genOrOp",""));
4723 /* note here that || operations that are in an
4724 if statement are taken away by backPatchLabels
4725 only those used in arthmetic operations remain */
4726 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4727 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4728 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4730 tlbl = newiTempLabel (NULL);
4731 tlbl0 = newiTempLabel (NULL);
4733 asmopToBool (AOP (left), FALSE);
4734 emitBranch ("bne", tlbl0);
4735 asmopToBool (AOP (right), FALSE);
4736 emitBranch ("bne", tlbl0);
4737 loadRegFromConst (hc08_reg_a,zero);
4738 emitBranch ("bra", tlbl);
4740 loadRegFromConst (hc08_reg_a,one);
4743 hc08_useReg (hc08_reg_a);
4744 hc08_freeReg (hc08_reg_a);
4746 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4749 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4750 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4751 freeAsmop (result, NULL, ic, TRUE);
4754 /*-----------------------------------------------------------------*/
4755 /* isLiteralBit - test if lit == 2^n */
4756 /*-----------------------------------------------------------------*/
4758 isLiteralBit (unsigned long lit)
4760 unsigned long pw[32] =
4761 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4762 0x100L, 0x200L, 0x400L, 0x800L,
4763 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4764 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4765 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4766 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4767 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4770 for (idx = 0; idx < 32; idx++)
4777 /*-----------------------------------------------------------------*/
4778 /* continueIfTrue - */
4779 /*-----------------------------------------------------------------*/
4781 continueIfTrue (iCode * ic)
4784 emitBranch ("jmp", IC_TRUE (ic));
4788 /*-----------------------------------------------------------------*/
4790 /*-----------------------------------------------------------------*/
4792 jumpIfTrue (iCode * ic)
4795 emitBranch ("jmp", IC_FALSE (ic));
4799 /*-----------------------------------------------------------------*/
4800 /* jmpTrueOrFalse - */
4801 /*-----------------------------------------------------------------*/
4803 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4805 // ugly but optimized by peephole
4808 symbol *nlbl = newiTempLabel (NULL);
4809 emitBranch ("bra", nlbl);
4811 emitBranch ("jmp", IC_TRUE (ic));
4816 emitBranch ("jmp", IC_FALSE (ic));
4823 /*-----------------------------------------------------------------*/
4824 /* genAnd - code for and */
4825 /*-----------------------------------------------------------------*/
4827 genAnd (iCode * ic, iCode * ifx)
4829 operand *left, *right, *result;
4830 int size, offset = 0;
4831 unsigned long lit = 0L;
4832 unsigned long litinv;
4833 unsigned char bytemask;
4839 D(emitcode ("; genAnd",""));
4841 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4842 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4843 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4846 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4848 AOP_TYPE (left), AOP_TYPE (right)));
4849 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4851 AOP_SIZE (left), AOP_SIZE (right)));
4854 /* if left is a literal & right is not then exchange them */
4855 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4857 operand *tmp = right;
4862 /* if right is accumulator & left is not then exchange them */
4863 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4865 operand *tmp = right;
4870 if (AOP_TYPE (right) == AOP_LIT)
4871 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4873 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4875 if (AOP_TYPE (result) == AOP_CRY
4877 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
4879 /* this generates ugly code, but meets volatility requirements */
4880 loadRegFromConst (hc08_reg_a, zero);
4881 pushReg (hc08_reg_a, TRUE);
4886 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4887 accopWithAop ("and", AOP (right), offset);
4888 emitcode ("ora", "1,s");
4889 emitcode ("sta", "1,s");
4893 pullReg (hc08_reg_a);
4894 emitcode ("tsta", "");
4895 genIfxJump (ifx, "a");
4899 if (AOP_TYPE (result) == AOP_CRY)
4901 symbol *tlbl = NULL;
4902 wassertl (ifx, "AOP_CRY result without ifx");
4907 bytemask = (lit >> (offset*8)) & 0xff;
4909 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
4913 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
4915 rmwWithAop ("tst", AOP (left), offset);
4919 tlbl = newiTempLabel (NULL);
4920 emitBranch ("bne", tlbl);
4925 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4926 accopWithAop ("and", AOP (right), offset);
4927 hc08_freeReg( hc08_reg_a);
4931 tlbl = newiTempLabel (NULL);
4932 emitBranch ("bne", tlbl);
4939 genIfxJump (ifx, "a");
4943 size = AOP_SIZE (result);
4945 if (AOP_TYPE (right) == AOP_LIT)
4947 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4948 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4949 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4951 int bitpos = isLiteralBit(litinv)-1;
4952 emitcode ("bclr","#%d,%s",bitpos & 7,
4953 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4961 bytemask = (lit >> (offset*8)) & 0xff;
4963 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
4965 if (isOperandVolatile (left, FALSE))
4967 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4968 hc08_freeReg( hc08_reg_a);
4970 storeConstToAop (zero, AOP (result), offset);
4972 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
4974 transferAopAop (AOP (left), offset, AOP (result), offset);
4978 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4979 accopWithAop ("and", AOP (right), offset);
4980 storeRegToAop (hc08_reg_a, AOP (result), offset);
4981 hc08_freeReg (hc08_reg_a);
4987 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4988 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4989 freeAsmop (result, NULL, ic, TRUE);
4992 /*-----------------------------------------------------------------*/
4993 /* genOr - code for or */
4994 /*-----------------------------------------------------------------*/
4996 genOr (iCode * ic, iCode * ifx)
4998 operand *left, *right, *result;
4999 int size, offset = 0;
5000 unsigned long lit = 0L;
5001 unsigned char bytemask;
5003 D(emitcode ("; genOr",""));
5005 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5006 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5007 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5010 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5012 AOP_TYPE (left), AOP_TYPE (right)));
5013 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5015 AOP_SIZE (left), AOP_SIZE (right)));
5018 /* if left is a literal & right is not then exchange them */
5019 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5021 operand *tmp = right;
5026 /* if left is accumulator & right is not then exchange them */
5027 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5029 operand *tmp = right;
5034 if (AOP_TYPE (right) == AOP_LIT)
5035 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5037 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5039 if (AOP_TYPE (result) == AOP_CRY
5041 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5043 /* this generates ugly code, but meets volatility requirements */
5044 loadRegFromConst (hc08_reg_a, zero);
5045 pushReg (hc08_reg_a, TRUE);
5050 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5051 accopWithAop ("ora", AOP (right), offset);
5052 emitcode ("ora", "1,s");
5053 emitcode ("sta", "1,s");
5057 pullReg (hc08_reg_a);
5058 emitcode ("tsta", "");
5059 genIfxJump (ifx, "a");
5063 if (AOP_TYPE (result) == AOP_CRY)
5065 symbol *tlbl = NULL;
5066 wassertl (ifx, "AOP_CRY result without ifx");
5071 bytemask = (lit >> (offset*8)) & 0xff;
5073 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5075 rmwWithAop ("tst", AOP (left), offset);
5079 tlbl = newiTempLabel (NULL);
5080 emitBranch ("bne", tlbl);
5085 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5086 accopWithAop ("ora", AOP (right), offset);
5087 hc08_freeReg( hc08_reg_a);
5091 tlbl = newiTempLabel (NULL);
5092 emitBranch ("bne", tlbl);
5099 genIfxJump (ifx, "a");
5102 if (AOP_TYPE (right) == AOP_LIT)
5103 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5105 size = AOP_SIZE (result);
5107 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5108 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5109 (AOP_TYPE (left) == AOP_DIR))
5111 int bitpos = isLiteralBit(lit)-1;
5112 emitcode ("bset","#%d,%s",bitpos & 7,
5113 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5120 bytemask = (lit >> (offset*8)) & 0xff;
5122 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5124 if (isOperandVolatile (left, FALSE))
5126 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5127 hc08_freeReg( hc08_reg_a);
5129 transferAopAop (AOP (right), offset, AOP (result), offset);
5131 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5133 transferAopAop (AOP (left), offset, AOP (result), offset);
5137 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5138 accopWithAop ("ora", AOP (right), offset);
5139 storeRegToAop (hc08_reg_a, AOP (result), offset);
5140 hc08_freeReg (hc08_reg_a);
5147 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5148 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5149 freeAsmop (result, NULL, ic, TRUE);
5152 /*-----------------------------------------------------------------*/
5153 /* genXor - code for xclusive or */
5154 /*-----------------------------------------------------------------*/
5156 genXor (iCode * ic, iCode * ifx)
5158 operand *left, *right, *result;
5159 int size, offset = 0;
5160 unsigned long lit = 0L;
5162 D(emitcode ("; genXor",""));
5164 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5165 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5166 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5169 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5171 AOP_TYPE (left), AOP_TYPE (right)));
5172 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5174 AOP_SIZE (left), AOP_SIZE (right)));
5177 /* if left is a literal & right is not ||
5178 if left needs acc & right does not */
5179 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5181 operand *tmp = right;
5186 /* if left is accumulator & right is not then exchange them */
5187 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5189 operand *tmp = right;
5194 if (AOP_TYPE (result) == AOP_CRY)
5197 wassertl (ifx, "AOP_CPY result without ifx");
5199 tlbl = newiTempLabel (NULL);
5200 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5204 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5205 if ((AOP_TYPE (right) == AOP_LIT)
5206 && (((lit >> (offset*8)) & 0xff) == 0))
5207 emitcode ("tsta","");
5209 accopWithAop ("eor", AOP (right), offset);
5210 hc08_freeReg( hc08_reg_a);
5212 emitBranch ("bne", tlbl);
5216 genIfxJump (ifx, "a");
5222 if (AOP_TYPE (right) == AOP_LIT)
5223 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5225 size = AOP_SIZE (result);
5229 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5230 accopWithAop ("eor", AOP (right), offset);
5231 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5232 hc08_freeReg( hc08_reg_a);
5236 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5237 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5238 freeAsmop (result, NULL, ic, TRUE);
5242 emitinline (iCode * ic, char *inlin)
5248 symbol *sym, *tempsym;
5257 while (isalnum(*inlin) || (*inlin == '_'))
5261 //printf("Found possible symbol '%s'\n",symname);
5262 tempsym = newSymbol (symname, ic->level);
5263 tempsym->block = ic->block;
5264 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5273 aop = aopForSym (ic, sym, FALSE);
5274 l = aopAdrStr (aop, aop->size - 1, TRUE);
5278 if (sym->level && !sym->allocreq && !sym->ismyparm)
5280 werror (E_ID_UNDEF, sym->name);
5282 " Add 'volatile' to the variable declaration so that it\n"
5283 " can be referenced within inline assembly");
5285 //printf("Replacing with '%s'\n",l);
5289 if ((2+bp-buffer)>sizeof(buffer))
5298 if ((2+bp-buffer)>sizeof(buffer))
5305 if ((2+bp-buffer)>sizeof(buffer))
5306 fprintf(stderr, "Inline assembly buffer overflow\n");
5308 //printf("%s\n",buffer);
5309 emitcode (buffer,"");
5313 /*-----------------------------------------------------------------*/
5314 /* genInline - write the inline code out */
5315 /*-----------------------------------------------------------------*/
5317 genInline (iCode * ic)
5319 char *buffer, *bp, *bp1;
5321 D(emitcode ("; genInline",""));
5323 _G.inLine += (!options.asmpeep);
5325 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5326 strcpy (buffer, IC_INLINE (ic));
5328 /* emit each line as a code */
5334 /* emitcode (bp1, ""); */
5335 emitinline (ic, bp1);
5354 /* emitcode (bp1, ""); */
5355 emitinline (ic, bp1);
5357 /* emitcode("",buffer); */
5358 _G.inLine -= (!options.asmpeep);
5361 /*-----------------------------------------------------------------*/
5362 /* genRRC - rotate right with carry */
5363 /*-----------------------------------------------------------------*/
5367 operand *left, *result;
5368 int size, offset = 0;
5369 bool needpula = FALSE;
5370 bool resultInA = FALSE;
5373 D(emitcode ("; genRRC",""));
5375 /* rotate right with carry */
5376 left = IC_LEFT (ic);
5377 result = IC_RESULT (ic);
5378 aopOp (left, ic, FALSE);
5379 aopOp (result, ic, FALSE);
5381 if ((AOP_TYPE (result) == AOP_REG)
5382 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5385 size = AOP_SIZE (result);
5389 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5393 rmwWithAop (shift, AOP (result), offset--);
5401 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5402 rmwWithReg (shift, hc08_reg_a);
5403 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5404 hc08_freeReg (hc08_reg_a);
5409 if ((!hc08_reg_a->isFree) || resultInA)
5411 pushReg (hc08_reg_a, TRUE);
5415 /* now we need to put the carry into the
5416 highest order byte of the result */
5417 offset = AOP_SIZE (result) - 1;
5418 emitcode ("clra","");
5419 emitcode ("rora","");
5420 hc08_dirtyReg (hc08_reg_a, FALSE);
5423 emitcode ("ora", "1,s");
5424 emitcode ("ais", "#1");
5425 hc08_dirtyReg (hc08_reg_a, FALSE);
5429 accopWithAop ("ora", AOP (result), offset);
5430 storeRegToAop (hc08_reg_a, AOP (result), offset);
5432 pullOrFreeReg (hc08_reg_a, needpula);
5434 freeAsmop (left, NULL, ic, TRUE);
5435 freeAsmop (result, NULL, ic, TRUE);
5438 /*-----------------------------------------------------------------*/
5439 /* genRLC - generate code for rotate left with carry */
5440 /*-----------------------------------------------------------------*/
5444 operand *left, *result;
5445 int size, offset = 0;
5447 bool resultInA = FALSE;
5448 bool needpula = FALSE;
5450 D(emitcode ("; genRLC",""));
5452 /* rotate right with carry */
5453 left = IC_LEFT (ic);
5454 result = IC_RESULT (ic);
5455 aopOp (left, ic, FALSE);
5456 aopOp (result, ic, FALSE);
5458 if ((AOP_TYPE (result) == AOP_REG)
5459 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5462 size = AOP_SIZE (result);
5466 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5470 rmwWithAop (shift, AOP (result), offset--);
5478 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5479 rmwWithReg (shift, hc08_reg_a);
5480 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5481 hc08_freeReg (hc08_reg_a);
5486 if ((!hc08_reg_a->isFree) || resultInA)
5488 pushReg (hc08_reg_a, TRUE);
5492 /* now we need to put the carry into the
5493 lowest order byte of the result */
5495 emitcode ("clra","");
5496 emitcode ("rola","");
5497 hc08_dirtyReg (hc08_reg_a, FALSE);
5500 emitcode ("ora", "1,s");
5501 emitcode ("ais", "#1");
5502 hc08_dirtyReg (hc08_reg_a, FALSE);
5506 accopWithAop ("ora", AOP (result), offset);
5507 storeRegToAop (hc08_reg_a, AOP (result), offset);
5509 pullOrFreeReg (hc08_reg_a, needpula);
5511 freeAsmop (left, NULL, ic, TRUE);
5512 freeAsmop (result, NULL, ic, TRUE);
5515 /*-----------------------------------------------------------------*/
5516 /* genGetHbit - generates code get highest order bit */
5517 /*-----------------------------------------------------------------*/
5519 genGetHbit (iCode * ic)
5521 operand *left, *result;
5523 D(emitcode ("; genGetHbit",""));
5525 left = IC_LEFT (ic);
5526 result = IC_RESULT (ic);
5527 aopOp (left, ic, FALSE);
5528 aopOp (result, ic, FALSE);
5530 /* get the highest order byte into a */
5531 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5532 emitcode ("rola", "");
5533 emitcode ("clra", "");
5534 emitcode ("rola", "");
5535 hc08_dirtyReg (hc08_reg_a, FALSE);
5536 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5537 hc08_freeReg (hc08_reg_a);
5539 freeAsmop (left, NULL, ic, TRUE);
5540 freeAsmop (result, NULL, ic, TRUE);
5543 /*-----------------------------------------------------------------*/
5544 /* genSwap - generates code to swap nibbles or bytes */
5545 /*-----------------------------------------------------------------*/
5547 genSwap (iCode * ic)
5549 operand *left, *result;
5551 D(emitcode ("; genSwap",""));
5553 left = IC_LEFT (ic);
5554 result = IC_RESULT (ic);
5555 aopOp (left, ic, FALSE);
5556 aopOp (result, ic, FALSE);
5558 switch (AOP_SIZE (left))
5560 case 1: /* swap nibbles in byte */
5561 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5562 emitcode ("nsa", "");
5563 hc08_dirtyReg (hc08_reg_a, FALSE);
5564 storeRegToAop (hc08_reg_a, AOP (result), 0);
5565 hc08_freeReg (hc08_reg_a);
5567 case 2: /* swap bytes in a word */
5568 if (operandsEqu (left, result))
5570 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5571 hc08_useReg (hc08_reg_a);
5572 transferAopAop (AOP (left), 1, AOP (result), 0);
5573 storeRegToAop (hc08_reg_a, AOP (result), 1);
5574 hc08_freeReg (hc08_reg_a);
5578 transferAopAop (AOP (left), 0, AOP (result), 1);
5579 transferAopAop (AOP (left), 1, AOP (result), 0);
5583 wassertl(FALSE, "unsupported SWAP operand size");
5586 freeAsmop (left, NULL, ic, TRUE);
5587 freeAsmop (result, NULL, ic, TRUE);
5591 /*-----------------------------------------------------------------*/
5592 /* AccRol - rotate left accumulator by known count */
5593 /*-----------------------------------------------------------------*/
5595 AccRol (int shCount)
5597 shCount &= 0x0007; // shCount : 0..7
5604 emitcode ("rola", ""); /* 1 cycle */
5607 emitcode ("rola", ""); /* 1 cycle */
5608 emitcode ("rola", ""); /* 1 cycle */
5611 emitcode ("nsa", "");
5612 emitcode ("rora", "");
5615 emitcode ("nsa", ""); /* 3 cycles */
5618 emitcode ("nsa", ""); /* 3 cycles */
5619 emitcode ("rola", ""); /* 1 cycle */
5622 emitcode ("nsa", ""); /* 3 cycles */
5623 emitcode ("rola", ""); /* 1 cycle */
5624 emitcode ("rola", ""); /* 1 cycle */
5627 emitcode ("nsa", ""); /* 3 cycles */
5628 emitcode ("rola", ""); /* 1 cycle */
5629 emitcode ("rola", ""); /* 1 cycle */
5630 emitcode ("rola", ""); /* 1 cycle */
5637 /*-----------------------------------------------------------------*/
5638 /* AccLsh - left shift accumulator by known count */
5639 /*-----------------------------------------------------------------*/
5641 AccLsh (int shCount)
5645 shCount &= 0x0007; // shCount : 0..7
5647 /* Shift counts of 4 and 5 are currently optimized for code size. */
5648 /* Falling through to the unrolled loop would be optimal for code speed. */
5649 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5653 if (optimize.codeSpeed)
5655 accopWithMisc ("nsa", "");
5656 accopWithMisc ("and", "#0xf0");
5657 /* total: 5 cycles, 3 bytes */
5660 if (optimize.codeSpeed)
5662 accopWithMisc ("nsa", "");
5663 accopWithMisc ("and", "#0xf0");
5664 accopWithMisc ("lsla", "");
5665 /* total: 6 cycles, 4 bytes */
5668 accopWithMisc ("rora", "");
5669 accopWithMisc ("rora", "");
5670 accopWithMisc ("rora", "");
5671 accopWithMisc ("and", "#0xc0");
5672 /* total: 5 cycles, 5 bytes */
5675 accopWithMisc ("rora", "");
5676 accopWithMisc ("clra", "");
5677 accopWithMisc ("rora", "");
5678 /* total: 3 cycles, 3 bytes */
5682 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5683 /* the fastest (shCount<6) and shortest (shCount<4). */
5684 for (i=0;i<shCount;i++)
5685 accopWithMisc ("lsla", "");
5689 /*-----------------------------------------------------------------*/
5690 /* AccSRsh - signed right shift accumulator by known count */
5691 /*-----------------------------------------------------------------*/
5693 AccSRsh (int shCount)
5697 shCount &= 0x0007; // shCount : 0..7
5701 accopWithMisc ("rola", "");
5702 accopWithMisc ("clra", "");
5703 accopWithMisc ("sbc", zero);
5704 /* total: 4 cycles, 4 bytes */
5708 for (i=0;i<shCount;i++)
5709 accopWithMisc ("asra", "");
5712 /*-----------------------------------------------------------------*/
5713 /* AccRsh - right shift accumulator by known count */
5714 /*-----------------------------------------------------------------*/
5716 AccRsh (int shCount, bool sign)
5726 shCount &= 0x0007; // shCount : 0..7
5728 /* Shift counts of 4 and 5 are currently optimized for code size. */
5729 /* Falling through to the unrolled loop would be optimal for code speed. */
5730 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5734 if (optimize.codeSpeed)
5736 accopWithMisc ("nsa", "");
5737 accopWithMisc ("and", "#0x0f");
5738 /* total: 5 cycles, 3 bytes */
5741 if (optimize.codeSpeed)
5743 accopWithMisc ("nsa", "");
5744 accopWithMisc ("and", "#0x0f");
5745 accopWithMisc ("lsra", "");
5746 /* total: 6 cycles, 4 bytes */
5749 accopWithMisc ("rola", "");
5750 accopWithMisc ("rola", "");
5751 accopWithMisc ("rola", "");
5752 accopWithMisc ("and", "#0x03");
5753 /* total: 5 cycles, 5 bytes */
5756 accopWithMisc ("rola", "");
5757 accopWithMisc ("clra", "");
5758 accopWithMisc ("rola", "");
5759 /* total: 3 cycles, 3 bytes */
5763 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5764 /* the fastest (shCount<6) and shortest (shCount<4). */
5765 for (i=0;i<shCount;i++)
5766 accopWithMisc ("lsra", "");
5770 /*-----------------------------------------------------------------*/
5771 /* XAccLsh - left shift register pair XA by known count */
5772 /*-----------------------------------------------------------------*/
5774 XAccLsh (int shCount)
5778 shCount &= 0x000f; // shCount : 0..15
5783 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5784 loadRegFromConst (hc08_reg_a, zero);
5788 /* if we can beat 2n cycles or bytes for some special case, do it here */
5792 /* bytes cycles reg x reg a carry
5793 ** abcd efgh ijkl mnop ?
5794 ** lsrx 1 1 0abc defg ijkl mnop h
5795 ** rora 1 1 0abc defg hijk lmno p
5796 ** tax 1 1 hijk lmno hijk lmno p
5797 ** clra 1 1 hijk lmno 0000 0000 p
5798 ** rora 1 1 hijk lmno p000 0000 0
5799 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5801 rmwWithReg ("lsr", hc08_reg_x);
5802 rmwWithReg ("ror", hc08_reg_a);
5803 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5804 loadRegFromConst (hc08_reg_a, zero);
5805 rmwWithReg ("ror", hc08_reg_a);
5812 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5813 /* the fastest and shortest. */
5814 for (i=0;i<shCount;i++)
5816 rmwWithReg ("lsl", hc08_reg_a);
5817 rmwWithReg ("rol", hc08_reg_x);
5821 /*-----------------------------------------------------------------*/
5822 /* XAccSRsh - signed right shift register pair XA by known count */
5823 /*-----------------------------------------------------------------*/
5825 XAccSRsh (int shCount)
5829 shCount &= 0x000f; // shCount : 0..7
5831 /* if we can beat 2n cycles or bytes for some special case, do it here */
5835 /* bytes cycles reg x reg a carry
5836 ** abcd efgh ijkl mnop ?
5837 ** lslx 1 1 bcde fgh0 ijkl mnop a
5838 ** clra 1 1 bcde fgh0 0000 0000 a
5839 ** rola 1 1 bcde fgh0 0000 000a 0
5840 ** nega 1 1 bcde fgh0 aaaa aaaa a
5841 ** tax 1 1 aaaa aaaa aaaa aaaa a
5842 ** total: 5 cycles, 5 bytes
5844 rmwWithReg ("lsl", hc08_reg_x);
5845 loadRegFromConst (hc08_reg_a, zero);
5846 rmwWithReg ("rol", hc08_reg_a);
5847 rmwWithReg ("neg", hc08_reg_a);
5848 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5858 /* bytes cycles reg x reg a carry
5859 ** abcd efgh ijkl mnop ?
5860 ** txa 1 1 abcd efgh abcd efgh ?
5861 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5862 ** lsla 1 1 abcd efgh ???? ???? a
5863 ** clrx 1 1 0000 0000 ???? ???? a
5864 ** rolx 1 1 0000 000a ???? ???? 0
5865 ** negx 1 1 aaaa aaaa ???? ???? a
5866 ** rora 1 1 aaaa aaaa LSBresult 0
5867 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5869 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5870 AccSRsh (shCount-8);
5871 rmwWithReg ("lsl", hc08_reg_a);
5872 loadRegFromConst (hc08_reg_x, zero);
5873 rmwWithReg ("rol", hc08_reg_x);
5874 rmwWithReg ("neg", hc08_reg_x);
5875 rmwWithReg ("ror", hc08_reg_a);
5882 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5883 /* the fastest and shortest. */
5884 for (i=0;i<shCount;i++)
5886 rmwWithReg ("asr", hc08_reg_x);
5887 rmwWithReg ("ror", hc08_reg_a);
5891 /*-----------------------------------------------------------------*/
5892 /* XAccRsh - right shift register pair XA by known count */
5893 /*-----------------------------------------------------------------*/
5895 XAccRsh (int shCount, bool sign)
5905 shCount &= 0x000f; // shCount : 0..f
5907 /* if we can beat 2n cycles or bytes for some special case, do it here */
5911 /* bytes cycles reg x reg a carry
5912 ** abcd efgh ijkl mnop ?
5913 ** clra 1 1 abcd efgh 0000 0000 a
5914 ** lslx 1 1 bcde fgh0 0000 0000 a
5915 ** rola 1 1 bcde fgh0 0000 000a 0
5916 ** clrx 1 1 0000 0000 0000 000a 0
5917 ** total: 4 cycles, 4 bytes
5919 loadRegFromConst (hc08_reg_x, zero);
5920 rmwWithReg ("lsl", hc08_reg_x);
5921 rmwWithReg ("rol", hc08_reg_a);
5922 loadRegFromConst (hc08_reg_a, zero);
5926 /* bytes cycles reg x reg a carry
5927 ** abcd efgh ijkl mnop ?
5928 ** clra 1 1 abcd efgh 0000 0000 a
5929 ** lslx 1 1 bcde fgh0 0000 0000 a
5930 ** rola 1 1 bcde fgh0 0000 000a 0
5931 ** lslx 1 1 cdef gh00 0000 000a b
5932 ** rola 1 1 cdef gh00 0000 00ab 0
5933 ** clrx 1 1 0000 0000 0000 00ab 0
5934 ** total: 6 cycles, 6 bytes
5936 loadRegFromConst (hc08_reg_x, zero);
5937 rmwWithReg ("lsl", hc08_reg_x);
5938 rmwWithReg ("rol", hc08_reg_a);
5939 rmwWithReg ("lsl", hc08_reg_x);
5940 rmwWithReg ("rol", hc08_reg_a);
5941 loadRegFromConst (hc08_reg_a, zero);
5950 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5951 AccRsh (shCount-8, FALSE);
5952 loadRegFromConst (hc08_reg_x, zero);
5956 /* bytes cycles reg x reg a carry
5957 ** abcd efgh ijkl mnop ?
5958 ** lsla 1 1 abcd efgh jklm nop0 i
5959 ** txa 1 1 abcd efgh abcd efgh i
5960 ** rola 1 1 abcd efgh bcde fghi a
5961 ** clrx 1 1 0000 0000 bcde fghi a
5962 ** rolx 1 1 0000 000a bcde fghi 0
5963 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5965 rmwWithReg ("lsl", hc08_reg_a);
5966 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5967 rmwWithReg ("rol", hc08_reg_a);
5968 loadRegFromConst (hc08_reg_x, zero);
5969 rmwWithReg ("rol", hc08_reg_x);
5972 /* bytes cycles reg x reg a carry
5973 ** abcd efgh ijkl mnop ?
5974 ** lsla 1 1 abcd efgh jklm nop0 i
5975 ** rolx 1 1 bcde fghi jklm nop0 a
5976 ** rola 1 1 bcde fghi klmn op0a j
5977 ** rolx 1 1 cdef ghij klmn op0a b
5978 ** rola 1 1 cdef ghij lmno p0ab k
5979 ** and #3 2 2 cdef ghij 0000 00ab k
5980 ** psha 1 2 cdef ghij 0000 00ab k
5981 ** txa 1 1 cdef ghij cdef ghij k
5982 ** pula 1 2 0000 00ab cdef ghij k
5983 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5989 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5990 /* the fastest and shortest. */
5991 for (i=0;i<shCount;i++)
5993 rmwWithReg ("lsr", hc08_reg_x);
5994 rmwWithReg ("ror", hc08_reg_a);
6001 /*-----------------------------------------------------------------*/
6002 /* shiftR1Left2Result - shift right one byte from left to result */
6003 /*-----------------------------------------------------------------*/
6005 shiftR1Left2Result (operand * left, int offl,
6006 operand * result, int offr,
6007 int shCount, int sign)
6009 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6010 /* shift right accumulator */
6011 AccRsh (shCount, sign);
6012 storeRegToAop (hc08_reg_a, AOP (result), offr);
6016 /*-----------------------------------------------------------------*/
6017 /* shiftL1Left2Result - shift left one byte from left to result */
6018 /*-----------------------------------------------------------------*/
6020 shiftL1Left2Result (operand * left, int offl,
6021 operand * result, int offr, int shCount)
6023 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6024 /* shift left accumulator */
6026 storeRegToAop (hc08_reg_a, AOP (result), offr);
6029 /*-----------------------------------------------------------------*/
6030 /* movLeft2Result - move byte from left to result */
6031 /*-----------------------------------------------------------------*/
6033 movLeft2Result (operand * left, int offl,
6034 operand * result, int offr, int sign)
6036 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6038 transferAopAop (AOP (left), offl, AOP (result), offr);
6043 /*-----------------------------------------------------------------*/
6044 /* shiftL2Left2Result - shift left two bytes from left to result */
6045 /*-----------------------------------------------------------------*/
6047 shiftL2Left2Result (operand * left, int offl,
6048 operand * result, int offr, int shCount)
6051 bool needpula = FALSE;
6052 bool needpulx = FALSE;
6054 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6055 needpula = pushRegIfUsed (hc08_reg_a);
6058 if (!IS_AOP_XA (AOP (left)))
6059 needpulx = pushRegIfUsed (hc08_reg_x);
6063 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6068 rmwWithReg ("lsr", hc08_reg_x);
6069 rmwWithReg ("ror", hc08_reg_a);
6070 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6071 rmwWithReg ("clr", hc08_reg_a);
6072 rmwWithReg ("ror", hc08_reg_a);
6075 for (i=0; i<shCount; i++)
6077 rmwWithReg ("lsl", hc08_reg_a);
6078 rmwWithReg ("rol", hc08_reg_x);
6081 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6083 pullOrFreeReg (hc08_reg_x, needpulx);
6084 pullOrFreeReg (hc08_reg_a, needpula);
6090 /*-----------------------------------------------------------------*/
6091 /* shiftR2Left2Result - shift right two bytes from left to result */
6092 /*-----------------------------------------------------------------*/
6094 shiftR2Left2Result (operand * left, int offl,
6095 operand * result, int offr,
6096 int shCount, int sign)
6099 bool needpula = FALSE;
6100 bool needpulx = FALSE;
6102 needpula = pushRegIfUsed (hc08_reg_a);
6103 needpulx = pushRegIfUsed (hc08_reg_x);
6105 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6106 for (i=0; i<shCount; i++)
6109 rmwWithReg ("asr", hc08_reg_x);
6111 rmwWithReg ("lsr", hc08_reg_x);
6112 rmwWithReg ("ror", hc08_reg_a);
6114 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6116 pullOrFreeReg (hc08_reg_x, needpulx);
6117 pullOrFreeReg (hc08_reg_a, needpula);
6122 /*-----------------------------------------------------------------*/
6123 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6124 /*-----------------------------------------------------------------*/
6126 shiftLLeftOrResult (operand * left, int offl,
6127 operand * result, int offr, int shCount)
6129 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6130 /* shift left accumulator */
6132 /* or with result */
6133 accopWithAop ("ora", AOP (result), offr);
6134 /* back to result */
6135 storeRegToAop (hc08_reg_a, AOP (result), offr);
6136 hc08_freeReg (hc08_reg_a);
6140 /*-----------------------------------------------------------------*/
6141 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6142 /*-----------------------------------------------------------------*/
6144 shiftRLeftOrResult (operand * left, int offl,
6145 operand * result, int offr, int shCount)
6147 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6148 /* shift left accumulator */
6149 AccRsh (shCount, FALSE);
6150 /* or with result */
6151 accopWithAop ("ora", AOP (result), offr);
6152 /* back to result */
6153 storeRegToAop (hc08_reg_a, AOP (result), offr);
6154 hc08_freeReg (hc08_reg_a);
6157 /*-----------------------------------------------------------------*/
6158 /* genlshOne - left shift a one byte quantity by known count */
6159 /*-----------------------------------------------------------------*/
6161 genlshOne (operand * result, operand * left, int shCount)
6163 D(emitcode ("; genlshOne",""));
6165 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6168 /*-----------------------------------------------------------------*/
6169 /* genlshTwo - left shift two bytes by known amount != 0 */
6170 /*-----------------------------------------------------------------*/
6172 genlshTwo (operand * result, operand * left, int shCount)
6176 D(emitcode ("; genlshTwo",""));
6179 size = getDataSize (result);
6181 /* if shCount >= 8 */
6188 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6190 storeRegToAop (hc08_reg_a, AOP (result), 1);
6192 storeConstToAop(zero, AOP (result), LSB);
6195 /* 1 <= shCount <= 7 */
6198 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6200 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6204 /*-----------------------------------------------------------------*/
6205 /* shiftLLong - shift left one long from left to result */
6206 /* offl = LSB or MSB16 */
6207 /*-----------------------------------------------------------------*/
6209 shiftLLong (operand * left, operand * result, int offr)
6212 // int size = AOP_SIZE (result);
6214 bool needpula = FALSE;
6215 bool needpulx = FALSE;
6217 needpula = pushRegIfUsed (hc08_reg_a);
6218 needpulx = pushRegIfUsed (hc08_reg_x);
6220 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6221 rmwWithReg ("lsl", hc08_reg_a);
6222 rmwWithReg ("rol", hc08_reg_x);
6223 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6227 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6228 rmwWithReg ("rol", hc08_reg_a);
6229 rmwWithReg ("rol", hc08_reg_x);
6230 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6232 else if (offr==MSB16)
6234 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6235 rmwWithReg ("rol", hc08_reg_a);
6236 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6239 pullOrFreeReg (hc08_reg_x, needpulx);
6240 pullOrFreeReg (hc08_reg_a, needpula);
6243 /*-----------------------------------------------------------------*/
6244 /* genlshFour - shift four byte by a known amount != 0 */
6245 /*-----------------------------------------------------------------*/
6247 genlshFour (operand * result, operand * left, int shCount)
6251 D(emitcode ("; genlshFour",""));
6253 size = AOP_SIZE (result);
6255 /* TODO: deal with the &result == &left case */
6257 /* if shifting more that 3 bytes */
6262 /* lowest order of left goes to the highest
6263 order of the destination */
6264 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6266 movLeft2Result (left, LSB, result, MSB32, 0);
6267 storeConstToAop (zero, AOP (result), LSB);
6268 storeConstToAop (zero, AOP (result), MSB16);
6269 storeConstToAop (zero, AOP (result), MSB24);
6273 /* more than two bytes */
6274 else if (shCount >= 16)
6276 /* lower order two bytes goes to higher order two bytes */
6278 /* if some more remaining */
6280 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6283 movLeft2Result (left, MSB16, result, MSB32, 0);
6284 movLeft2Result (left, LSB, result, MSB24, 0);
6286 storeConstToAop (zero, AOP (result), LSB);
6287 storeConstToAop (zero, AOP (result), MSB16);
6291 /* if more than 1 byte */
6292 else if (shCount >= 8)
6294 /* lower order three bytes goes to higher order three bytes */
6299 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6301 movLeft2Result (left, LSB, result, MSB16, 0);
6307 movLeft2Result (left, MSB24, result, MSB32, 0);
6308 movLeft2Result (left, MSB16, result, MSB24, 0);
6309 movLeft2Result (left, LSB, result, MSB16, 0);
6310 storeConstToAop (zero, AOP (result), LSB);
6312 else if (shCount == 1)
6313 shiftLLong (left, result, MSB16);
6316 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6317 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6318 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6319 storeConstToAop (zero, AOP (result), LSB);
6324 /* 1 <= shCount <= 7 */
6325 else if (shCount <= 2)
6327 shiftLLong (left, result, LSB);
6329 shiftLLong (result, result, LSB);
6331 /* 3 <= shCount <= 7, optimize */
6334 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6335 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6336 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6340 /*-----------------------------------------------------------------*/
6341 /* genLeftShiftLiteral - left shifting by known count */
6342 /*-----------------------------------------------------------------*/
6344 genLeftShiftLiteral (operand * left,
6349 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6352 D(emitcode ("; genLeftShiftLiteral",""));
6354 freeAsmop (right, NULL, ic, TRUE);
6356 aopOp (left, ic, FALSE);
6357 aopOp (result, ic, FALSE);
6359 // size = getSize (operandType (result));
6360 size = AOP_SIZE (result);
6363 D(emitcode ("; shift left ", "result %d, left %d", size,
6370 transferAopAop( AOP(left), size, AOP(result), size);
6372 else if (shCount >= (size * 8))
6375 storeConstToAop (zero, AOP (result), size);
6382 genlshOne (result, left, shCount);
6386 genlshTwo (result, left, shCount);
6390 genlshFour (result, left, shCount);
6393 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6394 "*** ack! mystery literal shift!\n");
6398 freeAsmop (left, NULL, ic, TRUE);
6399 freeAsmop (result, NULL, ic, TRUE);
6402 /*-----------------------------------------------------------------*/
6403 /* genLeftShift - generates code for left shifting */
6404 /*-----------------------------------------------------------------*/
6406 genLeftShift (iCode * ic)
6408 operand *left, *right, *result;
6410 symbol *tlbl, *tlbl1;
6415 D(emitcode ("; genLeftShift",""));
6417 right = IC_RIGHT (ic);
6418 left = IC_LEFT (ic);
6419 result = IC_RESULT (ic);
6421 aopOp (right, ic, FALSE);
6423 /* if the shift count is known then do it
6424 as efficiently as possible */
6425 if (AOP_TYPE (right) == AOP_LIT)
6427 genLeftShiftLiteral (left, right, result, ic);
6431 /* shift count is unknown then we have to form
6432 a loop get the loop count in A : Note: we take
6433 only the lower order byte since shifting
6434 more that 32 bits make no sense anyway, ( the
6435 largest size of an object can be only 32 bits ) */
6437 aopOp (left, ic, FALSE);
6438 aopOp (result, ic, FALSE);
6440 /* now move the left to the result if they are not the
6442 if (!sameRegs (AOP (left), AOP (result)))
6445 size = AOP_SIZE (result);
6449 transferAopAop (AOP (left), offset, AOP (result), offset);
6453 freeAsmop (left, NULL, ic, TRUE);
6455 tlbl = newiTempLabel (NULL);
6456 size = AOP_SIZE (result);
6458 tlbl1 = newiTempLabel (NULL);
6462 loadRegFromAop (reg, AOP (right), 0);
6463 freeAsmop (right, NULL, ic, TRUE);
6464 emitBranch ("beq", tlbl1);
6468 for (offset=0;offset<size;offset++)
6470 rmwWithAop (shift, AOP (result), offset);
6473 rmwWithReg ("dec", reg);
6474 emitBranch ("bne", tlbl);
6478 freeAsmop (result, NULL, ic, TRUE);
6481 /*-----------------------------------------------------------------*/
6482 /* genrshOne - right shift a one byte quantity by known count */
6483 /*-----------------------------------------------------------------*/
6485 genrshOne (operand * result, operand * left,
6486 int shCount, int sign)
6488 D(emitcode ("; genrshOne",""));
6490 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6491 AccRsh (shCount, sign);
6492 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6495 /*-----------------------------------------------------------------*/
6496 /* genrshTwo - right shift two bytes by known amount != 0 */
6497 /*-----------------------------------------------------------------*/
6499 genrshTwo (operand * result, operand * left,
6500 int shCount, int sign)
6502 D(emitcode ("; genrshTwo",""));
6504 /* if shCount >= 8 */
6507 if (shCount || sign)
6509 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6510 AccRsh (shCount-8, sign);
6511 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6515 transferAopAop (AOP (left), 1, AOP (result), 0);
6516 storeConstToAop (zero, AOP (result), 1);
6520 /* 1 <= shCount <= 7 */
6523 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6524 XAccRsh (shCount, sign);
6525 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6529 /*-----------------------------------------------------------------*/
6530 /* shiftRLong - shift right one long from left to result */
6531 /* offl = LSB or MSB16 */
6532 /*-----------------------------------------------------------------*/
6534 shiftRLong (operand * left, int offl,
6535 operand * result, int sign)
6538 // int size = AOP_SIZE (result);
6540 bool needpula = FALSE;
6541 bool needpulx = FALSE;
6543 needpula = pushRegIfUsed (hc08_reg_a);
6544 needpulx = pushRegIfUsed (hc08_reg_x);
6548 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6550 rmwWithReg ("asr", hc08_reg_x);
6552 rmwWithReg ("lsr", hc08_reg_x);
6553 rmwWithReg ("ror", hc08_reg_a);
6554 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6556 else if (offl==MSB16)
6558 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6560 rmwWithReg ("asr", hc08_reg_a);
6562 rmwWithReg ("lsr", hc08_reg_a);
6563 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6566 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6567 rmwWithReg ("ror", hc08_reg_x);
6568 rmwWithReg ("ror", hc08_reg_a);
6569 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6572 pullOrFreeReg (hc08_reg_x, needpulx);
6573 pullOrFreeReg (hc08_reg_a, needpula);
6576 /*-----------------------------------------------------------------*/
6577 /* genrshFour - shift four byte by a known amount != 0 */
6578 /*-----------------------------------------------------------------*/
6580 genrshFour (operand * result, operand * left,
6581 int shCount, int sign)
6583 /* TODO: handle cases where left == result */
6585 D(emitcode ("; genrshFour",""));
6587 /* if shifting more that 3 bytes */
6590 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6591 AccRsh (shCount-24, sign);
6592 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6595 else if (shCount >= 16)
6597 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6598 XAccRsh (shCount-16, sign);
6599 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6602 else if (shCount >= 8)
6605 shiftRLong (left, MSB16, result, sign);
6606 else if (shCount == 8)
6608 transferAopAop (AOP (left), 1, AOP (result), 0);
6609 transferAopAop (AOP (left), 2, AOP (result), 1);
6610 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6611 storeRegToAop (hc08_reg_a, AOP (result), 2);
6612 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6614 else if (shCount == 9)
6616 shiftRLong (left, MSB16, result, sign);
6620 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6621 XAccRsh (shCount-8, FALSE);
6622 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6623 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6624 loadRegFromConst (hc08_reg_a, zero);
6625 XAccRsh (shCount-8, sign);
6626 accopWithAop ("ora", AOP (result), 1);
6627 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6631 { /* 1 <= shCount <= 7 */
6634 shiftRLong (left, LSB, result, sign);
6638 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6639 XAccRsh (shCount, FALSE);
6640 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6641 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6643 accopWithAop ("ora", AOP (result), 1);
6644 storeRegToAop (hc08_reg_a, AOP (result), 1);
6645 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6646 XAccRsh (shCount, sign);
6647 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6652 /*-----------------------------------------------------------------*/
6653 /* genRightShiftLiteral - right shifting by known count */
6654 /*-----------------------------------------------------------------*/
6656 genRightShiftLiteral (operand * left,
6662 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6665 D(emitcode ("; genRightShiftLiteral",""));
6667 freeAsmop (right, NULL, ic, TRUE);
6669 aopOp (left, ic, FALSE);
6670 aopOp (result, ic, FALSE);
6673 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6677 size = getDataSize (left);
6678 /* test the LEFT size !!! */
6680 /* I suppose that the left size >= result size */
6683 size = getDataSize (result);
6685 transferAopAop (AOP (left), size, AOP(result), size);
6687 else if (shCount >= (size * 8))
6690 /* get sign in acc.7 */
6691 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6693 addSign (result, LSB, sign);
6700 genrshOne (result, left, shCount, sign);
6704 genrshTwo (result, left, shCount, sign);
6708 genrshFour (result, left, shCount, sign);
6714 freeAsmop (left, NULL, ic, TRUE);
6715 freeAsmop (result, NULL, ic, TRUE);
6719 /*-----------------------------------------------------------------*/
6720 /* genRightShift - generate code for right shifting */
6721 /*-----------------------------------------------------------------*/
6723 genRightShift (iCode * ic)
6725 operand *right, *left, *result;
6729 symbol *tlbl, *tlbl1;
6733 D(emitcode ("; genRightShift",""));
6735 /* if signed then we do it the hard way preserve the
6736 sign bit moving it inwards */
6737 retype = getSpec (operandType (IC_RESULT (ic)));
6738 sign = !SPEC_USIGN (retype);
6740 /* signed & unsigned types are treated the same : i.e. the
6741 signed is NOT propagated inwards : quoting from the
6742 ANSI - standard : "for E1 >> E2, is equivalent to division
6743 by 2**E2 if unsigned or if it has a non-negative value,
6744 otherwise the result is implementation defined ", MY definition
6745 is that the sign does not get propagated */
6747 right = IC_RIGHT (ic);
6748 left = IC_LEFT (ic);
6749 result = IC_RESULT (ic);
6751 aopOp (right, ic, FALSE);
6753 /* if the shift count is known then do it
6754 as efficiently as possible */
6755 if (AOP_TYPE (right) == AOP_LIT)
6757 genRightShiftLiteral (left, right, result, ic, sign);
6761 /* shift count is unknown then we have to form
6762 a loop get the loop count in X : Note: we take
6763 only the lower order byte since shifting
6764 more that 32 bits make no sense anyway, ( the
6765 largest size of an object can be only 32 bits ) */
6767 aopOp (left, ic, FALSE);
6768 aopOp (result, ic, FALSE);
6770 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6771 AOP (result) = forceStackedAop (AOP (result));
6773 size = AOP_SIZE (result);
6777 transferAopAop (AOP (left), offset, AOP (result), offset);
6781 tlbl = newiTempLabel (NULL);
6782 size = AOP_SIZE (result);
6784 tlbl1 = newiTempLabel (NULL);
6786 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6787 emitcode ("tstx", "");
6788 emitcode ("beq", "%05d$", tlbl1->key + 100);
6789 emitcode ("", "%05d$:", tlbl->key + 100);
6790 shift= sign ? "asr" : "lsr";
6791 for (offset=size-1;offset>=0;offset--)
6793 rmwWithAop (shift, AOP (result), offset);
6796 rmwWithReg ("dec", hc08_reg_x);
6797 emitcode ("bne","%05d$", tlbl->key + 100);
6798 emitcode ("", "%05d$:", tlbl1->key + 100);
6800 freeAsmop (result, NULL, ic, TRUE);
6801 freeAsmop (left, NULL, ic, TRUE);
6802 freeAsmop (right, NULL, ic, TRUE);
6806 /*-----------------------------------------------------------------*/
6807 /* genUnpackBits - generates code for unpacking bits */
6808 /*-----------------------------------------------------------------*/
6810 genUnpackBits (operand * result, iCode *ifx)
6812 int offset = 0; /* result byte offset */
6813 int rsize; /* result size */
6814 int rlen = 0; /* remaining bitfield length */
6815 sym_link *etype; /* bitfield type information */
6816 int blen; /* bitfield length */
6817 int bstr; /* bitfield starting bit within byte */
6819 D(emitcode ("; genUnpackBits",""));
6821 etype = getSpec (operandType (result));
6822 rsize = getSize (operandType (result));
6823 blen = SPEC_BLEN (etype);
6824 bstr = SPEC_BSTR (etype);
6826 /* If the bitfield length is less than a byte */
6829 emitcode ("lda", ",x");
6830 hc08_dirtyReg (hc08_reg_a, FALSE);
6833 AccRsh (bstr, FALSE);
6834 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6835 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6839 emitcode ("and", "#0x%02x",
6840 (((unsigned char) -1) >> (8 - blen)) << bstr);
6845 /* Bit field did not fit in a byte. Copy all
6846 but the partial byte at the end. */
6847 for (rlen=blen;rlen>=8;rlen-=8)
6849 emitcode ("lda", ",x");
6850 hc08_dirtyReg (hc08_reg_a, FALSE);
6852 storeRegToAop (hc08_reg_a, AOP (result), offset);
6855 emitcode ("aix", "#1");
6858 /* Handle the partial byte at the end */
6861 emitcode ("lda", ",x");
6862 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6863 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6871 storeConstToAop (zero, AOP (result), offset++);
6874 if (ifx && !ifx->generated)
6876 genIfxJump (ifx, "a");
6881 /*-----------------------------------------------------------------*/
6882 /* genUnpackBitsImmed - generates code for unpacking bits */
6883 /*-----------------------------------------------------------------*/
6885 genUnpackBitsImmed (operand * left,
6891 int offset = 0; /* result byte offset */
6892 int rsize; /* result size */
6893 int rlen = 0; /* remaining bitfield length */
6894 sym_link *etype; /* bitfield type information */
6895 int blen; /* bitfield length */
6896 int bstr; /* bitfield starting bit within byte */
6899 D(emitcode ("; genUnpackBitsImmed",""));
6901 aopOp (result, ic, TRUE);
6902 size = AOP_SIZE (result);
6904 derefaop = aopDerefAop (AOP (left));
6905 freeAsmop (left, NULL, ic, TRUE);
6906 derefaop->size = size;
6908 etype = getSpec (operandType (result));
6909 rsize = getSize (operandType (result));
6910 blen = SPEC_BLEN (etype);
6911 bstr = SPEC_BSTR (etype);
6913 /* if the bitfield is a single bit in the direct page */
6914 if (blen == 1 && derefaop->type == AOP_DIR)
6918 symbol *tlbl = newiTempLabel (NULL);
6920 loadRegFromConst (hc08_reg_a, zero);
6921 emitcode ("brclr", "#%d,%s,%05d$",
6922 bstr, aopAdrStr (derefaop, 0, FALSE),
6924 rmwWithReg ("inc", hc08_reg_a);
6926 storeRegToAop (hc08_reg_a, AOP (result), offset);
6927 hc08_freeReg (hc08_reg_a);
6933 symbol *tlbl = newiTempLabel (NULL);
6939 jlbl = IC_TRUE (ifx);
6944 jlbl = IC_FALSE (ifx);
6947 emitcode (inst, "#%d,%s,%05d$",
6948 bstr, aopAdrStr (derefaop, 0, FALSE),
6950 emitBranch ("jmp", jlbl);
6958 /* If the bitfield length is less than a byte */
6961 loadRegFromAop (hc08_reg_a, derefaop, 0);
6964 AccRsh (bstr, FALSE);
6965 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6966 hc08_dirtyReg (hc08_reg_a, FALSE);
6967 storeRegToAop (hc08_reg_a, AOP (result), offset);
6971 emitcode ("and", "#0x%02x",
6972 (((unsigned char) -1) >> (8 - blen)) << bstr);
6973 hc08_dirtyReg (hc08_reg_a, FALSE);
6979 /* Bit field did not fit in a byte. Copy all
6980 but the partial byte at the end. */
6981 for (rlen=blen;rlen>=8;rlen-=8)
6983 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6985 storeRegToAop (hc08_reg_a, AOP (result), offset);
6987 emitcode ("tsta", "");
6991 /* Handle the partial byte at the end */
6994 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6995 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6996 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7004 storeConstToAop (zero, AOP (result), offset++);
7007 freeAsmop (NULL, derefaop, ic, TRUE);
7008 freeAsmop (result, NULL, ic, TRUE);
7010 if (ifx && !ifx->generated)
7012 genIfxJump (ifx, "a");
7017 /*-----------------------------------------------------------------*/
7018 /* genDataPointerGet - generates code when ptr offset is known */
7019 /*-----------------------------------------------------------------*/
7021 genDataPointerGet (operand * left,
7029 D(emitcode ("; genDataPointerGet",""));
7031 aopOp (result, ic, TRUE);
7032 size = AOP_SIZE (result);
7034 derefaop = aopDerefAop (AOP (left));
7035 freeAsmop (left, NULL, ic, TRUE);
7036 derefaop->size = size;
7041 transferAopAop (derefaop, size, AOP (result), size);
7043 loadRegFromAop (hc08_reg_a, derefaop, size);
7046 freeAsmop (NULL, derefaop, ic, TRUE);
7047 freeAsmop (result, NULL, ic, TRUE);
7049 if (ifx && !ifx->generated)
7051 genIfxJump (ifx, "a");
7056 /*-----------------------------------------------------------------*/
7057 /* genPointerGet - generate code for pointer get */
7058 /*-----------------------------------------------------------------*/
7060 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7062 operand *left = IC_LEFT (ic);
7063 operand *result = IC_RESULT (ic);
7065 sym_link *retype = getSpec (operandType (result));
7067 D(emitcode ("; genPointerGet",""));
7069 if (getSize (operandType (result))>1)
7072 aopOp (left, ic, FALSE);
7074 /* if left is rematerialisable and
7075 result is not bit variable type */
7076 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7078 if (!IS_BITVAR (retype))
7080 genDataPointerGet (left, result, ic, ifx);
7085 genUnpackBitsImmed (left, result, ic, ifx);
7090 /* if the operand is already in hx
7091 then we do nothing else we move the value to hx */
7092 if (AOP_TYPE (left) != AOP_STR)
7094 /* if this is remateriazable */
7095 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7098 /* so hx now contains the address */
7099 aopOp (result, ic, FALSE);
7101 /* if bit then unpack */
7102 if (IS_BITVAR (retype))
7103 genUnpackBits (result, ifx);
7106 size = AOP_SIZE (result);
7111 accopWithMisc ("lda", ",x");
7114 emitcode ("aix", "#1");
7115 hc08_dirtyReg (hc08_reg_hx, FALSE);
7118 storeRegToAop (hc08_reg_a, AOP (result), offset);
7120 hc08_freeReg (hc08_reg_a);
7124 freeAsmop (left, NULL, ic, TRUE);
7125 freeAsmop (result, NULL, ic, TRUE);
7128 aopOp (IC_RESULT (pi), pi, FALSE);
7129 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7130 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7134 if (ifx && !ifx->generated)
7136 genIfxJump (ifx, "a");
7139 hc08_freeReg (hc08_reg_hx);
7143 /*-----------------------------------------------------------------*/
7144 /* genPackBits - generates code for packed bit storage */
7145 /*-----------------------------------------------------------------*/
7147 genPackBits (sym_link * etype,
7150 int offset = 0; /* source byte offset */
7151 int rlen = 0; /* remaining bitfield length */
7152 int blen; /* bitfield length */
7153 int bstr; /* bitfield starting bit within byte */
7154 int litval; /* source literal value (if AOP_LIT) */
7155 unsigned char mask; /* bitmask within current byte */
7158 D(emitcode ("; genPackBits",""));
7160 blen = SPEC_BLEN (etype);
7161 bstr = SPEC_BSTR (etype);
7163 /* If the bitfield length is less than a byte */
7166 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7167 (unsigned char) (0xFF >> (8 - bstr)));
7169 if (AOP_TYPE (right) == AOP_LIT)
7171 /* Case with a bitfield length <8 and literal source
7173 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7175 litval &= (~mask) & 0xff;
7177 emitcode ("lda", ",x");
7178 if ((mask|litval)!=0xff)
7179 emitcode ("and","#0x%02x", mask);
7181 emitcode ("ora","#0x%02x", litval);
7182 hc08_dirtyReg (hc08_reg_a, FALSE);
7183 emitcode ("sta", ",x");
7185 hc08_freeReg (hc08_reg_a);
7189 /* Case with a bitfield length < 8 and arbitrary source
7191 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7192 /* shift and mask source value */
7194 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7195 hc08_dirtyReg (hc08_reg_a, FALSE);
7196 pushReg (hc08_reg_a, TRUE);
7198 emitcode ("lda", ",x");
7199 emitcode ("and", "#0x%02x", mask);
7200 emitcode ("ora", "1,s");
7201 emitcode ("sta", ",x");
7202 pullReg (hc08_reg_a);
7204 hc08_freeReg (hc08_reg_a);
7208 /* Bit length is greater than 7 bits. In this case, copy */
7209 /* all except the partial byte at the end */
7210 for (rlen=blen;rlen>=8;rlen-=8)
7212 if (AOP (right)->type == AOP_DIR)
7214 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7219 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7220 emitcode ("sta", "%d,x", offset);
7225 /* If there was a partial byte at the end */
7228 mask = (((unsigned char) -1 << rlen) & 0xff);
7230 if (AOP_TYPE (right) == AOP_LIT)
7232 /* Case with partial byte and literal source
7234 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7235 litval >>= (blen-rlen);
7236 litval &= (~mask) & 0xff;
7237 emitcode ("lda", "%d,x", offset - xoffset);
7238 hc08_dirtyReg (hc08_reg_a, FALSE);
7239 if ((mask|litval)!=0xff)
7240 emitcode ("and","#0x%02x", mask);
7242 emitcode ("ora","#0x%02x", litval);
7243 emitcode ("sta", "%d,x", offset - xoffset);
7244 hc08_dirtyReg (hc08_reg_a, FALSE);
7245 hc08_freeReg (hc08_reg_a);
7249 /* Case with partial byte and arbitrary source
7251 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7252 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7253 hc08_dirtyReg (hc08_reg_a, FALSE);
7254 pushReg (hc08_reg_a, TRUE);
7256 emitcode ("lda", "%d,x", offset - xoffset);
7257 emitcode ("and", "#0x%02x", mask);
7258 emitcode ("ora", "1,s");
7259 emitcode ("sta", "%d,x", offset - xoffset);
7260 pullReg (hc08_reg_a);
7263 hc08_freeReg (hc08_reg_a);
7266 /*-----------------------------------------------------------------*/
7267 /* genPackBitsImmed - generates code for packed bit storage */
7268 /*-----------------------------------------------------------------*/
7270 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7274 int offset = 0; /* source byte offset */
7275 int rlen = 0; /* remaining bitfield length */
7276 int blen; /* bitfield length */
7277 int bstr; /* bitfield starting bit within byte */
7278 int litval; /* source literal value (if AOP_LIT) */
7279 unsigned char mask; /* bitmask within current byte */
7281 D(emitcode ("; genPackBitsImmed",""));
7283 blen = SPEC_BLEN (etype);
7284 bstr = SPEC_BSTR (etype);
7286 aopOp (right, ic, FALSE);
7287 size = AOP_SIZE (right);
7289 derefaop = aopDerefAop (AOP (result));
7290 freeAsmop (result, NULL, ic, TRUE);
7291 derefaop->size = size;
7293 /* if the bitfield is a single bit in the direct page */
7294 if (blen == 1 && derefaop->type == AOP_DIR)
7296 if (AOP_TYPE (right) == AOP_LIT)
7298 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7300 emitcode ((litval & 1) ? "bset" : "bclr",
7301 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7305 symbol *tlbl1 = newiTempLabel (NULL);
7306 symbol *tlbl2 = newiTempLabel (NULL);
7308 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7309 emitcode ("bit", "#1");
7310 emitBranch ("bne", tlbl1);
7311 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7312 emitBranch ("bra", tlbl2);
7314 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7316 hc08_freeReg (hc08_reg_a);
7321 /* If the bitfield length is less than a byte */
7324 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7325 (unsigned char) (0xFF >> (8 - bstr)));
7327 if (AOP_TYPE (right) == AOP_LIT)
7329 /* Case with a bitfield length <8 and literal source
7331 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7333 litval &= (~mask) & 0xff;
7335 loadRegFromAop (hc08_reg_a, derefaop, 0);
7336 if ((mask|litval)!=0xff)
7337 emitcode ("and","#0x%02x", mask);
7339 emitcode ("ora","#0x%02x", litval);
7340 hc08_dirtyReg (hc08_reg_a, FALSE);
7341 storeRegToAop (hc08_reg_a, derefaop, 0);
7343 hc08_freeReg (hc08_reg_a);
7347 /* Case with a bitfield length < 8 and arbitrary source
7349 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7350 /* shift and mask source value */
7352 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7353 hc08_dirtyReg (hc08_reg_a, FALSE);
7354 pushReg (hc08_reg_a, TRUE);
7356 loadRegFromAop (hc08_reg_a, derefaop, 0);
7357 emitcode ("and", "#0x%02x", mask);
7358 emitcode ("ora", "1,s");
7359 storeRegToAop (hc08_reg_a, derefaop, 0);
7360 pullReg (hc08_reg_a);
7362 hc08_freeReg (hc08_reg_a);
7366 /* Bit length is greater than 7 bits. In this case, copy */
7367 /* all except the partial byte at the end */
7368 for (rlen=blen;rlen>=8;rlen-=8)
7370 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7374 /* If there was a partial byte at the end */
7377 mask = (((unsigned char) -1 << rlen) & 0xff);
7379 if (AOP_TYPE (right) == AOP_LIT)
7381 /* Case with partial byte and literal source
7383 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7384 litval >>= (blen-rlen);
7385 litval &= (~mask) & 0xff;
7386 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7387 if ((mask|litval)!=0xff)
7388 emitcode ("and","#0x%02x", mask);
7390 emitcode ("ora","#0x%02x", litval);
7391 hc08_dirtyReg (hc08_reg_a, FALSE);
7392 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7393 hc08_dirtyReg (hc08_reg_a, FALSE);
7394 hc08_freeReg (hc08_reg_a);
7398 /* Case with partial byte and arbitrary source
7400 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7401 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7402 hc08_dirtyReg (hc08_reg_a, FALSE);
7403 pushReg (hc08_reg_a, TRUE);
7405 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7406 emitcode ("and", "#0x%02x", mask);
7407 emitcode ("ora", "1,s");
7408 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7409 pullReg (hc08_reg_a);
7412 hc08_freeReg (hc08_reg_a);
7415 freeAsmop (right, NULL, ic, TRUE);
7416 freeAsmop (NULL, derefaop, ic, TRUE);
7419 /*-----------------------------------------------------------------*/
7420 /* genDataPointerSet - remat pointer to data space */
7421 /*-----------------------------------------------------------------*/
7423 genDataPointerSet (operand * right,
7430 D(emitcode ("; genDataPointerSet",""));
7432 aopOp (right, ic, FALSE);
7433 size = AOP_SIZE (right);
7435 derefaop = aopDerefAop (AOP (result));
7436 freeAsmop (result, NULL, ic, TRUE);
7437 derefaop->size = size;
7441 transferAopAop (AOP (right), size, derefaop, size);
7444 freeAsmop (right, NULL, ic, TRUE);
7445 freeAsmop (NULL, derefaop, ic, TRUE);
7449 /*-----------------------------------------------------------------*/
7450 /* genPointerSet - stores the value into a pointer location */
7451 /*-----------------------------------------------------------------*/
7453 genPointerSet (iCode * ic, iCode *pi)
7455 operand *right = IC_RIGHT (ic);
7456 operand *result = IC_RESULT (ic);
7457 sym_link *type, *etype;
7459 sym_link *retype = getSpec (operandType (right));
7460 sym_link *letype = getSpec (operandType (result));
7462 D(emitcode ("; genPointerSet",""));
7464 type = operandType (result);
7465 etype = getSpec (type);
7467 aopOp (result, ic, FALSE);
7469 /* if the result is rematerializable */
7470 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7472 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7474 genDataPointerSet (right, result, ic);
7479 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7484 /* if the operand is already in hx
7485 then we do nothing else we move the value to hx */
7486 if (AOP_TYPE (result) != AOP_STR)
7488 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7490 /* so hx now contains the address */
7491 aopOp (right, ic, FALSE);
7493 /* if bit then unpack */
7494 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7495 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7498 size = AOP_SIZE (right);
7503 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7504 accopWithMisc ("sta", ",x");
7507 emitcode ("aix", "#1");
7509 hc08_freeReg (hc08_reg_a);
7513 freeAsmop (result, NULL, ic, TRUE);
7514 freeAsmop (right, NULL, ic, TRUE);
7517 aopOp (IC_RESULT (pi), pi, FALSE);
7518 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7519 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7523 hc08_freeReg (hc08_reg_hx);
7527 /*-----------------------------------------------------------------*/
7528 /* genIfx - generate code for Ifx statement */
7529 /*-----------------------------------------------------------------*/
7531 genIfx (iCode * ic, iCode * popIc)
7533 operand *cond = IC_COND (ic);
7536 D(emitcode ("; genIfx",""));
7538 aopOp (cond, ic, FALSE);
7540 /* get the value into acc */
7541 if (AOP_TYPE (cond) != AOP_CRY)
7542 asmopToBool (AOP (cond), FALSE);
7545 /* the result is now in the accumulator */
7546 freeAsmop (cond, NULL, ic, TRUE);
7548 /* if there was something to be popped then do it */
7552 /* if the condition is a bit variable */
7553 if (isbit && IS_ITEMP (cond) &&
7555 genIfxJump (ic, SPIL_LOC (cond)->rname);
7556 else if (isbit && !IS_ITEMP (cond))
7557 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7559 genIfxJump (ic, "a");
7564 /*-----------------------------------------------------------------*/
7565 /* genAddrOf - generates code for address of */
7566 /*-----------------------------------------------------------------*/
7568 genAddrOf (iCode * ic)
7570 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7573 D(emitcode ("; genAddrOf",""));
7575 aopOp (IC_RESULT (ic), ic, FALSE);
7577 /* if the operand is on the stack then we
7578 need to get the stack offset of this
7582 /* if it has an offset then we need to compute
7584 hc08_useReg (hc08_reg_hx);
7585 emitcode ("tsx", "");
7586 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7587 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7588 hc08_freeReg (hc08_reg_hx);
7593 /* object not on stack then we need the name */
7594 size = AOP_SIZE (IC_RESULT (ic));
7599 char s[SDCC_NAME_MAX+10];
7602 sprintf (s, "#%s", sym->rname);
7605 sprintf (s, "#>%s", sym->rname);
7608 sprintf (s, "#(%s >> %d)",
7612 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7616 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7620 /*-----------------------------------------------------------------*/
7621 /* genAssign - generate code for assignment */
7622 /*-----------------------------------------------------------------*/
7624 genAssign (iCode * ic)
7626 operand *result, *right;
7628 // unsigned long lit = 0L;
7630 D(emitcode("; genAssign",""));
7632 result = IC_RESULT (ic);
7633 right = IC_RIGHT (ic);
7635 /* if they are the same */
7636 if (operandsEqu (result, right)) {
7640 aopOp (right, ic, FALSE);
7641 aopOp (result, ic, TRUE);
7643 /* if they are the same registers */
7644 if (sameRegs (AOP (right), AOP (result)))
7647 if ((AOP_TYPE (right) == AOP_LIT)
7648 && (IS_AOP_HX(AOP(result))))
7650 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7655 size = AOP_SIZE (result);
7658 transferAopAop (AOP (right), size, AOP (result), size);
7662 freeAsmop (right, NULL, ic, TRUE);
7663 freeAsmop (result, NULL, ic, TRUE);
7666 /*-----------------------------------------------------------------*/
7667 /* genJumpTab - genrates code for jump table */
7668 /*-----------------------------------------------------------------*/
7670 genJumpTab (iCode * ic)
7673 symbol *jtablo = newiTempLabel (NULL);
7674 symbol *jtabhi = newiTempLabel (NULL);
7676 D(emitcode ("; genJumpTab",""));
7678 aopOp (IC_JTCOND (ic), ic, FALSE);
7680 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7682 /* get the condition into x */
7683 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7684 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7685 loadRegFromConst (hc08_reg_h, zero);
7687 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7688 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7689 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7690 emitcode ("jmp", ",x");
7692 hc08_dirtyReg (hc08_reg_a, TRUE);
7693 hc08_dirtyReg (hc08_reg_hx, TRUE);
7698 pushReg(hc08_reg_hx, TRUE);
7700 /* get the condition into x */
7701 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7702 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7703 loadRegFromConst (hc08_reg_h, zero);
7705 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7706 emitcode ("sta", "3,s");
7707 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7708 emitcode ("sta", "4,s");
7710 pullReg(hc08_reg_hx);
7711 emitcode ("rts", "");
7712 _G.stackPushes += 2;
7716 /* now generate the jump labels */
7718 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7719 jtab = setNextItem (IC_JTLABELS (ic)))
7720 emitcode (".db", "%05d$", jtab->key + 100);
7722 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7723 jtab = setNextItem (IC_JTLABELS (ic)))
7724 emitcode (".db", ">%05d$", jtab->key + 100);
7728 /*-----------------------------------------------------------------*/
7729 /* genCast - gen code for casting */
7730 /*-----------------------------------------------------------------*/
7732 genCast (iCode * ic)
7734 operand *result = IC_RESULT (ic);
7735 sym_link *ctype = operandType (IC_LEFT (ic));
7736 sym_link *rtype = operandType (IC_RIGHT (ic));
7737 operand *right = IC_RIGHT (ic);
7740 D(emitcode("; genCast",""));
7742 /* if they are equivalent then do nothing */
7743 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7746 aopOp (right, ic, FALSE);
7747 aopOp (result, ic, FALSE);
7750 /* if they are the same size : or less */
7751 if (AOP_SIZE (result) <= AOP_SIZE (right))
7754 /* if they are in the same place */
7756 if (sameRegs (AOP (right), AOP (result)))
7760 /* if they in different places then copy */
7761 size = AOP_SIZE (result);
7765 transferAopAop(AOP (right), offset, AOP (result), offset);
7772 /* if the result is of type pointer */
7777 sym_link *type = operandType (right);
7778 sym_link *etype = getSpec (type);
7780 /* pointer to generic pointer */
7781 if (IS_GENPTR (ctype))
7784 p_type = DCL_TYPE (type);
7787 if (SPEC_SCLS(etype)==S_REGISTER) {
7788 // let's assume it is a generic pointer
7791 /* we have to go by the storage class */
7792 p_type = PTR_TYPE (SPEC_OCLS (etype));
7796 /* the first two bytes are known */
7797 size = GPTRSIZE - 1;
7801 transferAopAop(AOP (right), offset, AOP (result), offset);
7804 /* the last byte depending on type */
7807 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7812 // pointerTypeToGPByte will have bitched.
7816 sprintf(gpValStr, "#0x%d", gpVal);
7817 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7823 /* just copy the pointers */
7824 size = AOP_SIZE (result);
7828 transferAopAop(AOP (right), offset, AOP (result), offset);
7834 /* so we now know that the size of destination is greater
7835 than the size of the source */
7836 /* we move to result for the size of source */
7837 size = AOP_SIZE (right);
7841 transferAopAop(AOP (right), offset, AOP (result), offset);
7845 /* now depending on the sign of the source && destination */
7846 size = AOP_SIZE (result) - AOP_SIZE (right);
7847 /* if unsigned or not an integral type */
7848 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7851 storeConstToAop (zero, AOP (result), offset++);
7855 /* we need to extend the sign :{ */
7856 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7857 accopWithMisc ("rola", "");
7858 accopWithMisc ("clra", "");
7859 accopWithMisc ("sbc", zero);
7861 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7864 /* we are done hurray !!!! */
7867 freeAsmop (right, NULL, ic, TRUE);
7868 freeAsmop (result, NULL, ic, TRUE);
7872 /*-----------------------------------------------------------------*/
7873 /* genDjnz - generate decrement & jump if not zero instrucion */
7874 /*-----------------------------------------------------------------*/
7876 genDjnz (iCode * ic, iCode * ifx)
7882 D(emitcode ("; genDjnz",""));
7884 /* if the if condition has a false label
7885 then we cannot save */
7889 /* if the minus is not of the form
7891 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7892 !IS_OP_LITERAL (IC_RIGHT (ic)))
7895 if (operandLitValue (IC_RIGHT (ic)) != 1)
7898 /* dbnz doesn't support extended mode */
7899 if (isOperandInFarSpace (IC_RESULT (ic)))
7902 /* if the size of this greater than one then no
7904 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7906 aopOp (IC_RESULT (ic), ic, FALSE);
7907 if (AOP_SIZE (IC_RESULT (ic))>1)
7909 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7913 /* otherwise we can save BIG */
7914 lbl = newiTempLabel (NULL);
7915 lbl1 = newiTempLabel (NULL);
7918 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7921 emitBranch ("bra", lbl1);
7923 emitBranch ("jmp", IC_TRUE (ifx));
7926 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7931 /*-----------------------------------------------------------------*/
7932 /* genReceive - generate code for a receive iCode */
7933 /*-----------------------------------------------------------------*/
7935 genReceive (iCode * ic)
7939 D(emitcode ("; genReceive",""));
7941 aopOp (IC_RESULT (ic), ic, FALSE);
7942 size = AOP_SIZE (IC_RESULT (ic));
7947 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7948 AOP (IC_RESULT (ic)), offset);
7949 if (hc08_aop_pass[offset]->type == AOP_REG)
7950 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7955 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7958 /*-----------------------------------------------------------------*/
7959 /* genDummyRead - generate code for dummy read of volatiles */
7960 /*-----------------------------------------------------------------*/
7962 genDummyRead (iCode * ic)
7967 D(emitcode("; genDummyRead",""));
7970 if (op && IS_SYMOP (op))
7973 aopOp (op, ic, FALSE);
7975 size = AOP_SIZE (op);
7980 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7981 hc08_freeReg (hc08_reg_a);
7985 freeAsmop (op, NULL, ic, TRUE);
7988 if (op && IS_SYMOP (op))
7991 aopOp (op, ic, FALSE);
7993 size = AOP_SIZE (op);
7998 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7999 hc08_freeReg (hc08_reg_a);
8003 freeAsmop (op, NULL, ic, TRUE);
8007 /*-----------------------------------------------------------------*/
8008 /* genCritical - generate code for start of a critical sequence */
8009 /*-----------------------------------------------------------------*/
8011 genCritical (iCode *ic)
8013 D(emitcode("; genCritical",""));
8016 aopOp (IC_RESULT (ic), ic, TRUE);
8018 emitcode ("tpa", "");
8019 hc08_dirtyReg (hc08_reg_a, FALSE);
8020 emitcode ("sei", "");
8023 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8025 pushReg (hc08_reg_a, FALSE);
8027 hc08_freeReg (hc08_reg_a);
8029 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8032 /*-----------------------------------------------------------------*/
8033 /* genEndCritical - generate code for end of a critical sequence */
8034 /*-----------------------------------------------------------------*/
8036 genEndCritical (iCode *ic)
8038 D(emitcode("; genEndCritical",""));
8042 aopOp (IC_RIGHT (ic), ic, FALSE);
8043 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8044 emitcode ("tap", "");
8045 hc08_freeReg (hc08_reg_a);
8046 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8050 pullReg (hc08_reg_a);
8051 emitcode ("tap", "");
8057 /*-----------------------------------------------------------------*/
8058 /* genhc08Code - generate code for HC08 based controllers */
8059 /*-----------------------------------------------------------------*/
8061 genhc08Code (iCode * lic)
8068 lineHead = lineCurr = NULL;
8070 /* print the allocation information */
8071 if (allocInfo && currFunc)
8072 printAllocInfo (currFunc, codeOutFile);
8073 /* if debug information required */
8074 if (options.debug && currFunc)
8076 debugFile->writeFunction (currFunc, lic);
8079 if (IS_STATIC (currFunc->etype))
8080 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8082 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8086 /* stack pointer name */
8087 if (options.useXstack)
8092 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8094 hc08_aop_pass[0] = newAsmop (AOP_REG);
8095 hc08_aop_pass[0]->size=1;
8096 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8097 hc08_aop_pass[1] = newAsmop (AOP_REG);
8098 hc08_aop_pass[1]->size=1;
8099 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8100 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8101 hc08_aop_pass[2]->size=1;
8102 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8103 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8104 hc08_aop_pass[3]->size=1;
8105 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8107 for (ic = lic; ic; ic = ic->next)
8110 _G.current_iCode = ic;
8112 if (ic->level != clevel || ic->block != cblock)
8116 debugFile->writeScope(ic);
8122 if (ic->lineno && cln != ic->lineno)
8126 debugFile->writeCLine(ic);
8129 emitcode ("", "C$%s$%d$%d$%d ==.",
8130 FileBaseName (ic->filename), ic->lineno,
8131 ic->level, ic->block);
8135 if (!options.noCcodeInAsm) {
8136 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8137 printCLine(ic->filename, ic->lineno));
8141 if (options.iCodeInAsm) {
8145 for (i=0; i<6; i++) {
8146 sprintf (®sInUse[i],
8147 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8150 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8152 /* if the result is marked as
8153 spilt and rematerializable or code for
8154 this has already been generated then
8156 if (resultRemat (ic) || ic->generated)
8164 for (i=A_IDX;i<=XA_IDX;i++)
8166 reg = hc08_regWithIdx(i);
8168 emitcode("","; %s = %s offset %d", reg->name,
8169 aopName(reg->aop), reg->aopofs);
8172 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8174 sym = OP_SYMBOL (IC_LEFT (ic));
8175 if (sym->accuse == ACCUSE_HX)
8177 hc08_reg_h->isFree = FALSE;
8178 hc08_reg_x->isFree = FALSE;
8180 else if (sym->accuse == ACCUSE_XA)
8182 hc08_reg_a->isFree = FALSE;
8184 hc08_reg_x->isFree = FALSE;
8187 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8189 sym = OP_SYMBOL (IC_RIGHT (ic));
8190 if (sym->accuse == ACCUSE_HX)
8192 hc08_reg_h->isFree = FALSE;
8193 hc08_reg_x->isFree = FALSE;
8195 else if (sym->accuse == ACCUSE_XA)
8197 hc08_reg_a->isFree = FALSE;
8199 hc08_reg_x->isFree = FALSE;
8204 /* depending on the operation */
8224 /* IPOP happens only when trying to restore a
8225 spilt live range, if there is an ifx statement
8226 following this pop then the if statement might
8227 be using some of the registers being popped which
8228 would destory the contents of the register so
8229 we need to check for this condition and handle it */
8231 ic->next->op == IFX &&
8232 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8233 genIfx (ic->next, ic);
8251 genEndFunction (ic);
8267 if (!genPointerGetSetOfs (ic))
8272 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8289 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8293 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8300 /* note these two are xlated by algebraic equivalence
8301 during parsing SDCC.y */
8302 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8303 "got '>=' or '<=' shouldn't have come here");
8307 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8319 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8323 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8327 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8354 case GET_VALUE_AT_ADDRESS:
8356 hasInc (IC_LEFT (ic), ic,
8357 getSize (operandType (IC_RESULT (ic)))),
8358 ifxForOp (IC_RESULT (ic), ic) );
8362 if (POINTER_SET (ic))
8363 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8389 addSet (&_G.sendSet, ic);
8392 case DUMMY_READ_VOLATILE:
8401 genEndCritical (ic);
8412 if (!hc08_reg_a->isFree)
8413 D(emitcode("","; forgot to free a"));
8414 if (!hc08_reg_x->isFree)
8415 D(emitcode("","; forgot to free x"));
8416 if (!hc08_reg_h->isFree)
8417 D(emitcode("","; forgot to free h"));
8418 if (!hc08_reg_hx->isFree)
8419 D(emitcode("","; forgot to free hx"));
8420 if (!hc08_reg_xa->isFree)
8421 D(emitcode("","; forgot to free xa"));
8424 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8427 /* now we are ready to call the
8428 peep hole optimizer */
8429 if (!options.nopeep)
8430 peepHole (&lineHead);
8432 /* now do the actual printing */
8433 printLine (lineHead, codeOutFile);