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);
6237 storeConstToAop (zero, AOP (result), 0);
6240 pullOrFreeReg (hc08_reg_x, needpulx);
6241 pullOrFreeReg (hc08_reg_a, needpula);
6244 /*-----------------------------------------------------------------*/
6245 /* genlshFour - shift four byte by a known amount != 0 */
6246 /*-----------------------------------------------------------------*/
6248 genlshFour (operand * result, operand * left, int shCount)
6252 D(emitcode ("; genlshFour",""));
6254 size = AOP_SIZE (result);
6256 /* TODO: deal with the &result == &left case */
6258 /* if shifting more that 3 bytes */
6263 /* lowest order of left goes to the highest
6264 order of the destination */
6265 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6267 movLeft2Result (left, LSB, result, MSB32, 0);
6268 storeConstToAop (zero, AOP (result), LSB);
6269 storeConstToAop (zero, AOP (result), MSB16);
6270 storeConstToAop (zero, AOP (result), MSB24);
6274 /* more than two bytes */
6275 else if (shCount >= 16)
6277 /* lower order two bytes goes to higher order two bytes */
6279 /* if some more remaining */
6281 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6284 movLeft2Result (left, MSB16, result, MSB32, 0);
6285 movLeft2Result (left, LSB, result, MSB24, 0);
6287 storeConstToAop (zero, AOP (result), LSB);
6288 storeConstToAop (zero, AOP (result), MSB16);
6292 /* if more than 1 byte */
6293 else if (shCount >= 8)
6295 /* lower order three bytes goes to higher order three bytes */
6300 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6302 movLeft2Result (left, LSB, result, MSB16, 0);
6308 movLeft2Result (left, MSB24, result, MSB32, 0);
6309 movLeft2Result (left, MSB16, result, MSB24, 0);
6310 movLeft2Result (left, LSB, result, MSB16, 0);
6311 storeConstToAop (zero, AOP (result), LSB);
6313 else if (shCount == 1)
6314 shiftLLong (left, result, MSB16);
6317 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6318 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6319 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6320 storeConstToAop (zero, AOP (result), LSB);
6325 /* 1 <= shCount <= 7 */
6326 else if (shCount <= 2)
6328 shiftLLong (left, result, LSB);
6330 shiftLLong (result, result, LSB);
6332 /* 3 <= shCount <= 7, optimize */
6335 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6336 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6337 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6341 /*-----------------------------------------------------------------*/
6342 /* genLeftShiftLiteral - left shifting by known count */
6343 /*-----------------------------------------------------------------*/
6345 genLeftShiftLiteral (operand * left,
6350 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6353 D(emitcode ("; genLeftShiftLiteral",""));
6355 freeAsmop (right, NULL, ic, TRUE);
6357 aopOp (left, ic, FALSE);
6358 aopOp (result, ic, FALSE);
6360 // size = getSize (operandType (result));
6361 size = AOP_SIZE (result);
6364 D(emitcode ("; shift left ", "result %d, left %d", size,
6371 transferAopAop( AOP(left), size, AOP(result), size);
6373 else if (shCount >= (size * 8))
6376 storeConstToAop (zero, AOP (result), size);
6383 genlshOne (result, left, shCount);
6387 genlshTwo (result, left, shCount);
6391 genlshFour (result, left, shCount);
6394 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6395 "*** ack! mystery literal shift!\n");
6399 freeAsmop (left, NULL, ic, TRUE);
6400 freeAsmop (result, NULL, ic, TRUE);
6403 /*-----------------------------------------------------------------*/
6404 /* genLeftShift - generates code for left shifting */
6405 /*-----------------------------------------------------------------*/
6407 genLeftShift (iCode * ic)
6409 operand *left, *right, *result;
6411 symbol *tlbl, *tlbl1;
6416 D(emitcode ("; genLeftShift",""));
6418 right = IC_RIGHT (ic);
6419 left = IC_LEFT (ic);
6420 result = IC_RESULT (ic);
6422 aopOp (right, ic, FALSE);
6424 /* if the shift count is known then do it
6425 as efficiently as possible */
6426 if (AOP_TYPE (right) == AOP_LIT)
6428 genLeftShiftLiteral (left, right, result, ic);
6432 /* shift count is unknown then we have to form
6433 a loop get the loop count in A : Note: we take
6434 only the lower order byte since shifting
6435 more that 32 bits make no sense anyway, ( the
6436 largest size of an object can be only 32 bits ) */
6438 aopOp (left, ic, FALSE);
6439 aopOp (result, ic, FALSE);
6441 /* now move the left to the result if they are not the
6443 if (!sameRegs (AOP (left), AOP (result)))
6446 size = AOP_SIZE (result);
6450 transferAopAop (AOP (left), offset, AOP (result), offset);
6454 freeAsmop (left, NULL, ic, TRUE);
6456 tlbl = newiTempLabel (NULL);
6457 size = AOP_SIZE (result);
6459 tlbl1 = newiTempLabel (NULL);
6463 loadRegFromAop (reg, AOP (right), 0);
6464 freeAsmop (right, NULL, ic, TRUE);
6465 emitBranch ("beq", tlbl1);
6469 for (offset=0;offset<size;offset++)
6471 rmwWithAop (shift, AOP (result), offset);
6474 rmwWithReg ("dec", reg);
6475 emitBranch ("bne", tlbl);
6479 freeAsmop (result, NULL, ic, TRUE);
6482 /*-----------------------------------------------------------------*/
6483 /* genrshOne - right shift a one byte quantity by known count */
6484 /*-----------------------------------------------------------------*/
6486 genrshOne (operand * result, operand * left,
6487 int shCount, int sign)
6489 D(emitcode ("; genrshOne",""));
6491 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6492 AccRsh (shCount, sign);
6493 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6496 /*-----------------------------------------------------------------*/
6497 /* genrshTwo - right shift two bytes by known amount != 0 */
6498 /*-----------------------------------------------------------------*/
6500 genrshTwo (operand * result, operand * left,
6501 int shCount, int sign)
6503 D(emitcode ("; genrshTwo",""));
6505 /* if shCount >= 8 */
6508 if (shCount || sign)
6510 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6511 AccRsh (shCount-8, sign);
6512 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6516 transferAopAop (AOP (left), 1, AOP (result), 0);
6517 storeConstToAop (zero, AOP (result), 1);
6521 /* 1 <= shCount <= 7 */
6524 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6525 XAccRsh (shCount, sign);
6526 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6530 /*-----------------------------------------------------------------*/
6531 /* shiftRLong - shift right one long from left to result */
6532 /* offl = LSB or MSB16 */
6533 /*-----------------------------------------------------------------*/
6535 shiftRLong (operand * left, int offl,
6536 operand * result, int sign)
6539 // int size = AOP_SIZE (result);
6541 bool needpula = FALSE;
6542 bool needpulx = FALSE;
6544 needpula = pushRegIfUsed (hc08_reg_a);
6545 needpulx = pushRegIfUsed (hc08_reg_x);
6549 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6551 rmwWithReg ("asr", hc08_reg_x);
6553 rmwWithReg ("lsr", hc08_reg_x);
6554 rmwWithReg ("ror", hc08_reg_a);
6555 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6557 else if (offl==MSB16)
6559 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6561 rmwWithReg ("asr", hc08_reg_a);
6563 rmwWithReg ("lsr", hc08_reg_a);
6564 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6565 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6568 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6569 rmwWithReg ("ror", hc08_reg_x);
6570 rmwWithReg ("ror", hc08_reg_a);
6571 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6574 pullOrFreeReg (hc08_reg_x, needpulx);
6575 pullOrFreeReg (hc08_reg_a, needpula);
6578 /*-----------------------------------------------------------------*/
6579 /* genrshFour - shift four byte by a known amount != 0 */
6580 /*-----------------------------------------------------------------*/
6582 genrshFour (operand * result, operand * left,
6583 int shCount, int sign)
6585 /* TODO: handle cases where left == result */
6587 D(emitcode ("; genrshFour",""));
6589 /* if shifting more that 3 bytes */
6592 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6593 AccRsh (shCount-24, sign);
6594 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6597 else if (shCount >= 16)
6599 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6600 XAccRsh (shCount-16, sign);
6601 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6604 else if (shCount >= 8)
6607 shiftRLong (left, MSB16, result, sign);
6608 else if (shCount == 8)
6610 transferAopAop (AOP (left), 1, AOP (result), 0);
6611 transferAopAop (AOP (left), 2, AOP (result), 1);
6612 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6613 storeRegToAop (hc08_reg_a, AOP (result), 2);
6614 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6616 else if (shCount == 9)
6618 shiftRLong (left, MSB16, result, sign);
6622 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6623 XAccRsh (shCount-8, FALSE);
6624 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6625 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6626 loadRegFromConst (hc08_reg_a, zero);
6627 XAccRsh (shCount-8, sign);
6628 accopWithAop ("ora", AOP (result), 1);
6629 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6630 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6634 { /* 1 <= shCount <= 7 */
6637 shiftRLong (left, LSB, result, sign);
6641 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6642 XAccRsh (shCount, FALSE);
6643 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6644 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6646 accopWithAop ("ora", AOP (result), 1);
6647 storeRegToAop (hc08_reg_a, AOP (result), 1);
6648 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6649 XAccRsh (shCount, sign);
6650 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6655 /*-----------------------------------------------------------------*/
6656 /* genRightShiftLiteral - right shifting by known count */
6657 /*-----------------------------------------------------------------*/
6659 genRightShiftLiteral (operand * left,
6665 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6668 D(emitcode ("; genRightShiftLiteral",""));
6670 freeAsmop (right, NULL, ic, TRUE);
6672 aopOp (left, ic, FALSE);
6673 aopOp (result, ic, FALSE);
6676 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6680 size = getDataSize (left);
6681 /* test the LEFT size !!! */
6683 /* I suppose that the left size >= result size */
6686 size = getDataSize (result);
6688 transferAopAop (AOP (left), size, AOP(result), size);
6690 else if (shCount >= (size * 8))
6693 /* get sign in acc.7 */
6694 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6696 addSign (result, LSB, sign);
6703 genrshOne (result, left, shCount, sign);
6707 genrshTwo (result, left, shCount, sign);
6711 genrshFour (result, left, shCount, sign);
6717 freeAsmop (left, NULL, ic, TRUE);
6718 freeAsmop (result, NULL, ic, TRUE);
6722 /*-----------------------------------------------------------------*/
6723 /* genRightShift - generate code for right shifting */
6724 /*-----------------------------------------------------------------*/
6726 genRightShift (iCode * ic)
6728 operand *right, *left, *result;
6732 symbol *tlbl, *tlbl1;
6736 D(emitcode ("; genRightShift",""));
6738 /* if signed then we do it the hard way preserve the
6739 sign bit moving it inwards */
6740 retype = getSpec (operandType (IC_RESULT (ic)));
6741 sign = !SPEC_USIGN (retype);
6743 /* signed & unsigned types are treated the same : i.e. the
6744 signed is NOT propagated inwards : quoting from the
6745 ANSI - standard : "for E1 >> E2, is equivalent to division
6746 by 2**E2 if unsigned or if it has a non-negative value,
6747 otherwise the result is implementation defined ", MY definition
6748 is that the sign does not get propagated */
6750 right = IC_RIGHT (ic);
6751 left = IC_LEFT (ic);
6752 result = IC_RESULT (ic);
6754 aopOp (right, ic, FALSE);
6756 /* if the shift count is known then do it
6757 as efficiently as possible */
6758 if (AOP_TYPE (right) == AOP_LIT)
6760 genRightShiftLiteral (left, right, result, ic, sign);
6764 /* shift count is unknown then we have to form
6765 a loop get the loop count in X : Note: we take
6766 only the lower order byte since shifting
6767 more that 32 bits make no sense anyway, ( the
6768 largest size of an object can be only 32 bits ) */
6770 aopOp (left, ic, FALSE);
6771 aopOp (result, ic, FALSE);
6773 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6774 AOP (result) = forceStackedAop (AOP (result));
6776 size = AOP_SIZE (result);
6780 transferAopAop (AOP (left), offset, AOP (result), offset);
6784 tlbl = newiTempLabel (NULL);
6785 size = AOP_SIZE (result);
6787 tlbl1 = newiTempLabel (NULL);
6789 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6790 emitcode ("tstx", "");
6791 emitcode ("beq", "%05d$", tlbl1->key + 100);
6792 emitcode ("", "%05d$:", tlbl->key + 100);
6793 shift= sign ? "asr" : "lsr";
6794 for (offset=size-1;offset>=0;offset--)
6796 rmwWithAop (shift, AOP (result), offset);
6799 rmwWithReg ("dec", hc08_reg_x);
6800 emitcode ("bne","%05d$", tlbl->key + 100);
6801 emitcode ("", "%05d$:", tlbl1->key + 100);
6803 freeAsmop (result, NULL, ic, TRUE);
6804 freeAsmop (left, NULL, ic, TRUE);
6805 freeAsmop (right, NULL, ic, TRUE);
6809 /*-----------------------------------------------------------------*/
6810 /* genUnpackBits - generates code for unpacking bits */
6811 /*-----------------------------------------------------------------*/
6813 genUnpackBits (operand * result, iCode *ifx)
6815 int offset = 0; /* result byte offset */
6816 int rsize; /* result size */
6817 int rlen = 0; /* remaining bitfield length */
6818 sym_link *etype; /* bitfield type information */
6819 int blen; /* bitfield length */
6820 int bstr; /* bitfield starting bit within byte */
6822 D(emitcode ("; genUnpackBits",""));
6824 etype = getSpec (operandType (result));
6825 rsize = getSize (operandType (result));
6826 blen = SPEC_BLEN (etype);
6827 bstr = SPEC_BSTR (etype);
6829 /* If the bitfield length is less than a byte */
6832 emitcode ("lda", ",x");
6833 hc08_dirtyReg (hc08_reg_a, FALSE);
6836 AccRsh (bstr, FALSE);
6837 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6838 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6842 emitcode ("and", "#0x%02x",
6843 (((unsigned char) -1) >> (8 - blen)) << bstr);
6848 /* Bit field did not fit in a byte. Copy all
6849 but the partial byte at the end. */
6850 for (rlen=blen;rlen>=8;rlen-=8)
6852 emitcode ("lda", ",x");
6853 hc08_dirtyReg (hc08_reg_a, FALSE);
6855 storeRegToAop (hc08_reg_a, AOP (result), offset);
6858 emitcode ("aix", "#1");
6861 /* Handle the partial byte at the end */
6864 emitcode ("lda", ",x");
6865 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6866 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6874 storeConstToAop (zero, AOP (result), offset++);
6877 if (ifx && !ifx->generated)
6879 genIfxJump (ifx, "a");
6884 /*-----------------------------------------------------------------*/
6885 /* genUnpackBitsImmed - generates code for unpacking bits */
6886 /*-----------------------------------------------------------------*/
6888 genUnpackBitsImmed (operand * left,
6894 int offset = 0; /* result byte offset */
6895 int rsize; /* result size */
6896 int rlen = 0; /* remaining bitfield length */
6897 sym_link *etype; /* bitfield type information */
6898 int blen; /* bitfield length */
6899 int bstr; /* bitfield starting bit within byte */
6902 D(emitcode ("; genUnpackBitsImmed",""));
6904 aopOp (result, ic, TRUE);
6905 size = AOP_SIZE (result);
6907 derefaop = aopDerefAop (AOP (left));
6908 freeAsmop (left, NULL, ic, TRUE);
6909 derefaop->size = size;
6911 etype = getSpec (operandType (result));
6912 rsize = getSize (operandType (result));
6913 blen = SPEC_BLEN (etype);
6914 bstr = SPEC_BSTR (etype);
6916 /* if the bitfield is a single bit in the direct page */
6917 if (blen == 1 && derefaop->type == AOP_DIR)
6921 symbol *tlbl = newiTempLabel (NULL);
6923 loadRegFromConst (hc08_reg_a, zero);
6924 emitcode ("brclr", "#%d,%s,%05d$",
6925 bstr, aopAdrStr (derefaop, 0, FALSE),
6927 rmwWithReg ("inc", hc08_reg_a);
6929 storeRegToAop (hc08_reg_a, AOP (result), offset);
6930 hc08_freeReg (hc08_reg_a);
6936 symbol *tlbl = newiTempLabel (NULL);
6942 jlbl = IC_TRUE (ifx);
6947 jlbl = IC_FALSE (ifx);
6950 emitcode (inst, "#%d,%s,%05d$",
6951 bstr, aopAdrStr (derefaop, 0, FALSE),
6953 emitBranch ("jmp", jlbl);
6961 /* If the bitfield length is less than a byte */
6964 loadRegFromAop (hc08_reg_a, derefaop, 0);
6967 AccRsh (bstr, FALSE);
6968 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6969 hc08_dirtyReg (hc08_reg_a, FALSE);
6970 storeRegToAop (hc08_reg_a, AOP (result), offset);
6974 emitcode ("and", "#0x%02x",
6975 (((unsigned char) -1) >> (8 - blen)) << bstr);
6976 hc08_dirtyReg (hc08_reg_a, FALSE);
6982 /* Bit field did not fit in a byte. Copy all
6983 but the partial byte at the end. */
6984 for (rlen=blen;rlen>=8;rlen-=8)
6986 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6988 storeRegToAop (hc08_reg_a, AOP (result), offset);
6990 emitcode ("tsta", "");
6994 /* Handle the partial byte at the end */
6997 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
6998 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6999 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7007 storeConstToAop (zero, AOP (result), offset++);
7010 freeAsmop (NULL, derefaop, ic, TRUE);
7011 freeAsmop (result, NULL, ic, TRUE);
7013 if (ifx && !ifx->generated)
7015 genIfxJump (ifx, "a");
7020 /*-----------------------------------------------------------------*/
7021 /* genDataPointerGet - generates code when ptr offset is known */
7022 /*-----------------------------------------------------------------*/
7024 genDataPointerGet (operand * left,
7032 D(emitcode ("; genDataPointerGet",""));
7034 aopOp (result, ic, TRUE);
7035 size = AOP_SIZE (result);
7037 derefaop = aopDerefAop (AOP (left));
7038 freeAsmop (left, NULL, ic, TRUE);
7039 derefaop->size = size;
7044 transferAopAop (derefaop, size, AOP (result), size);
7046 loadRegFromAop (hc08_reg_a, derefaop, size);
7049 freeAsmop (NULL, derefaop, ic, TRUE);
7050 freeAsmop (result, NULL, ic, TRUE);
7052 if (ifx && !ifx->generated)
7054 genIfxJump (ifx, "a");
7059 /*-----------------------------------------------------------------*/
7060 /* genPointerGet - generate code for pointer get */
7061 /*-----------------------------------------------------------------*/
7063 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7065 operand *left = IC_LEFT (ic);
7066 operand *result = IC_RESULT (ic);
7068 sym_link *retype = getSpec (operandType (result));
7070 D(emitcode ("; genPointerGet",""));
7072 if (getSize (operandType (result))>1)
7075 aopOp (left, ic, FALSE);
7077 /* if left is rematerialisable and
7078 result is not bit variable type */
7079 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7081 if (!IS_BITVAR (retype))
7083 genDataPointerGet (left, result, ic, ifx);
7088 genUnpackBitsImmed (left, result, ic, ifx);
7093 /* if the operand is already in hx
7094 then we do nothing else we move the value to hx */
7095 if (AOP_TYPE (left) != AOP_STR)
7097 /* if this is remateriazable */
7098 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7101 /* so hx now contains the address */
7102 aopOp (result, ic, FALSE);
7104 /* if bit then unpack */
7105 if (IS_BITVAR (retype))
7106 genUnpackBits (result, ifx);
7109 size = AOP_SIZE (result);
7114 accopWithMisc ("lda", ",x");
7117 emitcode ("aix", "#1");
7118 hc08_dirtyReg (hc08_reg_hx, FALSE);
7121 storeRegToAop (hc08_reg_a, AOP (result), offset);
7123 hc08_freeReg (hc08_reg_a);
7127 freeAsmop (left, NULL, ic, TRUE);
7128 freeAsmop (result, NULL, ic, TRUE);
7131 aopOp (IC_RESULT (pi), pi, FALSE);
7132 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7133 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7137 if (ifx && !ifx->generated)
7139 genIfxJump (ifx, "a");
7142 hc08_freeReg (hc08_reg_hx);
7146 /*-----------------------------------------------------------------*/
7147 /* genPackBits - generates code for packed bit storage */
7148 /*-----------------------------------------------------------------*/
7150 genPackBits (sym_link * etype,
7153 int offset = 0; /* source byte offset */
7154 int rlen = 0; /* remaining bitfield length */
7155 int blen; /* bitfield length */
7156 int bstr; /* bitfield starting bit within byte */
7157 int litval; /* source literal value (if AOP_LIT) */
7158 unsigned char mask; /* bitmask within current byte */
7161 D(emitcode ("; genPackBits",""));
7163 blen = SPEC_BLEN (etype);
7164 bstr = SPEC_BSTR (etype);
7166 /* If the bitfield length is less than a byte */
7169 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7170 (unsigned char) (0xFF >> (8 - bstr)));
7172 if (AOP_TYPE (right) == AOP_LIT)
7174 /* Case with a bitfield length <8 and literal source
7176 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7178 litval &= (~mask) & 0xff;
7180 emitcode ("lda", ",x");
7181 if ((mask|litval)!=0xff)
7182 emitcode ("and","#0x%02x", mask);
7184 emitcode ("ora","#0x%02x", litval);
7185 hc08_dirtyReg (hc08_reg_a, FALSE);
7186 emitcode ("sta", ",x");
7188 hc08_freeReg (hc08_reg_a);
7192 /* Case with a bitfield length < 8 and arbitrary source
7194 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7195 /* shift and mask source value */
7197 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7198 hc08_dirtyReg (hc08_reg_a, FALSE);
7199 pushReg (hc08_reg_a, TRUE);
7201 emitcode ("lda", ",x");
7202 emitcode ("and", "#0x%02x", mask);
7203 emitcode ("ora", "1,s");
7204 emitcode ("sta", ",x");
7205 pullReg (hc08_reg_a);
7207 hc08_freeReg (hc08_reg_a);
7211 /* Bit length is greater than 7 bits. In this case, copy */
7212 /* all except the partial byte at the end */
7213 for (rlen=blen;rlen>=8;rlen-=8)
7215 if (AOP (right)->type == AOP_DIR)
7217 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7222 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7223 emitcode ("sta", "%d,x", offset);
7228 /* If there was a partial byte at the end */
7231 mask = (((unsigned char) -1 << rlen) & 0xff);
7233 if (AOP_TYPE (right) == AOP_LIT)
7235 /* Case with partial byte and literal source
7237 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7238 litval >>= (blen-rlen);
7239 litval &= (~mask) & 0xff;
7240 emitcode ("lda", "%d,x", offset - xoffset);
7241 hc08_dirtyReg (hc08_reg_a, FALSE);
7242 if ((mask|litval)!=0xff)
7243 emitcode ("and","#0x%02x", mask);
7245 emitcode ("ora","#0x%02x", litval);
7246 emitcode ("sta", "%d,x", offset - xoffset);
7247 hc08_dirtyReg (hc08_reg_a, FALSE);
7248 hc08_freeReg (hc08_reg_a);
7252 /* Case with partial byte and arbitrary source
7254 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7255 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7256 hc08_dirtyReg (hc08_reg_a, FALSE);
7257 pushReg (hc08_reg_a, TRUE);
7259 emitcode ("lda", "%d,x", offset - xoffset);
7260 emitcode ("and", "#0x%02x", mask);
7261 emitcode ("ora", "1,s");
7262 emitcode ("sta", "%d,x", offset - xoffset);
7263 pullReg (hc08_reg_a);
7266 hc08_freeReg (hc08_reg_a);
7269 /*-----------------------------------------------------------------*/
7270 /* genPackBitsImmed - generates code for packed bit storage */
7271 /*-----------------------------------------------------------------*/
7273 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7277 int offset = 0; /* source byte offset */
7278 int rlen = 0; /* remaining bitfield length */
7279 int blen; /* bitfield length */
7280 int bstr; /* bitfield starting bit within byte */
7281 int litval; /* source literal value (if AOP_LIT) */
7282 unsigned char mask; /* bitmask within current byte */
7284 D(emitcode ("; genPackBitsImmed",""));
7286 blen = SPEC_BLEN (etype);
7287 bstr = SPEC_BSTR (etype);
7289 aopOp (right, ic, FALSE);
7290 size = AOP_SIZE (right);
7292 derefaop = aopDerefAop (AOP (result));
7293 freeAsmop (result, NULL, ic, TRUE);
7294 derefaop->size = size;
7296 /* if the bitfield is a single bit in the direct page */
7297 if (blen == 1 && derefaop->type == AOP_DIR)
7299 if (AOP_TYPE (right) == AOP_LIT)
7301 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7303 emitcode ((litval & 1) ? "bset" : "bclr",
7304 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7308 symbol *tlbl1 = newiTempLabel (NULL);
7309 symbol *tlbl2 = newiTempLabel (NULL);
7311 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7312 emitcode ("bit", "#1");
7313 emitBranch ("bne", tlbl1);
7314 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7315 emitBranch ("bra", tlbl2);
7317 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7319 hc08_freeReg (hc08_reg_a);
7324 /* If the bitfield length is less than a byte */
7327 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7328 (unsigned char) (0xFF >> (8 - bstr)));
7330 if (AOP_TYPE (right) == AOP_LIT)
7332 /* Case with a bitfield length <8 and literal source
7334 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7336 litval &= (~mask) & 0xff;
7338 loadRegFromAop (hc08_reg_a, derefaop, 0);
7339 if ((mask|litval)!=0xff)
7340 emitcode ("and","#0x%02x", mask);
7342 emitcode ("ora","#0x%02x", litval);
7343 hc08_dirtyReg (hc08_reg_a, FALSE);
7344 storeRegToAop (hc08_reg_a, derefaop, 0);
7346 hc08_freeReg (hc08_reg_a);
7350 /* Case with a bitfield length < 8 and arbitrary source
7352 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7353 /* shift and mask source value */
7355 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7356 hc08_dirtyReg (hc08_reg_a, FALSE);
7357 pushReg (hc08_reg_a, TRUE);
7359 loadRegFromAop (hc08_reg_a, derefaop, 0);
7360 emitcode ("and", "#0x%02x", mask);
7361 emitcode ("ora", "1,s");
7362 storeRegToAop (hc08_reg_a, derefaop, 0);
7363 pullReg (hc08_reg_a);
7365 hc08_freeReg (hc08_reg_a);
7369 /* Bit length is greater than 7 bits. In this case, copy */
7370 /* all except the partial byte at the end */
7371 for (rlen=blen;rlen>=8;rlen-=8)
7373 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7377 /* If there was a partial byte at the end */
7380 mask = (((unsigned char) -1 << rlen) & 0xff);
7382 if (AOP_TYPE (right) == AOP_LIT)
7384 /* Case with partial byte and literal source
7386 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7387 litval >>= (blen-rlen);
7388 litval &= (~mask) & 0xff;
7389 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7390 if ((mask|litval)!=0xff)
7391 emitcode ("and","#0x%02x", mask);
7393 emitcode ("ora","#0x%02x", litval);
7394 hc08_dirtyReg (hc08_reg_a, FALSE);
7395 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7396 hc08_dirtyReg (hc08_reg_a, FALSE);
7397 hc08_freeReg (hc08_reg_a);
7401 /* Case with partial byte and arbitrary source
7403 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7404 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7405 hc08_dirtyReg (hc08_reg_a, FALSE);
7406 pushReg (hc08_reg_a, TRUE);
7408 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7409 emitcode ("and", "#0x%02x", mask);
7410 emitcode ("ora", "1,s");
7411 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7412 pullReg (hc08_reg_a);
7415 hc08_freeReg (hc08_reg_a);
7418 freeAsmop (right, NULL, ic, TRUE);
7419 freeAsmop (NULL, derefaop, ic, TRUE);
7422 /*-----------------------------------------------------------------*/
7423 /* genDataPointerSet - remat pointer to data space */
7424 /*-----------------------------------------------------------------*/
7426 genDataPointerSet (operand * right,
7433 D(emitcode ("; genDataPointerSet",""));
7435 aopOp (right, ic, FALSE);
7436 size = AOP_SIZE (right);
7438 derefaop = aopDerefAop (AOP (result));
7439 freeAsmop (result, NULL, ic, TRUE);
7440 derefaop->size = size;
7444 transferAopAop (AOP (right), size, derefaop, size);
7447 freeAsmop (right, NULL, ic, TRUE);
7448 freeAsmop (NULL, derefaop, ic, TRUE);
7452 /*-----------------------------------------------------------------*/
7453 /* genPointerSet - stores the value into a pointer location */
7454 /*-----------------------------------------------------------------*/
7456 genPointerSet (iCode * ic, iCode *pi)
7458 operand *right = IC_RIGHT (ic);
7459 operand *result = IC_RESULT (ic);
7460 sym_link *type, *etype;
7462 sym_link *retype = getSpec (operandType (right));
7463 sym_link *letype = getSpec (operandType (result));
7465 D(emitcode ("; genPointerSet",""));
7467 type = operandType (result);
7468 etype = getSpec (type);
7470 aopOp (result, ic, FALSE);
7472 /* if the result is rematerializable */
7473 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7475 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7477 genDataPointerSet (right, result, ic);
7482 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7487 /* if the operand is already in hx
7488 then we do nothing else we move the value to hx */
7489 if (AOP_TYPE (result) != AOP_STR)
7491 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7493 /* so hx now contains the address */
7494 aopOp (right, ic, FALSE);
7496 /* if bit then unpack */
7497 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7498 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7501 size = AOP_SIZE (right);
7506 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7507 accopWithMisc ("sta", ",x");
7510 emitcode ("aix", "#1");
7512 hc08_freeReg (hc08_reg_a);
7516 freeAsmop (result, NULL, ic, TRUE);
7517 freeAsmop (right, NULL, ic, TRUE);
7520 aopOp (IC_RESULT (pi), pi, FALSE);
7521 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7522 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7526 hc08_freeReg (hc08_reg_hx);
7530 /*-----------------------------------------------------------------*/
7531 /* genIfx - generate code for Ifx statement */
7532 /*-----------------------------------------------------------------*/
7534 genIfx (iCode * ic, iCode * popIc)
7536 operand *cond = IC_COND (ic);
7539 D(emitcode ("; genIfx",""));
7541 aopOp (cond, ic, FALSE);
7543 /* get the value into acc */
7544 if (AOP_TYPE (cond) != AOP_CRY)
7545 asmopToBool (AOP (cond), FALSE);
7548 /* the result is now in the accumulator */
7549 freeAsmop (cond, NULL, ic, TRUE);
7551 /* if there was something to be popped then do it */
7555 /* if the condition is a bit variable */
7556 if (isbit && IS_ITEMP (cond) &&
7558 genIfxJump (ic, SPIL_LOC (cond)->rname);
7559 else if (isbit && !IS_ITEMP (cond))
7560 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7562 genIfxJump (ic, "a");
7567 /*-----------------------------------------------------------------*/
7568 /* genAddrOf - generates code for address of */
7569 /*-----------------------------------------------------------------*/
7571 genAddrOf (iCode * ic)
7573 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7576 D(emitcode ("; genAddrOf",""));
7578 aopOp (IC_RESULT (ic), ic, FALSE);
7580 /* if the operand is on the stack then we
7581 need to get the stack offset of this
7585 /* if it has an offset then we need to compute
7587 hc08_useReg (hc08_reg_hx);
7588 emitcode ("tsx", "");
7589 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7590 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7591 hc08_freeReg (hc08_reg_hx);
7596 /* object not on stack then we need the name */
7597 size = AOP_SIZE (IC_RESULT (ic));
7602 char s[SDCC_NAME_MAX+10];
7605 sprintf (s, "#%s", sym->rname);
7608 sprintf (s, "#>%s", sym->rname);
7611 sprintf (s, "#(%s >> %d)",
7615 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7619 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7623 /*-----------------------------------------------------------------*/
7624 /* genAssign - generate code for assignment */
7625 /*-----------------------------------------------------------------*/
7627 genAssign (iCode * ic)
7629 operand *result, *right;
7631 // unsigned long lit = 0L;
7633 D(emitcode("; genAssign",""));
7635 result = IC_RESULT (ic);
7636 right = IC_RIGHT (ic);
7638 /* if they are the same */
7639 if (operandsEqu (result, right)) {
7643 aopOp (right, ic, FALSE);
7644 aopOp (result, ic, TRUE);
7646 /* if they are the same registers */
7647 if (sameRegs (AOP (right), AOP (result)))
7650 if ((AOP_TYPE (right) == AOP_LIT)
7651 && (IS_AOP_HX(AOP(result))))
7653 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7658 size = AOP_SIZE (result);
7661 transferAopAop (AOP (right), size, AOP (result), size);
7665 freeAsmop (right, NULL, ic, TRUE);
7666 freeAsmop (result, NULL, ic, TRUE);
7669 /*-----------------------------------------------------------------*/
7670 /* genJumpTab - genrates code for jump table */
7671 /*-----------------------------------------------------------------*/
7673 genJumpTab (iCode * ic)
7676 symbol *jtablo = newiTempLabel (NULL);
7677 symbol *jtabhi = newiTempLabel (NULL);
7679 D(emitcode ("; genJumpTab",""));
7681 aopOp (IC_JTCOND (ic), ic, FALSE);
7683 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7685 /* get the condition into x */
7686 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7687 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7688 loadRegFromConst (hc08_reg_h, zero);
7690 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7691 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7692 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7693 emitcode ("jmp", ",x");
7695 hc08_dirtyReg (hc08_reg_a, TRUE);
7696 hc08_dirtyReg (hc08_reg_hx, TRUE);
7701 pushReg(hc08_reg_hx, TRUE);
7703 /* get the condition into x */
7704 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7705 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7706 loadRegFromConst (hc08_reg_h, zero);
7708 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7709 emitcode ("sta", "3,s");
7710 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7711 emitcode ("sta", "4,s");
7713 pullReg(hc08_reg_hx);
7714 emitcode ("rts", "");
7715 _G.stackPushes += 2;
7719 /* now generate the jump labels */
7721 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7722 jtab = setNextItem (IC_JTLABELS (ic)))
7723 emitcode (".db", "%05d$", jtab->key + 100);
7725 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7726 jtab = setNextItem (IC_JTLABELS (ic)))
7727 emitcode (".db", ">%05d$", jtab->key + 100);
7731 /*-----------------------------------------------------------------*/
7732 /* genCast - gen code for casting */
7733 /*-----------------------------------------------------------------*/
7735 genCast (iCode * ic)
7737 operand *result = IC_RESULT (ic);
7738 sym_link *ctype = operandType (IC_LEFT (ic));
7739 sym_link *rtype = operandType (IC_RIGHT (ic));
7740 operand *right = IC_RIGHT (ic);
7743 D(emitcode("; genCast",""));
7745 /* if they are equivalent then do nothing */
7746 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7749 aopOp (right, ic, FALSE);
7750 aopOp (result, ic, FALSE);
7753 /* if they are the same size : or less */
7754 if (AOP_SIZE (result) <= AOP_SIZE (right))
7757 /* if they are in the same place */
7759 if (sameRegs (AOP (right), AOP (result)))
7763 /* if they in different places then copy */
7764 size = AOP_SIZE (result);
7768 transferAopAop(AOP (right), offset, AOP (result), offset);
7775 /* if the result is of type pointer */
7780 sym_link *type = operandType (right);
7781 sym_link *etype = getSpec (type);
7783 /* pointer to generic pointer */
7784 if (IS_GENPTR (ctype))
7787 p_type = DCL_TYPE (type);
7790 if (SPEC_SCLS(etype)==S_REGISTER) {
7791 // let's assume it is a generic pointer
7794 /* we have to go by the storage class */
7795 p_type = PTR_TYPE (SPEC_OCLS (etype));
7799 /* the first two bytes are known */
7800 size = GPTRSIZE - 1;
7804 transferAopAop(AOP (right), offset, AOP (result), offset);
7807 /* the last byte depending on type */
7810 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7815 // pointerTypeToGPByte will have bitched.
7819 sprintf(gpValStr, "#0x%d", gpVal);
7820 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7826 /* just copy the pointers */
7827 size = AOP_SIZE (result);
7831 transferAopAop(AOP (right), offset, AOP (result), offset);
7837 /* so we now know that the size of destination is greater
7838 than the size of the source */
7839 /* we move to result for the size of source */
7840 size = AOP_SIZE (right);
7844 transferAopAop(AOP (right), offset, AOP (result), offset);
7848 /* now depending on the sign of the source && destination */
7849 size = AOP_SIZE (result) - AOP_SIZE (right);
7850 /* if unsigned or not an integral type */
7851 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7854 storeConstToAop (zero, AOP (result), offset++);
7858 /* we need to extend the sign :{ */
7859 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7860 accopWithMisc ("rola", "");
7861 accopWithMisc ("clra", "");
7862 accopWithMisc ("sbc", zero);
7864 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7867 /* we are done hurray !!!! */
7870 freeAsmop (right, NULL, ic, TRUE);
7871 freeAsmop (result, NULL, ic, TRUE);
7875 /*-----------------------------------------------------------------*/
7876 /* genDjnz - generate decrement & jump if not zero instrucion */
7877 /*-----------------------------------------------------------------*/
7879 genDjnz (iCode * ic, iCode * ifx)
7885 D(emitcode ("; genDjnz",""));
7887 /* if the if condition has a false label
7888 then we cannot save */
7892 /* if the minus is not of the form
7894 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7895 !IS_OP_LITERAL (IC_RIGHT (ic)))
7898 if (operandLitValue (IC_RIGHT (ic)) != 1)
7901 /* dbnz doesn't support extended mode */
7902 if (isOperandInFarSpace (IC_RESULT (ic)))
7905 /* if the size of this greater than one then no
7907 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7909 aopOp (IC_RESULT (ic), ic, FALSE);
7910 if (AOP_SIZE (IC_RESULT (ic))>1)
7912 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7916 /* otherwise we can save BIG */
7917 lbl = newiTempLabel (NULL);
7918 lbl1 = newiTempLabel (NULL);
7921 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7924 emitBranch ("bra", lbl1);
7926 emitBranch ("jmp", IC_TRUE (ifx));
7929 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7934 /*-----------------------------------------------------------------*/
7935 /* genReceive - generate code for a receive iCode */
7936 /*-----------------------------------------------------------------*/
7938 genReceive (iCode * ic)
7942 D(emitcode ("; genReceive",""));
7944 aopOp (IC_RESULT (ic), ic, FALSE);
7945 size = AOP_SIZE (IC_RESULT (ic));
7950 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7951 AOP (IC_RESULT (ic)), offset);
7952 if (hc08_aop_pass[offset]->type == AOP_REG)
7953 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7958 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7961 /*-----------------------------------------------------------------*/
7962 /* genDummyRead - generate code for dummy read of volatiles */
7963 /*-----------------------------------------------------------------*/
7965 genDummyRead (iCode * ic)
7970 D(emitcode("; genDummyRead",""));
7973 if (op && IS_SYMOP (op))
7976 aopOp (op, ic, FALSE);
7978 size = AOP_SIZE (op);
7983 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7984 hc08_freeReg (hc08_reg_a);
7988 freeAsmop (op, NULL, ic, TRUE);
7991 if (op && IS_SYMOP (op))
7994 aopOp (op, ic, FALSE);
7996 size = AOP_SIZE (op);
8001 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8002 hc08_freeReg (hc08_reg_a);
8006 freeAsmop (op, NULL, ic, TRUE);
8010 /*-----------------------------------------------------------------*/
8011 /* genCritical - generate code for start of a critical sequence */
8012 /*-----------------------------------------------------------------*/
8014 genCritical (iCode *ic)
8016 D(emitcode("; genCritical",""));
8019 aopOp (IC_RESULT (ic), ic, TRUE);
8021 emitcode ("tpa", "");
8022 hc08_dirtyReg (hc08_reg_a, FALSE);
8023 emitcode ("sei", "");
8026 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8028 pushReg (hc08_reg_a, FALSE);
8030 hc08_freeReg (hc08_reg_a);
8032 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8035 /*-----------------------------------------------------------------*/
8036 /* genEndCritical - generate code for end of a critical sequence */
8037 /*-----------------------------------------------------------------*/
8039 genEndCritical (iCode *ic)
8041 D(emitcode("; genEndCritical",""));
8045 aopOp (IC_RIGHT (ic), ic, FALSE);
8046 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8047 emitcode ("tap", "");
8048 hc08_freeReg (hc08_reg_a);
8049 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8053 pullReg (hc08_reg_a);
8054 emitcode ("tap", "");
8060 /*-----------------------------------------------------------------*/
8061 /* genhc08Code - generate code for HC08 based controllers */
8062 /*-----------------------------------------------------------------*/
8064 genhc08Code (iCode * lic)
8071 lineHead = lineCurr = NULL;
8073 /* print the allocation information */
8074 if (allocInfo && currFunc)
8075 printAllocInfo (currFunc, codeOutFile);
8076 /* if debug information required */
8077 if (options.debug && currFunc)
8079 debugFile->writeFunction (currFunc, lic);
8082 if (IS_STATIC (currFunc->etype))
8083 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8085 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8089 /* stack pointer name */
8090 if (options.useXstack)
8095 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8097 hc08_aop_pass[0] = newAsmop (AOP_REG);
8098 hc08_aop_pass[0]->size=1;
8099 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8100 hc08_aop_pass[1] = newAsmop (AOP_REG);
8101 hc08_aop_pass[1]->size=1;
8102 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8103 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8104 hc08_aop_pass[2]->size=1;
8105 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8106 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8107 hc08_aop_pass[3]->size=1;
8108 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8110 for (ic = lic; ic; ic = ic->next)
8113 _G.current_iCode = ic;
8115 if (ic->level != clevel || ic->block != cblock)
8119 debugFile->writeScope(ic);
8125 if (ic->lineno && cln != ic->lineno)
8129 debugFile->writeCLine(ic);
8132 emitcode ("", "C$%s$%d$%d$%d ==.",
8133 FileBaseName (ic->filename), ic->lineno,
8134 ic->level, ic->block);
8138 if (!options.noCcodeInAsm) {
8139 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8140 printCLine(ic->filename, ic->lineno));
8144 if (options.iCodeInAsm) {
8148 for (i=0; i<6; i++) {
8149 sprintf (®sInUse[i],
8150 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8153 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8155 /* if the result is marked as
8156 spilt and rematerializable or code for
8157 this has already been generated then
8159 if (resultRemat (ic) || ic->generated)
8167 for (i=A_IDX;i<=XA_IDX;i++)
8169 reg = hc08_regWithIdx(i);
8171 emitcode("","; %s = %s offset %d", reg->name,
8172 aopName(reg->aop), reg->aopofs);
8175 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8177 sym = OP_SYMBOL (IC_LEFT (ic));
8178 if (sym->accuse == ACCUSE_HX)
8180 hc08_reg_h->isFree = FALSE;
8181 hc08_reg_x->isFree = FALSE;
8183 else if (sym->accuse == ACCUSE_XA)
8185 hc08_reg_a->isFree = FALSE;
8187 hc08_reg_x->isFree = FALSE;
8190 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8192 sym = OP_SYMBOL (IC_RIGHT (ic));
8193 if (sym->accuse == ACCUSE_HX)
8195 hc08_reg_h->isFree = FALSE;
8196 hc08_reg_x->isFree = FALSE;
8198 else if (sym->accuse == ACCUSE_XA)
8200 hc08_reg_a->isFree = FALSE;
8202 hc08_reg_x->isFree = FALSE;
8207 /* depending on the operation */
8227 /* IPOP happens only when trying to restore a
8228 spilt live range, if there is an ifx statement
8229 following this pop then the if statement might
8230 be using some of the registers being popped which
8231 would destory the contents of the register so
8232 we need to check for this condition and handle it */
8234 ic->next->op == IFX &&
8235 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8236 genIfx (ic->next, ic);
8254 genEndFunction (ic);
8270 if (!genPointerGetSetOfs (ic))
8275 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8292 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8296 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8303 /* note these two are xlated by algebraic equivalence
8304 during parsing SDCC.y */
8305 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8306 "got '>=' or '<=' shouldn't have come here");
8310 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8322 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8326 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8330 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8357 case GET_VALUE_AT_ADDRESS:
8359 hasInc (IC_LEFT (ic), ic,
8360 getSize (operandType (IC_RESULT (ic)))),
8361 ifxForOp (IC_RESULT (ic), ic) );
8365 if (POINTER_SET (ic))
8366 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8392 addSet (&_G.sendSet, ic);
8395 case DUMMY_READ_VOLATILE:
8404 genEndCritical (ic);
8415 if (!hc08_reg_a->isFree)
8416 D(emitcode("","; forgot to free a"));
8417 if (!hc08_reg_x->isFree)
8418 D(emitcode("","; forgot to free x"));
8419 if (!hc08_reg_h->isFree)
8420 D(emitcode("","; forgot to free h"));
8421 if (!hc08_reg_hx->isFree)
8422 D(emitcode("","; forgot to free hx"));
8423 if (!hc08_reg_xa->isFree)
8424 D(emitcode("","; forgot to free xa"));
8427 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8430 /* now we are ready to call the
8431 peep hole optimizer */
8432 if (!options.nopeep)
8433 peepHole (&lineHead);
8435 /* now do the actual printing */
8436 printLine (lineHead, codeOutFile);